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
This commit is contained in:
hschlueter 2022-05-26 12:52:45 +00:00 committed by Marc Baechinger
parent 8f3b4f590f
commit 0eaf3d30c8
17 changed files with 196 additions and 194 deletions

View File

@ -32,19 +32,20 @@ import androidx.media3.common.C;
import androidx.media3.common.util.GlProgram; import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.GlUtil;
import androidx.media3.transformer.FrameProcessingException; import androidx.media3.transformer.FrameProcessingException;
import androidx.media3.transformer.GlFrameProcessor; import androidx.media3.transformer.SingleFrameGlTextureProcessor;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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.
* *
* <p>The bitmap is drawn using an Android {@link Canvas}. * <p>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 // TODO(b/227625365): Delete this class and use a texture processor from the Transformer library,
// overlaying a bitmap and text is supported in Transformer. // once overlaying a bitmap and text is supported in Transformer.
/* package */ final class BitmapOverlayFrameProcessor implements GlFrameProcessor { /* package */ final class BitmapOverlayProcessor implements SingleFrameGlTextureProcessor {
static { static {
GlUtil.glAssertionsEnabled = true; GlUtil.glAssertionsEnabled = true;
} }
@ -65,7 +66,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private @MonotonicNonNull Bitmap logoBitmap; private @MonotonicNonNull Bitmap logoBitmap;
private @MonotonicNonNull GlProgram glProgram; private @MonotonicNonNull GlProgram glProgram;
public BitmapOverlayFrameProcessor() { public BitmapOverlayProcessor() {
paint = new Paint(); paint = new Paint();
paint.setTextSize(64); paint.setTextSize(64);
paint.setAntiAlias(true); paint.setAntiAlias(true);

View File

@ -24,15 +24,15 @@ import android.util.Size;
import androidx.media3.common.util.GlProgram; import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.GlUtil;
import androidx.media3.transformer.FrameProcessingException; import androidx.media3.transformer.FrameProcessingException;
import androidx.media3.transformer.GlFrameProcessor; import androidx.media3.transformer.SingleFrameGlTextureProcessor;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* A {@link GlFrameProcessor} that periodically dims the frames such that pixels are darker the * A {@link SingleFrameGlTextureProcessor} that periodically dims the frames such that pixels are
* further they are away from the frame center. * darker the further they are away from the frame center.
*/ */
/* package */ final class PeriodicVignetteFrameProcessor implements GlFrameProcessor { /* package */ final class PeriodicVignetteProcessor implements SingleFrameGlTextureProcessor {
static { static {
GlUtil.glAssertionsEnabled = true; 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 maxInnerRadius The upper bound of the radius that is unaffected by the effect.
* @param outerRadius The radius after which all pixels are black. * @param outerRadius The radius after which all pixels are black.
*/ */
public PeriodicVignetteFrameProcessor( public PeriodicVignetteProcessor(
float centerX, float centerY, float minInnerRadius, float maxInnerRadius, float outerRadius) { float centerX, float centerY, float minInnerRadius, float maxInnerRadius, float outerRadius) {
checkArgument(minInnerRadius <= maxInnerRadius); checkArgument(minInnerRadius <= maxInnerRadius);
checkArgument(maxInnerRadius <= outerRadius); checkArgument(maxInnerRadius <= outerRadius);

View File

@ -42,8 +42,8 @@ import androidx.media3.exoplayer.util.DebugTextViewHelper;
import androidx.media3.transformer.DefaultEncoderFactory; import androidx.media3.transformer.DefaultEncoderFactory;
import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.EncoderSelector;
import androidx.media3.transformer.GlEffect; import androidx.media3.transformer.GlEffect;
import androidx.media3.transformer.GlFrameProcessor;
import androidx.media3.transformer.ProgressHolder; import androidx.media3.transformer.ProgressHolder;
import androidx.media3.transformer.SingleFrameGlTextureProcessor;
import androidx.media3.transformer.TransformationException; import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.TransformationResult; import androidx.media3.transformer.TransformationResult;
@ -253,14 +253,13 @@ public final class TransformerActivity extends AppCompatActivity {
} }
if (selectedEffects[1]) { if (selectedEffects[1]) {
try { try {
Class<?> clazz = Class<?> clazz = Class.forName("androidx.media3.demo.transformer.MediaPipeProcessor");
Class.forName("androidx.media3.demo.transformer.MediaPipeFrameProcessor");
Constructor<?> constructor = Constructor<?> constructor =
clazz.getConstructor(String.class, String.class, String.class); clazz.getConstructor(String.class, String.class, String.class);
effects.add( effects.add(
() -> { () -> {
try { try {
return (GlFrameProcessor) return (SingleFrameGlTextureProcessor)
constructor.newInstance( constructor.newInstance(
/* graphName= */ "edge_detector_mediapipe_graph.binarypb", /* graphName= */ "edge_detector_mediapipe_graph.binarypb",
/* inputStreamName= */ "input_video", /* inputStreamName= */ "input_video",
@ -277,7 +276,7 @@ public final class TransformerActivity extends AppCompatActivity {
if (selectedEffects[2]) { if (selectedEffects[2]) {
effects.add( effects.add(
() -> () ->
new PeriodicVignetteFrameProcessor( new PeriodicVignetteProcessor(
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X), bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X),
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_Y), bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_Y),
/* minInnerRadius= */ bundle.getFloat( /* minInnerRadius= */ bundle.getFloat(
@ -290,7 +289,7 @@ public final class TransformerActivity extends AppCompatActivity {
effects.add(MatrixTransformationFactory.createSpin3dEffect()); effects.add(MatrixTransformationFactory.createSpin3dEffect());
} }
if (selectedEffects[4]) { if (selectedEffects[4]) {
effects.add(BitmapOverlayFrameProcessor::new); effects.add(BitmapOverlayProcessor::new);
} }
if (selectedEffects[5]) { if (selectedEffects[5]) {
effects.add(MatrixTransformationFactory.createZoomInTransition()); effects.add(MatrixTransformationFactory.createZoomInTransition());

View File

@ -27,7 +27,7 @@ import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.LibraryLoader; import androidx.media3.common.util.LibraryLoader;
import androidx.media3.transformer.FrameProcessingException; 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.components.FrameProcessor;
import com.google.mediapipe.framework.AndroidAssetUtil; import com.google.mediapipe.framework.AndroidAssetUtil;
import com.google.mediapipe.framework.AppTextureFrame; 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 * Runs a MediaPipe graph on input frames. The implementation is currently limited to graphs that
* can immediately produce one output frame per input frame. * 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 = private static final LibraryLoader LOADER =
new LibraryLoader("mediapipe_jni") { new LibraryLoader("mediapipe_jni") {
@ -77,14 +77,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private @MonotonicNonNull RuntimeException frameProcessorPendingError; 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 graphName Name of a MediaPipe graph asset to load.
* @param inputStreamName Name of the input video stream in the graph. * @param inputStreamName Name of the input video stream in the graph.
* @param outputStreamName Name of the input video stream in the graph. * @param outputStreamName Name of the input video stream in the graph.
*/ */
public MediaPipeFrameProcessor( public MediaPipeProcessor(String graphName, String inputStreamName, String outputStreamName) {
String graphName, String inputStreamName, String outputStreamName) {
checkState(LOADER.isAvailable()); checkState(LOADER.isAvailable());
this.graphName = graphName; this.graphName = graphName;
this.inputStreamName = inputStreamName; 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. // 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 // 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 // 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(); Thread.currentThread().interrupt();
return; return;
} }

View File

@ -40,7 +40,7 @@ import java.nio.ByteBuffer;
/** /**
* Utilities for instrumentation tests for the {@link FrameProcessorChain} and {@link * Utilities for instrumentation tests for the {@link FrameProcessorChain} and {@link
* GlFrameProcessor GlFrameProcessors}. * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors}.
*/ */
public class BitmapTestUtil { public class BitmapTestUtil {
@ -50,15 +50,15 @@ public class BitmapTestUtil {
* Maximum allowed average pixel difference between the expected and actual edited images in pixel * 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 * 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 * 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 * distortions introduced by changes in the behavior of the {@link SingleFrameGlTextureProcessor
* GlFrameProcessors} will cause the test to fail. * SingleFrameGlTextureProcessors} will cause the test to fail.
* *
* <p>To run pixel difference-based tests on physical devices, please use a value of 5f, rather * <p>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 * 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 * 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 * 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 * 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; public static final float MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE = 0.1f;

View File

@ -41,10 +41,10 @@ public final class FrameProcessorChainTest {
public void getOutputSize_noOperation_returnsInputSize() throws Exception { public void getOutputSize_noOperation_returnsInputSize() throws Exception {
Size inputSize = new Size(200, 100); Size inputSize = new Size(200, 100);
FrameProcessorChain frameProcessorChain = FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors( createFrameProcessorChainWithFakeTextureProcessors(
/* pixelWidthHeightRatio= */ 1f, /* pixelWidthHeightRatio= */ 1f,
inputSize, inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of()); /* textureProcessorOutputSizes= */ ImmutableList.of());
Size outputSize = frameProcessorChain.getOutputSize(); Size outputSize = frameProcessorChain.getOutputSize();
@ -56,10 +56,10 @@ public final class FrameProcessorChainTest {
public void getOutputSize_withWidePixels_returnsWiderOutputSize() throws Exception { public void getOutputSize_withWidePixels_returnsWiderOutputSize() throws Exception {
Size inputSize = new Size(200, 100); Size inputSize = new Size(200, 100);
FrameProcessorChain frameProcessorChain = FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors( createFrameProcessorChainWithFakeTextureProcessors(
/* pixelWidthHeightRatio= */ 2f, /* pixelWidthHeightRatio= */ 2f,
inputSize, inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of()); /* textureProcessorOutputSizes= */ ImmutableList.of());
Size outputSize = frameProcessorChain.getOutputSize(); Size outputSize = frameProcessorChain.getOutputSize();
@ -71,10 +71,10 @@ public final class FrameProcessorChainTest {
public void getOutputSize_withTallPixels_returnsTallerOutputSize() throws Exception { public void getOutputSize_withTallPixels_returnsTallerOutputSize() throws Exception {
Size inputSize = new Size(200, 100); Size inputSize = new Size(200, 100);
FrameProcessorChain frameProcessorChain = FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors( createFrameProcessorChainWithFakeTextureProcessors(
/* pixelWidthHeightRatio= */ .5f, /* pixelWidthHeightRatio= */ .5f,
inputSize, inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of()); /* textureProcessorOutputSizes= */ ImmutableList.of());
Size outputSize = frameProcessorChain.getOutputSize(); Size outputSize = frameProcessorChain.getOutputSize();
@ -83,32 +83,32 @@ public final class FrameProcessorChainTest {
} }
@Test @Test
public void getOutputSize_withOneFrameProcessor_returnsItsOutputSize() throws Exception { public void getOutputSize_withOneTextureProcessor_returnsItsOutputSize() throws Exception {
Size inputSize = new Size(200, 100); Size inputSize = new Size(200, 100);
Size frameProcessorOutputSize = new Size(300, 250); Size textureProcessorOutputSize = new Size(300, 250);
FrameProcessorChain frameProcessorChain = FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors( createFrameProcessorChainWithFakeTextureProcessors(
/* pixelWidthHeightRatio= */ 1f, /* pixelWidthHeightRatio= */ 1f,
inputSize, inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of(frameProcessorOutputSize)); /* textureProcessorOutputSizes= */ ImmutableList.of(textureProcessorOutputSize));
Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize();
assertThat(frameProcessorChainOutputSize).isEqualTo(frameProcessorOutputSize); assertThat(frameProcessorChainOutputSize).isEqualTo(textureProcessorOutputSize);
assertThat(frameProcessingException.get()).isNull(); assertThat(frameProcessingException.get()).isNull();
} }
@Test @Test
public void getOutputSize_withThreeFrameProcessors_returnsLastOutputSize() throws Exception { public void getOutputSize_withThreeTextureProcessors_returnsLastOutputSize() throws Exception {
Size inputSize = new Size(200, 100); Size inputSize = new Size(200, 100);
Size outputSize1 = new Size(300, 250); Size outputSize1 = new Size(300, 250);
Size outputSize2 = new Size(400, 244); Size outputSize2 = new Size(400, 244);
Size outputSize3 = new Size(150, 160); Size outputSize3 = new Size(150, 160);
FrameProcessorChain frameProcessorChain = FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors( createFrameProcessorChainWithFakeTextureProcessors(
/* pixelWidthHeightRatio= */ 1f, /* pixelWidthHeightRatio= */ 1f,
inputSize, inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of( /* textureProcessorOutputSizes= */ ImmutableList.of(
outputSize1, outputSize2, outputSize3)); outputSize1, outputSize2, outputSize3));
Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize();
@ -117,12 +117,12 @@ public final class FrameProcessorChainTest {
assertThat(frameProcessingException.get()).isNull(); assertThat(frameProcessingException.get()).isNull();
} }
private FrameProcessorChain createFrameProcessorChainWithFakeFrameProcessors( private FrameProcessorChain createFrameProcessorChainWithFakeTextureProcessors(
float pixelWidthHeightRatio, Size inputSize, List<Size> frameProcessorOutputSizes) float pixelWidthHeightRatio, Size inputSize, List<Size> textureProcessorOutputSizes)
throws FrameProcessingException { throws FrameProcessingException {
ImmutableList.Builder<GlEffect> effects = new ImmutableList.Builder<>(); ImmutableList.Builder<GlEffect> effects = new ImmutableList.Builder<>();
for (Size element : frameProcessorOutputSizes) { for (Size element : textureProcessorOutputSizes) {
effects.add(() -> new FakeFrameProcessor(element)); effects.add(() -> new FakeTextureProcessor(element));
} }
return FrameProcessorChain.create( return FrameProcessorChain.create(
getApplicationContext(), getApplicationContext(),
@ -134,11 +134,11 @@ public final class FrameProcessorChainTest {
/* enableExperimentalHdrEditing= */ false); /* enableExperimentalHdrEditing= */ false);
} }
private static class FakeFrameProcessor implements GlFrameProcessor { private static class FakeTextureProcessor implements SingleFrameGlTextureProcessor {
private final Size outputSize; private final Size outputSize;
private FakeFrameProcessor(Size outputSize) { private FakeTextureProcessor(Size outputSize) {
this.outputSize = outputSize; this.outputSize = outputSize;
} }

View File

@ -34,7 +34,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/** /**
* Pixel test for frame processing via {@link MatrixTransformationFrameProcessor}. * Pixel test for texture processing via {@link MatrixTransformationProcessor}.
* *
* <p>Expected images are taken from an emulator, so tests on different emulators or physical * <p>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 * 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}. * as recommended in {@link FrameProcessorChainPixelTest}.
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class MatrixTransformationFrameProcessorPixelTest { public final class MatrixTransformationProcessorPixelTest {
public static final String ORIGINAL_PNG_ASSET_PATH = public static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/original.png"; "media/bitmap/sample_mp4_first_frame/original.png";
public static final String TRANSLATE_RIGHT_PNG_ASSET_PATH = 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 EGLDisplay eglDisplay = GlUtil.createEglDisplay();
private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay); private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay);
private @MonotonicNonNull GlFrameProcessor matrixTransformationFrameProcessor; private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTransformationProcessor;
private int inputTexId; private int inputTexId;
private int outputTexId; private int outputTexId;
private int width; private int width;
@ -80,8 +80,8 @@ public final class MatrixTransformationFrameProcessorPixelTest {
@After @After
public void release() { public void release() {
if (matrixTransformationFrameProcessor != null) { if (matrixTransformationProcessor != null) {
matrixTransformationFrameProcessor.release(); matrixTransformationProcessor.release();
} }
GlUtil.destroyEglContext(eglDisplay, eglContext); GlUtil.destroyEglContext(eglDisplay, eglContext);
} }
@ -90,13 +90,12 @@ public final class MatrixTransformationFrameProcessorPixelTest {
public void drawFrame_noEdits_producesExpectedOutput() throws Exception { public void drawFrame_noEdits_producesExpectedOutput() throws Exception {
String testId = "drawFrame_noEdits"; String testId = "drawFrame_noEdits";
Matrix identityMatrix = new Matrix(); Matrix identityMatrix = new Matrix();
matrixTransformationFrameProcessor = matrixTransformationProcessor =
new MatrixTransformationFrameProcessor((long presentationTimeUs) -> identityMatrix); new MatrixTransformationProcessor((long presentationTimeUs) -> identityMatrix);
matrixTransformationFrameProcessor.initialize( matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height);
getApplicationContext(), inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH);
matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
@ -114,13 +113,12 @@ public final class MatrixTransformationFrameProcessorPixelTest {
String testId = "drawFrame_translateRight"; String testId = "drawFrame_translateRight";
Matrix translateRightMatrix = new Matrix(); Matrix translateRightMatrix = new Matrix();
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
matrixTransformationFrameProcessor = matrixTransformationProcessor =
new MatrixTransformationFrameProcessor((long presentationTimeUs) -> translateRightMatrix); new MatrixTransformationProcessor((long presentationTimeUs) -> translateRightMatrix);
matrixTransformationFrameProcessor.initialize( matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height);
getApplicationContext(), inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH);
matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
@ -138,13 +136,12 @@ public final class MatrixTransformationFrameProcessorPixelTest {
String testId = "drawFrame_scaleNarrow"; String testId = "drawFrame_scaleNarrow";
Matrix scaleNarrowMatrix = new Matrix(); Matrix scaleNarrowMatrix = new Matrix();
scaleNarrowMatrix.postScale(.5f, 1.2f); scaleNarrowMatrix.postScale(.5f, 1.2f);
matrixTransformationFrameProcessor = matrixTransformationProcessor =
new MatrixTransformationFrameProcessor((long presentationTimeUs) -> scaleNarrowMatrix); new MatrixTransformationProcessor((long presentationTimeUs) -> scaleNarrowMatrix);
matrixTransformationFrameProcessor.initialize( matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height);
getApplicationContext(), inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(SCALE_NARROW_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(SCALE_NARROW_PNG_ASSET_PATH);
matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
@ -162,13 +159,12 @@ public final class MatrixTransformationFrameProcessorPixelTest {
String testId = "drawFrame_rotate90"; String testId = "drawFrame_rotate90";
Matrix rotate90Matrix = new Matrix(); Matrix rotate90Matrix = new Matrix();
rotate90Matrix.postRotate(/* degrees= */ 90); rotate90Matrix.postRotate(/* degrees= */ 90);
matrixTransformationFrameProcessor = matrixTransformationProcessor =
new MatrixTransformationFrameProcessor((long presentationTimeUs) -> rotate90Matrix); new MatrixTransformationProcessor((long presentationTimeUs) -> rotate90Matrix);
matrixTransformationFrameProcessor.initialize( matrixTransformationProcessor.initialize(getApplicationContext(), inputTexId, width, height);
getApplicationContext(), inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_PNG_ASSET_PATH);
matrixTransformationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); matrixTransformationProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height); BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);

View File

@ -35,7 +35,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/** /**
* Pixel test for frame processing via {@link Presentation}. * Pixel test for texture processing via {@link Presentation}.
* *
* <p>Expected images are taken from an emulator, so tests on different emulators or physical * <p>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 * 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 EGLDisplay eglDisplay = GlUtil.createEglDisplay();
private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay); private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay);
private @MonotonicNonNull GlFrameProcessor presentationFrameProcessor; private @MonotonicNonNull SingleFrameGlTextureProcessor presentationTextureProcessor;
private @MonotonicNonNull EGLSurface placeholderEglSurface; private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId; private int inputTexId;
private int outputTexId; private int outputTexId;
@ -88,8 +88,8 @@ public final class PresentationPixelTest {
@After @After
public void release() { public void release() {
if (presentationFrameProcessor != null) { if (presentationTextureProcessor != null) {
presentationFrameProcessor.release(); presentationTextureProcessor.release();
} }
GlUtil.destroyEglContext(eglDisplay, eglContext); GlUtil.destroyEglContext(eglDisplay, eglContext);
} }
@ -97,14 +97,14 @@ public final class PresentationPixelTest {
@Test @Test
public void drawFrame_noEdits_producesExpectedOutput() throws Exception { public void drawFrame_noEdits_producesExpectedOutput() throws Exception {
String testId = "drawFrame_noEdits"; String testId = "drawFrame_noEdits";
presentationFrameProcessor = new Presentation.Builder().build().toGlFrameProcessor(); presentationTextureProcessor = new Presentation.Builder().build().toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -121,18 +121,18 @@ public final class PresentationPixelTest {
@Test @Test
public void drawFrame_cropSmaller_producesExpectedOutput() throws Exception { public void drawFrame_cropSmaller_producesExpectedOutput() throws Exception {
String testId = "drawFrame_cropSmaller"; String testId = "drawFrame_cropSmaller";
GlFrameProcessor presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setCrop(/* left= */ -.9f, /* right= */ .1f, /* bottom= */ -1f, /* top= */ .5f) .setCrop(/* left= */ -.9f, /* right= */ .1f, /* bottom= */ -1f, /* top= */ .5f)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_SMALLER_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_SMALLER_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -149,18 +149,18 @@ public final class PresentationPixelTest {
@Test @Test
public void drawFrame_cropLarger_producesExpectedOutput() throws Exception { public void drawFrame_cropLarger_producesExpectedOutput() throws Exception {
String testId = "drawFrame_cropSmaller"; String testId = "drawFrame_cropSmaller";
GlFrameProcessor presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setCrop(/* left= */ -2f, /* right= */ 2f, /* bottom= */ -1f, /* top= */ 2f) .setCrop(/* left= */ -2f, /* right= */ 2f, /* bottom= */ -1f, /* top= */ 2f)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_LARGER_PNG_ASSET_PATH); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_LARGER_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -178,19 +178,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFit_narrow_producesExpectedOutput() public void drawFrame_changeAspectRatio_scaleToFit_narrow_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow"; String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT) .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_NARROW_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_NARROW_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -208,19 +208,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFit_wide_producesExpectedOutput() public void drawFrame_changeAspectRatio_scaleToFit_wide_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFit_wide"; String testId = "drawFrame_changeAspectRatio_scaleToFit_wide";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT) .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WIDE_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WIDE_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -238,19 +238,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow_producesExpectedOutput() public void drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow"; String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_NARROW_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_NARROW_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -268,19 +268,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFitWithCrop_wide_producesExpectedOutput() public void drawFrame_changeAspectRatio_scaleToFitWithCrop_wide_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide"; String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_WIDE_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_WIDE_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -298,19 +298,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_stretchToFit_narrow_producesExpectedOutput() public void drawFrame_changeAspectRatio_stretchToFit_narrow_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow"; String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(1f, Presentation.LAYOUT_STRETCH_TO_FIT) .setAspectRatio(1f, Presentation.LAYOUT_STRETCH_TO_FIT)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_NARROW_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_NARROW_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());
@ -328,19 +328,19 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_stretchToFit_wide_producesExpectedOutput() public void drawFrame_changeAspectRatio_stretchToFit_wide_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "drawFrame_changeAspectRatio_stretchToFit_wide"; String testId = "drawFrame_changeAspectRatio_stretchToFit_wide";
presentationFrameProcessor = presentationTextureProcessor =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(2f, Presentation.LAYOUT_STRETCH_TO_FIT) .setAspectRatio(2f, Presentation.LAYOUT_STRETCH_TO_FIT)
.build() .build()
.toGlFrameProcessor(); .toGlTextureProcessor();
presentationFrameProcessor.initialize( presentationTextureProcessor.initialize(
getApplicationContext(), inputTexId, inputWidth, inputHeight); getApplicationContext(), inputTexId, inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationTextureProcessor.getOutputSize();
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_WIDE_PNG_ASSET_PATH); BitmapTestUtil.readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_WIDE_PNG_ASSET_PATH);
presentationFrameProcessor.drawFrame(/* presentationTimeUs= */ 0); presentationTextureProcessor.drawFrame(/* presentationTimeUs= */ 0);
Bitmap actualBitmap = Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer( BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.getWidth(), outputSize.getHeight()); outputSize.getWidth(), outputSize.getHeight());

View File

@ -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.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.content.Context;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.util.Size; import android.util.Size;
import androidx.media3.common.C; import androidx.media3.common.C;
@ -77,8 +76,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* *
* <p>Return values may be {@code 0} or {@code 90} degrees. * <p>Return values may be {@code 0} or {@code 90} degrees.
* *
* <p>The frame processor must be {@linkplain GlFrameProcessor#initialize(Context, int, int, int) * <p>Should only be called after {@linkplain #configure(int, int) configuration}.
* initialized}.
*/ */
public int getOutputRotationDegrees() { public int getOutputRotationDegrees() {
checkState( checkState(

View File

@ -27,7 +27,7 @@ import java.io.IOException;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Copies frames from an external texture and applies color transformations for HDR if needed. */ /** 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 { static {
GlUtil.glAssertionsEnabled = true; GlUtil.glAssertionsEnabled = true;
@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private @MonotonicNonNull Size size; private @MonotonicNonNull Size size;
private @MonotonicNonNull GlProgram glProgram; private @MonotonicNonNull GlProgram glProgram;
public ExternalCopyFrameProcessor(boolean enableExperimentalHdrEditing) { public ExternalTextureProcessor(boolean enableExperimentalHdrEditing) {
this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; this.enableExperimentalHdrEditing = enableExperimentalHdrEditing;
} }

View File

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

View File

@ -18,14 +18,16 @@ package androidx.media3.transformer;
import androidx.media3.common.util.UnstableApi; 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.
* *
* <p>Implementations contain information specifying the effect and can be {@linkplain * <p>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 @UnstableApi
public interface GlEffect { public interface GlEffect {
/** Returns a {@link GlFrameProcessor} that applies the the effect. */ /** Returns a {@link SingleFrameGlTextureProcessor} that applies the effect. */
GlFrameProcessor toGlFrameProcessor(); // TODO(b/227625423): use GlTextureProcessor here once this interface exists.
SingleFrameGlTextureProcessor toGlTextureProcessor();
} }

View File

@ -49,7 +49,7 @@ public interface GlMatrixTransformation extends GlEffect {
float[] getGlMatrixArray(long presentationTimeUs); float[] getGlMatrixArray(long presentationTimeUs);
@Override @Override
default GlFrameProcessor toGlFrameProcessor() { default SingleFrameGlTextureProcessor toGlTextureProcessor() {
return new MatrixTransformationFrameProcessor(this); return new MatrixTransformationProcessor(this);
} }
} }

View File

@ -43,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*/ */
@UnstableApi @UnstableApi
@SuppressWarnings("FunctionalInterfaceClash") // b/228192298 @SuppressWarnings("FunctionalInterfaceClash") // b/228192298
/* package */ final class MatrixTransformationFrameProcessor implements GlFrameProcessor { /* package */ final class MatrixTransformationProcessor implements SingleFrameGlTextureProcessor {
static { static {
GlUtil.glAssertionsEnabled = true; GlUtil.glAssertionsEnabled = true;
@ -93,7 +93,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* @param matrixTransformation A {@link MatrixTransformation} that specifies the transformation * @param matrixTransformation A {@link MatrixTransformation} that specifies the transformation
* matrix to use for each frame. * matrix to use for each frame.
*/ */
public MatrixTransformationFrameProcessor(MatrixTransformation matrixTransformation) { public MatrixTransformationProcessor(MatrixTransformation matrixTransformation) {
this(ImmutableList.of(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 * @param matrixTransformation A {@link GlMatrixTransformation} that specifies the transformation
* matrix to use for each frame. * matrix to use for each frame.
*/ */
public MatrixTransformationFrameProcessor(GlMatrixTransformation matrixTransformation) { public MatrixTransformationProcessor(GlMatrixTransformation matrixTransformation) {
this(ImmutableList.of(matrixTransformation)); this(ImmutableList.of(matrixTransformation));
} }
@ -113,7 +113,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* @param matrixTransformations The {@link GlMatrixTransformation GlMatrixTransformations} to * @param matrixTransformations The {@link GlMatrixTransformation GlMatrixTransformations} to
* apply to each frame in order. * apply to each frame in order.
*/ */
public MatrixTransformationFrameProcessor( public MatrixTransformationProcessor(
ImmutableList<GlMatrixTransformation> matrixTransformations) { ImmutableList<GlMatrixTransformation> matrixTransformations) {
this.matrixTransformations = matrixTransformations; this.matrixTransformations = matrixTransformations;

View File

@ -34,7 +34,9 @@ import java.io.IOException;
* </ol> * </ol>
*/ */
@UnstableApi @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 * 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)}. * Returns the output {@link Size} of frames processed through {@link #drawFrame(long)}.
* *
* <p>This method may only be called after the frame processor has been {@link * <p>This method may only be called after the texture processor has been {@link
* #initialize(Context, int, int, int) initialized}. * #initialize(Context, int, int, int) initialized}.
*/ */
Size getOutputSize(); Size getOutputSize();
@ -62,7 +64,7 @@ public interface GlFrameProcessor {
/** /**
* Draws one frame. * Draws one frame.
* *
* <p>This method may only be called after the frame processor has been {@link * <p>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 * #initialize(Context, int, int, int) initialized}. The caller is responsible for focussing the
* correct render target before calling this method. * correct render target before calling this method.
* *

View File

@ -27,7 +27,7 @@ import org.junit.runner.RunWith;
/** /**
* Unit tests for {@link Presentation}. * Unit tests for {@link Presentation}.
* *
* <p>See {@code PresentationFrameProcessorPixelTest} for pixel tests testing {@link Presentation}. * <p>See {@code PresentationPixelTest} for pixel tests testing {@link Presentation}.
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class PresentationTest { public final class PresentationTest {
@ -161,27 +161,27 @@ public final class PresentationTest {
@Test @Test
public void configure_setAspectRatioAndCrop_throwsIllegalStateException() { public void configure_setAspectRatioAndCrop_throwsIllegalStateException() {
Presentation.Builder presentationFrameProcessor = Presentation.Builder presentationBuilder =
new Presentation.Builder() new Presentation.Builder()
.setAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT); .setAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT);
assertThrows( assertThrows(
IllegalStateException.class, IllegalStateException.class,
() -> () ->
presentationFrameProcessor.setCrop( presentationBuilder.setCrop(
/* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f)); /* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f));
} }
@Test @Test
public void configure_setCropAndAspectRatio_throwsIllegalStateException() { public void configure_setCropAndAspectRatio_throwsIllegalStateException() {
Presentation.Builder presentationFrameProcessor = Presentation.Builder presentationBuilder =
new Presentation.Builder() new Presentation.Builder()
.setCrop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f); .setCrop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ .5f, /* top= */ 1f);
assertThrows( assertThrows(
IllegalStateException.class, IllegalStateException.class,
() -> () ->
presentationFrameProcessor.setAspectRatio( presentationBuilder.setAspectRatio(
/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT)); /* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT));
} }
} }

View File

@ -25,8 +25,8 @@ import org.junit.runner.RunWith;
/** /**
* Unit tests for {@link ScaleToFitTransformation}. * Unit tests for {@link ScaleToFitTransformation}.
* *
* <p>See {@code MatrixTransformationFrameProcessorPixelTest} for pixel tests testing {@link * <p>See {@code MatrixTransformationPixelTest} for pixel tests testing {@link
* MatrixTransformationFrameProcessor} given a transformation matrix. * MatrixTransformationProcessor} given a transformation matrix.
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class ScaleToFitTransformationTest { public final class ScaleToFitTransformationTest {