1 /* 2 * Copyright 2014 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.cts; 18 19 import android.media.cts.R; 20 21 import android.media.cts.CodecUtils; 22 23 import android.graphics.ImageFormat; 24 import android.graphics.SurfaceTexture; 25 import android.media.Image; 26 import android.media.MediaCodec; 27 import android.media.MediaCodec.BufferInfo; 28 import android.media.MediaCodecInfo; 29 import android.media.MediaCodecInfo.CodecCapabilities; 30 import android.media.MediaCodecInfo.VideoCapabilities; 31 import android.media.MediaCodecList; 32 import android.media.MediaExtractor; 33 import android.media.MediaFormat; 34 import android.media.MediaMuxer; 35 import android.net.Uri; 36 import android.platform.test.annotations.AppModeFull; 37 import android.util.Log; 38 import android.util.Pair; 39 import android.util.Range; 40 import android.util.Size; 41 import android.view.Surface; 42 43 import androidx.test.filters.SmallTest; 44 45 import com.android.compatibility.common.util.MediaUtils; 46 47 import java.io.File; 48 import java.io.IOException; 49 import java.nio.ByteBuffer; 50 import java.util.ArrayList; 51 import java.util.function.Consumer; 52 import java.util.function.Function; 53 import java.util.HashMap; 54 import java.util.HashSet; 55 import java.util.Iterator; 56 import java.util.LinkedList; 57 import java.util.Map; 58 import java.util.Set; 59 60 @MediaHeavyPresubmitTest 61 @AppModeFull(reason = "TODO: evaluate and port to instant") 62 public class VideoEncoderTest extends MediaPlayerTestBase { 63 private static final int MAX_SAMPLE_SIZE = 256 * 1024; 64 private static final String TAG = "VideoEncoderTest"; 65 private static final long FRAME_TIMEOUT_MS = 1000; 66 // use larger delay before we get first frame, some encoders may need more time 67 private static final long INIT_TIMEOUT_MS = 2000; 68 69 private static final String SOURCE_URL = 70 "android.resource://android.media.cts/raw/video_480x360_mp4_h264_871kbps_30fps"; 71 72 private final boolean DEBUG = false; 73 74 class VideoStorage { 75 private LinkedList<Pair<ByteBuffer, BufferInfo>> mStream; 76 private MediaFormat mFormat; 77 private int mInputBufferSize; 78 VideoStorage()79 public VideoStorage() { 80 mStream = new LinkedList<Pair<ByteBuffer, BufferInfo>>(); 81 } 82 setFormat(MediaFormat format)83 public void setFormat(MediaFormat format) { 84 mFormat = format; 85 } 86 addBuffer(ByteBuffer buffer, BufferInfo info)87 public void addBuffer(ByteBuffer buffer, BufferInfo info) { 88 ByteBuffer savedBuffer = ByteBuffer.allocate(info.size); 89 savedBuffer.put(buffer); 90 if (info.size > mInputBufferSize) { 91 mInputBufferSize = info.size; 92 } 93 BufferInfo savedInfo = new BufferInfo(); 94 savedInfo.set(0, savedBuffer.position(), info.presentationTimeUs, info.flags); 95 mStream.addLast(Pair.create(savedBuffer, savedInfo)); 96 } 97 play(MediaCodec decoder, Surface surface)98 private void play(MediaCodec decoder, Surface surface) { 99 decoder.reset(); 100 final Object condition = new Object(); 101 final Iterator<Pair<ByteBuffer, BufferInfo>> it = mStream.iterator(); 102 decoder.setCallback(new MediaCodec.Callback() { 103 public void onOutputBufferAvailable(MediaCodec codec, int ix, BufferInfo info) { 104 codec.releaseOutputBuffer(ix, info.size > 0); 105 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 106 synchronized (condition) { 107 condition.notifyAll(); 108 } 109 } 110 } 111 public void onInputBufferAvailable(MediaCodec codec, int ix) { 112 if (it.hasNext()) { 113 Pair<ByteBuffer, BufferInfo> el = it.next(); 114 el.first.clear(); 115 try { 116 codec.getInputBuffer(ix).put(el.first); 117 } catch (java.nio.BufferOverflowException e) { 118 Log.e(TAG, "cannot fit " + el.first.limit() 119 + "-byte encoded buffer into " 120 + codec.getInputBuffer(ix).remaining() 121 + "-byte input buffer of " + codec.getName() 122 + " configured for " + codec.getInputFormat()); 123 throw e; 124 } 125 BufferInfo info = el.second; 126 codec.queueInputBuffer( 127 ix, 0, info.size, info.presentationTimeUs, info.flags); 128 } 129 } 130 public void onError(MediaCodec codec, MediaCodec.CodecException e) { 131 Log.i(TAG, "got codec exception", e); 132 fail("received codec error during decode" + e); 133 } 134 public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { 135 Log.i(TAG, "got output format " + format); 136 } 137 }); 138 mFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, mInputBufferSize); 139 decoder.configure(mFormat, surface, null /* crypto */, 0 /* flags */); 140 decoder.start(); 141 synchronized (condition) { 142 try { 143 condition.wait(); 144 } catch (InterruptedException e) { 145 fail("playback interrupted"); 146 } 147 } 148 decoder.stop(); 149 } 150 playAll(Surface surface)151 public void playAll(Surface surface) { 152 if (mFormat == null) { 153 Log.i(TAG, "no stream to play"); 154 return; 155 } 156 String mime = mFormat.getString(MediaFormat.KEY_MIME); 157 MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 158 for (MediaCodecInfo info : mcl.getCodecInfos()) { 159 if (info.isEncoder()) { 160 continue; 161 } 162 MediaCodec codec = null; 163 try { 164 CodecCapabilities caps = info.getCapabilitiesForType(mime); 165 if (!caps.isFormatSupported(mFormat)) { 166 continue; 167 } 168 codec = MediaCodec.createByCodecName(info.getName()); 169 } catch (IllegalArgumentException | IOException e) { 170 continue; 171 } 172 play(codec, surface); 173 codec.release(); 174 } 175 } 176 } 177 178 abstract class VideoProcessorBase extends MediaCodec.Callback { 179 private static final String TAG = "VideoProcessorBase"; 180 181 /* 182 * Set this to true to save the encoding results to /data/local/tmp 183 * You will need to make /data/local/tmp writeable, run "setenforce 0", 184 * and remove files left from a previous run. 185 */ 186 private boolean mSaveResults = false; 187 private static final String FILE_DIR = "/data/local/tmp"; 188 protected int mMuxIndex = -1; 189 190 protected String mProcessorName = "VideoProcessor"; 191 private MediaExtractor mExtractor; 192 protected MediaMuxer mMuxer; 193 private ByteBuffer mBuffer = ByteBuffer.allocate(MAX_SAMPLE_SIZE); 194 protected int mTrackIndex = -1; 195 private boolean mSignaledDecoderEOS; 196 197 protected boolean mCompleted; 198 protected boolean mEncoderIsActive; 199 protected boolean mEncodeOutputFormatUpdated; 200 protected final Object mCondition = new Object(); 201 protected final Object mCodecLock = new Object(); 202 203 protected MediaFormat mDecFormat; 204 protected MediaCodec mDecoder, mEncoder; 205 206 private VideoStorage mEncodedStream; 207 protected int mFrameRate = 0; 208 protected int mBitRate = 0; 209 210 protected Function<MediaFormat, Boolean> mUpdateConfigFormatHook; 211 protected Function<MediaFormat, Boolean> mCheckOutputFormatHook; 212 setProcessorName(String name)213 public void setProcessorName(String name) { 214 mProcessorName = name; 215 } 216 setUpdateConfigHook(Function<MediaFormat, Boolean> hook)217 public void setUpdateConfigHook(Function<MediaFormat, Boolean> hook) { 218 mUpdateConfigFormatHook = hook; 219 } 220 setCheckOutputFormatHook(Function<MediaFormat, Boolean> hook)221 public void setCheckOutputFormatHook(Function<MediaFormat, Boolean> hook) { 222 mCheckOutputFormatHook = hook; 223 } 224 open(String path)225 protected void open(String path) throws IOException { 226 mExtractor = new MediaExtractor(); 227 if (path.startsWith("android.resource://")) { 228 mExtractor.setDataSource(mContext, Uri.parse(path), null); 229 } else { 230 mExtractor.setDataSource(path); 231 } 232 233 for (int i = 0; i < mExtractor.getTrackCount(); i++) { 234 MediaFormat fmt = mExtractor.getTrackFormat(i); 235 String mime = fmt.getString(MediaFormat.KEY_MIME).toLowerCase(); 236 if (mime.startsWith("video/")) { 237 mTrackIndex = i; 238 mDecFormat = fmt; 239 mExtractor.selectTrack(i); 240 break; 241 } 242 } 243 mEncodedStream = new VideoStorage(); 244 assertTrue("file " + path + " has no video", mTrackIndex >= 0); 245 } 246 247 // returns true if encoder supports the size initCodecsAndConfigureEncoder( String videoEncName, String outMime, int width, int height, int colorFormat)248 protected boolean initCodecsAndConfigureEncoder( 249 String videoEncName, String outMime, int width, int height, 250 int colorFormat) throws IOException { 251 mDecFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); 252 253 MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 254 String videoDecName = mcl.findDecoderForFormat(mDecFormat); 255 Log.i(TAG, "decoder for " + mDecFormat + " is " + videoDecName); 256 mDecoder = MediaCodec.createByCodecName(videoDecName); 257 mEncoder = MediaCodec.createByCodecName(videoEncName); 258 259 mDecoder.setCallback(this); 260 mEncoder.setCallback(this); 261 262 VideoCapabilities encCaps = 263 mEncoder.getCodecInfo().getCapabilitiesForType(outMime).getVideoCapabilities(); 264 if (!encCaps.isSizeSupported(width, height)) { 265 Log.i(TAG, videoEncName + " does not support size: " + width + "x" + height); 266 return false; 267 } 268 269 MediaFormat outFmt = MediaFormat.createVideoFormat(outMime, width, height); 270 int bitRate = 0; 271 MediaUtils.setMaxEncoderFrameAndBitrates(encCaps, outFmt, 30); 272 if (mFrameRate > 0) { 273 outFmt.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate); 274 } 275 if (mBitRate > 0) { 276 outFmt.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate); 277 } 278 outFmt.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); 279 outFmt.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); 280 // Some extra configure before starting the encoder. 281 if (mUpdateConfigFormatHook != null) { 282 if (!mUpdateConfigFormatHook.apply(outFmt)) { 283 return false; 284 } 285 } 286 mEncoder.configure(outFmt, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 287 Log.i(TAG, "encoder input format " + mEncoder.getInputFormat() + " from " + outFmt); 288 if (mSaveResults) { 289 try { 290 String outFileName = 291 FILE_DIR + mProcessorName + "_" + bitRate + "bps"; 292 if (outMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) || 293 outMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) { 294 mMuxer = new MediaMuxer( 295 outFileName + ".webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM); 296 } else { 297 mMuxer = new MediaMuxer( 298 outFileName + ".mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 299 } 300 // The track can't be added until we have the codec specific data 301 } catch (Exception e) { 302 Log.i(TAG, "couldn't create muxer: " + e); 303 } 304 } 305 return true; 306 } 307 close()308 protected void close() { 309 synchronized (mCodecLock) { 310 if (mDecoder != null) { 311 mDecoder.release(); 312 mDecoder = null; 313 } 314 if (mEncoder != null) { 315 mEncoder.release(); 316 mEncoder = null; 317 } 318 } 319 if (mExtractor != null) { 320 mExtractor.release(); 321 mExtractor = null; 322 } 323 if (mMuxer != null) { 324 mMuxer.stop(); 325 mMuxer.release(); 326 mMuxer = null; 327 } 328 } 329 330 // returns true if filled buffer fillDecoderInputBuffer(int ix)331 protected boolean fillDecoderInputBuffer(int ix) { 332 if (DEBUG) Log.v(TAG, "decoder received input #" + ix); 333 while (!mSignaledDecoderEOS) { 334 int track = mExtractor.getSampleTrackIndex(); 335 if (track >= 0 && track != mTrackIndex) { 336 mExtractor.advance(); 337 continue; 338 } 339 int size = mExtractor.readSampleData(mBuffer, 0); 340 if (size < 0) { 341 // queue decoder input EOS 342 if (DEBUG) Log.v(TAG, "queuing decoder EOS"); 343 mDecoder.queueInputBuffer( 344 ix, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 345 mSignaledDecoderEOS = true; 346 } else { 347 mBuffer.limit(size); 348 mBuffer.position(0); 349 BufferInfo info = new BufferInfo(); 350 info.set( 351 0, mBuffer.limit(), mExtractor.getSampleTime(), 352 mExtractor.getSampleFlags()); 353 mDecoder.getInputBuffer(ix).put(mBuffer); 354 if (DEBUG) Log.v(TAG, "queing input #" + ix + " for decoder with timestamp " 355 + info.presentationTimeUs); 356 mDecoder.queueInputBuffer( 357 ix, 0, mBuffer.limit(), info.presentationTimeUs, 0); 358 } 359 mExtractor.advance(); 360 return true; 361 } 362 return false; 363 } 364 emptyEncoderOutputBuffer(int ix, BufferInfo info)365 protected void emptyEncoderOutputBuffer(int ix, BufferInfo info) { 366 if (DEBUG) Log.v(TAG, "encoder received output #" + ix 367 + " (sz=" + info.size + ", f=" + info.flags 368 + ", ts=" + info.presentationTimeUs + ")"); 369 ByteBuffer outputBuffer = mEncoder.getOutputBuffer(ix); 370 mEncodedStream.addBuffer(outputBuffer, info); 371 372 if (mMuxer != null) { 373 // reset position as addBuffer() modifies it 374 outputBuffer.position(info.offset); 375 outputBuffer.limit(info.offset + info.size); 376 mMuxer.writeSampleData(mMuxIndex, outputBuffer, info); 377 } 378 379 if (!mCompleted) { 380 mEncoder.releaseOutputBuffer(ix, false); 381 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 382 Log.d(TAG, "encoder received output EOS"); 383 synchronized(mCondition) { 384 mCompleted = true; 385 mCondition.notifyAll(); // condition is always satisfied 386 } 387 } else { 388 synchronized(mCondition) { 389 mEncoderIsActive = true; 390 } 391 } 392 } 393 } 394 saveEncoderFormat(MediaFormat format)395 protected void saveEncoderFormat(MediaFormat format) { 396 mEncodedStream.setFormat(format); 397 if (mCheckOutputFormatHook != null) { 398 mCheckOutputFormatHook.apply(format); 399 } 400 if (mMuxer != null) { 401 if (mMuxIndex < 0) { 402 mMuxIndex = mMuxer.addTrack(format); 403 mMuxer.start(); 404 } 405 } 406 } 407 playBack(Surface surface)408 public void playBack(Surface surface) { 409 mEncodedStream.playAll(surface); 410 } 411 setFrameAndBitRates(int frameRate, int bitRate)412 public void setFrameAndBitRates(int frameRate, int bitRate) { 413 mFrameRate = frameRate; 414 mBitRate = bitRate; 415 } 416 417 @Override onInputBufferAvailable(MediaCodec mediaCodec, int ix)418 public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) { 419 synchronized (mCodecLock) { 420 if (mEncoder != null && mDecoder != null) { 421 onInputBufferAvailableLocked(mediaCodec, ix); 422 } 423 } 424 } 425 426 @Override onOutputBufferAvailable( MediaCodec mediaCodec, int ix, BufferInfo info)427 public void onOutputBufferAvailable( 428 MediaCodec mediaCodec, int ix, BufferInfo info) { 429 synchronized (mCodecLock) { 430 if (mEncoder != null && mDecoder != null) { 431 onOutputBufferAvailableLocked(mediaCodec, ix, info); 432 } 433 } 434 } 435 processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)436 public abstract boolean processLoop( 437 String path, String outMime, String videoEncName, 438 int width, int height, boolean optional); onInputBufferAvailableLocked( MediaCodec mediaCodec, int ix)439 protected abstract void onInputBufferAvailableLocked( 440 MediaCodec mediaCodec, int ix); onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)441 protected abstract void onOutputBufferAvailableLocked( 442 MediaCodec mediaCodec, int ix, BufferInfo info); 443 } 444 445 class VideoProcessor extends VideoProcessorBase { 446 private static final String TAG = "VideoProcessor"; 447 private boolean mWorkInProgress; 448 private boolean mGotDecoderEOS; 449 private boolean mSignaledEncoderEOS; 450 451 private LinkedList<Pair<Integer, BufferInfo>> mBuffersToRender = 452 new LinkedList<Pair<Integer, BufferInfo>>(); 453 private LinkedList<Integer> mEncInputBuffers = new LinkedList<Integer>(); 454 455 private int mEncInputBufferSize = -1; 456 457 @Override processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)458 public boolean processLoop( 459 String path, String outMime, String videoEncName, 460 int width, int height, boolean optional) { 461 boolean skipped = true; 462 try { 463 open(path); 464 if (!initCodecsAndConfigureEncoder( 465 videoEncName, outMime, width, height, 466 CodecCapabilities.COLOR_FormatYUV420Flexible)) { 467 assertTrue("could not configure encoder for supported size", optional); 468 return !skipped; 469 } 470 skipped = false; 471 472 mDecoder.configure(mDecFormat, null /* surface */, null /* crypto */, 0); 473 474 mDecoder.start(); 475 mEncoder.start(); 476 477 // main loop - process GL ops as only main thread has GL context 478 while (!mCompleted) { 479 Pair<Integer, BufferInfo> decBuffer = null; 480 int encBuffer = -1; 481 synchronized (mCondition) { 482 try { 483 // wait for an encoder input buffer and a decoder output buffer 484 // Use a timeout to avoid stalling the test if it doesn't arrive. 485 if (!haveBuffers() && !mCompleted) { 486 mCondition.wait(mEncodeOutputFormatUpdated ? 487 FRAME_TIMEOUT_MS : INIT_TIMEOUT_MS); 488 } 489 } catch (InterruptedException ie) { 490 fail("wait interrupted"); // shouldn't happen 491 } 492 if (mCompleted) { 493 break; 494 } 495 if (!haveBuffers()) { 496 if (mEncoderIsActive) { 497 mEncoderIsActive = false; 498 Log.d(TAG, "No more input but still getting output from encoder."); 499 continue; 500 } 501 fail("timed out after " + mBuffersToRender.size() 502 + " decoder output and " + mEncInputBuffers.size() 503 + " encoder input buffers"); 504 } 505 506 if (DEBUG) Log.v(TAG, "got image"); 507 decBuffer = mBuffersToRender.removeFirst(); 508 encBuffer = mEncInputBuffers.removeFirst(); 509 if (isEOSOnlyBuffer(decBuffer)) { 510 queueEncoderEOS(decBuffer, encBuffer); 511 continue; 512 } 513 mWorkInProgress = true; 514 } 515 516 if (mWorkInProgress) { 517 renderDecodedBuffer(decBuffer, encBuffer); 518 synchronized(mCondition) { 519 mWorkInProgress = false; 520 } 521 } 522 } 523 } catch (IOException e) { 524 e.printStackTrace(); 525 fail("received exception " + e); 526 } finally { 527 close(); 528 } 529 return !skipped; 530 } 531 532 @Override onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix)533 public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) { 534 if (mediaCodec == mDecoder) { 535 // fill input buffer from extractor 536 fillDecoderInputBuffer(ix); 537 } else if (mediaCodec == mEncoder) { 538 synchronized(mCondition) { 539 mEncInputBuffers.addLast(ix); 540 tryToPropagateEOS(); 541 if (haveBuffers()) { 542 mCondition.notifyAll(); 543 } 544 } 545 } else { 546 fail("received input buffer on " + mediaCodec.getName()); 547 } 548 } 549 550 @Override onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)551 public void onOutputBufferAvailableLocked( 552 MediaCodec mediaCodec, int ix, BufferInfo info) { 553 if (mediaCodec == mDecoder) { 554 if (DEBUG) Log.v(TAG, "decoder received output #" + ix 555 + " (sz=" + info.size + ", f=" + info.flags 556 + ", ts=" + info.presentationTimeUs + ")"); 557 // render output buffer from decoder 558 if (!mGotDecoderEOS) { 559 boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; 560 // can release empty buffers now 561 if (info.size == 0) { 562 mDecoder.releaseOutputBuffer(ix, false /* render */); 563 ix = -1; // dummy index used by render to not render 564 } 565 synchronized(mCondition) { 566 if (ix < 0 && eos && mBuffersToRender.size() > 0) { 567 // move lone EOS flag to last buffer to be rendered 568 mBuffersToRender.peekLast().second.flags |= 569 MediaCodec.BUFFER_FLAG_END_OF_STREAM; 570 } else if (ix >= 0 || eos) { 571 mBuffersToRender.addLast(Pair.create(ix, info)); 572 } 573 if (eos) { 574 tryToPropagateEOS(); 575 mGotDecoderEOS = true; 576 } 577 if (haveBuffers()) { 578 mCondition.notifyAll(); 579 } 580 } 581 } 582 } else if (mediaCodec == mEncoder) { 583 emptyEncoderOutputBuffer(ix, info); 584 } else { 585 fail("received output buffer on " + mediaCodec.getName()); 586 } 587 } 588 renderDecodedBuffer(Pair<Integer, BufferInfo> decBuffer, int encBuffer)589 private void renderDecodedBuffer(Pair<Integer, BufferInfo> decBuffer, int encBuffer) { 590 // process heavyweight actions under instance lock 591 Image encImage = mEncoder.getInputImage(encBuffer); 592 Image decImage = mDecoder.getOutputImage(decBuffer.first); 593 assertNotNull("could not get encoder image for " + mEncoder.getInputFormat(), encImage); 594 assertNotNull("could not get decoder image for " + mDecoder.getInputFormat(), decImage); 595 assertEquals("incorrect decoder format",decImage.getFormat(), ImageFormat.YUV_420_888); 596 assertEquals("incorrect encoder format", encImage.getFormat(), ImageFormat.YUV_420_888); 597 598 CodecUtils.copyFlexYUVImage(encImage, decImage); 599 600 // TRICKY: need this for queueBuffer 601 if (mEncInputBufferSize < 0) { 602 mEncInputBufferSize = mEncoder.getInputBuffer(encBuffer).capacity(); 603 } 604 Log.d(TAG, "queuing input #" + encBuffer + " for encoder (sz=" 605 + mEncInputBufferSize + ", f=" + decBuffer.second.flags 606 + ", ts=" + decBuffer.second.presentationTimeUs + ")"); 607 mEncoder.queueInputBuffer( 608 encBuffer, 0, mEncInputBufferSize, decBuffer.second.presentationTimeUs, 609 decBuffer.second.flags); 610 if ((decBuffer.second.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 611 mSignaledEncoderEOS = true; 612 } 613 mDecoder.releaseOutputBuffer(decBuffer.first, false /* render */); 614 } 615 616 @Override onError(MediaCodec mediaCodec, MediaCodec.CodecException e)617 public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { 618 fail("received error on " + mediaCodec.getName() + ": " + e); 619 } 620 621 @Override onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)622 public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) { 623 Log.i(TAG, mediaCodec.getName() + " got new output format " + mediaFormat); 624 if (mediaCodec == mEncoder) { 625 mEncodeOutputFormatUpdated = true; 626 saveEncoderFormat(mediaFormat); 627 } 628 } 629 630 // next methods are synchronized on mCondition haveBuffers()631 private boolean haveBuffers() { 632 return mEncInputBuffers.size() > 0 && mBuffersToRender.size() > 0 633 && !mSignaledEncoderEOS; 634 } 635 isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer)636 private boolean isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer) { 637 return decBuffer.first < 0 || decBuffer.second.size == 0; 638 } 639 tryToPropagateEOS()640 protected void tryToPropagateEOS() { 641 if (!mWorkInProgress && haveBuffers() && isEOSOnlyBuffer(mBuffersToRender.getFirst())) { 642 Pair<Integer, BufferInfo> decBuffer = mBuffersToRender.removeFirst(); 643 int encBuffer = mEncInputBuffers.removeFirst(); 644 queueEncoderEOS(decBuffer, encBuffer); 645 } 646 } 647 queueEncoderEOS(Pair<Integer, BufferInfo> decBuffer, int encBuffer)648 void queueEncoderEOS(Pair<Integer, BufferInfo> decBuffer, int encBuffer) { 649 Log.d(TAG, "signaling encoder EOS"); 650 mEncoder.queueInputBuffer(encBuffer, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 651 mSignaledEncoderEOS = true; 652 if (decBuffer.first >= 0) { 653 mDecoder.releaseOutputBuffer(decBuffer.first, false /* render */); 654 } 655 } 656 } 657 658 659 class SurfaceVideoProcessor extends VideoProcessorBase 660 implements SurfaceTexture.OnFrameAvailableListener { 661 private static final String TAG = "SurfaceVideoProcessor"; 662 private boolean mFrameAvailable; 663 private boolean mGotDecoderEOS; 664 private boolean mSignaledEncoderEOS; 665 666 private InputSurface mEncSurface; 667 private OutputSurface mDecSurface; 668 private BufferInfo mInfoOnSurface; 669 670 private LinkedList<Pair<Integer, BufferInfo>> mBuffersToRender = 671 new LinkedList<Pair<Integer, BufferInfo>>(); 672 673 @Override processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)674 public boolean processLoop( 675 String path, String outMime, String videoEncName, 676 int width, int height, boolean optional) { 677 boolean skipped = true; 678 try { 679 open(path); 680 if (!initCodecsAndConfigureEncoder( 681 videoEncName, outMime, width, height, 682 CodecCapabilities.COLOR_FormatSurface)) { 683 assertTrue("could not configure encoder for supported size", optional); 684 return !skipped; 685 } 686 skipped = false; 687 688 mEncSurface = new InputSurface(mEncoder.createInputSurface()); 689 mEncSurface.makeCurrent(); 690 691 mDecSurface = new OutputSurface(this); 692 //mDecSurface.changeFragmentShader(FRAGMENT_SHADER); 693 mDecoder.configure(mDecFormat, mDecSurface.getSurface(), null /* crypto */, 0); 694 695 mDecoder.start(); 696 mEncoder.start(); 697 698 // main loop - process GL ops as only main thread has GL context 699 while (!mCompleted) { 700 BufferInfo info = null; 701 synchronized (mCondition) { 702 try { 703 // wait for mFrameAvailable, which is set by onFrameAvailable(). 704 // Use a timeout to avoid stalling the test if it doesn't arrive. 705 if (!mFrameAvailable && !mCompleted && !mEncoderIsActive) { 706 mCondition.wait(mEncodeOutputFormatUpdated ? 707 FRAME_TIMEOUT_MS : INIT_TIMEOUT_MS); 708 } 709 } catch (InterruptedException ie) { 710 fail("wait interrupted"); // shouldn't happen 711 } 712 if (mCompleted) { 713 break; 714 } 715 if (mEncoderIsActive) { 716 mEncoderIsActive = false; 717 if (DEBUG) Log.d(TAG, "encoder is still active, continue"); 718 continue; 719 } 720 assertTrue("still waiting for image", mFrameAvailable); 721 if (DEBUG) Log.v(TAG, "got image"); 722 info = mInfoOnSurface; 723 } 724 if (info == null) { 725 continue; 726 } 727 if (info.size > 0) { 728 mDecSurface.latchImage(); 729 if (DEBUG) Log.v(TAG, "latched image"); 730 mFrameAvailable = false; 731 732 mDecSurface.drawImage(); 733 Log.d(TAG, "encoding frame at " + info.presentationTimeUs * 1000); 734 735 mEncSurface.setPresentationTime(info.presentationTimeUs * 1000); 736 mEncSurface.swapBuffers(); 737 } 738 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 739 mSignaledEncoderEOS = true; 740 Log.d(TAG, "signaling encoder EOS"); 741 mEncoder.signalEndOfInputStream(); 742 } 743 744 synchronized (mCondition) { 745 mInfoOnSurface = null; 746 if (mBuffersToRender.size() > 0 && mInfoOnSurface == null) { 747 if (DEBUG) Log.v(TAG, "handling postponed frame"); 748 Pair<Integer, BufferInfo> nextBuffer = mBuffersToRender.removeFirst(); 749 renderDecodedBuffer(nextBuffer.first, nextBuffer.second); 750 } 751 } 752 } 753 } catch (IOException e) { 754 e.printStackTrace(); 755 fail("received exception " + e); 756 } finally { 757 close(); 758 if (mEncSurface != null) { 759 mEncSurface.release(); 760 mEncSurface = null; 761 } 762 if (mDecSurface != null) { 763 mDecSurface.release(); 764 mDecSurface = null; 765 } 766 } 767 return !skipped; 768 } 769 770 @Override onFrameAvailable(SurfaceTexture st)771 public void onFrameAvailable(SurfaceTexture st) { 772 if (DEBUG) Log.v(TAG, "new frame available"); 773 synchronized (mCondition) { 774 assertFalse("mFrameAvailable already set, frame could be dropped", mFrameAvailable); 775 mFrameAvailable = true; 776 mCondition.notifyAll(); 777 } 778 } 779 780 @Override onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix)781 public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) { 782 if (mediaCodec == mDecoder) { 783 // fill input buffer from extractor 784 fillDecoderInputBuffer(ix); 785 } else { 786 fail("received input buffer on " + mediaCodec.getName()); 787 } 788 } 789 790 @Override onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)791 public void onOutputBufferAvailableLocked( 792 MediaCodec mediaCodec, int ix, BufferInfo info) { 793 if (mediaCodec == mDecoder) { 794 if (DEBUG) Log.v(TAG, "decoder received output #" + ix 795 + " (sz=" + info.size + ", f=" + info.flags 796 + ", ts=" + info.presentationTimeUs + ")"); 797 // render output buffer from decoder 798 if (!mGotDecoderEOS) { 799 boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; 800 if (eos) { 801 mGotDecoderEOS = true; 802 } 803 // can release empty buffers now 804 if (info.size == 0) { 805 mDecoder.releaseOutputBuffer(ix, false /* render */); 806 ix = -1; // dummy index used by render to not render 807 } 808 if (eos || info.size > 0) { 809 synchronized(mCondition) { 810 if (mInfoOnSurface != null || mBuffersToRender.size() > 0) { 811 if (DEBUG) Log.v(TAG, "postponing render, surface busy"); 812 mBuffersToRender.addLast(Pair.create(ix, info)); 813 } else { 814 renderDecodedBuffer(ix, info); 815 } 816 } 817 } 818 } 819 } else if (mediaCodec == mEncoder) { 820 emptyEncoderOutputBuffer(ix, info); 821 synchronized(mCondition) { 822 if (!mCompleted) { 823 mEncoderIsActive = true; 824 mCondition.notifyAll(); 825 } 826 } 827 } else { 828 fail("received output buffer on " + mediaCodec.getName()); 829 } 830 } 831 renderDecodedBuffer(int ix, BufferInfo info)832 private void renderDecodedBuffer(int ix, BufferInfo info) { 833 boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; 834 mInfoOnSurface = info; 835 if (info.size > 0) { 836 Log.d(TAG, "rendering frame #" + ix + " at " + info.presentationTimeUs * 1000 837 + (eos ? " with EOS" : "")); 838 mDecoder.releaseOutputBuffer(ix, info.presentationTimeUs * 1000); 839 } 840 841 if (eos && info.size == 0) { 842 if (DEBUG) Log.v(TAG, "decoder output EOS available"); 843 mFrameAvailable = true; 844 mCondition.notifyAll(); 845 } 846 } 847 848 @Override onError(MediaCodec mediaCodec, MediaCodec.CodecException e)849 public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { 850 fail("received error on " + mediaCodec.getName() + ": " + e); 851 } 852 853 @Override onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)854 public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) { 855 Log.i(TAG, mediaCodec.getName() + " got new output format " + mediaFormat); 856 if (mediaCodec == mEncoder) { 857 mEncodeOutputFormatUpdated = true; 858 saveEncoderFormat(mediaFormat); 859 } 860 } 861 } 862 863 class Encoder { 864 final private String mName; 865 final private String mMime; 866 final private CodecCapabilities mCaps; 867 final private VideoCapabilities mVideoCaps; 868 869 final private Map<Size, Set<Size>> mMinMax; // extreme sizes 870 final private Map<Size, Set<Size>> mNearMinMax; // sizes near extreme 871 final private Set<Size> mArbitraryW; // arbitrary widths in the middle 872 final private Set<Size> mArbitraryH; // arbitrary heights in the middle 873 final private Set<Size> mSizes; // all non-specifically tested sizes 874 875 final private int xAlign; 876 final private int yAlign; 877 Encoder(String name, String mime, CodecCapabilities caps)878 Encoder(String name, String mime, CodecCapabilities caps) { 879 mName = name; 880 mMime = mime; 881 mCaps = caps; 882 mVideoCaps = caps.getVideoCapabilities(); 883 884 /* calculate min/max sizes */ 885 mMinMax = new HashMap<Size, Set<Size>>(); 886 mNearMinMax = new HashMap<Size, Set<Size>>(); 887 mArbitraryW = new HashSet<Size>(); 888 mArbitraryH = new HashSet<Size>(); 889 mSizes = new HashSet<Size>(); 890 891 xAlign = mVideoCaps.getWidthAlignment(); 892 yAlign = mVideoCaps.getHeightAlignment(); 893 894 initializeSizes(); 895 } 896 initializeSizes()897 private void initializeSizes() { 898 for (int x = 0; x < 2; ++x) { 899 for (int y = 0; y < 2; ++y) { 900 addExtremeSizesFor(x, y); 901 } 902 } 903 904 // initialize arbitrary sizes 905 for (int i = 1; i <= 7; ++i) { 906 int j = ((7 * i) % 11) + 1; 907 int width, height; 908 try { 909 width = alignedPointInRange(i * 0.125, xAlign, mVideoCaps.getSupportedWidths()); 910 height = alignedPointInRange( 911 j * 0.077, yAlign, mVideoCaps.getSupportedHeightsFor(width)); 912 mArbitraryW.add(new Size(width, height)); 913 } catch (IllegalArgumentException e) { 914 } 915 916 try { 917 height = alignedPointInRange(i * 0.125, yAlign, mVideoCaps.getSupportedHeights()); 918 width = alignedPointInRange(j * 0.077, xAlign, mVideoCaps.getSupportedWidthsFor(height)); 919 mArbitraryH.add(new Size(width, height)); 920 } catch (IllegalArgumentException e) { 921 } 922 } 923 mArbitraryW.removeAll(mArbitraryH); 924 mArbitraryW.removeAll(mSizes); 925 mSizes.addAll(mArbitraryW); 926 mArbitraryH.removeAll(mSizes); 927 mSizes.addAll(mArbitraryH); 928 if (DEBUG) Log.i(TAG, "arbitrary=" + mArbitraryW + "/" + mArbitraryH); 929 } 930 addExtremeSizesFor(int x, int y)931 private void addExtremeSizesFor(int x, int y) { 932 Set<Size> minMax = new HashSet<Size>(); 933 Set<Size> nearMinMax = new HashSet<Size>(); 934 935 for (int dx = 0; dx <= xAlign; dx += xAlign) { 936 for (int dy = 0; dy <= yAlign; dy += yAlign) { 937 Set<Size> bucket = (dx + dy == 0) ? minMax : nearMinMax; 938 try { 939 int width = getExtreme(mVideoCaps.getSupportedWidths(), x, dx); 940 int height = getExtreme(mVideoCaps.getSupportedHeightsFor(width), y, dy); 941 bucket.add(new Size(width, height)); 942 943 // try max max with more reasonable ratio if too skewed 944 if (x + y == 2 && width >= 4 * height) { 945 Size wideScreen = getLargestSizeForRatio(16, 9); 946 width = getExtreme( 947 mVideoCaps.getSupportedWidths() 948 .intersect(0, wideScreen.getWidth()), x, dx); 949 height = getExtreme(mVideoCaps.getSupportedHeightsFor(width), y, 0); 950 bucket.add(new Size(width, height)); 951 } 952 } catch (IllegalArgumentException e) { 953 } 954 955 try { 956 int height = getExtreme(mVideoCaps.getSupportedHeights(), y, dy); 957 int width = getExtreme(mVideoCaps.getSupportedWidthsFor(height), x, dx); 958 bucket.add(new Size(width, height)); 959 960 // try max max with more reasonable ratio if too skewed 961 if (x + y == 2 && height >= 4 * width) { 962 Size wideScreen = getLargestSizeForRatio(9, 16); 963 height = getExtreme( 964 mVideoCaps.getSupportedHeights() 965 .intersect(0, wideScreen.getHeight()), y, dy); 966 width = getExtreme(mVideoCaps.getSupportedWidthsFor(height), x, dx); 967 bucket.add(new Size(width, height)); 968 } 969 } catch (IllegalArgumentException e) { 970 } 971 } 972 } 973 974 // keep unique sizes 975 minMax.removeAll(mSizes); 976 mSizes.addAll(minMax); 977 nearMinMax.removeAll(mSizes); 978 mSizes.addAll(nearMinMax); 979 980 mMinMax.put(new Size(x, y), minMax); 981 mNearMinMax.put(new Size(x, y), nearMinMax); 982 if (DEBUG) Log.i(TAG, x + "x" + y + ": minMax=" + mMinMax + ", near=" + mNearMinMax); 983 } 984 alignInRange(double value, int align, Range<Integer> range)985 private int alignInRange(double value, int align, Range<Integer> range) { 986 return range.clamp(align * (int)Math.round(value / align)); 987 } 988 989 /* point should be between 0. and 1. */ alignedPointInRange(double point, int align, Range<Integer> range)990 private int alignedPointInRange(double point, int align, Range<Integer> range) { 991 return alignInRange( 992 range.getLower() + point * (range.getUpper() - range.getLower()), align, range); 993 } 994 getExtreme(Range<Integer> range, int i, int delta)995 private int getExtreme(Range<Integer> range, int i, int delta) { 996 int dim = i == 1 ? range.getUpper() - delta : range.getLower() + delta; 997 if (delta == 0 998 || (dim > range.getLower() && dim < range.getUpper())) { 999 return dim; 1000 } 1001 throw new IllegalArgumentException(); 1002 } 1003 getLargestSizeForRatio(int x, int y)1004 private Size getLargestSizeForRatio(int x, int y) { 1005 Range<Integer> widthRange = mVideoCaps.getSupportedWidths(); 1006 Range<Integer> heightRange = mVideoCaps.getSupportedHeightsFor(widthRange.getUpper()); 1007 final int xAlign = mVideoCaps.getWidthAlignment(); 1008 final int yAlign = mVideoCaps.getHeightAlignment(); 1009 1010 // scale by alignment 1011 int width = alignInRange( 1012 Math.sqrt(widthRange.getUpper() * heightRange.getUpper() * (double)x / y), 1013 xAlign, widthRange); 1014 int height = alignInRange( 1015 width * (double)y / x, yAlign, mVideoCaps.getSupportedHeightsFor(width)); 1016 return new Size(width, height); 1017 } 1018 1019 testExtreme(int x, int y, boolean flexYUV, boolean near)1020 public boolean testExtreme(int x, int y, boolean flexYUV, boolean near) { 1021 boolean skipped = true; 1022 for (Size s : (near ? mNearMinMax : mMinMax).get(new Size(x, y))) { 1023 if (test(s.getWidth(), s.getHeight(), false /* optional */, flexYUV)) { 1024 skipped = false; 1025 } 1026 } 1027 return !skipped; 1028 } 1029 testArbitrary(boolean flexYUV, boolean widths)1030 public boolean testArbitrary(boolean flexYUV, boolean widths) { 1031 boolean skipped = true; 1032 for (Size s : (widths ? mArbitraryW : mArbitraryH)) { 1033 if (test(s.getWidth(), s.getHeight(), false /* optional */, flexYUV)) { 1034 skipped = false; 1035 } 1036 } 1037 return !skipped; 1038 } 1039 testSpecific(int width, int height, boolean flexYUV)1040 public boolean testSpecific(int width, int height, boolean flexYUV) { 1041 // already tested by one of the min/max tests 1042 if (mSizes.contains(new Size(width, height))) { 1043 return false; 1044 } 1045 return test(width, height, true /* optional */, flexYUV); 1046 } 1047 testIntraRefresh(int width, int height)1048 public boolean testIntraRefresh(int width, int height) { 1049 if (!mCaps.isFeatureSupported(CodecCapabilities.FEATURE_IntraRefresh)) { 1050 return false; 1051 } 1052 1053 final int refreshPeriod[] = new int[] {10, 13, 17, 22, 29, 38, 50, 60}; 1054 1055 // Test the support of refresh periods in the range of 10 - 60 frames 1056 for (int period : refreshPeriod) { 1057 Function<MediaFormat, Boolean> updateConfigFormatHook = 1058 new Function<MediaFormat, Boolean>() { 1059 public Boolean apply(MediaFormat fmt) { 1060 // set i-frame-interval to 10000 so encoded video only has 1 i-frame. 1061 fmt.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10000); 1062 fmt.setInteger(MediaFormat.KEY_INTRA_REFRESH_PERIOD, period); 1063 return true; 1064 } 1065 }; 1066 1067 Function<MediaFormat, Boolean> checkOutputFormatHook = 1068 new Function<MediaFormat, Boolean>() { 1069 public Boolean apply(MediaFormat fmt) { 1070 int intraPeriod = fmt.getInteger(MediaFormat.KEY_INTRA_REFRESH_PERIOD); 1071 // Make sure intra period is correct and carried in the output format. 1072 // intraPeriod must be larger than 0 and operate within 20% of refresh period. 1073 if (intraPeriod > 1.2 * period || intraPeriod < 0.8 * period) { 1074 throw new RuntimeException("Intra period mismatch"); 1075 } 1076 return true; 1077 } 1078 }; 1079 1080 String testName = 1081 mName + '_' + width + "x" + height + '_' + "flexYUV_intraRefresh"; 1082 1083 Consumer<VideoProcessorBase> configureVideoProcessor = 1084 new Consumer<VideoProcessorBase>() { 1085 public void accept(VideoProcessorBase processor) { 1086 processor.setProcessorName(testName); 1087 processor.setUpdateConfigHook(updateConfigFormatHook); 1088 processor.setCheckOutputFormatHook(checkOutputFormatHook); 1089 } 1090 }; 1091 1092 if (!test(width, height, 0 /* frameRate */, 0 /* bitRate */, true /* optional */, 1093 true /* flex */, configureVideoProcessor)) { 1094 return false; 1095 } 1096 } 1097 1098 return true; 1099 } 1100 testDetailed( int width, int height, int frameRate, int bitRate, boolean flexYUV)1101 public boolean testDetailed( 1102 int width, int height, int frameRate, int bitRate, boolean flexYUV) { 1103 String testName = 1104 mName + '_' + width + "x" + height + '_' + (flexYUV ? "flexYUV" : " surface"); 1105 Consumer<VideoProcessorBase> configureVideoProcessor = 1106 new Consumer<VideoProcessorBase>() { 1107 public void accept(VideoProcessorBase processor) { 1108 processor.setProcessorName(testName); 1109 } 1110 }; 1111 return test(width, height, frameRate, bitRate, true /* optional */, flexYUV, 1112 configureVideoProcessor); 1113 } 1114 testSupport(int width, int height, int frameRate, int bitRate)1115 public boolean testSupport(int width, int height, int frameRate, int bitRate) { 1116 return mVideoCaps.areSizeAndRateSupported(width, height, frameRate) && 1117 mVideoCaps.getBitrateRange().contains(bitRate); 1118 } 1119 test( int width, int height, boolean optional, boolean flexYUV)1120 private boolean test( 1121 int width, int height, boolean optional, boolean flexYUV) { 1122 String testName = 1123 mName + '_' + width + "x" + height + '_' + (flexYUV ? "flexYUV" : " surface"); 1124 Consumer<VideoProcessorBase> configureVideoProcessor = 1125 new Consumer<VideoProcessorBase>() { 1126 public void accept(VideoProcessorBase processor) { 1127 processor.setProcessorName(testName); 1128 } 1129 }; 1130 return test(width, height, 0 /* frameRate */, 0 /* bitRate */, 1131 optional, flexYUV, configureVideoProcessor); 1132 } 1133 test( int width, int height, int frameRate, int bitRate, boolean optional, boolean flexYUV, Consumer<VideoProcessorBase> configureVideoProcessor)1134 private boolean test( 1135 int width, int height, int frameRate, int bitRate, boolean optional, 1136 boolean flexYUV, Consumer<VideoProcessorBase> configureVideoProcessor) { 1137 Log.i(TAG, "testing " + mMime + " on " + mName + " for " + width + "x" + height 1138 + (flexYUV ? " flexYUV" : " surface")); 1139 1140 VideoProcessorBase processor = 1141 flexYUV ? new VideoProcessor() : new SurfaceVideoProcessor(); 1142 1143 processor.setFrameAndBitRates(frameRate, bitRate); 1144 configureVideoProcessor.accept(processor); 1145 1146 // We are using a resource URL as an example 1147 boolean success = processor.processLoop( 1148 SOURCE_URL, mMime, mName, width, height, optional); 1149 if (success) { 1150 processor.playBack(getActivity().getSurfaceHolder().getSurface()); 1151 } 1152 return success; 1153 } 1154 } 1155 googH265()1156 private Encoder[] googH265() { return goog(MediaFormat.MIMETYPE_VIDEO_HEVC); } googH264()1157 private Encoder[] googH264() { return goog(MediaFormat.MIMETYPE_VIDEO_AVC); } googH263()1158 private Encoder[] googH263() { return goog(MediaFormat.MIMETYPE_VIDEO_H263); } googMpeg4()1159 private Encoder[] googMpeg4() { return goog(MediaFormat.MIMETYPE_VIDEO_MPEG4); } googVP8()1160 private Encoder[] googVP8() { return goog(MediaFormat.MIMETYPE_VIDEO_VP8); } googVP9()1161 private Encoder[] googVP9() { return goog(MediaFormat.MIMETYPE_VIDEO_VP9); } 1162 otherH265()1163 private Encoder[] otherH265() { return other(MediaFormat.MIMETYPE_VIDEO_HEVC); } otherH264()1164 private Encoder[] otherH264() { return other(MediaFormat.MIMETYPE_VIDEO_AVC); } otherH263()1165 private Encoder[] otherH263() { return other(MediaFormat.MIMETYPE_VIDEO_H263); } otherMpeg4()1166 private Encoder[] otherMpeg4() { return other(MediaFormat.MIMETYPE_VIDEO_MPEG4); } otherVP8()1167 private Encoder[] otherVP8() { return other(MediaFormat.MIMETYPE_VIDEO_VP8); } otherVP9()1168 private Encoder[] otherVP9() { return other(MediaFormat.MIMETYPE_VIDEO_VP9); } 1169 goog(String mime)1170 private Encoder[] goog(String mime) { 1171 return encoders(mime, true /* goog */); 1172 } 1173 other(String mime)1174 private Encoder[] other(String mime) { 1175 return encoders(mime, false /* goog */); 1176 } 1177 combineArray(Encoder[] a, Encoder[] b)1178 private Encoder[] combineArray(Encoder[] a, Encoder[] b) { 1179 Encoder[] all = new Encoder[a.length + b.length]; 1180 System.arraycopy(a, 0, all, 0, a.length); 1181 System.arraycopy(b, 0, all, a.length, b.length); 1182 return all; 1183 } 1184 h264()1185 private Encoder[] h264() { 1186 return combineArray(googH264(), otherH264()); 1187 } 1188 vp8()1189 private Encoder[] vp8() { 1190 return combineArray(googVP8(), otherVP8()); 1191 } 1192 encoders(String mime, boolean goog)1193 private Encoder[] encoders(String mime, boolean goog) { 1194 MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 1195 ArrayList<Encoder> result = new ArrayList<Encoder>(); 1196 1197 for (MediaCodecInfo info : mcl.getCodecInfos()) { 1198 if (!info.isEncoder() || !info.isVendor() != goog) { 1199 continue; 1200 } 1201 CodecCapabilities caps = null; 1202 try { 1203 caps = info.getCapabilitiesForType(mime); 1204 } catch (IllegalArgumentException e) { // mime is not supported 1205 continue; 1206 } 1207 assertNotNull(info.getName() + " capabilties for " + mime + " returned null", caps); 1208 result.add(new Encoder(info.getName(), mime, caps)); 1209 } 1210 return result.toArray(new Encoder[result.size()]); 1211 } 1212 testGoogH265FlexMinMin()1213 public void testGoogH265FlexMinMin() { minmin(googH265(), true /* flex */); } testGoogH265SurfMinMin()1214 public void testGoogH265SurfMinMin() { minmin(googH265(), false /* flex */); } testGoogH264FlexMinMin()1215 public void testGoogH264FlexMinMin() { minmin(googH264(), true /* flex */); } testGoogH264SurfMinMin()1216 public void testGoogH264SurfMinMin() { minmin(googH264(), false /* flex */); } testGoogH263FlexMinMin()1217 public void testGoogH263FlexMinMin() { minmin(googH263(), true /* flex */); } testGoogH263SurfMinMin()1218 public void testGoogH263SurfMinMin() { minmin(googH263(), false /* flex */); } testGoogMpeg4FlexMinMin()1219 public void testGoogMpeg4FlexMinMin() { minmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMinMin()1220 public void testGoogMpeg4SurfMinMin() { minmin(googMpeg4(), false /* flex */); } testGoogVP8FlexMinMin()1221 public void testGoogVP8FlexMinMin() { minmin(googVP8(), true /* flex */); } testGoogVP8SurfMinMin()1222 public void testGoogVP8SurfMinMin() { minmin(googVP8(), false /* flex */); } testGoogVP9FlexMinMin()1223 public void testGoogVP9FlexMinMin() { minmin(googVP9(), true /* flex */); } testGoogVP9SurfMinMin()1224 public void testGoogVP9SurfMinMin() { minmin(googVP9(), false /* flex */); } 1225 testOtherH265FlexMinMin()1226 public void testOtherH265FlexMinMin() { minmin(otherH265(), true /* flex */); } testOtherH265SurfMinMin()1227 public void testOtherH265SurfMinMin() { minmin(otherH265(), false /* flex */); } testOtherH264FlexMinMin()1228 public void testOtherH264FlexMinMin() { minmin(otherH264(), true /* flex */); } testOtherH264SurfMinMin()1229 public void testOtherH264SurfMinMin() { minmin(otherH264(), false /* flex */); } testOtherH263FlexMinMin()1230 public void testOtherH263FlexMinMin() { minmin(otherH263(), true /* flex */); } testOtherH263SurfMinMin()1231 public void testOtherH263SurfMinMin() { minmin(otherH263(), false /* flex */); } testOtherMpeg4FlexMinMin()1232 public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMinMin()1233 public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexMinMin()1234 public void testOtherVP8FlexMinMin() { minmin(otherVP8(), true /* flex */); } testOtherVP8SurfMinMin()1235 public void testOtherVP8SurfMinMin() { minmin(otherVP8(), false /* flex */); } testOtherVP9FlexMinMin()1236 public void testOtherVP9FlexMinMin() { minmin(otherVP9(), true /* flex */); } testOtherVP9SurfMinMin()1237 public void testOtherVP9SurfMinMin() { minmin(otherVP9(), false /* flex */); } 1238 testGoogH265FlexMinMax()1239 public void testGoogH265FlexMinMax() { minmax(googH265(), true /* flex */); } testGoogH265SurfMinMax()1240 public void testGoogH265SurfMinMax() { minmax(googH265(), false /* flex */); } testGoogH264FlexMinMax()1241 public void testGoogH264FlexMinMax() { minmax(googH264(), true /* flex */); } testGoogH264SurfMinMax()1242 public void testGoogH264SurfMinMax() { minmax(googH264(), false /* flex */); } testGoogH263FlexMinMax()1243 public void testGoogH263FlexMinMax() { minmax(googH263(), true /* flex */); } testGoogH263SurfMinMax()1244 public void testGoogH263SurfMinMax() { minmax(googH263(), false /* flex */); } testGoogMpeg4FlexMinMax()1245 public void testGoogMpeg4FlexMinMax() { minmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMinMax()1246 public void testGoogMpeg4SurfMinMax() { minmax(googMpeg4(), false /* flex */); } testGoogVP8FlexMinMax()1247 public void testGoogVP8FlexMinMax() { minmax(googVP8(), true /* flex */); } testGoogVP8SurfMinMax()1248 public void testGoogVP8SurfMinMax() { minmax(googVP8(), false /* flex */); } testGoogVP9FlexMinMax()1249 public void testGoogVP9FlexMinMax() { minmax(googVP9(), true /* flex */); } testGoogVP9SurfMinMax()1250 public void testGoogVP9SurfMinMax() { minmax(googVP9(), false /* flex */); } 1251 testOtherH265FlexMinMax()1252 public void testOtherH265FlexMinMax() { minmax(otherH265(), true /* flex */); } testOtherH265SurfMinMax()1253 public void testOtherH265SurfMinMax() { minmax(otherH265(), false /* flex */); } testOtherH264FlexMinMax()1254 public void testOtherH264FlexMinMax() { minmax(otherH264(), true /* flex */); } testOtherH264SurfMinMax()1255 public void testOtherH264SurfMinMax() { minmax(otherH264(), false /* flex */); } testOtherH263FlexMinMax()1256 public void testOtherH263FlexMinMax() { minmax(otherH263(), true /* flex */); } testOtherH263SurfMinMax()1257 public void testOtherH263SurfMinMax() { minmax(otherH263(), false /* flex */); } testOtherMpeg4FlexMinMax()1258 public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMinMax()1259 public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexMinMax()1260 public void testOtherVP8FlexMinMax() { minmax(otherVP8(), true /* flex */); } testOtherVP8SurfMinMax()1261 public void testOtherVP8SurfMinMax() { minmax(otherVP8(), false /* flex */); } testOtherVP9FlexMinMax()1262 public void testOtherVP9FlexMinMax() { minmax(otherVP9(), true /* flex */); } testOtherVP9SurfMinMax()1263 public void testOtherVP9SurfMinMax() { minmax(otherVP9(), false /* flex */); } 1264 testGoogH265FlexMaxMin()1265 public void testGoogH265FlexMaxMin() { maxmin(googH265(), true /* flex */); } testGoogH265SurfMaxMin()1266 public void testGoogH265SurfMaxMin() { maxmin(googH265(), false /* flex */); } testGoogH264FlexMaxMin()1267 public void testGoogH264FlexMaxMin() { maxmin(googH264(), true /* flex */); } testGoogH264SurfMaxMin()1268 public void testGoogH264SurfMaxMin() { maxmin(googH264(), false /* flex */); } testGoogH263FlexMaxMin()1269 public void testGoogH263FlexMaxMin() { maxmin(googH263(), true /* flex */); } testGoogH263SurfMaxMin()1270 public void testGoogH263SurfMaxMin() { maxmin(googH263(), false /* flex */); } testGoogMpeg4FlexMaxMin()1271 public void testGoogMpeg4FlexMaxMin() { maxmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMaxMin()1272 public void testGoogMpeg4SurfMaxMin() { maxmin(googMpeg4(), false /* flex */); } testGoogVP8FlexMaxMin()1273 public void testGoogVP8FlexMaxMin() { maxmin(googVP8(), true /* flex */); } testGoogVP8SurfMaxMin()1274 public void testGoogVP8SurfMaxMin() { maxmin(googVP8(), false /* flex */); } testGoogVP9FlexMaxMin()1275 public void testGoogVP9FlexMaxMin() { maxmin(googVP9(), true /* flex */); } testGoogVP9SurfMaxMin()1276 public void testGoogVP9SurfMaxMin() { maxmin(googVP9(), false /* flex */); } 1277 testOtherH265FlexMaxMin()1278 public void testOtherH265FlexMaxMin() { maxmin(otherH265(), true /* flex */); } testOtherH265SurfMaxMin()1279 public void testOtherH265SurfMaxMin() { maxmin(otherH265(), false /* flex */); } testOtherH264FlexMaxMin()1280 public void testOtherH264FlexMaxMin() { maxmin(otherH264(), true /* flex */); } testOtherH264SurfMaxMin()1281 public void testOtherH264SurfMaxMin() { maxmin(otherH264(), false /* flex */); } testOtherH263FlexMaxMin()1282 public void testOtherH263FlexMaxMin() { maxmin(otherH263(), true /* flex */); } testOtherH263SurfMaxMin()1283 public void testOtherH263SurfMaxMin() { maxmin(otherH263(), false /* flex */); } testOtherMpeg4FlexMaxMin()1284 public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMaxMin()1285 public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexMaxMin()1286 public void testOtherVP8FlexMaxMin() { maxmin(otherVP8(), true /* flex */); } testOtherVP8SurfMaxMin()1287 public void testOtherVP8SurfMaxMin() { maxmin(otherVP8(), false /* flex */); } testOtherVP9FlexMaxMin()1288 public void testOtherVP9FlexMaxMin() { maxmin(otherVP9(), true /* flex */); } testOtherVP9SurfMaxMin()1289 public void testOtherVP9SurfMaxMin() { maxmin(otherVP9(), false /* flex */); } 1290 testGoogH265FlexMaxMax()1291 public void testGoogH265FlexMaxMax() { maxmax(googH265(), true /* flex */); } testGoogH265SurfMaxMax()1292 public void testGoogH265SurfMaxMax() { maxmax(googH265(), false /* flex */); } testGoogH264FlexMaxMax()1293 public void testGoogH264FlexMaxMax() { maxmax(googH264(), true /* flex */); } testGoogH264SurfMaxMax()1294 public void testGoogH264SurfMaxMax() { maxmax(googH264(), false /* flex */); } testGoogH263FlexMaxMax()1295 public void testGoogH263FlexMaxMax() { maxmax(googH263(), true /* flex */); } testGoogH263SurfMaxMax()1296 public void testGoogH263SurfMaxMax() { maxmax(googH263(), false /* flex */); } testGoogMpeg4FlexMaxMax()1297 public void testGoogMpeg4FlexMaxMax() { maxmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMaxMax()1298 public void testGoogMpeg4SurfMaxMax() { maxmax(googMpeg4(), false /* flex */); } testGoogVP8FlexMaxMax()1299 public void testGoogVP8FlexMaxMax() { maxmax(googVP8(), true /* flex */); } testGoogVP8SurfMaxMax()1300 public void testGoogVP8SurfMaxMax() { maxmax(googVP8(), false /* flex */); } testGoogVP9FlexMaxMax()1301 public void testGoogVP9FlexMaxMax() { maxmax(googVP9(), true /* flex */); } testGoogVP9SurfMaxMax()1302 public void testGoogVP9SurfMaxMax() { maxmax(googVP9(), false /* flex */); } 1303 testOtherH265FlexMaxMax()1304 public void testOtherH265FlexMaxMax() { maxmax(otherH265(), true /* flex */); } testOtherH265SurfMaxMax()1305 public void testOtherH265SurfMaxMax() { maxmax(otherH265(), false /* flex */); } testOtherH264FlexMaxMax()1306 public void testOtherH264FlexMaxMax() { maxmax(otherH264(), true /* flex */); } testOtherH264SurfMaxMax()1307 public void testOtherH264SurfMaxMax() { maxmax(otherH264(), false /* flex */); } testOtherH263FlexMaxMax()1308 public void testOtherH263FlexMaxMax() { maxmax(otherH263(), true /* flex */); } testOtherH263SurfMaxMax()1309 public void testOtherH263SurfMaxMax() { maxmax(otherH263(), false /* flex */); } testOtherMpeg4FlexMaxMax()1310 public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMaxMax()1311 public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexMaxMax()1312 public void testOtherVP8FlexMaxMax() { maxmax(otherVP8(), true /* flex */); } testOtherVP8SurfMaxMax()1313 public void testOtherVP8SurfMaxMax() { maxmax(otherVP8(), false /* flex */); } testOtherVP9FlexMaxMax()1314 public void testOtherVP9FlexMaxMax() { maxmax(otherVP9(), true /* flex */); } testOtherVP9SurfMaxMax()1315 public void testOtherVP9SurfMaxMax() { maxmax(otherVP9(), false /* flex */); } 1316 testGoogH265FlexNearMinMin()1317 public void testGoogH265FlexNearMinMin() { nearminmin(googH265(), true /* flex */); } testGoogH265SurfNearMinMin()1318 public void testGoogH265SurfNearMinMin() { nearminmin(googH265(), false /* flex */); } testGoogH264FlexNearMinMin()1319 public void testGoogH264FlexNearMinMin() { nearminmin(googH264(), true /* flex */); } testGoogH264SurfNearMinMin()1320 public void testGoogH264SurfNearMinMin() { nearminmin(googH264(), false /* flex */); } testGoogH263FlexNearMinMin()1321 public void testGoogH263FlexNearMinMin() { nearminmin(googH263(), true /* flex */); } testGoogH263SurfNearMinMin()1322 public void testGoogH263SurfNearMinMin() { nearminmin(googH263(), false /* flex */); } testGoogMpeg4FlexNearMinMin()1323 public void testGoogMpeg4FlexNearMinMin() { nearminmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMinMin()1324 public void testGoogMpeg4SurfNearMinMin() { nearminmin(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMinMin()1325 public void testGoogVP8FlexNearMinMin() { nearminmin(googVP8(), true /* flex */); } testGoogVP8SurfNearMinMin()1326 public void testGoogVP8SurfNearMinMin() { nearminmin(googVP8(), false /* flex */); } testGoogVP9FlexNearMinMin()1327 public void testGoogVP9FlexNearMinMin() { nearminmin(googVP9(), true /* flex */); } testGoogVP9SurfNearMinMin()1328 public void testGoogVP9SurfNearMinMin() { nearminmin(googVP9(), false /* flex */); } 1329 testOtherH265FlexNearMinMin()1330 public void testOtherH265FlexNearMinMin() { nearminmin(otherH265(), true /* flex */); } testOtherH265SurfNearMinMin()1331 public void testOtherH265SurfNearMinMin() { nearminmin(otherH265(), false /* flex */); } testOtherH264FlexNearMinMin()1332 public void testOtherH264FlexNearMinMin() { nearminmin(otherH264(), true /* flex */); } testOtherH264SurfNearMinMin()1333 public void testOtherH264SurfNearMinMin() { nearminmin(otherH264(), false /* flex */); } testOtherH263FlexNearMinMin()1334 public void testOtherH263FlexNearMinMin() { nearminmin(otherH263(), true /* flex */); } testOtherH263SurfNearMinMin()1335 public void testOtherH263SurfNearMinMin() { nearminmin(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMinMin()1336 public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMinMin()1337 public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMinMin()1338 public void testOtherVP8FlexNearMinMin() { nearminmin(otherVP8(), true /* flex */); } testOtherVP8SurfNearMinMin()1339 public void testOtherVP8SurfNearMinMin() { nearminmin(otherVP8(), false /* flex */); } testOtherVP9FlexNearMinMin()1340 public void testOtherVP9FlexNearMinMin() { nearminmin(otherVP9(), true /* flex */); } testOtherVP9SurfNearMinMin()1341 public void testOtherVP9SurfNearMinMin() { nearminmin(otherVP9(), false /* flex */); } 1342 testGoogH265FlexNearMinMax()1343 public void testGoogH265FlexNearMinMax() { nearminmax(googH265(), true /* flex */); } testGoogH265SurfNearMinMax()1344 public void testGoogH265SurfNearMinMax() { nearminmax(googH265(), false /* flex */); } testGoogH264FlexNearMinMax()1345 public void testGoogH264FlexNearMinMax() { nearminmax(googH264(), true /* flex */); } testGoogH264SurfNearMinMax()1346 public void testGoogH264SurfNearMinMax() { nearminmax(googH264(), false /* flex */); } testGoogH263FlexNearMinMax()1347 public void testGoogH263FlexNearMinMax() { nearminmax(googH263(), true /* flex */); } testGoogH263SurfNearMinMax()1348 public void testGoogH263SurfNearMinMax() { nearminmax(googH263(), false /* flex */); } testGoogMpeg4FlexNearMinMax()1349 public void testGoogMpeg4FlexNearMinMax() { nearminmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMinMax()1350 public void testGoogMpeg4SurfNearMinMax() { nearminmax(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMinMax()1351 public void testGoogVP8FlexNearMinMax() { nearminmax(googVP8(), true /* flex */); } testGoogVP8SurfNearMinMax()1352 public void testGoogVP8SurfNearMinMax() { nearminmax(googVP8(), false /* flex */); } testGoogVP9FlexNearMinMax()1353 public void testGoogVP9FlexNearMinMax() { nearminmax(googVP9(), true /* flex */); } testGoogVP9SurfNearMinMax()1354 public void testGoogVP9SurfNearMinMax() { nearminmax(googVP9(), false /* flex */); } 1355 testOtherH265FlexNearMinMax()1356 public void testOtherH265FlexNearMinMax() { nearminmax(otherH265(), true /* flex */); } testOtherH265SurfNearMinMax()1357 public void testOtherH265SurfNearMinMax() { nearminmax(otherH265(), false /* flex */); } testOtherH264FlexNearMinMax()1358 public void testOtherH264FlexNearMinMax() { nearminmax(otherH264(), true /* flex */); } testOtherH264SurfNearMinMax()1359 public void testOtherH264SurfNearMinMax() { nearminmax(otherH264(), false /* flex */); } testOtherH263FlexNearMinMax()1360 public void testOtherH263FlexNearMinMax() { nearminmax(otherH263(), true /* flex */); } testOtherH263SurfNearMinMax()1361 public void testOtherH263SurfNearMinMax() { nearminmax(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMinMax()1362 public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMinMax()1363 public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMinMax()1364 public void testOtherVP8FlexNearMinMax() { nearminmax(otherVP8(), true /* flex */); } testOtherVP8SurfNearMinMax()1365 public void testOtherVP8SurfNearMinMax() { nearminmax(otherVP8(), false /* flex */); } testOtherVP9FlexNearMinMax()1366 public void testOtherVP9FlexNearMinMax() { nearminmax(otherVP9(), true /* flex */); } testOtherVP9SurfNearMinMax()1367 public void testOtherVP9SurfNearMinMax() { nearminmax(otherVP9(), false /* flex */); } 1368 testGoogH265FlexNearMaxMin()1369 public void testGoogH265FlexNearMaxMin() { nearmaxmin(googH265(), true /* flex */); } testGoogH265SurfNearMaxMin()1370 public void testGoogH265SurfNearMaxMin() { nearmaxmin(googH265(), false /* flex */); } testGoogH264FlexNearMaxMin()1371 public void testGoogH264FlexNearMaxMin() { nearmaxmin(googH264(), true /* flex */); } testGoogH264SurfNearMaxMin()1372 public void testGoogH264SurfNearMaxMin() { nearmaxmin(googH264(), false /* flex */); } testGoogH263FlexNearMaxMin()1373 public void testGoogH263FlexNearMaxMin() { nearmaxmin(googH263(), true /* flex */); } testGoogH263SurfNearMaxMin()1374 public void testGoogH263SurfNearMaxMin() { nearmaxmin(googH263(), false /* flex */); } testGoogMpeg4FlexNearMaxMin()1375 public void testGoogMpeg4FlexNearMaxMin() { nearmaxmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMaxMin()1376 public void testGoogMpeg4SurfNearMaxMin() { nearmaxmin(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMaxMin()1377 public void testGoogVP8FlexNearMaxMin() { nearmaxmin(googVP8(), true /* flex */); } testGoogVP8SurfNearMaxMin()1378 public void testGoogVP8SurfNearMaxMin() { nearmaxmin(googVP8(), false /* flex */); } testGoogVP9FlexNearMaxMin()1379 public void testGoogVP9FlexNearMaxMin() { nearmaxmin(googVP9(), true /* flex */); } testGoogVP9SurfNearMaxMin()1380 public void testGoogVP9SurfNearMaxMin() { nearmaxmin(googVP9(), false /* flex */); } 1381 testOtherH265FlexNearMaxMin()1382 public void testOtherH265FlexNearMaxMin() { nearmaxmin(otherH265(), true /* flex */); } testOtherH265SurfNearMaxMin()1383 public void testOtherH265SurfNearMaxMin() { nearmaxmin(otherH265(), false /* flex */); } testOtherH264FlexNearMaxMin()1384 public void testOtherH264FlexNearMaxMin() { nearmaxmin(otherH264(), true /* flex */); } testOtherH264SurfNearMaxMin()1385 public void testOtherH264SurfNearMaxMin() { nearmaxmin(otherH264(), false /* flex */); } testOtherH263FlexNearMaxMin()1386 public void testOtherH263FlexNearMaxMin() { nearmaxmin(otherH263(), true /* flex */); } testOtherH263SurfNearMaxMin()1387 public void testOtherH263SurfNearMaxMin() { nearmaxmin(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMaxMin()1388 public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMaxMin()1389 public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMaxMin()1390 public void testOtherVP8FlexNearMaxMin() { nearmaxmin(otherVP8(), true /* flex */); } testOtherVP8SurfNearMaxMin()1391 public void testOtherVP8SurfNearMaxMin() { nearmaxmin(otherVP8(), false /* flex */); } testOtherVP9FlexNearMaxMin()1392 public void testOtherVP9FlexNearMaxMin() { nearmaxmin(otherVP9(), true /* flex */); } testOtherVP9SurfNearMaxMin()1393 public void testOtherVP9SurfNearMaxMin() { nearmaxmin(otherVP9(), false /* flex */); } 1394 testGoogH265FlexNearMaxMax()1395 public void testGoogH265FlexNearMaxMax() { nearmaxmax(googH265(), true /* flex */); } testGoogH265SurfNearMaxMax()1396 public void testGoogH265SurfNearMaxMax() { nearmaxmax(googH265(), false /* flex */); } testGoogH264FlexNearMaxMax()1397 public void testGoogH264FlexNearMaxMax() { nearmaxmax(googH264(), true /* flex */); } testGoogH264SurfNearMaxMax()1398 public void testGoogH264SurfNearMaxMax() { nearmaxmax(googH264(), false /* flex */); } testGoogH263FlexNearMaxMax()1399 public void testGoogH263FlexNearMaxMax() { nearmaxmax(googH263(), true /* flex */); } testGoogH263SurfNearMaxMax()1400 public void testGoogH263SurfNearMaxMax() { nearmaxmax(googH263(), false /* flex */); } testGoogMpeg4FlexNearMaxMax()1401 public void testGoogMpeg4FlexNearMaxMax() { nearmaxmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMaxMax()1402 public void testGoogMpeg4SurfNearMaxMax() { nearmaxmax(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMaxMax()1403 public void testGoogVP8FlexNearMaxMax() { nearmaxmax(googVP8(), true /* flex */); } testGoogVP8SurfNearMaxMax()1404 public void testGoogVP8SurfNearMaxMax() { nearmaxmax(googVP8(), false /* flex */); } testGoogVP9FlexNearMaxMax()1405 public void testGoogVP9FlexNearMaxMax() { nearmaxmax(googVP9(), true /* flex */); } testGoogVP9SurfNearMaxMax()1406 public void testGoogVP9SurfNearMaxMax() { nearmaxmax(googVP9(), false /* flex */); } 1407 testOtherH265FlexNearMaxMax()1408 public void testOtherH265FlexNearMaxMax() { nearmaxmax(otherH265(), true /* flex */); } testOtherH265SurfNearMaxMax()1409 public void testOtherH265SurfNearMaxMax() { nearmaxmax(otherH265(), false /* flex */); } testOtherH264FlexNearMaxMax()1410 public void testOtherH264FlexNearMaxMax() { nearmaxmax(otherH264(), true /* flex */); } testOtherH264SurfNearMaxMax()1411 public void testOtherH264SurfNearMaxMax() { nearmaxmax(otherH264(), false /* flex */); } testOtherH263FlexNearMaxMax()1412 public void testOtherH263FlexNearMaxMax() { nearmaxmax(otherH263(), true /* flex */); } testOtherH263SurfNearMaxMax()1413 public void testOtherH263SurfNearMaxMax() { nearmaxmax(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMaxMax()1414 public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMaxMax()1415 public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMaxMax()1416 public void testOtherVP8FlexNearMaxMax() { nearmaxmax(otherVP8(), true /* flex */); } testOtherVP8SurfNearMaxMax()1417 public void testOtherVP8SurfNearMaxMax() { nearmaxmax(otherVP8(), false /* flex */); } testOtherVP9FlexNearMaxMax()1418 public void testOtherVP9FlexNearMaxMax() { nearmaxmax(otherVP9(), true /* flex */); } testOtherVP9SurfNearMaxMax()1419 public void testOtherVP9SurfNearMaxMax() { nearmaxmax(otherVP9(), false /* flex */); } 1420 testGoogH265FlexArbitraryW()1421 public void testGoogH265FlexArbitraryW() { arbitraryw(googH265(), true /* flex */); } testGoogH265SurfArbitraryW()1422 public void testGoogH265SurfArbitraryW() { arbitraryw(googH265(), false /* flex */); } testGoogH264FlexArbitraryW()1423 public void testGoogH264FlexArbitraryW() { arbitraryw(googH264(), true /* flex */); } testGoogH264SurfArbitraryW()1424 public void testGoogH264SurfArbitraryW() { arbitraryw(googH264(), false /* flex */); } testGoogH263FlexArbitraryW()1425 public void testGoogH263FlexArbitraryW() { arbitraryw(googH263(), true /* flex */); } testGoogH263SurfArbitraryW()1426 public void testGoogH263SurfArbitraryW() { arbitraryw(googH263(), false /* flex */); } testGoogMpeg4FlexArbitraryW()1427 public void testGoogMpeg4FlexArbitraryW() { arbitraryw(googMpeg4(), true /* flex */); } testGoogMpeg4SurfArbitraryW()1428 public void testGoogMpeg4SurfArbitraryW() { arbitraryw(googMpeg4(), false /* flex */); } testGoogVP8FlexArbitraryW()1429 public void testGoogVP8FlexArbitraryW() { arbitraryw(googVP8(), true /* flex */); } testGoogVP8SurfArbitraryW()1430 public void testGoogVP8SurfArbitraryW() { arbitraryw(googVP8(), false /* flex */); } testGoogVP9FlexArbitraryW()1431 public void testGoogVP9FlexArbitraryW() { arbitraryw(googVP9(), true /* flex */); } testGoogVP9SurfArbitraryW()1432 public void testGoogVP9SurfArbitraryW() { arbitraryw(googVP9(), false /* flex */); } 1433 testOtherH265FlexArbitraryW()1434 public void testOtherH265FlexArbitraryW() { arbitraryw(otherH265(), true /* flex */); } testOtherH265SurfArbitraryW()1435 public void testOtherH265SurfArbitraryW() { arbitraryw(otherH265(), false /* flex */); } testOtherH264FlexArbitraryW()1436 public void testOtherH264FlexArbitraryW() { arbitraryw(otherH264(), true /* flex */); } testOtherH264SurfArbitraryW()1437 public void testOtherH264SurfArbitraryW() { arbitraryw(otherH264(), false /* flex */); } testOtherH263FlexArbitraryW()1438 public void testOtherH263FlexArbitraryW() { arbitraryw(otherH263(), true /* flex */); } testOtherH263SurfArbitraryW()1439 public void testOtherH263SurfArbitraryW() { arbitraryw(otherH263(), false /* flex */); } testOtherMpeg4FlexArbitraryW()1440 public void testOtherMpeg4FlexArbitraryW() { arbitraryw(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfArbitraryW()1441 public void testOtherMpeg4SurfArbitraryW() { arbitraryw(otherMpeg4(), false /* flex */); } testOtherVP8FlexArbitraryW()1442 public void testOtherVP8FlexArbitraryW() { arbitraryw(otherVP8(), true /* flex */); } testOtherVP8SurfArbitraryW()1443 public void testOtherVP8SurfArbitraryW() { arbitraryw(otherVP8(), false /* flex */); } testOtherVP9FlexArbitraryW()1444 public void testOtherVP9FlexArbitraryW() { arbitraryw(otherVP9(), true /* flex */); } testOtherVP9SurfArbitraryW()1445 public void testOtherVP9SurfArbitraryW() { arbitraryw(otherVP9(), false /* flex */); } 1446 testGoogH265FlexArbitraryH()1447 public void testGoogH265FlexArbitraryH() { arbitraryh(googH265(), true /* flex */); } testGoogH265SurfArbitraryH()1448 public void testGoogH265SurfArbitraryH() { arbitraryh(googH265(), false /* flex */); } testGoogH264FlexArbitraryH()1449 public void testGoogH264FlexArbitraryH() { arbitraryh(googH264(), true /* flex */); } testGoogH264SurfArbitraryH()1450 public void testGoogH264SurfArbitraryH() { arbitraryh(googH264(), false /* flex */); } testGoogH263FlexArbitraryH()1451 public void testGoogH263FlexArbitraryH() { arbitraryh(googH263(), true /* flex */); } testGoogH263SurfArbitraryH()1452 public void testGoogH263SurfArbitraryH() { arbitraryh(googH263(), false /* flex */); } testGoogMpeg4FlexArbitraryH()1453 public void testGoogMpeg4FlexArbitraryH() { arbitraryh(googMpeg4(), true /* flex */); } testGoogMpeg4SurfArbitraryH()1454 public void testGoogMpeg4SurfArbitraryH() { arbitraryh(googMpeg4(), false /* flex */); } testGoogVP8FlexArbitraryH()1455 public void testGoogVP8FlexArbitraryH() { arbitraryh(googVP8(), true /* flex */); } testGoogVP8SurfArbitraryH()1456 public void testGoogVP8SurfArbitraryH() { arbitraryh(googVP8(), false /* flex */); } testGoogVP9FlexArbitraryH()1457 public void testGoogVP9FlexArbitraryH() { arbitraryh(googVP9(), true /* flex */); } testGoogVP9SurfArbitraryH()1458 public void testGoogVP9SurfArbitraryH() { arbitraryh(googVP9(), false /* flex */); } 1459 testOtherH265FlexArbitraryH()1460 public void testOtherH265FlexArbitraryH() { arbitraryh(otherH265(), true /* flex */); } testOtherH265SurfArbitraryH()1461 public void testOtherH265SurfArbitraryH() { arbitraryh(otherH265(), false /* flex */); } testOtherH264FlexArbitraryH()1462 public void testOtherH264FlexArbitraryH() { arbitraryh(otherH264(), true /* flex */); } testOtherH264SurfArbitraryH()1463 public void testOtherH264SurfArbitraryH() { arbitraryh(otherH264(), false /* flex */); } testOtherH263FlexArbitraryH()1464 public void testOtherH263FlexArbitraryH() { arbitraryh(otherH263(), true /* flex */); } testOtherH263SurfArbitraryH()1465 public void testOtherH263SurfArbitraryH() { arbitraryh(otherH263(), false /* flex */); } testOtherMpeg4FlexArbitraryH()1466 public void testOtherMpeg4FlexArbitraryH() { arbitraryh(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfArbitraryH()1467 public void testOtherMpeg4SurfArbitraryH() { arbitraryh(otherMpeg4(), false /* flex */); } testOtherVP8FlexArbitraryH()1468 public void testOtherVP8FlexArbitraryH() { arbitraryh(otherVP8(), true /* flex */); } testOtherVP8SurfArbitraryH()1469 public void testOtherVP8SurfArbitraryH() { arbitraryh(otherVP8(), false /* flex */); } testOtherVP9FlexArbitraryH()1470 public void testOtherVP9FlexArbitraryH() { arbitraryh(otherVP9(), true /* flex */); } testOtherVP9SurfArbitraryH()1471 public void testOtherVP9SurfArbitraryH() { arbitraryh(otherVP9(), false /* flex */); } 1472 testGoogH265FlexQCIF()1473 public void testGoogH265FlexQCIF() { specific(googH265(), 176, 144, true /* flex */); } testGoogH265SurfQCIF()1474 public void testGoogH265SurfQCIF() { specific(googH265(), 176, 144, false /* flex */); } 1475 @SmallTest testGoogH264FlexQCIF()1476 public void testGoogH264FlexQCIF() { specific(googH264(), 176, 144, true /* flex */); } 1477 @SmallTest testGoogH264SurfQCIF()1478 public void testGoogH264SurfQCIF() { specific(googH264(), 176, 144, false /* flex */); } testGoogH263FlexQCIF()1479 public void testGoogH263FlexQCIF() { specific(googH263(), 176, 144, true /* flex */); } testGoogH263SurfQCIF()1480 public void testGoogH263SurfQCIF() { specific(googH263(), 176, 144, false /* flex */); } testGoogMpeg4FlexQCIF()1481 public void testGoogMpeg4FlexQCIF() { specific(googMpeg4(), 176, 144, true /* flex */); } testGoogMpeg4SurfQCIF()1482 public void testGoogMpeg4SurfQCIF() { specific(googMpeg4(), 176, 144, false /* flex */); } testGoogVP8FlexQCIF()1483 public void testGoogVP8FlexQCIF() { specific(googVP8(), 176, 144, true /* flex */); } testGoogVP8SurfQCIF()1484 public void testGoogVP8SurfQCIF() { specific(googVP8(), 176, 144, false /* flex */); } testGoogVP9FlexQCIF()1485 public void testGoogVP9FlexQCIF() { specific(googVP9(), 176, 144, true /* flex */); } testGoogVP9SurfQCIF()1486 public void testGoogVP9SurfQCIF() { specific(googVP9(), 176, 144, false /* flex */); } 1487 testOtherH265FlexQCIF()1488 public void testOtherH265FlexQCIF() { specific(otherH265(), 176, 144, true /* flex */); } testOtherH265SurfQCIF()1489 public void testOtherH265SurfQCIF() { specific(otherH265(), 176, 144, false /* flex */); } 1490 @SmallTest testOtherH264FlexQCIF()1491 public void testOtherH264FlexQCIF() { specific(otherH264(), 176, 144, true /* flex */); } 1492 @SmallTest testOtherH264SurfQCIF()1493 public void testOtherH264SurfQCIF() { specific(otherH264(), 176, 144, false /* flex */); } testOtherH263FlexQCIF()1494 public void testOtherH263FlexQCIF() { specific(otherH263(), 176, 144, true /* flex */); } testOtherH263SurfQCIF()1495 public void testOtherH263SurfQCIF() { specific(otherH263(), 176, 144, false /* flex */); } testOtherMpeg4FlexQCIF()1496 public void testOtherMpeg4FlexQCIF() { specific(otherMpeg4(), 176, 144, true /* flex */); } testOtherMpeg4SurfQCIF()1497 public void testOtherMpeg4SurfQCIF() { specific(otherMpeg4(), 176, 144, false /* flex */); } testOtherVP8FlexQCIF()1498 public void testOtherVP8FlexQCIF() { specific(otherVP8(), 176, 144, true /* flex */); } testOtherVP8SurfQCIF()1499 public void testOtherVP8SurfQCIF() { specific(otherVP8(), 176, 144, false /* flex */); } testOtherVP9FlexQCIF()1500