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