Add AssetLoader.Factory

This is so that apps can customise AssetLoader

PiperOrigin-RevId: 494998497
This commit is contained in:
kimvde 2022-12-13 13:58:05 +00:00 committed by Ian Baker
parent c17c23d1f1
commit 339ce4fced
4 changed files with 244 additions and 11 deletions

View file

@ -16,7 +16,13 @@
package com.google.android.exoplayer2.transformer;
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;
/**
* Provides media data to a {@linkplain Transformer}.
@ -28,6 +34,82 @@ import com.google.android.exoplayer2.Format;
*/
public interface AssetLoader {
/** A factory for {@link AssetLoader} instances. */
interface Factory {
/** Sets the context. */
@CanIgnoreReturnValue
Factory setContext(Context context);
/** Sets the {@link MediaItem} to load. */
@CanIgnoreReturnValue
Factory setMediaItem(MediaItem mediaItem);
/**
* Sets whether to remove the audio samples from the output (if any).
*
* <p>The audio and video cannot both be removed because the output would not contain any
* samples.
*/
@CanIgnoreReturnValue
Factory setRemoveAudio(boolean removeAudio);
/**
* Sets whether to remove the video samples from the output (if any).
*
* <p>The audio and video cannot both be removed because the output would not contain any
* samples.
*/
@CanIgnoreReturnValue
Factory setRemoveVideo(boolean removeVideo);
/**
* Sets whether the video samples should be flattened prior to decoding for media containing
* slow motion markers.
*
* <p>The audio samples are flattened after they are output by the {@link AssetLoader}, because
* this is done on decoded samples.
*
* <p>For more information on slow motion flattening, see {@link
* TransformationRequest.Builder#setFlattenForSlowMotion(boolean)}.
*/
@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);
/**
* Sets the {@link Looper} that's used to access the {@link AssetLoader} after it's been
* created.
*/
@CanIgnoreReturnValue
Factory setLooper(Looper looper);
/** Sets the {@link Listener} on which the {@link AssetLoader} should notify of events. */
@CanIgnoreReturnValue
Factory setListener(AssetLoader.Listener listener);
/**
* The {@link Clock} to use.
*
* <p>Should always be {@link Clock#DEFAULT} except for testing.
*/
@CanIgnoreReturnValue
Factory setClock(Clock clock);
/**
* Creates an {@link AssetLoader} instance. All the setters in this factory must be called
* before creating the {@link AssetLoader}.
*/
AssetLoader createAssetLoader();
}
/**
* A listener of asset loader events.
*

View file

@ -0,0 +1,127 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
@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 setMediaSourceFactory(MediaSource.Factory mediaSourceFactory) {
this.mediaSourceFactory = mediaSourceFactory;
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() {
return new ExoPlayerAssetLoader(
checkStateNotNull(context),
checkStateNotNull(mediaItem),
removeAudio,
removeVideo,
flattenVideoForSlowMotion,
checkStateNotNull(mediaSourceFactory),
checkStateNotNull(decoderFactory),
checkStateNotNull(looper),
checkStateNotNull(listener),
checkStateNotNull(clock));
}
}

View file

@ -90,6 +90,7 @@ public final class Transformer {
private boolean forceSilentAudio;
private ListenerSet<Transformer.Listener> listeners;
private MediaSource.@MonotonicNonNull Factory mediaSourceFactory;
private AssetLoader.Factory assetLoaderFactory;
private Codec.DecoderFactory decoderFactory;
private Codec.EncoderFactory encoderFactory;
private FrameProcessor.Factory frameProcessorFactory;
@ -108,6 +109,7 @@ public final class Transformer {
transformationRequest = new TransformationRequest.Builder().build();
audioProcessors = ImmutableList.of();
videoEffects = ImmutableList.of();
assetLoaderFactory = new DefaultAssetLoaderFactory();
decoderFactory = new DefaultDecoderFactory(this.context);
encoderFactory = new DefaultEncoderFactory.Builder(this.context).build();
frameProcessorFactory = new GlEffectsFrameProcessor.Factory();
@ -129,6 +131,7 @@ public final class Transformer {
this.forceSilentAudio = transformer.forceSilentAudio;
this.listeners = transformer.listeners;
this.mediaSourceFactory = transformer.mediaSourceFactory;
this.assetLoaderFactory = transformer.assetLoaderFactory;
this.decoderFactory = transformer.decoderFactory;
this.encoderFactory = transformer.encoderFactory;
this.frameProcessorFactory = transformer.frameProcessorFactory;
@ -304,6 +307,20 @@ public final class Transformer {
return this;
}
/**
* Sets the {@link AssetLoader.Factory} to be used to retrieve the samples to transform.
*
* <p>The default value is a {@link DefaultAssetLoaderFactory}.
*
* @param assetLoaderFactory An {@link AssetLoader.Factory}.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setAssetLoaderFactory(AssetLoader.Factory assetLoaderFactory) {
this.assetLoaderFactory = assetLoaderFactory;
return this;
}
/**
* Sets the {@link Codec.DecoderFactory} that will be used by the transformer.
*
@ -476,6 +493,7 @@ public final class Transformer {
forceSilentAudio,
listeners,
mediaSourceFactory,
assetLoaderFactory,
decoderFactory,
encoderFactory,
frameProcessorFactory,
@ -589,6 +607,7 @@ public final class Transformer {
private final boolean forceSilentAudio;
private final ListenerSet<Transformer.Listener> listeners;
private final MediaSource.Factory mediaSourceFactory;
private final AssetLoader.Factory assetLoaderFactory;
private final FrameProcessor.Factory frameProcessorFactory;
private final Muxer.Factory muxerFactory;
private final Looper looper;
@ -607,6 +626,7 @@ public final class Transformer {
boolean forceSilentAudio,
ListenerSet<Listener> listeners,
MediaSource.Factory mediaSourceFactory,
AssetLoader.Factory assetLoaderFactory,
Codec.DecoderFactory decoderFactory,
Codec.EncoderFactory encoderFactory,
FrameProcessor.Factory frameProcessorFactory,
@ -628,6 +648,7 @@ public final class Transformer {
this.forceSilentAudio = forceSilentAudio;
this.listeners = listeners;
this.mediaSourceFactory = mediaSourceFactory;
this.assetLoaderFactory = assetLoaderFactory;
this.decoderFactory = decoderFactory;
this.encoderFactory = encoderFactory;
this.frameProcessorFactory = frameProcessorFactory;
@ -770,6 +791,7 @@ public final class Transformer {
removeVideo,
forceSilentAudio,
mediaSourceFactory,
assetLoaderFactory,
decoderFactory,
encoderFactory,
frameProcessorFactory,

View file

@ -128,6 +128,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
boolean removeVideo,
boolean forceSilentAudio,
MediaSource.Factory mediaSourceFactory,
AssetLoader.Factory assetLoaderFactory,
Codec.DecoderFactory decoderFactory,
Codec.EncoderFactory encoderFactory,
FrameProcessor.Factory frameProcessorFactory,
@ -152,17 +153,18 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
Looper internalLooper = internalHandlerThread.getLooper();
ComponentListener componentListener = new ComponentListener(mediaItem, fallbackListener);
assetLoader =
new ExoPlayerAssetLoader(
context,
mediaItem,
removeAudio,
removeVideo,
transformationRequest.flattenForSlowMotion,
mediaSourceFactory,
decoderFactory,
internalLooper,
componentListener,
clock);
assetLoaderFactory
.setContext(context)
.setMediaItem(mediaItem)
.setRemoveAudio(removeAudio)
.setRemoveVideo(removeVideo)
.setFlattenVideoForSlowMotion(transformationRequest.flattenForSlowMotion)
.setMediaSourceFactory(mediaSourceFactory)
.setDecoderFactory(decoderFactory)
.setLooper(internalLooper)
.setListener(componentListener)
.setClock(clock)
.createAssetLoader();
samplePipelines = new ArrayList<>();
silentSamplePipelineIndex = C.INDEX_UNSET;
dequeueBufferConditionVariable = new ConditionVariable();