• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package android.mediav2.cts;
18 
19 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
20 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
21 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ALL;
22 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assume.assumeTrue;
27 
28 import android.media.MediaCodec;
29 import android.media.MediaFormat;
30 import android.mediav2.common.cts.CodecDecoderTestBase;
31 import android.mediav2.common.cts.CodecTestBase;
32 import android.mediav2.common.cts.OutputManager;
33 import android.mediav2.common.cts.OutputSurface;
34 import android.opengl.GLES20;
35 import android.opengl.GLES30;
36 import android.util.Log;
37 
38 import androidx.test.filters.LargeTest;
39 
40 import com.android.compatibility.common.util.ApiTest;
41 import com.android.compatibility.common.util.CddTest;
42 
43 import org.junit.After;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.junit.runners.Parameterized;
47 
48 import java.io.IOException;
49 import java.nio.ByteBuffer;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collection;
53 import java.util.List;
54 
55 import javax.microedition.khronos.opengles.GL10;
56 
57 /**
58  * Validates the correctness of color conversion in the decode followed by OpenGL
59  * rendering scenarios. The input video files fed to the decoders contain the pixel
60  * data in compressed YUV format. The output of the decoders is shared with OpenGL
61  * as external textures. And OpenGL outputs RGB pixels. The class validates whether
62  * the conversion of input YUV to output RGB is in accordance with the chosen color
63  * aspects. Video files used in the test do not have any color aspects info coded in
64  * the bitstreams
65  */
66 @RunWith(Parameterized.class)
67 public class DecodeGlAccuracyTest extends CodecDecoderTestBase {
68     private static final String LOG_TAG = DecodeGlAccuracyTest.class.getSimpleName();
69     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
70 
71     // Allowed color tolerance to account for differences in the conversion process
72     private static final int ALLOWED_COLOR_DELTA = 8;
73 
74     // The test video assets were generated with a set of color bars.
75     // Depending on the color aspects, the values from OpenGL pbuffer
76     // should not differ from the reference color values for the
77     // given color aspects below by more than the allowed tolerance.
78     //
79     // The reference RGB values were computed using the process described below.
80     //
81     // RGB = Transpose(FLOOR_CLIP_PIXEL(CONV_CSC * (Transpose(YUV) - LVL_OFFSET)))
82     // The matrices LVL_OFFSET and CONV_CSC for different color aspects are below.
83     //
84     // YUV values in the 8bit color bar test videos are in COLOR_BARS_YUV below
85     //
86     // The color conversion matrices (CONV_CSC) for the RGB equation above:
87     // MULTIPLY_ROW_WISE_LR = Transpose({255/219, 255/224, 255/224})
88     // CONV_FLOAT_601_FR =
89     //     {{1, 0, 1.402},
90     //      {1, -0.344136, -0.714136},
91     //      {1, 1.772, 0},}
92     // CONV_FLOAT_709_FR =
93     //     {{1, 0, 1.5748},
94     //      {1, -0.1873, -0.4681},
95     //      {1, 1.8556, 0},}
96     // CONV_FLOAT_601_LR = MULTIPLY_ROW_WISE_LR . CONV_FLOAT_601_FR
97     // CONV_FLOAT_709_LR = MULTIPLY_ROW_WISE_LR . CONV_FLOAT_709_FR
98     //
99     // The level shift matrices (LVL_OFFSET) for the RGB equation above:
100     // LVL_OFFSET_LR = Transpose({16, 128, 128})
101     // LVL_OFFSET_FR = Transpose({0, 128, 128})
102 
103     private static final int[][] COLOR_BARS_YUV = new int[][]{
104             {126, 191, 230},
105             {98, 104, 204},
106             {180, 20, 168},
107             {121, 109, 60},
108             {114, 179, 172},
109             {133, 138, 118},
110             {183, 93, 153},
111             {203, 20, 33},
112             {147, 131, 183},
113             {40, 177, 202},
114             {170, 82, 96},
115     };
116 
117     private static final int[][] COLOR_BARS_YUV_10BIT = new int[][]{
118             {504, 764, 920},
119             {392, 416, 816},
120             {720, 80, 672},
121             {484, 436, 240},
122             {456, 716, 688},
123             {532, 552, 472},
124             {732, 372, 612},
125             {812, 80, 132},
126             {588, 524, 732},
127             {160, 708, 808},
128             {680, 328, 384},
129     };
130 
131     // Reference RGB values for 601 Limited Range
132     private static final int[][] COLOR_BARS_601LR = new int[][]{
133             {255, 17, 252},
134             {219, 40, 44},
135             {255, 196, 0},
136             {11, 182, 81},
137             {185, 55, 214},
138             {119, 137, 153},
139             {235, 183, 119},
140             {62, 255, 0},
141             {242, 103, 155},
142             {148, 0, 126},
143             {127, 219, 82},
144     };
145 
146     // Reference RGB values for 601 Limited Range 10BIT
147     private static final int[][] COLOR_BARS_601LR_10BIT = new int[][]{
148             {1023, 82, 1023},
149             {870, 173, 189},
150             {1022, 805, 0},
151             {55, 742, 337},
152             {740, 234, 871},
153             {483, 564, 628},
154             {940, 754, 497},
155             {265, 1023, 0},
156             {964, 428, 636},
157             {586, 0, 509},
158             {515, 896, 347},
159     };
160 
161     // Reference RGB values for 601 Full Range
162     private static final int[][] COLOR_BARS_601FR = new int[][]{
163             {255, 31, 237},
164             {204, 51, 55},
165             {236, 188, 0},
166             {25, 176, 87},
167             {175, 65, 204},
168             {118, 136, 150},
169             {218, 177, 120},
170             {69, 255, 11},
171             {224, 106, 152},
172             {143, 0, 126},
173             {125, 208, 88},
174     };
175 
176     // Reference RGB values for 601 Full Range 10BIT
177     private static final int[][] COLOR_BARS_601FR_10BIT = new int[][]{
178             {1023, 126, 951},
179             {818, 208, 222},
180             {944, 754, 0},
181             {103, 704, 349},
182             {703, 260, 818},
183             {476, 547, 603},
184             {872, 709, 484},
185             {279, 1023, 46},
186             {897, 427, 609},
187             {575, 0, 507},
188             {501, 835, 354},
189     };
190 
191     // Reference RGB values for 709 Limited Range
192     private static final int[][] COLOR_BARS_709LR = new int[][]{
193             {255, 57, 255},
194             {234, 57, 42},
195             {255, 188, 0},
196             {0, 159, 79},
197             {194, 77, 219},
198             {117, 136, 154},
199             {240, 184, 116},
200             {43, 255, 0},
201             {253, 119, 155},
202             {163, 0, 130},
203             {120, 202, 78},
204     };
205 
206     // Reference RGB values for 709 Limited Range 10BIT
207     private static final int[][] COLOR_BARS_709LR_10BIT = new int[][]{
208             {1023, 242, 1023},
209             {930, 241, 180},
210             {1023, 773, 0},
211             {2, 652, 330},
212             {774, 320, 890},
213             {475, 559, 631},
214             {960, 757, 484},
215             {190, 1023, 0},
216             {1008, 492, 637},
217             {644, 0, 527},
218             {489, 827, 330},
219     };
220 
221     // Reference RGB values for 2020 Limited Range
222     private static final int[][] COLOR_BARS_2020LR = new int[][]{
223             {1023, 201, 1023},
224             {895, 203, 177},
225             {1023, 743, 0},
226             {33, 682, 327},
227             {754, 305, 896},
228             {479, 565, 633},
229             {949, 741, 479},
230             {234, 1023, 0},
231             {982, 466, 638},
232             {610, 0, 533},
233             {504, 837, 324},
234     };
235 
236     // Reference RGB values for 2020 Full Range
237     private static final int[][] COLOR_BARS_2020FR = new int[][]{
238             {1023, 229, 978},
239             {840, 234, 211},
240             {956, 700, 0},
241             {83, 652, 341},
242             {716, 322, 840},
243             {473, 548, 607},
244             {879, 698, 469},
245             {252, 1023, 0},
246             {912, 460, 611},
247             {596, 0, 529},
248             {491, 783, 334},
249     };
250 
251     // The test videos were generated with the above color bars. Each bar is of width 16.
252     private static final int COLOR_BAR_WIDTH = 16;
253     private static final int COLOR_BAR_OFFSET_X = 8;
254     private static final int COLOR_BAR_OFFSET_Y = 64;
255 
256     private final int mRange;
257     private final int mStandard;
258     private final int mTransferCurve;
259     private final boolean mUseYuvSampling;
260     private final boolean mUseHighBitDepth;
261 
262     private int[][] mColorBars;
263     private int mWidth;
264     private int mHeight;
265     private OutputSurface mEGLWindowOutSurface;
266     private int mBadFrames = 0;
267 
DecodeGlAccuracyTest(String decoder, String mediaType, String fileName, int range, int standard, int transfer, boolean useHighBitDepth, boolean useYuvSampling, String allTestParams)268     public DecodeGlAccuracyTest(String decoder, String mediaType, String fileName, int range,
269             int standard, int transfer, boolean useHighBitDepth, boolean useYuvSampling,
270             String allTestParams) {
271         super(decoder, mediaType, MEDIA_DIR + fileName, allTestParams);
272         mRange = range;
273         mStandard = standard;
274         mTransferCurve = transfer;
275         mUseYuvSampling = useYuvSampling;
276         mUseHighBitDepth = useHighBitDepth;
277 
278         if (!mUseYuvSampling) {
279             mColorBars = COLOR_BARS_601LR;
280             if ((mStandard == MediaFormat.COLOR_STANDARD_BT601_NTSC) && (mRange
281                     == MediaFormat.COLOR_RANGE_LIMITED)) {
282                 mColorBars = mUseHighBitDepth ? COLOR_BARS_601LR_10BIT : COLOR_BARS_601LR;
283             } else if ((mStandard == MediaFormat.COLOR_STANDARD_BT601_NTSC) && (mRange
284                     == MediaFormat.COLOR_RANGE_FULL)) {
285                 mColorBars = mUseHighBitDepth ? COLOR_BARS_601FR_10BIT : COLOR_BARS_601FR;
286             } else if ((mStandard == MediaFormat.COLOR_STANDARD_BT709) && (mRange
287                     == MediaFormat.COLOR_RANGE_LIMITED)) {
288                 mColorBars = mUseHighBitDepth ? COLOR_BARS_709LR_10BIT : COLOR_BARS_709LR;
289             } else if ((mStandard == MediaFormat.COLOR_STANDARD_BT2020) && (mRange
290                     == MediaFormat.COLOR_RANGE_LIMITED)) {
291                 mColorBars = COLOR_BARS_2020LR;
292             } else if ((mStandard == MediaFormat.COLOR_STANDARD_BT2020) && (mRange
293                     == MediaFormat.COLOR_RANGE_FULL)) {
294                 mColorBars = COLOR_BARS_2020FR;
295             } else {
296                 Log.e(LOG_TAG, "Unsupported Color Aspects.");
297             }
298         } else {
299             mColorBars = mUseHighBitDepth ? COLOR_BARS_YUV_10BIT : COLOR_BARS_YUV;
300         }
301     }
302 
303     @After
tearDown()304     public void tearDown() {
305         mSurface = null;
306         if (mEGLWindowOutSurface != null) {
307             mEGLWindowOutSurface.release();
308             mEGLWindowOutSurface = null;
309         }
310     }
311 
312     @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}_{4}_{5}_{6}_{7}")
input()313     public static Collection<Object[]> input() {
314         final boolean isEncoder = false;
315         final boolean needAudio = false;
316         final boolean needVideo = true;
317 
318         final List<Object[]> argsList = Arrays.asList(new Object[][]{
319                 // mediaType, asset, range, standard, transfer, mUseHighBitDepth
320                 // 601LR
321                 {MediaFormat.MIMETYPE_VIDEO_AVC, "color_bands_176x176_h264_8bit.mp4",
322                         MediaFormat.COLOR_RANGE_LIMITED,
323                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
324                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
325                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_8bit.mp4",
326                         MediaFormat.COLOR_RANGE_LIMITED,
327                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
328                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
329                 {MediaFormat.MIMETYPE_VIDEO_VP8, "color_bands_176x176_vp8_8bit.webm",
330                         MediaFormat.COLOR_RANGE_LIMITED,
331                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
332                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
333                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_8bit.webm",
334                         MediaFormat.COLOR_RANGE_LIMITED,
335                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
336                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
337                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_8bit.webm",
338                         MediaFormat.COLOR_RANGE_LIMITED,
339                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
340                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
341                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_10bit.mp4",
342                         MediaFormat.COLOR_RANGE_LIMITED,
343                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
344                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
345                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_10bit.webm",
346                         MediaFormat.COLOR_RANGE_LIMITED,
347                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
348                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
349                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_10bit.webm",
350                         MediaFormat.COLOR_RANGE_LIMITED,
351                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
352                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
353 
354                 // 601FR
355                 {MediaFormat.MIMETYPE_VIDEO_AVC, "color_bands_176x176_h264_8bit_fr.mp4",
356                         MediaFormat.COLOR_RANGE_FULL,
357                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
358                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
359                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_8bit_fr.mp4",
360                         MediaFormat.COLOR_RANGE_FULL,
361                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
362                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
363                 {MediaFormat.MIMETYPE_VIDEO_VP8, "color_bands_176x176_vp8_8bit_fr.webm",
364                         MediaFormat.COLOR_RANGE_FULL,
365                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
366                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
367                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_8bit_fr.webm",
368                         MediaFormat.COLOR_RANGE_FULL,
369                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
370                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
371                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_8bit_fr.webm",
372                         MediaFormat.COLOR_RANGE_FULL,
373                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
374                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
375                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_10bit_fr.mp4",
376                         MediaFormat.COLOR_RANGE_FULL,
377                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
378                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
379                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_10bit_fr.webm",
380                         MediaFormat.COLOR_RANGE_FULL,
381                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
382                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
383                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_10bit_fr.webm",
384                         MediaFormat.COLOR_RANGE_FULL,
385                         MediaFormat.COLOR_STANDARD_BT601_NTSC,
386                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
387 
388                 // 709LR
389                 {MediaFormat.MIMETYPE_VIDEO_AVC, "color_bands_176x176_h264_8bit.mp4",
390                         MediaFormat.COLOR_RANGE_LIMITED,
391                         MediaFormat.COLOR_STANDARD_BT709,
392                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
393                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_8bit.mp4",
394                         MediaFormat.COLOR_RANGE_LIMITED,
395                         MediaFormat.COLOR_STANDARD_BT709,
396                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
397                 {MediaFormat.MIMETYPE_VIDEO_VP8, "color_bands_176x176_vp8_8bit.webm",
398                         MediaFormat.COLOR_RANGE_LIMITED,
399                         MediaFormat.COLOR_STANDARD_BT709,
400                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
401                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_8bit.webm",
402                         MediaFormat.COLOR_RANGE_LIMITED,
403                         MediaFormat.COLOR_STANDARD_BT709,
404                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
405                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_8bit.webm",
406                         MediaFormat.COLOR_RANGE_LIMITED,
407                         MediaFormat.COLOR_STANDARD_BT709,
408                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, false},
409                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_10bit.mp4",
410                         MediaFormat.COLOR_RANGE_LIMITED,
411                         MediaFormat.COLOR_STANDARD_BT709,
412                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
413                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_10bit.webm",
414                         MediaFormat.COLOR_RANGE_LIMITED,
415                         MediaFormat.COLOR_STANDARD_BT709,
416                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
417                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_10bit.webm",
418                         MediaFormat.COLOR_RANGE_LIMITED,
419                         MediaFormat.COLOR_STANDARD_BT709,
420                         MediaFormat.COLOR_TRANSFER_SDR_VIDEO, true},
421                 // Note: OpenGL is not required to support 709 FR. So we are not testing it.
422 
423                 // BT2020LR
424                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_10bit.mp4",
425                         MediaFormat.COLOR_RANGE_LIMITED,
426                         MediaFormat.COLOR_STANDARD_BT2020,
427                         MediaFormat.COLOR_TRANSFER_ST2084, true},
428                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_10bit.webm",
429                         MediaFormat.COLOR_RANGE_LIMITED,
430                         MediaFormat.COLOR_STANDARD_BT2020,
431                         MediaFormat.COLOR_TRANSFER_ST2084, true},
432                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_10bit.webm",
433                         MediaFormat.COLOR_RANGE_LIMITED,
434                         MediaFormat.COLOR_STANDARD_BT2020,
435                         MediaFormat.COLOR_TRANSFER_ST2084, true},
436 
437                 // BT2020FR
438                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_10bit_fr.mp4",
439                         MediaFormat.COLOR_RANGE_FULL,
440                         MediaFormat.COLOR_STANDARD_BT2020,
441                         MediaFormat.COLOR_TRANSFER_ST2084, true},
442                 {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_10bit_fr.webm",
443                         MediaFormat.COLOR_RANGE_FULL,
444                         MediaFormat.COLOR_STANDARD_BT2020,
445                         MediaFormat.COLOR_TRANSFER_ST2084, true},
446                 {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_10bit_fr.webm",
447                         MediaFormat.COLOR_RANGE_FULL,
448                         MediaFormat.COLOR_STANDARD_BT2020,
449                         MediaFormat.COLOR_TRANSFER_ST2084, true},
450 
451         });
452         final List<Object[]> exhaustiveArgsList = new ArrayList<>();
453         for (Object[] arg : argsList) {
454             int argLength = argsList.get(0).length;
455             boolean[] boolStates = {true, false};
456             for (boolean useYuvSampling : boolStates) {
457                 Object[] testArgs = new Object[argLength + 1];
458                 System.arraycopy(arg, 0, testArgs, 0, argLength);
459                 testArgs[argLength] = useYuvSampling;
460                 exhaustiveArgsList.add(testArgs);
461             }
462         }
463         return CodecTestBase.prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo,
464                 false);
465     }
466 
isColorClose(int actual, int expected)467     boolean isColorClose(int actual, int expected) {
468         int delta = Math.abs(actual - expected);
469         return (delta <= ALLOWED_COLOR_DELTA);
470     }
471 
checkSurfaceFrame(int frameIndex)472     private boolean checkSurfaceFrame(int frameIndex) {
473         ByteBuffer pixelBuf = ByteBuffer.allocateDirect(4);
474         boolean frameFailed = false;
475         for (int i = 0; i < mColorBars.length; i++) {
476             int x = COLOR_BAR_WIDTH * i + COLOR_BAR_OFFSET_X;
477             int y = COLOR_BAR_OFFSET_Y;
478             int r, g, b;
479             if (mUseHighBitDepth) {
480                 GLES20.glReadPixels(x, y, 1, 1, GL10.GL_RGBA, GLES30.GL_UNSIGNED_INT_2_10_10_10_REV,
481                         pixelBuf);
482                 r = (pixelBuf.get(1) & 0x03) << 8 | (pixelBuf.get(0) & 0xFF);
483                 g = (pixelBuf.get(2) & 0x0F) << 6 | ((pixelBuf.get(1) >> 2) & 0x3F);
484                 b = (pixelBuf.get(3) & 0x3F) << 4 | ((pixelBuf.get(2) >> 4) & 0x0F);
485             } else {
486                 GLES20.glReadPixels(x, y, 1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuf);
487                 r = pixelBuf.get(0) & 0xff;
488                 g = pixelBuf.get(1) & 0xff;
489                 b = pixelBuf.get(2) & 0xff;
490             }
491             if (!(isColorClose(r, mColorBars[i][0]) &&
492                     isColorClose(g, mColorBars[i][1]) &&
493                     isColorClose(b, mColorBars[i][2]))) {
494                 Log.w(LOG_TAG, "Bad frame " + frameIndex + " (rect={" + x + " " + y + "} :rgb=" +
495                         r + "," + g + "," + b + " vs. expected " + mColorBars[i][0] +
496                         "," + mColorBars[i][1] + "," + mColorBars[i][2] + ")");
497                 frameFailed = true;
498             }
499         }
500         return frameFailed;
501     }
502 
dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info)503     protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
504         if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
505             mSawOutputEOS = true;
506         }
507         if (ENABLE_LOGS) {
508             Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: " +
509                     info.size + " timestamp: " + info.presentationTimeUs);
510         }
511         if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
512             mOutputBuff.saveOutPTS(info.presentationTimeUs);
513             mOutputCount++;
514         }
515         mCodec.releaseOutputBuffer(bufferIndex, mSurface != null);
516         if (info.size > 0) {
517             mEGLWindowOutSurface.awaitNewImage();
518             mEGLWindowOutSurface.drawImage();
519             if (checkSurfaceFrame(mOutputCount - 1)) mBadFrames++;
520         }
521     }
522 
523     /**
524      * The test decodes video assets with color bars and outputs frames to OpenGL input surface.
525      * The OpenGL fragment shader reads the frame buffers as external textures and renders to
526      * a pbuffer. The output RGB values are read and compared against the expected values.
527      */
528     @CddTest(requirements = {"5.12/C-7-4"})
529     @ApiTest(apis = {"android.media.MediaFormat#KEY_COLOR_RANGE",
530             "android.media.MediaFormat#KEY_COLOR_STANDARD",
531             "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
532     @LargeTest
533     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
testDecodeGlAccuracyRGB()534     public void testDecodeGlAccuracyRGB() throws IOException, InterruptedException {
535         if (mUseHighBitDepth && !isVendorCodec(mCodecName)) {
536             if (hasSupportForColorFormat(mCodecName, mMediaType, COLOR_FormatYUVP010)) {
537                 if (!mUseYuvSampling) {
538                     // TODO (b/219748700): Android software codecs work only with BT2020 FR.
539                     assumeTrue("Skipping " + mCodecName + " for color range " + mRange
540                                     + " and color standard " + mStandard,
541                             mRange == MediaFormat.COLOR_RANGE_FULL
542                                     && mStandard == MediaFormat.COLOR_STANDARD_BT2020);
543                 }
544             } else {
545                 // TODO (b/259321347): Skip yuv sampling in high bit depth cases for software codecs
546                 assumeTrue("Skipping " + mCodecName + " for high bit depth YUV sampling tests "
547                         + "when codec doesn't support P010", !mUseYuvSampling);
548             }
549         }
550 
551         if (mRange != MediaFormat.COLOR_RANGE_LIMITED
552                 || mStandard != MediaFormat.COLOR_STANDARD_BT601_NTSC) {
553             // Prior to Android T, only BT601 limited range support was tested. Hence
554             // limit testing other color spaces to devices launching with T
555             assumeTrue("Skipping color range " + mRange + " and color standard " + mStandard +
556                             " for devices upgrading to T",
557                     FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T);
558 
559             // TODO (b/219748700): Android software codecs work only with 601LR. Skip for now.
560             assumeTrue("Skipping " + mCodecName + " for color range " + mRange
561                             + " and color standard " + mStandard,
562                     isVendorCodec(mCodecName));
563         }
564 
565         MediaFormat format = setUpSource(mTestFile);
566 
567         // Set color parameters
568         format.setInteger(MediaFormat.KEY_COLOR_RANGE, mRange);
569         format.setInteger(MediaFormat.KEY_COLOR_STANDARD, mStandard);
570         format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, mTransferCurve);
571 
572         // Set the format to surface mode
573         format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
574 
575         mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
576         mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
577         if (mUseHighBitDepth) {
578             SupportClass supportRequirements =
579                     mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) ? CODEC_ALL : CODEC_OPTIONAL;
580             ArrayList<MediaFormat> formatList = new ArrayList<>();
581             formatList.add(format);
582             checkFormatSupport(mCodecName, mMediaType, false, formatList, null,
583                     supportRequirements);
584         }
585         mEGLWindowOutSurface =
586                 new OutputSurface(mWidth, mHeight, mUseHighBitDepth, mUseYuvSampling);
587 
588         // If device supports HDR editing, then GL_EXT_YUV_target extension support is mandatory
589         if (mUseYuvSampling) {
590             String message = "Device doesn't support EXT_YUV_target GL extension \n" + mTestConfig
591                     + mTestEnv;
592             if (IS_AT_LEAST_T && (IS_HDR_EDITING_SUPPORTED || IS_HLG_EDITING_SUPPORTED)) {
593                 assertTrue(message, mEGLWindowOutSurface.getEXTYuvTargetSupported());
594             } else {
595                 assumeTrue(message, mEGLWindowOutSurface.getEXTYuvTargetSupported());
596             }
597         }
598 
599         mSurface = mEGLWindowOutSurface.getSurface();
600 
601         mCodec = MediaCodec.createByCodecName(mCodecName);
602         configureCodec(format, true, true, false);
603         mOutputBuff = new OutputManager();
604         mCodec.start();
605         doWork(Integer.MAX_VALUE);
606         queueEOS();
607         waitForAllOutputs();
608         validateColorAspects(mCodec.getOutputFormat(), mRange, mStandard, mTransferCurve);
609         mCodec.stop();
610         mCodec.release();
611         tearDown();
612 
613         assertEquals("color difference exceeds allowed tolerance in " + mBadFrames + " out of "
614                 + mOutputCount + " frames \n" + mTestConfig + mTestEnv, 0, mBadFrames);
615     }
616 }
617 
618