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