From 7f7e84bee34ea7a793528a224d26c66bf1909baf Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Tue, 19 Apr 2022 17:42:22 +0100 Subject: [PATCH] FrameProcessor: Improve PresentationFrameProcessor javadocs. PiperOrigin-RevId: 442835160 --- .../PresentationFrameProcessorPixelTest.java | 12 +- .../transformer/AdvancedFrameProcessor.java | 7 +- .../media3/transformer/GlFrameProcessor.java | 3 +- .../PresentationFrameProcessor.java | 118 ++++++++++++------ .../transformer/ScaleToFitFrameProcessor.java | 9 +- .../transformer/TransformationRequest.java | 5 +- .../PresentationFrameProcessorTest.java | 8 +- 7 files changed, 104 insertions(+), 58 deletions(-) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java index 901364ccb3..cbfedddeb1 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationFrameProcessorPixelTest.java @@ -182,7 +182,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.SCALE_TO_FIT) + .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); @@ -211,7 +211,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_scaleToFit_wide"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.SCALE_TO_FIT) + .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); @@ -240,7 +240,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.SCALE_TO_FIT_WITH_CROP) + .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT_WITH_CROP) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); @@ -269,7 +269,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.SCALE_TO_FIT_WITH_CROP) + .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT_WITH_CROP) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); @@ -298,7 +298,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(1f, PresentationFrameProcessor.STRETCH_TO_FIT) + .setAspectRatio(1f, PresentationFrameProcessor.LAYOUT_STRETCH_TO_FIT) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); @@ -327,7 +327,7 @@ public final class PresentationFrameProcessorPixelTest { String testId = "drawFrame_changeAspectRatio_stretchToFit_wide"; presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(2f, PresentationFrameProcessor.STRETCH_TO_FIT) + .setAspectRatio(2f, PresentationFrameProcessor.LAYOUT_STRETCH_TO_FIT) .build(); presentationFrameProcessor.initialize( getApplicationContext(), inputTexId, inputWidth, inputHeight); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/AdvancedFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/AdvancedFrameProcessor.java index 2e5930e8cf..b578ada65e 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/AdvancedFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/AdvancedFrameProcessor.java @@ -28,11 +28,14 @@ import java.io.IOException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * Applies a transformation matrix in the vertex shader. + * 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. - * Width and height are not modified. The background color will default to black. + * Width and height are not modified. + * + *

The background color of the output frame will be black. */ @UnstableApi @SuppressWarnings("FunctionalInterfaceClash") // b/228192298 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 4beb8cc710..d2e80327e3 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlFrameProcessor.java @@ -21,7 +21,8 @@ import androidx.media3.common.util.UnstableApi; import java.io.IOException; /** - * Manages a GLSL shader program for processing a frame. + * Manages a GLSL shader program for processing a frame. Implementations generally copy input pixels + * into an output frame, with changes to pixels specific to the implementation. * *

Methods must be called in the following order: * diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java index f4c289a471..16dd161972 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/PresentationFrameProcessor.java @@ -39,34 +39,73 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** - * Controls how a frame is viewed, by cropping, changing aspect ratio, or changing resolution. + * 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). * *

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

