diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java index d6a5b5e132..d1b6893c0e 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java @@ -23,6 +23,7 @@ import androidx.annotation.IntDef; import androidx.annotation.IntRange; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; +import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -78,10 +79,6 @@ public interface AssetLoader { @CanIgnoreReturnValue Factory setFlattenVideoForSlowMotion(boolean flattenVideoForSlowMotion); - /** Sets the {@link Codec.DecoderFactory} to be used to decode the samples (if necessary). */ - @CanIgnoreReturnValue - Factory setDecoderFactory(Codec.DecoderFactory decoderFactory); - /** * Creates an {@link AssetLoader} instance. All the setters in this factory must be called * before creating the {@link AssetLoader}. @@ -176,6 +173,14 @@ public interface AssetLoader { @Transformer.ProgressState int getProgress(ProgressHolder progressHolder); + /** + * Return the used decoders' names. + * + * @return The decoders' names keyed by {@linkplain com.google.android.exoplayer2.C.TrackType + * track type}. + */ + ImmutableMap getDecoderNames(); + /** Stops loading data and releases all resources associated with the asset loader. */ void release(); } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultAssetLoaderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultAssetLoaderFactory.java index 10aed52478..6f36bfa81c 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultAssetLoaderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultAssetLoaderFactory.java @@ -34,12 +34,18 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { * @param context The {@link Context}. * @param mediaSourceFactory The {@link MediaSource.Factory} to use to retrieve the samples to * transform when an {@link ExoPlayerAssetLoader} is used. + * @param decoderFactory The {@link Codec.DecoderFactory} to use to decode the samples (if + * necessary). * @param clock The {@link Clock} to use. It should always be {@link Clock#DEFAULT}, except for * testing. */ public DefaultAssetLoaderFactory( - Context context, MediaSource.Factory mediaSourceFactory, Clock clock) { - assetLoaderFactory = new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, clock); + Context context, + MediaSource.Factory mediaSourceFactory, + Codec.DecoderFactory decoderFactory, + Clock clock) { + assetLoaderFactory = + new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, decoderFactory, clock); } @Override @@ -61,12 +67,6 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { return this; } - @Override - @CanIgnoreReturnValue - public AssetLoader.Factory setDecoderFactory(Codec.DecoderFactory decoderFactory) { - return assetLoaderFactory.setDecoderFactory(decoderFactory); - } - @Override public AssetLoader createAssetLoader( MediaItem mediaItem, Looper looper, AssetLoader.Listener listener) { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java index 72a8f19f80..db1883cba0 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java @@ -27,7 +27,6 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static java.lang.Math.min; import android.content.Context; @@ -51,6 +50,7 @@ import com.google.android.exoplayer2.text.TextOutput; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.video.VideoRendererEventListener; +import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; /** An {@link AssetLoader} implementation that uses an {@link ExoPlayer} to load samples. */ @@ -61,12 +61,12 @@ public final class ExoPlayerAssetLoader implements AssetLoader { private final Context context; private final MediaSource.Factory mediaSourceFactory; + private final Codec.DecoderFactory decoderFactory; private final Clock clock; private boolean removeAudio; private boolean removeVideo; private boolean flattenVideoForSlowMotion; - @Nullable private Codec.DecoderFactory decoderFactory; /** * Creates an instance. @@ -74,12 +74,19 @@ public final class ExoPlayerAssetLoader implements AssetLoader { * @param context The {@link Context}. * @param mediaSourceFactory The {@link MediaSource.Factory} to use to retrieve the samples to * transform. + * @param decoderFactory The {@link Codec.DecoderFactory} to use to decode the samples (if + * necessary). * @param clock The {@link Clock} to use. It should always be {@link Clock#DEFAULT}, except for * testing. */ - public Factory(Context context, MediaSource.Factory mediaSourceFactory, Clock clock) { + public Factory( + Context context, + MediaSource.Factory mediaSourceFactory, + Codec.DecoderFactory decoderFactory, + Clock clock) { this.context = context; this.mediaSourceFactory = mediaSourceFactory; + this.decoderFactory = decoderFactory; this.clock = clock; } @@ -104,13 +111,6 @@ public final class ExoPlayerAssetLoader implements AssetLoader { return this; } - @Override - @CanIgnoreReturnValue - public AssetLoader.Factory setDecoderFactory(Codec.DecoderFactory decoderFactory) { - this.decoderFactory = decoderFactory; - return this; - } - @Override public AssetLoader createAssetLoader(MediaItem mediaItem, Looper looper, Listener listener) { return new ExoPlayerAssetLoader( @@ -120,7 +120,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader { removeVideo, flattenVideoForSlowMotion, mediaSourceFactory, - checkStateNotNull(decoderFactory), + decoderFactory, looper, listener, clock); @@ -128,6 +128,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader { } private final MediaItem mediaItem; + private final CapturingDecoderFactory decoderFactory; private final ExoPlayer player; private @Transformer.ProgressState int progressState; @@ -144,6 +145,8 @@ public final class ExoPlayerAssetLoader implements AssetLoader { Listener listener, Clock clock) { this.mediaItem = mediaItem; + this.decoderFactory = new CapturingDecoderFactory(decoderFactory); + DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); trackSelector.setParameters( new DefaultTrackSelector.Parameters.Builder(context) @@ -163,7 +166,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader { new ExoPlayer.Builder( context, new RenderersFactoryImpl( - removeAudio, removeVideo, flattenForSlowMotion, decoderFactory, listener)) + removeAudio, removeVideo, flattenForSlowMotion, this.decoderFactory, listener)) .setMediaSourceFactory(mediaSourceFactory) .setTrackSelector(trackSelector) .setLoadControl(loadControl) @@ -174,7 +177,6 @@ public final class ExoPlayerAssetLoader implements AssetLoader { @SuppressWarnings("VisibleForTests") ExoPlayer.Builder unusedForAnnotation = playerBuilder.setClock(clock); } - player = playerBuilder.build(); player.addListener(new PlayerListener(listener)); @@ -198,6 +200,20 @@ public final class ExoPlayerAssetLoader implements AssetLoader { return progressState; } + @Override + public ImmutableMap getDecoderNames() { + ImmutableMap.Builder decoderNamesByTrackType = new ImmutableMap.Builder<>(); + @Nullable String audioDecoderName = decoderFactory.getAudioDecoderName(); + if (audioDecoderName != null) { + decoderNamesByTrackType.put(C.TRACK_TYPE_AUDIO, audioDecoderName); + } + @Nullable String videoDecoderName = decoderFactory.getVideoDecoderName(); + if (videoDecoderName != null) { + decoderNamesByTrackType.put(C.TRACK_TYPE_VIDEO, videoDecoderName); + } + return decoderNamesByTrackType.buildOrThrow(); + } + @Override public void release() { player.release(); 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 05733563b2..428b209f94 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 @@ -89,9 +89,8 @@ public final class Transformer { private boolean forceSilentAudio; private ListenerSet listeners; @Nullable private AssetLoader.Factory assetLoaderFactory; - private Codec.DecoderFactory decoderFactory; - private Codec.EncoderFactory encoderFactory; private FrameProcessor.Factory frameProcessorFactory; + private Codec.EncoderFactory encoderFactory; private Muxer.Factory muxerFactory; private Looper looper; private DebugViewProvider debugViewProvider; @@ -107,9 +106,8 @@ public final class Transformer { transformationRequest = new TransformationRequest.Builder().build(); audioProcessors = ImmutableList.of(); videoEffects = ImmutableList.of(); - decoderFactory = new DefaultDecoderFactory(this.context); - encoderFactory = new DefaultEncoderFactory.Builder(this.context).build(); frameProcessorFactory = new GlEffectsFrameProcessor.Factory(); + encoderFactory = new DefaultEncoderFactory.Builder(this.context).build(); muxerFactory = new DefaultMuxer.Factory(); looper = Util.getCurrentOrMainLooper(); debugViewProvider = DebugViewProvider.NONE; @@ -128,9 +126,8 @@ public final class Transformer { this.forceSilentAudio = transformer.forceSilentAudio; this.listeners = transformer.listeners; this.assetLoaderFactory = transformer.assetLoaderFactory; - this.decoderFactory = transformer.decoderFactory; - this.encoderFactory = transformer.encoderFactory; this.frameProcessorFactory = transformer.frameProcessorFactory; + this.encoderFactory = transformer.encoderFactory; this.muxerFactory = transformer.muxerFactory; this.looper = transformer.looper; this.debugViewProvider = transformer.debugViewProvider; @@ -292,7 +289,7 @@ public final class Transformer { * Sets the {@link AssetLoader.Factory} to be used to retrieve the samples to transform. * *

The default value is a {@link DefaultAssetLoaderFactory} built with a {@link - * DefaultMediaSourceFactory}. + * DefaultMediaSourceFactory} and a {@link DefaultDecoderFactory}. * * @param assetLoaderFactory An {@link AssetLoader.Factory}. * @return This builder. @@ -303,34 +300,6 @@ public final class Transformer { return this; } - /** - * Sets the {@link Codec.DecoderFactory} that will be used by the transformer. - * - *

The default value is a {@link DefaultDecoderFactory} instance. - * - * @param decoderFactory The {@link Codec.DecoderFactory} instance. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setDecoderFactory(Codec.DecoderFactory decoderFactory) { - this.decoderFactory = decoderFactory; - return this; - } - - /** - * Sets the {@link Codec.EncoderFactory} that will be used by the transformer. - * - *

The default value is a {@link DefaultEncoderFactory} instance. - * - * @param encoderFactory The {@link Codec.EncoderFactory} instance. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setEncoderFactory(Codec.EncoderFactory encoderFactory) { - this.encoderFactory = encoderFactory; - return this; - } - /** * Sets the {@link FrameProcessor.Factory} for the {@link FrameProcessor} to use when applying * {@linkplain Effect effects} to the video frames. @@ -351,6 +320,20 @@ public final class Transformer { return this; } + /** + * Sets the {@link Codec.EncoderFactory} that will be used by the transformer. + * + *

The default value is a {@link DefaultEncoderFactory} instance. + * + * @param encoderFactory The {@link Codec.EncoderFactory} instance. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder setEncoderFactory(Codec.EncoderFactory encoderFactory) { + this.encoderFactory = encoderFactory; + return this; + } + /** * Sets the factory for muxers that write the media container. * @@ -465,7 +448,9 @@ public final class Transformer { } MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context, defaultExtractorsFactory); - assetLoaderFactory = new DefaultAssetLoaderFactory(context, mediaSourceFactory, clock); + Codec.DecoderFactory decoderFactory = new DefaultDecoderFactory(context); + assetLoaderFactory = + new DefaultAssetLoaderFactory(context, mediaSourceFactory, decoderFactory, clock); } return new Transformer( context, @@ -477,9 +462,8 @@ public final class Transformer { forceSilentAudio, listeners, assetLoaderFactory, - decoderFactory, - encoderFactory, frameProcessorFactory, + encoderFactory, muxerFactory, looper, debugViewProvider, @@ -589,9 +573,6 @@ public final class Transformer { /** Indicates that the progress is permanently unavailable. */ public static final int PROGRESS_STATE_UNAVAILABLE = 3; - @VisibleForTesting /* package */ final Codec.DecoderFactory decoderFactory; - @VisibleForTesting /* package */ final Codec.EncoderFactory encoderFactory; - private final Context context; private final TransformationRequest transformationRequest; private final ImmutableList audioProcessors; @@ -602,6 +583,7 @@ public final class Transformer { private final ListenerSet listeners; private final AssetLoader.Factory assetLoaderFactory; private final FrameProcessor.Factory frameProcessorFactory; + private final Codec.EncoderFactory encoderFactory; private final Muxer.Factory muxerFactory; private final Looper looper; private final DebugViewProvider debugViewProvider; @@ -619,9 +601,8 @@ public final class Transformer { boolean forceSilentAudio, ListenerSet listeners, AssetLoader.Factory assetLoaderFactory, - Codec.DecoderFactory decoderFactory, - Codec.EncoderFactory encoderFactory, FrameProcessor.Factory frameProcessorFactory, + Codec.EncoderFactory encoderFactory, Muxer.Factory muxerFactory, Looper looper, DebugViewProvider debugViewProvider, @@ -640,9 +621,8 @@ public final class Transformer { this.forceSilentAudio = forceSilentAudio; this.listeners = listeners; this.assetLoaderFactory = assetLoaderFactory; - this.decoderFactory = decoderFactory; - this.encoderFactory = encoderFactory; this.frameProcessorFactory = frameProcessorFactory; + this.encoderFactory = encoderFactory; this.muxerFactory = muxerFactory; this.looper = looper; this.debugViewProvider = debugViewProvider; @@ -783,9 +763,8 @@ public final class Transformer { removeVideo, forceSilentAudio, assetLoaderFactory, - decoderFactory, - encoderFactory, frameProcessorFactory, + encoderFactory, muxerFactory, transformerInternalListener, fallbackListener, 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 824f8a9e17..3dd4cf0afa 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 @@ -45,6 +45,7 @@ import com.google.android.exoplayer2.util.FrameProcessor; import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.MimeTypes; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -93,9 +94,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final ImmutableList audioProcessors; private final ImmutableList videoEffects; private final boolean forceSilentAudio; - private final CapturingDecoderFactory decoderFactory; - private final CapturingEncoderFactory encoderFactory; private final FrameProcessor.Factory frameProcessorFactory; + private final CapturingEncoderFactory encoderFactory; private final Listener listener; private final HandlerWrapper applicationHandler; private final DebugViewProvider debugViewProvider; @@ -126,9 +126,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; boolean removeVideo, boolean forceSilentAudio, AssetLoader.Factory assetLoaderFactory, - Codec.DecoderFactory decoderFactory, - Codec.EncoderFactory encoderFactory, FrameProcessor.Factory frameProcessorFactory, + Codec.EncoderFactory encoderFactory, Muxer.Factory muxerFactory, Listener listener, FallbackListener fallbackListener, @@ -140,9 +139,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.audioProcessors = audioProcessors; this.videoEffects = videoEffects; this.forceSilentAudio = forceSilentAudio; - this.decoderFactory = new CapturingDecoderFactory(decoderFactory); - this.encoderFactory = new CapturingEncoderFactory(encoderFactory); this.frameProcessorFactory = frameProcessorFactory; + this.encoderFactory = new CapturingEncoderFactory(encoderFactory); this.listener = listener; this.applicationHandler = applicationHandler; this.debugViewProvider = debugViewProvider; @@ -156,7 +154,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; .setRemoveAudio(removeAudio) .setRemoveVideo(removeVideo) .setFlattenVideoForSlowMotion(transformationRequest.flattenForSlowMotion) - .setDecoderFactory(this.decoderFactory) .createAssetLoader(mediaItem, internalLooper, componentListener); samplePipelines = new ArrayList<>(); muxerWrapper = @@ -263,9 +260,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private void endInternal( @EndReason int endReason, @Nullable TransformationException transformationException) { + ImmutableMap decoderNames = assetLoader.getDecoderNames(); transformationResultBuilder - .setAudioDecoderName(decoderFactory.getAudioDecoderName()) - .setVideoDecoderName(decoderFactory.getVideoDecoderName()) + .setAudioDecoderName(decoderNames.get(C.TRACK_TYPE_AUDIO)) + .setVideoDecoderName(decoderNames.get(C.TRACK_TYPE_VIDEO)) .setAudioEncoderName(encoderFactory.getAudioEncoderName()) .setVideoEncoderName(encoderFactory.getVideoEncoderName()); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderTest.java index c1888a35f8..d6ef89220d 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderTest.java @@ -119,12 +119,12 @@ public class ExoPlayerAssetLoaderTest { Looper looper, AssetLoader.Listener listener, Clock clock) { Context context = ApplicationProvider.getApplicationContext(); MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context); + Codec.DecoderFactory decoderFactory = new DefaultDecoderFactory(context); MediaItem mediaItem = MediaItem.fromUri("asset:///media/mp4/sample.mp4"); - return new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, clock) + return new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, decoderFactory, clock) .setRemoveAudio(false) .setRemoveVideo(false) .setFlattenVideoForSlowMotion(false) - .setDecoderFactory(new DefaultDecoderFactory(context)) .createAssetLoader(mediaItem, looper, listener); } 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 ab3cbae661..c0c07f04e5 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 @@ -61,6 +61,7 @@ import com.google.android.exoplayer2.testutil.FakeClock; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.primitives.Ints; import java.io.IOException; @@ -527,8 +528,9 @@ public final class TransformerEndToEndTest { MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory( context, new SlowExtractorsFactory(/* delayBetweenReadsMs= */ 10)); + Codec.DecoderFactory decoderFactory = new DefaultDecoderFactory(context); AssetLoader.Factory assetLoaderFactory = - new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, clock); + new ExoPlayerAssetLoader.Factory(context, mediaSourceFactory, decoderFactory, clock); Muxer.Factory muxerFactory = new TestMuxerFactory(/* maxDelayBetweenSamplesMs= */ 1); Transformer transformer = createTransformerBuilder(/* enableFallback= */ false) @@ -1101,11 +1103,6 @@ public final class TransformerEndToEndTest { return this; } - @Override - public AssetLoader.Factory setDecoderFactory(Codec.DecoderFactory decoderFactory) { - return this; - } - @Override public AssetLoader createAssetLoader(MediaItem mediaItem, Looper looper, Listener listener) { return new FakeAssetLoader(listener, supportedOutputTypes, sampleConsumerRef); @@ -1155,6 +1152,11 @@ public final class TransformerEndToEndTest { return 0; } + @Override + public ImmutableMap getDecoderNames() { + return ImmutableMap.of(); + } + @Override public void release() {} }