diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformationFrameProcessorTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformationFrameProcessorTest.java index 6ad1c188c7..6e90041b59 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformationFrameProcessorTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformationFrameProcessorTest.java @@ -94,10 +94,10 @@ public final class TransformationFrameProcessorTest { Matrix identityMatrix = new Matrix(); transformationFrameProcessor = new TransformationFrameProcessor(getApplicationContext(), identityMatrix); - transformationFrameProcessor.initialize(); + transformationFrameProcessor.initialize(inputTexId); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING); - transformationFrameProcessor.updateProgramAndDraw(inputTexId, /* presentationTimeNs= */ 0); + transformationFrameProcessor.updateProgramAndDraw(/* presentationTimeNs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -117,11 +117,11 @@ public final class TransformationFrameProcessorTest { translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); transformationFrameProcessor = new TransformationFrameProcessor(getApplicationContext(), translateRightMatrix); - transformationFrameProcessor.initialize(); + transformationFrameProcessor.initialize(inputTexId); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_EXPECTED_OUTPUT_PNG_ASSET_STRING); - transformationFrameProcessor.updateProgramAndDraw(inputTexId, /* presentationTimeNs= */ 0); + transformationFrameProcessor.updateProgramAndDraw(/* presentationTimeNs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -141,11 +141,11 @@ public final class TransformationFrameProcessorTest { scaleNarrowMatrix.postScale(.5f, 1.2f); transformationFrameProcessor = new TransformationFrameProcessor(getApplicationContext(), scaleNarrowMatrix); - transformationFrameProcessor.initialize(); + transformationFrameProcessor.initialize(inputTexId); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(SCALE_NARROW_EXPECTED_OUTPUT_PNG_ASSET_STRING); - transformationFrameProcessor.updateProgramAndDraw(inputTexId, /* presentationTimeNs= */ 0); + transformationFrameProcessor.updateProgramAndDraw(/* presentationTimeNs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); @@ -168,10 +168,10 @@ public final class TransformationFrameProcessorTest { rotate90Matrix.postRotate(/* degrees= */ 90); transformationFrameProcessor = new TransformationFrameProcessor(getApplicationContext(), rotate90Matrix); - transformationFrameProcessor.initialize(); + transformationFrameProcessor.initialize(inputTexId); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_EXPECTED_OUTPUT_PNG_ASSET_STRING); - transformationFrameProcessor.updateProgramAndDraw(inputTexId, /* presentationTimeNs= */ 0); + transformationFrameProcessor.updateProgramAndDraw(/* presentationTimeNs= */ 0); Bitmap actualBitmap = BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java index e1314a2b62..05cd6dbf64 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalCopyFrameProcessor.java @@ -58,7 +58,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public void initialize() throws IOException { + public void initialize(int inputTexId) throws IOException { // TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms // expected in the code. String vertexShaderFilePath = @@ -70,6 +70,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ? FRAGMENT_SHADER_COPY_EXTERNAL_YUV_ES3_PATH : FRAGMENT_SHADER_COPY_EXTERNAL_PATH; glProgram = new GlProgram(context, vertexShaderFilePath, fragmentShaderFilePath); + glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* unit= */ 0); // Draw the frame on the entire normalized device coordinate space, from -1 to 1, for x and y. glProgram.setBufferAttribute( "aFramePosition", GlUtil.getNormalizedCoordinateBounds(), GlUtil.RECTANGLE_VERTICES_COUNT); @@ -94,9 +95,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public void updateProgramAndDraw(int inputTexId, long presentationTimeNs) { + public void updateProgramAndDraw(long presentationTimeNs) { checkStateNotNull(glProgram); - glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* unit= */ 0); glProgram.use(); glProgram.bindAttributesAndUniforms(); GLES20.glClearColor(/* red= */ 0, /* green= */ 0, /* blue= */ 0, /* alpha= */ 0); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameEditor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameEditor.java index 7b00b1351b..ffad915ae2 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameEditor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameEditor.java @@ -183,10 +183,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, outputWidth, outputHeight); int inputExternalTexId = GlUtil.createExternalTexture(); + externalCopyFrameProcessor.initialize(inputExternalTexId); int intermediateTexId = GlUtil.createTexture(outputWidth, outputHeight); int frameBuffer = GlUtil.createFboForTexture(intermediateTexId); - externalCopyFrameProcessor.initialize(); - transformationFrameProcessor.initialize(); + transformationFrameProcessor.initialize(intermediateTexId); return new FrameEditor( singleThreadExecutorService, @@ -196,7 +196,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; externalCopyFrameProcessor, transformationFrameProcessor, inputExternalTexId, - intermediateTexId, frameBuffer, outputWidth, outputHeight, @@ -228,11 +227,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private final float[] textureTransformMatrix; /** - * Identifier of the texture where the output of the {@link ExternalCopyFrameProcessor} is written - * to and the {@link TransformationFrameProcessor} reads its input from. + * Identifier of a framebuffer object associated with the intermediate texture that the output of + * the {@link ExternalCopyFrameProcessor} is written to and the {@link + * TransformationFrameProcessor} reads its input from. */ - private final int intermediateTexId; - /** Identifier of a framebuffer object associated with the intermediate texture. */ private final int frameBuffer; private final int outputWidth; @@ -255,7 +253,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ExternalCopyFrameProcessor externalCopyFrameProcessor, GlFrameProcessor transformationFrameProcessor, int inputExternalTexId, - int intermediateTexId, int frameBuffer, int outputWidth, int outputHeight, @@ -269,7 +266,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; this.externalCopyFrameProcessor = externalCopyFrameProcessor; this.transformationFrameProcessor = transformationFrameProcessor; this.inputExternalTexId = inputExternalTexId; - this.intermediateTexId = intermediateTexId; this.frameBuffer = frameBuffer; this.outputWidth = outputWidth; this.outputHeight = outputHeight; @@ -402,10 +398,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; GlUtil.focusFramebuffer( eglDisplay, eglContext, eglSurface, frameBuffer, outputWidth, outputHeight); externalCopyFrameProcessor.setTextureTransformMatrix(textureTransformMatrix); - externalCopyFrameProcessor.updateProgramAndDraw(inputExternalTexId, presentationTimeNs); + externalCopyFrameProcessor.updateProgramAndDraw(presentationTimeNs); GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, outputWidth, outputHeight); - transformationFrameProcessor.updateProgramAndDraw(intermediateTexId, presentationTimeNs); + transformationFrameProcessor.updateProgramAndDraw(presentationTimeNs); EGLExt.eglPresentationTimeANDROID(eglDisplay, eglSurface, presentationTimeNs); EGL14.eglSwapBuffers(eglDisplay, eglSurface); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java index 18be0193e4..3f4d85db74 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java @@ -28,19 +28,20 @@ import java.io.IOException; * *
This method may only be called after creating the OpenGL context and focusing a render * target. + * + * @param inputTexId The identifier of an OpenGL texture that the fragment shader can sample from. */ - void initialize() throws IOException; + void initialize(int inputTexId) throws IOException; /** * Updates the shader program's vertex attributes and uniforms, binds them, and draws. * - *
The frame processor must be {@link #initialize() initialized}. The caller is responsible for - * focussing the correct render target before calling this method. + *
The frame processor must be {@link #initialize(int) initialized}. The caller is responsible + * for focussing the correct render target before calling this method. * - * @param inputTexId The identifier of an OpenGL texture that the fragment shader can sample from. * @param presentationTimeNs The presentation timestamp of the current frame, in nanoseconds. */ - void updateProgramAndDraw(int inputTexId, long presentationTimeNs); + void updateProgramAndDraw(long presentationTimeNs); /** Releases all resources. */ void release(); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationFrameProcessor.java index 75c2c131c0..576fc74d96 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationFrameProcessor.java @@ -93,10 +93,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public void initialize() throws IOException { + public void initialize(int inputTexId) throws IOException { // TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms // expected in the code. glProgram = new GlProgram(context, VERTEX_SHADER_TRANSFORMATION_PATH, FRAGMENT_SHADER_PATH); + glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* unit= */ 0); // Draw the frame on the entire normalized device coordinate space, from -1 to 1, for x and y. glProgram.setBufferAttribute( "aFramePosition", GlUtil.getNormalizedCoordinateBounds(), GlUtil.RECTANGLE_VERTICES_COUNT); @@ -106,9 +107,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public void updateProgramAndDraw(int inputTexId, long presentationTimeNs) { + public void updateProgramAndDraw(long presentationTimeNs) { checkStateNotNull(glProgram); - glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* unit= */ 0); glProgram.use(); glProgram.bindAttributesAndUniforms(); GLES20.glClearColor(/* red= */ 0, /* green= */ 0, /* blue= */ 0, /* alpha= */ 0);