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