diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/AssetLoader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/AssetLoader.java new file mode 100644 index 0000000000..b6d9c1a691 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/AssetLoader.java @@ -0,0 +1,110 @@ +/* + * 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 androidx.media3.transformer; + +import androidx.media3.common.Format; +import androidx.media3.common.util.UnstableApi; + +/** + * Provides media data to a {@linkplain Transformer}. + * + *
The output samples can be encoded or decoded. + * + *
Only audio and video samples are supported. Both audio and video tracks can be provided by a + * single asset loader, but outputting multiple tracks of the same type is not supported. + */ +@UnstableApi +public interface AssetLoader { + + /** + * A listener of asset loader events. + * + *
This listener is typically used in the following way: + * + *
This listener can be called from any thread. + */ + interface Listener { + + /** Called when the duration of the input media is known. */ + void onDurationUs(long durationUs); + + /** + * Called to register a single output track of sample data. + * + *
Must be called for each track that will be output. + * + *
Must be called on the same thread as {@link #onTrackAdded(Format, long, long)}. + */ + void onTrackRegistered(); + + /** Called when all the tracks have been {@linkplain #onTrackRegistered() registered}. */ + void onAllTracksRegistered(); + + /** + * Called when the information on a {@linkplain #onTrackRegistered() registered} track is known. + * + *
Must be called after the duration has been {@linkplain #onDurationUs(long) reported} and + * all the tracks have been {@linkplain #onAllTracksRegistered registered}. + * + *
Must be called on the same thread as {@link #onTrackRegistered()}. + * + * @param format The {@link Format} of the input media (prior to video slow motion flattening or + * to decoding). + * @param streamStartPositionUs The start position of the stream (offset by {@code + * streamOffsetUs}), in microseconds. + * @param streamOffsetUs The offset that will be added to the timestamps to make sure they are + * non-negative, in microseconds. + * @return The {@link SamplePipeline.Input} describing the type of sample data expected, and to + * which to pass this data. + * @throws TransformationException If an error occurs configuring the {@link + * SamplePipeline.Input}. + */ + SamplePipeline.Input onTrackAdded( + Format format, long streamStartPositionUs, long streamOffsetUs) + throws TransformationException; + + /** + * Called if an error occurs in the asset loader. In this case, the asset loader will be + * {@linkplain #release() released} automatically. + */ + void onError(Exception e); + } + + /** Starts the asset loader. */ + void start(); + + /** + * Returns the current {@link Transformer.ProgressState} and updates {@code progressHolder} with + * the current progress if it is {@link Transformer#PROGRESS_STATE_AVAILABLE available}. + * + * @param progressHolder A {@link ProgressHolder}, updated to hold the percentage progress if + * {@link Transformer#PROGRESS_STATE_AVAILABLE available}. + * @return The {@link Transformer.ProgressState}. + */ + @Transformer.ProgressState + int getProgress(ProgressHolder progressHolder); + + /** Stops loading data and releases all resources associated with the asset loader. */ + void release(); +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoader.java index a4ba735566..3b8623e81c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoader.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoader.java @@ -30,7 +30,6 @@ import android.content.Context; import android.os.Handler; import android.os.Looper; import androidx.media3.common.C; -import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; @@ -48,22 +47,7 @@ import androidx.media3.exoplayer.text.TextOutput; import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; import androidx.media3.exoplayer.video.VideoRendererEventListener; -/* package */ final class ExoPlayerAssetLoader { - - public interface Listener { - - void onDurationUs(long durationUs); - - void onTrackRegistered(); - - void onAllTracksRegistered(); - - SamplePipeline.Input onTrackAdded( - Format format, long streamStartPositionUs, long streamOffsetUs) - throws TransformationException; - - void onError(Exception e); - } +/* package */ final class ExoPlayerAssetLoader implements AssetLoader { private final MediaItem mediaItem; private final ExoPlayer player; @@ -119,6 +103,7 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; progressState = PROGRESS_STATE_NO_TRANSFORMATION; } + @Override public void start() { player.setMediaItem(mediaItem); player.prepare(); @@ -126,6 +111,7 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; progressState = PROGRESS_STATE_WAITING_FOR_AVAILABILITY; } + @Override public @Transformer.ProgressState int getProgress(ProgressHolder progressHolder) { if (progressState == PROGRESS_STATE_AVAILABLE) { long durationMs = player.getDuration(); @@ -135,6 +121,7 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; return progressState; } + @Override public void release() { player.release(); progressState = PROGRESS_STATE_NO_TRANSFORMATION; @@ -147,14 +134,14 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; private final boolean removeVideo; private final boolean flattenForSlowMotion; private final Codec.DecoderFactory decoderFactory; - private final ExoPlayerAssetLoader.Listener assetLoaderListener; + private final Listener assetLoaderListener; public RenderersFactoryImpl( boolean removeAudio, boolean removeVideo, boolean flattenForSlowMotion, Codec.DecoderFactory decoderFactory, - ExoPlayerAssetLoader.Listener assetLoaderListener) { + Listener assetLoaderListener) { this.removeAudio = removeAudio; this.removeVideo = removeVideo; this.flattenForSlowMotion = flattenForSlowMotion; @@ -199,10 +186,10 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; private final class PlayerListener implements Player.Listener { - private final Listener listener; + private final Listener assetLoaderListener; - public PlayerListener(Listener listener) { - this.listener = listener; + public PlayerListener(Listener assetLoaderListener) { + this.assetLoaderListener = assetLoaderListener; } @Override @@ -221,18 +208,18 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener; durationUs <= 0 || durationUs == C.TIME_UNSET ? PROGRESS_STATE_UNAVAILABLE : PROGRESS_STATE_AVAILABLE; - listener.onDurationUs(window.durationUs); + assetLoaderListener.onDurationUs(window.durationUs); } } @Override public void onTracksChanged(Tracks tracks) { - listener.onAllTracksRegistered(); + assetLoaderListener.onAllTracksRegistered(); } @Override public void onPlayerError(PlaybackException error) { - listener.onError(error); + assetLoaderListener.onError(error); } } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoaderRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoaderRenderer.java index 9727fe765b..3337553174 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoaderRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoPlayerAssetLoaderRenderer.java @@ -43,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private final boolean flattenForSlowMotion; private final Codec.DecoderFactory decoderFactory; private final TransformerMediaClock mediaClock; - private final ExoPlayerAssetLoader.Listener assetLoaderListener; + private final AssetLoader.Listener assetLoaderListener; private final DecoderInputBuffer decoderInputBuffer; private boolean isTransformationRunning; @@ -60,7 +60,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; boolean flattenForSlowMotion, Codec.DecoderFactory decoderFactory, TransformerMediaClock mediaClock, - ExoPlayerAssetLoader.Listener assetLoaderListener) { + AssetLoader.Listener assetLoaderListener) { super(trackType); this.flattenForSlowMotion = flattenForSlowMotion; this.decoderFactory = decoderFactory; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SamplePipeline.java index f4058784ec..e33c79ad52 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SamplePipeline.java @@ -17,6 +17,7 @@ package androidx.media3.transformer; import androidx.annotation.Nullable; +import androidx.media3.common.util.UnstableApi; import androidx.media3.decoder.DecoderInputBuffer; /** @@ -24,7 +25,8 @@ import androidx.media3.decoder.DecoderInputBuffer; * *
This pipeline can be used to implement transformations of audio or video samples.
*/
-/* package */ interface SamplePipeline {
+@UnstableApi
+public interface SamplePipeline {
/** Input of a {@link SamplePipeline}. */
interface Input {
diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java
index 4f4078334b..a909d95b24 100644
--- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java
+++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java
@@ -102,7 +102,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final Clock clock;
private final HandlerThread internalHandlerThread;
private final HandlerWrapper internalHandler;
- private final ExoPlayerAssetLoader exoPlayerAssetLoader;
+ private final AssetLoader assetLoader;
private final List