From cd70a5cef538c9cd2f7d61dd4ee2d471775d171f Mon Sep 17 00:00:00 2001 From: kimvde Date: Mon, 19 Dec 2022 14:43:30 +0000 Subject: [PATCH] Move setMediaSourceFactory to ExoPlayerAssetLoader The MediaSourceFactory won't be used by the other AssetLoaders In order to do that, ExoPlayerAssetLoader has been made public, and the DefaultAssetLoaderFactory has become a wrapper around ExoPlayerAssetLoader. PiperOrigin-RevId: 496386853 --- .../exoplayer2/transformer/AssetLoader.java | 16 +-- .../DefaultAssetLoaderFactory.java | 65 +++------ .../transformer/ExoPlayerAssetLoader.java | 131 +++++++++++++++++- .../transformer/TransformationRequest.java | 8 +- .../exoplayer2/transformer/Transformer.java | 33 ----- .../transformer/TransformerInternal.java | 3 - .../transformer/TransformerEndToEndTest.java | 3 +- 7 files changed, 159 insertions(+), 100 deletions(-) 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 b14ca8c7c9..f6bbe37179 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 @@ -20,7 +20,6 @@ import android.content.Context; import android.os.Looper; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Clock; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -34,10 +33,15 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; */ public interface AssetLoader { - /** A factory for {@link AssetLoader} instances. */ + /** + * A factory for {@link AssetLoader} instances. + * + *

