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