From 0205e75ff83a98f8f0f01f5889846e0d563b0ab7 Mon Sep 17 00:00:00 2001 From: kimvde Date: Thu, 23 Feb 2023 08:21:44 +0000 Subject: [PATCH] Split transmux into transmuxAudio/Video - Split the transmux setting into transmuxAudio and transmuxVideo. This is more flexible for apps and will also be useful for unit testing (particularly as we can't test video transcoding on Robolectric at the moment). - Move these settings to Composition. It makes sense for these settings to be next to forceAudioTrack. Apps may also want to set these settings based on the current Composition's MediaItems. - Add a Composition.Builder because Composition now contains a few optional fields. PiperOrigin-RevId: 511708618 --- .../transformerdemo/TransformerActivity.java | 4 +- .../exoplayer2/transformer/Composition.java | 198 ++++++++++++++---- .../exoplayer2/transformer/Effects.java | 2 +- .../exoplayer2/transformer/Transformer.java | 30 +-- .../transformer/TransformerInternal.java | 26 ++- .../transformer/FallbackListenerTest.java | 12 +- .../transformer/TransformerEndToEndTest.java | 54 +++-- .../transformer/VideoEncoderWrapperTest.java | 12 +- 8 files changed, 222 insertions(+), 116 deletions(-) diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index 419ac03e44..bdd85da097 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -378,7 +378,9 @@ public final class TransformerActivity extends AppCompatActivity { editedMediaItems.add(editedMediaItemBuilder.build()); List sequences = new ArrayList<>(); sequences.add(new EditedMediaItemSequence(editedMediaItems)); - return new Composition(sequences, Effects.EMPTY, forceAudioTrack); + return new Composition.Builder(sequences) + .experimentalSetForceAudioTrack(forceAudioTrack) + .build(); } private ImmutableList createAudioProcessorsFromBundle(Bundle bundle) { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Composition.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Composition.java index 37a5229394..c6021d1bbb 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Composition.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Composition.java @@ -20,21 +20,152 @@ import static com.google.android.exoplayer2.util.Assertions.checkArgument; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.audio.AudioProcessor; import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.List; /** * A composition of {@link MediaItem} instances, with transformations to apply to them. * - *

The {@linkplain MediaItem} instances can be concatenated or mixed. {@link Effects} can be - * applied to individual {@linkplain MediaItem} instances, as well as to the composition. + *

The {@link MediaItem} instances can be concatenated or mixed. {@link Effects} can be applied + * to individual {@link MediaItem} instances, as well as to the composition. */ public final class Composition { + /** A builder for {@link Composition} instances. */ + public static final class Builder { + + private final ImmutableList sequences; + + private Effects effects; + private boolean forceAudioTrack; + private boolean transmuxAudio; + private boolean transmuxVideo; + + /** + * Creates an instance. + * + * @param sequences The {@link EditedMediaItemSequence} instances to compose. {@link MediaItem} + * instances from different sequences that are overlapping in time will be mixed in the + * output. This list must not be empty. + */ + public Builder(List sequences) { + checkArgument( + !sequences.isEmpty(), + "The composition must contain at least one EditedMediaItemSequence."); + this.sequences = ImmutableList.copyOf(sequences); + effects = Effects.EMPTY; + } + + /** + * Sets the {@link Effects} to apply to the {@link Composition}. + * + *

The default value is {@link Effects#EMPTY}. + * + * @param effects The {@link Composition} {@link Effects}. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder setEffects(Effects effects) { + this.effects = effects; + return this; + } + + /** + * Sets whether the output file should always contain an audio track. + * + *

The default value is {@code false}. + * + *

    + *
  • If {@code false}: + *
      + *
    • If the {@link Composition} export doesn't produce any audio at timestamp 0, the + * output won't contain any audio, and audio tracks from the {@link MediaItem} + * instances in the {@link Composition} will be ignored. + *
    • If the {@link Composition} export produces audio at timestamp 0, the output will + * contain an audio track. + *
    + *
  • If {@code true}, the output will always contain an audio track. + *
+ * + * If the output contains an audio track, silent audio will be generated for the segments where + * the {@link Composition} export doesn't produce any audio. + * + *

The MIME type of the output's audio track can be set using {@link + * TransformationRequest.Builder#setAudioMimeType(String)}. The sample rate and channel count + * can be set by passing relevant {@link AudioProcessor} instances to the {@link Composition}. + * + *

Forcing an audio track and {@linkplain #setTransmuxAudio(boolean) requesting audio + * transmuxing} are not allowed together because generating silence requires transcoding. + * + *

This method is experimental and may be removed or changed without warning. + * + * @param forceAudioTrack Whether to force an audio track in the output. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder experimentalSetForceAudioTrack(boolean forceAudioTrack) { + this.forceAudioTrack = forceAudioTrack; + return this; + } + + /** + * Sets whether to transmux the {@linkplain MediaItem media items'} audio tracks. + * + *

The default value is {@code false}. + * + *

If the {@link Composition} contains one {@link MediaItem}, the value set is ignored. The + * audio track will only be transcoded if necessary. + * + *

If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all + * the audio tracks are transmuxed if {@code transmuxAudio} is {@code true} and exporting the + * first {@link MediaItem} doesn't require audio transcoding. Otherwise, they are all + * transcoded. Transmuxed tracks must be compatible and must not overlap in time. + * + *

Requesting audio transmuxing and {@linkplain #experimentalSetForceAudioTrack(boolean) + * forcing an audio track} are not allowed together because generating silence requires + * transcoding. + * + * @param transmuxAudio Whether to transmux the audio tracks. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder setTransmuxAudio(boolean transmuxAudio) { + this.transmuxAudio = transmuxAudio; + return this; + } + + /** + * Sets whether to transmux the {@linkplain MediaItem media items'} video tracks. + * + *

The default value is {@code false}. + * + *

If the {@link Composition} contains one {@link MediaItem}, the value set is ignored. The + * video track will only be transcoded if necessary. + * + *

If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all + * the video tracks are transmuxed if {@code transmuxVideo} is {@code true} and exporting the + * first {@link MediaItem} doesn't require video transcoding. Otherwise, they are all + * transcoded. Transmuxed tracks must be compatible and must not overlap in time. + * + * @param transmuxVideo Whether to transmux the video tracks. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder setTransmuxVideo(boolean transmuxVideo) { + this.transmuxVideo = transmuxVideo; + return this; + } + + /** Builds a {@link Composition} instance. */ + public Composition build() { + return new Composition(sequences, effects, forceAudioTrack, transmuxAudio, transmuxVideo); + } + } + /** - * The {@link EditedMediaItemSequence} instances to compose. {@link MediaItem} instances from - * different sequences that are overlapping in time will be mixed in the output. + * The {@link EditedMediaItemSequence} instances to compose. * - *

This list must not be empty. + *

For more information, see {@link Builder#Builder(List)}. */ public final ImmutableList sequences; /** The {@link Effects} to apply to the composition. */ @@ -42,54 +173,35 @@ public final class Composition { /** * Whether the output file should always contain an audio track. * - *

    - *
  • If {@code false}: - *
      - *
    • If the {@link Composition} export doesn't produce any audio at timestamp 0, the - * output won't contain any audio, and audio tracks from the {@link MediaItem} - * instances in the {@link Composition} will be ignored. - *
    • If the {@link Composition} export produces audio at timestamp 0, the output will - * contain an audio track. - *
    - *
  • If {@code true}, the output will always contain an audio track. - *
- * - * If the output contains an audio track, silent audio will be generated for the segments where - * the {@link Composition} export doesn't produce any audio. - * - *

The MIME type of the output's audio track can be set using {@link - * TransformationRequest.Builder#setAudioMimeType(String)}. The sample rate and channel count can - * be set by passing relevant {@link AudioProcessor} instances to the {@link Composition}. - * - *

This parameter is experimental and may be removed or changed without warning. + *

For more information, see {@link Builder#experimentalSetForceAudioTrack(boolean)}. */ - public final boolean experimentalForceAudioTrack; - + public final boolean forceAudioTrack; /** - * Creates an instance. + * Whether to transmux the {@linkplain MediaItem media items'} audio tracks. * - *

This is equivalent to calling {@link Composition#Composition(List, Effects, boolean)} with - * {@link #experimentalForceAudioTrack} set to {@code false}. + *

For more information, see {@link Builder#setTransmuxAudio(boolean)}. */ - public Composition(List sequences, Effects effects) { - this(sequences, effects, /* experimentalForceAudioTrack= */ false); - } - + public final boolean transmuxAudio; /** - * Creates an instance. + * Whether to transmux the {@linkplain MediaItem media items'} video tracks. * - * @param sequences The {@link #sequences}. - * @param effects The {@link #effects}. - * @param experimentalForceAudioTrack Whether to {@linkplain #experimentalForceAudioTrack always - * add an audio track in the output}. + *

For more information, see {@link Builder#setTransmuxVideo(boolean)}. */ - public Composition( + public final boolean transmuxVideo; + + private Composition( List sequences, Effects effects, - boolean experimentalForceAudioTrack) { - checkArgument(!sequences.isEmpty()); + boolean forceAudioTrack, + boolean transmuxAudio, + boolean transmuxVideo) { + checkArgument( + !transmuxAudio || !forceAudioTrack, + "Audio transmuxing and audio track forcing are not allowed together."); this.sequences = ImmutableList.copyOf(sequences); this.effects = effects; - this.experimentalForceAudioTrack = experimentalForceAudioTrack; + this.transmuxAudio = transmuxAudio; + this.transmuxVideo = transmuxVideo; + this.forceAudioTrack = forceAudioTrack; } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java index a68f144c65..b553ed49ce 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java @@ -23,7 +23,7 @@ import com.google.android.exoplayer2.util.VideoFrameProcessor; import com.google.common.collect.ImmutableList; import java.util.List; -/** Effects to apply to a {@link MediaItem}. */ +/** Effects to apply to a {@link MediaItem} or to a {@link Composition}. */ public final class Effects { /** An empty {@link Effects} instance. */ diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java index b7b48c2e89..2fee0c96b5 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java @@ -82,7 +82,6 @@ public final class Transformer { private boolean removeAudio; private boolean removeVideo; private boolean flattenForSlowMotion; - private boolean transmux; private ListenerSet listeners; private AssetLoader.@MonotonicNonNull Factory assetLoaderFactory; private VideoFrameProcessor.Factory videoFrameProcessorFactory; @@ -202,28 +201,6 @@ public final class Transformer { return this; } - /** - * Sets whether to transmux the {@linkplain MediaItem media items} in the input {@link - * Composition}. - * - *

The default value is {@code false}. - * - *

If the input {@link Composition} contains one {@link MediaItem}, the value set is ignored. - * The {@link MediaItem} will only be transcoded if necessary. - * - *

If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, - * they are all transmuxed if {@code transmux} is {@code true} and exporting the first {@link - * MediaItem} doesn't require transcoding. Otherwise, they are all transcoded. - * - * @param transmux Whether to transmux. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setTransmux(boolean transmux) { - this.transmux = transmux; - return this; - } - /** * @deprecated Use {@link #addListener(Listener)}, {@link #removeListener(Listener)} or {@link * #removeAllListeners()} instead. @@ -414,7 +391,6 @@ public final class Transformer { removeAudio, removeVideo, flattenForSlowMotion, - transmux, listeners, assetLoaderFactory, videoFrameProcessorFactory, @@ -574,7 +550,6 @@ public final class Transformer { private final boolean removeAudio; private final boolean removeVideo; private final boolean flattenForSlowMotion; - private final boolean transmux; private final ListenerSet listeners; private final AssetLoader.Factory assetLoaderFactory; private final VideoFrameProcessor.Factory videoFrameProcessorFactory; @@ -594,7 +569,6 @@ public final class Transformer { boolean removeAudio, boolean removeVideo, boolean flattenForSlowMotion, - boolean transmux, ListenerSet listeners, AssetLoader.Factory assetLoaderFactory, VideoFrameProcessor.Factory videoFrameProcessorFactory, @@ -611,7 +585,6 @@ public final class Transformer { this.removeAudio = removeAudio; this.removeVideo = removeVideo; this.flattenForSlowMotion = flattenForSlowMotion; - this.transmux = transmux; this.listeners = listeners; this.assetLoaderFactory = assetLoaderFactory; this.videoFrameProcessorFactory = videoFrameProcessorFactory; @@ -730,7 +703,6 @@ public final class Transformer { composition, path, transformationRequest, - transmux, assetLoaderFactory, encoderFactory, muxerFactory, @@ -770,7 +742,7 @@ public final class Transformer { public void start(EditedMediaItem editedMediaItem, String path) { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); - start(new Composition(ImmutableList.of(sequence), Effects.EMPTY), path); + start(new Composition.Builder(ImmutableList.of(sequence)).build(), path); } /** diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 63e3b858b7..b59c2f5987 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -112,7 +112,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Composition composition, String outputPath, TransformationRequest transformationRequest, - boolean transmux, AssetLoader.Factory assetLoaderFactory, Codec.EncoderFactory encoderFactory, Muxer.Factory muxerFactory, @@ -133,11 +132,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Looper internalLooper = internalHandlerThread.getLooper(); EditedMediaItemSequence sequence = composition.sequences.get(0); ComponentListener componentListener = - new ComponentListener(sequence, transmux, fallbackListener); + new ComponentListener( + sequence, composition.transmuxAudio, composition.transmuxVideo, fallbackListener); compositeAssetLoader = new CompositeAssetLoader( sequence, - composition.experimentalForceAudioTrack, + composition.forceAudioTrack, assetLoaderFactory, internalLooper, componentListener, @@ -314,17 +314,22 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // The first EditedMediaItem in the sequence determines which SamplePipeline to use. private final EditedMediaItem firstEditedMediaItem; private final int mediaItemCount; - private final boolean transmux; + private final boolean transmuxAudio; + private final boolean transmuxVideo; private final FallbackListener fallbackListener; private final AtomicInteger trackCount; private boolean trackAdded; public ComponentListener( - EditedMediaItemSequence sequence, boolean transmux, FallbackListener fallbackListener) { + EditedMediaItemSequence sequence, + boolean transmuxAudio, + boolean transmuxVideo, + FallbackListener fallbackListener) { firstEditedMediaItem = sequence.editedMediaItems.get(0); mediaItemCount = sequence.editedMediaItems.size(); - this.transmux = transmux; + this.transmuxAudio = transmuxAudio; + this.transmuxVideo = transmuxVideo; this.fallbackListener = fallbackListener; trackCount = new AtomicInteger(); } @@ -479,12 +484,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; boolean shouldTranscode = false; if (!assetLoaderCanOutputEncoded) { shouldTranscode = true; - } else if (mediaItemCount > 1 && !transmux) { - shouldTranscode = true; } else if (MimeTypes.isAudio(inputFormat.sampleMimeType)) { - shouldTranscode = shouldTranscodeAudio(inputFormat); + shouldTranscode = + (mediaItemCount > 1 && !transmuxAudio) || shouldTranscodeAudio(inputFormat); } else if (MimeTypes.isVideo(inputFormat.sampleMimeType)) { - shouldTranscode = shouldTranscodeVideo(inputFormat, streamStartPositionUs, streamOffsetUs); + shouldTranscode = + (mediaItemCount > 1 && !transmuxVideo) + || shouldTranscodeVideo(inputFormat, streamStartPositionUs, streamOffsetUs); } checkState(!shouldTranscode || assetLoaderCanOutputDecoded); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java index 510dc9d1cd..cd6fe2cce4 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java @@ -39,12 +39,12 @@ import org.robolectric.shadows.ShadowLooper; public class FallbackListenerTest { private static final Composition PLACEHOLDER_COMPOSITION = - new Composition( - ImmutableList.of( - new EditedMediaItemSequence( - ImmutableList.of( - new EditedMediaItem.Builder(MediaItem.fromUri(Uri.EMPTY)).build()))), - Effects.EMPTY); + new Composition.Builder( + ImmutableList.of( + new EditedMediaItemSequence( + ImmutableList.of( + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.EMPTY)).build())))) + .build(); @Test public void onTransformationRequestFinalized_withoutTrackCountSet_throwsException() { diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 481dd99a65..b96f70c95c 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -286,8 +286,9 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); Composition composition = - new Composition( - ImmutableList.of(sequence), Effects.EMPTY, /* experimentalForceAudioTrack= */ true); + new Composition.Builder(ImmutableList.of(sequence)) + .experimentalSetForceAudioTrack(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -304,8 +305,9 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); Composition composition = - new Composition( - ImmutableList.of(sequence), Effects.EMPTY, /* experimentalForceAudioTrack= */ true); + new Composition.Builder(ImmutableList.of(sequence)) + .experimentalSetForceAudioTrack(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -323,8 +325,9 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); Composition composition = - new Composition( - ImmutableList.of(sequence), Effects.EMPTY, /* experimentalForceAudioTrack= */ true); + new Composition.Builder(ImmutableList.of(sequence)) + .experimentalSetForceAudioTrack(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -343,8 +346,9 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); Composition composition = - new Composition( - ImmutableList.of(sequence), Effects.EMPTY, /* experimentalForceAudioTrack= */ true); + new Composition.Builder(ImmutableList.of(sequence)) + .experimentalSetForceAudioTrack(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -360,8 +364,9 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence sequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); Composition composition = - new Composition( - ImmutableList.of(sequence), Effects.EMPTY, /* experimentalForceAudioTrack= */ true); + new Composition.Builder(ImmutableList.of(sequence)) + .experimentalSetForceAudioTrack(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -390,15 +395,17 @@ public final class TransformerEndToEndTest { @Test public void start_concatenateMediaItemsWithSameFormat_completesSuccessfully() throws Exception { - Transformer transformer = - createTransformerBuilder(/* enableFallback= */ false).setTransmux(true).build(); + Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem).setEffects(Effects.EMPTY).build(); EditedMediaItemSequence editedMediaItemSequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem, editedMediaItem)); Composition composition = - new Composition(ImmutableList.of(editedMediaItemSequence), Effects.EMPTY); + new Composition.Builder(ImmutableList.of(editedMediaItemSequence)) + .setTransmuxAudio(true) + .setTransmuxVideo(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -425,7 +432,7 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence editedMediaItemSequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem, editedMediaItem)); Composition composition = - new Composition(ImmutableList.of(editedMediaItemSequence), Effects.EMPTY); + new Composition.Builder(ImmutableList.of(editedMediaItemSequence)).build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); @@ -438,15 +445,20 @@ public final class TransformerEndToEndTest { public void start_singleMediaItemAndTransmux_ignoresTransmux() throws Exception { SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor(); sonicAudioProcessor.setOutputSampleRateHz(48000); - Transformer transformer = - createTransformerBuilder(/* enableFallback= */ false).setTransmux(true).build(); + Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); ImmutableList audioProcessors = ImmutableList.of(sonicAudioProcessor); Effects effects = new Effects(audioProcessors, /* videoEffects= */ ImmutableList.of()); EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem).setEffects(effects).build(); + EditedMediaItemSequence editedMediaItemSequence = + new EditedMediaItemSequence(ImmutableList.of(editedMediaItem)); + Composition composition = + new Composition.Builder(ImmutableList.of(editedMediaItemSequence)) + .setTransmuxAudio(true) + .build(); - transformer.start(editedMediaItem, outputPath); + transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); DumpFileAsserts.assertOutput( @@ -455,8 +467,7 @@ public final class TransformerEndToEndTest { @Test public void start_multipleMediaItemsWithEffectsAndTransmux_ignoresTransmux() throws Exception { - Transformer transformer = - createTransformerBuilder(/* enableFallback= */ false).setTransmux(true).build(); + Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); AudioProcessor audioProcessor = new SilenceSkippingAudioProcessor(); Effects effects = @@ -466,7 +477,10 @@ public final class TransformerEndToEndTest { EditedMediaItemSequence editedMediaItemSequence = new EditedMediaItemSequence(ImmutableList.of(editedMediaItem, editedMediaItem)); Composition composition = - new Composition(ImmutableList.of(editedMediaItemSequence), Effects.EMPTY); + new Composition.Builder(ImmutableList.of(editedMediaItemSequence)) + .setTransmuxAudio(true) + .setTransmuxVideo(true) + .build(); transformer.start(composition, outputPath); TransformerTestRunner.runLooper(transformer); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java index fbf518bdf3..7437e51164 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java @@ -44,12 +44,12 @@ import org.robolectric.shadows.ShadowMediaCodecList; @RunWith(AndroidJUnit4.class) public final class VideoEncoderWrapperTest { private static final Composition FAKE_COMPOSITION = - new Composition( - ImmutableList.of( - new EditedMediaItemSequence( - ImmutableList.of( - new EditedMediaItem.Builder(MediaItem.fromUri(Uri.EMPTY)).build()))), - Effects.EMPTY); + new Composition.Builder( + ImmutableList.of( + new EditedMediaItemSequence( + ImmutableList.of( + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.EMPTY)).build())))) + .build(); private final TransformationRequest emptyTransformationRequest = new TransformationRequest.Builder().build();