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