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 
VideoStorage()69         public VideoStorage() {
70             mStream = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
71         }
72 
setFormat(MediaFormat format)73         public void setFormat(MediaFormat format) {
74             mFormat = format;
75         }
76 
addBuffer(ByteBuffer buffer, BufferInfo info)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 
play(MediaCodec decoder, Surface surface)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 
playAll(Surface surface)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 
open(String path)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
initCodecsAndConfigureEncoder( String videoEncName, String outMime, int width, int height, int colorFormat)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 
close()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
fillDecoderInputBuffer(int ix)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 
emptyEncoderOutputBuffer(int ix, BufferInfo info)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 
saveEncoderFormat(MediaFormat format)329         protected void saveEncoderFormat(MediaFormat format) {
330             mEncodedStream.setFormat(format);
331         }
332 
playBack(Surface surface)333         public void playBack(Surface surface) {
334             mEncodedStream.playAll(surface);
335         }
336 
setFrameAndBitRates(int frameRate, int bitRate)337         public void setFrameAndBitRates(int frameRate, int bitRate) {
338             mFrameRate = frameRate;
339             mBitRate = bitRate;
340         }
341 
processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)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
processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)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
onInputBufferAvailable(MediaCodec mediaCodec, int ix)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
onOutputBufferAvailable( MediaCodec mediaCodec, int ix, BufferInfo info)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 
renderDecodedBuffer(Pair<Integer, BufferInfo> decBuffer, int encBuffer)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
onError(MediaCodec mediaCodec, MediaCodec.CodecException e)514         public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
515             fail("received error on " + mediaCodec.getName() + ": " + e);
516         }
517 
518         @Override
onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)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
haveBuffers()528         private boolean haveBuffers() {
529             return mEncInputBuffers.size() > 0 && mBuffersToRender.size() > 0
530                     && !mSignaledEncoderEOS;
531         }
532 
isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer)533         private boolean isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer) {
534             return decBuffer.first < 0 || decBuffer.second.size == 0;
535         }
536 
tryToPropagateEOS()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 
queueEncoderEOS(Pair<Integer, BufferInfo> decBuffer, int encBuffer)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
processLoop( String path, String outMime, String videoEncName, int width, int height, boolean optional)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
onFrameAvailable(SurfaceTexture st)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
onInputBufferAvailable(MediaCodec mediaCodec, int ix)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
onOutputBufferAvailable( MediaCodec mediaCodec, int ix, BufferInfo info)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 
renderDecodedBuffer(int ix, BufferInfo info)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
onError(MediaCodec mediaCodec, MediaCodec.CodecException e)747         public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
748             fail("received error on " + mediaCodec.getName() + ": " + e);
749         }
750 
751         @Override
onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat)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 
Encoder(String name, String mime, CodecCapabilities caps)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 
initializeSizes()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 
addExtremeSizesFor(int x, int y)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 
alignInRange(double value, int align, Range<Integer> range)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. */
alignedPointInRange(double point, int align, Range<Integer> range)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 
getExtreme(Range<Integer> range, int i, int delta)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 
getLargestSizeForRatio(int x, int y)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 
testExtreme(int x, int y, boolean flexYUV, boolean near)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 
testArbitrary(boolean flexYUV, boolean widths)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 
testSpecific(int width, int height, boolean flexYUV)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 
testDetailed( int width, int height, int frameRate, int bitRate, boolean flexYUV)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 
testSupport(int width, int height, int frameRate, int bitRate)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 
test(int width, int height, boolean optional, boolean flexYUV)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 
test(int width, int height, int frameRate, int bitRate, boolean optional, boolean flexYUV)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 
googH265()978     private Encoder[] googH265()  { return goog(MediaFormat.MIMETYPE_VIDEO_HEVC); }
googH264()979     private Encoder[] googH264()  { return goog(MediaFormat.MIMETYPE_VIDEO_AVC); }
googH263()980     private Encoder[] googH263()  { return goog(MediaFormat.MIMETYPE_VIDEO_H263); }
googMpeg4()981     private Encoder[] googMpeg4() { return goog(MediaFormat.MIMETYPE_VIDEO_MPEG4); }
googVP8()982     private Encoder[] googVP8()   { return goog(MediaFormat.MIMETYPE_VIDEO_VP8); }
googVP9()983     private Encoder[] googVP9()   { return goog(MediaFormat.MIMETYPE_VIDEO_VP9); }
984 
otherH265()985     private Encoder[] otherH265()  { return other(MediaFormat.MIMETYPE_VIDEO_HEVC); }
otherH264()986     private Encoder[] otherH264()  { return other(MediaFormat.MIMETYPE_VIDEO_AVC); }
otherH263()987     private Encoder[] otherH263()  { return other(MediaFormat.MIMETYPE_VIDEO_H263); }
otherMpeg4()988     private Encoder[] otherMpeg4() { return other(MediaFormat.MIMETYPE_VIDEO_MPEG4); }
otherVP8()989     private Encoder[] otherVP8()   { return other(MediaFormat.MIMETYPE_VIDEO_VP8); }
otherVP9()990     private Encoder[] otherVP9()   { return other(MediaFormat.MIMETYPE_VIDEO_VP9); }
991 
goog(String mime)992     private Encoder[] goog(String mime) {
993         return encoders(mime, true /* goog */);
994     }
995 
other(String mime)996     private Encoder[] other(String mime) {
997         return encoders(mime, false /* goog */);
998     }
999 
combineArray(Encoder[] a, Encoder[] b)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 
h264()1007     private Encoder[] h264()  {
1008         return combineArray(googH264(), otherH264());
1009     }
1010 
vp8()1011     private Encoder[] vp8()  {
1012         return combineArray(googVP8(), otherVP8());
1013     }
1014 
encoders(String mime, boolean goog)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 
testGoogH265FlexMinMin()1036     public void testGoogH265FlexMinMin()   { minmin(googH265(),   true /* flex */); }
testGoogH265SurfMinMin()1037     public void testGoogH265SurfMinMin()   { minmin(googH265(),   false /* flex */); }
testGoogH264FlexMinMin()1038     public void testGoogH264FlexMinMin()   { minmin(googH264(),   true /* flex */); }
testGoogH264SurfMinMin()1039     public void testGoogH264SurfMinMin()   { minmin(googH264(),   false /* flex */); }
testGoogH263FlexMinMin()1040     public void testGoogH263FlexMinMin()   { minmin(googH263(),   true /* flex */); }
testGoogH263SurfMinMin()1041     public void testGoogH263SurfMinMin()   { minmin(googH263(),   false /* flex */); }
testGoogMpeg4FlexMinMin()1042     public void testGoogMpeg4FlexMinMin()  { minmin(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfMinMin()1043     public void testGoogMpeg4SurfMinMin()  { minmin(googMpeg4(),  false /* flex */); }
testGoogVP8FlexMinMin()1044     public void testGoogVP8FlexMinMin()    { minmin(googVP8(),    true /* flex */); }
testGoogVP8SurfMinMin()1045     public void testGoogVP8SurfMinMin()    { minmin(googVP8(),    false /* flex */); }
testGoogVP9FlexMinMin()1046     public void testGoogVP9FlexMinMin()    { minmin(googVP9(),    true /* flex */); }
testGoogVP9SurfMinMin()1047     public void testGoogVP9SurfMinMin()    { minmin(googVP9(),    false /* flex */); }
1048 
testOtherH265FlexMinMin()1049     public void testOtherH265FlexMinMin()  { minmin(otherH265(),  true /* flex */); }
testOtherH265SurfMinMin()1050     public void testOtherH265SurfMinMin()  { minmin(otherH265(),  false /* flex */); }
testOtherH264FlexMinMin()1051     public void testOtherH264FlexMinMin()  { minmin(otherH264(),  true /* flex */); }
testOtherH264SurfMinMin()1052     public void testOtherH264SurfMinMin()  { minmin(otherH264(),  false /* flex */); }
testOtherH263FlexMinMin()1053     public void testOtherH263FlexMinMin()  { minmin(otherH263(),  true /* flex */); }
testOtherH263SurfMinMin()1054     public void testOtherH263SurfMinMin()  { minmin(otherH263(),  false /* flex */); }
testOtherMpeg4FlexMinMin()1055     public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfMinMin()1056     public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); }
testOtherVP8FlexMinMin()1057     public void testOtherVP8FlexMinMin()   { minmin(otherVP8(),   true /* flex */); }
testOtherVP8SurfMinMin()1058     public void testOtherVP8SurfMinMin()   { minmin(otherVP8(),   false /* flex */); }
testOtherVP9FlexMinMin()1059     public void testOtherVP9FlexMinMin()   { minmin(otherVP9(),   true /* flex */); }
testOtherVP9SurfMinMin()1060     public void testOtherVP9SurfMinMin()   { minmin(otherVP9(),   false /* flex */); }
1061 
testGoogH265FlexMinMax()1062     public void testGoogH265FlexMinMax()   { minmax(googH265(),   true /* flex */); }
testGoogH265SurfMinMax()1063     public void testGoogH265SurfMinMax()   { minmax(googH265(),   false /* flex */); }
testGoogH264FlexMinMax()1064     public void testGoogH264FlexMinMax()   { minmax(googH264(),   true /* flex */); }
testGoogH264SurfMinMax()1065     public void testGoogH264SurfMinMax()   { minmax(googH264(),   false /* flex */); }
testGoogH263FlexMinMax()1066     public void testGoogH263FlexMinMax()   { minmax(googH263(),   true /* flex */); }
testGoogH263SurfMinMax()1067     public void testGoogH263SurfMinMax()   { minmax(googH263(),   false /* flex */); }
testGoogMpeg4FlexMinMax()1068     public void testGoogMpeg4FlexMinMax()  { minmax(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfMinMax()1069     public void testGoogMpeg4SurfMinMax()  { minmax(googMpeg4(),  false /* flex */); }
testGoogVP8FlexMinMax()1070     public void testGoogVP8FlexMinMax()    { minmax(googVP8(),    true /* flex */); }
testGoogVP8SurfMinMax()1071     public void testGoogVP8SurfMinMax()    { minmax(googVP8(),    false /* flex */); }
testGoogVP9FlexMinMax()1072     public void testGoogVP9FlexMinMax()    { minmax(googVP9(),    true /* flex */); }
testGoogVP9SurfMinMax()1073     public void testGoogVP9SurfMinMax()    { minmax(googVP9(),    false /* flex */); }
1074 
testOtherH265FlexMinMax()1075     public void testOtherH265FlexMinMax()  { minmax(otherH265(),  true /* flex */); }
testOtherH265SurfMinMax()1076     public void testOtherH265SurfMinMax()  { minmax(otherH265(),  false /* flex */); }
testOtherH264FlexMinMax()1077     public void testOtherH264FlexMinMax()  { minmax(otherH264(),  true /* flex */); }
testOtherH264SurfMinMax()1078     public void testOtherH264SurfMinMax()  { minmax(otherH264(),  false /* flex */); }
testOtherH263FlexMinMax()1079     public void testOtherH263FlexMinMax()  { minmax(otherH263(),  true /* flex */); }
testOtherH263SurfMinMax()1080     public void testOtherH263SurfMinMax()  { minmax(otherH263(),  false /* flex */); }
testOtherMpeg4FlexMinMax()1081     public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfMinMax()1082     public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); }
testOtherVP8FlexMinMax()1083     public void testOtherVP8FlexMinMax()   { minmax(otherVP8(),   true /* flex */); }
testOtherVP8SurfMinMax()1084     public void testOtherVP8SurfMinMax()   { minmax(otherVP8(),   false /* flex */); }
testOtherVP9FlexMinMax()1085     public void testOtherVP9FlexMinMax()   { minmax(otherVP9(),   true /* flex */); }
testOtherVP9SurfMinMax()1086     public void testOtherVP9SurfMinMax()   { minmax(otherVP9(),   false /* flex */); }
1087 
testGoogH265FlexMaxMin()1088     public void testGoogH265FlexMaxMin()   { maxmin(googH265(),   true /* flex */); }
testGoogH265SurfMaxMin()1089     public void testGoogH265SurfMaxMin()   { maxmin(googH265(),   false /* flex */); }
testGoogH264FlexMaxMin()1090     public void testGoogH264FlexMaxMin()   { maxmin(googH264(),   true /* flex */); }
testGoogH264SurfMaxMin()1091     public void testGoogH264SurfMaxMin()   { maxmin(googH264(),   false /* flex */); }
testGoogH263FlexMaxMin()1092     public void testGoogH263FlexMaxMin()   { maxmin(googH263(),   true /* flex */); }
testGoogH263SurfMaxMin()1093     public void testGoogH263SurfMaxMin()   { maxmin(googH263(),   false /* flex */); }
testGoogMpeg4FlexMaxMin()1094     public void testGoogMpeg4FlexMaxMin()  { maxmin(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfMaxMin()1095     public void testGoogMpeg4SurfMaxMin()  { maxmin(googMpeg4(),  false /* flex */); }
testGoogVP8FlexMaxMin()1096     public void testGoogVP8FlexMaxMin()    { maxmin(googVP8(),    true /* flex */); }
testGoogVP8SurfMaxMin()1097     public void testGoogVP8SurfMaxMin()    { maxmin(googVP8(),    false /* flex */); }
testGoogVP9FlexMaxMin()1098     public void testGoogVP9FlexMaxMin()    { maxmin(googVP9(),    true /* flex */); }
testGoogVP9SurfMaxMin()1099     public void testGoogVP9SurfMaxMin()    { maxmin(googVP9(),    false /* flex */); }
1100 
testOtherH265FlexMaxMin()1101     public void testOtherH265FlexMaxMin()  { maxmin(otherH265(),  true /* flex */); }
testOtherH265SurfMaxMin()1102     public void testOtherH265SurfMaxMin()  { maxmin(otherH265(),  false /* flex */); }
testOtherH264FlexMaxMin()1103     public void testOtherH264FlexMaxMin()  { maxmin(otherH264(),  true /* flex */); }
testOtherH264SurfMaxMin()1104     public void testOtherH264SurfMaxMin()  { maxmin(otherH264(),  false /* flex */); }
testOtherH263FlexMaxMin()1105     public void testOtherH263FlexMaxMin()  { maxmin(otherH263(),  true /* flex */); }
testOtherH263SurfMaxMin()1106     public void testOtherH263SurfMaxMin()  { maxmin(otherH263(),  false /* flex */); }
testOtherMpeg4FlexMaxMin()1107     public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfMaxMin()1108     public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); }
testOtherVP8FlexMaxMin()1109     public void testOtherVP8FlexMaxMin()   { maxmin(otherVP8(),   true /* flex */); }
testOtherVP8SurfMaxMin()1110     public void testOtherVP8SurfMaxMin()   { maxmin(otherVP8(),   false /* flex */); }
testOtherVP9FlexMaxMin()1111     public void testOtherVP9FlexMaxMin()   { maxmin(otherVP9(),   true /* flex */); }
testOtherVP9SurfMaxMin()1112     public void testOtherVP9SurfMaxMin()   { maxmin(otherVP9(),   false /* flex */); }
1113 
testGoogH265FlexMaxMax()1114     public void testGoogH265FlexMaxMax()   { maxmax(googH265(),   true /* flex */); }
testGoogH265SurfMaxMax()1115     public void testGoogH265SurfMaxMax()   { maxmax(googH265(),   false /* flex */); }
testGoogH264FlexMaxMax()1116     public void testGoogH264FlexMaxMax()   { maxmax(googH264(),   true /* flex */); }
testGoogH264SurfMaxMax()1117     public void testGoogH264SurfMaxMax()   { maxmax(googH264(),   false /* flex */); }
testGoogH263FlexMaxMax()1118     public void testGoogH263FlexMaxMax()   { maxmax(googH263(),   true /* flex */); }
testGoogH263SurfMaxMax()1119     public void testGoogH263SurfMaxMax()   { maxmax(googH263(),   false /* flex */); }
testGoogMpeg4FlexMaxMax()1120     public void testGoogMpeg4FlexMaxMax()  { maxmax(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfMaxMax()1121     public void testGoogMpeg4SurfMaxMax()  { maxmax(googMpeg4(),  false /* flex */); }
testGoogVP8FlexMaxMax()1122     public void testGoogVP8FlexMaxMax()    { maxmax(googVP8(),    true /* flex */); }
testGoogVP8SurfMaxMax()1123     public void testGoogVP8SurfMaxMax()    { maxmax(googVP8(),    false /* flex */); }
testGoogVP9FlexMaxMax()1124     public void testGoogVP9FlexMaxMax()    { maxmax(googVP9(),    true /* flex */); }
testGoogVP9SurfMaxMax()1125     public void testGoogVP9SurfMaxMax()    { maxmax(googVP9(),    false /* flex */); }
1126 
testOtherH265FlexMaxMax()1127     public void testOtherH265FlexMaxMax()  { maxmax(otherH265(),  true /* flex */); }
testOtherH265SurfMaxMax()1128     public void testOtherH265SurfMaxMax()  { maxmax(otherH265(),  false /* flex */); }
testOtherH264FlexMaxMax()1129     public void testOtherH264FlexMaxMax()  { maxmax(otherH264(),  true /* flex */); }
testOtherH264SurfMaxMax()1130     public void testOtherH264SurfMaxMax()  { maxmax(otherH264(),  false /* flex */); }
testOtherH263FlexMaxMax()1131     public void testOtherH263FlexMaxMax()  { maxmax(otherH263(),  true /* flex */); }
testOtherH263SurfMaxMax()1132     public void testOtherH263SurfMaxMax()  { maxmax(otherH263(),  false /* flex */); }
testOtherMpeg4FlexMaxMax()1133     public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfMaxMax()1134     public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); }
testOtherVP8FlexMaxMax()1135     public void testOtherVP8FlexMaxMax()   { maxmax(otherVP8(),   true /* flex */); }
testOtherVP8SurfMaxMax()1136     public void testOtherVP8SurfMaxMax()   { maxmax(otherVP8(),   false /* flex */); }
testOtherVP9FlexMaxMax()1137     public void testOtherVP9FlexMaxMax()   { maxmax(otherVP9(),   true /* flex */); }
testOtherVP9SurfMaxMax()1138     public void testOtherVP9SurfMaxMax()   { maxmax(otherVP9(),   false /* flex */); }
1139 
testGoogH265FlexNearMinMin()1140     public void testGoogH265FlexNearMinMin()   { nearminmin(googH265(),   true /* flex */); }
testGoogH265SurfNearMinMin()1141     public void testGoogH265SurfNearMinMin()   { nearminmin(googH265(),   false /* flex */); }
testGoogH264FlexNearMinMin()1142     public void testGoogH264FlexNearMinMin()   { nearminmin(googH264(),   true /* flex */); }
testGoogH264SurfNearMinMin()1143     public void testGoogH264SurfNearMinMin()   { nearminmin(googH264(),   false /* flex */); }
testGoogH263FlexNearMinMin()1144     public void testGoogH263FlexNearMinMin()   { nearminmin(googH263(),   true /* flex */); }
testGoogH263SurfNearMinMin()1145     public void testGoogH263SurfNearMinMin()   { nearminmin(googH263(),   false /* flex */); }
testGoogMpeg4FlexNearMinMin()1146     public void testGoogMpeg4FlexNearMinMin()  { nearminmin(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfNearMinMin()1147     public void testGoogMpeg4SurfNearMinMin()  { nearminmin(googMpeg4(),  false /* flex */); }
testGoogVP8FlexNearMinMin()1148     public void testGoogVP8FlexNearMinMin()    { nearminmin(googVP8(),    true /* flex */); }
testGoogVP8SurfNearMinMin()1149     public void testGoogVP8SurfNearMinMin()    { nearminmin(googVP8(),    false /* flex */); }
testGoogVP9FlexNearMinMin()1150     public void testGoogVP9FlexNearMinMin()    { nearminmin(googVP9(),    true /* flex */); }
testGoogVP9SurfNearMinMin()1151     public void testGoogVP9SurfNearMinMin()    { nearminmin(googVP9(),    false /* flex */); }
1152 
testOtherH265FlexNearMinMin()1153     public void testOtherH265FlexNearMinMin()  { nearminmin(otherH265(),  true /* flex */); }
testOtherH265SurfNearMinMin()1154     public void testOtherH265SurfNearMinMin()  { nearminmin(otherH265(),  false /* flex */); }
testOtherH264FlexNearMinMin()1155     public void testOtherH264FlexNearMinMin()  { nearminmin(otherH264(),  true /* flex */); }
testOtherH264SurfNearMinMin()1156     public void testOtherH264SurfNearMinMin()  { nearminmin(otherH264(),  false /* flex */); }
testOtherH263FlexNearMinMin()1157     public void testOtherH263FlexNearMinMin()  { nearminmin(otherH263(),  true /* flex */); }
testOtherH263SurfNearMinMin()1158     public void testOtherH263SurfNearMinMin()  { nearminmin(otherH263(),  false /* flex */); }
testOtherMpeg4FlexNearMinMin()1159     public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfNearMinMin()1160     public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); }
testOtherVP8FlexNearMinMin()1161     public void testOtherVP8FlexNearMinMin()   { nearminmin(otherVP8(),   true /* flex */); }
testOtherVP8SurfNearMinMin()1162     public void testOtherVP8SurfNearMinMin()   { nearminmin(otherVP8(),   false /* flex */); }
testOtherVP9FlexNearMinMin()1163     public void testOtherVP9FlexNearMinMin()   { nearminmin(otherVP9(),   true /* flex */); }
testOtherVP9SurfNearMinMin()1164     public void testOtherVP9SurfNearMinMin()   { nearminmin(otherVP9(),   false /* flex */); }
1165 
testGoogH265FlexNearMinMax()1166     public void testGoogH265FlexNearMinMax()   { nearminmax(googH265(),   true /* flex */); }
testGoogH265SurfNearMinMax()1167     public void testGoogH265SurfNearMinMax()   { nearminmax(googH265(),   false /* flex */); }
testGoogH264FlexNearMinMax()1168     public void testGoogH264FlexNearMinMax()   { nearminmax(googH264(),   true /* flex */); }
testGoogH264SurfNearMinMax()1169     public void testGoogH264SurfNearMinMax()   { nearminmax(googH264(),   false /* flex */); }
testGoogH263FlexNearMinMax()1170     public void testGoogH263FlexNearMinMax()   { nearminmax(googH263(),   true /* flex */); }
testGoogH263SurfNearMinMax()1171     public void testGoogH263SurfNearMinMax()   { nearminmax(googH263(),   false /* flex */); }
testGoogMpeg4FlexNearMinMax()1172     public void testGoogMpeg4FlexNearMinMax()  { nearminmax(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfNearMinMax()1173     public void testGoogMpeg4SurfNearMinMax()  { nearminmax(googMpeg4(),  false /* flex */); }
testGoogVP8FlexNearMinMax()1174     public void testGoogVP8FlexNearMinMax()    { nearminmax(googVP8(),    true /* flex */); }
testGoogVP8SurfNearMinMax()1175     public void testGoogVP8SurfNearMinMax()    { nearminmax(googVP8(),    false /* flex */); }
testGoogVP9FlexNearMinMax()1176     public void testGoogVP9FlexNearMinMax()    { nearminmax(googVP9(),    true /* flex */); }
testGoogVP9SurfNearMinMax()1177     public void testGoogVP9SurfNearMinMax()    { nearminmax(googVP9(),    false /* flex */); }
1178 
testOtherH265FlexNearMinMax()1179     public void testOtherH265FlexNearMinMax()  { nearminmax(otherH265(),  true /* flex */); }
testOtherH265SurfNearMinMax()1180     public void testOtherH265SurfNearMinMax()  { nearminmax(otherH265(),  false /* flex */); }
testOtherH264FlexNearMinMax()1181     public void testOtherH264FlexNearMinMax()  { nearminmax(otherH264(),  true /* flex */); }
testOtherH264SurfNearMinMax()1182     public void testOtherH264SurfNearMinMax()  { nearminmax(otherH264(),  false /* flex */); }
testOtherH263FlexNearMinMax()1183     public void testOtherH263FlexNearMinMax()  { nearminmax(otherH263(),  true /* flex */); }
testOtherH263SurfNearMinMax()1184     public void testOtherH263SurfNearMinMax()  { nearminmax(otherH263(),  false /* flex */); }
testOtherMpeg4FlexNearMinMax()1185     public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfNearMinMax()1186     public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); }
testOtherVP8FlexNearMinMax()1187     public void testOtherVP8FlexNearMinMax()   { nearminmax(otherVP8(),   true /* flex */); }
testOtherVP8SurfNearMinMax()1188     public void testOtherVP8SurfNearMinMax()   { nearminmax(otherVP8(),   false /* flex */); }
testOtherVP9FlexNearMinMax()1189     public void testOtherVP9FlexNearMinMax()   { nearminmax(otherVP9(),   true /* flex */); }
testOtherVP9SurfNearMinMax()1190     public void testOtherVP9SurfNearMinMax()   { nearminmax(otherVP9(),   false /* flex */); }
1191 
testGoogH265FlexNearMaxMin()1192     public void testGoogH265FlexNearMaxMin()   { nearmaxmin(googH265(),   true /* flex */); }
testGoogH265SurfNearMaxMin()1193     public void testGoogH265SurfNearMaxMin()   { nearmaxmin(googH265(),   false /* flex */); }
testGoogH264FlexNearMaxMin()1194     public void testGoogH264FlexNearMaxMin()   { nearmaxmin(googH264(),   true /* flex */); }
testGoogH264SurfNearMaxMin()1195     public void testGoogH264SurfNearMaxMin()   { nearmaxmin(googH264(),   false /* flex */); }
testGoogH263FlexNearMaxMin()1196     public void testGoogH263FlexNearMaxMin()   { nearmaxmin(googH263(),   true /* flex */); }
testGoogH263SurfNearMaxMin()1197     public void testGoogH263SurfNearMaxMin()   { nearmaxmin(googH263(),   false /* flex */); }
testGoogMpeg4FlexNearMaxMin()1198     public void testGoogMpeg4FlexNearMaxMin()  { nearmaxmin(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfNearMaxMin()1199     public void testGoogMpeg4SurfNearMaxMin()  { nearmaxmin(googMpeg4(),  false /* flex */); }
testGoogVP8FlexNearMaxMin()1200     public void testGoogVP8FlexNearMaxMin()    { nearmaxmin(googVP8(),    true /* flex */); }
testGoogVP8SurfNearMaxMin()1201     public void testGoogVP8SurfNearMaxMin()    { nearmaxmin(googVP8(),    false /* flex */); }
testGoogVP9FlexNearMaxMin()1202     public void testGoogVP9FlexNearMaxMin()    { nearmaxmin(googVP9(),    true /* flex */); }
testGoogVP9SurfNearMaxMin()1203     public void testGoogVP9SurfNearMaxMin()    { nearmaxmin(googVP9(),    false /* flex */); }
1204 
testOtherH265FlexNearMaxMin()1205     public void testOtherH265FlexNearMaxMin()  { nearmaxmin(otherH265(),  true /* flex */); }
testOtherH265SurfNearMaxMin()1206     public void testOtherH265SurfNearMaxMin()  { nearmaxmin(otherH265(),  false /* flex */); }
testOtherH264FlexNearMaxMin()1207     public void testOtherH264FlexNearMaxMin()  { nearmaxmin(otherH264(),  true /* flex */); }
testOtherH264SurfNearMaxMin()1208     public void testOtherH264SurfNearMaxMin()  { nearmaxmin(otherH264(),  false /* flex */); }
testOtherH263FlexNearMaxMin()1209     public void testOtherH263FlexNearMaxMin()  { nearmaxmin(otherH263(),  true /* flex */); }
testOtherH263SurfNearMaxMin()1210     public void testOtherH263SurfNearMaxMin()  { nearmaxmin(otherH263(),  false /* flex */); }
testOtherMpeg4FlexNearMaxMin()1211     public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfNearMaxMin()1212     public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); }
testOtherVP8FlexNearMaxMin()1213     public void testOtherVP8FlexNearMaxMin()   { nearmaxmin(otherVP8(),   true /* flex */); }
testOtherVP8SurfNearMaxMin()1214     public void testOtherVP8SurfNearMaxMin()   { nearmaxmin(otherVP8(),   false /* flex */); }
testOtherVP9FlexNearMaxMin()1215     public void testOtherVP9FlexNearMaxMin()   { nearmaxmin(otherVP9(),   true /* flex */); }
testOtherVP9SurfNearMaxMin()1216     public void testOtherVP9SurfNearMaxMin()   { nearmaxmin(otherVP9(),   false /* flex */); }
1217 
testGoogH265FlexNearMaxMax()1218     public void testGoogH265FlexNearMaxMax()   { nearmaxmax(googH265(),   true /* flex */); }
testGoogH265SurfNearMaxMax()1219     public void testGoogH265SurfNearMaxMax()   { nearmaxmax(googH265(),   false /* flex */); }
testGoogH264FlexNearMaxMax()1220     public void testGoogH264FlexNearMaxMax()   { nearmaxmax(googH264(),   true /* flex */); }
testGoogH264SurfNearMaxMax()1221     public void testGoogH264SurfNearMaxMax()   { nearmaxmax(googH264(),   false /* flex */); }
testGoogH263FlexNearMaxMax()1222     public void testGoogH263FlexNearMaxMax()   { nearmaxmax(googH263(),   true /* flex */); }
testGoogH263SurfNearMaxMax()1223     public void testGoogH263SurfNearMaxMax()   { nearmaxmax(googH263(),   false /* flex */); }
testGoogMpeg4FlexNearMaxMax()1224     public void testGoogMpeg4FlexNearMaxMax()  { nearmaxmax(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfNearMaxMax()1225     public void testGoogMpeg4SurfNearMaxMax()  { nearmaxmax(googMpeg4(),  false /* flex */); }
testGoogVP8FlexNearMaxMax()1226     public void testGoogVP8FlexNearMaxMax()    { nearmaxmax(googVP8(),    true /* flex */); }
testGoogVP8SurfNearMaxMax()1227     public void testGoogVP8SurfNearMaxMax()    { nearmaxmax(googVP8(),    false /* flex */); }
testGoogVP9FlexNearMaxMax()1228     public void testGoogVP9FlexNearMaxMax()    { nearmaxmax(googVP9(),    true /* flex */); }
testGoogVP9SurfNearMaxMax()1229     public void testGoogVP9SurfNearMaxMax()    { nearmaxmax(googVP9(),    false /* flex */); }
1230 
testOtherH265FlexNearMaxMax()1231     public void testOtherH265FlexNearMaxMax()  { nearmaxmax(otherH265(),  true /* flex */); }
testOtherH265SurfNearMaxMax()1232     public void testOtherH265SurfNearMaxMax()  { nearmaxmax(otherH265(),  false /* flex */); }
testOtherH264FlexNearMaxMax()1233     public void testOtherH264FlexNearMaxMax()  { nearmaxmax(otherH264(),  true /* flex */); }
testOtherH264SurfNearMaxMax()1234     public void testOtherH264SurfNearMaxMax()  { nearmaxmax(otherH264(),  false /* flex */); }
testOtherH263FlexNearMaxMax()1235     public void testOtherH263FlexNearMaxMax()  { nearmaxmax(otherH263(),  true /* flex */); }
testOtherH263SurfNearMaxMax()1236     public void testOtherH263SurfNearMaxMax()  { nearmaxmax(otherH263(),  false /* flex */); }
testOtherMpeg4FlexNearMaxMax()1237     public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfNearMaxMax()1238     public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); }
testOtherVP8FlexNearMaxMax()1239     public void testOtherVP8FlexNearMaxMax()   { nearmaxmax(otherVP8(),   true /* flex */); }
testOtherVP8SurfNearMaxMax()1240     public void testOtherVP8SurfNearMaxMax()   { nearmaxmax(otherVP8(),   false /* flex */); }
testOtherVP9FlexNearMaxMax()1241     public void testOtherVP9FlexNearMaxMax()   { nearmaxmax(otherVP9(),   true /* flex */); }
testOtherVP9SurfNearMaxMax()1242     public void testOtherVP9SurfNearMaxMax()   { nearmaxmax(otherVP9(),   false /* flex */); }
1243 
testGoogH265FlexArbitraryW()1244     public void testGoogH265FlexArbitraryW()   { arbitraryw(googH265(),   true /* flex */); }
testGoogH265SurfArbitraryW()1245     public void testGoogH265SurfArbitraryW()   { arbitraryw(googH265(),   false /* flex */); }
testGoogH264FlexArbitraryW()1246     public void testGoogH264FlexArbitraryW()   { arbitraryw(googH264(),   true /* flex */); }
testGoogH264SurfArbitraryW()1247     public void testGoogH264SurfArbitraryW()   { arbitraryw(googH264(),   false /* flex */); }
testGoogH263FlexArbitraryW()1248     public void testGoogH263FlexArbitraryW()   { arbitraryw(googH263(),   true /* flex */); }
testGoogH263SurfArbitraryW()1249     public void testGoogH263SurfArbitraryW()   { arbitraryw(googH263(),   false /* flex */); }
testGoogMpeg4FlexArbitraryW()1250     public void testGoogMpeg4FlexArbitraryW()  { arbitraryw(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfArbitraryW()1251     public void testGoogMpeg4SurfArbitraryW()  { arbitraryw(googMpeg4(),  false /* flex */); }
testGoogVP8FlexArbitraryW()1252     public void testGoogVP8FlexArbitraryW()    { arbitraryw(googVP8(),    true /* flex */); }
testGoogVP8SurfArbitraryW()1253     public void testGoogVP8SurfArbitraryW()    { arbitraryw(googVP8(),    false /* flex */); }
testGoogVP9FlexArbitraryW()1254     public void testGoogVP9FlexArbitraryW()    { arbitraryw(googVP9(),    true /* flex */); }
testGoogVP9SurfArbitraryW()1255     public void testGoogVP9SurfArbitraryW()    { arbitraryw(googVP9(),    false /* flex */); }
1256 
testOtherH265FlexArbitraryW()1257     public void testOtherH265FlexArbitraryW()  { arbitraryw(otherH265(),  true /* flex */); }
testOtherH265SurfArbitraryW()1258     public void testOtherH265SurfArbitraryW()  { arbitraryw(otherH265(),  false /* flex */); }
testOtherH264FlexArbitraryW()1259     public void testOtherH264FlexArbitraryW()  { arbitraryw(otherH264(),  true /* flex */); }
testOtherH264SurfArbitraryW()1260     public void testOtherH264SurfArbitraryW()  { arbitraryw(otherH264(),  false /* flex */); }
testOtherH263FlexArbitraryW()1261     public void testOtherH263FlexArbitraryW()  { arbitraryw(otherH263(),  true /* flex */); }
testOtherH263SurfArbitraryW()1262     public void testOtherH263SurfArbitraryW()  { arbitraryw(otherH263(),  false /* flex */); }
testOtherMpeg4FlexArbitraryW()1263     public void testOtherMpeg4FlexArbitraryW() { arbitraryw(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfArbitraryW()1264     public void testOtherMpeg4SurfArbitraryW() { arbitraryw(otherMpeg4(), false /* flex */); }
testOtherVP8FlexArbitraryW()1265     public void testOtherVP8FlexArbitraryW()   { arbitraryw(otherVP8(),   true /* flex */); }
testOtherVP8SurfArbitraryW()1266     public void testOtherVP8SurfArbitraryW()   { arbitraryw(otherVP8(),   false /* flex */); }
testOtherVP9FlexArbitraryW()1267     public void testOtherVP9FlexArbitraryW()   { arbitraryw(otherVP9(),   true /* flex */); }
testOtherVP9SurfArbitraryW()1268     public void testOtherVP9SurfArbitraryW()   { arbitraryw(otherVP9(),   false /* flex */); }
1269 
testGoogH265FlexArbitraryH()1270     public void testGoogH265FlexArbitraryH()   { arbitraryh(googH265(),   true /* flex */); }
testGoogH265SurfArbitraryH()1271     public void testGoogH265SurfArbitraryH()   { arbitraryh(googH265(),   false /* flex */); }
testGoogH264FlexArbitraryH()1272     public void testGoogH264FlexArbitraryH()   { arbitraryh(googH264(),   true /* flex */); }
testGoogH264SurfArbitraryH()1273     public void testGoogH264SurfArbitraryH()   { arbitraryh(googH264(),   false /* flex */); }
testGoogH263FlexArbitraryH()1274     public void testGoogH263FlexArbitraryH()   { arbitraryh(googH263(),   true /* flex */); }
testGoogH263SurfArbitraryH()1275     public void testGoogH263SurfArbitraryH()   { arbitraryh(googH263(),   false /* flex */); }
testGoogMpeg4FlexArbitraryH()1276     public void testGoogMpeg4FlexArbitraryH()  { arbitraryh(googMpeg4(),  true /* flex */); }
testGoogMpeg4SurfArbitraryH()1277     public void testGoogMpeg4SurfArbitraryH()  { arbitraryh(googMpeg4(),  false /* flex */); }
testGoogVP8FlexArbitraryH()1278     public void testGoogVP8FlexArbitraryH()    { arbitraryh(googVP8(),    true /* flex */); }
testGoogVP8SurfArbitraryH()1279     public void testGoogVP8SurfArbitraryH()    { arbitraryh(googVP8(),    false /* flex */); }
testGoogVP9FlexArbitraryH()1280     public void testGoogVP9FlexArbitraryH()    { arbitraryh(googVP9(),    true /* flex */); }
testGoogVP9SurfArbitraryH()1281     public void testGoogVP9SurfArbitraryH()    { arbitraryh(googVP9(),    false /* flex */); }
1282 
testOtherH265FlexArbitraryH()1283     public void testOtherH265FlexArbitraryH()  { arbitraryh(otherH265(),  true /* flex */); }
testOtherH265SurfArbitraryH()1284     public void testOtherH265SurfArbitraryH()  { arbitraryh(otherH265(),  false /* flex */); }
testOtherH264FlexArbitraryH()1285     public void testOtherH264FlexArbitraryH()  { arbitraryh(otherH264(),  true /* flex */); }
testOtherH264SurfArbitraryH()1286     public void testOtherH264SurfArbitraryH()  { arbitraryh(otherH264(),  false /* flex */); }
testOtherH263FlexArbitraryH()1287     public void testOtherH263FlexArbitraryH()  { arbitraryh(otherH263(),  true /* flex */); }
testOtherH263SurfArbitraryH()1288     public void testOtherH263SurfArbitraryH()  { arbitraryh(otherH263(),  false /* flex */); }
testOtherMpeg4FlexArbitraryH()1289     public void testOtherMpeg4FlexArbitraryH() { arbitraryh(otherMpeg4(), true /* flex */); }
testOtherMpeg4SurfArbitraryH()1290     public void testOtherMpeg4SurfArbitraryH() { arbitraryh(otherMpeg4(), false /* flex */); }
testOtherVP8FlexArbitraryH()1291     public void testOtherVP8FlexArbitraryH()   { arbitraryh(otherVP8(),   true /* flex */); }
testOtherVP8SurfArbitraryH()1292     public void testOtherVP8SurfArbitraryH()   { arbitraryh(otherVP8(),   false /* flex */); }
testOtherVP9FlexArbitraryH()1293     public void testOtherVP9FlexArbitraryH()   { arbitraryh(otherVP9(),   true /* flex */); }
testOtherVP9SurfArbitraryH()1294     public void testOtherVP9SurfArbitraryH()   { arbitraryh(otherVP9(),   false /* flex */); }
1295 
testGoogH265FlexQCIF()1296     public void testGoogH265FlexQCIF()   { specific(googH265(),   176, 144, true /* flex */); }
testGoogH265SurfQCIF()1297     public void testGoogH265SurfQCIF()   { specific(googH265(),   176, 144, false /* flex */); }
testGoogH264FlexQCIF()1298     public void testGoogH264FlexQCIF()   { specific(googH264(),   176, 144, true /* flex */); }
testGoogH264SurfQCIF()1299     public void testGoogH264SurfQCIF()   { specific(googH264(),   176, 144, false /* flex */); }
testGoogH263FlexQCIF()1300     public void testGoogH263FlexQCIF()   { specific(googH263(),   176, 144, true /* flex */); }
testGoogH263SurfQCIF()1301     public void testGoogH263SurfQCIF()   { specific(googH263(),   176, 144, false /* flex */); }
testGoogMpeg4FlexQCIF()1302     public void testGoogMpeg4FlexQCIF()  { specific(googMpeg4(),  176, 144, true /* flex */); }
testGoogMpeg4SurfQCIF()1303     public void testGoogMpeg4SurfQCIF()  { specific(googMpeg4(),  176, 144, false /* flex */); }
testGoogVP8FlexQCIF()1304     public void testGoogVP8FlexQCIF()    { specific(googVP8(),    176, 144, true /* flex */); }
testGoogVP8SurfQCIF()1305     public void testGoogVP8SurfQCIF()    { specific(googVP8(),    176, 144, false /* flex */); }
testGoogVP9FlexQCIF()1306     public void testGoogVP9FlexQCIF()    { specific(googVP9(),    176, 144, true /* flex */); }
testGoogVP9SurfQCIF()1307     public void testGoogVP9SurfQCIF()    { specific(googVP9(),    176, 144, false /* flex */); }
1308 
testOtherH265FlexQCIF()1309     public void testOtherH265FlexQCIF()  { specific(otherH265(),  176, 144, true /* flex */); }
testOtherH265SurfQCIF()1310     public void testOtherH265SurfQCIF()  { specific(otherH265(),  176, 144, false /* flex */); }
testOtherH264FlexQCIF()1311     public void testOtherH264FlexQCIF()  { specific(otherH264(),  176, 144, true /* flex */); }
testOtherH264SurfQCIF()1312     public void testOtherH264SurfQCIF()  { specific(otherH264(),  176, 144, false /* flex */); }
testOtherH263FlexQCIF()1313     public void testOtherH263FlexQCIF()  { specific(otherH263(),  176, 144, true /* flex */); }
testOtherH263SurfQCIF()1314     public void testOtherH263SurfQCIF()  { specific(otherH263(),  176, 144, false /* flex */); }
testOtherMpeg4FlexQCIF()1315     public void testOtherMpeg4FlexQCIF() { specific(otherMpeg4(), 176, 144, true /* flex */); }
testOtherMpeg4SurfQCIF()1316     public void testOtherMpeg4SurfQCIF() { specific(otherMpeg4(), 176, 144, false /* flex */); }
testOtherVP8FlexQCIF()1317     public void testOtherVP8FlexQCIF()   { specific(otherVP8(),   176, 144, true /* flex */); }
testOtherVP8SurfQCIF()1318     public void testOtherVP8SurfQCIF()   { specific(otherVP8(),   176, 144, false /* flex */); }
testOtherVP9FlexQCIF()1319     public void testOtherVP9FlexQCIF()   { specific(otherVP9(),   176, 144, true /* flex */); }
testOtherVP9SurfQCIF()1320     public void testOtherVP9SurfQCIF()   { specific(otherVP9(),   176, 144, false /* flex */); }
1321 
testGoogH265Flex480p()1322     public void testGoogH265Flex480p()   { specific(googH265(),   720, 480, true /* flex */); }
testGoogH265Surf480p()1323     public void testGoogH265Surf480p()   { specific(googH265(),   720, 480, false /* flex */); }
testGoogH264Flex480p()1324     public void testGoogH264Flex480p()   { specific(googH264(),   720, 480, true /* flex */); }
testGoogH264Surf480p()1325     public void testGoogH264Surf480p()   { specific(googH264(),   720, 480, false /* flex */); }
testGoogH263Flex480p()1326     public void testGoogH263Flex480p()   { specific(googH263(),   720, 480, true /* flex */); }
testGoogH263Surf480p()1327     public void testGoogH263Surf480p()   { specific(googH263(),   720, 480, false /* flex */); }
testGoogMpeg4Flex480p()1328     public void testGoogMpeg4Flex480p()  { specific(googMpeg4(),  720, 480, true /* flex */); }
testGoogMpeg4Surf480p()1329     public void testGoogMpeg4Surf480p()  { specific(googMpeg4(),  720, 480, false /* flex */); }
testGoogVP8Flex480p()1330     public void testGoogVP8Flex480p()    { specific(googVP8(),    720, 480, true /* flex */); }
testGoogVP8Surf480p()1331     public void testGoogVP8Surf480p()    { specific(googVP8(),    720, 480, false /* flex */); }
testGoogVP9Flex480p()1332     public void testGoogVP9Flex480p()    { specific(googVP9(),    720, 480, true /* flex */); }
testGoogVP9Surf480p()1333     public void testGoogVP9Surf480p()    { specific(googVP9(),    720, 480, false /* flex */); }
1334 
testOtherH265Flex480p()1335     public void testOtherH265Flex480p()  { specific(otherH265(),  720, 480, true /* flex */); }
testOtherH265Surf480p()1336     public void testOtherH265Surf480p()  { specific(otherH265(),  720, 480, false /* flex */); }
testOtherH264Flex480p()1337     public void testOtherH264Flex480p()  { specific(otherH264(),  720, 480, true /* flex */); }
testOtherH264Surf480p()1338     public void testOtherH264Surf480p()  { specific(otherH264(),  720, 480, false /* flex */); }
testOtherH263Flex480p()1339     public void testOtherH263Flex480p()  { specific(otherH263(),  720, 480, true /* flex */); }
testOtherH263Surf480p()1340     public void testOtherH263Surf480p()  { specific(otherH263(),  720, 480, false /* flex */); }
testOtherMpeg4Flex480p()1341     public void testOtherMpeg4Flex480p() { specific(otherMpeg4(), 720, 480, true /* flex */); }
testOtherMpeg4Surf480p()1342     public void testOtherMpeg4Surf480p() { specific(otherMpeg4(), 720, 480, false /* flex */); }
testOtherVP8Flex480p()1343     public void testOtherVP8Flex480p()   { specific(otherVP8(),   720, 480, true /* flex */); }
testOtherVP8Surf480p()1344     public void testOtherVP8Surf480p()   { specific(otherVP8(),   720, 480, false /* flex */); }
testOtherVP9Flex480p()1345     public void testOtherVP9Flex480p()   { specific(otherVP9(),   720, 480, true /* flex */); }
testOtherVP9Surf480p()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 
testGoogH265Flex720p()1351     public void testGoogH265Flex720p()   { specific(googH265(),   1280, 720, true /* flex */); }
testGoogH265Surf720p()1352     public void testGoogH265Surf720p()   { specific(googH265(),   1280, 720, false /* flex */); }
testGoogH264Flex720p()1353     public void testGoogH264Flex720p()   { specific(googH264(),   1280, 720, true /* flex */); }
testGoogH264Surf720p()1354     public void testGoogH264Surf720p()   { specific(googH264(),   1280, 720, false /* flex */); }
testGoogH263Flex720p()1355     public void testGoogH263Flex720p()   { specific(googH263(),   1280, 720, true /* flex */); }
testGoogH263Surf720p()1356     public void testGoogH263Surf720p()   { specific(googH263(),   1280, 720, false /* flex */); }
testGoogMpeg4Flex720p()1357     public void testGoogMpeg4Flex720p()  { specific(googMpeg4(),  1280, 720, true /* flex */); }
testGoogMpeg4Surf720p()1358     public void testGoogMpeg4Surf720p()  { specific(googMpeg4(),  1280, 720, false /* flex */); }
testGoogVP8Flex720p()1359     public void testGoogVP8Flex720p()    { specific(googVP8(),    1280, 720, true /* flex */); }
testGoogVP8Surf720p()1360     public void testGoogVP8Surf720p()    { specific(googVP8(),    1280, 720, false /* flex */); }
testGoogVP9Flex720p()1361     public void testGoogVP9Flex720p()    { specific(googVP9(),    1280, 720, true /* flex */); }
testGoogVP9Surf720p()1362     public void testGoogVP9Surf720p()    { specific(googVP9(),    1280, 720, false /* flex */); }
1363 
testOtherH265Flex720p()1364     public void testOtherH265Flex720p()  { specific(otherH265(),  1280, 720, true /* flex */); }
testOtherH265Surf720p()1365     public void testOtherH265Surf720p()  { specific(otherH265(),  1280, 720, false /* flex */); }
testOtherH264Flex720p()1366     public void testOtherH264Flex720p()  { specific(otherH264(),  1280, 720, true /* flex */); }
testOtherH264Surf720p()1367     public void testOtherH264Surf720p()  { specific(otherH264(),  1280, 720, false /* flex */); }
testOtherH263Flex720p()1368     public void testOtherH263Flex720p()  { specific(otherH263(),  1280, 720, true /* flex */); }
testOtherH263Surf720p()1369     public void testOtherH263Surf720p()  { specific(otherH263(),  1280, 720, false /* flex */); }
testOtherMpeg4Flex720p()1370     public void testOtherMpeg4Flex720p() { specific(otherMpeg4(), 1280, 720, true /* flex */); }
testOtherMpeg4Surf720p()1371     public void testOtherMpeg4Surf720p() { specific(otherMpeg4(), 1280, 720, false /* flex */); }
testOtherVP8Flex720p()1372     public void testOtherVP8Flex720p()   { specific(otherVP8(),   1280, 720, true /* flex */); }
testOtherVP8Surf720p()1373     public void testOtherVP8Surf720p()   { specific(otherVP8(),   1280, 720, false /* flex */); }
testOtherVP9Flex720p()1374     public void testOtherVP9Flex720p()   { specific(otherVP9(),   1280, 720, true /* flex */); }
testOtherVP9Surf720p()1375     public void testOtherVP9Surf720p()   { specific(otherVP9(),   1280, 720, false /* flex */); }
1376 
testGoogH265Flex1080p()1377     public void testGoogH265Flex1080p()   { specific(googH265(),   1920, 1080, true /* flex */); }
testGoogH265Surf1080p()1378     public void testGoogH265Surf1080p()   { specific(googH265(),   1920, 1080, false /* flex */); }
testGoogH264Flex1080p()1379     public void testGoogH264Flex1080p()   { specific(googH264(),   1920, 1080, true /* flex */); }
testGoogH264Surf1080p()1380     public void testGoogH264Surf1080p()   { specific(googH264(),   1920, 1080, false /* flex */); }
testGoogH263Flex1080p()1381     public void testGoogH263Flex1080p()   { specific(googH263(),   1920, 1080, true /* flex */); }
testGoogH263Surf1080p()1382     public void testGoogH263Surf1080p()   { specific(googH263(),   1920, 1080, false /* flex */); }
testGoogMpeg4Flex1080p()1383     public void testGoogMpeg4Flex1080p()  { specific(googMpeg4(),  1920, 1080, true /* flex */); }
testGoogMpeg4Surf1080p()1384     public void testGoogMpeg4Surf1080p()  { specific(googMpeg4(),  1920, 1080, false /* flex */); }
testGoogVP8Flex1080p()1385     public void testGoogVP8Flex1080p()    { specific(googVP8(),    1920, 1080, true /* flex */); }
testGoogVP8Surf1080p()1386     public void testGoogVP8Surf1080p()    { specific(googVP8(),    1920, 1080, false /* flex */); }
testGoogVP9Flex1080p()1387     public void testGoogVP9Flex1080p()    { specific(googVP9(),    1920, 1080, true /* flex */); }
testGoogVP9Surf1080p()1388     public void testGoogVP9Surf1080p()    { specific(googVP9(),    1920, 1080, false /* flex */); }
1389 
testOtherH265Flex1080p()1390     public void testOtherH265Flex1080p()  { specific(otherH265(),  1920, 1080, true /* flex */); }
testOtherH265Surf1080p()1391     public void testOtherH265Surf1080p()  { specific(otherH265(),  1920, 1080, false /* flex */); }
testOtherH264Flex1080p()1392     public void testOtherH264Flex1080p()  { specific(otherH264(),  1920, 1080, true /* flex */); }
testOtherH264Surf1080p()1393     public void testOtherH264Surf1080p()  { specific(otherH264(),  1920, 1080, false /* flex */); }
testOtherH263Flex1080p()1394     public void testOtherH263Flex1080p()  { specific(otherH263(),  1920, 1080, true /* flex */); }
testOtherH263Surf1080p()1395     public void testOtherH263Surf1080p()  { specific(otherH263(),  1920, 1080, false /* flex */); }
testOtherMpeg4Flex1080p()1396     public void testOtherMpeg4Flex1080p() { specific(otherMpeg4(), 1920, 1080, true /* flex */); }
testOtherMpeg4Surf1080p()1397     public void testOtherMpeg4Surf1080p() { specific(otherMpeg4(), 1920, 1080, false /* flex */); }
testOtherVP8Flex1080p()1398     public void testOtherVP8Flex1080p()   { specific(otherVP8(),   1920, 1080, true /* flex */); }
testOtherVP8Surf1080p()1399     public void testOtherVP8Surf1080p()   { specific(otherVP8(),   1920, 1080, false /* flex */); }
testOtherVP9Flex1080p()1400     public void testOtherVP9Flex1080p()   { specific(otherVP9(),   1920, 1080, true /* flex */); }
testOtherVP9Surf1080p()1401     public void testOtherVP9Surf1080p()   { specific(otherVP9(),   1920, 1080, false /* flex */); }
1402 
1403     // Tests encoder profiles required by CDD.
1404     // H264
testH264LowQualitySDSupport()1405     public void testH264LowQualitySDSupport()   {
1406         support(h264(), 320, 240, 20, 384 * 1000);
1407     }
1408 
testH264HighQualitySDSupport()1409     public void testH264HighQualitySDSupport()   {
1410         support(h264(), 720, 480, 30, 2 * 1000000);
1411     }
1412 
testH264FlexQVGA20fps384kbps()1413     public void testH264FlexQVGA20fps384kbps()   {
1414         detailed(h264(), 320, 240, 20, 384 * 1000, true /* flex */);
1415     }
1416 
testH264SurfQVGA20fps384kbps()1417     public void testH264SurfQVGA20fps384kbps()   {
1418         detailed(h264(), 320, 240, 20, 384 * 1000, false /* flex */);
1419     }
1420 
testH264Flex480p30fps2Mbps()1421     public void testH264Flex480p30fps2Mbps()   {
1422         detailed(h264(), 720, 480, 30, 2 * 1000000, true /* flex */);
1423     }
1424 
testH264Surf480p30fps2Mbps()1425     public void testH264Surf480p30fps2Mbps()   {
1426         detailed(h264(), 720, 480, 30, 2 * 1000000, false /* flex */);
1427     }
1428 
testH264Flex720p30fps4Mbps()1429     public void testH264Flex720p30fps4Mbps()   {
1430         detailed(h264(), 1280, 720, 30, 4 * 1000000, true /* flex */);
1431     }
1432 
testH264Surf720p30fps4Mbps()1433     public void testH264Surf720p30fps4Mbps()   {
1434         detailed(h264(), 1280, 720, 30, 4 * 1000000, false /* flex */);
1435     }
1436 
testH264Flex1080p30fps10Mbps()1437     public void testH264Flex1080p30fps10Mbps()   {
1438         detailed(h264(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
1439     }
1440 
testH264Surf1080p30fps10Mbps()1441     public void testH264Surf1080p30fps10Mbps()   {
1442         detailed(h264(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
1443     }
1444 
1445     // VP8
testVP8LowQualitySDSupport()1446     public void testVP8LowQualitySDSupport()   {
1447         support(vp8(), 320, 180, 30, 800 * 1000);
1448     }
1449 
testVP8HighQualitySDSupport()1450     public void testVP8HighQualitySDSupport()   {
1451         support(vp8(), 640, 360, 30, 2 * 1000000);
1452     }
1453 
testVP8Flex180p30fps800kbps()1454     public void testVP8Flex180p30fps800kbps()   {
1455         detailed(vp8(), 320, 180, 30, 800 * 1000, true /* flex */);
1456     }
1457 
testVP8Surf180p30fps800kbps()1458     public void testVP8Surf180p30fps800kbps()   {
1459         detailed(vp8(), 320, 180, 30, 800 * 1000, false /* flex */);
1460     }
1461 
testVP8Flex360p30fps2Mbps()1462     public void testVP8Flex360p30fps2Mbps()   {
1463         detailed(vp8(), 640, 360, 30, 2 * 1000000, true /* flex */);
1464     }
1465 
testVP8Surf360p30fps2Mbps()1466     public void testVP8Surf360p30fps2Mbps()   {
1467         detailed(vp8(), 640, 360, 30, 2 * 1000000, false /* flex */);
1468     }
1469 
testVP8Flex720p30fps4Mbps()1470     public void testVP8Flex720p30fps4Mbps()   {
1471         detailed(vp8(), 1280, 720, 30, 4 * 1000000, true /* flex */);
1472     }
1473 
testVP8Surf720p30fps4Mbps()1474     public void testVP8Surf720p30fps4Mbps()   {
1475         detailed(vp8(), 1280, 720, 30, 4 * 1000000, false /* flex */);
1476     }
1477 
testVP8Flex1080p30fps10Mbps()1478     public void testVP8Flex1080p30fps10Mbps()   {
1479         detailed(vp8(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
1480     }
1481 
testVP8Surf1080p30fps10Mbps()1482     public void testVP8Surf1080p30fps10Mbps()   {
1483         detailed(vp8(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
1484     }
1485 
minmin(Encoder[] encoders, boolean flexYUV)1486     private void minmin(Encoder[] encoders, boolean flexYUV) {
1487         extreme(encoders, 0 /* x */, 0 /* y */, flexYUV, false /* near */);
1488     }
1489 
minmax(Encoder[] encoders, boolean flexYUV)1490     private void minmax(Encoder[] encoders, boolean flexYUV) {
1491         extreme(encoders, 0 /* x */, 1 /* y */, flexYUV, false /* near */);
1492     }
1493 
maxmin(Encoder[] encoders, boolean flexYUV)1494     private void maxmin(Encoder[] encoders, boolean flexYUV) {
1495         extreme(encoders, 1 /* x */, 0 /* y */, flexYUV, false /* near */);
1496     }
1497 
maxmax(Encoder[] encoders, boolean flexYUV)1498     private void maxmax(Encoder[] encoders, boolean flexYUV) {
1499         extreme(encoders, 1 /* x */, 1 /* y */, flexYUV, false /* near */);
1500     }
1501 
nearminmin(Encoder[] encoders, boolean flexYUV)1502     private void nearminmin(Encoder[] encoders, boolean flexYUV) {
1503         extreme(encoders, 0 /* x */, 0 /* y */, flexYUV, true /* near */);
1504     }
1505 
nearminmax(Encoder[] encoders, boolean flexYUV)1506     private void nearminmax(Encoder[] encoders, boolean flexYUV) {
1507         extreme(encoders, 0 /* x */, 1 /* y */, flexYUV, true /* near */);
1508     }
1509 
nearmaxmin(Encoder[] encoders, boolean flexYUV)1510     private void nearmaxmin(Encoder[] encoders, boolean flexYUV) {
1511         extreme(encoders, 1 /* x */, 0 /* y */, flexYUV, true /* near */);
1512     }
1513 
nearmaxmax(Encoder[] encoders, boolean flexYUV)1514     private void nearmaxmax(Encoder[] encoders, boolean flexYUV) {
1515         extreme(encoders, 1 /* x */, 1 /* y */, flexYUV, true /* near */);
1516     }
1517 
extreme(Encoder[] encoders, int x, int y, boolean flexYUV, boolean near)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 
arbitrary(Encoder[] encoders, boolean flexYUV, boolean widths)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 
arbitraryw(Encoder[] encoders, boolean flexYUV)1550     private void arbitraryw(Encoder[] encoders, boolean flexYUV) {
1551         arbitrary(encoders, flexYUV, true /* widths */);
1552     }
1553 
arbitraryh(Encoder[] encoders, boolean flexYUV)1554     private void arbitraryh(Encoder[] encoders, boolean flexYUV) {
1555         arbitrary(encoders, flexYUV, false /* widths */);
1556     }
1557 
1558     /* test specific size */
specific(Encoder[] encoders, int width, int height, boolean flexYUV)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 */
detailed( Encoder[] encoders, int width, int height, int frameRate, int bitRate, boolean flexYUV)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 */
support(Encoder[] encoders, int width, int height, int frameRate, int bitRate)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