• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ALL;
20 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
21 
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 
25 import android.media.MediaCodec;
26 import android.media.MediaExtractor;
27 import android.media.MediaFormat;
28 import android.mediav2.common.cts.CodecDecoderTestBase;
29 import android.mediav2.common.cts.CodecTestActivity;
30 import android.mediav2.common.cts.OutputManager;
31 import android.util.Log;
32 import android.view.Surface;
33 
34 import androidx.test.ext.junit.rules.ActivityScenarioRule;
35 import androidx.test.filters.LargeTest;
36 
37 import com.android.compatibility.common.util.ApiTest;
38 import com.android.compatibility.common.util.CddTest;
39 
40 import org.junit.Assume;
41 import org.junit.Before;
42 import org.junit.Rule;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.junit.runners.Parameterized;
46 
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.List;
52 
53 /**
54  * Test mediacodec api, video decoders and their interactions in surface mode.
55  * <p>
56  * When video decoders are configured in surface mode, the getOutputImage() returns null. So
57  * there is no way to validate the decoded output frame analytically. The tests in this class
58  * however ensures that,
59  * <ul>
60  *     <li> The number of decoded frames are equal to the number of input frames.</li>
61  *     <li> The output timestamp list is same as the input timestamp list.</li>
62  *     <li> The timestamp information obtained is consistent with results seen in byte buffer
63  *     mode.</li>
64  * </ul>
65  * <p>
66  * The test verifies all the above needs by running mediacodec in both sync and async mode.
67  */
68 @RunWith(Parameterized.class)
69 public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
70     private static final String LOG_TAG = CodecDecoderSurfaceTest.class.getSimpleName();
71     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
72 
73     private final String mReconfigFile;
74     private final SupportClass mSupportRequirements;
75 
76     static {
77         System.loadLibrary("ctsmediav2codecdecsurface_jni");
78     }
79 
CodecDecoderSurfaceTest(String decoder, String mediaType, String testFile, String reconfigFile, SupportClass supportRequirements, String allTestParams)80     public CodecDecoderSurfaceTest(String decoder, String mediaType, String testFile,
81             String reconfigFile, SupportClass supportRequirements, String allTestParams) {
82         super(decoder, mediaType, MEDIA_DIR + testFile, allTestParams);
83         mReconfigFile = MEDIA_DIR + reconfigFile;
84         mSupportRequirements = supportRequirements;
85     }
86 
dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info)87     protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
88         if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
89             mSawOutputEOS = true;
90         }
91         if (ENABLE_LOGS) {
92             Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: " +
93                     info.size + " timestamp: " + info.presentationTimeUs);
94         }
95         if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
96             mOutputBuff.saveOutPTS(info.presentationTimeUs);
97             mOutputCount++;
98         }
99         mCodec.releaseOutputBuffer(bufferIndex, mSurface != null);
100     }
101 
decodeAndSavePts(String file, String decoder, long pts, int mode, int frameLimit)102     private void decodeAndSavePts(String file, String decoder, long pts, int mode, int frameLimit)
103             throws IOException, InterruptedException {
104         Surface sf = mSurface;
105         mSurface = null; // for reference, decode in non-surface mode
106         mOutputBuff = new OutputManager();
107         mCodec = MediaCodec.createByCodecName(decoder);
108         MediaFormat format = setUpSource(file);
109         configureCodec(format, false, true, false);
110         mCodec.start();
111         mExtractor.seekTo(pts, mode);
112         doWork(frameLimit);
113         queueEOS();
114         waitForAllOutputs();
115         mCodec.stop();
116         mCodec.release();
117         mExtractor.release();
118         mSurface = sf; // restore surface
119     }
120 
121     @Rule
122     public ActivityScenarioRule<CodecTestActivity> mActivityRule =
123             new ActivityScenarioRule<>(CodecTestActivity.class);
124 
125     @Before
setUp()126     public void setUp() throws IOException, InterruptedException {
127         MediaFormat format = setUpSource(mTestFile);
128         mExtractor.release();
129         if (IS_Q) {
130             Log.i(LOG_TAG, "Android 10: skip checkFormatSupport() for format " + format);
131         } else {
132             ArrayList<MediaFormat> formatList = new ArrayList<>();
133             formatList.add(format);
134             checkFormatSupport(mCodecName, mMediaType, false, formatList, null,
135                     mSupportRequirements);
136         }
137         mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
138         setUpSurface(mActivity);
139     }
140 
141     @Parameterized.Parameters(name = "{index}_{0}_{1}")
input()142     public static Collection<Object[]> input() {
143         final boolean isEncoder = false;
144         final boolean needAudio = false;
145         final boolean needVideo = true;
146         // mediaType, test file, reconfig test file, SupportClass
147         final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
148                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_340x280_768kbps_30fps_mpeg2.mp4",
149                         "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
150                 {MediaFormat.MIMETYPE_VIDEO_MPEG2,
151                         "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4",
152                         "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
153                 {MediaFormat.MIMETYPE_VIDEO_MPEG2,
154                         "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
155                         "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
156                 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_340x280_768kbps_30fps_avc.mp4",
157                         "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
158                 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_360x640_768kbps_30fps_avc.mp4",
159                         "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
160                 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_160x1024_1500kbps_30fps_avc.mp4",
161                         "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_OPTIONAL},
162                 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x120_1500kbps_30fps_avc.mp4",
163                         "bbb_340x280_768kbps_30fps_avc.mp4", CODEC_OPTIONAL},
164                 {MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_520x390_1mbps_30fps_hevc.mp4",
165                         "bbb_340x280_768kbps_30fps_hevc.mp4", CODEC_ALL},
166                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_128x96_64kbps_12fps_mpeg4.mp4",
167                         "bbb_176x144_192kbps_15fps_mpeg4.mp4", CODEC_ALL},
168                 {MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp",
169                         "bbb_176x144_192kbps_10fps_h263.3gp", CODEC_ALL},
170                 {MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_340x280_768kbps_30fps_vp8.webm",
171                         "bbb_520x390_1mbps_30fps_vp8.webm", CODEC_ALL},
172                 {MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_340x280_768kbps_30fps_vp9.webm",
173                         "bbb_520x390_1mbps_30fps_vp9.webm", CODEC_ALL},
174                 {MediaFormat.MIMETYPE_VIDEO_VP9,
175                         "bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm",
176                         "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm", CODEC_ALL},
177                 {MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_340x280_768kbps_30fps_av1.mp4",
178                         "bbb_520x390_1mbps_30fps_av1.mp4", CODEC_ALL},
179                 {MediaFormat.MIMETYPE_VIDEO_AV1,
180                         "bikes_qcif_color_bt2020_smpte2086Hlg_bt2020Ncl_fr_av1.mp4",
181                         "bbb_520x390_1mbps_30fps_av1.mp4", CODEC_ALL},
182         }));
183         // P010 support was added in Android T, hence limit the following tests to Android T and
184         // above
185         if (IS_AT_LEAST_T) {
186             exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
187                     {MediaFormat.MIMETYPE_VIDEO_AVC, "cosmat_340x280_24fps_crf22_avc_10bit.mkv",
188                             "cosmat_520x390_24fps_crf22_avc_10bit.mkv", CODEC_OPTIONAL},
189                     {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_340x280_24fps_crf22_hevc_10bit.mkv",
190                             "cosmat_520x390_24fps_crf22_hevc_10bit.mkv", CODEC_OPTIONAL},
191                     {MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_340x280_24fps_crf22_vp9_10bit.mkv",
192                             "cosmat_520x390_24fps_crf22_vp9_10bit.mkv", CODEC_OPTIONAL},
193                     {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_340x280_24fps_512kbps_av1_10bit.mkv",
194                             "cosmat_520x390_24fps_768kbps_av1_10bit.mkv", CODEC_ALL},
195                     {MediaFormat.MIMETYPE_VIDEO_AVC, "cosmat_340x280_24fps_crf22_avc_10bit.mkv",
196                             "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_OPTIONAL},
197                     {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_340x280_24fps_crf22_hevc_10bit.mkv",
198                             "bbb_520x390_1mbps_30fps_hevc.mp4", CODEC_OPTIONAL},
199                     {MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_340x280_24fps_crf22_vp9_10bit.mkv",
200                             "bbb_520x390_1mbps_30fps_vp9.webm", CODEC_OPTIONAL},
201                     {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_340x280_24fps_512kbps_av1_10bit.mkv",
202                             "bbb_520x390_1mbps_30fps_av1.mp4", CODEC_ALL},
203                     {MediaFormat.MIMETYPE_VIDEO_AVC, "cosmat_520x390_24fps_crf22_avc_10bit.mkv",
204                             "bbb_340x280_768kbps_30fps_avc.mp4", CODEC_OPTIONAL},
205                     {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_520x390_24fps_crf22_hevc_10bit.mkv",
206                             "bbb_340x280_768kbps_30fps_hevc.mp4", CODEC_OPTIONAL},
207                     {MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_520x390_24fps_crf22_vp9_10bit.mkv",
208                             "bbb_340x280_768kbps_30fps_vp9.webm", CODEC_OPTIONAL},
209                     {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_520x390_24fps_768kbps_av1_10bit.mkv",
210                             "bbb_340x280_768kbps_30fps_av1.mp4", CODEC_ALL},
211             }));
212         }
213         return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, true);
214     }
215 
216     /**
217      * Checks if the component under test can decode the test file to surface. The test runs
218      * mediacodec in both synchronous and asynchronous mode. It expects consistent output
219      * timestamp list in all runs and this list to be identical to the reference list. The
220      * reference list is obtained from the same decoder running in byte buffer mode
221      */
222     @CddTest(requirements = {"2.2.2", "2.3.2", "2.5.2"})
223     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
224     @LargeTest
225     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testSimpleDecodeToSurface()226     public void testSimpleDecodeToSurface() throws IOException, InterruptedException {
227         boolean[] boolStates = {true, false};
228         final long pts = 0;
229         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
230         {
231             decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
232             OutputManager ref = mOutputBuff;
233             OutputManager test = new OutputManager(ref.getSharedErrorLogs());
234             MediaFormat format = setUpSource(mTestFile);
235             mCodec = MediaCodec.createByCodecName(mCodecName);
236             mOutputBuff = test;
237             mActivity.setScreenParams(getWidth(format), getHeight(format), true);
238             for (boolean isAsync : boolStates) {
239                 mOutputBuff.reset();
240                 mExtractor.seekTo(pts, mode);
241                 configureCodec(format, isAsync, true, false);
242                 mCodec.start();
243                 doWork(Integer.MAX_VALUE);
244                 queueEOS();
245                 waitForAllOutputs();
246                 mCodec.stop();
247                 if (!(mIsInterlaced ? ref.equalsInterlaced(test) : ref.equals(test))) {
248                     fail("Decoder output in surface mode does not match with output in bytebuffer "
249                             + "mode \n" + mTestConfig + mTestEnv + test.getErrMsg());
250                 }
251             }
252             mCodec.release();
253             mExtractor.release();
254         }
255     }
256 
257     /**
258      * Checks component and framework behaviour to flush API when the codec is operating in
259      * surface mode.
260      * <p>
261      * While the component is decoding the test clip to surface, mediacodec flush() is called.
262      * The flush API is called at various points :-
263      * <ul>
264      *     <li>In running state but before queueing any input (might have to resubmit csd as they
265      *     may not have been processed).</li>
266      *     <li>In running state, after queueing 1 frame.</li>
267      *     <li>In running state, after queueing n frames.</li>
268      *     <li>In eos state.</li>
269      * </ul>
270      * <p>
271      * In all situations (pre-flush or post-flush), the test expects the output timestamps to be
272      * strictly increasing. The flush call makes the output received non-deterministic even for a
273      * given input. Hence, besides timestamp checks, no additional validation is done for outputs
274      * received before flush. Post flush, the decode begins from a sync frame. So the test
275      * expects consistent output and this needs to be identical to the reference. The reference
276      * is obtained from the same decoder running in byte buffer mode.
277      * <p>
278      * The test runs mediacodec in synchronous and asynchronous mode.
279      */
280     @ApiTest(apis = {"android.media.MediaCodec#flush"})
281     @LargeTest
282     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testFlush()283     public void testFlush() throws IOException, InterruptedException {
284         MediaFormat format = setUpSource(mTestFile);
285         mExtractor.release();
286         mCsdBuffers.clear();
287         for (int i = 0; ; i++) {
288             String csdKey = "csd-" + i;
289             if (format.containsKey(csdKey)) {
290                 mCsdBuffers.add(format.getByteBuffer(csdKey));
291             } else break;
292         }
293         final long pts = 500000;
294         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
295         boolean[] boolStates = {true, false};
296         {
297             decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
298             OutputManager ref = mOutputBuff;
299             OutputManager test = new OutputManager(ref.getSharedErrorLogs());
300             mOutputBuff = test;
301             setUpSource(mTestFile);
302             mCodec = MediaCodec.createByCodecName(mCodecName);
303             mActivity.setScreenParams(getWidth(format), getHeight(format), false);
304             for (boolean isAsync : boolStates) {
305                 if (isAsync) continue;  // TODO(b/147576107)
306                 mExtractor.seekTo(0, mode);
307                 configureCodec(format, isAsync, true, false);
308                 mCodec.start();
309 
310                 /* test flush in running state before queuing input */
311                 flushCodec();
312                 if (mIsCodecInAsyncMode) mCodec.start();
313                 queueCodecConfig(); /* flushed codec too soon after start, resubmit csd */
314 
315                 doWork(1);
316                 flushCodec();
317                 if (mIsCodecInAsyncMode) mCodec.start();
318                 queueCodecConfig(); /* flushed codec too soon after start, resubmit csd */
319 
320                 mExtractor.seekTo(0, mode);
321                 test.reset();
322                 doWork(23);
323                 if (!test.isPtsStrictlyIncreasing(mPrevOutputPts)) {
324                     fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
325                             + test.getErrMsg());
326                 }
327 
328                 /* test flush in running state */
329                 flushCodec();
330                 if (mIsCodecInAsyncMode) mCodec.start();
331                 test.reset();
332                 mExtractor.seekTo(pts, mode);
333                 doWork(Integer.MAX_VALUE);
334                 queueEOS();
335                 waitForAllOutputs();
336                 if (!(mIsInterlaced ? ref.equalsInterlaced(test) : ref.equals(test))) {
337                     fail("Decoder output in surface mode does not match with output in bytebuffer "
338                             + "mode \n" + mTestConfig + mTestEnv + test.getErrMsg());
339                 }
340 
341                 /* test flush in eos state */
342                 flushCodec();
343                 if (mIsCodecInAsyncMode) mCodec.start();
344                 test.reset();
345                 mExtractor.seekTo(pts, mode);
346                 doWork(Integer.MAX_VALUE);
347                 queueEOS();
348                 waitForAllOutputs();
349                 mCodec.stop();
350                 if (!(mIsInterlaced ? ref.equalsInterlaced(test) : ref.equals(test))) {
351                     fail("Decoder output in surface mode does not match with output in bytebuffer "
352                             + "mode \n" + mTestConfig + mTestEnv + test.getErrMsg());
353                 }
354             }
355             mCodec.release();
356             mExtractor.release();
357         }
358     }
359 
360     /**
361      * Checks component and framework behaviour for resolution change in surface mode. The
362      * resolution change is not seamless (AdaptivePlayback) but done via reconfigure.
363      * <p>
364      * The reconfiguring of media codec component happens at various points :-
365      * <ul>
366      *     <li>After initial configuration (stopped state).</li>
367      *     <li>In running state, before queueing any input.</li>
368      *     <li>In running state, after queuing n frames.</li>
369      *     <li>In eos state.</li>
370      * </ul>
371      * In eos state,
372      * <ul>
373      *     <li>reconfigure with same clip.</li>
374      *     <li>reconfigure with different clip (different resolution).</li>
375      * </ul>
376      * <p>
377      * In all situations (pre-reconfigure or post-reconfigure), the test expects the output
378      * timestamps to be strictly increasing. The reconfigure call makes the output received
379      * non-deterministic even for a given input. Hence, besides timestamp checks, no additional
380      * validation is done for outputs received before reconfigure. Post reconfigure, the decode
381      * begins from a sync frame. So the test expects consistent output and this needs to be
382      * identical to the reference. The reference is obtained from the same decoder running in
383      * byte buffer mode.
384      * <p>
385      * The test runs mediacodec in synchronous and asynchronous mode.
386      * <p>
387      * During reconfiguration, the mode of operation is toggled. That is, if first configure
388      * operates the codec in sync mode, then next configure operates the codec in async mode and
389      * so on.
390      */
391     @ApiTest(apis = "android.media.MediaCodec#configure")
392     @LargeTest
393     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testReconfigure()394     public void testReconfigure() throws IOException, InterruptedException {
395         Assume.assumeTrue("Test needs Android 11", IS_AT_LEAST_R);
396 
397         MediaFormat format = setUpSource(mTestFile);
398         mExtractor.release();
399         MediaFormat newFormat = setUpSource(mReconfigFile);
400         mExtractor.release();
401         ArrayList<MediaFormat> formatList = new ArrayList<>();
402         formatList.add(newFormat);
403         checkFormatSupport(mCodecName, mMediaType, false, formatList, null, mSupportRequirements);
404         final long pts = 500000;
405         final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
406         boolean[] boolStates = {true, false};
407         {
408             decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
409             OutputManager ref = mOutputBuff;
410             decodeAndSavePts(mReconfigFile, mCodecName, pts, mode, Integer.MAX_VALUE);
411             OutputManager configRef = mOutputBuff;
412             OutputManager test = new OutputManager(ref.getSharedErrorLogs());
413             OutputManager configTest = new OutputManager(configRef.getSharedErrorLogs());
414             mCodec = MediaCodec.createByCodecName(mCodecName);
415             mActivity.setScreenParams(getWidth(format), getHeight(format), false);
416             for (boolean isAsync : boolStates) {
417                 mOutputBuff = test;
418                 setUpSource(mTestFile);
419                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
420                 configureCodec(format, isAsync, true, false);
421 
422                 /* test reconfigure in stopped state */
423                 reConfigureCodec(format, !isAsync, false, false);
424                 mCodec.start();
425 
426                 /* test reconfigure in running state before queuing input */
427                 reConfigureCodec(format, !isAsync, false, false);
428                 mCodec.start();
429                 doWork(23);
430 
431                 /* test reconfigure codec in running state */
432                 reConfigureCodec(format, isAsync, true, false);
433                 mCodec.start();
434                 test.reset();
435                 mExtractor.seekTo(pts, mode);
436                 doWork(Integer.MAX_VALUE);
437                 queueEOS();
438                 waitForAllOutputs();
439                 mCodec.stop();
440                 if (!(mIsInterlaced ? ref.equalsInterlaced(test) : ref.equals(test))) {
441                     fail("Decoder output in surface mode does not match with output in bytebuffer "
442                             + "mode \n" + mTestConfig + mTestEnv + test.getErrMsg());
443                 }
444 
445                 /* test reconfigure codec at eos state */
446                 reConfigureCodec(format, !isAsync, false, false);
447                 mCodec.start();
448                 test.reset();
449                 mExtractor.seekTo(pts, mode);
450                 doWork(Integer.MAX_VALUE);
451                 queueEOS();
452                 waitForAllOutputs();
453                 mCodec.stop();
454                 if (!(mIsInterlaced ? ref.equalsInterlaced(test) : ref.equals(test))) {
455                     fail("Decoder output in surface mode does not match with output in bytebuffer "
456                             + "mode \n" + mTestConfig + mTestEnv + test.getErrMsg());
457                 }
458                 mExtractor.release();
459 
460                 /* test reconfigure codec for new file */
461                 mOutputBuff = configTest;
462                 setUpSource(mReconfigFile);
463                 mActivity.setScreenParams(getWidth(newFormat), getHeight(newFormat), true);
464                 reConfigureCodec(newFormat, isAsync, false, false);
465                 mCodec.start();
466                 configTest.reset();
467                 mExtractor.seekTo(pts, mode);
468                 doWork(Integer.MAX_VALUE);
469                 queueEOS();
470                 waitForAllOutputs();
471                 mCodec.stop();
472                 if (!(mIsInterlaced ? configRef.equalsInterlaced(configTest) :
473                         configRef.equals(configTest))) {
474                     fail("Decoder output in surface mode does not match with output in bytebuffer "
475                             + "mode \n" + mTestConfig + mTestEnv + configTest.getErrMsg());
476                 }
477                 mExtractor.release();
478             }
479             mCodec.release();
480         }
481     }
482 
nativeTestSimpleDecode(String decoder, Surface surface, String mediaType, String testFile, String refFile, int colorFormat, float rmsError, long checksum, StringBuilder retMsg)483     private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mediaType,
484             String testFile, String refFile, int colorFormat, float rmsError, long checksum,
485             StringBuilder retMsg);
486 
487     /**
488      * Tests is similar to {@link #testSimpleDecodeToSurface()} but uses ndk api
489      */
490     @CddTest(requirements = {"2.2.2", "2.3.2", "2.5.2"})
491     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
492     @LargeTest
493     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testSimpleDecodeToSurfaceNative()494     public void testSimpleDecodeToSurfaceNative() throws IOException {
495         MediaFormat format = setUpSource(mTestFile);
496         mExtractor.release();
497         mActivity.setScreenParams(getWidth(format), getHeight(format), false);
498         boolean isPass = nativeTestSimpleDecode(mCodecName, mSurface, mMediaType, mTestFile,
499                 mReconfigFile, format.getInteger(MediaFormat.KEY_COLOR_FORMAT), -1.0f, 0L,
500                 mTestConfig);
501         assertTrue(mTestConfig.toString(), isPass);
502     }
503 
nativeTestFlush(String decoder, Surface surface, String mediaType, String testFile, int colorFormat, StringBuilder retMsg)504     private native boolean nativeTestFlush(String decoder, Surface surface, String mediaType,
505             String testFile, int colorFormat, StringBuilder retMsg);
506 
507     /**
508      * Test is similar to {@link #testFlush()} but uses ndk api
509      */
510     @ApiTest(apis = {"android.media.MediaCodec#flush"})
511     @LargeTest
512     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testFlushNative()513     public void testFlushNative() throws IOException {
514         MediaFormat format = setUpSource(mTestFile);
515         mExtractor.release();
516         mActivity.setScreenParams(getWidth(format), getHeight(format), true);
517         boolean isPass = nativeTestFlush(mCodecName, mSurface, mMediaType, mTestFile,
518                 format.getInteger(MediaFormat.KEY_COLOR_FORMAT), mTestConfig);
519         assertTrue(mTestConfig.toString(), isPass);
520     }
521 }
522