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