From 4b8ff72d301cbd52873a9ad750e3187dbf95151c Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 4 May 2022 17:40:33 +0100 Subject: [PATCH] Use MatrixTransformation instead of wrapping its GlFrameProcssor. ScaleToFitFrameProcessor, PresentationFrameProcessor, and EncoderCompatibilityFrameProcessor now each implement MatrixTransformation instead of wrapping MatrixTransformationFrameProcessor. PiperOrigin-RevId: 446480286 --- .../FrameProcessorChainPixelTest.java | 9 +- ...elTest.java => PresentationPixelTest.java} | 60 +++++++------ ...> EncoderCompatibilityTransformation.java} | 60 +++++-------- .../transformer/FrameProcessorChain.java | 10 ++- .../MatrixTransformationFrameProcessor.java | 5 +- ...nFrameProcessor.java => Presentation.java} | 71 ++++----------- ...sor.java => ScaleToFitTransformation.java} | 62 +++---------- .../VideoTranscodingSamplePipeline.java | 22 ++--- ...ncoderCompatibilityFrameProcessorTest.java | 73 --------------- ...ncoderCompatibilityTransformationTest.java | 80 +++++++++++++++++ ...ocessorTest.java => PresentationTest.java} | 88 ++++++++----------- ...java => ScaleToFitTransformationTest.java} | 62 ++++++------- 12 files changed, 256 insertions(+), 346 deletions(-) rename libraries/transformer/src/androidTest/java/androidx/media3/transformer/{PresentationFrameProcessorPixelTest.java => PresentationPixelTest.java} (92%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{EncoderCompatibilityFrameProcessor.java => EncoderCompatibilityTransformation.java} (59%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{PresentationFrameProcessor.java => Presentation.java} (82%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{ScaleToFitFrameProcessor.java => ScaleToFitTransformation.java} (70%) delete mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessorTest.java create mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java rename libraries/transformer/src/test/java/androidx/media3/transformer/{PresentationFrameProcessorTest.java => PresentationTest.java} (56%) rename libraries/transformer/src/test/java/androidx/media3/transformer/{ScaleToFitFrameProcessorTest.java => ScaleToFitTransformationTest.java} (50%) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java index 540df28de9..7e3ec259c6 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java @@ -154,7 +154,7 @@ public final class FrameProcessorChainPixelTest { setUpAndPrepareFirstFrame( DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, (MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix, - () -> new ScaleToFitFrameProcessor.Builder().setRotationDegrees(45).build()); + new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_THEN_ROTATE_PNG_ASSET_PATH); Bitmap actualBitmap = processFirstFrameAndEnd(); @@ -176,7 +176,7 @@ public final class FrameProcessorChainPixelTest { translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); setUpAndPrepareFirstFrame( DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, - () -> new ScaleToFitFrameProcessor.Builder().setRotationDegrees(45).build(), + new ScaleToFitTransformation.Builder().setRotationDegrees(45).build(), (MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_THEN_TRANSLATE_PNG_ASSET_PATH); @@ -195,8 +195,7 @@ public final class FrameProcessorChainPixelTest { public void processData_withPresentation_setResolution_producesExpectedOutput() throws Exception { String testId = "processData_withPresentation_setResolution"; setUpAndPrepareFirstFrame( - DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, - () -> new PresentationFrameProcessor.Builder().setResolution(480).build()); + DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, new Presentation.Builder().setResolution(480).build()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(REQUEST_OUTPUT_HEIGHT_PNG_ASSET_PATH); Bitmap actualBitmap = processFirstFrameAndEnd(); @@ -216,7 +215,7 @@ public final class FrameProcessorChainPixelTest { String testId = "processData_withScaleToFitTransformation_rotate45"; setUpAndPrepareFirstFrame( DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, - () -> new ScaleToFitFrameProcessor.Builder().setRotationDegrees(45).build()); + new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE45_SCALE_TO_FIT_PNG_ASSET_PATH); Bitmap actualBitmap = processFirstFrameAndEnd(); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java similarity index 92% rename from libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java rename to libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java index aaeb217622..e76e4963b9 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.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 PresentationFrameProcessor}. + * Pixel test for frame 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 @@ -43,7 +43,7 @@ import org.junit.runner.RunWith; * as recommended in {@link FrameProcessorChainPixelTest}. */ @RunWith(AndroidJUnit4.class) -public final class PresentationFrameProcessorPixelTest { +public final class PresentationPixelTest { public static final String ORIGINAL_PNG_ASSET_PATH = "media/bitmap/sample_mp4_first_frame/original.png"; public static final String CROP_SMALLER_PNG_ASSET_PATH = @@ -97,7 +97,7 @@ public final class PresentationFrameProcessorPixelTest { @Test public void drawFrame_noEdits_producesExpectedOutput() throws Exception { String testId = "drawFrame_noEdits"; - presentationFrameProcessor = new PresentationFrameProcessor.Builder().build(); + presentationFrameProcessor = new Presentation.Builder().build().toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -122,9 +122,10 @@ public final class PresentationFrameProcessorPixelTest { public void drawFrame_cropSmaller_producesExpectedOutput() throws Exception { String testId = "drawFrame_cropSmaller"; GlFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() + new Presentation.Builder() .setCrop(/* left= */ -.9f, /* right= */ .1f, /* bottom= */ -1f, /* top= */ .5f) - .build(); + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -149,9 +150,10 @@ public final class PresentationFrameProcessorPixelTest { public void drawFrame_cropLarger_producesExpectedOutput() throws Exception { String testId = "drawFrame_cropSmaller"; GlFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() + new Presentation.Builder() .setCrop(/* left= */ -2f, /* right= */ 2f, /* bottom= */ -1f, /* top= */ 2f) - .build(); + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -177,9 +179,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) - .build(); + new Presentation.Builder() + .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -206,9 +209,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_wide"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) - .build(); + new Presentation.Builder() + .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -235,9 +239,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT_WITH_CROP) - .build(); + new Presentation.Builder() + .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -264,9 +269,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT_WITH_CROP) - .build(); + new Presentation.Builder() + .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -293,9 +299,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_STRETCH_TO_FIT) - .build(); + new Presentation.Builder() + .setAspectRatio(1f, Presentation.LAYOUT_STRETCH_TO_FIT) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -322,9 +329,10 @@ public final class PresentationFrameProcessorPixelTest { throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_wide"; presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_STRETCH_TO_FIT) - .build(); + new Presentation.Builder() + .setAspectRatio(2f, Presentation.LAYOUT_STRETCH_TO_FIT) + .build() + .toGlFrameProcessor(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); Size outputSize = presentationFrameProcessor.getOutputSize(); @@ -346,7 +354,7 @@ public final class PresentationFrameProcessorPixelTest { assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); } - private void setupOutputTexture(int outputWidth, int outputHeight) throws IOException { + private void setupOutputTexture(int outputWidth, int outputHeight) { outputTexId = GlUtil.createTexture(outputWidth, outputHeight); int frameBuffer = GlUtil.createFboForTexture(outputTexId); GlUtil.focusFramebuffer( diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java similarity index 59% rename from libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java index 0cd45fa9ac..b326c480c1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java @@ -20,23 +20,22 @@ 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.annotation.VisibleForTesting; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.util.GlUtil; -import java.io.IOException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * Copies frames from a texture and applies {@link Format#rotationDegrees} for encoder - * compatibility, if needed. + * Specifies a {@link Format#rotationDegrees} to apply to each frame for encoder compatibility, if + * needed. * *

Encoders commonly support higher maximum widths than maximum heights. This may rotate the * decoded frame before encoding, so the encoded frame's width >= height, and set {@link * Format#rotationDegrees} to ensure the frame is displayed in the correct orientation. */ -/* package */ class EncoderCompatibilityFrameProcessor implements GlFrameProcessor { +/* package */ class EncoderCompatibilityTransformation implements MatrixTransformation { // TODO(b/218488308): Allow reconfiguration of the output size, as encoders may not support the // requested output resolution. @@ -45,26 +44,32 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private int outputRotationDegrees; - private @MonotonicNonNull ScaleToFitFrameProcessor rotateFrameProcessor; + private @MonotonicNonNull Matrix transformationMatrix; /** Creates a new instance. */ - /* package */ EncoderCompatibilityFrameProcessor() { - + public EncoderCompatibilityTransformation() { outputRotationDegrees = C.LENGTH_UNSET; } @Override - public void initialize(Context context, int inputTexId, int inputWidth, int inputHeight) - throws IOException { - configureOutputSizeAndRotation(inputWidth, inputHeight); - rotateFrameProcessor = - new ScaleToFitFrameProcessor.Builder().setRotationDegrees(outputRotationDegrees).build(); - rotateFrameProcessor.initialize(context, inputTexId, inputWidth, inputHeight); + public Size configure(int inputWidth, int inputHeight) { + checkArgument(inputWidth > 0, "inputWidth must be positive"); + checkArgument(inputHeight > 0, "inputHeight must be positive"); + + transformationMatrix = new Matrix(); + if (inputHeight > inputWidth) { + outputRotationDegrees = 90; + transformationMatrix.postRotate(outputRotationDegrees); + return new Size(inputHeight, inputWidth); + } else { + outputRotationDegrees = 0; + return new Size(inputWidth, inputHeight); + } } @Override - public Size getOutputSize() { - return checkStateNotNull(rotateFrameProcessor).getOutputSize(); + public Matrix getMatrix(long presentationTimeUs) { + return checkStateNotNull(transformationMatrix, "configure must be called first"); } /** @@ -78,28 +83,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public int getOutputRotationDegrees() { checkState( outputRotationDegrees != C.LENGTH_UNSET, - "configureOutputSizeAndTransformationMatrix must be called before" - + " getOutputRotationDegrees"); + "configure must be called before getOutputRotationDegrees"); return outputRotationDegrees; } - - @Override - public void drawFrame(long presentationTimeUs) { - checkStateNotNull(rotateFrameProcessor).drawFrame(presentationTimeUs); - } - - @Override - public void release() { - if (rotateFrameProcessor != null) { - rotateFrameProcessor.release(); - } - } - - @VisibleForTesting // Allows robolectric testing of output size calculation without OpenGL. - /* package */ void configureOutputSizeAndRotation(int inputWidth, int inputHeight) { - checkArgument(inputWidth > 0, "inputWidth must be positive"); - checkArgument(inputHeight > 0, "inputHeight must be positive"); - - outputRotationDegrees = (inputHeight > inputWidth) ? 90 : 0; - } } 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 52df7d267a..a61d74699f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -190,14 +190,16 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // Scale to expand the frame to apply the pixelWidthHeightRatio. if (pixelWidthHeightRatio > 1f) { frameProcessors.add( - new ScaleToFitFrameProcessor.Builder() + new ScaleToFitTransformation.Builder() .setScale(/* scaleX= */ pixelWidthHeightRatio, /* scaleY= */ 1f) - .build()); + .build() + .toGlFrameProcessor()); } else if (pixelWidthHeightRatio < 1f) { frameProcessors.add( - new ScaleToFitFrameProcessor.Builder() + new ScaleToFitTransformation.Builder() .setScale(/* scaleX= */ 1f, /* scaleY= */ 1f / pixelWidthHeightRatio) - .build()); + .build() + .toGlFrameProcessor()); } for (int i = 0; i < effects.size(); i++) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java index 0c500e9e6b..78888af90f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationFrameProcessor.java @@ -32,8 +32,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * Applies a transformation matrix in the vertex shader, and copies input pixels into an output * frame based on their locations after applying this matrix. * - *

Operations are done on normalized device coordinates (-1 to 1 on x and y axes). No automatic - * adjustments (like done in {@link ScaleToFitFrameProcessor}) are applied on the transformation. + *

Operations are done on normalized device coordinates (-1 to 1 on x and y axes). * *

The background color of the output frame will be black. */ @@ -41,7 +40,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // after each matrix. @UnstableApi @SuppressWarnings("FunctionalInterfaceClash") // b/228192298 -public final class MatrixTransformationFrameProcessor implements GlFrameProcessor { +/* package */ final class MatrixTransformationFrameProcessor implements GlFrameProcessor { static { GlUtil.glAssertionsEnabled = true; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java similarity index 82% rename from libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java index 48fb9131d9..7823a601ef 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java @@ -21,36 +21,30 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.content.Context; import android.graphics.Matrix; import android.util.Size; import androidx.annotation.IntDef; -import androidx.annotation.VisibleForTesting; import androidx.media3.common.C; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.UnstableApi; -import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** - * Controls how a frame is presented, by copying input pixels into an output frame, with options to - * set the output resolution, crop the input, and choose how to map the input pixels onto the output - * frame geometry (for example, by stretching the input frame to match the specified output frame, - * or fitting the input frame using letterboxing). + * Controls how a frame is presented with options to set the output resolution, crop the input, and + * choose how to map the input pixels onto the output frame geometry (for example, by stretching the + * input frame to match the specified output frame, or fitting the input frame using letterboxing). * *

Cropping or aspect ratio is applied before setting resolution. * *

The background color of the output frame will be black. */ @UnstableApi -// TODO(b/227625423): Implement MatrixTransformation instead of wrapping -// MatrixTransformationFrameProcessor. -public final class PresentationFrameProcessor implements GlFrameProcessor { +public final class Presentation implements MatrixTransformation { + /** * Strategies controlling the layout of input pixels in the output frame. * @@ -108,7 +102,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { */ public static final int LAYOUT_STRETCH_TO_FIT = 2; - /** A builder for {@link PresentationFrameProcessor} instances. */ + /** A builder for {@link Presentation} instances. */ public static final class Builder { // Optional fields. @@ -161,7 +155,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { * applied after cropping changes. * *

Only one of {@code setCrop} or {@link #setAspectRatio(float, int)} can be called for one - * {@link PresentationFrameProcessor}. + * {@link Presentation}. * * @param left The left edge of the output frame, in NDC. Must be less than {@code right}. * @param right The right edge of the output frame, in NDC. Must be greater than {@code left}. @@ -196,7 +190,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { * applied after aspect ratio changes. * *

Only one of {@link #setCrop(float, float, float, float)} or {@code setAspectRatio} can be - * called for one {@link PresentationFrameProcessor}. + * called for one {@link Presentation}. * * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be * positive. @@ -217,8 +211,8 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { return this; } - public PresentationFrameProcessor build() { - return new PresentationFrameProcessor( + public Presentation build() { + return new Presentation( heightPixels, cropLeft, cropRight, cropBottom, cropTop, aspectRatio, layout); } } @@ -237,12 +231,10 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { private float outputWidth; private float outputHeight; - private @MonotonicNonNull Size outputSize; private @MonotonicNonNull Matrix transformationMatrix; - private @MonotonicNonNull MatrixTransformationFrameProcessor matrixTransformationFrameProcessor; /** Creates a new instance. */ - private PresentationFrameProcessor( + private Presentation( int requestedHeightPixels, float cropLeft, float cropRight, @@ -264,39 +256,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { } @Override - public void initialize(Context context, int inputTexId, int inputWidth, int inputHeight) - throws IOException { - configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor( - /* matrixTransformation= */ (long presentationTimeUs) -> - checkStateNotNull(transformationMatrix)); - matrixTransformationFrameProcessor.initialize(context, inputTexId, inputWidth, inputHeight); - } - - @Override - public Size getOutputSize() { - checkStateNotNull( - outputSize, - "configureOutputSizeAndTransformationMatrix must be called before getOutputSize"); - return outputSize; - } - - @Override - public void drawFrame(long presentationTimeUs) { - checkStateNotNull(matrixTransformationFrameProcessor).drawFrame(presentationTimeUs); - } - - @Override - public void release() { - if (matrixTransformationFrameProcessor != null) { - matrixTransformationFrameProcessor.release(); - } - } - - @EnsuresNonNull("transformationMatrix") - @VisibleForTesting // Allows robolectric testing of output size calculation without OpenGL. - /* package */ void configureOutputSizeAndTransformationMatrix(int inputWidth, int inputHeight) { + public Size configure(int inputWidth, int inputHeight) { checkArgument(inputWidth > 0, "inputWidth must be positive"); checkArgument(inputHeight > 0, "inputHeight must be positive"); @@ -318,7 +278,12 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { outputWidth = requestedHeightPixels * outputWidth / outputHeight; outputHeight = requestedHeightPixels; } - outputSize = new Size(Math.round(outputWidth), Math.round(outputHeight)); + return new Size(Math.round(outputWidth), Math.round(outputHeight)); + } + + @Override + public Matrix getMatrix(long presentationTimeUs) { + return checkStateNotNull(transformationMatrix, "configure must be called first"); } @RequiresNonNull("transformationMatrix") diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitTransformation.java similarity index 70% rename from libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitTransformation.java index f9612367b1..55eddb6aec 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitTransformation.java @@ -20,18 +20,14 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull; import static java.lang.Math.max; import static java.lang.Math.min; -import android.content.Context; import android.graphics.Matrix; import android.util.Size; -import androidx.annotation.VisibleForTesting; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.UnstableApi; -import java.io.IOException; -import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * Applies a simple rotation and/or scale in the vertex shader. + * Specifies a simple rotation and/or scale to apply in the vertex shader. * *

All input frames' pixels will be preserved and copied into an output frame, potentially * changing the width and height of the frame by scaling dimensions to fit. @@ -39,11 +35,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; *

The background color of the output frame will be black. */ @UnstableApi -// TODO(b/227625423): Implement MatrixTransformation instead of wrapping -// MatrixTransformationFrameProcessor. -public final class ScaleToFitFrameProcessor implements GlFrameProcessor { +public final class ScaleToFitTransformation implements MatrixTransformation { - /** A builder for {@link ScaleToFitFrameProcessor} instances. */ + /** A builder for {@link ScaleToFitTransformation} instances. */ public static final class Builder { // Optional fields. @@ -86,8 +80,8 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { return this; } - public ScaleToFitFrameProcessor build() { - return new ScaleToFitFrameProcessor(scaleX, scaleY, rotationDegrees); + public ScaleToFitTransformation build() { + return new ScaleToFitTransformation(scaleX, scaleY, rotationDegrees); } } @@ -96,9 +90,6 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { } private final Matrix transformationMatrix; - - private @MonotonicNonNull MatrixTransformationFrameProcessor matrixTransformationFrameProcessor; - private @MonotonicNonNull Size outputSize; private @MonotonicNonNull Matrix adjustedTransformationMatrix; /** @@ -108,51 +99,21 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { * @param scaleY The multiplier by which the frame will scale vertically, along the y-axis. * @param rotationDegrees How much to rotate the frame counterclockwise, in degrees. */ - private ScaleToFitFrameProcessor(float scaleX, float scaleY, float rotationDegrees) { + private ScaleToFitTransformation(float scaleX, float scaleY, float rotationDegrees) { this.transformationMatrix = new Matrix(); this.transformationMatrix.postScale(scaleX, scaleY); this.transformationMatrix.postRotate(rotationDegrees); } @Override - public void initialize(Context context, int inputTexId, int inputWidth, int inputHeight) - throws IOException { - configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - matrixTransformationFrameProcessor = - new MatrixTransformationFrameProcessor( - /* matrixTransformation= */ (long presentationTimeUs) -> - checkStateNotNull(adjustedTransformationMatrix)); - matrixTransformationFrameProcessor.initialize(context, inputTexId, inputWidth, inputHeight); - } - - @Override - public Size getOutputSize() { - return checkStateNotNull(outputSize); - } - - @Override - public void drawFrame(long presentationTimeUs) { - checkStateNotNull(matrixTransformationFrameProcessor).drawFrame(presentationTimeUs); - } - - @Override - public void release() { - if (matrixTransformationFrameProcessor != null) { - matrixTransformationFrameProcessor.release(); - } - } - - @EnsuresNonNull("adjustedTransformationMatrix") - @VisibleForTesting // Allows robolectric testing of output size calculation without OpenGL. - /* package */ void configureOutputSizeAndTransformationMatrix(int inputWidth, int inputHeight) { + public Size configure(int inputWidth, int inputHeight) { checkArgument(inputWidth > 0, "inputWidth must be positive"); checkArgument(inputHeight > 0, "inputHeight must be positive"); adjustedTransformationMatrix = new Matrix(transformationMatrix); if (transformationMatrix.isIdentity()) { - outputSize = new Size(inputWidth, inputHeight); - return; + return new Size(inputWidth, inputHeight); } float inputAspectRatio = (float) inputWidth / inputHeight; @@ -181,6 +142,11 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { float scaleX = (maxX - minX) / GlUtil.LENGTH_NDC; float scaleY = (maxY - minY) / GlUtil.LENGTH_NDC; adjustedTransformationMatrix.postScale(1f / scaleX, 1f / scaleY); - outputSize = new Size(Math.round(inputWidth * scaleX), Math.round(inputHeight * scaleY)); + return new Size(Math.round(inputWidth * scaleX), Math.round(inputHeight * scaleY)); + } + + @Override + public Matrix getMatrix(long presentationTimeUs) { + return checkStateNotNull(adjustedTransformationMatrix, "configure must be called first"); } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 6d105085c0..6d28f8925f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -74,22 +74,18 @@ import org.checkerframework.dataflow.qual.Pure; || transformationRequest.scaleY != 1f || transformationRequest.rotationDegrees != 0f) { effectsListBuilder.add( - () -> - new ScaleToFitFrameProcessor.Builder() - .setScale(transformationRequest.scaleX, transformationRequest.scaleY) - .setRotationDegrees(transformationRequest.rotationDegrees) - .build()); + new ScaleToFitTransformation.Builder() + .setScale(transformationRequest.scaleX, transformationRequest.scaleY) + .setRotationDegrees(transformationRequest.rotationDegrees) + .build()); } if (transformationRequest.outputHeight != C.LENGTH_UNSET) { effectsListBuilder.add( - () -> - new PresentationFrameProcessor.Builder() - .setResolution(transformationRequest.outputHeight) - .build()); + new Presentation.Builder().setResolution(transformationRequest.outputHeight).build()); } - EncoderCompatibilityFrameProcessor encoderCompatibilityFrameProcessor = - new EncoderCompatibilityFrameProcessor(); - effectsListBuilder.add(() -> encoderCompatibilityFrameProcessor); + EncoderCompatibilityTransformation encoderCompatibilityTransformation = + new EncoderCompatibilityTransformation(); + effectsListBuilder.add(encoderCompatibilityTransformation); frameProcessorChain = FrameProcessorChain.create( context, @@ -99,7 +95,7 @@ import org.checkerframework.dataflow.qual.Pure; effectsListBuilder.build(), transformationRequest.enableHdrEditing); Size requestedEncoderSize = frameProcessorChain.getOutputSize(); - outputRotationDegrees = encoderCompatibilityFrameProcessor.getOutputRotationDegrees(); + outputRotationDegrees = encoderCompatibilityTransformation.getOutputRotationDegrees(); Format requestedEncoderFormat = new Format.Builder() diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessorTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessorTest.java deleted file mode 100644 index 4fb73c9024..0000000000 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityFrameProcessorTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.transformer; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertThrows; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** Unit tests for {@link EncoderCompatibilityFrameProcessor}. */ -@RunWith(AndroidJUnit4.class) -public final class EncoderCompatibilityFrameProcessorTest { - @Test - public void getOutputSize_noEditsLandscape_leavesOrientationUnchanged() { - int inputWidth = 200; - int inputHeight = 150; - EncoderCompatibilityFrameProcessor encoderCompatibilityFrameProcessor = - new EncoderCompatibilityFrameProcessor(); - - encoderCompatibilityFrameProcessor.configureOutputSizeAndRotation(inputWidth, inputHeight); - - assertThat(encoderCompatibilityFrameProcessor.getOutputRotationDegrees()).isEqualTo(0); - } - - @Test - public void getOutputSize_noEditsSquare_leavesOrientationUnchanged() { - int inputWidth = 150; - int inputHeight = 150; - EncoderCompatibilityFrameProcessor encoderCompatibilityFrameProcessor = - new EncoderCompatibilityFrameProcessor(); - - encoderCompatibilityFrameProcessor.configureOutputSizeAndRotation(inputWidth, inputHeight); - - assertThat(encoderCompatibilityFrameProcessor.getOutputRotationDegrees()).isEqualTo(0); - } - - @Test - public void getOutputSize_noEditsPortrait_flipsOrientation() { - int inputWidth = 150; - int inputHeight = 200; - EncoderCompatibilityFrameProcessor encoderCompatibilityFrameProcessor = - new EncoderCompatibilityFrameProcessor(); - - encoderCompatibilityFrameProcessor.configureOutputSizeAndRotation(inputWidth, inputHeight); - - assertThat(encoderCompatibilityFrameProcessor.getOutputRotationDegrees()).isEqualTo(90); - } - - @Test - public void getOutputRotationDegreesBeforeConfigure_throwsIllegalStateException() { - EncoderCompatibilityFrameProcessor encoderCompatibilityFrameProcessor = - new EncoderCompatibilityFrameProcessor(); - - // configureOutputSize not called before getOutputRotationDegrees. - assertThrows( - IllegalStateException.class, encoderCompatibilityFrameProcessor::getOutputRotationDegrees); - } -} diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java new file mode 100644 index 0000000000..3eb95008d1 --- /dev/null +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.media3.transformer; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import android.util.Size; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit tests for {@link EncoderCompatibilityTransformation}. */ +@RunWith(AndroidJUnit4.class) +public final class EncoderCompatibilityTransformationTest { + @Test + public void configure_noEditsLandscape_leavesOrientationUnchanged() { + int inputWidth = 200; + int inputHeight = 150; + EncoderCompatibilityTransformation encoderCompatibilityTransformation = + new EncoderCompatibilityTransformation(); + + Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); + + assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(0); + assertThat(outputSize.getWidth()).isEqualTo(inputWidth); + assertThat(outputSize.getHeight()).isEqualTo(inputHeight); + } + + @Test + public void configure_noEditsSquare_leavesOrientationUnchanged() { + int inputWidth = 150; + int inputHeight = 150; + EncoderCompatibilityTransformation encoderCompatibilityTransformation = + new EncoderCompatibilityTransformation(); + + Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); + + assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(0); + assertThat(outputSize.getWidth()).isEqualTo(inputWidth); + assertThat(outputSize.getHeight()).isEqualTo(inputHeight); + } + + @Test + public void configure_noEditsPortrait_flipsOrientation() { + int inputWidth = 150; + int inputHeight = 200; + EncoderCompatibilityTransformation encoderCompatibilityTransformation = + new EncoderCompatibilityTransformation(); + + Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); + + assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(90); + assertThat(outputSize.getWidth()).isEqualTo(inputHeight); + assertThat(outputSize.getHeight()).isEqualTo(inputWidth); + } + + @Test + public void getOutputRotationDegreesBeforeConfigure_throwsIllegalStateException() { + EncoderCompatibilityTransformation encoderCompatibilityTransformation = + new EncoderCompatibilityTransformation(); + + // configure not called before getOutputRotationDegrees. + assertThrows( + IllegalStateException.class, encoderCompatibilityTransformation::getOutputRotationDegrees); + } +} diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java similarity index 56% rename from libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java rename to libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java index 09b999241e..aa0c69995d 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java @@ -25,55 +25,49 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Unit tests for {@link PresentationFrameProcessor}. + * Unit tests for {@link Presentation}. * - *

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

See {@code PresentationFrameProcessorPixelTest} for pixel tests testing {@link Presentation}. */ @RunWith(AndroidJUnit4.class) -public final class PresentationFrameProcessorTest { +public final class PresentationTest { @Test - public void getOutputSize_noEdits_leavesFramesUnchanged() { + public void configure_noEdits_leavesFramesUnchanged() { int inputWidth = 200; int inputHeight = 150; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder().build(); + Presentation presentation = new Presentation.Builder().build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputWidth); assertThat(outputSize.getHeight()).isEqualTo(inputHeight); } @Test - public void getOutputSize_setResolution_changesDimensions() { + public void configure_setResolution_changesDimensions() { int inputWidth = 200; int inputHeight = 150; int requestedHeight = 300; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder().setResolution(requestedHeight).build(); + Presentation presentation = new Presentation.Builder().setResolution(requestedHeight).build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(requestedHeight * inputWidth / inputHeight); assertThat(outputSize.getHeight()).isEqualTo(requestedHeight); } @Test - public void getOutputSize_setCrop_changesDimensions() { + public void configure_setCrop_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float left = -.5f; float right = .5f; float bottom = .5f; float top = 1f; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder().setCrop(left, right, bottom, top).build(); + Presentation presentation = + new Presentation.Builder().setCrop(left, right, bottom, top).build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); int expectedPostCropWidth = Math.round(inputWidth * (right - left) / GlUtil.LENGTH_NDC); int expectedPostCropHeight = Math.round(inputHeight * (top - bottom) / GlUtil.LENGTH_NDC); @@ -82,7 +76,7 @@ public final class PresentationFrameProcessorTest { } @Test - public void getOutputSize_setCropAndSetResolution_changesDimensions() { + public void configure_setCropAndSetResolution_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float left = -.5f; @@ -90,14 +84,13 @@ public final class PresentationFrameProcessorTest { float bottom = .5f; float top = 1f; int requestedHeight = 100; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() + Presentation presentation = + new Presentation.Builder() .setCrop(left, right, bottom, top) .setResolution(requestedHeight) .build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); int expectedPostCropWidth = Math.round(inputWidth * (right - left) / GlUtil.LENGTH_NDC); int expectedPostCropHeight = Math.round(inputHeight * (top - bottom) / GlUtil.LENGTH_NDC); @@ -108,7 +101,7 @@ public final class PresentationFrameProcessorTest { } @Test - public void getOutputSize_setResolutionAndCrop_changesDimensions() { + public void configure_setResolutionAndCrop_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float left = -.5f; @@ -116,14 +109,13 @@ public final class PresentationFrameProcessorTest { float bottom = .5f; float top = 1f; int requestedHeight = 100; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() + Presentation presentation = + new Presentation.Builder() .setResolution(requestedHeight) .setCrop(left, right, bottom, top) .build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); int expectedPostCropWidth = Math.round(inputWidth * (right - left) / GlUtil.LENGTH_NDC); int expectedPostCropHeight = Math.round(inputHeight * (top - bottom) / GlUtil.LENGTH_NDC); @@ -134,46 +126,44 @@ public final class PresentationFrameProcessorTest { } @Test - public void getOutputSize_setAspectRatio_changesDimensions() { + public void configure_setAspectRatio_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float aspectRatio = 2f; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(aspectRatio, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) + Presentation presentation = + new Presentation.Builder() + .setAspectRatio(aspectRatio, Presentation.LAYOUT_SCALE_TO_FIT) .build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(Math.round(aspectRatio * inputHeight)); assertThat(outputSize.getHeight()).isEqualTo(inputHeight); } @Test - public void getOutputSize_setAspectRatioAndResolution_changesDimensions() { + public void configure_setAspectRatioAndResolution_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float aspectRatio = 2f; int requestedHeight = 100; - PresentationFrameProcessor presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(aspectRatio, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) + Presentation presentation = + new Presentation.Builder() + .setAspectRatio(aspectRatio, Presentation.LAYOUT_SCALE_TO_FIT) .setResolution(requestedHeight) .build(); - presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = presentationFrameProcessor.getOutputSize(); + Size outputSize = presentation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(Math.round(aspectRatio * requestedHeight)); assertThat(outputSize.getHeight()).isEqualTo(requestedHeight); } @Test - public void getOutputSize_setAspectRatioAndCrop_throwsIllegalStateException() { - PresentationFrameProcessor.Builder presentationFrameProcessor = - new PresentationFrameProcessor.Builder() - .setAspectRatio(/* aspectRatio= */ 2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT); + public void configure_setAspectRatioAndCrop_throwsIllegalStateException() { + Presentation.Builder presentationFrameProcessor = + new Presentation.Builder() + .setAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT); assertThrows( IllegalStateException.class, @@ -183,15 +173,15 @@ public final class PresentationFrameProcessorTest { } @Test - public void getOutputSize_setCropAndAspectRatio_throwsIllegalStateException() { - PresentationFrameProcessor.Builder presentationFrameProcessor = - new PresentationFrameProcessor.Builder() + public void configure_setCropAndAspectRatio_throwsIllegalStateException() { + Presentation.Builder presentationFrameProcessor = + new Presentation.Builder() .setCrop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f); assertThrows( IllegalStateException.class, () -> presentationFrameProcessor.setAspectRatio( - /* aspectRatio= */ 2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT)); + /* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT)); } } diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitFrameProcessorTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java similarity index 50% rename from libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitFrameProcessorTest.java rename to libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java index 6f270e1b4a..abd3b8b9d0 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitFrameProcessorTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/ScaleToFitTransformationTest.java @@ -23,96 +23,90 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Unit tests for {@link ScaleToFitFrameProcessor}. + * Unit tests for {@link ScaleToFitTransformation}. * - *

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

See {@code MatrixTransformationFrameProcessorText} for pixel tests testing {@link + * MatrixTransformationFrameProcessor} given a transformation matrix. */ @RunWith(AndroidJUnit4.class) -public final class ScaleToFitFrameProcessorTest { +public final class ScaleToFitTransformationTest { @Test - public void getOutputSize_noEdits_leavesFramesUnchanged() { + public void configure_noEdits_leavesFramesUnchanged() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder().build(); + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder().build(); - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputWidth); assertThat(outputSize.getHeight()).isEqualTo(inputHeight); } @Test - public void getOutputSize_scaleNarrow_decreasesWidth() { + public void configure_scaleNarrow_decreasesWidth() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder() + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder() .setScale(/* scaleX= */ .5f, /* scaleY= */ 1f) .build(); - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(Math.round(inputWidth * .5f)); assertThat(outputSize.getHeight()).isEqualTo(inputHeight); } @Test - public void getOutputSize_scaleWide_increasesWidth() { + public void configure_scaleWide_increasesWidth() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder().setScale(/* scaleX= */ 2f, /* scaleY= */ 1f).build(); + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder().setScale(/* scaleX= */ 2f, /* scaleY= */ 1f).build(); - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputWidth * 2); assertThat(outputSize.getHeight()).isEqualTo(inputHeight); } @Test - public void getOutputSize_scaleTall_increasesHeight() { + public void configure_scaleTall_increasesHeight() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder().setScale(/* scaleX= */ 1f, /* scaleY= */ 2f).build(); + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder().setScale(/* scaleX= */ 1f, /* scaleY= */ 2f).build(); - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputWidth); assertThat(outputSize.getHeight()).isEqualTo(inputHeight * 2); } @Test - public void getOutputSize_rotate90_swapsDimensions() { + public void configure_rotate90_swapsDimensions() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder().setRotationDegrees(90).build(); + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder().setRotationDegrees(90).build(); - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputHeight); assertThat(outputSize.getHeight()).isEqualTo(inputWidth); } @Test - public void getOutputSize_rotate45_changesDimensions() { + public void configure_rotate45_changesDimensions() { int inputWidth = 200; int inputHeight = 150; - ScaleToFitFrameProcessor scaleToFitFrameProcessor = - new ScaleToFitFrameProcessor.Builder().setRotationDegrees(45).build(); + ScaleToFitTransformation scaleToFitTransformation = + new ScaleToFitTransformation.Builder().setRotationDegrees(45).build(); long expectedOutputWidthHeight = 247; - scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); - Size outputSize = scaleToFitFrameProcessor.getOutputSize(); + Size outputSize = scaleToFitTransformation.configure(inputWidth, inputHeight); assertThat(outputSize.getWidth()).isEqualTo(expectedOutputWidthHeight); assertThat(outputSize.getHeight()).isEqualTo(expectedOutputWidthHeight);