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