• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.exoplayer2.transformer;
17 
18 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
19 import static com.google.android.exoplayer2.transformer.BitmapTestUtil.FIRST_FRAME_PNG_ASSET_STRING;
20 import static com.google.android.exoplayer2.transformer.BitmapTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
21 import static com.google.android.exoplayer2.transformer.BitmapTestUtil.ROTATE_90_EXPECTED_OUTPUT_PNG_ASSET_STRING;
22 import static com.google.android.exoplayer2.transformer.BitmapTestUtil.SCALE_NARROW_EXPECTED_OUTPUT_PNG_ASSET_STRING;
23 import static com.google.android.exoplayer2.transformer.BitmapTestUtil.TRANSLATE_RIGHT_EXPECTED_OUTPUT_PNG_ASSET_STRING;
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import android.graphics.Bitmap;
27 import android.graphics.Matrix;
28 import android.graphics.SurfaceTexture;
29 import android.opengl.EGLContext;
30 import android.opengl.EGLDisplay;
31 import android.opengl.EGLSurface;
32 import androidx.test.ext.junit.runners.AndroidJUnit4;
33 import com.google.android.exoplayer2.util.GlUtil;
34 import java.io.IOException;
35 import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
36 import org.junit.After;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 
41 /**
42  * Pixel test for frame processing via {@link AdvancedFrameProcessor}.
43  *
44  * <p>Expected images are taken from an emulator, so tests on different emulators or physical
45  * devices may fail. To test on other devices, please increase the {@link
46  * BitmapTestUtil#MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE} and/or inspect the saved output bitmaps
47  * as recommended in {@link FrameProcessorChainPixelTest}.
48  */
49 @RunWith(AndroidJUnit4.class)
50 public final class AdvancedFrameProcessorPixelTest {
51 
52   static {
53     GlUtil.glAssertionsEnabled = true;
54   }
55 
56   private final EGLDisplay eglDisplay = GlUtil.createEglDisplay();
57   private final EGLContext eglContext = GlUtil.createEglContext(eglDisplay);
58   private @MonotonicNonNull GlFrameProcessor advancedFrameProcessor;
59   private int inputTexId;
60   private int outputTexId;
61   private int width;
62   private int height;
63 
64   @Before
createTextures()65   public void createTextures() throws IOException {
66     Bitmap inputBitmap = BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING);
67     width = inputBitmap.getWidth();
68     height = inputBitmap.getHeight();
69     // This surface is needed for focussing a render target, but the tests don't write output to it.
70     // The frame processor's output is written to a framebuffer instead.
71     EGLSurface eglSurface = GlUtil.getEglSurface(eglDisplay, new SurfaceTexture(false));
72     GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, width, height);
73     inputTexId =
74         BitmapTestUtil.createGlTextureFromBitmap(
75             BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING));
76     outputTexId = GlUtil.createTexture(width, height);
77     int frameBuffer = GlUtil.createFboForTexture(outputTexId);
78     GlUtil.focusFramebuffer(eglDisplay, eglContext, eglSurface, frameBuffer, width, height);
79   }
80 
81   @After
release()82   public void release() {
83     if (advancedFrameProcessor != null) {
84       advancedFrameProcessor.release();
85     }
86     GlUtil.destroyEglContext(eglDisplay, eglContext);
87   }
88 
89   @Test
updateProgramAndDraw_noEdits_producesExpectedOutput()90   public void updateProgramAndDraw_noEdits_producesExpectedOutput() throws Exception {
91     String testId = "updateProgramAndDraw_noEdits";
92     Matrix identityMatrix = new Matrix();
93     advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), identityMatrix);
94     advancedFrameProcessor.initialize(inputTexId, width, height);
95     Bitmap expectedBitmap = BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING);
96 
97     advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
98     Bitmap actualBitmap =
99         BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
100 
101     // TODO(b/207848601): switch to using proper tooling for testing against golden data.
102     float averagePixelAbsoluteDifference =
103         BitmapTestUtil.getAveragePixelAbsoluteDifferenceArgb8888(
104             expectedBitmap, actualBitmap, testId);
105     BitmapTestUtil.saveTestBitmapToCacheDirectory(
106         testId, /* bitmapLabel= */ "actual", actualBitmap, /* throwOnFailure= */ false);
107     assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
108   }
109 
110   @Test
updateProgramAndDraw_translateRight_producesExpectedOutput()111   public void updateProgramAndDraw_translateRight_producesExpectedOutput() throws Exception {
112     String testId = "updateProgramAndDraw_translateRight";
113     Matrix translateRightMatrix = new Matrix();
114     translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
115     advancedFrameProcessor =
116         new AdvancedFrameProcessor(getApplicationContext(), translateRightMatrix);
117     advancedFrameProcessor.initialize(inputTexId, width, height);
118     Bitmap expectedBitmap =
119         BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_EXPECTED_OUTPUT_PNG_ASSET_STRING);
120 
121     advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
122     Bitmap actualBitmap =
123         BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
124 
125     // TODO(b/207848601): switch to using proper tooling for testing against golden data.
126     float averagePixelAbsoluteDifference =
127         BitmapTestUtil.getAveragePixelAbsoluteDifferenceArgb8888(
128             expectedBitmap, actualBitmap, testId);
129     BitmapTestUtil.saveTestBitmapToCacheDirectory(
130         testId, /* bitmapLabel= */ "actual", actualBitmap, /* throwOnFailure= */ false);
131     assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
132   }
133 
134   @Test
updateProgramAndDraw_scaleNarrow_producesExpectedOutput()135   public void updateProgramAndDraw_scaleNarrow_producesExpectedOutput() throws Exception {
136     String testId = "updateProgramAndDraw_scaleNarrow";
137     Matrix scaleNarrowMatrix = new Matrix();
138     scaleNarrowMatrix.postScale(.5f, 1.2f);
139     advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), scaleNarrowMatrix);
140     advancedFrameProcessor.initialize(inputTexId, width, height);
141     Bitmap expectedBitmap =
142         BitmapTestUtil.readBitmap(SCALE_NARROW_EXPECTED_OUTPUT_PNG_ASSET_STRING);
143 
144     advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
145     Bitmap actualBitmap =
146         BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
147 
148     // TODO(b/207848601): switch to using proper tooling for testing against golden data.
149     float averagePixelAbsoluteDifference =
150         BitmapTestUtil.getAveragePixelAbsoluteDifferenceArgb8888(
151             expectedBitmap, actualBitmap, testId);
152     BitmapTestUtil.saveTestBitmapToCacheDirectory(
153         testId, /* bitmapLabel= */ "actual", actualBitmap, /* throwOnFailure= */ false);
154     assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
155   }
156 
157   @Test
updateProgramAndDraw_rotate90_producesExpectedOutput()158   public void updateProgramAndDraw_rotate90_producesExpectedOutput() throws Exception {
159     String testId = "updateProgramAndDraw_rotate90";
160     Matrix rotate90Matrix = new Matrix();
161     rotate90Matrix.postRotate(/* degrees= */ 90);
162     advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), rotate90Matrix);
163     advancedFrameProcessor.initialize(inputTexId, width, height);
164     Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_EXPECTED_OUTPUT_PNG_ASSET_STRING);
165 
166     advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
167     Bitmap actualBitmap =
168         BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
169 
170     // TODO(b/207848601): switch to using proper tooling for testing against golden data.
171     float averagePixelAbsoluteDifference =
172         BitmapTestUtil.getAveragePixelAbsoluteDifferenceArgb8888(
173             expectedBitmap, actualBitmap, testId);
174     BitmapTestUtil.saveTestBitmapToCacheDirectory(
175         testId, /* bitmapLabel= */ "actual", actualBitmap, /* throwOnFailure= */ false);
176     assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
177   }
178 }
179