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