The setters in this interface will be called with the values used to build and start the + * {@link Transformer}. + */ interface Factory { - /** Sets the context. */ + /** Sets the {@link Context}. */ @CanIgnoreReturnValue Factory setContext(Context context); @@ -76,10 +80,6 @@ public interface AssetLoader { @CanIgnoreReturnValue Factory setFlattenVideoForSlowMotion(boolean flattenVideoForSlowMotion); - /** Sets the {@link MediaSource.Factory} to be used to retrieve the samples. */ - @CanIgnoreReturnValue - Factory setMediaSourceFactory(MediaSource.Factory mediaSourceFactory); - /** Sets the {@link Codec.DecoderFactory} to be used to decode the samples (if necessary). */ @CanIgnoreReturnValue Factory setDecoderFactory(Codec.DecoderFactory decoderFactory); @@ -111,7 +111,7 @@ public interface AssetLoader { } /** - * A listener of asset loader events. + * A listener of {@link AssetLoader} events. * *

This listener is typically used in the following way: * 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 f0f0287796..c5ab9d6365 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 @@ -16,112 +16,79 @@ package com.google.android.exoplayer2.transformer; -import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; - import android.content.Context; import android.os.Looper; -import androidx.annotation.Nullable; import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Clock; import com.google.errorprone.annotations.CanIgnoreReturnValue; /** The default {@link AssetLoader.Factory} implementation. */ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { - @Nullable private Context context; - @Nullable private MediaItem mediaItem; - private boolean removeAudio; - private boolean removeVideo; - private boolean flattenVideoForSlowMotion; - @Nullable private MediaSource.Factory mediaSourceFactory; - @Nullable private Codec.DecoderFactory decoderFactory; - @Nullable private Looper looper; - @Nullable private AssetLoader.Listener listener; - @Nullable private Clock clock; + private final AssetLoader.Factory assetLoaderFactory; + + /** Creates an instance. */ + public DefaultAssetLoaderFactory() { + assetLoaderFactory = new ExoPlayerAssetLoader.Factory(); + } @Override @CanIgnoreReturnValue public AssetLoader.Factory setContext(Context context) { - this.context = context; - return this; + return assetLoaderFactory.setContext(context); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setMediaItem(MediaItem mediaItem) { - this.mediaItem = mediaItem; - return this; + return assetLoaderFactory.setMediaItem(mediaItem); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setRemoveAudio(boolean removeAudio) { - this.removeAudio = removeAudio; - return this; + return assetLoaderFactory.setRemoveAudio(removeAudio); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setRemoveVideo(boolean removeVideo) { - this.removeVideo = removeVideo; - return this; + return assetLoaderFactory.setRemoveVideo(removeVideo); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setFlattenVideoForSlowMotion(boolean flattenVideoForSlowMotion) { - this.flattenVideoForSlowMotion = flattenVideoForSlowMotion; - return this; - } - - @Override - @CanIgnoreReturnValue - public AssetLoader.Factory setMediaSourceFactory(MediaSource.Factory mediaSourceFactory) { - this.mediaSourceFactory = mediaSourceFactory; + assetLoaderFactory.setFlattenVideoForSlowMotion(flattenVideoForSlowMotion); return this; } @Override @CanIgnoreReturnValue public AssetLoader.Factory setDecoderFactory(Codec.DecoderFactory decoderFactory) { - this.decoderFactory = decoderFactory; - return this; + return assetLoaderFactory.setDecoderFactory(decoderFactory); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setLooper(Looper looper) { - this.looper = looper; - return this; + return assetLoaderFactory.setLooper(looper); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setListener(AssetLoader.Listener listener) { - this.listener = listener; - return this; + return assetLoaderFactory.setListener(listener); } @Override @CanIgnoreReturnValue public AssetLoader.Factory setClock(Clock clock) { - this.clock = clock; - return this; + return assetLoaderFactory.setClock(clock); } @Override public AssetLoader createAssetLoader() { - return new ExoPlayerAssetLoader( - checkStateNotNull(context), - checkStateNotNull(mediaItem), - removeAudio, - removeVideo, - flattenVideoForSlowMotion, - checkStateNotNull(mediaSourceFactory), - checkStateNotNull(decoderFactory), - checkStateNotNull(looper), - checkStateNotNull(listener), - checkStateNotNull(clock)); + return assetLoaderFactory.createAssetLoader(); } } 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 356c33334f..d3b388efd2 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 @@ -24,11 +24,13 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_NO_TRANSFORMATION; 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.checkStateNotNull; import static java.lang.Math.min; import android.content.Context; import android.os.Handler; import android.os.Looper; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.ExoPlayer; @@ -40,21 +42,146 @@ import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Tracks; import com.google.android.exoplayer2.audio.AudioRendererEventListener; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; +import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; import com.google.android.exoplayer2.metadata.MetadataOutput; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.MediaSource; 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.errorprone.annotations.CanIgnoreReturnValue; -/* package */ final class ExoPlayerAssetLoader implements AssetLoader { +/** An {@link AssetLoader} implementation that uses an {@link ExoPlayer} to load samples. */ +public final class ExoPlayerAssetLoader implements AssetLoader { + + /** An {@link AssetLoader.Factory} for {@link ExoPlayerAssetLoader} instances. */ + public static final class Factory implements AssetLoader.Factory { + + @Nullable private Context context; + @Nullable private MediaItem mediaItem; + private boolean removeAudio; + private boolean removeVideo; + private boolean flattenVideoForSlowMotion; + @Nullable private MediaSource.Factory mediaSourceFactory; + @Nullable private Codec.DecoderFactory decoderFactory; + @Nullable private Looper looper; + @Nullable private AssetLoader.Listener listener; + @Nullable private Clock clock; + + /** + * Creates an instance. + * + *

The {@link ExoPlayerAssetLoader} instances produced use a {@link + * DefaultMediaSourceFactory} built with the context provided in {@linkplain + * #setContext(Context)}. + */ + public Factory() {} + + /** + * Creates an instance. + * + * @param mediaSourceFactory The {@link MediaSource.Factory} to be used to retrieve the samples + * to transform. + */ + public Factory(MediaSource.Factory mediaSourceFactory) { + this.mediaSourceFactory = mediaSourceFactory; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setContext(Context context) { + this.context = context; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setMediaItem(MediaItem mediaItem) { + this.mediaItem = mediaItem; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setRemoveAudio(boolean removeAudio) { + this.removeAudio = removeAudio; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setRemoveVideo(boolean removeVideo) { + this.removeVideo = removeVideo; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setFlattenVideoForSlowMotion(boolean flattenVideoForSlowMotion) { + this.flattenVideoForSlowMotion = flattenVideoForSlowMotion; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setDecoderFactory(Codec.DecoderFactory decoderFactory) { + this.decoderFactory = decoderFactory; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setLooper(Looper looper) { + this.looper = looper; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setListener(AssetLoader.Listener listener) { + this.listener = listener; + return this; + } + + @Override + @CanIgnoreReturnValue + public AssetLoader.Factory setClock(Clock clock) { + this.clock = clock; + return this; + } + + @Override + public AssetLoader createAssetLoader() { + Context context = checkStateNotNull(this.context); + if (mediaSourceFactory == null) { + DefaultExtractorsFactory defaultExtractorsFactory = new DefaultExtractorsFactory(); + if (flattenVideoForSlowMotion) { + defaultExtractorsFactory.setMp4ExtractorFlags(Mp4Extractor.FLAG_READ_SEF_DATA); + } + mediaSourceFactory = new DefaultMediaSourceFactory(context, defaultExtractorsFactory); + } + return new ExoPlayerAssetLoader( + context, + checkStateNotNull(mediaItem), + removeAudio, + removeVideo, + flattenVideoForSlowMotion, + mediaSourceFactory, + checkStateNotNull(decoderFactory), + checkStateNotNull(looper), + checkStateNotNull(listener), + checkStateNotNull(clock)); + } + } private final MediaItem mediaItem; private final ExoPlayer player; private @Transformer.ProgressState int progressState; - public ExoPlayerAssetLoader( + private ExoPlayerAssetLoader( Context context, MediaItem mediaItem, boolean removeAudio, diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java index 1da4662288..e37c144e9f 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java @@ -140,10 +140,10 @@ public final class TransformationRequest { *

  • The recording frame rate of the video is 120 or 240 fps. * * - *

    If specifying a {@link MediaSource.Factory} using {@link - * Transformer.Builder#setMediaSourceFactory(MediaSource.Factory)}, make sure that {@link - * Mp4Extractor#FLAG_READ_SEF_DATA} is set on the {@link Mp4Extractor} used. Otherwise, the slow - * motion metadata will be ignored and the input won't be flattened. + *

    If using an {@link ExoPlayerAssetLoader.Factory} with a provided {@link + * MediaSource.Factory}, make sure that {@link Mp4Extractor#FLAG_READ_SEF_DATA} is set on the + * {@link Mp4Extractor} used. Otherwise, the slow motion metadata will be ignored and the input + * won't be flattened. * *

    Using slow motion flattening together with {@link * com.google.android.exoplayer2.MediaItem.ClippingConfiguration} is not supported yet. 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 d2580a4944..1ebaafa68c 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 @@ -34,9 +34,6 @@ import com.google.android.exoplayer2.audio.SonicAudioProcessor; import com.google.android.exoplayer2.effect.GlEffect; import com.google.android.exoplayer2.effect.GlEffectsFrameProcessor; import com.google.android.exoplayer2.effect.GlMatrixTransformation; -import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; -import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; -import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.DebugViewProvider; @@ -53,7 +50,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.List; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * A transformer to transform media inputs. @@ -89,7 +85,6 @@ public final class Transformer { private boolean removeVideo; private boolean forceSilentAudio; private ListenerSet listeners; - private MediaSource.@MonotonicNonNull Factory mediaSourceFactory; private AssetLoader.Factory assetLoaderFactory; private Codec.DecoderFactory decoderFactory; private Codec.EncoderFactory encoderFactory; @@ -130,7 +125,6 @@ public final class Transformer { this.removeVideo = transformer.removeVideo; this.forceSilentAudio = transformer.forceSilentAudio; this.listeners = transformer.listeners; - this.mediaSourceFactory = transformer.mediaSourceFactory; this.assetLoaderFactory = transformer.assetLoaderFactory; this.decoderFactory = transformer.decoderFactory; this.encoderFactory = transformer.encoderFactory; @@ -292,21 +286,6 @@ public final class Transformer { return this; } - /** - * Sets the {@link MediaSource.Factory} to be used to retrieve the inputs to transform. - * - *

    The default value is a {@link DefaultMediaSourceFactory} built with the context provided - * in {@linkplain #Builder(Context) the constructor}. - * - * @param mediaSourceFactory A {@link MediaSource.Factory}. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setMediaSourceFactory(MediaSource.Factory mediaSourceFactory) { - this.mediaSourceFactory = mediaSourceFactory; - return this; - } - /** * Sets the {@link AssetLoader.Factory} to be used to retrieve the samples to transform. * @@ -476,13 +455,6 @@ public final class Transformer { if (transformationRequest.videoMimeType != null) { checkSampleMimeType(transformationRequest.videoMimeType); } - if (mediaSourceFactory == null) { - DefaultExtractorsFactory defaultExtractorsFactory = new DefaultExtractorsFactory(); - if (transformationRequest.flattenForSlowMotion) { - defaultExtractorsFactory.setMp4ExtractorFlags(Mp4Extractor.FLAG_READ_SEF_DATA); - } - mediaSourceFactory = new DefaultMediaSourceFactory(context, defaultExtractorsFactory); - } return new Transformer( context, transformationRequest, @@ -492,7 +464,6 @@ public final class Transformer { removeVideo, forceSilentAudio, listeners, - mediaSourceFactory, assetLoaderFactory, decoderFactory, encoderFactory, @@ -618,7 +589,6 @@ public final class Transformer { private final boolean removeVideo; private final boolean forceSilentAudio; private final ListenerSet listeners; - private final MediaSource.Factory mediaSourceFactory; private final AssetLoader.Factory assetLoaderFactory; private final FrameProcessor.Factory frameProcessorFactory; private final Muxer.Factory muxerFactory; @@ -637,7 +607,6 @@ public final class Transformer { boolean removeVideo, boolean forceSilentAudio, ListenerSet listeners, - MediaSource.Factory mediaSourceFactory, AssetLoader.Factory assetLoaderFactory, Codec.DecoderFactory decoderFactory, Codec.EncoderFactory encoderFactory, @@ -659,7 +628,6 @@ public final class Transformer { this.removeVideo = removeVideo; this.forceSilentAudio = forceSilentAudio; this.listeners = listeners; - this.mediaSourceFactory = mediaSourceFactory; this.assetLoaderFactory = assetLoaderFactory; this.decoderFactory = decoderFactory; this.encoderFactory = encoderFactory; @@ -802,7 +770,6 @@ public final class Transformer { removeAudio, removeVideo, forceSilentAudio, - mediaSourceFactory, assetLoaderFactory, decoderFactory, encoderFactory, 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 6a930880d5..66273c3f94 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 @@ -35,7 +35,6 @@ import com.google.android.exoplayer2.audio.AudioProcessor; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.mp4.SlowMotionData; -import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.DebugViewProvider; @@ -126,7 +125,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; boolean removeAudio, boolean removeVideo, boolean forceSilentAudio, - MediaSource.Factory mediaSourceFactory, AssetLoader.Factory assetLoaderFactory, Codec.DecoderFactory decoderFactory, Codec.EncoderFactory encoderFactory, @@ -158,7 +156,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; .setRemoveAudio(removeAudio) .setRemoveVideo(removeVideo) .setFlattenVideoForSlowMotion(transformationRequest.flattenForSlowMotion) - .setMediaSourceFactory(mediaSourceFactory) .setDecoderFactory(this.decoderFactory) .setLooper(internalLooper) .setListener(componentListener) 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 7e3277347c..5fc90dc285 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 @@ -533,10 +533,11 @@ public final class TransformerEndToEndTest { MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory( context, new SlowExtractorsFactory(/* delayBetweenReadsMs= */ 10)); + AssetLoader.Factory assetLoaderFactory = new ExoPlayerAssetLoader.Factory(mediaSourceFactory); Muxer.Factory muxerFactory = new TestMuxerFactory(/* maxDelayBetweenSamplesMs= */ 1); Transformer transformer = createTransformerBuilder(/* enableFallback= */ false) - .setMediaSourceFactory(mediaSourceFactory) + .setAssetLoaderFactory(assetLoaderFactory) .setMuxerFactory(muxerFactory) .build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);