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