The background color of the output frame will be black. */ @UnstableApi public final class PresentationFrameProcessor implements GlFrameProcessor { /** - * Strategies for how to apply the presented frame. One of {@link #SCALE_TO_FIT}, {@link - * #SCALE_TO_FIT_WITH_CROP}, or {@link #STRETCH_TO_FIT}. + * Strategies controlling the layout of input pixels in the output frame. + * + *

One of {@link #LAYOUT_SCALE_TO_FIT}, {@link #LAYOUT_SCALE_TO_FIT_WITH_CROP}, or {@link + * #LAYOUT_STRETCH_TO_FIT}. + * + *

May scale either width or height, leaving the other output dimension equal to its input, + * unless {@link Builder#setResolution(int)} rescales width and height. */ @Documented @Retention(SOURCE) @Target(TYPE_USE) - @IntDef({SCALE_TO_FIT, SCALE_TO_FIT_WITH_CROP, STRETCH_TO_FIT}) - public @interface PresentationStrategy {} + @IntDef({LAYOUT_SCALE_TO_FIT, LAYOUT_SCALE_TO_FIT_WITH_CROP, LAYOUT_STRETCH_TO_FIT}) + public @interface Layout {} /** * Empty pixels added above and below the input frame (for letterboxing), or to the left and right * of the input frame (for pillarboxing), until the desired aspect ratio is achieved. All input * frame pixels will be within the output frame. + * + *

When applying: + * + *

*/ - public static final int SCALE_TO_FIT = 0; + public static final int LAYOUT_SCALE_TO_FIT = 0; /** - * Pixels cropped from the input frame, until the desired aspect ratio is achieved. Pixels will be - * cropped either from the top and bottom, or from the left and right sides, of the input frame. + * Pixels cropped from the input frame, until the desired aspect ratio is achieved. Pixels may be + * cropped either from the bottom and top, or from the left and right sides, of the input frame. + * + *

When cropping from the: + * + *

*/ - public static final int SCALE_TO_FIT_WITH_CROP = 1; - /** Frame stretched larger on the x or y axes to fit the desired aspect ratio. */ - public static final int STRETCH_TO_FIT = 2; + public static final int LAYOUT_SCALE_TO_FIT_WITH_CROP = 1; + /** + * Frame stretched larger on the x or y axes to fit the desired aspect ratio. + * + *

When stretching to a: + * + *

+ */ + public static final int LAYOUT_STRETCH_TO_FIT = 2; /** A builder for {@link PresentationFrameProcessor} instances. */ public static final class Builder { @@ -78,7 +117,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { private float cropBottom; private float cropTop; private float aspectRatio; - private @PresentationStrategy int presentationStrategy; + private @Layout int layout; /** Creates a builder with default values. */ public Builder() { @@ -93,7 +132,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { /** * Sets the output resolution using the output height. * - *

The default value {@link C#LENGTH_UNSET} corresponds to using the same height as the + *

The default value, {@link C#LENGTH_UNSET}, corresponds to using the same height as the * input. Output width of the displayed frame will scale to preserve the frame's aspect ratio * after other transformations. * @@ -113,10 +152,12 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { * frame corresponds to the square ranging from -1 to 1 on the x and y axes. * *

{@code left} and {@code bottom} default to -1, and {@code right} and {@code top} default - * to 1. To crop to a smaller subset of the input frame, use values between -1 and 1. To crop to - * a larger frame, use values below -1 and above 1. + * to 1, which corresponds to not applying any crop. To crop to a smaller subset of the input + * frame, use values between -1 and 1. To crop to a larger frame, use values below -1 and above + * 1. * - *

Width and height values set may be rescaled by {@link #setResolution(int)}. + *

Width and height values set may be rescaled by {@link #setResolution(int)}, which is + * applied after cropping changes. * *

Only one of {@code setCrop} or {@link #setAspectRatio(float, int)} can be called for one * {@link PresentationFrameProcessor}. @@ -144,43 +185,40 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { } /** - * Resize a frame's width or height to conform to an {@code aspectRatio}, given a {@link - * PresentationStrategy}, and leaving input pixels unchanged. + * Sets the aspect ratio (width/height ratio) for the output frame. * - *

Width and height values set here may be rescaled by {@link #setResolution(int)}. + *

Resizes a frame's width or height to conform to an {@code aspectRatio}, given a {@link + * Layout}. {@code aspectRatio} defaults to {@link C#LENGTH_UNSET}, which corresponds to the + * same aspect ratio as the input frame. {@code layout} defaults to {@link #LAYOUT_SCALE_TO_FIT} + * + *

Width and height values set may be rescaled by {@link #setResolution(int)}, which is + * applied after aspect ratio changes. * *

Only one of {@link #setCrop(float, float, float, float)} or {@code setAspectRatio} can be * called for one {@link PresentationFrameProcessor}. * - * @param aspectRatio The aspect ratio of the output frame, defined as width/height. Must be + * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be * positive. * @return This builder. */ - public Builder setAspectRatio( - float aspectRatio, @PresentationStrategy int presentationStrategy) { + public Builder setAspectRatio(float aspectRatio, @Layout int layout) { checkArgument(aspectRatio > 0, "aspect ratio " + aspectRatio + " must be positive"); checkArgument( - presentationStrategy == SCALE_TO_FIT - || presentationStrategy == SCALE_TO_FIT_WITH_CROP - || presentationStrategy == STRETCH_TO_FIT, - "invalid presentationStrategy " + presentationStrategy); + layout == LAYOUT_SCALE_TO_FIT + || layout == LAYOUT_SCALE_TO_FIT_WITH_CROP + || layout == LAYOUT_STRETCH_TO_FIT, + "invalid layout " + layout); checkState( cropLeft == -1f && cropRight == 1f && cropBottom == -1f && cropTop == 1f, "setAspectRatio and setCrop cannot be called in the same instance"); this.aspectRatio = aspectRatio; - this.presentationStrategy = presentationStrategy; + this.layout = layout; return this; } public PresentationFrameProcessor build() { return new PresentationFrameProcessor( - heightPixels, - cropLeft, - cropRight, - cropBottom, - cropTop, - aspectRatio, - presentationStrategy); + heightPixels, cropLeft, cropRight, cropBottom, cropTop, aspectRatio, layout); } } @@ -194,7 +232,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { private final float cropBottom; private final float cropTop; private final float requestedAspectRatio; - private final @PresentationStrategy int presentationStrategy; + private final @Layout int layout; private int outputRotationDegrees; private int outputWidth; @@ -210,14 +248,14 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { float cropBottom, float cropTop, float requestedAspectRatio, - @PresentationStrategy int presentationStrategy) { + @Layout int layout) { this.requestedHeightPixels = requestedHeightPixels; this.cropLeft = cropLeft; this.cropRight = cropRight; this.cropBottom = cropBottom; this.cropTop = cropTop; this.requestedAspectRatio = requestedAspectRatio; - this.presentationStrategy = presentationStrategy; + this.layout = layout; outputWidth = C.LENGTH_UNSET; outputHeight = C.LENGTH_UNSET; @@ -326,7 +364,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { @RequiresNonNull("transformationMatrix") private void applyAspectRatio() { float inputAspectRatio = (float) outputWidth / outputHeight; - if (presentationStrategy == SCALE_TO_FIT) { + if (layout == LAYOUT_SCALE_TO_FIT) { if (requestedAspectRatio > inputAspectRatio) { transformationMatrix.setScale(inputAspectRatio / requestedAspectRatio, 1f); outputWidth = Math.round(outputHeight * requestedAspectRatio); @@ -334,7 +372,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { transformationMatrix.setScale(1f, requestedAspectRatio / inputAspectRatio); outputHeight = Math.round(outputWidth / requestedAspectRatio); } - } else if (presentationStrategy == SCALE_TO_FIT_WITH_CROP) { + } else if (layout == LAYOUT_SCALE_TO_FIT_WITH_CROP) { if (requestedAspectRatio > inputAspectRatio) { transformationMatrix.setScale(1f, requestedAspectRatio / inputAspectRatio); outputHeight = Math.round(outputWidth / requestedAspectRatio); @@ -342,7 +380,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { transformationMatrix.setScale(inputAspectRatio / requestedAspectRatio, 1f); outputWidth = Math.round(outputHeight * requestedAspectRatio); } - } else if (presentationStrategy == STRETCH_TO_FIT) { + } else if (layout == LAYOUT_STRETCH_TO_FIT) { if (requestedAspectRatio > inputAspectRatio) { outputWidth = Math.round(outputHeight * requestedAspectRatio); } else { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java index c172787255..68e58f17a0 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ScaleToFitFrameProcessor.java @@ -31,9 +31,12 @@ 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. All input frames' pixels will be - * preserved, potentially changing the width and height of the frame by scaling dimensions to fit. - * The background color will default to black. + * Applies a simple rotation and/or scale 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. + * + *

The background color of the output frame will be black. */ @UnstableApi public final class ScaleToFitFrameProcessor implements GlFrameProcessor { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java index 2e0473b646..0441f9619d 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java @@ -102,7 +102,8 @@ public final class TransformationRequest { * Sets the x and y axis scaling factors to apply to each frame's width and height, stretching * the video along these axes appropriately. * - *

The values default to 1, which corresponds to not scaling along both axes. + *

The default value for {@code scaleX} and {@code scaleY}, 1, corresponds to not scaling + * along the x and y axes, respectively. * * @param scaleX The multiplier by which the frame will scale horizontally, along the x-axis. * @param scaleY The multiplier by which the frame will scale vertically, along the y-axis. @@ -139,7 +140,7 @@ public final class TransformationRequest { * *

For example, a 1920x1440 video can be scaled to 640x480 by calling setResolution(480). * - *

The default value {@link C#LENGTH_UNSET} leaves the width and height unchanged unless + *

The default value, {@link C#LENGTH_UNSET}, leaves the width and height unchanged unless * {@linkplain #setScale(float,float) scaling} or @linkplain #setRotationDegrees(float) * rotation} are requested. * diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java index 0408f2438c..e311820253 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationFrameProcessorTest.java @@ -175,7 +175,7 @@ public final class PresentationFrameProcessorTest { float aspectRatio = 2f; PresentationFrameProcessor presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(aspectRatio, PresentationFrameProcessor.SCALE_TO_FIT) + .setAspectRatio(aspectRatio, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) .build(); presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight); @@ -194,7 +194,7 @@ public final class PresentationFrameProcessorTest { int requestedHeight = 100; PresentationFrameProcessor presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(aspectRatio, PresentationFrameProcessor.SCALE_TO_FIT) + .setAspectRatio(aspectRatio, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT) .setResolution(requestedHeight) .build(); @@ -210,7 +210,7 @@ public final class PresentationFrameProcessorTest { public void getOutputSize_setAspectRatioAndCrop_throwsIllegalStateException() { PresentationFrameProcessor.Builder presentationFrameProcessor = new PresentationFrameProcessor.Builder() - .setAspectRatio(/* aspectRatio= */ 2f, PresentationFrameProcessor.SCALE_TO_FIT); + .setAspectRatio(/* aspectRatio= */ 2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT); assertThrows( IllegalStateException.class, @@ -229,7 +229,7 @@ public final class PresentationFrameProcessorTest { IllegalStateException.class, () -> presentationFrameProcessor.setAspectRatio( - /* aspectRatio= */ 2f, PresentationFrameProcessor.SCALE_TO_FIT)); + /* aspectRatio= */ 2f, PresentationFrameProcessor.LAYOUT_SCALE_TO_FIT)); } @Test