1 /*
2  * Copyright (C) 2015 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.media.decoder.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.fail;
22 import static org.junit.Assume.assumeFalse;
23 
24 import android.media.MediaCodec;
25 import android.media.MediaCodecInfo.VideoCapabilities;
26 import android.media.MediaExtractor;
27 import android.media.MediaFormat;
28 import android.media.cts.MediaHeavyPresubmitTest;
29 import android.media.cts.MediaTestBase;
30 import android.media.cts.TestArgs;
31 import android.media.cts.TestUtils;
32 import android.platform.test.annotations.AppModeFull;
33 import android.util.Log;
34 import android.util.Pair;
35 import android.view.Surface;
36 
37 import androidx.test.platform.app.InstrumentationRegistry;
38 
39 import com.android.compatibility.common.util.DeviceReportLog;
40 import com.android.compatibility.common.util.MediaPerfUtils;
41 import com.android.compatibility.common.util.MediaUtils;
42 import com.android.compatibility.common.util.Preconditions;
43 import com.android.compatibility.common.util.ResultType;
44 import com.android.compatibility.common.util.ResultUnit;
45 
46 import org.junit.After;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.junit.runners.Parameterized;
51 
52 import java.nio.ByteBuffer;
53 import java.util.ArrayList;
54 import java.util.Arrays;
55 import java.util.Collection;
56 import java.util.LinkedList;
57 import java.util.List;
58 
59 @MediaHeavyPresubmitTest
60 @AppModeFull(reason = "TODO: evaluate and port to instant")
61 @RunWith(Parameterized.class)
62 public class VideoDecoderPerfTest extends MediaTestBase {
63     private static final String TAG = "VideoDecoderPerfTest";
64     private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
65     private static final int TOTAL_FRAMES = 30000;
66     private static final int MIN_FRAMES = 3000;
67     private static final int MAX_TIME_MS = 120000;  // 2 minutes
68     private static final int MAX_TEST_TIMEOUT_MS = 300000;  // 5 minutes
69     private static final int MIN_TEST_MS = 10000;  // 10 seconds
70     private static final int NUMBER_OF_REPEATS = 2;
71 
72     private static final String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
73     private static final String H263 = MediaFormat.MIMETYPE_VIDEO_H263;
74     private static final String HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
75     private static final String MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
76     private static final String MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
77     private static final String VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
78     private static final String VP9 = MediaFormat.MIMETYPE_VIDEO_VP9;
79     private static final String AV1 = MediaFormat.MIMETYPE_VIDEO_AV1;
80 
81     private static final boolean GOOG = true;
82     private static final boolean OTHER = false;
83 
84     private static final int MAX_SIZE_SAMPLES_IN_MEMORY_BYTES = 12 << 20;  // 12MB
85 
86     private final String mDecoderName;
87     private final String mMediaType;
88     private final String[] mResources;
89 
90     // each sample contains the buffer and the PTS offset from the frame index
91     LinkedList<Pair<ByteBuffer, Double>> mSamplesInMemory = new LinkedList<Pair<ByteBuffer, Double>>();
92     private MediaFormat mDecInputFormat;
93     private MediaFormat mDecOutputFormat;
94     private int mBitrate;
95 
96     private boolean mSkipRateChecking = false;
97     private boolean mUpdatedSwCodecModule = false;
98     static final String mInpPrefix = WorkDir.getMediaDirString();
99 
prepareParamList(List<Object[]> exhaustiveArgsList)100     static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
101         final List<Object[]> argsList = new ArrayList<>();
102         int argLength = exhaustiveArgsList.get(0).length;
103         for (Object[] arg : exhaustiveArgsList) {
104             String mediaType = (String)arg[0];
105             if (TestArgs.shouldSkipMediaType(mediaType)) {
106                 continue;
107             }
108             String[] decoders = MediaUtils.getDecoderNamesForMime(mediaType);
109             for (String decoder : decoders) {
110                 if (TestArgs.shouldSkipCodec(decoder)) {
111                     continue;
112                 }
113                 Object[] testArgs = new Object[argLength + 1];
114                 // Add codec name as first argument and then copy all other arguments passed
115                 testArgs[0] = decoder;
116                 System.arraycopy(arg, 0, testArgs, 1, argLength);
117                 argsList.add(testArgs);
118             }
119         }
120         return argsList;
121     }
122 
123     @Parameterized.Parameters(name = "{index}_{0}_{3}")
input()124     public static Collection<Object[]> input() {
125         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
126                 // MediaType, resources, graphics display resolution
127                 {AVC, sAvcMedia0320x0240, "qvga"},
128                 {AVC, sAvcMedia0720x0480, "sd"},
129                 {AVC, sAvcMedia1280x0720, "hd"},
130                 {AVC, sAvcMedia1920x1080, "fullhd"},
131 
132                 {H263, sH263Media0176x0144, "qcif"},
133                 {H263, sH263Media0352x0288, "cif"},
134 
135                 {HEVC, sHevcMedia0352x0288, "cif"},
136                 {HEVC, sHevcMedia0640x0360, "vga"},
137                 {HEVC, sHevcMedia0720x0480, "sd"},
138                 {HEVC, sHevcMedia1280x0720, "hd"},
139                 {HEVC, sHevcMedia1920x1080, "fullhd"},
140                 {HEVC, sHevcMedia3840x2160, "uhd"},
141 
142                 {MPEG4, sMpeg4Media0176x0144, "qcif"},
143                 {MPEG4, sMpeg4Media0480x0360, "360p"},
144                 {MPEG4, sMpeg4Media1280x0720, "hd"},
145 
146                 {VP8, sVp8Media0320x0180, "qvga"},
147                 {VP8, sVp8Media0640x0360, "vga"},
148                 {VP8, sVp8Media1280x0720, "hd"},
149                 {VP8, sVp8Media1920x1080, "fullhd"},
150 
151                 {VP9, sVp9Media0320x0180, "qvga"},
152                 {VP9, sVp9Media0640x0360, "vga"},
153                 {VP9, sVp9Media1280x0720, "hd"},
154                 {VP9, sVp9Media1920x1080, "fullhd"},
155                 {VP9, sVp9Media3840x2160, "uhd"},
156 
157                 {AV1, sAv1Media0352x0288, "cif"},
158                 {AV1, sAv1Media0640x0360, "vga"},
159                 {AV1, sAv1Media0720x0480, "sd"},
160                 {AV1, sAv1Media1280x0720, "hd"},
161                 {AV1, sAv1Media1920x1080, "fullhd"},
162         });
163         return prepareParamList(exhaustiveArgsList);
164     }
165 
VideoDecoderPerfTest(String decodername, String mediaType, String[] resources, @SuppressWarnings("unused") String gfxcode)166     public VideoDecoderPerfTest(String decodername, String mediaType, String[] resources,
167             @SuppressWarnings("unused") String gfxcode) {
168 
169         mDecoderName = decodername;
170         mMediaType = mediaType;
171         mResources = resources;
172     }
173 
174     @Before
175     @Override
setUp()176     public void setUp() throws Throwable {
177         super.setUp();
178 
179         mSkipRateChecking = TestUtils.isMtsMode();
180         mUpdatedSwCodecModule =
181                 !TestUtils.isMainlineModuleFactoryVersion("com.google.android.media.swcodec");
182     }
183 
184     @After
185     @Override
tearDown()186     public void tearDown() {
187         super.tearDown();
188     }
189 
decode(String name, final String resource, MediaFormat format)190     private void decode(String name, final String resource, MediaFormat format) throws Exception {
191         int width = format.getInteger(MediaFormat.KEY_WIDTH);
192         int height = format.getInteger(MediaFormat.KEY_HEIGHT);
193         String mime = format.getString(MediaFormat.KEY_MIME);
194 
195         // Ensure we can finish this test within the test timeout. Allow 25% slack (4/5).
196         long maxTimeMs = Math.min(
197                 MAX_TEST_TIMEOUT_MS * 4 / 5 / NUMBER_OF_REPEATS, MAX_TIME_MS);
198         // reduce test run on non-real device to maximum of 2 seconds
199         if (MediaUtils.onFrankenDevice()) {
200             maxTimeMs = Math.min(2000, maxTimeMs);
201         }
202         double measuredFps[] = new double[NUMBER_OF_REPEATS];
203 
204         for (int i = 0; i < NUMBER_OF_REPEATS; ++i) {
205             // Decode to Surface.
206             Log.d(TAG, "round #" + i + ": " + name + " for " + maxTimeMs + " msecs to surface");
207             Surface s = getActivity().getSurfaceHolder().getSurface();
208             // only verify the result for decode to surface case.
209             measuredFps[i] = doDecode(name, resource, width, height, s, i, maxTimeMs);
210 
211             // We don't test decoding to buffer.
212             // Log.d(TAG, "round #" + i + " decode to buffer");
213             // doDecode(name, video, width, height, null, i, maxTimeMs);
214         }
215 
216         // allow improvements in mainline-updated google-supplied software codecs.
217         boolean fasterIsOk = mUpdatedSwCodecModule & TestUtils.isMainlineCodec(name);
218         String error =
219             MediaPerfUtils.verifyAchievableFrameRates(name, mime, width, height,
220                            fasterIsOk,  measuredFps);
221         if (error != null && MediaUtils.onFrankenDevice()) {
222             // not a real device; so note it as a non-fatal assumption failure
223             assumeFalse(error, error.startsWith("Failed to get "));
224         } else if (error != null && mSkipRateChecking) {
225             // sometimes speed issues are noted, but non-fatal
226             // this is most often because we're running mts (not mcts, not cts)
227             assumeFalse(error, error.startsWith("Failed to get "));
228         } else {
229             // the rest of the time, we insist on performance verification.
230             assertNull(error, error);
231         }
232         mSamplesInMemory.clear();
233     }
234 
doDecode(String name, final String filename, int w, int h, Surface surface, int round, long maxTimeMs)235     private double doDecode(String name, final String filename, int w, int h, Surface surface,
236             int round, long maxTimeMs) throws Exception {
237         final String video = mInpPrefix + filename;
238         Preconditions.assertTestFileExists(video);
239         MediaExtractor extractor = new MediaExtractor();
240         extractor.setDataSource(video);
241         extractor.selectTrack(0);
242         int trackIndex = extractor.getSampleTrackIndex();
243         MediaFormat format = extractor.getTrackFormat(trackIndex);
244         String mime = format.getString(MediaFormat.KEY_MIME);
245 
246         // use frame rate to calculate PTS offset used for PTS scaling
247         double frameRate = 0.; // default - 0 is used for using zero PTS offset
248         if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
249             frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
250         } else if (!mime.equals(MediaFormat.MIMETYPE_VIDEO_VP8)
251                 && !mime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
252             fail("need framerate info for video file");
253         }
254 
255         ByteBuffer[] codecInputBuffers;
256         ByteBuffer[] codecOutputBuffers;
257 
258         if (mSamplesInMemory.size() == 0) {
259             int totalMemory = 0;
260             ByteBuffer tmpBuf = ByteBuffer.allocate(w * h * 3 / 2);
261             int sampleSize = 0;
262             int index = 0;
263             long firstPTS = 0;
264             double presentationOffset = 0.;
265             while ((sampleSize = extractor.readSampleData(tmpBuf, 0 /* offset */)) > 0) {
266                 if (totalMemory + sampleSize > MAX_SIZE_SAMPLES_IN_MEMORY_BYTES) {
267                     break;
268                 }
269                 if (mSamplesInMemory.size() == 0) {
270                     firstPTS = extractor.getSampleTime();
271                 }
272                 ByteBuffer copied = ByteBuffer.allocate(sampleSize);
273                 copied.put(tmpBuf);
274                 if (frameRate > 0.) {
275                     // presentation offset is an offset from the frame index
276                     presentationOffset =
277                         (extractor.getSampleTime() - firstPTS) * frameRate / 1e6 - index;
278                 }
279                 mSamplesInMemory.addLast(Pair.create(copied, presentationOffset));
280                 totalMemory += sampleSize;
281                 ++index;
282                 extractor.advance();
283             }
284             Log.d(TAG, mSamplesInMemory.size() + " samples in memory for " +
285                     (totalMemory / 1024) + " KB.");
286             // bitrate normalized to 30fps
287             mBitrate = (int)Math.round(totalMemory * 30. * 8. / mSamplesInMemory.size());
288         }
289         format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
290 
291         int sampleIndex = 0;
292 
293         extractor.release();
294 
295         MediaCodec codec = MediaCodec.createByCodecName(name);
296         VideoCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime).getVideoCapabilities();
297         frameRate = cap.getSupportedFrameRatesFor(w, h).getUpper();
298         codec.configure(format, surface, null /* crypto */, 0 /* flags */);
299         codec.start();
300         codecInputBuffers = codec.getInputBuffers();
301         codecOutputBuffers = codec.getOutputBuffers();
302         mDecInputFormat = codec.getInputFormat();
303 
304         // start decode loop
305         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
306 
307         final long kTimeOutUs = 1000; // 1ms timeout
308         double[] frameTimeUsDiff = new double[TOTAL_FRAMES - 1];
309         long lastOutputTimeUs = 0;
310         boolean sawInputEOS = false;
311         boolean sawOutputEOS = false;
312         int inputNum = 0;
313         int outputNum = 0;
314         long start = System.currentTimeMillis();
315         while (!sawOutputEOS) {
316             // handle input
317             if (!sawInputEOS) {
318                 int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
319 
320                 if (inputBufIndex >= 0) {
321                     ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
322                     // sample contains the buffer and the PTS offset normalized to frame index
323                     Pair<ByteBuffer, Double> sample =
324                             mSamplesInMemory.get(sampleIndex++ % mSamplesInMemory.size());
325                     sample.first.rewind();
326                     int sampleSize = sample.first.remaining();
327                     dstBuf.put(sample.first);
328                     // use max supported framerate to compute pts
329                     long presentationTimeUs = (long)((inputNum + sample.second) * 1e6 / frameRate);
330 
331                     long elapsed = System.currentTimeMillis() - start;
332                     sawInputEOS = ((++inputNum == TOTAL_FRAMES)
333                                    || (elapsed > maxTimeMs)
334                                    || (elapsed > MIN_TEST_MS && outputNum > MIN_FRAMES));
335                     if (sawInputEOS) {
336                         Log.d(TAG, "saw input EOS (stop at sample).");
337                     }
338                     codec.queueInputBuffer(
339                             inputBufIndex,
340                             0 /* offset */,
341                             sampleSize,
342                             presentationTimeUs,
343                             sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
344                 } else {
345                     assertEquals(
346                             "codec.dequeueInputBuffer() unrecognized return value: " + inputBufIndex,
347                             MediaCodec.INFO_TRY_AGAIN_LATER, inputBufIndex);
348                 }
349             }
350 
351             // handle output
352             int outputBufIndex = codec.dequeueOutputBuffer(info, kTimeOutUs);
353 
354             if (outputBufIndex >= 0) {
355                 if (info.size > 0) { // Disregard 0-sized buffers at the end.
356                     long nowUs = (System.nanoTime() + 500) / 1000;
357                     if (outputNum > 1) {
358                         frameTimeUsDiff[outputNum - 1] = nowUs - lastOutputTimeUs;
359                     }
360                     lastOutputTimeUs = nowUs;
361                     outputNum++;
362                 }
363                 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
364                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
365                     Log.d(TAG, "saw output EOS.");
366                     sawOutputEOS = true;
367                 }
368             } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
369                 codecOutputBuffers = codec.getOutputBuffers();
370                 Log.d(TAG, "output buffers have changed.");
371             } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
372                 mDecOutputFormat = codec.getOutputFormat();
373                 int width = mDecOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
374                 int height = mDecOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
375                 Log.d(TAG, "output resolution " + width + "x" + height);
376             } else {
377                 assertEquals(
378                         "codec.dequeueOutputBuffer() unrecognized return index: "
379                                 + outputBufIndex,
380                         MediaCodec.INFO_TRY_AGAIN_LATER, outputBufIndex);
381             }
382         }
383         long finish = System.currentTimeMillis();
384         int validDataNum = outputNum - 1;
385         frameTimeUsDiff = Arrays.copyOf(frameTimeUsDiff, validDataNum);
386         codec.stop();
387         codec.release();
388 
389         Log.d(TAG, "input num " + inputNum + " vs output num " + outputNum);
390 
391         DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, "video_decoder_performance");
392         String message = MediaPerfUtils.addPerformanceHeadersToLog(
393                 log, "decoder stats: decodeTo=" + ((surface == null) ? "buffer" : "surface"),
394                 round, name, format, mDecInputFormat, mDecOutputFormat);
395         log.addValue("video_res", video, ResultType.NEUTRAL, ResultUnit.NONE);
396         log.addValue("decode_to", surface == null ? "buffer" : "surface",
397                 ResultType.NEUTRAL, ResultUnit.NONE);
398 
399         double fps = outputNum / ((finish - start) / 1000.0);
400         log.addValue("average_fps", fps, ResultType.HIGHER_BETTER, ResultUnit.FPS);
401 
402         MediaUtils.Stats stats = new MediaUtils.Stats(frameTimeUsDiff);
403         fps = MediaPerfUtils.addPerformanceStatsToLog(log, stats, message);
404         log.submit(InstrumentationRegistry.getInstrumentation());
405         return fps;
406     }
407 
getVideoTrackFormats(String... resources)408     private MediaFormat[] getVideoTrackFormats(String... resources) throws Exception {
409         MediaFormat[] formats = new MediaFormat[resources.length];
410         for (int i = 0; i < resources.length; ++i) {
411             Preconditions.assertTestFileExists(mInpPrefix + resources[i]);
412             formats[i] = MediaUtils.getTrackFormatForResource(mInpPrefix + resources[i], "video/");
413         }
414         return formats;
415     }
416 
perf(final String decoderName, final String[] resources)417     private void perf(final String decoderName, final String[] resources) throws Exception {
418         MediaFormat[] formats = getVideoTrackFormats(resources);
419         // Decode/measure the first supported video resource
420         for (int i = 0; i < resources.length; ++i) {
421             if (MediaUtils.supports(decoderName, formats[i])) {
422                 decode(decoderName, resources[i], formats[i]);
423                 break;
424             }
425         }
426     }
427 
428     // AVC tests
429 
430     private static final String[] sAvcMedia0320x0240 = {
431         "bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz.mp4",
432     };
433 
434     private static final String[] sAvcMedia0720x0480 = {
435         "bbb_s1_720x480_mp4_h264_mp3_2mbps_30fps_aac_lc_5ch_320kbps_48000hz.mp4",
436     };
437 
438     // prefer highest effective bitrate, then high profile
439     private static final String[] sAvcMedia1280x0720 = {
440         "bbb_s4_1280x720_mp4_h264_mp31_8mbps_30fps_aac_he_mono_40kbps_44100hz.mp4",
441         "bbb_s3_1280x720_mp4_h264_hp32_8mbps_60fps_aac_he_v2_stereo_48kbps_48000hz.mp4",
442         "bbb_s3_1280x720_mp4_h264_mp32_8mbps_60fps_aac_he_v2_6ch_144kbps_44100hz.mp4",
443     };
444 
445     // prefer highest effective bitrate, then high profile
446     private static final String[] sAvcMedia1920x1080 = {
447         "bbb_s4_1920x1080_wide_mp4_h264_hp4_20mbps_30fps_aac_lc_6ch_384kbps_44100hz.mp4",
448         "bbb_s4_1920x1080_wide_mp4_h264_mp4_20mbps_30fps_aac_he_5ch_200kbps_44100hz.mp4",
449         "bbb_s2_1920x1080_mp4_h264_hp42_20mbps_60fps_aac_lc_6ch_384kbps_48000hz.mp4",
450         "bbb_s2_1920x1080_mp4_h264_mp42_20mbps_60fps_aac_he_v2_5ch_160kbps_48000hz.mp4",
451     };
452 
453     // H263 tests
454 
455     private static final String[] sH263Media0176x0144 = {
456         "video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp",
457     };
458 
459     private static final String[] sH263Media0352x0288 = {
460         "video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp",
461     };
462 
463     // No media for H263 704x576
464 
465     // No media for H263 1408x1152
466 
467     // HEVC tests
468 
469     private static final String[] sHevcMedia0352x0288 = {
470         "bbb_s1_352x288_mp4_hevc_mp2_600kbps_30fps_aac_he_stereo_96kbps_48000hz.mp4",
471     };
472 
473     private static final String[] sHevcMedia0640x0360 = {
474         "bbb_s1_640x360_mp4_hevc_mp21_1600kbps_30fps_aac_he_6ch_288kbps_44100hz.mp4",
475     };
476 
477     private static final String[] sHevcMedia0720x0480 = {
478         "bbb_s1_720x480_mp4_hevc_mp3_1600kbps_30fps_aac_he_6ch_240kbps_48000hz.mp4",
479     };
480 
481     private static final String[] sHevcMedia1280x0720 = {
482         "bbb_s4_1280x720_mp4_hevc_mp31_4mbps_30fps_aac_he_stereo_80kbps_32000hz.mp4",
483     };
484 
485     private static final String[] sHevcMedia1920x1080 = {
486         "bbb_s2_1920x1080_mp4_hevc_mp41_10mbps_60fps_aac_lc_6ch_384kbps_22050hz.mp4",
487     };
488 
489     // prefer highest effective bitrate
490     private static final String[] sHevcMedia3840x2160 = {
491         "bbb_s4_3840x2160_mp4_hevc_mp5_20mbps_30fps_aac_lc_6ch_384kbps_24000hz.mp4",
492         "bbb_s2_3840x2160_mp4_hevc_mp51_20mbps_60fps_aac_lc_6ch_384kbps_32000hz.mp4",
493     };
494 
495     // MPEG2 tests
496 
497     // No media for MPEG2 176x144
498 
499     // No media for MPEG2 352x288
500 
501     // No media for MPEG2 640x480
502 
503     // No media for MPEG2 1280x720
504 
505     // No media for MPEG2 1920x1080
506 
507     // MPEG4 tests
508 
509     private static final String[] sMpeg4Media0176x0144 = {
510         "video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
511     };
512 
513     private static final String[] sMpeg4Media0480x0360 = {
514         "video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
515     };
516 
517     // No media for MPEG4 640x480
518 
519     private static final String[] sMpeg4Media1280x0720 = {
520         "video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
521     };
522 
523     // VP8 tests
524 
525     private static final String[] sVp8Media0320x0180 = {
526         "bbb_s1_320x180_webm_vp8_800kbps_30fps_opus_5ch_320kbps_48000hz.webm",
527     };
528 
529     private static final String[] sVp8Media0640x0360 = {
530         "bbb_s1_640x360_webm_vp8_2mbps_30fps_vorbis_5ch_320kbps_48000hz.webm",
531     };
532 
533     // prefer highest effective bitrate
534     private static final String[] sVp8Media1280x0720 = {
535         "bbb_s4_1280x720_webm_vp8_8mbps_30fps_opus_mono_64kbps_48000hz.webm",
536         "bbb_s3_1280x720_webm_vp8_8mbps_60fps_opus_6ch_384kbps_48000hz.webm",
537     };
538 
539     // prefer highest effective bitrate
540     private static final String[] sVp8Media1920x1080 = {
541         "bbb_s4_1920x1080_wide_webm_vp8_20mbps_30fps_vorbis_6ch_384kbps_44100hz.webm",
542         "bbb_s2_1920x1080_webm_vp8_20mbps_60fps_vorbis_6ch_384kbps_48000hz.webm",
543     };
544 
545     // VP9 tests
546 
547     private static final String[] sVp9Media0320x0180 = {
548         "bbb_s1_320x180_webm_vp9_0p11_600kbps_30fps_vorbis_mono_64kbps_48000hz.webm",
549     };
550 
551     private static final String[] sVp9Media0640x0360 = {
552         "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
553     };
554 
555     private static final String[] sVp9Media1280x0720 = {
556         "bbb_s4_1280x720_webm_vp9_0p31_4mbps_30fps_opus_stereo_128kbps_48000hz.webm",
557     };
558 
559     private static final String[] sVp9Media1920x1080 = {
560         "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm",
561     };
562 
563     // prefer highest effective bitrate
564     private static final String[] sVp9Media3840x2160 = {
565         "bbb_s4_3840x2160_webm_vp9_0p5_20mbps_30fps_vorbis_6ch_384kbps_24000hz.webm",
566         "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm",
567     };
568 
569     // AV1 tests
570 
571     private static final String[] sAv1Media0352x0288 = {
572         "bbb_s1_352x288_mp4_av1_355kbps_30fps_aac_lc_stereo_128kbps_48000hz.mp4",
573     };
574 
575     private static final String[] sAv1Media0640x0360 = {
576         "bbb_s1_640x360_mp4_av1_994kbps_30fps_aac_lc_6ch_342kbps_48000hz.mp4",
577     };
578 
579     private static final String[] sAv1Media0720x0480 = {
580         "bbb_s1_720x480_mp4_av1_977kbps_30fps_aac_lc_6ch_341kbps_48000hz.mp4",
581     };
582 
583     private static final String[] sAv1Media1280x0720 = {
584         "bbb_s4_1280x720_mp4_av1_2387kbps_30fps_aac_lc_stereo_130kbps_32000hz.mp4",
585     };
586 
587     private static final String[] sAv1Media1920x1080 = {
588         "bbb_s2_1920x1080_mp4_av1_5010kbps_60fps_aac_lc_6ch_348kbps_22050hz.mp4",
589     };
590 
591     @Test
testPerf()592     public void testPerf() throws Exception {
593         perf(mDecoderName, mResources);
594     }
595 }
596 
597