diff --git a/libraries/common/src/main/java/androidx/media3/common/FrameInfo.java b/libraries/common/src/main/java/androidx/media3/common/FrameInfo.java index b8589e0118..35598483a9 100644 --- a/libraries/common/src/main/java/androidx/media3/common/FrameInfo.java +++ b/libraries/common/src/main/java/androidx/media3/common/FrameInfo.java @@ -27,6 +27,7 @@ public class FrameInfo { /** A builder for {@link FrameInfo} instances. */ public static final class Builder { + private ColorInfo colorInfo; private int width; private int height; private float pixelWidthHeightRatio; @@ -35,10 +36,12 @@ public class FrameInfo { /** * Creates an instance with default values. * + * @param colorInfo The {@link ColorInfo}. * @param width The frame width, in pixels. * @param height The frame height, in pixels. */ - public Builder(int width, int height) { + public Builder(ColorInfo colorInfo, int width, int height) { + this.colorInfo = colorInfo; this.width = width; this.height = height; pixelWidthHeightRatio = 1; @@ -46,12 +49,20 @@ public class FrameInfo { /** Creates an instance with the values of the provided {@link FrameInfo}. */ public Builder(FrameInfo frameInfo) { + colorInfo = frameInfo.colorInfo; width = frameInfo.width; height = frameInfo.height; pixelWidthHeightRatio = frameInfo.pixelWidthHeightRatio; offsetToAddUs = frameInfo.offsetToAddUs; } + /** Sets the {@link ColorInfo}. */ + @CanIgnoreReturnValue + public Builder setColorInfo(ColorInfo colorInfo) { + this.colorInfo = colorInfo; + return this; + } + /** Sets the frame width, in pixels. */ @CanIgnoreReturnValue public Builder setWidth(int width) { @@ -91,10 +102,13 @@ public class FrameInfo { /** Builds a {@link FrameInfo} instance. */ public FrameInfo build() { - return new FrameInfo(width, height, pixelWidthHeightRatio, offsetToAddUs); + return new FrameInfo(colorInfo, width, height, pixelWidthHeightRatio, offsetToAddUs); } } + /** The {@link ColorInfo} of the frame. */ + public final ColorInfo colorInfo; + /** The width of the frame, in pixels. */ public final int width; @@ -112,12 +126,12 @@ public class FrameInfo { */ public final long offsetToAddUs; - // TODO(b/227624622): Add color space information for HDR. - - private FrameInfo(int width, int height, float pixelWidthHeightRatio, long offsetToAddUs) { + private FrameInfo( + ColorInfo colorInfo, int width, int height, float pixelWidthHeightRatio, long offsetToAddUs) { checkArgument(width > 0, "width must be positive, but is: " + width); checkArgument(height > 0, "height must be positive, but is: " + height); + this.colorInfo = colorInfo; this.width = width; this.height = height; this.pixelWidthHeightRatio = pixelWidthHeightRatio; diff --git a/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java b/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java index 79816427fc..a9d6a6f08e 100644 --- a/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java +++ b/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java @@ -82,7 +82,6 @@ public interface VideoFrameProcessor { * * @param context A {@link Context}. * @param debugViewProvider A {@link DebugViewProvider}. - * @param inputColorInfo The {@link ColorInfo} for the input frames. * @param outputColorInfo The {@link ColorInfo} for the output frames. * @param renderFramesAutomatically If {@code true}, the instance will render output frames to * the {@linkplain #setOutputSurfaceInfo(SurfaceInfo) output surface} automatically as @@ -98,7 +97,6 @@ public interface VideoFrameProcessor { VideoFrameProcessor create( Context context, DebugViewProvider debugViewProvider, - ColorInfo inputColorInfo, ColorInfo outputColorInfo, boolean renderFramesAutomatically, Executor listenerExecutor, diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorTest.java index 6a28b80a0d..6a9a9c3802 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorTest.java @@ -100,7 +100,8 @@ public class DefaultVideoFrameProcessorTest { defaultVideoFrameProcessor.registerInputStream( VideoFrameProcessor.INPUT_TYPE_BITMAP, ImmutableList.of(), - new FrameInfo.Builder(/* width= */ 100, /* height= */ 100).build()); + new FrameInfo.Builder(ColorInfo.SRGB_BT709_FULL, /* width= */ 100, /* height= */ 100) + .build()); assertThat(defaultVideoFrameProcessor.getPendingInputFrameCount()).isEqualTo(0); // Unblocks configuration. @@ -150,17 +151,20 @@ public class DefaultVideoFrameProcessorTest { new InputStreamInfo( VideoFrameProcessor.INPUT_TYPE_BITMAP, ImmutableList.of(), - new FrameInfo.Builder(/* width= */ 100, /* height= */ 100).build()); + new FrameInfo.Builder(ColorInfo.SRGB_BT709_FULL, /* width= */ 100, /* height= */ 100) + .build()); InputStreamInfo stream2 = new InputStreamInfo( VideoFrameProcessor.INPUT_TYPE_BITMAP, ImmutableList.of(new Contrast(.5f)), - new FrameInfo.Builder(/* width= */ 200, /* height= */ 200).build()); + new FrameInfo.Builder(ColorInfo.SRGB_BT709_FULL, /* width= */ 200, /* height= */ 200) + .build()); InputStreamInfo stream3 = new InputStreamInfo( VideoFrameProcessor.INPUT_TYPE_BITMAP, ImmutableList.of(), - new FrameInfo.Builder(/* width= */ 300, /* height= */ 300).build()); + new FrameInfo.Builder(ColorInfo.SRGB_BT709_FULL, /* width= */ 300, /* height= */ 300) + .build()); registerInputStream(defaultVideoFrameProcessor, stream1); registerInputStream(defaultVideoFrameProcessor, stream2); @@ -179,7 +183,6 @@ public class DefaultVideoFrameProcessorTest { .create( getApplicationContext(), DebugViewProvider.NONE, - /* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, /* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, /* renderFramesAutomatically= */ true, /* listenerExecutor= */ MoreExecutors.directExecutor(), diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorVideoFrameRenderingTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorVideoFrameRenderingTest.java index 950aec9e9e..56a11a590f 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorVideoFrameRenderingTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/DefaultVideoFrameProcessorVideoFrameRenderingTest.java @@ -292,7 +292,6 @@ public final class DefaultVideoFrameProcessorVideoFrameRenderingTest { .create( getApplicationContext(), DebugViewProvider.NONE, - /* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, /* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, renderFramesAutomatically, MoreExecutors.directExecutor(), @@ -349,7 +348,7 @@ public final class DefaultVideoFrameProcessorVideoFrameRenderingTest { .registerInputStream( INPUT_TYPE_SURFACE, /* effects= */ ImmutableList.of((GlEffect) (context, useHdr) -> blankFrameProducer), - new FrameInfo.Builder(WIDTH, HEIGHT).build()); + new FrameInfo.Builder(ColorInfo.SDR_BT709_LIMITED, WIDTH, HEIGHT).build()); videoFrameProcessorReadyCountDownLatch.await(); blankFrameProducer.produceBlankFrames(inputPresentationTimesUs); defaultVideoFrameProcessor.signalEndOfInput(); diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/FrameDropTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/FrameDropTest.java index 93f8ff7640..0a3d067fa4 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/FrameDropTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/FrameDropTest.java @@ -172,7 +172,6 @@ public class FrameDropTest { .create( getApplicationContext(), DebugViewProvider.NONE, - /* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, /* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, /* renderFramesAutomatically= */ true, MoreExecutors.directExecutor(), @@ -241,7 +240,9 @@ public class FrameDropTest { } })), frameDropEffect), - new FrameInfo.Builder(BLANK_FRAME_WIDTH, BLANK_FRAME_HEIGHT).build()); + new FrameInfo.Builder( + ColorInfo.SDR_BT709_LIMITED, BLANK_FRAME_WIDTH, BLANK_FRAME_HEIGHT) + .build()); videoFrameProcessorReadyCountDownLatch.await(); checkNoVideoFrameProcessingExceptionIsThrown(videoFrameProcessingExceptionReference); blankFrameProducer.produceBlankFrames(inputPresentationTimesUs); diff --git a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java index 0d4dc748ce..86b789ce67 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java @@ -246,7 +246,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { public DefaultVideoFrameProcessor create( Context context, DebugViewProvider debugViewProvider, - ColorInfo inputColorInfo, ColorInfo outputColorInfo, boolean renderFramesAutomatically, Executor listenerExecutor, @@ -268,7 +267,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { createOpenGlObjectsAndFrameProcessor( context, debugViewProvider, - inputColorInfo, outputColorInfo, enableColorTransfers, renderFramesAutomatically, @@ -321,9 +319,10 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { private final List activeEffects; private final Object lock; private final boolean enableColorTransfers; - private final ColorInfo firstInputColorInfo; private final ColorInfo outputColorInfo; + private @MonotonicNonNull ColorInfo firstInputColorInfo; + private volatile @MonotonicNonNull FrameInfo nextInputFrameInfo; private volatile boolean inputStreamEnded; @@ -339,7 +338,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { FinalShaderProgramWrapper finalShaderProgramWrapper, boolean renderFramesAutomatically, boolean enableColorTransfers, - ColorInfo firstInputColorInfo, ColorInfo outputColorInfo) { this.context = context; this.glObjectsProvider = glObjectsProvider; @@ -353,7 +351,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { this.activeEffects = new ArrayList<>(); this.lock = new Object(); this.enableColorTransfers = enableColorTransfers; - this.firstInputColorInfo = firstInputColorInfo; this.outputColorInfo = outputColorInfo; this.finalShaderProgramWrapper = finalShaderProgramWrapper; this.intermediateGlShaderPrograms = new ArrayList<>(); @@ -438,6 +435,13 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { return inputSwitcher.getInputSurface(); } + /** + * {@inheritDoc} + * + *

The {@link FrameInfo}'s {@link ColorInfo} must not change between different calls to this + * method. + */ + // TODO: b/307952514: Remove this javadoc after FrameInfo.colorInfo may change between calls. @Override public void registerInputStream( @InputType int inputType, List effects, FrameInfo frameInfo) { @@ -463,10 +467,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { synchronized (lock) { // An input stream is pending until its effects are configured. - // TODO: b/307952514 - Move inputColorInfo's API from Factory.create into registerInputStream, - // and from StreamInfo into FrameInfo. - InputStreamInfo pendingInputStreamInfo = - new InputStreamInfo(inputType, effects, this.firstInputColorInfo, frameInfo); + InputStreamInfo pendingInputStreamInfo = new InputStreamInfo(inputType, effects, frameInfo); if (!registeredFirstInputStream) { registeredFirstInputStream = true; inputStreamRegisteredCondition.close(); @@ -611,7 +612,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor( Context context, DebugViewProvider debugViewProvider, - ColorInfo inputColorInfo, ColorInfo outputColorInfo, boolean enableColorTransfers, boolean renderFramesAutomatically, @@ -685,7 +685,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { finalShaderProgramWrapper, renderFramesAutomatically, enableColorTransfers, - /* firstInputColorInfo= */ inputColorInfo, outputColorInfo); } @@ -802,7 +801,18 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { */ private void configureEffects(InputStreamInfo inputStreamInfo, boolean forceReconfigure) throws VideoFrameProcessingException { - checkColors(firstInputColorInfo, outputColorInfo, enableColorTransfers); + // TODO: b/307952514 - Remove this color check, and reinitialize the InputSwitcher's + // samplingGlShaderProgram instead. + checkState( + firstInputColorInfo == null + || firstInputColorInfo.equals(inputStreamInfo.frameInfo.colorInfo)); + if (inputStreamInfo.frameInfo.colorInfo != null) { + firstInputColorInfo = inputStreamInfo.frameInfo.colorInfo; + } + checkColors( + /* inputColorInfo= */ inputStreamInfo.frameInfo.colorInfo, + outputColorInfo, + enableColorTransfers); if (forceReconfigure || !activeEffects.equals(inputStreamInfo.effects)) { if (!intermediateGlShaderPrograms.isEmpty()) { for (int i = 0; i < intermediateGlShaderPrograms.size(); i++) { @@ -830,8 +840,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { activeEffects.addAll(inputStreamInfo.effects); } - inputSwitcher.switchToInput( - inputStreamInfo.inputType, inputStreamInfo.frameInfo, inputStreamInfo.colorInfo); + inputSwitcher.switchToInput(inputStreamInfo.inputType, inputStreamInfo.frameInfo); inputStreamRegisteredCondition.open(); listenerExecutor.execute( () -> @@ -940,14 +949,11 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { private static final class InputStreamInfo { public final @InputType int inputType; public final List effects; - public final ColorInfo colorInfo; public final FrameInfo frameInfo; - public InputStreamInfo( - @InputType int inputType, List effects, ColorInfo colorInfo, FrameInfo frameInfo) { + public InputStreamInfo(@InputType int inputType, List effects, FrameInfo frameInfo) { this.inputType = inputType; this.effects = effects; - this.colorInfo = colorInfo; this.frameInfo = frameInfo; } } diff --git a/libraries/effect/src/main/java/androidx/media3/effect/InputSwitcher.java b/libraries/effect/src/main/java/androidx/media3/effect/InputSwitcher.java index 7ed39555eb..3c4a4ce6c8 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/InputSwitcher.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/InputSwitcher.java @@ -152,12 +152,9 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @param newInputType The new {@link VideoFrameProcessor.InputType} to switch to. * @param inputFrameInfo The {@link FrameInfo} associated with the new input. - * @param inputColorInfo The {@link ColorInfo} associated with the new input. */ public void switchToInput( - @VideoFrameProcessor.InputType int newInputType, - FrameInfo inputFrameInfo, - ColorInfo inputColorInfo) + @VideoFrameProcessor.InputType int newInputType, FrameInfo inputFrameInfo) throws VideoFrameProcessingException { checkStateNotNull(downstreamShaderProgram); checkState(contains(inputs, newInputType), "Input type not registered: " + newInputType); @@ -170,7 +167,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; // TODO: b/307952514 - When switchToInput is called, and the inputColorInfo doesn't match // the prior inputColorInfo, recreate and reinitialize the input.samplingGlShaderProgram. input.setSamplingGlShaderProgram( - createSamplingShaderProgram(inputColorInfo, newInputType)); + createSamplingShaderProgram(inputFrameInfo.colorInfo, newInputType)); } input.setChainingListener( new GatedChainingListenerWrapper( diff --git a/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java index 86c3c5d80b..e416f299e5 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java @@ -147,9 +147,6 @@ public abstract class MultipleInputVideoGraph implements VideoGraph { videoFrameProcessorFactory.create( context, debugViewProvider, - // Pre-processing VideoFrameProcessors have converted the inputColor to outputColor - // already. - /* inputColorInfo= */ outputColorInfo, outputColorInfo, /* renderFramesAutomatically= */ true, /* listenerExecutor= */ MoreExecutors.directExecutor(), @@ -233,7 +230,6 @@ public abstract class MultipleInputVideoGraph implements VideoGraph { .create( context, DebugViewProvider.NONE, - inputColorInfo, outputColorInfo, // Pre-processors render frames as soon as available, to VideoCompositor. /* renderFramesAutomatically= */ true, @@ -361,7 +357,11 @@ public abstract class MultipleInputVideoGraph implements VideoGraph { .registerInputStream( INPUT_TYPE_TEXTURE_ID, compositionEffects, - new FrameInfo.Builder(outputTexture.width, outputTexture.height).build()); + // Pre-processing VideoFrameProcessors have converted the inputColor to outputColor + // already, so use outputColorInfo for the input color to the + // compositionVideoFrameProcessor. + new FrameInfo.Builder(outputColorInfo, outputTexture.width, outputTexture.height) + .build()); compositionVideoFrameProcessorInputStreamRegistered = true; // Return as the VideoFrameProcessor rejects input textures until the input is registered. return; diff --git a/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java index f97dddeb0c..ae76305437 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java @@ -63,6 +63,7 @@ public abstract class SingleInputVideoGraph implements VideoGraph { * *

{@code videoCompositorSettings} must be {@link VideoCompositorSettings#DEFAULT}. */ + // TODO: b/307952514 - Remove inputColorInfo reference in VideoGraph constructor. public SingleInputVideoGraph( Context context, VideoFrameProcessor.Factory videoFrameProcessorFactory, @@ -109,7 +110,6 @@ public abstract class SingleInputVideoGraph implements VideoGraph { videoFrameProcessorFactory.create( context, debugViewProvider, - inputColorInfo, outputColorInfo, renderFramesAutomatically, /* listenerExecutor= */ MoreExecutors.directExecutor(), diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java index 8428ea169f..20116da24d 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java @@ -259,10 +259,7 @@ public final class CompositingVideoSinkProvider // Lazily initialize the handler here so it's initialized on the playback looper. handler = clock.createHandler(checkStateNotNull(Looper.myLooper()), /* callback= */ null); - ColorInfo inputColorInfo = - sourceFormat.colorInfo != null && ColorInfo.isTransferHdr(sourceFormat.colorInfo) - ? sourceFormat.colorInfo - : ColorInfo.SDR_BT709_LIMITED; + ColorInfo inputColorInfo = getAdjustedInputColorInfo(sourceFormat.colorInfo); ColorInfo outputColorInfo = inputColorInfo; if (inputColorInfo.colorTransfer == C.COLOR_TRANSFER_HLG) { // SurfaceView only supports BT2020 PQ input. Therefore, convert HLG to PQ. @@ -552,6 +549,12 @@ public final class CompositingVideoSinkProvider videoFrameRenderControl.onStreamOffsetChange(bufferPresentationTimeUs, streamOffsetUs); } + private static ColorInfo getAdjustedInputColorInfo(@Nullable ColorInfo inputColorInfo) { + return inputColorInfo != null && ColorInfo.isTransferHdr(inputColorInfo) + ? inputColorInfo + : ColorInfo.SDR_BT709_LIMITED; + } + /** Receives input from an ExoPlayer renderer and forwards it to the video graph. */ private static final class VideoSinkImpl implements VideoSink { private final Context context; @@ -562,6 +565,7 @@ public final class CompositingVideoSinkProvider @Nullable private Effect rotationEffect; @Nullable private Format inputFormat; + private @MonotonicNonNull ColorInfo firstInputColorInfo; @InputType int inputType; private long inputStreamOffsetUs; private boolean pendingInputStreamOffsetChange; @@ -779,10 +783,15 @@ public final class CompositingVideoSinkProvider } effects.addAll(videoEffects); Format inputFormat = checkNotNull(this.inputFormat); + if (firstInputColorInfo == null) { + // TODO: b/307952514 - Get inputColorInfo from inputFormat for each stream, after this value + // can change per-stream. + firstInputColorInfo = getAdjustedInputColorInfo(inputFormat.colorInfo); + } videoFrameProcessor.registerInputStream( inputType, effects, - new FrameInfo.Builder(inputFormat.width, inputFormat.height) + new FrameInfo.Builder(firstInputColorInfo, inputFormat.width, inputFormat.height) .setPixelWidthHeightRatio(inputFormat.pixelWidthHeightRatio) .build()); } @@ -908,7 +917,6 @@ public final class CompositingVideoSinkProvider public VideoFrameProcessor create( Context context, DebugViewProvider debugViewProvider, - ColorInfo inputColorInfo, ColorInfo outputColorInfo, boolean renderFramesAutomatically, Executor listenerExecutor, @@ -919,7 +927,6 @@ public final class CompositingVideoSinkProvider .create( context, debugViewProvider, - inputColorInfo, outputColorInfo, renderFramesAutomatically, listenerExecutor, diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java index 1f5a03f466..7f2357a7ae 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java @@ -262,6 +262,7 @@ public final class VideoFrameProcessorTestRunner { private final AtomicReference videoFrameProcessingException; private final VideoFrameProcessor videoFrameProcessor; private final ImmutableList effects; + private final ColorInfo inputColorInfo; private final @MonotonicNonNull BitmapReader bitmapReader; private VideoFrameProcessorTestRunner( @@ -290,7 +291,6 @@ public final class VideoFrameProcessorTestRunner { videoFrameProcessorFactory.create( getApplicationContext(), DebugViewProvider.NONE, - inputColorInfo, outputColorInfo, /* renderFramesAutomatically= */ true, /* listenerExecutor= */ MoreExecutors.directExecutor(), @@ -335,6 +335,7 @@ public final class VideoFrameProcessorTestRunner { } }); this.effects = effects; + this.inputColorInfo = inputColorInfo; } public void processFirstFrameAndEnd() throws Exception { @@ -348,6 +349,7 @@ public final class VideoFrameProcessorTestRunner { INPUT_TYPE_SURFACE, effects, new FrameInfo.Builder( + inputColorInfo, mediaFormat.getInteger(MediaFormat.KEY_WIDTH), mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)) .setPixelWidthHeightRatio(pixelWidthHeightRatio) @@ -377,7 +379,7 @@ public final class VideoFrameProcessorTestRunner { videoFrameProcessor.registerInputStream( INPUT_TYPE_BITMAP, effects, - new FrameInfo.Builder(inputBitmap.getWidth(), inputBitmap.getHeight()) + new FrameInfo.Builder(inputColorInfo, inputBitmap.getWidth(), inputBitmap.getHeight()) .setPixelWidthHeightRatio(pixelWidthHeightRatio) .setOffsetToAddUs(offsetToAddUs) .build()); @@ -393,7 +395,7 @@ public final class VideoFrameProcessorTestRunner { videoFrameProcessor.registerInputStream( INPUT_TYPE_BITMAP, effects, - new FrameInfo.Builder(width, height) + new FrameInfo.Builder(inputColorInfo, width, height) .setPixelWidthHeightRatio(pixelWidthHeightRatio) .build()); videoFrameProcessorReadyCondition.block(); @@ -406,7 +408,7 @@ public final class VideoFrameProcessorTestRunner { videoFrameProcessor.registerInputStream( INPUT_TYPE_TEXTURE_ID, effects, - new FrameInfo.Builder(inputTexture.width, inputTexture.height) + new FrameInfo.Builder(inputColorInfo, inputTexture.width, inputTexture.height) .setPixelWidthHeightRatio(pixelWidthHeightRatio) .build()); videoFrameProcessor.setOnInputFrameProcessedListener( 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 a489f1f14e..30aaa27620 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoFrameProcessingWrapper.java @@ -54,6 +54,7 @@ import java.util.concurrent.atomic.AtomicLong; long initialTimestampOffsetUs) { this.videoFrameProcessor = videoFrameProcessor; this.mediaItemOffsetUs = new AtomicLong(); + // TODO: b/307952514 - Remove inputColorInfo reference. this.inputColorInfo = inputColorInfo; this.initialTimestampOffsetUs = initialTimestampOffsetUs; this.presentation = presentation; @@ -70,7 +71,7 @@ import java.util.concurrent.atomic.AtomicLong; videoFrameProcessor.registerInputStream( getInputType(checkNotNull(trackFormat.sampleMimeType)), createEffectListWithPresentation(editedMediaItem.effects.videoEffects, presentation), - new FrameInfo.Builder(decodedSize.getWidth(), decodedSize.getHeight()) + new FrameInfo.Builder(inputColorInfo, decodedSize.getWidth(), decodedSize.getHeight()) .setPixelWidthHeightRatio(trackFormat.pixelWidthHeightRatio) .setOffsetToAddUs(initialTimestampOffsetUs + mediaItemOffsetUs.get()) .build());