From 0eaf3d30c81c28cede8ae7b70d67a6f1c1fb65a4 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 26 May 2022 12:52:45 +0000 Subject: [PATCH] Rename GlFrameProcessor to SingleFrameGlTextureProcessor. Also update names of implementations to match design doc. In follow-ups, SingleFrameGlTextureProcessor will become an abstract implementation of a new GlTextureProcessor interface. Texture processor makes sense as it processes OpenGL textures. The term frame processor will be used for something else in follow-ups. PiperOrigin-RevId: 451142085 --- ...essor.java => BitmapOverlayProcessor.java} | 13 ++- ...or.java => PeriodicVignetteProcessor.java} | 10 +- .../demo/transformer/TransformerActivity.java | 11 +- ...Processor.java => MediaPipeProcessor.java} | 11 +- .../media3/transformer/BitmapTestUtil.java | 8 +- .../transformer/FrameProcessorChainTest.java | 40 +++---- ...trixTransformationProcessorPixelTest.java} | 46 ++++---- .../transformer/PresentationPixelTest.java | 96 ++++++++-------- .../EncoderCompatibilityTransformation.java | 4 +- ...sor.java => ExternalTextureProcessor.java} | 4 +- .../transformer/FrameProcessorChain.java | 103 +++++++++--------- .../androidx/media3/transformer/GlEffect.java | 10 +- .../transformer/GlMatrixTransformation.java | 4 +- ...ava => MatrixTransformationProcessor.java} | 8 +- ...ava => SingleFrameGlTextureProcessor.java} | 8 +- .../media3/transformer/PresentationTest.java | 10 +- .../ScaleToFitTransformationTest.java | 4 +- 17 files changed, 196 insertions(+), 194 deletions(-) rename demos/transformer/src/main/java/androidx/media3/demo/transformer/{BitmapOverlayFrameProcessor.java => BitmapOverlayProcessor.java} (92%) rename demos/transformer/src/main/java/androidx/media3/demo/transformer/{PeriodicVignetteFrameProcessor.java => PeriodicVignetteProcessor.java} (92%) rename demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/{MediaPipeFrameProcessor.java => MediaPipeProcessor.java} (94%) rename libraries/transformer/src/androidTest/java/androidx/media3/transformer/{MatrixTransformationFrameProcessorPixelTest.java => MatrixTransformationProcessorPixelTest.java} (80%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{ExternalCopyFrameProcessor.java => ExternalTextureProcessor.java} (96%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{MatrixTransformationFrameProcessor.java => MatrixTransformationProcessor.java} (96%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{GlFrameProcessor.java => SingleFrameGlTextureProcessor.java} (87%) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayFrameProcessor.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayProcessor.java similarity index 92% rename from demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayFrameProcessor.java rename to demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayProcessor.java index 5de56cd0e0..85a8d59b6d 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayFrameProcessor.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/BitmapOverlayProcessor.java @@ -32,19 +32,20 @@ import androidx.media3.common.C; import androidx.media3.common.util.GlProgram; import androidx.media3.common.util.GlUtil; import androidx.media3.transformer.FrameProcessingException; -import androidx.media3.transformer.GlFrameProcessor; +import androidx.media3.transformer.SingleFrameGlTextureProcessor; import java.io.IOException; import java.util.Locale; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * A {@link GlFrameProcessor} that overlays a bitmap with a logo and timer on each frame. + * A {@link SingleFrameGlTextureProcessor} that overlays a bitmap with a logo and timer on each + * frame. * *

The bitmap is drawn using an Android {@link Canvas}. */ -// TODO(b/227625365): Delete this class and use a frame processor from the Transformer library, once -// overlaying a bitmap and text is supported in Transformer. -/* package */ final class BitmapOverlayFrameProcessor implements GlFrameProcessor { +// TODO(b/227625365): Delete this class and use a texture processor from the Transformer library, +// once overlaying a bitmap and text is supported in Transformer. +/* package */ final class BitmapOverlayProcessor implements SingleFrameGlTextureProcessor { static { GlUtil.glAssertionsEnabled = true; } @@ -65,7 +66,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private @MonotonicNonNull Bitmap logoBitmap; private @MonotonicNonNull GlProgram glProgram; - public BitmapOverlayFrameProcessor() { + public BitmapOverlayProcessor() { paint = new Paint(); paint.setTextSize(64); paint.setAntiAlias(true); diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteFrameProcessor.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteProcessor.java similarity index 92% rename from demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteFrameProcessor.java rename to demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteProcessor.java index 1b91e10687..74c1a31294 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteFrameProcessor.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/PeriodicVignetteProcessor.java @@ -24,15 +24,15 @@ import android.util.Size; import androidx.media3.common.util.GlProgram; import androidx.media3.common.util.GlUtil; import androidx.media3.transformer.FrameProcessingException; -import androidx.media3.transformer.GlFrameProcessor; +import androidx.media3.transformer.SingleFrameGlTextureProcessor; import java.io.IOException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * A {@link GlFrameProcessor} that periodically dims the frames such that pixels are darker the - * further they are away from the frame center. + * A {@link SingleFrameGlTextureProcessor} that periodically dims the frames such that pixels are + * darker the further they are away from the frame center. */ -/* package */ final class PeriodicVignetteFrameProcessor implements GlFrameProcessor { +/* package */ final class PeriodicVignetteProcessor implements SingleFrameGlTextureProcessor { static { GlUtil.glAssertionsEnabled = true; } @@ -67,7 +67,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param maxInnerRadius The upper bound of the radius that is unaffected by the effect. * @param outerRadius The radius after which all pixels are black. */ - public PeriodicVignetteFrameProcessor( + public PeriodicVignetteProcessor( float centerX, float centerY, float minInnerRadius, float maxInnerRadius, float outerRadius) { checkArgument(minInnerRadius <= maxInnerRadius); checkArgument(maxInnerRadius <= outerRadius); diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 34205e8da2..72d4e9eb6a 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -42,8 +42,8 @@ import androidx.media3.exoplayer.util.DebugTextViewHelper; import androidx.media3.transformer.DefaultEncoderFactory; import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.GlEffect; -import androidx.media3.transformer.GlFrameProcessor; import androidx.media3.transformer.ProgressHolder; +import androidx.media3.transformer.SingleFrameGlTextureProcessor; import androidx.media3.transformer.TransformationException; import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationResult; @@ -253,14 +253,13 @@ public final class TransformerActivity extends AppCompatActivity { } if (selectedEffects[1]) { try { - Class clazz = - Class.forName("androidx.media3.demo.transformer.MediaPipeFrameProcessor"); + Class clazz = Class.forName("androidx.media3.demo.transformer.MediaPipeProcessor"); Constructor constructor = clazz.getConstructor(String.class, String.class, String.class); effects.add( () -> { try { - return (GlFrameProcessor) + return (SingleFrameGlTextureProcessor) constructor.newInstance( /* graphName= */ "edge_detector_mediapipe_graph.binarypb", /* inputStreamName= */ "input_video", @@ -277,7 +276,7 @@ public final class TransformerActivity extends AppCompatActivity { if (selectedEffects[2]) { effects.add( () -> - new PeriodicVignetteFrameProcessor( + new PeriodicVignetteProcessor( bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X), bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_Y), /* minInnerRadius= */ bundle.getFloat( @@ -290,7 +289,7 @@ public final class TransformerActivity extends AppCompatActivity { effects.add(MatrixTransformationFactory.createSpin3dEffect()); } if (selectedEffects[4]) { - effects.add(BitmapOverlayFrameProcessor::new); + effects.add(BitmapOverlayProcessor::new); } if (selectedEffects[5]) { effects.add(MatrixTransformationFactory.createZoomInTransition()); diff --git a/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeFrameProcessor.java b/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java similarity index 94% rename from demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeFrameProcessor.java rename to demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java index 95b421eedd..8860a2ccc9 100644 --- a/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeFrameProcessor.java +++ b/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java @@ -27,7 +27,7 @@ import androidx.media3.common.util.GlProgram; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.LibraryLoader; import androidx.media3.transformer.FrameProcessingException; -import androidx.media3.transformer.GlFrameProcessor; +import androidx.media3.transformer.SingleFrameGlTextureProcessor; import com.google.mediapipe.components.FrameProcessor; import com.google.mediapipe.framework.AndroidAssetUtil; import com.google.mediapipe.framework.AppTextureFrame; @@ -40,7 +40,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * Runs a MediaPipe graph on input frames. The implementation is currently limited to graphs that * can immediately produce one output frame per input frame. */ -/* package */ final class MediaPipeFrameProcessor implements GlFrameProcessor { +/* package */ final class MediaPipeProcessor implements SingleFrameGlTextureProcessor { private static final LibraryLoader LOADER = new LibraryLoader("mediapipe_jni") { @@ -77,14 +77,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private @MonotonicNonNull RuntimeException frameProcessorPendingError; /** - * Creates a new frame processor that wraps a MediaPipe graph. + * Creates a new texture processor that wraps a MediaPipe graph. * * @param graphName Name of a MediaPipe graph asset to load. * @param inputStreamName Name of the input video stream in the graph. * @param outputStreamName Name of the input video stream in the graph. */ - public MediaPipeFrameProcessor( - String graphName, String inputStreamName, String outputStreamName) { + public MediaPipeProcessor(String graphName, String inputStreamName, String outputStreamName) { checkState(LOADER.isAvailable()); this.graphName = graphName; this.inputStreamName = inputStreamName; @@ -141,7 +140,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // Propagate the interrupted flag so the next blocking operation will throw. // TODO(b/230469581): The next processor that runs will not have valid input due to returning // early here. This could be fixed by checking for interruption in the outer loop that runs - // through the frame processors. + // through the texture processors. Thread.currentThread().interrupt(); return; } diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java index 1f7bb8e8f4..fda61200d1 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java @@ -40,7 +40,7 @@ import java.nio.ByteBuffer; /** * Utilities for instrumentation tests for the {@link FrameProcessorChain} and {@link - * GlFrameProcessor GlFrameProcessors}. + * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors}. */ public class BitmapTestUtil { @@ -50,15 +50,15 @@ public class BitmapTestUtil { * Maximum allowed average pixel difference between the expected and actual edited images in pixel * difference-based tests. The value is chosen so that differences in decoder behavior across * emulator versions don't affect whether the test passes for most emulators, but substantial - * distortions introduced by changes in the behavior of the {@link GlFrameProcessor - * GlFrameProcessors} will cause the test to fail. + * distortions introduced by changes in the behavior of the {@link SingleFrameGlTextureProcessor + * SingleFrameGlTextureProcessors} will cause the test to fail. * *

To run pixel difference-based tests on physical devices, please use a value of 5f, rather * than 0.1f. This higher value will ignore some very small errors, but will allow for some * differences caused by graphics implementations to be ignored. When the difference is close to * the threshold, manually inspect expected/actual bitmaps to confirm failure, as it's possible * this is caused by a difference in the codec or graphics implementation as opposed to a {@link - * GlFrameProcessor} issue. + * SingleFrameGlTextureProcessor} issue. */ public static final float MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE = 0.1f; diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java index 99c29fbfb5..511593ea39 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java @@ -41,10 +41,10 @@ public final class FrameProcessorChainTest { public void getOutputSize_noOperation_returnsInputSize() throws Exception { Size inputSize = new Size(200, 100); FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeFrameProcessors( + createFrameProcessorChainWithFakeTextureProcessors( /* pixelWidthHeightRatio= */ 1f, inputSize, - /* frameProcessorOutputSizes= */ ImmutableList.of()); + /* textureProcessorOutputSizes= */ ImmutableList.of()); Size outputSize = frameProcessorChain.getOutputSize(); @@ -56,10 +56,10 @@ public final class FrameProcessorChainTest { public void getOutputSize_withWidePixels_returnsWiderOutputSize() throws Exception { Size inputSize = new Size(200, 100); FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeFrameProcessors( + createFrameProcessorChainWithFakeTextureProcessors( /* pixelWidthHeightRatio= */ 2f, inputSize, - /* frameProcessorOutputSizes= */ ImmutableList.of()); + /* textureProcessorOutputSizes= */ ImmutableList.of()); Size outputSize = frameProcessorChain.getOutputSize(); @@ -71,10 +71,10 @@ public final class FrameProcessorChainTest { public void getOutputSize_withTallPixels_returnsTallerOutputSize() throws Exception { Size inputSize = new Size(200, 100); FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeFrameProcessors( + createFrameProcessorChainWithFakeTextureProcessors( /* pixelWidthHeightRatio= */ .5f, inputSize, - /* frameProcessorOutputSizes= */ ImmutableList.of()); + /* textureProcessorOutputSizes= */ ImmutableList.of()); Size outputSize = frameProcessorChain.getOutputSize(); @@ -83,32 +83,32 @@ public final class FrameProcessorChainTest { } @Test - public void getOutputSize_withOneFrameProcessor_returnsItsOutputSize() throws Exception { + public void getOutputSize_withOneTextureProcessor_returnsItsOutputSize() throws Exception { Size inputSize = new Size(200, 100); - Size frameProcessorOutputSize = new Size(300, 250); + Size textureProcessorOutputSize = new Size(300, 250); FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeFrameProcessors( + createFrameProcessorChainWithFakeTextureProcessors( /* pixelWidthHeightRatio= */ 1f, inputSize, - /* frameProcessorOutputSizes= */ ImmutableList.of(frameProcessorOutputSize)); + /* textureProcessorOutputSizes= */ ImmutableList.of(textureProcessorOutputSize)); Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); - assertThat(frameProcessorChainOutputSize).isEqualTo(frameProcessorOutputSize); + assertThat(frameProcessorChainOutputSize).isEqualTo(textureProcessorOutputSize); assertThat(frameProcessingException.get()).isNull(); } @Test - public void getOutputSize_withThreeFrameProcessors_returnsLastOutputSize() throws Exception { + public void getOutputSize_withThreeTextureProcessors_returnsLastOutputSize() throws Exception { Size inputSize = new Size(200, 100); Size outputSize1 = new Size(300, 250); Size outputSize2 = new Size(400, 244); Size outputSize3 = new Size(150, 160); FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeFrameProcessors( + createFrameProcessorChainWithFakeTextureProcessors( /* pixelWidthHeightRatio= */ 1f, inputSize, - /* frameProcessorOutputSizes= */ ImmutableList.of( + /* textureProcessorOutputSizes= */ ImmutableList.of( outputSize1, outputSize2, outputSize3)); Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); @@ -117,12 +117,12 @@ public final class FrameProcessorChainTest { assertThat(frameProcessingException.get()).isNull(); } - private FrameProcessorChain createFrameProcessorChainWithFakeFrameProcessors( - float pixelWidthHeightRatio, Size inputSize, List frameProcessorOutputSizes) + private FrameProcessorChain createFrameProcessorChainWithFakeTextureProcessors( + float pixelWidthHeightRatio, Size inputSize, List textureProcessorOutputSizes) throws FrameProcessingException { ImmutableList.Builder effects = new ImmutableList.Builder<>(); - for (Size element : frameProcessorOutputSizes) { - effects.add(() -> new FakeFrameProcessor(element)); + for (Size element : textureProcessorOutputSizes) { + effects.add(() -> new FakeTextureProcessor(element)); } return FrameProcessorChain.create( getApplicationContext(), @@ -134,11 +134,11 @@ public final class FrameProcessorChainTest { /* enableExperimentalHdrEditing= */ false); } - private static class FakeFrameProcessor implements GlFrameProcessor { + private static class FakeTextureProcessor implements SingleFrameGlTextureProcessor { private final Size outputSize; - private FakeFrameProcessor(Size outputSize) { + private FakeTextureProcessor(Size outputSize) { this.outputSize = outputSize; } diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java similarity index 80% rename from libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationFrameProcessorPixelTest.java rename to libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java index 879dfb03ec..9a5648274d 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java @@ -34,7 +34,7 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Pixel test for frame processing via {@link MatrixTransformationFrameProcessor}. + * Pixel test for texture processing via {@link MatrixTransformationProcessor}. * *

Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link @@ -42,7 +42,7 @@ import org.junit.runner.RunWith; * as recommended in {@link FrameProcessorChainPixelTest}. */ @RunWith(AndroidJUnit4.class) -public final class MatrixTransformationFrameProcessorPixelTest { +public final class MatrixTransformationProcessorPixelTest { public static final String ORIGINAL_PNG_ASSET_PATH = "media/bitmap/sample_mp4_first_frame/original.png"; public static final String TRANSLATE_RIGHT_PNG_ASSET_PATH = @@ -58,7 +58,7 @@ public final class MatrixTransformationFrameProcessorPixelTest { private final EGLDisplay eglDisplay = GlUtil.createEglDisplay(); private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay); - private @MonotonicNonNull GlFrameProcessor matrixTransformationFrameProcessor; + private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTransformationProcessor; private int inputTexId; private int outputTexId; private int width; @@ -80,8 +80,8 @@ public final class MatrixTransformationFrameProcessorPixelTest { @After public void release() { - if (matrixTransformationFrameProcessor != null) { - matrixTransformationFrameProcessor.release(); + if (matrixTransformationProcessor != null) { + matrixTransformationProcessor.release(); } GlUtil.destroyEglContext(eglDisplay, eglContext); } @@ -90,13 +90,12 @@ public final class MatrixTransformationFrameProcessorPixelTest { public void drawFrame_noEdits_producesExpectedOutput() throws Exception { String testId = "drawFrame_noEdits"; Matrix identityMatrix = new Matrix(); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor((long presentationTimeUs) -> identityMatrix); - matrixTransformationFrameProcessor.initialize( - getApplicationContext(), inputTexId, width, height); + matrixTransformationProcessor = + new MatrixTransformationProcessor((long presentationTimeUs) -> identityMatrix); + matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH); - matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -114,13 +113,12 @@ public final class MatrixTransformationFrameProcessorPixelTest { String testId = "drawFrame_translateRight"; Matrix translateRightMatrix = new Matrix(); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor((long presentationTimeUs) -> translateRightMatrix); - matrixTransformationFrameProcessor.initialize( - getApplicationContext(), inputTexId, width, height); + matrixTransformationProcessor = + new MatrixTransformationProcessor((long presentationTimeUs) -> translateRightMatrix); + matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH); - matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -138,13 +136,12 @@ public final class MatrixTransformationFrameProcessorPixelTest { String testId = "drawFrame_scaleNarrow"; Matrix scaleNarrowMatrix = new Matrix(); scaleNarrowMatrix.postScale(.5f, 1.2f); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor((long presentationTimeUs) -> scaleNarrowMatrix); - matrixTransformationFrameProcessor.initialize( - getApplicationContext(), inputTexId, width, height); + matrixTransformationProcessor = + new MatrixTransformationProcessor((long presentationTimeUs) -> scaleNarrowMatrix); + matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(SCALE_NARROW_PNG_ASSET_PATH); - matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -162,13 +159,12 @@ public final class MatrixTransformationFrameProcessorPixelTest { String testId = "drawFrame_rotate90"; Matrix rotate90Matrix = new Matrix(); rotate90Matrix.postRotate(/* degrees= */ 90); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor((long presentationTimeUs) -> rotate90Matrix); - matrixTransformationFrameProcessor.initialize( - getApplicationContext(), inputTexId, width, height); + matrixTransformationProcessor = + new MatrixTransformationProcessor((long presentationTimeUs) -> rotate90Matrix); + matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_PNG_ASSET_PATH); - matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java index e76e4963b9..6e34118d04 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java @@ -35,7 +35,7 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Pixel test for frame processing via {@link Presentation}. + * Pixel test for texture processing via {@link Presentation}. * *

Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link @@ -69,7 +69,7 @@ public final class PresentationPixelTest { private final EGLDisplay eglDisplay = GlUtil.createEglDisplay(); private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay); - private @MonotonicNonNull GlFrameProcessor presentationFrameProcessor; + private @MonotonicNonNull SingleFrameGlTextureProcessor presentationTextureProcessor; private @MonotonicNonNull EGLSurface placeholderEglSurface; private int inputTexId; private int outputTexId; @@ -88,8 +88,8 @@ public final class PresentationPixelTest { @After public void release() { - if (presentationFrameProcessor != null) { - presentationFrameProcessor.release(); + if (presentationTextureProcessor != null) { + presentationTextureProcessor.release(); } GlUtil.destroyEglContext(eglDisplay, eglContext); } @@ -97,14 +97,14 @@ public final class PresentationPixelTest { @Test public void drawFrame_noEdits_producesExpectedOutput() throws Exception { String testId = "drawFrame_noEdits"; - presentationFrameProcessor = new Presentation.Builder().build().toGlFrameProcessor(); - presentationFrameProcessor.initialize( + presentationTextureProcessor = new Presentation.Builder().build().toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -121,18 +121,18 @@ public final class PresentationPixelTest { @Test public void drawFrame_cropSmaller_producesExpectedOutput() throws Exception { String testId = "drawFrame_cropSmaller"; - GlFrameProcessor presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setCrop(/* left= */ -.9f, /* right= */ .1f, /* bottom= */ -1f, /* top= */ .5f) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_SMALLER_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -149,18 +149,18 @@ public final class PresentationPixelTest { @Test public void drawFrame_cropLarger_producesExpectedOutput() throws Exception { String testId = "drawFrame_cropSmaller"; - GlFrameProcessor presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setCrop(/* left= */ -2f, /* right= */ 2f, /* bottom= */ -1f, /* top= */ 2f) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_LARGER_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -178,19 +178,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_scaleToFit_narrow_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_NARROW_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -208,19 +208,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_scaleToFit_wide_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_wide"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WIDE_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -238,19 +238,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_NARROW_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -268,19 +268,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_scaleToFitWithCrop_wide_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_WIDE_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -298,19 +298,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_stretchToFit_narrow_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(1f, Presentation.LAYOUT_STRETCH_TO_FIT) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_NARROW_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); @@ -328,19 +328,19 @@ public final class PresentationPixelTest { public void drawFrame_changeAspectRatio_stretchToFit_wide_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_wide"; - presentationFrameProcessor = + presentationTextureProcessor = new Presentation.Builder() .setAspectRatio(2f, Presentation.LAYOUT_STRETCH_TO_FIT) .build() - .toGlFrameProcessor(); - presentationFrameProcessor.initialize( + .toGlTextureProcessor(); + presentationTextureProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentationTextureProcessor.getOutputSize(); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_WIDE_PNG_ASSET_PATH); - presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); + presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( outputSize.getWidth(), outputSize.getHeight()); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java index b326c480c1..d12e1b5f82 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java @@ -19,7 +19,6 @@ import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkStateNotNull; -import android.content.Context; import android.graphics.Matrix; import android.util.Size; import androidx.media3.common.C; @@ -77,8 +76,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * *

Return values may be {@code 0} or {@code 90} degrees. * - *

The frame processor must be {@linkplain GlFrameProcessor#initialize(Context, int, int, int) - * initialized}. + *

Should only be called after {@linkplain #configure(int, int) configuration}. */ public int getOutputRotationDegrees() { checkState( diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java similarity index 96% rename from libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java index 83c3abffde..8000d738ee 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java @@ -27,7 +27,7 @@ import java.io.IOException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** Copies frames from an external texture and applies color transformations for HDR if needed. */ -/* package */ class ExternalCopyFrameProcessor implements GlFrameProcessor { +/* package */ class ExternalTextureProcessor implements SingleFrameGlTextureProcessor { static { GlUtil.glAssertionsEnabled = true; @@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private @MonotonicNonNull Size size; private @MonotonicNonNull GlProgram glProgram; - public ExternalCopyFrameProcessor(boolean enableExperimentalHdrEditing) { + public ExternalTextureProcessor(boolean enableExperimentalHdrEditing) { this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index 3e4d895933..b2e13171b8 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -63,6 +63,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * fully processed yet. Output is written to its {@linkplain #setOutputSurface(Surface, int, int, * SurfaceView) output surface}. */ +// TODO(b/227625423): Factor out FrameProcessor interface and rename this class to GlFrameProcessor. /* package */ final class FrameProcessorChain { static { @@ -131,9 +132,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } /** - * Creates the OpenGL textures and framebuffers, initializes the {@link GlFrameProcessor - * GlFrameProcessors} corresponding to the {@link GlEffect GlEffects}, and returns a new {@code - * FrameProcessorChain}. + * Creates the OpenGL textures and framebuffers, initializes the {@link + * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} corresponding to the {@link + * GlEffect GlEffects}, and returns a new {@code FrameProcessorChain}. * *

This method must be executed using the {@code singleThreadExecutorService}. */ @@ -166,23 +167,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); } - ExternalCopyFrameProcessor externalCopyFrameProcessor = - new ExternalCopyFrameProcessor(enableExperimentalHdrEditing); - ImmutableList frameProcessors = - getFrameProcessors(externalCopyFrameProcessor, pixelWidthHeightRatio, effects); + ExternalTextureProcessor externalTextureProcessor = + new ExternalTextureProcessor(enableExperimentalHdrEditing); + ImmutableList textureProcessors = + getTextureProcessors(externalTextureProcessor, pixelWidthHeightRatio, effects); - // Initialize frame processors. + // Initialize texture processors. int inputExternalTexId = GlUtil.createExternalTexture(); - externalCopyFrameProcessor.initialize(context, inputExternalTexId, inputWidth, inputHeight); + externalTextureProcessor.initialize(context, inputExternalTexId, inputWidth, inputHeight); - int[] framebuffers = new int[frameProcessors.size() - 1]; - Size inputSize = externalCopyFrameProcessor.getOutputSize(); - for (int i = 1; i < frameProcessors.size(); i++) { + int[] framebuffers = new int[textureProcessors.size() - 1]; + Size inputSize = externalTextureProcessor.getOutputSize(); + for (int i = 1; i < textureProcessors.size(); i++) { int inputTexId = GlUtil.createTexture(inputSize.getWidth(), inputSize.getHeight()); framebuffers[i - 1] = GlUtil.createFboForTexture(inputTexId); - GlFrameProcessor frameProcessor = frameProcessors.get(i); - frameProcessor.initialize(context, inputTexId, inputSize.getWidth(), inputSize.getHeight()); - inputSize = frameProcessor.getOutputSize(); + SingleFrameGlTextureProcessor textureProcessor = textureProcessors.get(i); + textureProcessor.initialize(context, inputTexId, inputSize.getWidth(), inputSize.getHeight()); + inputSize = textureProcessor.getOutputSize(); } return new FrameProcessorChain( eglDisplay, @@ -190,17 +191,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; singleThreadExecutorService, inputExternalTexId, framebuffers, - frameProcessors, + textureProcessors, listener, enableExperimentalHdrEditing); } - private static ImmutableList getFrameProcessors( - ExternalCopyFrameProcessor externalCopyFrameProcessor, + private static ImmutableList getTextureProcessors( + ExternalTextureProcessor externalTextureProcessor, float pixelWidthHeightRatio, List effects) { - ImmutableList.Builder frameProcessors = - new ImmutableList.Builder().add(externalCopyFrameProcessor); + ImmutableList.Builder textureProcessors = + new ImmutableList.Builder().add(externalTextureProcessor); ImmutableList.Builder matrixTransformationListBuilder = new ImmutableList.Builder<>(); @@ -217,8 +218,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; .build()); } - // Combine consecutive GlMatrixTransformations into a single GlFrameProcessor and convert - // all other GlEffects to GlFrameProcessors. + // Combine consecutive GlMatrixTransformations into a single SingleFrameGlTextureProcessor and + // convert all other GlEffects to SingleFrameGlTextureProcessors. for (int i = 0; i < effects.size(); i++) { GlEffect effect = effects.get(i); if (effect instanceof GlMatrixTransformation) { @@ -228,18 +229,18 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ImmutableList matrixTransformations = matrixTransformationListBuilder.build(); if (!matrixTransformations.isEmpty()) { - frameProcessors.add(new MatrixTransformationFrameProcessor(matrixTransformations)); + textureProcessors.add(new MatrixTransformationProcessor(matrixTransformations)); matrixTransformationListBuilder = new ImmutableList.Builder<>(); } - frameProcessors.add(effect.toGlFrameProcessor()); + textureProcessors.add(effect.toGlTextureProcessor()); } ImmutableList matrixTransformations = matrixTransformationListBuilder.build(); if (!matrixTransformations.isEmpty()) { - frameProcessors.add(new MatrixTransformationFrameProcessor(matrixTransformations)); + textureProcessors.add(new MatrixTransformationProcessor(matrixTransformations)); } - return frameProcessors.build(); + return textureProcessors.build(); } private static final String TAG = "FrameProcessorChain"; @@ -264,14 +265,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final float[] textureTransformMatrix; /** - * Contains an {@link ExternalCopyFrameProcessor} at the 0th index and optionally other {@link - * GlFrameProcessor GlFrameProcessors} at indices >= 1. + * Contains an {@link ExternalTextureProcessor} at the 0th index and optionally other {@link + * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} at indices >= 1. */ - private final ImmutableList frameProcessors; + private final ImmutableList textureProcessors; /** * Identifiers of a framebuffer object associated with the intermediate textures that receive - * output from the previous {@link GlFrameProcessor}, and provide input for the following {@link - * GlFrameProcessor}. + * output from the previous {@link SingleFrameGlTextureProcessor}, and provide input for the + * following {@link SingleFrameGlTextureProcessor}. */ private final int[] framebuffers; @@ -289,33 +290,35 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * Wraps the output {@link Surface} that is populated with the output of the final {@link - * GlFrameProcessor} for each frame. + * SingleFrameGlTextureProcessor} for each frame. */ private @MonotonicNonNull EGLSurface outputEglSurface; /** * Wraps a debug {@link SurfaceView} that is populated with the output of the final {@link - * GlFrameProcessor} for each frame. + * SingleFrameGlTextureProcessor} for each frame. */ private @MonotonicNonNull SurfaceViewWrapper debugSurfaceViewWrapper; private boolean inputStreamEnded; + // TODO(b/227625423): accept GlTextureProcessors instead of SingleFrameGlTextureProcessors once + // this interface exists. private FrameProcessorChain( EGLDisplay eglDisplay, EGLContext eglContext, ExecutorService singleThreadExecutorService, int inputExternalTexId, int[] framebuffers, - ImmutableList frameProcessors, + ImmutableList textureProcessors, Listener listener, boolean enableExperimentalHdrEditing) { - checkState(!frameProcessors.isEmpty()); + checkState(!textureProcessors.isEmpty()); this.eglDisplay = eglDisplay; this.eglContext = eglContext; this.singleThreadExecutorService = singleThreadExecutorService; this.framebuffers = framebuffers; - this.frameProcessors = frameProcessors; + this.textureProcessors = textureProcessors; this.listener = listener; this.stopProcessing = new AtomicBoolean(); this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; @@ -336,7 +339,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * SurfaceView) output surface}. */ public Size getOutputSize() { - return getLast(frameProcessors).getOutputSize(); + return getLast(textureProcessors).getOutputSize(); } /** @@ -356,7 +359,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; int outputHeight, @Nullable SurfaceView debugSurfaceView) { // TODO(b/218488308): Don't override output size for encoder fallback. Instead allow the final - // GlFrameProcessor to be re-configured or append another GlFrameProcessor. + // SingleFrameGlTextureProcessor to be re-configured or append another + // SingleFrameGlTextureProcessor. this.outputSurface = outputSurface; this.outputWidth = outputWidth; this.outputHeight = outputHeight; @@ -432,7 +436,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; checkNotNull(futures.poll()).cancel(/* mayInterruptIfRunning= */ false); } futures.add( - singleThreadExecutorService.submit(this::releaseFrameProcessorsAndDestroyGlContext)); + singleThreadExecutorService.submit(this::releaseTextureProcessorsAndDestroyGlContext)); singleThreadExecutorService.shutdown(); try { if (!singleThreadExecutorService.awaitTermination(RELEASE_WAIT_TIME_MS, MILLISECONDS)) { @@ -475,15 +479,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; long presentationTimeNs = inputSurfaceTexture.getTimestamp(); presentationTimeUs = presentationTimeNs / 1000; inputSurfaceTexture.getTransformMatrix(textureTransformMatrix); - ((ExternalCopyFrameProcessor) frameProcessors.get(0)) + ((ExternalTextureProcessor) textureProcessors.get(0)) .setTextureTransformMatrix(textureTransformMatrix); - for (int i = 0; i < frameProcessors.size() - 1; i++) { + for (int i = 0; i < textureProcessors.size() - 1; i++) { if (stopProcessing.get()) { return; } - Size intermediateSize = frameProcessors.get(i).getOutputSize(); + Size intermediateSize = textureProcessors.get(i).getOutputSize(); GlUtil.focusFramebuffer( eglDisplay, eglContext, @@ -492,11 +496,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; intermediateSize.getWidth(), intermediateSize.getHeight()); clearOutputFrame(); - frameProcessors.get(i).drawFrame(presentationTimeUs); + textureProcessors.get(i).drawFrame(presentationTimeUs); } GlUtil.focusEglSurface(eglDisplay, eglContext, outputEglSurface, outputWidth, outputHeight); clearOutputFrame(); - getLast(frameProcessors).drawFrame(presentationTimeUs); + getLast(textureProcessors).drawFrame(presentationTimeUs); EGLExt.eglPresentationTimeANDROID(eglDisplay, outputEglSurface, presentationTimeNs); EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); @@ -507,7 +511,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; () -> { clearOutputFrame(); try { - getLast(frameProcessors).drawFrame(framePresentationTimeUs); + getLast(textureProcessors).drawFrame(framePresentationTimeUs); } catch (FrameProcessingException e) { Log.d(TAG, "Error rendering to debug preview", e); } @@ -532,15 +536,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } /** - * Releases the {@link GlFrameProcessor GlFrameProcessors} and destroys the OpenGL context. + * Releases the {@link SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} and destroys + * the OpenGL context. * *

This method must be called on the {@linkplain #THREAD_NAME background thread}. */ @WorkerThread - private void releaseFrameProcessorsAndDestroyGlContext() { + private void releaseTextureProcessorsAndDestroyGlContext() { try { - for (int i = 0; i < frameProcessors.size(); i++) { - frameProcessors.get(i).release(); + for (int i = 0; i < textureProcessors.size(); i++) { + textureProcessors.get(i).release(); } GlUtil.destroyEglContext(eglDisplay, eglContext); } catch (RuntimeException e) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java index 422bff3017..854446d6a1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java @@ -18,14 +18,16 @@ package androidx.media3.transformer; import androidx.media3.common.util.UnstableApi; /** - * Interface for a video frame effect with a {@link GlFrameProcessor} implementation. + * Interface for a video frame effect with a {@link SingleFrameGlTextureProcessor} implementation. * *

Implementations contain information specifying the effect and can be {@linkplain - * #toGlFrameProcessor() converted} to a {@link GlFrameProcessor} which applies the effect. + * #toGlTextureProcessor() converted} to a {@link SingleFrameGlTextureProcessor} which applies the + * effect. */ @UnstableApi public interface GlEffect { - /** Returns a {@link GlFrameProcessor} that applies the the effect. */ - GlFrameProcessor toGlFrameProcessor(); + /** Returns a {@link SingleFrameGlTextureProcessor} that applies the effect. */ + // TODO(b/227625423): use GlTextureProcessor here once this interface exists. + SingleFrameGlTextureProcessor toGlTextureProcessor(); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlMatrixTransformation.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlMatrixTransformation.java index 4a304543e7..c6d8c37104 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlMatrixTransformation.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlMatrixTransformation.java @@ -49,7 +49,7 @@ public interface GlMatrixTransformation extends GlEffect { float[] getGlMatrixArray(long presentationTimeUs); @Override - default GlFrameProcessor toGlFrameProcessor() { - return new MatrixTransformationFrameProcessor(this); + default SingleFrameGlTextureProcessor toGlTextureProcessor() { + return new MatrixTransformationProcessor(this); } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java similarity index 96% rename from libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java index 850f30d06c..e464b82245 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java @@ -43,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; */ @UnstableApi @SuppressWarnings("FunctionalInterfaceClash") // b/228192298 -/* package */ final class MatrixTransformationFrameProcessor implements GlFrameProcessor { +/* package */ final class MatrixTransformationProcessor implements SingleFrameGlTextureProcessor { static { GlUtil.glAssertionsEnabled = true; @@ -93,7 +93,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param matrixTransformation A {@link MatrixTransformation} that specifies the transformation * matrix to use for each frame. */ - public MatrixTransformationFrameProcessor(MatrixTransformation matrixTransformation) { + public MatrixTransformationProcessor(MatrixTransformation matrixTransformation) { this(ImmutableList.of(matrixTransformation)); } @@ -103,7 +103,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param matrixTransformation A {@link GlMatrixTransformation} that specifies the transformation * matrix to use for each frame. */ - public MatrixTransformationFrameProcessor(GlMatrixTransformation matrixTransformation) { + public MatrixTransformationProcessor(GlMatrixTransformation matrixTransformation) { this(ImmutableList.of(matrixTransformation)); } @@ -113,7 +113,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param matrixTransformations The {@link GlMatrixTransformation GlMatrixTransformations} to * apply to each frame in order. */ - public MatrixTransformationFrameProcessor( + public MatrixTransformationProcessor( ImmutableList matrixTransformations) { this.matrixTransformations = matrixTransformations; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java similarity index 87% rename from libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java index edecda427c..3e0546f7d2 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java @@ -34,7 +34,9 @@ import java.io.IOException; * */ @UnstableApi -public interface GlFrameProcessor { +// TODO(b/227625423): Add GlTextureProcessor interface for async texture processors and make this an +// abstract class with a default implementation of GlTextureProcessor methods. +public interface SingleFrameGlTextureProcessor { /** * Performs all initialization that requires OpenGL, such as, loading and compiling a GLSL shader @@ -54,7 +56,7 @@ public interface GlFrameProcessor { /** * Returns the output {@link Size} of frames processed through {@link #drawFrame(long)}. * - *

This method may only be called after the frame processor has been {@link + *

This method may only be called after the texture processor has been {@link * #initialize(Context, int, int, int) initialized}. */ Size getOutputSize(); @@ -62,7 +64,7 @@ public interface GlFrameProcessor { /** * Draws one frame. * - *

This method may only be called after the frame processor has been {@link + *

This method may only be called after the texture processor has been {@link * #initialize(Context, int, int, int) initialized}. The caller is responsible for focussing the * correct render target before calling this method. * diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java index aa0c69995d..fd0685a8f7 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java @@ -27,7 +27,7 @@ import org.junit.runner.RunWith; /** * Unit tests for {@link Presentation}. * - *

See {@code PresentationFrameProcessorPixelTest} for pixel tests testing {@link Presentation}. + *

See {@code PresentationPixelTest} for pixel tests testing {@link Presentation}. */ @RunWith(AndroidJUnit4.class) public final class PresentationTest { @@ -161,27 +161,27 @@ public final class PresentationTest { @Test public void configure_setAspectRatioAndCrop_throwsIllegalStateException() { - Presentation.Builder presentationFrameProcessor = + Presentation.Builder presentationBuilder = new Presentation.Builder() .setAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT); assertThrows( IllegalStateException.class, () -> - presentationFrameProcessor.setCrop( + presentationBuilder.setCrop( /* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f)); } @Test public void configure_setCropAndAspectRatio_throwsIllegalStateException() { - Presentation.Builder presentationFrameProcessor = + Presentation.Builder presentationBuilder = new Presentation.Builder() .setCrop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f); assertThrows( IllegalStateException.class, () -> - presentationFrameProcessor.setAspectRatio( + presentationBuilder.setAspectRatio( /* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT)); } } diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java index de7ec0014e..e7172731a0 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java @@ -25,8 +25,8 @@ import org.junit.runner.RunWith; /** * Unit tests for {@link ScaleToFitTransformation}. * - *

See {@code MatrixTransformationFrameProcessorPixelTest} for pixel tests testing {@link - * MatrixTransformationFrameProcessor} given a transformation matrix. + *

See {@code MatrixTransformationPixelTest} for pixel tests testing {@link + * MatrixTransformationProcessor} given a transformation matrix. */ @RunWith(AndroidJUnit4.class) public final class ScaleToFitTransformationTest {