Remove setDecoderFactory from Transformer

It makes more sense to have it in the AssetLoader now that decoding is
done there, particularly as the decoder factory should rarely be
customized.

Also remove the setter from the AssetLoader.Factory because it's
uncommon to have setters in a factory.

PiperOrigin-RevId: 501244974
This commit is contained in:
kimvde 2023-01-11 12:27:33 +00:00 committed by Rohit Singh
parent a5288a20fb
commit bbffa8ae27
7 changed files with 89 additions and 89 deletions

View file

@ -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<Integer, String> getDecoderNames();
/** Stops loading data and releases all resources associated with the asset loader. */
void release();
}

View file

@ -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) {

View file

@ -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<Integer, String> getDecoderNames() {
ImmutableMap.Builder<Integer, String> 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();

View file

@ -89,9 +89,8 @@ public final class Transformer {
private boolean forceSilentAudio;
private ListenerSet<Transformer.Listener> 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.
*
* <p>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.
*
* <p>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.
*
* <p>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.
*
* <p>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<AudioProcessor> audioProcessors;
@ -602,6 +583,7 @@ public final class Transformer {
private final ListenerSet<Transformer.Listener> 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<Listener> 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,

View file

@ -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<AudioProcessor> audioProcessors;
private final ImmutableList<Effect> 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<Integer, String> 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());

View file

@ -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);
}

View file

@ -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<Integer, String> getDecoderNames() {
return ImmutableMap.of();
}
@Override
public void release() {}
}