Commit 27d44e86 by huangdarwin Committed by Rohit Singh

Effect: Create GlEffectsFrameProcessorTestRunner.

Makes GlEffectsFrameProcessorPixelTest slightly more modular in preparation for
copying this into transformer/mh.

Refactoring change. No functional change intended.

PiperOrigin-RevId: 501902223
parent eb496660
...@@ -24,7 +24,6 @@ import static com.google.android.exoplayer2.testutil.BitmapPixelTestUtil.readBit ...@@ -24,7 +24,6 @@ import static com.google.android.exoplayer2.testutil.BitmapPixelTestUtil.readBit
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
...@@ -47,9 +46,11 @@ import com.google.android.exoplayer2.util.SurfaceInfo; ...@@ -47,9 +46,11 @@ import com.google.android.exoplayer2.util.SurfaceInfo;
import com.google.android.exoplayer2.video.ColorInfo; import com.google.android.exoplayer2.video.ColorInfo;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.After; import org.junit.After;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
...@@ -103,36 +104,20 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -103,36 +104,20 @@ public final class GlEffectsFrameProcessorPixelTest {
/** Input PQ video of which we only use the first frame. */ /** Input PQ video of which we only use the first frame. */
private static final String INPUT_PQ_MP4_ASSET_STRING = "media/mp4/hdr10-1080p.mp4"; private static final String INPUT_PQ_MP4_ASSET_STRING = "media/mp4/hdr10-1080p.mp4";
/** private @MonotonicNonNull GlEffectsFrameProcessorTestRunner glEffectsFrameProcessorTestRunner;
* Time to wait for the decoded frame to populate the {@link GlEffectsFrameProcessor} instance's
* input surface and the {@link GlEffectsFrameProcessor} to finish processing the frame, in
* milliseconds.
*/
private static final int FRAME_PROCESSING_WAIT_MS = 5000;
/** The ratio of width over height, for each pixel in a frame. */
private static final float DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO = 1;
private final AtomicReference<FrameProcessingException> frameProcessingException =
new AtomicReference<>();
private @MonotonicNonNull GlEffectsFrameProcessor glEffectsFrameProcessor;
private volatile @MonotonicNonNull ImageReader outputImageReader;
private volatile boolean frameProcessingEnded;
@After @After
public void release() { public void release() {
if (glEffectsFrameProcessor != null) { checkNotNull(glEffectsFrameProcessorTestRunner).release();
glEffectsFrameProcessor.release();
}
} }
@Test @Test
public void processData_noEdits_producesExpectedOutput() throws Exception { public void processData_noEdits_producesExpectedOutput() throws Exception {
String testId = "processData_noEdits"; String testId = "processData_noEdits";
setUpAndPrepareFirstFrame(); glEffectsFrameProcessorTestRunner = new GlEffectsFrameProcessorTestRunner.Builder().build();
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -144,10 +129,13 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -144,10 +129,13 @@ public final class GlEffectsFrameProcessorPixelTest {
@Test @Test
public void processData_noEditsWithCache_leavesFrameUnchanged() throws Exception { public void processData_noEditsWithCache_leavesFrameUnchanged() throws Exception {
String testId = "processData_noEditsWithCache"; String testId = "processData_noEditsWithCache";
setUpAndPrepareFirstFrame(new FrameCache(/* capacity= */ 5)); glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(new FrameCache(/* capacity= */ 5))
.build();
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -159,15 +147,11 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -159,15 +147,11 @@ public final class GlEffectsFrameProcessorPixelTest {
@Test @Test
public void processData_withPixelWidthHeightRatio_producesExpectedOutput() throws Exception { public void processData_withPixelWidthHeightRatio_producesExpectedOutput() throws Exception {
String testId = "processData_withPixelWidthHeightRatio"; String testId = "processData_withPixelWidthHeightRatio";
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
INPUT_SDR_MP4_ASSET_STRING, new GlEffectsFrameProcessorTestRunner.Builder().setPixelWidthHeightRatio(2f).build();
/* pixelWidthHeightRatio= */ 2f,
/* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
/* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
/* effects= */ ImmutableList.of());
Bitmap expectedBitmap = readBitmap(SCALE_WIDE_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(SCALE_WIDE_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -182,11 +166,13 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -182,11 +166,13 @@ public final class GlEffectsFrameProcessorPixelTest {
String testId = "processData_withMatrixTransformation_translateRight"; String testId = "processData_withMatrixTransformation_translateRight";
Matrix translateRightMatrix = new Matrix(); Matrix translateRightMatrix = new Matrix();
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
(MatrixTransformation) (long presentationTimeNs) -> translateRightMatrix); new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects((MatrixTransformation) (long presentationTimeNs) -> translateRightMatrix)
.build();
Bitmap expectedBitmap = readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -201,12 +187,15 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -201,12 +187,15 @@ public final class GlEffectsFrameProcessorPixelTest {
String testId = "processData_withMatrixAndScaleToFitTransformation"; String testId = "processData_withMatrixAndScaleToFitTransformation";
Matrix translateRightMatrix = new Matrix(); Matrix translateRightMatrix = new Matrix();
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
(MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix, new GlEffectsFrameProcessorTestRunner.Builder()
new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()); .setEffects(
(MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix,
new ScaleToFitTransformation.Builder().setRotationDegrees(45).build())
.build();
Bitmap expectedBitmap = readBitmap(TRANSLATE_THEN_ROTATE_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(TRANSLATE_THEN_ROTATE_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -221,12 +210,15 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -221,12 +210,15 @@ public final class GlEffectsFrameProcessorPixelTest {
String testId = "processData_withScaleToFitAndMatrixTransformation"; String testId = "processData_withScaleToFitAndMatrixTransformation";
Matrix translateRightMatrix = new Matrix(); Matrix translateRightMatrix = new Matrix();
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
new ScaleToFitTransformation.Builder().setRotationDegrees(45).build(), new GlEffectsFrameProcessorTestRunner.Builder()
(MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix); .setEffects(
new ScaleToFitTransformation.Builder().setRotationDegrees(45).build(),
(MatrixTransformation) (long presentationTimeUs) -> translateRightMatrix)
.build();
Bitmap expectedBitmap = readBitmap(ROTATE_THEN_TRANSLATE_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(ROTATE_THEN_TRANSLATE_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -239,10 +231,13 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -239,10 +231,13 @@ public final class GlEffectsFrameProcessorPixelTest {
public void processData_withPresentation_createForHeight_producesExpectedOutput() public void processData_withPresentation_createForHeight_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "processData_withPresentation_createForHeight"; String testId = "processData_withPresentation_createForHeight";
setUpAndPrepareFirstFrame(Presentation.createForHeight(480)); glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(Presentation.createForHeight(480))
.build();
Bitmap expectedBitmap = readBitmap(REQUEST_OUTPUT_HEIGHT_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(REQUEST_OUTPUT_HEIGHT_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -254,13 +249,16 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -254,13 +249,16 @@ public final class GlEffectsFrameProcessorPixelTest {
@Test @Test
public void processData_withCropThenPresentation_producesExpectedOutput() throws Exception { public void processData_withCropThenPresentation_producesExpectedOutput() throws Exception {
String testId = "processData_withCropThenPresentation"; String testId = "processData_withCropThenPresentation";
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
new Crop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ -.5f, /* top= */ .5f), new GlEffectsFrameProcessorTestRunner.Builder()
Presentation.createForAspectRatio( .setEffects(
/* aspectRatio= */ .5f, Presentation.LAYOUT_SCALE_TO_FIT)); new Crop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ -.5f, /* top= */ .5f),
Presentation.createForAspectRatio(
/* aspectRatio= */ .5f, Presentation.LAYOUT_SCALE_TO_FIT))
.build();
Bitmap expectedBitmap = readBitmap(CROP_THEN_ASPECT_RATIO_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(CROP_THEN_ASPECT_RATIO_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -273,11 +271,13 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -273,11 +271,13 @@ public final class GlEffectsFrameProcessorPixelTest {
public void processData_withScaleToFitTransformation_rotate45_producesExpectedOutput() public void processData_withScaleToFitTransformation_rotate45_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "processData_withScaleToFitTransformation_rotate45"; String testId = "processData_withScaleToFitTransformation_rotate45";
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()); new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(new ScaleToFitTransformation.Builder().setRotationDegrees(45).build())
.build();
Bitmap expectedBitmap = readBitmap(ROTATE45_SCALE_TO_FIT_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(ROTATE45_SCALE_TO_FIT_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -290,15 +290,19 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -290,15 +290,19 @@ public final class GlEffectsFrameProcessorPixelTest {
public void processData_withTwoWrappedScaleToFitTransformations_producesExpectedOutput() public void processData_withTwoWrappedScaleToFitTransformations_producesExpectedOutput()
throws Exception { throws Exception {
String testId = "processData_withTwoWrappedScaleToFitTransformations"; String testId = "processData_withTwoWrappedScaleToFitTransformations";
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
new GlEffectWrapper(new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()), new GlEffectsFrameProcessorTestRunner.Builder()
new GlEffectWrapper( .setEffects(
new ScaleToFitTransformation.Builder() new GlEffectWrapper(
.setScale(/* scaleX= */ 2, /* scaleY= */ 1) new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()),
.build())); new GlEffectWrapper(
new ScaleToFitTransformation.Builder()
.setScale(/* scaleX= */ 2, /* scaleY= */ 1)
.build()))
.build();
Bitmap expectedBitmap = readBitmap(ROTATE_THEN_SCALE_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(ROTATE_THEN_SCALE_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -321,10 +325,16 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -321,10 +325,16 @@ public final class GlEffectsFrameProcessorPixelTest {
} }
full10StepRotationAndCenterCrop.add(centerCrop); full10StepRotationAndCenterCrop.add(centerCrop);
setUpAndPrepareFirstFrame(centerCrop); glEffectsFrameProcessorTestRunner =
Bitmap centerCropResultBitmap = processFirstFrameAndEnd(); new GlEffectsFrameProcessorTestRunner.Builder().setEffects(centerCrop).build();
setUpAndPrepareFirstFrame(full10StepRotationAndCenterCrop.build()); Bitmap centerCropResultBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
Bitmap fullRotationAndCenterCropResultBitmap = processFirstFrameAndEnd(); glEffectsFrameProcessorTestRunner.release();
glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(full10StepRotationAndCenterCrop.build())
.build();
Bitmap fullRotationAndCenterCropResultBitmap =
glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory( maybeSaveTestBitmapToCacheDirectory(
testId, /* bitmapLabel= */ "centerCrop", centerCropResultBitmap); testId, /* bitmapLabel= */ "centerCrop", centerCropResultBitmap);
...@@ -347,10 +357,11 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -347,10 +357,11 @@ public final class GlEffectsFrameProcessorPixelTest {
new RgbAdjustment.Builder().setRedScale(5).build(), new RgbAdjustment.Builder().setRedScale(5).build(),
new RgbAdjustment.Builder().setGreenScale(5).build(), new RgbAdjustment.Builder().setGreenScale(5).build(),
new RgbAdjustment.Builder().setBlueScale(5).build()); new RgbAdjustment.Builder().setBlueScale(5).build());
setUpAndPrepareFirstFrame(increaseBrightness); glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder().setEffects(increaseBrightness).build();
Bitmap expectedBitmap = readBitmap(INCREASE_BRIGHTNESS_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(INCREASE_BRIGHTNESS_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -375,14 +386,22 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -375,14 +386,22 @@ public final class GlEffectsFrameProcessorPixelTest {
new RgbAdjustment.Builder().setBlueScale(5).build(), new RgbAdjustment.Builder().setBlueScale(5).build(),
new Rotation(/* degrees= */ 90), new Rotation(/* degrees= */ 90),
centerCrop); centerCrop);
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
ImmutableList.of( new GlEffectsFrameProcessorTestRunner.Builder()
new RgbAdjustment.Builder().setRedScale(5).setBlueScale(5).setGreenScale(5).build(), .setEffects(
centerCrop)); new RgbAdjustment.Builder().setRedScale(5).setBlueScale(5).setGreenScale(5).build(),
Bitmap centerCropAndBrightnessIncreaseResultBitmap = processFirstFrameAndEnd(); centerCrop)
setUpAndPrepareFirstFrame(increaseBrightnessFullRotationCenterCrop); .build();
Bitmap centerCropAndBrightnessIncreaseResultBitmap =
glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
Bitmap fullRotationBrightnessIncreaseAndCenterCropResultBitmap = processFirstFrameAndEnd(); glEffectsFrameProcessorTestRunner.release();
glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(increaseBrightnessFullRotationCenterCrop)
.build();
Bitmap fullRotationBrightnessIncreaseAndCenterCropResultBitmap =
glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory( maybeSaveTestBitmapToCacheDirectory(
testId, /* bitmapLabel= */ "centerCrop", centerCropAndBrightnessIncreaseResultBitmap); testId, /* bitmapLabel= */ "centerCrop", centerCropAndBrightnessIncreaseResultBitmap);
...@@ -418,14 +437,22 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -418,14 +437,22 @@ public final class GlEffectsFrameProcessorPixelTest {
new Rotation(/* degrees= */ 90), new Rotation(/* degrees= */ 90),
new FrameCache(/* capacity= */ 2), new FrameCache(/* capacity= */ 2),
centerCrop); centerCrop);
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
ImmutableList.of( new GlEffectsFrameProcessorTestRunner.Builder()
new RgbAdjustment.Builder().setRedScale(5).setBlueScale(5).setGreenScale(5).build(), .setEffects(
centerCrop)); new RgbAdjustment.Builder().setRedScale(5).setBlueScale(5).setGreenScale(5).build(),
Bitmap centerCropAndBrightnessIncreaseResultBitmap = processFirstFrameAndEnd(); centerCrop)
setUpAndPrepareFirstFrame(increaseBrightnessFullRotationCenterCrop); .build();
Bitmap centerCropAndBrightnessIncreaseResultBitmap =
glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
glEffectsFrameProcessorTestRunner.release();
glEffectsFrameProcessorTestRunner =
new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(increaseBrightnessFullRotationCenterCrop)
.build();
Bitmap fullRotationBrightnessIncreaseAndCenterCropResultBitmap = processFirstFrameAndEnd(); Bitmap fullRotationBrightnessIncreaseAndCenterCropResultBitmap =
glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory( maybeSaveTestBitmapToCacheDirectory(
testId, /* bitmapLabel= */ "centerCrop", centerCropAndBrightnessIncreaseResultBitmap); testId, /* bitmapLabel= */ "centerCrop", centerCropAndBrightnessIncreaseResultBitmap);
...@@ -446,11 +473,15 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -446,11 +473,15 @@ public final class GlEffectsFrameProcessorPixelTest {
public void drawFrame_grayscaleAndIncreaseRedChannel_producesGrayscaleAndRedImage() public void drawFrame_grayscaleAndIncreaseRedChannel_producesGrayscaleAndRedImage()
throws Exception { throws Exception {
String testId = "drawFrame_grayscaleAndIncreaseRedChannel"; String testId = "drawFrame_grayscaleAndIncreaseRedChannel";
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
RgbFilter.createGrayscaleFilter(), new RgbAdjustment.Builder().setRedScale(3).build()); new GlEffectsFrameProcessorTestRunner.Builder()
.setEffects(
RgbFilter.createGrayscaleFilter(),
new RgbAdjustment.Builder().setRedScale(3).build())
.build();
Bitmap expectedBitmap = readBitmap(GRAYSCALE_THEN_INCREASE_RED_CHANNEL_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(GRAYSCALE_THEN_INCREASE_RED_CHANNEL_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -476,15 +507,15 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -476,15 +507,15 @@ public final class GlEffectsFrameProcessorPixelTest {
.setColorRange(C.COLOR_RANGE_LIMITED) .setColorRange(C.COLOR_RANGE_LIMITED)
.setColorTransfer(C.COLOR_TRANSFER_GAMMA_2_2) .setColorTransfer(C.COLOR_TRANSFER_GAMMA_2_2)
.build(); .build();
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
INPUT_HLG_MP4_ASSET_STRING, new GlEffectsFrameProcessorTestRunner.Builder()
DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, .setVideoAssetPath(INPUT_HLG_MP4_ASSET_STRING)
/* inputColorInfo= */ hlgColor, .setInputColorInfo(hlgColor)
/* outputColorInfo= */ toneMapSdrColor, .setOutputColorInfo(toneMapSdrColor)
/* effects= */ ImmutableList.of()); .build();
Bitmap expectedBitmap = readBitmap(TONE_MAP_HLG_TO_SDR_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(TONE_MAP_HLG_TO_SDR_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -510,15 +541,15 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -510,15 +541,15 @@ public final class GlEffectsFrameProcessorPixelTest {
.setColorRange(C.COLOR_RANGE_LIMITED) .setColorRange(C.COLOR_RANGE_LIMITED)
.setColorTransfer(C.COLOR_TRANSFER_GAMMA_2_2) .setColorTransfer(C.COLOR_TRANSFER_GAMMA_2_2)
.build(); .build();
setUpAndPrepareFirstFrame( glEffectsFrameProcessorTestRunner =
INPUT_PQ_MP4_ASSET_STRING, new GlEffectsFrameProcessorTestRunner.Builder()
DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, .setVideoAssetPath(INPUT_PQ_MP4_ASSET_STRING)
/* inputColorInfo= */ pqColor, .setInputColorInfo(pqColor)
/* outputColorInfo= */ toneMapSdrColor, .setOutputColorInfo(toneMapSdrColor)
/* effects= */ ImmutableList.of()); .build();
Bitmap expectedBitmap = readBitmap(TONE_MAP_PQ_TO_SDR_PNG_ASSET_PATH); Bitmap expectedBitmap = readBitmap(TONE_MAP_PQ_TO_SDR_PNG_ASSET_PATH);
Bitmap actualBitmap = processFirstFrameAndEnd(); Bitmap actualBitmap = glEffectsFrameProcessorTestRunner.processFirstFrameAndEnd();
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
// TODO(b/207848601): switch to using proper tooling for testing against golden data. // TODO(b/207848601): switch to using proper tooling for testing against golden data.
...@@ -530,104 +561,207 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -530,104 +561,207 @@ public final class GlEffectsFrameProcessorPixelTest {
// TODO(b/227624622): Add a test for HDR input after BitmapPixelTestUtil can read HDR bitmaps, // TODO(b/227624622): Add a test for HDR input after BitmapPixelTestUtil can read HDR bitmaps,
// using GlEffectWrapper to ensure usage of intermediate textures. // using GlEffectWrapper to ensure usage of intermediate textures.
/** /* A test runner for {@link GlEffectsFrameProcessor} tests. */
* Sets up and prepares the first frame from an input video, as well as the relevant test private static final class GlEffectsFrameProcessorTestRunner {
* infrastructure.
* /** A builder for {@link GlEffectsFrameProcessorTestRunner} instances. */
* <p>The frame will be sent towards {@link #glEffectsFrameProcessor}, and output may be accessed public static final class Builder {
* on the {@code outputImageReader}. private @Nullable ImmutableList<Effect> effects;
* private String videoAssetPath;
* @param effects The {@link GlEffect GlEffects} to apply to the input frame. private float pixelWidthHeightRatio;
*/ private ColorInfo inputColorInfo;
private void setUpAndPrepareFirstFrame(GlEffect... effects) throws Exception { private ColorInfo outputColorInfo;
setUpAndPrepareFirstFrame(asList(effects));
} /** Creates a new instance with default values. */
public Builder() {
private void setUpAndPrepareFirstFrame(List<Effect> effects) throws Exception { videoAssetPath = INPUT_SDR_MP4_ASSET_STRING;
setUpAndPrepareFirstFrame( pixelWidthHeightRatio = DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO;
INPUT_SDR_MP4_ASSET_STRING, inputColorInfo = ColorInfo.SDR_BT709_LIMITED;
DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, outputColorInfo = ColorInfo.SDR_BT709_LIMITED;
/* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED, }
/* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
effects); /**
} * Sets the effects used.
*
* <p>The default value is an empty list.
*/
@CanIgnoreReturnValue
public Builder setEffects(List<Effect> effects) {
this.effects = ImmutableList.copyOf(effects);
return this;
}
/**
* Sets the effects used.
*
* <p>The default value is an empty list.
*/
@CanIgnoreReturnValue
public Builder setEffects(Effect... effects) {
this.effects = ImmutableList.copyOf(effects);
return this;
}
/**
* Sets the input video asset path.
*
* <p>The default value is {@link #INPUT_SDR_MP4_ASSET_STRING}.
*/
@CanIgnoreReturnValue
public Builder setVideoAssetPath(String videoAssetPath) {
this.videoAssetPath = videoAssetPath;
return this;
}
/**
* Sets the {@code pixelWidthHeightRatio}.
*
* <p>The default value is {@link #DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO}.
*/
@CanIgnoreReturnValue
public Builder setPixelWidthHeightRatio(float pixelWidthHeightRatio) {
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
return this;
}
/**
* Sets the input color.
*
* <p>The default value is {@link ColorInfo.SDR_BT709_LIMITED}.
*/
@CanIgnoreReturnValue
public Builder setInputColorInfo(ColorInfo inputColorInfo) {
this.inputColorInfo = inputColorInfo;
return this;
}
/**
* Sets the output color.
*
* <p>The default value is {@link ColorInfo.SDR_BT709_LIMITED}.
*/
@CanIgnoreReturnValue
public Builder setOutputColorInfo(ColorInfo outputColorInfo) {
this.outputColorInfo = outputColorInfo;
return this;
}
public GlEffectsFrameProcessorTestRunner build() throws FrameProcessingException {
return new GlEffectsFrameProcessorTestRunner(
effects == null ? ImmutableList.of() : effects,
videoAssetPath,
pixelWidthHeightRatio,
inputColorInfo,
outputColorInfo);
}
}
private void setUpAndPrepareFirstFrame( /** The ratio of width over height, for each pixel in a frame. */
String videoAssetPath, private static final float DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO = 1;
float pixelWidthHeightRatio, /**
ColorInfo inputColorInfo, * Time to wait for the decoded frame to populate the {@link GlEffectsFrameProcessor} instance's
ColorInfo outputColorInfo, * input surface and the {@link GlEffectsFrameProcessor} to finish processing the frame, in
List<Effect> effects) * milliseconds.
throws Exception { */
glEffectsFrameProcessor = private static final int FRAME_PROCESSING_WAIT_MS = 5000;
checkNotNull(
new GlEffectsFrameProcessor.Factory() private final String videoAssetPath;
.create( private final float pixelWidthHeightRatio;
getApplicationContext(), private final AtomicReference<FrameProcessingException> frameProcessingException;
effects,
DebugViewProvider.NONE, private final GlEffectsFrameProcessor glEffectsFrameProcessor;
inputColorInfo,
outputColorInfo, private volatile @MonotonicNonNull ImageReader outputImageReader;
/* releaseFramesAutomatically= */ true, private volatile boolean frameProcessingEnded;
MoreExecutors.directExecutor(),
new FrameProcessor.Listener() { private GlEffectsFrameProcessorTestRunner(
@Override ImmutableList<Effect> effects,
public void onOutputSizeChanged(int width, int height) { String videoAssetPath,
outputImageReader = float pixelWidthHeightRatio,
ImageReader.newInstance( ColorInfo inputColorInfo,
width, height, PixelFormat.RGBA_8888, /* maxImages= */ 1); ColorInfo outputColorInfo)
checkNotNull(glEffectsFrameProcessor) throws FrameProcessingException {
.setOutputSurfaceInfo( this.videoAssetPath = videoAssetPath;
new SurfaceInfo(outputImageReader.getSurface(), width, height)); this.pixelWidthHeightRatio = pixelWidthHeightRatio;
} frameProcessingException = new AtomicReference<>();
@Override glEffectsFrameProcessor =
public void onOutputFrameAvailable(long presentationTimeUs) { checkNotNull(
// Do nothing as frames are released automatically. new GlEffectsFrameProcessor.Factory()
} .create(
getApplicationContext(),
@Override effects,
public void onFrameProcessingError(FrameProcessingException exception) { DebugViewProvider.NONE,
frameProcessingException.set(exception); inputColorInfo,
} outputColorInfo,
/* releaseFramesAutomatically= */ true,
@Override MoreExecutors.directExecutor(),
public void onFrameProcessingEnded() { new FrameProcessor.Listener() {
frameProcessingEnded = true; @Override
} public void onOutputSizeChanged(int width, int height) {
})); outputImageReader =
DecodeOneFrameUtil.decodeOneAssetFileFrame( ImageReader.newInstance(
videoAssetPath, width, height, PixelFormat.RGBA_8888, /* maxImages= */ 1);
new DecodeOneFrameUtil.Listener() { checkNotNull(glEffectsFrameProcessor)
@Override .setOutputSurfaceInfo(
public void onContainerExtracted(MediaFormat mediaFormat) { new SurfaceInfo(outputImageReader.getSurface(), width, height));
glEffectsFrameProcessor.setInputFrameInfo( }
new FrameInfo(
mediaFormat.getInteger(MediaFormat.KEY_WIDTH), @Override
mediaFormat.getInteger(MediaFormat.KEY_HEIGHT), public void onOutputFrameAvailable(long presentationTimeUs) {
pixelWidthHeightRatio, // Do nothing as frames are released automatically.
/* streamOffsetUs= */ 0)); }
glEffectsFrameProcessor.registerInputFrame();
} @Override
public void onFrameProcessingError(FrameProcessingException exception) {
@Override frameProcessingException.set(exception);
public void onFrameDecoded(MediaFormat mediaFormat) { }
// Do nothing.
} @Override
}, public void onFrameProcessingEnded() {
glEffectsFrameProcessor.getInputSurface()); frameProcessingEnded = true;
} }
}));
}
private Bitmap processFirstFrameAndEnd() throws InterruptedException { public Bitmap processFirstFrameAndEnd() throws Exception {
checkNotNull(glEffectsFrameProcessor).signalEndOfInput(); DecodeOneFrameUtil.decodeOneAssetFileFrame(
Thread.sleep(FRAME_PROCESSING_WAIT_MS); videoAssetPath,
assertThat(frameProcessingEnded).isTrue(); new DecodeOneFrameUtil.Listener() {
assertThat(frameProcessingException.get()).isNull(); @Override
public void onContainerExtracted(MediaFormat mediaFormat) {
glEffectsFrameProcessor.setInputFrameInfo(
new FrameInfo(
mediaFormat.getInteger(MediaFormat.KEY_WIDTH),
mediaFormat.getInteger(MediaFormat.KEY_HEIGHT),
pixelWidthHeightRatio,
/* streamOffsetUs= */ 0));
glEffectsFrameProcessor.registerInputFrame();
}
@Override
public void onFrameDecoded(MediaFormat mediaFormat) {
// Do nothing.
}
},
glEffectsFrameProcessor.getInputSurface());
checkNotNull(glEffectsFrameProcessor).signalEndOfInput();
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
assertThat(frameProcessingEnded).isTrue();
assertThat(frameProcessingException.get()).isNull();
Image frameProcessorOutputImage = checkNotNull(outputImageReader).acquireLatestImage();
Bitmap actualBitmap = createArgb8888BitmapFromRgba8888Image(frameProcessorOutputImage);
frameProcessorOutputImage.close();
return actualBitmap;
}
Image frameProcessorOutputImage = checkNotNull(outputImageReader).acquireLatestImage(); public void release() {
Bitmap actualBitmap = createArgb8888BitmapFromRgba8888Image(frameProcessorOutputImage); if (glEffectsFrameProcessor != null) {
frameProcessorOutputImage.close(); glEffectsFrameProcessor.release();
return actualBitmap; }
}
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment