diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java index 7d76833bb0..6cb3bc7ea3 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java @@ -40,6 +40,7 @@ import androidx.media3.common.Effect; import androidx.media3.common.FrameInfo; import androidx.media3.common.GlObjectsProvider; import androidx.media3.common.GlTextureInfo; +import androidx.media3.common.SurfaceInfo; import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.util.Consumer; @@ -195,8 +196,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public void onOutputSizeChanged(int width, int height) { - checkNotNull(compositionVideoFrameProcessor) - .setOutputSurfaceInfo(listener.onOutputSizeChanged(width, height)); + listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height)); } @Override @@ -297,6 +297,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return preProcessingVideoFrameProcessorWrapper; } + @Override + public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { + checkNotNull(compositionVideoFrameProcessor).setOutputSurfaceInfo(outputSurfaceInfo); + } + @Override public boolean hasProducedFrameWithTimestampZero() { return hasProducedFrameWithTimestampZero; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java index 0c117aff3f..1daf489464 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java @@ -25,6 +25,7 @@ import androidx.media3.common.ColorInfo; import androidx.media3.common.DebugViewProvider; import androidx.media3.common.Effect; import androidx.media3.common.FrameInfo; +import androidx.media3.common.SurfaceInfo; import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.util.Consumer; @@ -157,9 +158,7 @@ import java.util.concurrent.Executor; @Override public void onOutputSizeChanged(int width, int height) { - // TODO: b/289986435 - Allow setting output surface info on VideoGraph. - checkNotNull(videoFrameProcessingWrapper) - .setOutputSurfaceInfo(listener.onOutputSizeChanged(width, height)); + listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height)); } @Override @@ -188,6 +187,11 @@ import java.util.concurrent.Executor; return videoFrameProcessingWrapper; } + @Override + public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { + checkNotNull(videoFrameProcessingWrapper).setOutputSurfaceInfo(outputSurfaceInfo); + } + @Override public boolean hasProducedFrameWithTimestampZero() { return hasProducedFrameWithTimestampZero; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoGraph.java index 1043eebe1a..e60015c598 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoGraph.java @@ -68,12 +68,8 @@ import java.util.concurrent.Executor; * * @param width The new output width in pixels. * @param height The new output width in pixels. - * @return A {@link SurfaceInfo} to which the {@link VideoGraph} renders to, or {@code null} if - * the output is not needed. */ - // TODO - b/289985577: Consider returning void from this method. - @Nullable - SurfaceInfo onOutputSizeChanged(int width, int height); + void onOutputSizeChanged(int width, int height); /** Called after the {@link VideoGraph} has rendered its final output frame. */ void onEnded(long finalFramePresentationTimeUs); @@ -108,6 +104,23 @@ import java.util.concurrent.Executor; */ GraphInput createInput() throws VideoFrameProcessingException; + /** + * Sets the output surface and supporting information. + * + *
The new output {@link SurfaceInfo} is applied from the next output frame rendered onwards. + * If the output {@link SurfaceInfo} is {@code null}, the {@code VideoGraph} will stop rendering + * pending frames and resume rendering once a non-null {@link SurfaceInfo} is set. + * + *
If the dimensions given in {@link SurfaceInfo} do not match the {@linkplain + * Listener#onOutputSizeChanged(int,int) output size after applying the final effect} the frames + * are resized before rendering to the surface and letter/pillar-boxing is applied. + * + *
The caller is responsible for tracking the lifecycle of the {@link SurfaceInfo#surface} + * including calling this method with a new surface if it is destroyed. When this method returns, + * the previous output surface is no longer being used and can safely be released by the caller. + */ + void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo); + /** * Returns whether the {@code VideoGraph} has produced a frame with zero presentation timestamp. */ 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 ab1a58702c..f64cbad630 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java @@ -498,16 +498,15 @@ import org.checkerframework.dataflow.qual.Pure; initialTimestampOffsetUs); } - @Nullable @Override - public SurfaceInfo onOutputSizeChanged(int width, int height) { + public void onOutputSizeChanged(int width, int height) { @Nullable SurfaceInfo surfaceInfo = null; try { surfaceInfo = encoderWrapper.getSurfaceInfo(width, height); } catch (ExportException e) { errorConsumer.accept(e); } - return surfaceInfo; + setOutputSurfaceInfo(surfaceInfo); } @Override @@ -535,6 +534,11 @@ import org.checkerframework.dataflow.qual.Pure; return videoGraph.createInput(); } + @Override + public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { + videoGraph.setOutputSurfaceInfo(outputSurfaceInfo); + } + @Override public boolean hasProducedFrameWithTimestampZero() { return videoGraph.hasProducedFrameWithTimestampZero();