From cd6f8a42a515e1b7b68d08e0f3abd5c1aa15bfb9 Mon Sep 17 00:00:00 2001 From: claincly Date: Thu, 28 Sep 2023 08:24:21 -0700 Subject: [PATCH] Move Single/MultiVideoGraph impl to effect PiperOrigin-RevId: 569188658 --- .../androidx/media3/common/VideoGraph.java | 21 +++ .../effect}/MultipleInputVideoGraph.java | 153 ++++++++---------- .../media3/effect}/SingleInputVideoGraph.java | 63 +++++--- .../TransformerMultipleInputVideoGraph.java | 94 +++++++++++ .../TransformerSingleInputVideoGraph.java | 27 +++- .../VideoFrameProcessingWrapper.java | 26 +-- .../transformer/VideoSampleExporter.java | 12 +- 7 files changed, 263 insertions(+), 133 deletions(-) rename libraries/{transformer/src/main/java/androidx/media3/transformer => effect/src/main/java/androidx/media3/effect}/MultipleInputVideoGraph.java (81%) rename libraries/{transformer/src/main/java/androidx/media3/transformer => effect/src/main/java/androidx/media3/effect}/SingleInputVideoGraph.java (80%) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/TransformerMultipleInputVideoGraph.java diff --git a/libraries/common/src/main/java/androidx/media3/common/VideoGraph.java b/libraries/common/src/main/java/androidx/media3/common/VideoGraph.java index 57b5908aed..adba883f42 100644 --- a/libraries/common/src/main/java/androidx/media3/common/VideoGraph.java +++ b/libraries/common/src/main/java/androidx/media3/common/VideoGraph.java @@ -24,6 +24,7 @@ import androidx.media3.common.util.UnstableApi; public interface VideoGraph { /** Listener for video frame processing events. */ + @UnstableApi interface Listener { /** * Called when the output size changes. @@ -58,6 +59,26 @@ public interface VideoGraph { */ void initialize() throws VideoFrameProcessingException; + /** + * Registers a new input to the {@code VideoGraph}. + * + *

A underlying processing {@link VideoFrameProcessor} is created every time this method is + * called. + * + *

If the method throws, the caller must call {@link #release}. + * + * @return The id of the registered input, which can be used to get the underlying {@link + * VideoFrameProcessor} via {@link #getProcessor(int)}. + */ + int registerInput() throws VideoFrameProcessingException; + + /** + * Returns the {@link VideoFrameProcessor} that handles the processing for an input registered via + * {@link #registerInput()}. If the {@code inputId} is not {@linkplain #registerInput() + * registered} before, this method will throw an {@link IllegalStateException}. + */ + VideoFrameProcessor getProcessor(int inputId); + /** * Sets the output surface and supporting information. * diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java similarity index 81% rename from libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java rename to libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java index 6fedfce7a5..86c3c5d80b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.media3.transformer; +package androidx.media3.effect; import static androidx.media3.common.VideoFrameProcessor.INPUT_TYPE_TEXTURE_ID; import static androidx.media3.common.util.Assertions.checkNotNull; @@ -45,12 +45,7 @@ import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoGraph; import androidx.media3.common.util.GlUtil; -import androidx.media3.effect.DefaultGlObjectsProvider; -import androidx.media3.effect.DefaultVideoCompositor; -import androidx.media3.effect.DefaultVideoFrameProcessor; -import androidx.media3.effect.GlTextureProducer; -import androidx.media3.effect.VideoCompositor; -import androidx.media3.effect.VideoCompositorSettings; +import androidx.media3.common.util.UnstableApi; import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayDeque; import java.util.ArrayList; @@ -61,32 +56,8 @@ import java.util.concurrent.ExecutorService; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** A {@link VideoGraph} that handles multiple input streams. */ -/* package */ final class MultipleInputVideoGraph implements TransformerVideoGraph { - - public static final class Factory implements TransformerVideoGraph.Factory { - @Override - public MultipleInputVideoGraph create( - Context context, - ColorInfo inputColorInfo, - ColorInfo outputColorInfo, - DebugViewProvider debugViewProvider, - Listener listener, - Executor listenerExecutor, - VideoCompositorSettings videoCompositorSettings, - List compositionEffects, - long initialTimestampOffsetUs) { - return new MultipleInputVideoGraph( - context, - inputColorInfo, - outputColorInfo, - debugViewProvider, - listener, - listenerExecutor, - videoCompositorSettings, - compositionEffects, - initialTimestampOffsetUs); - } - } +@UnstableApi +public abstract class MultipleInputVideoGraph implements VideoGraph { private static final String SHARED_EXECUTOR_NAME = "Transformer:MultipleInputVideoGraph:Thread"; @@ -95,15 +66,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private static final int COMPOSITOR_TEXTURE_OUTPUT_CAPACITY = 1; private final Context context; + private final ColorInfo inputColorInfo; private final ColorInfo outputColorInfo; private final GlObjectsProvider glObjectsProvider; private final DebugViewProvider debugViewProvider; - private final Listener listener; + private final VideoGraph.Listener listener; private final Executor listenerExecutor; private final VideoCompositorSettings videoCompositorSettings; private final List compositionEffects; - private final List preProcessingWrappers; + private final List preProcessors; private final ExecutorService sharedExecutorService; @@ -124,12 +96,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private volatile boolean hasProducedFrameWithTimestampZero; - private MultipleInputVideoGraph( + protected MultipleInputVideoGraph( Context context, ColorInfo inputColorInfo, ColorInfo outputColorInfo, DebugViewProvider debugViewProvider, - Listener listener, + VideoGraph.Listener listener, Executor listenerExecutor, VideoCompositorSettings videoCompositorSettings, List compositionEffects, @@ -144,7 +116,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.compositionEffects = new ArrayList<>(compositionEffects); this.initialTimestampOffsetUs = initialTimestampOffsetUs; lastRenderedPresentationTimeUs = C.TIME_UNSET; - preProcessingWrappers = new ArrayList<>(); + preProcessors = new ArrayList<>(); sharedExecutorService = newSingleThreadScheduledExecutor(SHARED_EXECUTOR_NAME); glObjectsProvider = new SingleContextGlObjectsProvider(); // TODO - b/289986435: Support injecting VideoFrameProcessor.Factory. @@ -165,7 +137,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public void initialize() throws VideoFrameProcessingException { checkState( - preProcessingWrappers.isEmpty() + preProcessors.isEmpty() && videoCompositor == null && compositionVideoFrameProcessor == null && !released); @@ -243,56 +215,61 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public GraphInput createInput() throws VideoFrameProcessingException { + public int registerInput() throws VideoFrameProcessingException { checkStateNotNull(videoCompositor); int videoCompositorInputId = videoCompositor.registerInputSource(); // Creating a new VideoFrameProcessor for the input. - VideoFrameProcessingWrapper preProcessingVideoFrameProcessorWrapper = - new VideoFrameProcessingWrapper( - context, - videoFrameProcessorFactory - .buildUpon() - .setTextureOutput( - // Texture output to compositor. - (textureProducer, texture, presentationTimeUs, syncObject) -> - queuePreProcessingOutputToCompositor( - videoCompositorInputId, textureProducer, texture, presentationTimeUs), - PRE_COMPOSITOR_TEXTURE_OUTPUT_CAPACITY) - .build(), - inputColorInfo, - outputColorInfo, - DebugViewProvider.NONE, - listenerExecutor, - new VideoFrameProcessor.Listener() { - // All of this listener's methods are called on the sharedExecutorService. - @Override - public void onInputStreamRegistered( - @VideoFrameProcessor.InputType int inputType, - List effects, - FrameInfo frameInfo) {} + VideoFrameProcessor preProcessor = + videoFrameProcessorFactory + .buildUpon() + .setTextureOutput( + // Texture output to compositor. + (textureProducer, texture, presentationTimeUs, syncObject) -> + queuePreProcessingOutputToCompositor( + videoCompositorInputId, textureProducer, texture, presentationTimeUs), + PRE_COMPOSITOR_TEXTURE_OUTPUT_CAPACITY) + .build() + .create( + context, + DebugViewProvider.NONE, + inputColorInfo, + outputColorInfo, + // Pre-processors render frames as soon as available, to VideoCompositor. + /* renderFramesAutomatically= */ true, + listenerExecutor, + new VideoFrameProcessor.Listener() { + // All of this listener's methods are called on the sharedExecutorService. + @Override + public void onInputStreamRegistered( + @VideoFrameProcessor.InputType int inputType, + List effects, + FrameInfo frameInfo) {} - @Override - public void onOutputSizeChanged(int width, int height) {} + @Override + public void onOutputSizeChanged(int width, int height) {} - @Override - public void onOutputFrameAvailableForRendering(long presentationTimeUs) {} + @Override + public void onOutputFrameAvailableForRendering(long presentationTimeUs) {} - @Override - public void onError(VideoFrameProcessingException exception) { - handleVideoFrameProcessingException(exception); - } + @Override + public void onError(VideoFrameProcessingException exception) { + handleVideoFrameProcessingException(exception); + } - @Override - public void onEnded() { - onPreProcessingVideoFrameProcessorEnded(videoCompositorInputId); - } - }, - /* renderFramesAutomatically= */ true, - /* presentation= */ null, - initialTimestampOffsetUs); - preProcessingWrappers.add(preProcessingVideoFrameProcessorWrapper); - return preProcessingVideoFrameProcessorWrapper; + @Override + public void onEnded() { + onPreProcessingVideoFrameProcessorEnded(videoCompositorInputId); + } + }); + preProcessors.add(preProcessor); + return videoCompositorInputId; + } + + @Override + public VideoFrameProcessor getProcessor(int inputId) { + checkState(inputId < preProcessors.size()); + return preProcessors.get(inputId); } @Override @@ -312,10 +289,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } // Needs to release the frame processors before their internal executor services are released. - for (int i = 0; i < preProcessingWrappers.size(); i++) { - preProcessingWrappers.get(i).release(); + for (int i = 0; i < preProcessors.size(); i++) { + preProcessors.get(i).release(); } - preProcessingWrappers.clear(); + preProcessors.clear(); if (videoCompositor != null) { videoCompositor.release(); @@ -338,6 +315,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; released = true; } + protected ColorInfo getInputColorInfo() { + return inputColorInfo; + } + + protected long getInitialTimestampOffsetUs() { + return initialTimestampOffsetUs; + } + // This method is called on the sharedExecutorService. private void queuePreProcessingOutputToCompositor( int videoCompositorInputId, diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java similarity index 80% rename from libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java rename to libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java index 4934956ef6..b2133fb771 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.media3.transformer; +package androidx.media3.effect; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; @@ -30,13 +30,16 @@ import androidx.media3.common.SurfaceInfo; import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoGraph; -import androidx.media3.effect.Presentation; -import androidx.media3.effect.VideoCompositorSettings; +import androidx.media3.common.util.UnstableApi; import java.util.List; import java.util.concurrent.Executor; /** A {@link VideoGraph} that handles one input stream. */ -/* package */ abstract class SingleInputVideoGraph implements VideoGraph { +@UnstableApi +public abstract class SingleInputVideoGraph implements VideoGraph { + + /** The ID {@link #registerInput()} returns. */ + public static final int SINGLE_INPUT_INDEX = 0; private final Context context; private final VideoFrameProcessor.Factory videoFrameProcessorFactory; @@ -46,10 +49,11 @@ import java.util.concurrent.Executor; private final DebugViewProvider debugViewProvider; private final Executor listenerExecutor; private final boolean renderFramesAutomatically; + private final long initialTimestampOffsetUs; @Nullable private final Presentation presentation; - @Nullable private VideoFrameProcessingWrapper videoFrameProcessingWrapper; + @Nullable private VideoFrameProcessor videoFrameProcessor; private boolean released; private volatile boolean hasProducedFrameWithTimestampZero; @@ -93,16 +97,21 @@ import java.util.concurrent.Executor; *

This method must be called at most once. */ @Override - public void initialize() throws VideoFrameProcessingException { - checkStateNotNull(videoFrameProcessingWrapper == null && !released); + public void initialize() { + // Initialization is deferred to registerInput(); + } - videoFrameProcessingWrapper = - new VideoFrameProcessingWrapper( + @Override + public int registerInput() throws VideoFrameProcessingException { + checkStateNotNull(videoFrameProcessor == null && !released); + + videoFrameProcessor = + videoFrameProcessorFactory.create( context, - videoFrameProcessorFactory, + debugViewProvider, inputColorInfo, outputColorInfo, - debugViewProvider, + renderFramesAutomatically, listenerExecutor, new VideoFrameProcessor.Listener() { private long lastProcessedFramePresentationTimeUs; @@ -136,15 +145,18 @@ import java.util.concurrent.Executor; public void onEnded() { listener.onEnded(lastProcessedFramePresentationTimeUs); } - }, - renderFramesAutomatically, - presentation, - initialTimestampOffsetUs); + }); + return SINGLE_INPUT_INDEX; + } + + @Override + public VideoFrameProcessor getProcessor(int inputId) { + return checkStateNotNull(videoFrameProcessor); } @Override public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { - checkNotNull(videoFrameProcessingWrapper).setOutputSurfaceInfo(outputSurfaceInfo); + checkNotNull(videoFrameProcessor).setOutputSurfaceInfo(outputSurfaceInfo); } @Override @@ -158,14 +170,23 @@ import java.util.concurrent.Executor; return; } - if (videoFrameProcessingWrapper != null) { - videoFrameProcessingWrapper.release(); - videoFrameProcessingWrapper = null; + if (videoFrameProcessor != null) { + videoFrameProcessor.release(); + videoFrameProcessor = null; } released = true; } - protected VideoFrameProcessingWrapper getVideoFrameProcessingWrapper() { - return checkNotNull(videoFrameProcessingWrapper); + protected ColorInfo getInputColorInfo() { + return inputColorInfo; + } + + protected long getInitialTimestampOffsetUs() { + return initialTimestampOffsetUs; + } + + @Nullable + protected Presentation getPresentation() { + return presentation; } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerMultipleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerMultipleInputVideoGraph.java new file mode 100644 index 0000000000..468408609a --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerMultipleInputVideoGraph.java @@ -0,0 +1,94 @@ +/* + * Copyright 2023 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 + * + * https://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 android.content.Context; +import androidx.media3.common.ColorInfo; +import androidx.media3.common.DebugViewProvider; +import androidx.media3.common.Effect; +import androidx.media3.common.VideoFrameProcessingException; +import androidx.media3.common.VideoGraph; +import androidx.media3.effect.MultipleInputVideoGraph; +import androidx.media3.effect.VideoCompositorSettings; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * A {@link TransformerVideoGraph Transformer}-specific implementation of {@link + * MultipleInputVideoGraph}. + */ +/* package */ final class TransformerMultipleInputVideoGraph extends MultipleInputVideoGraph + implements TransformerVideoGraph { + + /** A factory for creating {@link TransformerMultipleInputVideoGraph} instances. */ + public static final class Factory implements TransformerVideoGraph.Factory { + @Override + public TransformerMultipleInputVideoGraph create( + Context context, + ColorInfo inputColorInfo, + ColorInfo outputColorInfo, + DebugViewProvider debugViewProvider, + VideoGraph.Listener listener, + Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, + List compositionEffects, + long initialTimestampOffsetUs) { + return new TransformerMultipleInputVideoGraph( + context, + inputColorInfo, + outputColorInfo, + debugViewProvider, + listener, + listenerExecutor, + videoCompositorSettings, + compositionEffects, + initialTimestampOffsetUs); + } + } + + private TransformerMultipleInputVideoGraph( + Context context, + ColorInfo inputColorInfo, + ColorInfo outputColorInfo, + DebugViewProvider debugViewProvider, + Listener listener, + Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, + List compositionEffects, + long initialTimestampOffsetUs) { + super( + context, + inputColorInfo, + outputColorInfo, + debugViewProvider, + listener, + listenerExecutor, + videoCompositorSettings, + compositionEffects, + initialTimestampOffsetUs); + } + + @Override + public GraphInput createInput() throws VideoFrameProcessingException { + int inputId = registerInput(); + return new VideoFrameProcessingWrapper( + getProcessor(inputId), + getInputColorInfo(), + /* presentation= */ null, + getInitialTimestampOffsetUs()); + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java index e8c97c7401..de37dcd9f5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java @@ -16,21 +16,30 @@ package androidx.media3.transformer; +import static androidx.media3.common.util.Assertions.checkState; + import android.content.Context; import androidx.annotation.Nullable; import androidx.media3.common.ColorInfo; import androidx.media3.common.DebugViewProvider; import androidx.media3.common.Effect; +import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.effect.Presentation; +import androidx.media3.effect.SingleInputVideoGraph; import androidx.media3.effect.VideoCompositorSettings; import java.util.List; import java.util.concurrent.Executor; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +/** + * A {@link TransformerVideoGraph Transformer}-specific implementation of {@link + * SingleInputVideoGraph}. + */ /* package */ final class TransformerSingleInputVideoGraph extends SingleInputVideoGraph implements TransformerVideoGraph { - /** A factory for creating a {@link SingleInputVideoGraph}. */ + /** A factory for creating {@link TransformerSingleInputVideoGraph} instances. */ public static final class Factory implements TransformerVideoGraph.Factory { private final VideoFrameProcessor.Factory videoFrameProcessorFactory; @@ -40,7 +49,7 @@ import java.util.concurrent.Executor; } @Override - public TransformerVideoGraph create( + public TransformerSingleInputVideoGraph create( Context context, ColorInfo inputColorInfo, ColorInfo outputColorInfo, @@ -72,6 +81,8 @@ import java.util.concurrent.Executor; } } + private @MonotonicNonNull VideoFrameProcessingWrapper videoFrameProcessingWrapper; + private TransformerSingleInputVideoGraph( Context context, VideoFrameProcessor.Factory videoFrameProcessorFactory, @@ -99,7 +110,15 @@ import java.util.concurrent.Executor; } @Override - public GraphInput createInput() { - return getVideoFrameProcessingWrapper(); + public GraphInput createInput() throws VideoFrameProcessingException { + checkState(videoFrameProcessingWrapper == null); + int inputId = registerInput(); + videoFrameProcessingWrapper = + new VideoFrameProcessingWrapper( + getProcessor(inputId), + getInputColorInfo(), + getPresentation(), + getInitialTimestampOffsetUs()); + return videoFrameProcessingWrapper; } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java index f6e5429806..a489f1f14e 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java @@ -21,26 +21,22 @@ import static androidx.media3.common.VideoFrameProcessor.INPUT_TYPE_SURFACE; import static androidx.media3.common.VideoFrameProcessor.INPUT_TYPE_TEXTURE_ID; import static androidx.media3.common.util.Assertions.checkNotNull; -import android.content.Context; import android.graphics.Bitmap; import android.view.Surface; import androidx.annotation.Nullable; import androidx.media3.common.ColorInfo; -import androidx.media3.common.DebugViewProvider; import androidx.media3.common.Effect; import androidx.media3.common.Format; import androidx.media3.common.FrameInfo; import androidx.media3.common.MimeTypes; import androidx.media3.common.OnInputFrameProcessedListener; import androidx.media3.common.SurfaceInfo; -import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.util.Size; import androidx.media3.common.util.TimestampIterator; import androidx.media3.effect.Presentation; import com.google.common.collect.ImmutableList; import java.util.List; -import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicLong; /** A wrapper for {@link VideoFrameProcessor} that handles {@link GraphInput} events. */ @@ -52,31 +48,15 @@ import java.util.concurrent.atomic.AtomicLong; @Nullable final Presentation presentation; public VideoFrameProcessingWrapper( - Context context, - VideoFrameProcessor.Factory videoFrameProcessorFactory, + VideoFrameProcessor videoFrameProcessor, ColorInfo inputColorInfo, - ColorInfo outputColorInfo, - DebugViewProvider debugViewProvider, - Executor listenerExecutor, - VideoFrameProcessor.Listener listener, - boolean renderFramesAutomatically, @Nullable Presentation presentation, - long initialTimestampOffsetUs) - throws VideoFrameProcessingException { + long initialTimestampOffsetUs) { + this.videoFrameProcessor = videoFrameProcessor; this.mediaItemOffsetUs = new AtomicLong(); this.inputColorInfo = inputColorInfo; this.initialTimestampOffsetUs = initialTimestampOffsetUs; this.presentation = presentation; - - videoFrameProcessor = - videoFrameProcessorFactory.create( - context, - debugViewProvider, - inputColorInfo, - outputColorInfo, - renderFramesAutomatically, - listenerExecutor, - listener); } @Override diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java index 24f95794f1..396efe2bc5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java @@ -147,7 +147,7 @@ import org.checkerframework.dataflow.qual.Pure; new VideoGraphWrapper( context, hasMultipleInputs - ? new MultipleInputVideoGraph.Factory() + ? new TransformerMultipleInputVideoGraph.Factory() : new TransformerSingleInputVideoGraph.Factory(videoFrameProcessorFactory), videoGraphInputColor, videoGraphOutputColor, @@ -533,6 +533,16 @@ import org.checkerframework.dataflow.qual.Pure; videoGraph.initialize(); } + @Override + public int registerInput() throws VideoFrameProcessingException { + return videoGraph.registerInput(); + } + + @Override + public VideoFrameProcessor getProcessor(int inputId) { + return videoGraph.getProcessor(inputId); + } + @Override public GraphInput createInput() throws VideoFrameProcessingException { return videoGraph.createInput();