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 VideoStorage()76 public VideoStorage() { 77 mStream = new LinkedList<Pair<ByteBuffer, BufferInfo>>(); 78 } 79 setFormat(MediaFormat format)80 public void setFormat(MediaFormat format) { 81 mFormat = format; 82 } 83 addBuffer(ByteBuffer buffer, BufferInfo info)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 play(MediaCodec decoder, Surface surface)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 playAll(Surface surface)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 setProcessorName(String name)210 public void setProcessorName(String name) { 211 mProcessorName = name; 212 } 213 setUpdateConfigHook(Function<MediaFormat, Boolean> hook)214 public void setUpdateConfigHook(Function<MediaFormat, Boolean> hook) { 215 mUpdateConfigFormatHook = hook; 216 } 217 setCheckOutputFormatHook(Function<MediaFormat, Boolean> hook)218 public void setCheckOutputFormatHook(Function<MediaFormat, Boolean> hook) { 219 mCheckOutputFormatHook = hook; 220 } 221 open(String path)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 initCodecsAndConfigureEncoder( String videoEncName, String outMime, int width, int height, int colorFormat)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 close()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 fillDecoderInputBuffer(int ix)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 emptyEncoderOutputBuffer(int ix, BufferInfo info)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 saveEncoderFormat(MediaFormat format)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 playBack(Surface surface)405 public void playBack(Surface surface) { 406 mEncodedStream.playAll(surface); 407 } 408 setFrameAndBitRates(int frameRate, int bitRate)409 public void setFrameAndBitRates(int frameRate, int bitRate) { 410 mFrameRate = frameRate; 411 mBitRate = bitRate; 412 } 413 414 @Override onInputBufferAvailable(MediaCodec mediaCodec, int ix)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 onOutputBufferAvailable( MediaCodec mediaCodec, int ix, BufferInfo info)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 processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)433 public abstract boolean processLoop( 434 String path, String outMime, String videoEncName, 435 int width, int height, boolean optional); onInputBufferAvailableLocked( MediaCodec mediaCodec, int ix)436 protected abstract void onInputBufferAvailableLocked( 437 MediaCodec mediaCodec, int ix); onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)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 processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)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 onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix)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 onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)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 renderDecodedBuffer(Pair<Integer, BufferInfo> decBuffer, int encBuffer)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 onError(MediaCodec mediaCodec, MediaCodec.CodecException e)614 public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { 615 fail("received error on " + mediaCodec.getName() + ": " + e); 616 } 617 618 @Override onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)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 haveBuffers()628 private boolean haveBuffers() { 629 return mEncInputBuffers.size() > 0 && mBuffersToRender.size() > 0 630 && !mSignaledEncoderEOS; 631 } 632 isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer)633 private boolean isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer) { 634 return decBuffer.first < 0 || decBuffer.second.size == 0; 635 } 636 tryToPropagateEOS()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 queueEncoderEOS(Pair<Integer, BufferInfo> decBuffer, int encBuffer)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 processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)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 onFrameAvailable(SurfaceTexture st)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 onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix)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 onOutputBufferAvailableLocked( MediaCodec mediaCodec, int ix, BufferInfo info)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 renderDecodedBuffer(int ix, BufferInfo info)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 onError(MediaCodec mediaCodec, MediaCodec.CodecException e)846 public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { 847 fail("received error on " + mediaCodec.getName() + ": " + e); 848 } 849 850 @Override onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)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 Encoder(String name, String mime, CodecCapabilities caps)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 initializeSizes()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 addExtremeSizesFor(int x, int y)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 alignInRange(double value, int align, Range<Integer> range)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. */ alignedPointInRange(double point, int align, Range<Integer> range)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 getExtreme(Range<Integer> range, int i, int delta)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 getLargestSizeForRatio(int x, int y)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 testExtreme(int x, int y, boolean flexYUV, boolean near)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 testArbitrary(boolean flexYUV, boolean widths)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 testSpecific(int width, int height, boolean flexYUV)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 testIntraRefresh(int width, int height)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 testDetailed( int width, int height, int frameRate, int bitRate, boolean flexYUV)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 testSupport(int width, int height, int frameRate, int bitRate)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 test( int width, int height, boolean optional, boolean flexYUV)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 test( int width, int height, int frameRate, int bitRate, boolean optional, boolean flexYUV, Consumer<VideoProcessorBase> configureVideoProcessor)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 googH265()1153 private Encoder[] googH265() { return goog(MediaFormat.MIMETYPE_VIDEO_HEVC); } googH264()1154 private Encoder[] googH264() { return goog(MediaFormat.MIMETYPE_VIDEO_AVC); } googH263()1155 private Encoder[] googH263() { return goog(MediaFormat.MIMETYPE_VIDEO_H263); } googMpeg4()1156 private Encoder[] googMpeg4() { return goog(MediaFormat.MIMETYPE_VIDEO_MPEG4); } googVP8()1157 private Encoder[] googVP8() { return goog(MediaFormat.MIMETYPE_VIDEO_VP8); } googVP9()1158 private Encoder[] googVP9() { return goog(MediaFormat.MIMETYPE_VIDEO_VP9); } 1159 otherH265()1160 private Encoder[] otherH265() { return other(MediaFormat.MIMETYPE_VIDEO_HEVC); } otherH264()1161 private Encoder[] otherH264() { return other(MediaFormat.MIMETYPE_VIDEO_AVC); } otherH263()1162 private Encoder[] otherH263() { return other(MediaFormat.MIMETYPE_VIDEO_H263); } otherMpeg4()1163 private Encoder[] otherMpeg4() { return other(MediaFormat.MIMETYPE_VIDEO_MPEG4); } otherVP8()1164 private Encoder[] otherVP8() { return other(MediaFormat.MIMETYPE_VIDEO_VP8); } otherVP9()1165 private Encoder[] otherVP9() { return other(MediaFormat.MIMETYPE_VIDEO_VP9); } 1166 goog(String mime)1167 private Encoder[] goog(String mime) { 1168 return encoders(mime, true /* goog */); 1169 } 1170 other(String mime)1171 private Encoder[] other(String mime) { 1172 return encoders(mime, false /* goog */); 1173 } 1174 combineArray(Encoder[] a, Encoder[] b)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 h264()1182 private Encoder[] h264() { 1183 return combineArray(googH264(), otherH264()); 1184 } 1185 vp8()1186 private Encoder[] vp8() { 1187 return combineArray(googVP8(), otherVP8()); 1188 } 1189 encoders(String mime, boolean goog)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 testGoogH265FlexMinMin()1210 public void testGoogH265FlexMinMin() { minmin(googH265(), true /* flex */); } testGoogH265SurfMinMin()1211 public void testGoogH265SurfMinMin() { minmin(googH265(), false /* flex */); } testGoogH264FlexMinMin()1212 public void testGoogH264FlexMinMin() { minmin(googH264(), true /* flex */); } testGoogH264SurfMinMin()1213 public void testGoogH264SurfMinMin() { minmin(googH264(), false /* flex */); } testGoogH263FlexMinMin()1214 public void testGoogH263FlexMinMin() { minmin(googH263(), true /* flex */); } testGoogH263SurfMinMin()1215 public void testGoogH263SurfMinMin() { minmin(googH263(), false /* flex */); } testGoogMpeg4FlexMinMin()1216 public void testGoogMpeg4FlexMinMin() { minmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMinMin()1217 public void testGoogMpeg4SurfMinMin() { minmin(googMpeg4(), false /* flex */); } testGoogVP8FlexMinMin()1218 public void testGoogVP8FlexMinMin() { minmin(googVP8(), true /* flex */); } testGoogVP8SurfMinMin()1219 public void testGoogVP8SurfMinMin() { minmin(googVP8(), false /* flex */); } testGoogVP9FlexMinMin()1220 public void testGoogVP9FlexMinMin() { minmin(googVP9(), true /* flex */); } testGoogVP9SurfMinMin()1221 public void testGoogVP9SurfMinMin() { minmin(googVP9(), false /* flex */); } 1222 testOtherH265FlexMinMin()1223 public void testOtherH265FlexMinMin() { minmin(otherH265(), true /* flex */); } testOtherH265SurfMinMin()1224 public void testOtherH265SurfMinMin() { minmin(otherH265(), false /* flex */); } testOtherH264FlexMinMin()1225 public void testOtherH264FlexMinMin() { minmin(otherH264(), true /* flex */); } testOtherH264SurfMinMin()1226 public void testOtherH264SurfMinMin() { minmin(otherH264(), false /* flex */); } testOtherH263FlexMinMin()1227 public void testOtherH263FlexMinMin() { minmin(otherH263(), true /* flex */); } testOtherH263SurfMinMin()1228 public void testOtherH263SurfMinMin() { minmin(otherH263(), false /* flex */); } testOtherMpeg4FlexMinMin()1229 public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMinMin()1230 public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexMinMin()1231 public void testOtherVP8FlexMinMin() { minmin(otherVP8(), true /* flex */); } testOtherVP8SurfMinMin()1232 public void testOtherVP8SurfMinMin() { minmin(otherVP8(), false /* flex */); } testOtherVP9FlexMinMin()1233 public void testOtherVP9FlexMinMin() { minmin(otherVP9(), true /* flex */); } testOtherVP9SurfMinMin()1234 public void testOtherVP9SurfMinMin() { minmin(otherVP9(), false /* flex */); } 1235 testGoogH265FlexMinMax()1236 public void testGoogH265FlexMinMax() { minmax(googH265(), true /* flex */); } testGoogH265SurfMinMax()1237 public void testGoogH265SurfMinMax() { minmax(googH265(), false /* flex */); } testGoogH264FlexMinMax()1238 public void testGoogH264FlexMinMax() { minmax(googH264(), true /* flex */); } testGoogH264SurfMinMax()1239 public void testGoogH264SurfMinMax() { minmax(googH264(), false /* flex */); } testGoogH263FlexMinMax()1240 public void testGoogH263FlexMinMax() { minmax(googH263(), true /* flex */); } testGoogH263SurfMinMax()1241 public void testGoogH263SurfMinMax() { minmax(googH263(), false /* flex */); } testGoogMpeg4FlexMinMax()1242 public void testGoogMpeg4FlexMinMax() { minmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMinMax()1243 public void testGoogMpeg4SurfMinMax() { minmax(googMpeg4(), false /* flex */); } testGoogVP8FlexMinMax()1244 public void testGoogVP8FlexMinMax() { minmax(googVP8(), true /* flex */); } testGoogVP8SurfMinMax()1245 public void testGoogVP8SurfMinMax() { minmax(googVP8(), false /* flex */); } testGoogVP9FlexMinMax()1246 public void testGoogVP9FlexMinMax() { minmax(googVP9(), true /* flex */); } testGoogVP9SurfMinMax()1247 public void testGoogVP9SurfMinMax() { minmax(googVP9(), false /* flex */); } 1248 testOtherH265FlexMinMax()1249 public void testOtherH265FlexMinMax() { minmax(otherH265(), true /* flex */); } testOtherH265SurfMinMax()1250 public void testOtherH265SurfMinMax() { minmax(otherH265(), false /* flex */); } testOtherH264FlexMinMax()1251 public void testOtherH264FlexMinMax() { minmax(otherH264(), true /* flex */); } testOtherH264SurfMinMax()1252 public void testOtherH264SurfMinMax() { minmax(otherH264(), false /* flex */); } testOtherH263FlexMinMax()1253 public void testOtherH263FlexMinMax() { minmax(otherH263(), true /* flex */); } testOtherH263SurfMinMax()1254 public void testOtherH263SurfMinMax() { minmax(otherH263(), false /* flex */); } testOtherMpeg4FlexMinMax()1255 public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMinMax()1256 public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexMinMax()1257 public void testOtherVP8FlexMinMax() { minmax(otherVP8(), true /* flex */); } testOtherVP8SurfMinMax()1258 public void testOtherVP8SurfMinMax() { minmax(otherVP8(), false /* flex */); } testOtherVP9FlexMinMax()1259 public void testOtherVP9FlexMinMax() { minmax(otherVP9(), true /* flex */); } testOtherVP9SurfMinMax()1260 public void testOtherVP9SurfMinMax() { minmax(otherVP9(), false /* flex */); } 1261 testGoogH265FlexMaxMin()1262 public void testGoogH265FlexMaxMin() { maxmin(googH265(), true /* flex */); } testGoogH265SurfMaxMin()1263 public void testGoogH265SurfMaxMin() { maxmin(googH265(), false /* flex */); } testGoogH264FlexMaxMin()1264 public void testGoogH264FlexMaxMin() { maxmin(googH264(), true /* flex */); } testGoogH264SurfMaxMin()1265 public void testGoogH264SurfMaxMin() { maxmin(googH264(), false /* flex */); } testGoogH263FlexMaxMin()1266 public void testGoogH263FlexMaxMin() { maxmin(googH263(), true /* flex */); } testGoogH263SurfMaxMin()1267 public void testGoogH263SurfMaxMin() { maxmin(googH263(), false /* flex */); } testGoogMpeg4FlexMaxMin()1268 public void testGoogMpeg4FlexMaxMin() { maxmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMaxMin()1269 public void testGoogMpeg4SurfMaxMin() { maxmin(googMpeg4(), false /* flex */); } testGoogVP8FlexMaxMin()1270 public void testGoogVP8FlexMaxMin() { maxmin(googVP8(), true /* flex */); } testGoogVP8SurfMaxMin()1271 public void testGoogVP8SurfMaxMin() { maxmin(googVP8(), false /* flex */); } testGoogVP9FlexMaxMin()1272 public void testGoogVP9FlexMaxMin() { maxmin(googVP9(), true /* flex */); } testGoogVP9SurfMaxMin()1273 public void testGoogVP9SurfMaxMin() { maxmin(googVP9(), false /* flex */); } 1274 testOtherH265FlexMaxMin()1275 public void testOtherH265FlexMaxMin() { maxmin(otherH265(), true /* flex */); } testOtherH265SurfMaxMin()1276 public void testOtherH265SurfMaxMin() { maxmin(otherH265(), false /* flex */); } testOtherH264FlexMaxMin()1277 public void testOtherH264FlexMaxMin() { maxmin(otherH264(), true /* flex */); } testOtherH264SurfMaxMin()1278 public void testOtherH264SurfMaxMin() { maxmin(otherH264(), false /* flex */); } testOtherH263FlexMaxMin()1279 public void testOtherH263FlexMaxMin() { maxmin(otherH263(), true /* flex */); } testOtherH263SurfMaxMin()1280 public void testOtherH263SurfMaxMin() { maxmin(otherH263(), false /* flex */); } testOtherMpeg4FlexMaxMin()1281 public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMaxMin()1282 public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexMaxMin()1283 public void testOtherVP8FlexMaxMin() { maxmin(otherVP8(), true /* flex */); } testOtherVP8SurfMaxMin()1284 public void testOtherVP8SurfMaxMin() { maxmin(otherVP8(), false /* flex */); } testOtherVP9FlexMaxMin()1285 public void testOtherVP9FlexMaxMin() { maxmin(otherVP9(), true /* flex */); } testOtherVP9SurfMaxMin()1286 public void testOtherVP9SurfMaxMin() { maxmin(otherVP9(), false /* flex */); } 1287 testGoogH265FlexMaxMax()1288 public void testGoogH265FlexMaxMax() { maxmax(googH265(), true /* flex */); } testGoogH265SurfMaxMax()1289 public void testGoogH265SurfMaxMax() { maxmax(googH265(), false /* flex */); } testGoogH264FlexMaxMax()1290 public void testGoogH264FlexMaxMax() { maxmax(googH264(), true /* flex */); } testGoogH264SurfMaxMax()1291 public void testGoogH264SurfMaxMax() { maxmax(googH264(), false /* flex */); } testGoogH263FlexMaxMax()1292 public void testGoogH263FlexMaxMax() { maxmax(googH263(), true /* flex */); } testGoogH263SurfMaxMax()1293 public void testGoogH263SurfMaxMax() { maxmax(googH263(), false /* flex */); } testGoogMpeg4FlexMaxMax()1294 public void testGoogMpeg4FlexMaxMax() { maxmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfMaxMax()1295 public void testGoogMpeg4SurfMaxMax() { maxmax(googMpeg4(), false /* flex */); } testGoogVP8FlexMaxMax()1296 public void testGoogVP8FlexMaxMax() { maxmax(googVP8(), true /* flex */); } testGoogVP8SurfMaxMax()1297 public void testGoogVP8SurfMaxMax() { maxmax(googVP8(), false /* flex */); } testGoogVP9FlexMaxMax()1298 public void testGoogVP9FlexMaxMax() { maxmax(googVP9(), true /* flex */); } testGoogVP9SurfMaxMax()1299 public void testGoogVP9SurfMaxMax() { maxmax(googVP9(), false /* flex */); } 1300 testOtherH265FlexMaxMax()1301 public void testOtherH265FlexMaxMax() { maxmax(otherH265(), true /* flex */); } testOtherH265SurfMaxMax()1302 public void testOtherH265SurfMaxMax() { maxmax(otherH265(), false /* flex */); } testOtherH264FlexMaxMax()1303 public void testOtherH264FlexMaxMax() { maxmax(otherH264(), true /* flex */); } testOtherH264SurfMaxMax()1304 public void testOtherH264SurfMaxMax() { maxmax(otherH264(), false /* flex */); } testOtherH263FlexMaxMax()1305 public void testOtherH263FlexMaxMax() { maxmax(otherH263(), true /* flex */); } testOtherH263SurfMaxMax()1306 public void testOtherH263SurfMaxMax() { maxmax(otherH263(), false /* flex */); } testOtherMpeg4FlexMaxMax()1307 public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfMaxMax()1308 public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexMaxMax()1309 public void testOtherVP8FlexMaxMax() { maxmax(otherVP8(), true /* flex */); } testOtherVP8SurfMaxMax()1310 public void testOtherVP8SurfMaxMax() { maxmax(otherVP8(), false /* flex */); } testOtherVP9FlexMaxMax()1311 public void testOtherVP9FlexMaxMax() { maxmax(otherVP9(), true /* flex */); } testOtherVP9SurfMaxMax()1312 public void testOtherVP9SurfMaxMax() { maxmax(otherVP9(), false /* flex */); } 1313 testGoogH265FlexNearMinMin()1314 public void testGoogH265FlexNearMinMin() { nearminmin(googH265(), true /* flex */); } testGoogH265SurfNearMinMin()1315 public void testGoogH265SurfNearMinMin() { nearminmin(googH265(), false /* flex */); } testGoogH264FlexNearMinMin()1316 public void testGoogH264FlexNearMinMin() { nearminmin(googH264(), true /* flex */); } testGoogH264SurfNearMinMin()1317 public void testGoogH264SurfNearMinMin() { nearminmin(googH264(), false /* flex */); } testGoogH263FlexNearMinMin()1318 public void testGoogH263FlexNearMinMin() { nearminmin(googH263(), true /* flex */); } testGoogH263SurfNearMinMin()1319 public void testGoogH263SurfNearMinMin() { nearminmin(googH263(), false /* flex */); } testGoogMpeg4FlexNearMinMin()1320 public void testGoogMpeg4FlexNearMinMin() { nearminmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMinMin()1321 public void testGoogMpeg4SurfNearMinMin() { nearminmin(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMinMin()1322 public void testGoogVP8FlexNearMinMin() { nearminmin(googVP8(), true /* flex */); } testGoogVP8SurfNearMinMin()1323 public void testGoogVP8SurfNearMinMin() { nearminmin(googVP8(), false /* flex */); } testGoogVP9FlexNearMinMin()1324 public void testGoogVP9FlexNearMinMin() { nearminmin(googVP9(), true /* flex */); } testGoogVP9SurfNearMinMin()1325 public void testGoogVP9SurfNearMinMin() { nearminmin(googVP9(), false /* flex */); } 1326 testOtherH265FlexNearMinMin()1327 public void testOtherH265FlexNearMinMin() { nearminmin(otherH265(), true /* flex */); } testOtherH265SurfNearMinMin()1328 public void testOtherH265SurfNearMinMin() { nearminmin(otherH265(), false /* flex */); } testOtherH264FlexNearMinMin()1329 public void testOtherH264FlexNearMinMin() { nearminmin(otherH264(), true /* flex */); } testOtherH264SurfNearMinMin()1330 public void testOtherH264SurfNearMinMin() { nearminmin(otherH264(), false /* flex */); } testOtherH263FlexNearMinMin()1331 public void testOtherH263FlexNearMinMin() { nearminmin(otherH263(), true /* flex */); } testOtherH263SurfNearMinMin()1332 public void testOtherH263SurfNearMinMin() { nearminmin(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMinMin()1333 public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMinMin()1334 public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMinMin()1335 public void testOtherVP8FlexNearMinMin() { nearminmin(otherVP8(), true /* flex */); } testOtherVP8SurfNearMinMin()1336 public void testOtherVP8SurfNearMinMin() { nearminmin(otherVP8(), false /* flex */); } testOtherVP9FlexNearMinMin()1337 public void testOtherVP9FlexNearMinMin() { nearminmin(otherVP9(), true /* flex */); } testOtherVP9SurfNearMinMin()1338 public void testOtherVP9SurfNearMinMin() { nearminmin(otherVP9(), false /* flex */); } 1339 testGoogH265FlexNearMinMax()1340 public void testGoogH265FlexNearMinMax() { nearminmax(googH265(), true /* flex */); } testGoogH265SurfNearMinMax()1341 public void testGoogH265SurfNearMinMax() { nearminmax(googH265(), false /* flex */); } testGoogH264FlexNearMinMax()1342 public void testGoogH264FlexNearMinMax() { nearminmax(googH264(), true /* flex */); } testGoogH264SurfNearMinMax()1343 public void testGoogH264SurfNearMinMax() { nearminmax(googH264(), false /* flex */); } testGoogH263FlexNearMinMax()1344 public void testGoogH263FlexNearMinMax() { nearminmax(googH263(), true /* flex */); } testGoogH263SurfNearMinMax()1345 public void testGoogH263SurfNearMinMax() { nearminmax(googH263(), false /* flex */); } testGoogMpeg4FlexNearMinMax()1346 public void testGoogMpeg4FlexNearMinMax() { nearminmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMinMax()1347 public void testGoogMpeg4SurfNearMinMax() { nearminmax(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMinMax()1348 public void testGoogVP8FlexNearMinMax() { nearminmax(googVP8(), true /* flex */); } testGoogVP8SurfNearMinMax()1349 public void testGoogVP8SurfNearMinMax() { nearminmax(googVP8(), false /* flex */); } testGoogVP9FlexNearMinMax()1350 public void testGoogVP9FlexNearMinMax() { nearminmax(googVP9(), true /* flex */); } testGoogVP9SurfNearMinMax()1351 public void testGoogVP9SurfNearMinMax() { nearminmax(googVP9(), false /* flex */); } 1352 testOtherH265FlexNearMinMax()1353 public void testOtherH265FlexNearMinMax() { nearminmax(otherH265(), true /* flex */); } testOtherH265SurfNearMinMax()1354 public void testOtherH265SurfNearMinMax() { nearminmax(otherH265(), false /* flex */); } testOtherH264FlexNearMinMax()1355 public void testOtherH264FlexNearMinMax() { nearminmax(otherH264(), true /* flex */); } testOtherH264SurfNearMinMax()1356 public void testOtherH264SurfNearMinMax() { nearminmax(otherH264(), false /* flex */); } testOtherH263FlexNearMinMax()1357 public void testOtherH263FlexNearMinMax() { nearminmax(otherH263(), true /* flex */); } testOtherH263SurfNearMinMax()1358 public void testOtherH263SurfNearMinMax() { nearminmax(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMinMax()1359 public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMinMax()1360 public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMinMax()1361 public void testOtherVP8FlexNearMinMax() { nearminmax(otherVP8(), true /* flex */); } testOtherVP8SurfNearMinMax()1362 public void testOtherVP8SurfNearMinMax() { nearminmax(otherVP8(), false /* flex */); } testOtherVP9FlexNearMinMax()1363 public void testOtherVP9FlexNearMinMax() { nearminmax(otherVP9(), true /* flex */); } testOtherVP9SurfNearMinMax()1364 public void testOtherVP9SurfNearMinMax() { nearminmax(otherVP9(), false /* flex */); } 1365 testGoogH265FlexNearMaxMin()1366 public void testGoogH265FlexNearMaxMin() { nearmaxmin(googH265(), true /* flex */); } testGoogH265SurfNearMaxMin()1367 public void testGoogH265SurfNearMaxMin() { nearmaxmin(googH265(), false /* flex */); } testGoogH264FlexNearMaxMin()1368 public void testGoogH264FlexNearMaxMin() { nearmaxmin(googH264(), true /* flex */); } testGoogH264SurfNearMaxMin()1369 public void testGoogH264SurfNearMaxMin() { nearmaxmin(googH264(), false /* flex */); } testGoogH263FlexNearMaxMin()1370 public void testGoogH263FlexNearMaxMin() { nearmaxmin(googH263(), true /* flex */); } testGoogH263SurfNearMaxMin()1371 public void testGoogH263SurfNearMaxMin() { nearmaxmin(googH263(), false /* flex */); } testGoogMpeg4FlexNearMaxMin()1372 public void testGoogMpeg4FlexNearMaxMin() { nearmaxmin(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMaxMin()1373 public void testGoogMpeg4SurfNearMaxMin() { nearmaxmin(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMaxMin()1374 public void testGoogVP8FlexNearMaxMin() { nearmaxmin(googVP8(), true /* flex */); } testGoogVP8SurfNearMaxMin()1375 public void testGoogVP8SurfNearMaxMin() { nearmaxmin(googVP8(), false /* flex */); } testGoogVP9FlexNearMaxMin()1376 public void testGoogVP9FlexNearMaxMin() { nearmaxmin(googVP9(), true /* flex */); } testGoogVP9SurfNearMaxMin()1377 public void testGoogVP9SurfNearMaxMin() { nearmaxmin(googVP9(), false /* flex */); } 1378 testOtherH265FlexNearMaxMin()1379 public void testOtherH265FlexNearMaxMin() { nearmaxmin(otherH265(), true /* flex */); } testOtherH265SurfNearMaxMin()1380 public void testOtherH265SurfNearMaxMin() { nearmaxmin(otherH265(), false /* flex */); } testOtherH264FlexNearMaxMin()1381 public void testOtherH264FlexNearMaxMin() { nearmaxmin(otherH264(), true /* flex */); } testOtherH264SurfNearMaxMin()1382 public void testOtherH264SurfNearMaxMin() { nearmaxmin(otherH264(), false /* flex */); } testOtherH263FlexNearMaxMin()1383 public void testOtherH263FlexNearMaxMin() { nearmaxmin(otherH263(), true /* flex */); } testOtherH263SurfNearMaxMin()1384 public void testOtherH263SurfNearMaxMin() { nearmaxmin(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMaxMin()1385 public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMaxMin()1386 public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMaxMin()1387 public void testOtherVP8FlexNearMaxMin() { nearmaxmin(otherVP8(), true /* flex */); } testOtherVP8SurfNearMaxMin()1388 public void testOtherVP8SurfNearMaxMin() { nearmaxmin(otherVP8(), false /* flex */); } testOtherVP9FlexNearMaxMin()1389 public void testOtherVP9FlexNearMaxMin() { nearmaxmin(otherVP9(), true /* flex */); } testOtherVP9SurfNearMaxMin()1390 public void testOtherVP9SurfNearMaxMin() { nearmaxmin(otherVP9(), false /* flex */); } 1391 testGoogH265FlexNearMaxMax()1392 public void testGoogH265FlexNearMaxMax() { nearmaxmax(googH265(), true /* flex */); } testGoogH265SurfNearMaxMax()1393 public void testGoogH265SurfNearMaxMax() { nearmaxmax(googH265(), false /* flex */); } testGoogH264FlexNearMaxMax()1394 public void testGoogH264FlexNearMaxMax() { nearmaxmax(googH264(), true /* flex */); } testGoogH264SurfNearMaxMax()1395 public void testGoogH264SurfNearMaxMax() { nearmaxmax(googH264(), false /* flex */); } testGoogH263FlexNearMaxMax()1396 public void testGoogH263FlexNearMaxMax() { nearmaxmax(googH263(), true /* flex */); } testGoogH263SurfNearMaxMax()1397 public void testGoogH263SurfNearMaxMax() { nearmaxmax(googH263(), false /* flex */); } testGoogMpeg4FlexNearMaxMax()1398 public void testGoogMpeg4FlexNearMaxMax() { nearmaxmax(googMpeg4(), true /* flex */); } testGoogMpeg4SurfNearMaxMax()1399 public void testGoogMpeg4SurfNearMaxMax() { nearmaxmax(googMpeg4(), false /* flex */); } testGoogVP8FlexNearMaxMax()1400 public void testGoogVP8FlexNearMaxMax() { nearmaxmax(googVP8(), true /* flex */); } testGoogVP8SurfNearMaxMax()1401 public void testGoogVP8SurfNearMaxMax() { nearmaxmax(googVP8(), false /* flex */); } testGoogVP9FlexNearMaxMax()1402 public void testGoogVP9FlexNearMaxMax() { nearmaxmax(googVP9(), true /* flex */); } testGoogVP9SurfNearMaxMax()1403 public void testGoogVP9SurfNearMaxMax() { nearmaxmax(googVP9(), false /* flex */); } 1404 testOtherH265FlexNearMaxMax()1405 public void testOtherH265FlexNearMaxMax() { nearmaxmax(otherH265(), true /* flex */); } testOtherH265SurfNearMaxMax()1406 public void testOtherH265SurfNearMaxMax() { nearmaxmax(otherH265(), false /* flex */); } testOtherH264FlexNearMaxMax()1407 public void testOtherH264FlexNearMaxMax() { nearmaxmax(otherH264(), true /* flex */); } testOtherH264SurfNearMaxMax()1408 public void testOtherH264SurfNearMaxMax() { nearmaxmax(otherH264(), false /* flex */); } testOtherH263FlexNearMaxMax()1409 public void testOtherH263FlexNearMaxMax() { nearmaxmax(otherH263(), true /* flex */); } testOtherH263SurfNearMaxMax()1410 public void testOtherH263SurfNearMaxMax() { nearmaxmax(otherH263(), false /* flex */); } testOtherMpeg4FlexNearMaxMax()1411 public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfNearMaxMax()1412 public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); } testOtherVP8FlexNearMaxMax()1413 public void testOtherVP8FlexNearMaxMax() { nearmaxmax(otherVP8(), true /* flex */); } testOtherVP8SurfNearMaxMax()1414 public void testOtherVP8SurfNearMaxMax() { nearmaxmax(otherVP8(), false /* flex */); } testOtherVP9FlexNearMaxMax()1415 public void testOtherVP9FlexNearMaxMax() { nearmaxmax(otherVP9(), true /* flex */); } testOtherVP9SurfNearMaxMax()1416 public void testOtherVP9SurfNearMaxMax() { nearmaxmax(otherVP9(), false /* flex */); } 1417 testGoogH265FlexArbitraryW()1418 public void testGoogH265FlexArbitraryW() { arbitraryw(googH265(), true /* flex */); } testGoogH265SurfArbitraryW()1419 public void testGoogH265SurfArbitraryW() { arbitraryw(googH265(), false /* flex */); } testGoogH264FlexArbitraryW()1420 public void testGoogH264FlexArbitraryW() { arbitraryw(googH264(), true /* flex */); } testGoogH264SurfArbitraryW()1421 public void testGoogH264SurfArbitraryW() { arbitraryw(googH264(), false /* flex */); } testGoogH263FlexArbitraryW()1422 public void testGoogH263FlexArbitraryW() { arbitraryw(googH263(), true /* flex */); } testGoogH263SurfArbitraryW()1423 public void testGoogH263SurfArbitraryW() { arbitraryw(googH263(), false /* flex */); } testGoogMpeg4FlexArbitraryW()1424 public void testGoogMpeg4FlexArbitraryW() { arbitraryw(googMpeg4(), true /* flex */); } testGoogMpeg4SurfArbitraryW()1425 public void testGoogMpeg4SurfArbitraryW() { arbitraryw(googMpeg4(), false /* flex */); } testGoogVP8FlexArbitraryW()1426 public void testGoogVP8FlexArbitraryW() { arbitraryw(googVP8(), true /* flex */); } testGoogVP8SurfArbitraryW()1427 public void testGoogVP8SurfArbitraryW() { arbitraryw(googVP8(), false /* flex */); } testGoogVP9FlexArbitraryW()1428 public void testGoogVP9FlexArbitraryW() { arbitraryw(googVP9(), true /* flex */); } testGoogVP9SurfArbitraryW()1429 public void testGoogVP9SurfArbitraryW() { arbitraryw(googVP9(), false /* flex */); } 1430 testOtherH265FlexArbitraryW()1431 public void testOtherH265FlexArbitraryW() { arbitraryw(otherH265(), true /* flex */); } testOtherH265SurfArbitraryW()1432 public void testOtherH265SurfArbitraryW() { arbitraryw(otherH265(), false /* flex */); } testOtherH264FlexArbitraryW()1433 public void testOtherH264FlexArbitraryW() { arbitraryw(otherH264(), true /* flex */); } testOtherH264SurfArbitraryW()1434 public void testOtherH264SurfArbitraryW() { arbitraryw(otherH264(), false /* flex */); } testOtherH263FlexArbitraryW()1435 public void testOtherH263FlexArbitraryW() { arbitraryw(otherH263(), true /* flex */); } testOtherH263SurfArbitraryW()1436 public void testOtherH263SurfArbitraryW() { arbitraryw(otherH263(), false /* flex */); } testOtherMpeg4FlexArbitraryW()1437 public void testOtherMpeg4FlexArbitraryW() { arbitraryw(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfArbitraryW()1438 public void testOtherMpeg4SurfArbitraryW() { arbitraryw(otherMpeg4(), false /* flex */); } testOtherVP8FlexArbitraryW()1439 public void testOtherVP8FlexArbitraryW() { arbitraryw(otherVP8(), true /* flex */); } testOtherVP8SurfArbitraryW()1440 public void testOtherVP8SurfArbitraryW() { arbitraryw(otherVP8(), false /* flex */); } testOtherVP9FlexArbitraryW()1441 public void testOtherVP9FlexArbitraryW() { arbitraryw(otherVP9(), true /* flex */); } testOtherVP9SurfArbitraryW()1442 public void testOtherVP9SurfArbitraryW() { arbitraryw(otherVP9(), false /* flex */); } 1443 testGoogH265FlexArbitraryH()1444 public void testGoogH265FlexArbitraryH() { arbitraryh(googH265(), true /* flex */); } testGoogH265SurfArbitraryH()1445 public void testGoogH265SurfArbitraryH() { arbitraryh(googH265(), false /* flex */); } testGoogH264FlexArbitraryH()1446 public void testGoogH264FlexArbitraryH() { arbitraryh(googH264(), true /* flex */); } testGoogH264SurfArbitraryH()1447 public void testGoogH264SurfArbitraryH() { arbitraryh(googH264(), false /* flex */); } testGoogH263FlexArbitraryH()1448 public void testGoogH263FlexArbitraryH() { arbitraryh(googH263(), true /* flex */); } testGoogH263SurfArbitraryH()1449 public void testGoogH263SurfArbitraryH() { arbitraryh(googH263(), false /* flex */); } testGoogMpeg4FlexArbitraryH()1450 public void testGoogMpeg4FlexArbitraryH() { arbitraryh(googMpeg4(), true /* flex */); } testGoogMpeg4SurfArbitraryH()1451 public void testGoogMpeg4SurfArbitraryH() { arbitraryh(googMpeg4(), false /* flex */); } testGoogVP8FlexArbitraryH()1452 public void testGoogVP8FlexArbitraryH() { arbitraryh(googVP8(), true /* flex */); } testGoogVP8SurfArbitraryH()1453 public void testGoogVP8SurfArbitraryH() { arbitraryh(googVP8(), false /* flex */); } testGoogVP9FlexArbitraryH()1454 public void testGoogVP9FlexArbitraryH() { arbitraryh(googVP9(), true /* flex */); } testGoogVP9SurfArbitraryH()1455 public void testGoogVP9SurfArbitraryH() { arbitraryh(googVP9(), false /* flex */); } 1456 testOtherH265FlexArbitraryH()1457 public void testOtherH265FlexArbitraryH() { arbitraryh(otherH265(), true /* flex */); } testOtherH265SurfArbitraryH()1458 public void testOtherH265SurfArbitraryH() { arbitraryh(otherH265(), false /* flex */); } testOtherH264FlexArbitraryH()1459 public void testOtherH264FlexArbitraryH() { arbitraryh(otherH264(), true /* flex */); } testOtherH264SurfArbitraryH()1460 public void testOtherH264SurfArbitraryH() { arbitraryh(otherH264(), false /* flex */); } testOtherH263FlexArbitraryH()1461 public void testOtherH263FlexArbitraryH() { arbitraryh(otherH263(), true /* flex */); } testOtherH263SurfArbitraryH()1462 public void testOtherH263SurfArbitraryH() { arbitraryh(otherH263(), false /* flex */); } testOtherMpeg4FlexArbitraryH()1463 public void testOtherMpeg4FlexArbitraryH() { arbitraryh(otherMpeg4(), true /* flex */); } testOtherMpeg4SurfArbitraryH()1464 public void testOtherMpeg4SurfArbitraryH() { arbitraryh(otherMpeg4(), false /* flex */); } testOtherVP8FlexArbitraryH()1465 public void testOtherVP8FlexArbitraryH() { arbitraryh(otherVP8(), true /* flex */); } testOtherVP8SurfArbitraryH()1466 public void testOtherVP8SurfArbitraryH() { arbitraryh(otherVP8(), false /* flex */); } testOtherVP9FlexArbitraryH()1467 public void testOtherVP9FlexArbitraryH() { arbitraryh(otherVP9(), true /* flex */); } testOtherVP9SurfArbitraryH()1468 public void testOtherVP9SurfArbitraryH() { arbitraryh(otherVP9(), false /* flex */); } 1469 testGoogH265FlexQCIF()1470 public void testGoogH265FlexQCIF() { specific(googH265(), 176, 144, true /* flex */); } testGoogH265SurfQCIF()1471 public void testGoogH265SurfQCIF() { specific(googH265(), 176, 144, false /* flex */); } testGoogH264FlexQCIF()1472 public void testGoogH264FlexQCIF() { specific(googH264(), 176, 144, true /* flex */); } testGoogH264SurfQCIF()1473 public void testGoogH264SurfQCIF() { specific(googH264(), 176, 144, false /* flex */); } testGoogH263FlexQCIF()1474 public void testGoogH263FlexQCIF() { specific(googH263(), 176, 144, true /* flex */); } testGoogH263SurfQCIF()1475 public void testGoogH263SurfQCIF() { specific(googH263(), 176, 144, false /* flex */); } testGoogMpeg4FlexQCIF()1476 public void testGoogMpeg4FlexQCIF() { specific(googMpeg4(), 176, 144, true /* flex */); } testGoogMpeg4SurfQCIF()1477 public void testGoogMpeg4SurfQCIF() { specific(googMpeg4(), 176, 144, false /* flex */); } testGoogVP8FlexQCIF()1478 public void testGoogVP8FlexQCIF() { specific(googVP8(), 176, 144, true /* flex */); } testGoogVP8SurfQCIF()1479 public void testGoogVP8SurfQCIF() { specific(googVP8(), 176, 144, false /* flex */); } testGoogVP9FlexQCIF()1480 public void testGoogVP9FlexQCIF() { specific(googVP9(), 176, 144, true /* flex */); } testGoogVP9SurfQCIF()1481 public void testGoogVP9SurfQCIF() { specific(googVP9(), 176, 144, false /* flex */); } 1482 testOtherH265FlexQCIF()1483 public void testOtherH265FlexQCIF() { specific(otherH265(), 176, 144, true /* flex */); } testOtherH265SurfQCIF()1484 public void testOtherH265SurfQCIF() { specific(otherH265(), 176, 144, false /* flex */); } testOtherH264FlexQCIF()1485 public void testOtherH264FlexQCIF() { specific(otherH264(), 176, 144, true /* flex */); } testOtherH264SurfQCIF()1486 public void testOtherH264SurfQCIF() { specific(otherH264(), 176, 144, false /* flex */); } testOtherH263FlexQCIF()1487 public void testOtherH263FlexQCIF() { specific(otherH263(), 176, 144, true /* flex */); } testOtherH263SurfQCIF()1488 public void testOtherH263SurfQCIF() { specific(otherH263(), 176, 144, false /* flex */); } testOtherMpeg4FlexQCIF()1489