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 android.media.MediaCodec; 20 import android.media.MediaCodecInfo; 21 import android.media.MediaCodecList; 22 import android.media.MediaExtractor; 23 import android.media.MediaFormat; 24 import android.media.MediaMuxer; 25 import android.util.Log; 26 import android.util.Pair; 27 import android.view.Surface; 28 29 import androidx.test.filters.LargeTest; 30 import androidx.test.platform.app.InstrumentationRegistry; 31 32 import org.junit.Before; 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.Parameterized; 36 37 import java.io.File; 38 import java.io.IOException; 39 import java.nio.ByteBuffer; 40 import java.util.Arrays; 41 import java.util.Collection; 42 import java.util.List; 43 44 import static org.junit.Assert.assertTrue; 45 import static org.junit.Assert.fail; 46 47 @RunWith(Parameterized.class) 48 public class CodecEncoderSurfaceTest { 49 private static final String LOG_TAG = CodecEncoderSurfaceTest.class.getSimpleName(); 50 private static final String mInpPrefix = WorkDir.getMediaDirString(); 51 private static final boolean ENABLE_LOGS = false; 52 53 private final String mCompName; 54 private final String mMime; 55 private final String mTestFile; 56 private final int mBitrate; 57 private final int mFrameRate; 58 private final int mMaxBFrames; 59 private int mLatency; 60 private boolean mReviseLatency; 61 62 private MediaExtractor mExtractor; 63 private MediaCodec mEncoder; 64 private CodecAsyncHandler mAsyncHandleEncoder; 65 private MediaCodec mDecoder; 66 private CodecAsyncHandler mAsyncHandleDecoder; 67 private boolean mIsCodecInAsyncMode; 68 private boolean mSignalEOSWithLastFrame; 69 private boolean mSawDecInputEOS; 70 private boolean mSawDecOutputEOS; 71 private boolean mSawEncOutputEOS; 72 private int mDecInputCount; 73 private int mDecOutputCount; 74 private int mEncOutputCount; 75 76 private boolean mSaveToMem; 77 private OutputManager mOutputBuff; 78 79 private Surface mSurface; 80 81 private MediaMuxer mMuxer; 82 private int mTrackID = -1; 83 84 static { 85 android.os.Bundle args = InstrumentationRegistry.getArguments(); 86 CodecTestBase.mimeSelKeys = args.getString(CodecTestBase.MIME_SEL_KEY); 87 } 88 CodecEncoderSurfaceTest(String encoder, String mime, String testFile, int bitrate, int frameRate)89 public CodecEncoderSurfaceTest(String encoder, String mime, String testFile, int bitrate, 90 int frameRate) { 91 mCompName = encoder; 92 mMime = mime; 93 mTestFile = testFile; 94 mBitrate = bitrate; 95 mFrameRate = frameRate; 96 mMaxBFrames = 0; 97 mLatency = mMaxBFrames; 98 mReviseLatency = false; 99 mAsyncHandleDecoder = new CodecAsyncHandler(); 100 mAsyncHandleEncoder = new CodecAsyncHandler(); 101 } 102 103 @Before isCodecNameValid()104 public void isCodecNameValid() { 105 if (mCompName.startsWith(CodecTestBase.INVALID_CODEC)) { 106 fail("no valid component available for current test "); 107 } 108 } 109 110 @Parameterized.Parameters(name = "{index}({0}_{1})") input()111 public static Collection<Object[]> input() { 112 final boolean isEncoder = true; 113 final boolean needAudio = false; 114 final boolean needVideo = true; 115 final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{ 116 // Video - CodecMime, test file, bit rate, frame rate 117 {MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp", 128000, 15}, 118 {MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_128x96_64kbps_12fps_mpeg4.mp4", 64000, 12}, 119 {MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_cif_768kbps_30fps_avc.mp4", 512000, 30}, 120 {MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_cif_768kbps_30fps_avc.mp4", 512000, 30}, 121 {MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_cif_768kbps_30fps_avc.mp4", 512000, 30}, 122 {MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_cif_768kbps_30fps_avc.mp4", 512000, 30}, 123 {MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_cif_768kbps_30fps_avc.mp4", 512000, 30}, 124 }); 125 return CodecTestBase.prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, 126 true); 127 } 128 hasSeenError()129 private boolean hasSeenError() { 130 return mAsyncHandleDecoder.hasSeenError() || mAsyncHandleEncoder.hasSeenError(); 131 } 132 setUpSource(String srcFile)133 private MediaFormat setUpSource(String srcFile) throws IOException { 134 mExtractor = new MediaExtractor(); 135 mExtractor.setDataSource(mInpPrefix + srcFile); 136 for (int trackID = 0; trackID < mExtractor.getTrackCount(); trackID++) { 137 MediaFormat format = mExtractor.getTrackFormat(trackID); 138 String mime = format.getString(MediaFormat.KEY_MIME); 139 if (mime.startsWith("video/")) { 140 mExtractor.selectTrack(trackID); 141 // COLOR_FormatYUV420Flexible by default should be supported by all components 142 // This call shouldn't effect configure() call for any codec 143 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, 144 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible); 145 return format; 146 } 147 } 148 mExtractor.release(); 149 fail("No video track found in file: " + srcFile); 150 return null; 151 } 152 resetContext(boolean isAsync, boolean signalEOSWithLastFrame)153 private void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) { 154 mAsyncHandleDecoder.resetContext(); 155 mAsyncHandleEncoder.resetContext(); 156 mIsCodecInAsyncMode = isAsync; 157 mSignalEOSWithLastFrame = signalEOSWithLastFrame; 158 mSawDecInputEOS = false; 159 mSawDecOutputEOS = false; 160 mSawEncOutputEOS = false; 161 mDecInputCount = 0; 162 mDecOutputCount = 0; 163 mEncOutputCount = 0; 164 } 165 configureCodec(MediaFormat decFormat, MediaFormat encFormat, boolean isAsync, boolean signalEOSWithLastFrame)166 private void configureCodec(MediaFormat decFormat, MediaFormat encFormat, boolean isAsync, 167 boolean signalEOSWithLastFrame) { 168 resetContext(isAsync, signalEOSWithLastFrame); 169 mAsyncHandleEncoder.setCallBack(mEncoder, isAsync); 170 mEncoder.configure(encFormat, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null); 171 if (mEncoder.getInputFormat().containsKey(MediaFormat.KEY_LATENCY)) { 172 mReviseLatency = true; 173 mLatency = mEncoder.getInputFormat().getInteger(MediaFormat.KEY_LATENCY); 174 } 175 mSurface = mEncoder.createInputSurface(); 176 assertTrue("Surface is not valid", mSurface.isValid()); 177 mAsyncHandleDecoder.setCallBack(mDecoder, isAsync); 178 mDecoder.configure(decFormat, mSurface, null, 0); 179 if (ENABLE_LOGS) { 180 Log.v(LOG_TAG, "codec configured"); 181 } 182 } 183 enqueueDecoderEOS(int bufferIndex)184 private void enqueueDecoderEOS(int bufferIndex) { 185 if (!mSawDecInputEOS) { 186 mDecoder.queueInputBuffer(bufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 187 mSawDecInputEOS = true; 188 if (ENABLE_LOGS) { 189 Log.v(LOG_TAG, "Queued End of Stream"); 190 } 191 } 192 } 193 enqueueDecoderInput(int bufferIndex)194 private void enqueueDecoderInput(int bufferIndex) { 195 if (mExtractor.getSampleSize() < 0) { 196 enqueueDecoderEOS(bufferIndex); 197 } else { 198 ByteBuffer inputBuffer = mDecoder.getInputBuffer(bufferIndex); 199 mExtractor.readSampleData(inputBuffer, 0); 200 int size = (int) mExtractor.getSampleSize(); 201 long pts = mExtractor.getSampleTime(); 202 int extractorFlags = mExtractor.getSampleFlags(); 203 int codecFlags = 0; 204 if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) { 205 codecFlags |= MediaCodec.BUFFER_FLAG_KEY_FRAME; 206 } 207 if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_PARTIAL_FRAME) != 0) { 208 codecFlags |= MediaCodec.BUFFER_FLAG_PARTIAL_FRAME; 209 } 210 if (!mExtractor.advance() && mSignalEOSWithLastFrame) { 211 codecFlags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM; 212 mSawDecInputEOS = true; 213 } 214 if (ENABLE_LOGS) { 215 Log.v(LOG_TAG, "input: id: " + bufferIndex + " size: " + size + " pts: " + pts + 216 " flags: " + codecFlags); 217 } 218 mDecoder.queueInputBuffer(bufferIndex, 0, size, pts, codecFlags); 219 if (size > 0 && (codecFlags & (MediaCodec.BUFFER_FLAG_CODEC_CONFIG | 220 MediaCodec.BUFFER_FLAG_PARTIAL_FRAME)) == 0) { 221 mOutputBuff.saveInPTS(pts); 222 mDecInputCount++; 223 } 224 } 225 } 226 dequeueDecoderOutput(int bufferIndex, MediaCodec.BufferInfo info)227 private void dequeueDecoderOutput(int bufferIndex, MediaCodec.BufferInfo info) { 228 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 229 mSawDecOutputEOS = true; 230 } 231 if (ENABLE_LOGS) { 232 Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: " + 233 info.size + " timestamp: " + info.presentationTimeUs); 234 } 235 if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { 236 mDecOutputCount++; 237 } 238 mDecoder.releaseOutputBuffer(bufferIndex, mSurface != null); 239 } 240 dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info)241 private void dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info) { 242 if (ENABLE_LOGS) { 243 Log.v(LOG_TAG, "encoder output: id: " + bufferIndex + " flags: " + info.flags + 244 " size: " + info.size + " timestamp: " + info.presentationTimeUs); 245 } 246 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 247 mSawEncOutputEOS = true; 248 } 249 if (info.size > 0) { 250 ByteBuffer buf = mEncoder.getOutputBuffer(bufferIndex); 251 if (mSaveToMem) { 252 mOutputBuff.saveToMemory(buf, info); 253 } 254 if (mMuxer != null) { 255 if (mTrackID == -1) { 256 mTrackID = mMuxer.addTrack(mEncoder.getOutputFormat()); 257 mMuxer.start(); 258 } 259 mMuxer.writeSampleData(mTrackID, buf, info); 260 } 261 if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { 262 mOutputBuff.saveOutPTS(info.presentationTimeUs); 263 mEncOutputCount++; 264 } 265 } 266 mEncoder.releaseOutputBuffer(bufferIndex, false); 267 } 268 tryEncoderOutput(long timeOutUs)269 private void tryEncoderOutput(long timeOutUs) throws InterruptedException { 270 if (mIsCodecInAsyncMode) { 271 if (!hasSeenError() && !mSawEncOutputEOS) { 272 int retry = 0; 273 while (mReviseLatency) { 274 if (mAsyncHandleEncoder.hasOutputFormatChanged()) { 275 mReviseLatency = false; 276 int actualLatency = mAsyncHandleEncoder.getOutputFormat() 277 .getInteger(MediaFormat.KEY_LATENCY, mLatency); 278 if (mLatency < actualLatency) { 279 mLatency = actualLatency; 280 return; 281 } 282 } else { 283 if (retry > CodecTestBase.RETRY_LIMIT) throw new InterruptedException( 284 "did not receive output format changed for encoder after " + 285 CodecTestBase.Q_DEQ_TIMEOUT_US * CodecTestBase.RETRY_LIMIT + 286 " us"); 287 Thread.sleep(CodecTestBase.Q_DEQ_TIMEOUT_US / 1000); 288 retry ++; 289 } 290 } 291 Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleEncoder.getOutput(); 292 if (element != null) { 293 dequeueEncoderOutput(element.first, element.second); 294 } 295 } 296 } else { 297 MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); 298 if (!mSawEncOutputEOS) { 299 int outputBufferId = mEncoder.dequeueOutputBuffer(outInfo, timeOutUs); 300 if (outputBufferId >= 0) { 301 dequeueEncoderOutput(outputBufferId, outInfo); 302 } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 303 mLatency = mEncoder.getOutputFormat() 304 .getInteger(MediaFormat.KEY_LATENCY, mLatency); 305 } 306 } 307 } 308 } 309 waitForAllEncoderOutputs()310 private void waitForAllEncoderOutputs() throws InterruptedException { 311 if (mIsCodecInAsyncMode) { 312 while (!hasSeenError() && !mSawEncOutputEOS) { 313 tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US); 314 } 315 } else { 316 while (!mSawEncOutputEOS) { 317 tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US); 318 } 319 } 320 } 321 queueEOS()322 private void queueEOS() throws InterruptedException { 323 if (mIsCodecInAsyncMode) { 324 while (!mAsyncHandleDecoder.hasSeenError() && !mSawDecInputEOS) { 325 Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleDecoder.getWork(); 326 if (element != null) { 327 int bufferID = element.first; 328 MediaCodec.BufferInfo info = element.second; 329 if (info != null) { 330 dequeueDecoderOutput(bufferID, info); 331 } else { 332 enqueueDecoderEOS(element.first); 333 } 334 } 335 } 336 } else { 337 MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); 338 while (!mSawDecInputEOS) { 339 int outputBufferId = 340 mDecoder.dequeueOutputBuffer(outInfo, CodecTestBase.Q_DEQ_TIMEOUT_US); 341 if (outputBufferId >= 0) { 342 dequeueDecoderOutput(outputBufferId, outInfo); 343 } 344 int inputBufferId = mDecoder.dequeueInputBuffer(CodecTestBase.Q_DEQ_TIMEOUT_US); 345 if (inputBufferId != -1) { 346 enqueueDecoderEOS(inputBufferId); 347 } 348 } 349 } 350 if (mIsCodecInAsyncMode) { 351 while (!hasSeenError() && !mSawDecOutputEOS) { 352 Pair<Integer, MediaCodec.BufferInfo> decOp = mAsyncHandleDecoder.getOutput(); 353 if (decOp != null) dequeueDecoderOutput(decOp.first, decOp.second); 354 if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream(); 355 if (mDecOutputCount - mEncOutputCount > mLatency) { 356 tryEncoderOutput(-1); 357 } 358 } 359 } else { 360 MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); 361 while (!mSawDecOutputEOS) { 362 int outputBufferId = 363 mDecoder.dequeueOutputBuffer(outInfo, CodecTestBase.Q_DEQ_TIMEOUT_US); 364 if (outputBufferId >= 0) { 365 dequeueDecoderOutput(outputBufferId, outInfo); 366 } 367 if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream(); 368 if (mDecOutputCount - mEncOutputCount > mLatency) { 369 tryEncoderOutput(-1); 370 } 371 } 372 } 373 } 374 doWork(int frameLimit)375 private void doWork(int frameLimit) throws InterruptedException { 376 int frameCnt = 0; 377 if (mIsCodecInAsyncMode) { 378 // dequeue output after inputEOS is expected to be done in waitForAllOutputs() 379 while (!hasSeenError() && !mSawDecInputEOS && frameCnt < frameLimit) { 380 Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleDecoder.getWork(); 381 if (element != null) { 382 int bufferID = element.first; 383 MediaCodec.BufferInfo info = element.second; 384 if (info != null) { 385 // <id, info> corresponds to output callback. Handle it accordingly 386 dequeueDecoderOutput(bufferID, info); 387 } else { 388 // <id, null> corresponds to input callback. Handle it accordingly 389 enqueueDecoderInput(bufferID); 390 frameCnt++; 391 } 392 } 393 // check decoder EOS 394 if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream(); 395 // encoder output 396 if (mDecOutputCount - mEncOutputCount > mLatency) { 397 tryEncoderOutput(-1); 398 } 399 } 400 } else { 401 MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); 402 while (!mSawDecInputEOS && frameCnt < frameLimit) { 403 // decoder input 404 int inputBufferId = mDecoder.dequeueInputBuffer(CodecTestBase.Q_DEQ_TIMEOUT_US); 405 if (inputBufferId != -1) { 406 enqueueDecoderInput(inputBufferId); 407 frameCnt++; 408 } 409 // decoder output 410 int outputBufferId = 411 mDecoder.dequeueOutputBuffer(outInfo, CodecTestBase.Q_DEQ_TIMEOUT_US); 412 if (outputBufferId >= 0) { 413 dequeueDecoderOutput(outputBufferId, outInfo); 414 } 415 // check decoder EOS 416 if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream(); 417 // encoder output 418 if (mDecOutputCount - mEncOutputCount > mLatency) { 419 tryEncoderOutput(-1); 420 } 421 } 422 } 423 } 424 setUpEncoderFormat(MediaFormat decoderFormat)425 private MediaFormat setUpEncoderFormat(MediaFormat decoderFormat) { 426 MediaFormat encoderFormat = new MediaFormat(); 427 encoderFormat.setString(MediaFormat.KEY_MIME, mMime); 428 encoderFormat.setInteger(MediaFormat.KEY_WIDTH, 429 decoderFormat.getInteger(MediaFormat.KEY_WIDTH)); 430 encoderFormat.setInteger(MediaFormat.KEY_HEIGHT, 431 decoderFormat.getInteger(MediaFormat.KEY_HEIGHT)); 432 encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate); 433 encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate); 434 encoderFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f); 435 encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, 436 MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); 437 encoderFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames); 438 return encoderFormat; 439 } 440 441 /** 442 * Tests listed encoder components for sync and async mode in surface mode.The output has to 443 * be consistent (not flaky) in all runs. 444 */ 445 @LargeTest 446 @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) testSimpleEncodeFromSurface()447 public void testSimpleEncodeFromSurface() throws IOException, InterruptedException { 448 MediaFormat decoderFormat = setUpSource(mTestFile); 449 MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 450 String decoder = codecList.findDecoderForFormat(decoderFormat); 451 if (decoder == null) { 452 mExtractor.release(); 453 fail("no suitable decoder found for format: " + decoderFormat.toString()); 454 } 455 mDecoder = MediaCodec.createByCodecName(decoder); 456 MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat); 457 boolean muxOutput = true; 458 { 459 mEncoder = MediaCodec.createByCodecName(mCompName); 460 /* TODO(b/149027258) */ 461 mSaveToMem = false; 462 OutputManager ref = new OutputManager(); 463 OutputManager test = new OutputManager(); 464 int loopCounter = 0; 465 boolean[] boolStates = {true, false}; 466 for (boolean isAsync : boolStates) { 467 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC); 468 mOutputBuff = loopCounter == 0 ? ref : test; 469 mOutputBuff.reset(); 470 if (muxOutput && loopCounter == 0) { 471 String tmpPath; 472 int muxerFormat; 473 if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) || 474 mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) { 475 muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM; 476 tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath(); 477 } else { 478 muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4; 479 tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath(); 480 } 481 mMuxer = new MediaMuxer(tmpPath, muxerFormat); 482 } 483 configureCodec(decoderFormat, encoderFormat, isAsync, false); 484 mEncoder.start(); 485 mDecoder.start(); 486 doWork(Integer.MAX_VALUE); 487 queueEOS(); 488 waitForAllEncoderOutputs(); 489 if (muxOutput) { 490 if (mTrackID != -1) { 491 mMuxer.stop(); 492 mTrackID = -1; 493 } 494 if (mMuxer != null) { 495 mMuxer.release(); 496 mMuxer = null; 497 } 498 } 499 /* TODO(b/147348711) */ 500 if (false) mDecoder.stop(); 501 else mDecoder.reset(); 502 /* TODO(b/147348711) */ 503 if (false) mEncoder.stop(); 504 else mEncoder.reset(); 505 String log = String.format( 506 "format: %s \n codec: %s, file: %s, mode: %s:: ", 507 encoderFormat, mCompName, mTestFile, (isAsync ? "async" : "sync")); 508 assertTrue(log + " unexpected error", !hasSeenError()); 509 assertTrue(log + "no input sent", 0 != mDecInputCount); 510 assertTrue(log + "no decoder output received", 0 != mDecOutputCount); 511 assertTrue(log + "no encoder output received", 0 != mEncOutputCount); 512 assertTrue(log + "decoder input count != output count, act/exp: " + 513 mDecOutputCount + 514 " / " + mDecInputCount, mDecInputCount == mDecOutputCount); 515 /* TODO(b/153127506) 516 * Currently disabling all encoder output checks. Added checks only for encoder 517 * timeStamp is in increasing order or not. 518 * Once issue is fixed remove increasing timestamp check and enable encoder checks. 519 */ 520 /*assertTrue(log + "encoder output count != decoder output count, act/exp: " + 521 mEncOutputCount + " / " + mDecOutputCount, 522 mEncOutputCount == mDecOutputCount); 523 if (loopCounter != 0) { 524 assertTrue(log + "encoder output is flaky", ref.equals(test)); 525 } else { 526 assertTrue(log + " input pts list and output pts list are not identical", 527 ref.isOutPtsListIdenticalToInpPtsList((false))); 528 }*/ 529 if (loopCounter != 0) { 530 assertTrue("test output pts is not strictly increasing", 531 test.isPtsStrictlyIncreasing(Long.MIN_VALUE)); 532 } else { 533 assertTrue("ref output pts is not strictly increasing", 534 ref.isPtsStrictlyIncreasing(Long.MIN_VALUE)); 535 } 536 loopCounter++; 537 mSurface.release(); 538 mSurface = null; 539 } 540 mEncoder.release(); 541 } 542 mDecoder.release(); 543 mExtractor.release(); 544 } 545 nativeTestSimpleEncode(String encoder, String decoder, String mime, String testFile, String muxFile, int bitrate, int framerate)546 private native boolean nativeTestSimpleEncode(String encoder, String decoder, String mime, 547 String testFile, String muxFile, int bitrate, int framerate); 548 549 @LargeTest 550 @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) testSimpleEncodeFromSurfaceNative()551 public void testSimpleEncodeFromSurfaceNative() throws IOException { 552 MediaFormat decoderFormat = setUpSource(mTestFile); 553 MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 554 String decoder = codecList.findDecoderForFormat(decoderFormat); 555 if (decoder == null) { 556 mExtractor.release(); 557 fail("no suitable decoder found for format: " + decoderFormat.toString()); 558 } 559 { 560 String tmpPath; 561 if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) || 562 mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) { 563 tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath(); 564 } else { 565 tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath(); 566 } 567 assertTrue(nativeTestSimpleEncode(mCompName, decoder, mMime, mInpPrefix + mTestFile, 568 tmpPath, mBitrate, mFrameRate)); 569 } 570 } 571 } 572