• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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.video.cts;
18 
19 import android.graphics.ImageFormat;
20 import android.graphics.Point;
21 import android.media.Image;
22 import android.media.Image.Plane;
23 import android.media.MediaCodec;
24 import android.media.MediaCodec.BufferInfo;
25 import android.media.MediaCodecInfo;
26 import android.media.MediaCodecInfo.CodecCapabilities;
27 import android.media.MediaFormat;
28 import android.media.cts.CodecImage;
29 import android.media.cts.CodecUtils;
30 import android.media.cts.TestArgs;
31 import android.media.cts.TestUtils;
32 import android.media.cts.YUVImage;
33 import android.os.Build;
34 import android.util.Log;
35 import android.util.Pair;
36 import android.util.Range;
37 
38 import com.android.compatibility.common.util.CtsAndroidTestCase;
39 import com.android.compatibility.common.util.DeviceReportLog;
40 import com.android.compatibility.common.util.MediaPerfUtils;
41 import com.android.compatibility.common.util.MediaUtils;
42 import com.android.compatibility.common.util.ResultType;
43 import com.android.compatibility.common.util.ResultUnit;
44 import com.android.compatibility.common.util.Stat;
45 
46 import java.io.IOException;
47 import java.nio.ByteBuffer;
48 import java.util.Arrays;
49 import java.util.LinkedList;
50 import java.util.Random;
51 import java.util.Scanner;
52 
53 /**
54  * This tries to test video encoder / decoder performance by running encoding / decoding
55  * without displaying the raw data. To make things simpler, encoder is used to encode synthetic
56  * data and decoder is used to decode the encoded video. This approach does not work where
57  * there is only decoder. Performance index is total time taken for encoding and decoding
58  * the whole frames.
59  * To prevent sacrificing quality for faster encoding / decoding, randomly selected pixels are
60  * compared with the original image. As the pixel comparison can slow down the decoding process,
61  * only some randomly selected pixels are compared. As there can be only one performance index,
62  * error above certain threshold in pixel value will be treated as an error.
63  */
64 public class VideoEncoderDecoderTest extends CtsAndroidTestCase {
65     private static final String TAG = "VideoEncoderDecoderTest";
66     private static final String REPORT_LOG_NAME = "CtsVideoTestCases";
67     // this wait time affects fps as too big value will work as a blocker if device fps
68     // is not very high.
69     private static final long VIDEO_CODEC_WAIT_TIME_US = 1000;
70     private static final boolean VERBOSE = false;
71     private static final int MAX_FPS = 30; // measure performance at 30fps, this is relevant for
72                                            // the meaning of bitrate
73 
74     private static final String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
75     private static final String H263 = MediaFormat.MIMETYPE_VIDEO_H263;
76     private static final String HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
77     private static final String MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
78     private static final String MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
79     private static final String VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
80     private static final String VP9 = MediaFormat.MIMETYPE_VIDEO_VP9;
81 
82     private static final boolean GOOG = true;
83     private static final boolean OTHER = false;
84 
85     // test results:
86 
87     private int mCurrentTestRound = 0;
88     private double[][] mEncoderFrameTimeUsDiff;
89     private double[] mEncoderFpsResults;
90 
91     private double[][] mDecoderFrameTimeUsDiff;
92     private double[] mDecoderFpsResults;
93     private double[] mTotalFpsResults;
94     private double[] mDecoderRmsErrorResults;
95 
96     // i frame interval for encoder
97     private static final int KEY_I_FRAME_INTERVAL = 5;
98     private static final int MAX_TEST_TIMEOUT_MS = 300000;   // 5 minutes
99 
100     private static final int Y_CLAMP_MIN = 16;
101     private static final int Y_CLAMP_MAX = 235;
102     private static final int YUV_PLANE_ADDITIONAL_LENGTH = 200;
103     private ByteBuffer mYBuffer, mYDirectBuffer;
104     private ByteBuffer mUVBuffer, mUVDirectBuffer;
105     private int mSrcColorFormat;
106     private int mDstColorFormat;
107     private int mBufferWidth;
108     private int mBufferHeight;
109     private int mVideoWidth;
110     private int mVideoHeight;
111     private int mVideoStride;
112     private int mVideoVStride;
113     private int mFrameRate;
114 
115     private MediaFormat mEncConfigFormat;
116     private MediaFormat mEncInputFormat;
117     private MediaFormat mEncOutputFormat;
118     private MediaFormat mDecOutputFormat;
119 
120     private LinkedList<Pair<ByteBuffer, BufferInfo>> mEncodedOutputBuffer;
121     // check this many pixels per each decoded frame
122     // checking too many points decreases decoder frame rates a lot.
123     private static final int PIXEL_CHECK_PER_FRAME = 1000;
124     // RMS error in pixel values above this will be treated as error.
125     private static final double PIXEL_RMS_ERROR_MARGIN = 20.0;
126     private double mRmsErrorMargin;
127     private Random mRandom;
128 
129     private boolean mUpdatedSwCodec = false;
130 
131     private class TestConfig {
132         public boolean mTestPixels = true;
133         public boolean mReportFrameTime = false;
134         public int mTotalFrames = 300;
135         public int mMinNumFrames = 300;
136         public int mMaxTimeMs = 120000;  // 2 minutes
137         public int mMinTimeMs = 10000;   // 10 seconds
138         public int mNumberOfRepeat = 10;
139 
initPerfTest()140         public void initPerfTest() {
141             mTestPixels = false;
142             mTotalFrames = 30000;
143             mMinNumFrames = 3000;
144             mNumberOfRepeat = 2;
145         }
146     }
147 
148     private TestConfig mTestConfig;
149 
isPreferredAbi()150     private static boolean isPreferredAbi() {
151         boolean prefers64Bit = false;
152         if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
153                 Build.SUPPORTED_ABIS.length > 0 &&
154                 Build.SUPPORTED_ABIS[0].equals(Build.SUPPORTED_64_BIT_ABIS[0])) {
155             prefers64Bit = true;
156         }
157         return android.os.Process.is64Bit() ? prefers64Bit : !prefers64Bit;
158     }
159 
160     @Override
setUp()161     protected void setUp() throws Exception {
162         mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
163         mRmsErrorMargin = PIXEL_RMS_ERROR_MARGIN;
164         mUpdatedSwCodec =
165                 !TestUtils.isMainlineModuleFactoryVersion("com.google.android.media.swcodec");
166         // Use time as a seed, hoping to prevent checking pixels in the same pattern
167         long now = System.currentTimeMillis();
168         mRandom = new Random(now);
169         mTestConfig = new TestConfig();
170         super.setUp();
171     }
172 
173     @Override
tearDown()174     protected void tearDown() throws Exception {
175         mEncodedOutputBuffer.clear();
176         mEncodedOutputBuffer = null;
177         mYBuffer = null;
178         mUVBuffer = null;
179         mYDirectBuffer = null;
180         mUVDirectBuffer = null;
181         mRandom = null;
182         mTestConfig = null;
183         super.tearDown();
184     }
185 
count(String mime, int width, int height, int numGoog, int numOther)186     private void count(String mime, int width, int height, int numGoog, int numOther)
187             throws Exception {
188         MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
189         MediaUtils.verifyNumCodecs(numGoog,  true /* isEncoder */, true /* isGoog */,  format);
190         MediaUtils.verifyNumCodecs(numOther, true /* isEncoder */, false /* isGoog */, format);
191     }
192 
193     /** run performance test. */
perf(String mimeType, int w, int h, boolean isGoog, int ix)194     private void perf(String mimeType, int w, int h, boolean isGoog, int ix) throws Exception {
195         doTest(mimeType, w, h, true /* isPerf */, isGoog, ix);
196     }
197 
198     /** run quality test. */
qual(String mimeType, int w, int h, boolean isGoog, int ix)199     private void qual(String mimeType, int w, int h, boolean isGoog, int ix) throws Exception {
200         doTest(mimeType, w, h, false /* isPerf */, isGoog, ix);
201     }
202 
203     /** run quality test but do not report error. */
qual(String mimeType, int w, int h, boolean isGoog, int ix, double margin)204     private void qual(String mimeType, int w, int h, boolean isGoog, int ix, double margin)
205             throws Exception {
206         mRmsErrorMargin = margin;
207         doTest(mimeType, w, h, false /* isPerf */, isGoog, ix);
208     }
209 
210     // Poor man's Parametrized test as this test must still run on CTSv1 runner.
211 
212     // The count tests are to ensure this Cts test covers all encoders. Add further
213     // tests and change the count if there can be more encoders.
214 
215     // AVC tests
testAvcCount0320x0240()216     public void testAvcCount0320x0240() throws Exception { count(AVC, 320, 240, 2, 4); }
testAvcGoog0Qual0320x0240()217     public void testAvcGoog0Qual0320x0240() throws Exception { qual(AVC, 320, 240, GOOG, 0); }
testAvcGoog0Perf0320x0240()218     public void testAvcGoog0Perf0320x0240() throws Exception { perf(AVC, 320, 240, GOOG, 0); }
testAvcGoog1Qual0320x0240()219     public void testAvcGoog1Qual0320x0240() throws Exception { qual(AVC, 320, 240, GOOG, 1); }
testAvcGoog1Perf0320x0240()220     public void testAvcGoog1Perf0320x0240() throws Exception { perf(AVC, 320, 240, GOOG, 1); }
221 
testAvcOther0Qual0320x0240()222     public void testAvcOther0Qual0320x0240() throws Exception { qual(AVC, 320, 240, OTHER, 0); }
testAvcOther0Perf0320x0240()223     public void testAvcOther0Perf0320x0240() throws Exception { perf(AVC, 320, 240, OTHER, 0); }
testAvcOther1Qual0320x0240()224     public void testAvcOther1Qual0320x0240() throws Exception { qual(AVC, 320, 240, OTHER, 1); }
testAvcOther1Perf0320x0240()225     public void testAvcOther1Perf0320x0240() throws Exception { perf(AVC, 320, 240, OTHER, 1); }
testAvcOther2Qual0320x0240()226     public void testAvcOther2Qual0320x0240() throws Exception { qual(AVC, 320, 240, OTHER, 2); }
testAvcOther2Perf0320x0240()227     public void testAvcOther2Perf0320x0240() throws Exception { perf(AVC, 320, 240, OTHER, 2); }
testAvcOther3Qual0320x0240()228     public void testAvcOther3Qual0320x0240() throws Exception { qual(AVC, 320, 240, OTHER, 3); }
testAvcOther3Perf0320x0240()229     public void testAvcOther3Perf0320x0240() throws Exception { perf(AVC, 320, 240, OTHER, 3); }
testAvcCount0720x0480()230     public void testAvcCount0720x0480() throws Exception { count(AVC, 720, 480, 2, 4); }
testAvcGoog0Qual0720x0480()231     public void testAvcGoog0Qual0720x0480() throws Exception { qual(AVC, 720, 480, GOOG, 0); }
testAvcGoog0Perf0720x0480()232     public void testAvcGoog0Perf0720x0480() throws Exception { perf(AVC, 720, 480, GOOG, 0); }
testAvcGoog1Qual0720x0480()233     public void testAvcGoog1Qual0720x0480() throws Exception { qual(AVC, 720, 480, GOOG, 1); }
testAvcGoog1Perf0720x0480()234     public void testAvcGoog1Perf0720x0480() throws Exception { perf(AVC, 720, 480, GOOG, 1); }
235 
testAvcOther0Qual0720x0480()236     public void testAvcOther0Qual0720x0480() throws Exception { qual(AVC, 720, 480, OTHER, 0); }
testAvcOther0Perf0720x0480()237     public void testAvcOther0Perf0720x0480() throws Exception { perf(AVC, 720, 480, OTHER, 0); }
testAvcOther1Qual0720x0480()238     public void testAvcOther1Qual0720x0480() throws Exception { qual(AVC, 720, 480, OTHER, 1); }
testAvcOther1Perf0720x0480()239     public void testAvcOther1Perf0720x0480() throws Exception { perf(AVC, 720, 480, OTHER, 1); }
testAvcOther2Qual0720x0480()240     public void testAvcOther2Qual0720x0480() throws Exception { qual(AVC, 720, 480, OTHER, 2); }
testAvcOther2Perf0720x0480()241     public void testAvcOther2Perf0720x0480() throws Exception { perf(AVC, 720, 480, OTHER, 2); }
testAvcOther3Qual0720x0480()242     public void testAvcOther3Qual0720x0480() throws Exception { qual(AVC, 720, 480, OTHER, 3); }
testAvcOther3Perf0720x0480()243     public void testAvcOther3Perf0720x0480() throws Exception { perf(AVC, 720, 480, OTHER, 3); }
testAvcCount1280x0720()244     public void testAvcCount1280x0720() throws Exception { count(AVC, 1280, 720, 2, 4); }
testAvcGoog0Qual1280x0720()245     public void testAvcGoog0Qual1280x0720() throws Exception { qual(AVC, 1280, 720, GOOG, 0); }
testAvcGoog0Perf1280x0720()246     public void testAvcGoog0Perf1280x0720() throws Exception { perf(AVC, 1280, 720, GOOG, 0); }
testAvcGoog1Qual1280x0720()247     public void testAvcGoog1Qual1280x0720() throws Exception { qual(AVC, 1280, 720, GOOG, 1); }
testAvcGoog1Perf1280x0720()248     public void testAvcGoog1Perf1280x0720() throws Exception { perf(AVC, 1280, 720, GOOG, 1); }
249 
testAvcOther0Qual1280x0720()250     public void testAvcOther0Qual1280x0720() throws Exception { qual(AVC, 1280, 720, OTHER, 0); }
testAvcOther0Perf1280x0720()251     public void testAvcOther0Perf1280x0720() throws Exception { perf(AVC, 1280, 720, OTHER, 0); }
testAvcOther1Qual1280x0720()252     public void testAvcOther1Qual1280x0720() throws Exception { qual(AVC, 1280, 720, OTHER, 1); }
testAvcOther1Perf1280x0720()253     public void testAvcOther1Perf1280x0720() throws Exception { perf(AVC, 1280, 720, OTHER, 1); }
testAvcOther2Qual1280x0720()254     public void testAvcOther2Qual1280x0720() throws Exception { qual(AVC, 1280, 720, OTHER, 2); }
testAvcOther2Perf1280x0720()255     public void testAvcOther2Perf1280x0720() throws Exception { perf(AVC, 1280, 720, OTHER, 2); }
testAvcOther3Qual1280x0720()256     public void testAvcOther3Qual1280x0720() throws Exception { qual(AVC, 1280, 720, OTHER, 3); }
testAvcOther3Perf1280x0720()257     public void testAvcOther3Perf1280x0720() throws Exception { perf(AVC, 1280, 720, OTHER, 3); }
testAvcCount1920x1080()258     public void testAvcCount1920x1080() throws Exception { count(AVC, 1920, 1080, 2, 4); }
testAvcGoog0Qual1920x1080()259     public void testAvcGoog0Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, GOOG, 0); }
testAvcGoog0Perf1920x1080()260     public void testAvcGoog0Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, GOOG, 0); }
testAvcGoog1Qual1920x1080()261     public void testAvcGoog1Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, GOOG, 1); }
testAvcGoog1Perf1920x1080()262     public void testAvcGoog1Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, GOOG, 1); }
263 
testAvcOther0Qual1920x1080()264     public void testAvcOther0Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, OTHER, 0); }
testAvcOther0Perf1920x1080()265     public void testAvcOther0Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, OTHER, 0); }
testAvcOther1Qual1920x1080()266     public void testAvcOther1Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, OTHER, 1); }
testAvcOther1Perf1920x1080()267     public void testAvcOther1Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, OTHER, 1); }
testAvcOther2Qual1920x1080()268     public void testAvcOther2Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, OTHER, 2); }
testAvcOther2Perf1920x1080()269     public void testAvcOther2Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, OTHER, 2); }
testAvcOther3Qual1920x1080()270     public void testAvcOther3Qual1920x1080() throws Exception { qual(AVC, 1920, 1080, OTHER, 3); }
testAvcOther3Perf1920x1080()271     public void testAvcOther3Perf1920x1080() throws Exception { perf(AVC, 1920, 1080, OTHER, 3); }
272 
273     // H263 tests
testH263Count0176x0144()274     public void testH263Count0176x0144() throws Exception { count(H263, 176, 144, 2, 2); }
testH263Goog0Qual0176x0144()275     public void testH263Goog0Qual0176x0144() throws Exception { qual(H263, 176, 144, GOOG, 0); }
testH263Goog0Perf0176x0144()276     public void testH263Goog0Perf0176x0144() throws Exception { perf(H263, 176, 144, GOOG, 0); }
testH263Goog1Qual0176x0144()277     public void testH263Goog1Qual0176x0144() throws Exception { qual(H263, 176, 144, GOOG, 1); }
testH263Goog1Perf0176x0144()278     public void testH263Goog1Perf0176x0144() throws Exception { perf(H263, 176, 144, GOOG, 1); }
279 
testH263Other0Qual0176x0144()280     public void testH263Other0Qual0176x0144() throws Exception { qual(H263, 176, 144, OTHER, 0); }
testH263Other0Perf0176x0144()281     public void testH263Other0Perf0176x0144() throws Exception { perf(H263, 176, 144, OTHER, 0); }
testH263Other1Qual0176x0144()282     public void testH263Other1Qual0176x0144() throws Exception { qual(H263, 176, 144, OTHER, 1); }
testH263Other1Perf0176x0144()283     public void testH263Other1Perf0176x0144() throws Exception { perf(H263, 176, 144, OTHER, 1); }
testH263Count0352x0288()284     public void testH263Count0352x0288() throws Exception { count(H263, 352, 288, 2, 2); }
testH263Goog0Qual0352x0288()285     public void testH263Goog0Qual0352x0288() throws Exception { qual(H263, 352, 288, GOOG, 0); }
testH263Goog0Perf0352x0288()286     public void testH263Goog0Perf0352x0288() throws Exception { perf(H263, 352, 288, GOOG, 0); }
testH263Goog1Qual0352x0288()287     public void testH263Goog1Qual0352x0288() throws Exception { qual(H263, 352, 288, GOOG, 1); }
testH263Goog1Perf0352x0288()288     public void testH263Goog1Perf0352x0288() throws Exception { perf(H263, 352, 288, GOOG, 1); }
289 
testH263Other0Qual0352x0288()290     public void testH263Other0Qual0352x0288() throws Exception { qual(H263, 352, 288, OTHER, 0); }
testH263Other0Perf0352x0288()291     public void testH263Other0Perf0352x0288() throws Exception { perf(H263, 352, 288, OTHER, 0); }
testH263Other1Qual0352x0288()292     public void testH263Other1Qual0352x0288() throws Exception { qual(H263, 352, 288, OTHER, 1); }
testH263Other1Perf0352x0288()293     public void testH263Other1Perf0352x0288() throws Exception { perf(H263, 352, 288, OTHER, 1); }
testH263Count0704x0576()294     public void testH263Count0704x0576() throws Exception { count(H263, 704, 576, 2, 2); }
testH263Goog0Qual0704x0576()295     public void testH263Goog0Qual0704x0576() throws Exception { qual(H263, 704, 576, GOOG, 0, 25); }
testH263Goog0Perf0704x0576()296     public void testH263Goog0Perf0704x0576() throws Exception { perf(H263, 704, 576, GOOG, 0); }
testH263Other0Qual0704x0576()297     public void testH263Other0Qual0704x0576() throws Exception { qual(H263, 704, 576, OTHER, 0, 25); }
testH263Other0Perf0704x0576()298     public void testH263Other0Perf0704x0576() throws Exception { perf(H263, 704, 576, OTHER, 0); }
testH263Other1Qual0704x0576()299     public void testH263Other1Qual0704x0576() throws Exception { qual(H263, 704, 576, OTHER, 1, 25); }
testH263Other1Perf0704x0576()300     public void testH263Other1Perf0704x0576() throws Exception { perf(H263, 704, 576, OTHER, 1); }
testH263Count1408x1152()301     public void testH263Count1408x1152() throws Exception { count(H263, 1408, 1152, 2, 2); }
testH263Goog0Qual1408x1152()302     public void testH263Goog0Qual1408x1152() throws Exception { qual(H263, 1408, 1152, GOOG, 0, 25); }
testH263Goog0Perf1408x1152()303     public void testH263Goog0Perf1408x1152() throws Exception { perf(H263, 1408, 1152, GOOG, 0); }
testH263Other0Qual1408x1152()304     public void testH263Other0Qual1408x1152() throws Exception { qual(H263, 1408, 1152, OTHER, 0, 25); }
testH263Other0Perf1408x1152()305     public void testH263Other0Perf1408x1152() throws Exception { perf(H263, 1408, 1152, OTHER, 0); }
testH263Other1Qual1408x1152()306     public void testH263Other1Qual1408x1152() throws Exception { qual(H263, 1408, 1152, OTHER, 1, 25); }
testH263Other1Perf1408x1152()307     public void testH263Other1Perf1408x1152() throws Exception { perf(H263, 1408, 1152, OTHER, 1); }
308 
309     // HEVC tests
testHevcCount0320x0240()310     public void testHevcCount0320x0240() throws Exception { count(HEVC, 320, 240, 2, 4); }
testHevcGoog0Qual0320x0240()311     public void testHevcGoog0Qual0320x0240() throws Exception { qual(HEVC, 320, 240, GOOG, 0); }
testHevcGoog0Perf0320x0240()312     public void testHevcGoog0Perf0320x0240() throws Exception { perf(HEVC, 320, 240, GOOG, 0); }
testHevcGoog1Qual0320x0240()313     public void testHevcGoog1Qual0320x0240() throws Exception { qual(HEVC, 320, 240, GOOG, 1); }
testHevcGoog1Perf0320x0240()314     public void testHevcGoog1Perf0320x0240() throws Exception { perf(HEVC, 320, 240, GOOG, 1); }
315 
testHevcOther0Qual0320x0240()316     public void testHevcOther0Qual0320x0240() throws Exception { qual(HEVC, 320, 240, OTHER, 0); }
testHevcOther0Perf0320x0240()317     public void testHevcOther0Perf0320x0240() throws Exception { perf(HEVC, 320, 240, OTHER, 0); }
testHevcOther1Qual0320x0240()318     public void testHevcOther1Qual0320x0240() throws Exception { qual(HEVC, 320, 240, OTHER, 1); }
testHevcOther1Perf0320x0240()319     public void testHevcOther1Perf0320x0240() throws Exception { perf(HEVC, 320, 240, OTHER, 1); }
testHevcOther2Qual0320x0240()320     public void testHevcOther2Qual0320x0240() throws Exception { qual(HEVC, 320, 240, OTHER, 2); }
testHevcOther2Perf0320x0240()321     public void testHevcOther2Perf0320x0240() throws Exception { perf(HEVC, 320, 240, OTHER, 2); }
testHevcOther3Qual0320x0240()322     public void testHevcOther3Qual0320x0240() throws Exception { qual(HEVC, 320, 240, OTHER, 3); }
testHevcOther3Perf0320x0240()323     public void testHevcOther3Perf0320x0240() throws Exception { perf(HEVC, 320, 240, OTHER, 3); }
testHevcCount0720x0480()324     public void testHevcCount0720x0480() throws Exception { count(HEVC, 720, 480, 2, 4); }
testHevcGoog0Qual0720x0480()325     public void testHevcGoog0Qual0720x0480() throws Exception { qual(HEVC, 720, 480, GOOG, 0); }
testHevcGoog0Perf0720x0480()326     public void testHevcGoog0Perf0720x0480() throws Exception { perf(HEVC, 720, 480, GOOG, 0); }
testHevcGoog1Qual0720x0480()327     public void testHevcGoog1Qual0720x0480() throws Exception { qual(HEVC, 720, 480, GOOG, 1); }
testHevcGoog1Perf0720x0480()328     public void testHevcGoog1Perf0720x0480() throws Exception { perf(HEVC, 720, 480, GOOG, 1); }
329 
testHevcOther0Qual0720x0480()330     public void testHevcOther0Qual0720x0480() throws Exception { qual(HEVC, 720, 480, OTHER, 0); }
testHevcOther0Perf0720x0480()331     public void testHevcOther0Perf0720x0480() throws Exception { perf(HEVC, 720, 480, OTHER, 0); }
testHevcOther1Qual0720x0480()332     public void testHevcOther1Qual0720x0480() throws Exception { qual(HEVC, 720, 480, OTHER, 1); }
testHevcOther1Perf0720x0480()333     public void testHevcOther1Perf0720x0480() throws Exception { perf(HEVC, 720, 480, OTHER, 1); }
testHevcOther2Qual0720x0480()334     public void testHevcOther2Qual0720x0480() throws Exception { qual(HEVC, 720, 480, OTHER, 2); }
testHevcOther2Perf0720x0480()335     public void testHevcOther2Perf0720x0480() throws Exception { perf(HEVC, 720, 480, OTHER, 2); }
testHevcOther3Qual0720x0480()336     public void testHevcOther3Qual0720x0480() throws Exception { qual(HEVC, 720, 480, OTHER, 3); }
testHevcOther3Perf0720x0480()337     public void testHevcOther3Perf0720x0480() throws Exception { perf(HEVC, 720, 480, OTHER, 3); }
testHevcCount1280x0720()338     public void testHevcCount1280x0720() throws Exception { count(HEVC, 1280, 720, 2, 4); }
testHevcGoog0Qual1280x0720()339     public void testHevcGoog0Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, GOOG, 0); }
testHevcGoog0Perf1280x0720()340     public void testHevcGoog0Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, GOOG, 0); }
testHevcGoog1Qual1280x0720()341     public void testHevcGoog1Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, GOOG, 1); }
testHevcGoog1Perf1280x0720()342     public void testHevcGoog1Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, GOOG, 1); }
343 
testHevcOther0Qual1280x0720()344     public void testHevcOther0Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, OTHER, 0); }
testHevcOther0Perf1280x0720()345     public void testHevcOther0Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, OTHER, 0); }
testHevcOther1Qual1280x0720()346     public void testHevcOther1Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, OTHER, 1); }
testHevcOther1Perf1280x0720()347     public void testHevcOther1Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, OTHER, 1); }
testHevcOther2Qual1280x0720()348     public void testHevcOther2Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, OTHER, 2); }
testHevcOther2Perf1280x0720()349     public void testHevcOther2Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, OTHER, 2); }
testHevcOther3Qual1280x0720()350     public void testHevcOther3Qual1280x0720() throws Exception { qual(HEVC, 1280, 720, OTHER, 3); }
testHevcOther3Perf1280x0720()351     public void testHevcOther3Perf1280x0720() throws Exception { perf(HEVC, 1280, 720, OTHER, 3); }
testHevcCount1920x1080()352     public void testHevcCount1920x1080() throws Exception { count(HEVC, 1920, 1080, 2, 4); }
testHevcGoog0Qual1920x1080()353     public void testHevcGoog0Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, GOOG, 0); }
testHevcGoog0Perf1920x1080()354     public void testHevcGoog0Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, GOOG, 0); }
testHevcGoog1Qual1920x1080()355     public void testHevcGoog1Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, GOOG, 1); }
testHevcGoog1Perf1920x1080()356     public void testHevcGoog1Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, GOOG, 1); }
357 
testHevcOther0Qual1920x1080()358     public void testHevcOther0Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, OTHER, 0); }
testHevcOther0Perf1920x1080()359     public void testHevcOther0Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, OTHER, 0); }
testHevcOther1Qual1920x1080()360     public void testHevcOther1Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, OTHER, 1); }
testHevcOther1Perf1920x1080()361     public void testHevcOther1Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, OTHER, 1); }
testHevcOther2Qual1920x1080()362     public void testHevcOther2Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, OTHER, 2); }
testHevcOther2Perf1920x1080()363     public void testHevcOther2Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, OTHER, 2); }
testHevcOther3Qual1920x1080()364     public void testHevcOther3Qual1920x1080() throws Exception { qual(HEVC, 1920, 1080, OTHER, 3); }
testHevcOther3Perf1920x1080()365     public void testHevcOther3Perf1920x1080() throws Exception { perf(HEVC, 1920, 1080, OTHER, 3); }
testHevcCount3840x2160()366     public void testHevcCount3840x2160() throws Exception { count(HEVC, 3840, 2160, 2, 4); }
testHevcGoog0Qual3840x2160()367     public void testHevcGoog0Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, GOOG, 0); }
testHevcGoog0Perf3840x2160()368     public void testHevcGoog0Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, GOOG, 0); }
testHevcGoog1Qual3840x2160()369     public void testHevcGoog1Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, GOOG, 1); }
testHevcGoog1Perf3840x2160()370     public void testHevcGoog1Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, GOOG, 1); }
371 
testHevcOther0Qual3840x2160()372     public void testHevcOther0Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, OTHER, 0); }
testHevcOther0Perf3840x2160()373     public void testHevcOther0Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, OTHER, 0); }
testHevcOther1Qual3840x2160()374     public void testHevcOther1Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, OTHER, 1); }
testHevcOther1Perf3840x2160()375     public void testHevcOther1Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, OTHER, 1); }
testHevcOther2Qual3840x2160()376     public void testHevcOther2Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, OTHER, 2); }
testHevcOther2Perf3840x2160()377     public void testHevcOther2Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, OTHER, 2); }
testHevcOther3Qual3840x2160()378     public void testHevcOther3Qual3840x2160() throws Exception { qual(HEVC, 3840, 2160, OTHER, 3); }
testHevcOther3Perf3840x2160()379     public void testHevcOther3Perf3840x2160() throws Exception { perf(HEVC, 3840, 2160, OTHER, 3); }
380 
381     // MPEG2 tests
testMpeg2Count0176x0144()382     public void testMpeg2Count0176x0144() throws Exception { count(MPEG2, 176, 144, 2, 4); }
testMpeg2Goog0Qual0176x0144()383     public void testMpeg2Goog0Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, GOOG, 0); }
testMpeg2Goog0Perf0176x0144()384     public void testMpeg2Goog0Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, GOOG, 0); }
testMpeg2Goog1Qual0176x0144()385     public void testMpeg2Goog1Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, GOOG, 1); }
testMpeg2Goog1Perf0176x0144()386     public void testMpeg2Goog1Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, GOOG, 1); }
387 
testMpeg2Other0Qual0176x0144()388     public void testMpeg2Other0Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, OTHER, 0); }
testMpeg2Other0Perf0176x0144()389     public void testMpeg2Other0Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, OTHER, 0); }
testMpeg2Other1Qual0176x0144()390     public void testMpeg2Other1Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, OTHER, 1); }
testMpeg2Other1Perf0176x0144()391     public void testMpeg2Other1Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, OTHER, 1); }
testMpeg2Other2Qual0176x0144()392     public void testMpeg2Other2Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, OTHER, 2); }
testMpeg2Other2Perf0176x0144()393     public void testMpeg2Other2Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, OTHER, 2); }
testMpeg2Other3Qual0176x0144()394     public void testMpeg2Other3Qual0176x0144() throws Exception { qual(MPEG2, 176, 144, OTHER, 3); }
testMpeg2Other3Perf0176x0144()395     public void testMpeg2Other3Perf0176x0144() throws Exception { perf(MPEG2, 176, 144, OTHER, 3); }
testMpeg2Count0352x0288()396     public void testMpeg2Count0352x0288() throws Exception { count(MPEG2, 352, 288, 2, 4); }
testMpeg2Goog0Qual0352x0288()397     public void testMpeg2Goog0Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, GOOG, 0); }
testMpeg2Goog0Perf0352x0288()398     public void testMpeg2Goog0Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, GOOG, 0); }
testMpeg2Goog1Qual0352x0288()399     public void testMpeg2Goog1Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, GOOG, 1); }
testMpeg2Goog1Perf0352x0288()400     public void testMpeg2Goog1Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, GOOG, 1); }
401 
testMpeg2Other0Qual0352x0288()402     public void testMpeg2Other0Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, OTHER, 0); }
testMpeg2Other0Perf0352x0288()403     public void testMpeg2Other0Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, OTHER, 0); }
testMpeg2Other1Qual0352x0288()404     public void testMpeg2Other1Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, OTHER, 1); }
testMpeg2Other1Perf0352x0288()405     public void testMpeg2Other1Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, OTHER, 1); }
testMpeg2Other2Qual0352x0288()406     public void testMpeg2Other2Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, OTHER, 2); }
testMpeg2Other2Perf0352x0288()407     public void testMpeg2Other2Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, OTHER, 2); }
testMpeg2Other3Qual0352x0288()408     public void testMpeg2Other3Qual0352x0288() throws Exception { qual(MPEG2, 352, 288, OTHER, 3); }
testMpeg2Other3Perf0352x0288()409     public void testMpeg2Other3Perf0352x0288() throws Exception { perf(MPEG2, 352, 288, OTHER, 3); }
testMpeg2Count0640x0480()410     public void testMpeg2Count0640x0480() throws Exception { count(MPEG2, 640, 480, 2, 4); }
testMpeg2Goog0Qual0640x0480()411     public void testMpeg2Goog0Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, GOOG, 0); }
testMpeg2Goog0Perf0640x0480()412     public void testMpeg2Goog0Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, GOOG, 0); }
testMpeg2Goog1Qual0640x0480()413     public void testMpeg2Goog1Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, GOOG, 1); }
testMpeg2Goog1Perf0640x0480()414     public void testMpeg2Goog1Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, GOOG, 1); }
415 
testMpeg2Other0Qual0640x0480()416     public void testMpeg2Other0Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, OTHER, 0); }
testMpeg2Other0Perf0640x0480()417     public void testMpeg2Other0Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, OTHER, 0); }
testMpeg2Other1Qual0640x0480()418     public void testMpeg2Other1Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, OTHER, 1); }
testMpeg2Other1Perf0640x0480()419     public void testMpeg2Other1Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, OTHER, 1); }
testMpeg2Other2Qual0640x0480()420     public void testMpeg2Other2Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, OTHER, 2); }
testMpeg2Other2Perf0640x0480()421     public void testMpeg2Other2Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, OTHER, 2); }
testMpeg2Other3Qual0640x0480()422     public void testMpeg2Other3Qual0640x0480() throws Exception { qual(MPEG2, 640, 480, OTHER, 3); }
testMpeg2Other3Perf0640x0480()423     public void testMpeg2Other3Perf0640x0480() throws Exception { perf(MPEG2, 640, 480, OTHER, 3); }
testMpeg2Count1280x0720()424     public void testMpeg2Count1280x0720() throws Exception { count(MPEG2, 1280, 720, 2, 4); }
testMpeg2Goog0Qual1280x0720()425     public void testMpeg2Goog0Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, GOOG, 0); }
testMpeg2Goog0Perf1280x0720()426     public void testMpeg2Goog0Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, GOOG, 0); }
testMpeg2Goog1Qual1280x0720()427     public void testMpeg2Goog1Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, GOOG, 1); }
testMpeg2Goog1Perf1280x0720()428     public void testMpeg2Goog1Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, GOOG, 1); }
429 
testMpeg2Other0Qual1280x0720()430     public void testMpeg2Other0Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, OTHER, 0); }
testMpeg2Other0Perf1280x0720()431     public void testMpeg2Other0Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, OTHER, 0); }
testMpeg2Other1Qual1280x0720()432     public void testMpeg2Other1Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, OTHER, 1); }
testMpeg2Other1Perf1280x0720()433     public void testMpeg2Other1Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, OTHER, 1); }
testMpeg2Other2Qual1280x0720()434     public void testMpeg2Other2Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, OTHER, 2); }
testMpeg2Other2Perf1280x0720()435     public void testMpeg2Other2Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, OTHER, 2); }
testMpeg2Other3Qual1280x0720()436     public void testMpeg2Other3Qual1280x0720() throws Exception { qual(MPEG2, 1280, 720, OTHER, 3); }
testMpeg2Other3Perf1280x0720()437     public void testMpeg2Other3Perf1280x0720() throws Exception { perf(MPEG2, 1280, 720, OTHER, 3); }
testMpeg2Count1920x1080()438     public void testMpeg2Count1920x1080() throws Exception { count(MPEG2, 1920, 1080, 2, 4); }
testMpeg2Goog0Qual1920x1080()439     public void testMpeg2Goog0Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, GOOG, 0); }
testMpeg2Goog0Perf1920x1080()440     public void testMpeg2Goog0Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, GOOG, 0); }
testMpeg2Goog1Qual1920x1080()441     public void testMpeg2Goog1Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, GOOG, 1); }
testMpeg2Goog1Perf1920x1080()442     public void testMpeg2Goog1Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, GOOG, 1); }
443 
testMpeg2Other0Qual1920x1080()444     public void testMpeg2Other0Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, OTHER, 0); }
testMpeg2Other0Perf1920x1080()445     public void testMpeg2Other0Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, OTHER, 0); }
testMpeg2Other1Qual1920x1080()446     public void testMpeg2Other1Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, OTHER, 1); }
testMpeg2Other1Perf1920x1080()447     public void testMpeg2Other1Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, OTHER, 1); }
testMpeg2Other2Qual1920x1080()448     public void testMpeg2Other2Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, OTHER, 2); }
testMpeg2Other2Perf1920x1080()449     public void testMpeg2Other2Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, OTHER, 2); }
testMpeg2Other3Qual1920x1080()450     public void testMpeg2Other3Qual1920x1080() throws Exception { qual(MPEG2, 1920, 1080, OTHER, 3); }
testMpeg2Other3Perf1920x1080()451     public void testMpeg2Other3Perf1920x1080() throws Exception { perf(MPEG2, 1920, 1080, OTHER, 3); }
452 
453     // MPEG4 tests
testMpeg4Count0176x0144()454     public void testMpeg4Count0176x0144() throws Exception { count(MPEG4, 176, 144, 2, 4); }
testMpeg4Goog0Qual0176x0144()455     public void testMpeg4Goog0Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, GOOG, 0); }
testMpeg4Goog0Perf0176x0144()456     public void testMpeg4Goog0Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, GOOG, 0); }
testMpeg4Goog1Qual0176x0144()457     public void testMpeg4Goog1Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, GOOG, 1); }
testMpeg4Goog1Perf0176x0144()458     public void testMpeg4Goog1Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, GOOG, 1); }
459 
testMpeg4Other0Qual0176x0144()460     public void testMpeg4Other0Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, OTHER, 0); }
testMpeg4Other0Perf0176x0144()461     public void testMpeg4Other0Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, OTHER, 0); }
testMpeg4Other1Qual0176x0144()462     public void testMpeg4Other1Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, OTHER, 1); }
testMpeg4Other1Perf0176x0144()463     public void testMpeg4Other1Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, OTHER, 1); }
testMpeg4Other2Qual0176x0144()464     public void testMpeg4Other2Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, OTHER, 2); }
testMpeg4Other2Perf0176x0144()465     public void testMpeg4Other2Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, OTHER, 2); }
testMpeg4Other3Qual0176x0144()466     public void testMpeg4Other3Qual0176x0144() throws Exception { qual(MPEG4, 176, 144, OTHER, 3); }
testMpeg4Other3Perf0176x0144()467     public void testMpeg4Other3Perf0176x0144() throws Exception { perf(MPEG4, 176, 144, OTHER, 3); }
testMpeg4Count0352x0288()468     public void testMpeg4Count0352x0288() throws Exception { count(MPEG4, 352, 288, 2, 4); }
testMpeg4Goog0Qual0352x0288()469     public void testMpeg4Goog0Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, GOOG, 0); }
testMpeg4Goog0Perf0352x0288()470     public void testMpeg4Goog0Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, GOOG, 0); }
testMpeg4Goog1Qual0352x0288()471     public void testMpeg4Goog1Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, GOOG, 1); }
testMpeg4Goog1Perf0352x0288()472     public void testMpeg4Goog1Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, GOOG, 1); }
473 
testMpeg4Other0Qual0352x0288()474     public void testMpeg4Other0Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, OTHER, 0); }
testMpeg4Other0Perf0352x0288()475     public void testMpeg4Other0Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, OTHER, 0); }
testMpeg4Other1Qual0352x0288()476     public void testMpeg4Other1Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, OTHER, 1); }
testMpeg4Other1Perf0352x0288()477     public void testMpeg4Other1Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, OTHER, 1); }
testMpeg4Other2Qual0352x0288()478     public void testMpeg4Other2Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, OTHER, 2); }
testMpeg4Other2Perf0352x0288()479     public void testMpeg4Other2Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, OTHER, 2); }
testMpeg4Other3Qual0352x0288()480     public void testMpeg4Other3Qual0352x0288() throws Exception { qual(MPEG4, 352, 288, OTHER, 3); }
testMpeg4Other3Perf0352x0288()481     public void testMpeg4Other3Perf0352x0288() throws Exception { perf(MPEG4, 352, 288, OTHER, 3); }
testMpeg4Count0640x0480()482     public void testMpeg4Count0640x0480() throws Exception { count(MPEG4, 640, 480, 2, 4); }
testMpeg4Goog0Qual0640x0480()483     public void testMpeg4Goog0Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, GOOG, 0); }
testMpeg4Goog0Perf0640x0480()484     public void testMpeg4Goog0Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, GOOG, 0); }
testMpeg4Goog1Qual0640x0480()485     public void testMpeg4Goog1Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, GOOG, 1); }
testMpeg4Goog1Perf0640x0480()486     public void testMpeg4Goog1Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, GOOG, 1); }
487 
testMpeg4Other0Qual0640x0480()488     public void testMpeg4Other0Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, OTHER, 0); }
testMpeg4Other0Perf0640x0480()489     public void testMpeg4Other0Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, OTHER, 0); }
testMpeg4Other1Qual0640x0480()490     public void testMpeg4Other1Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, OTHER, 1); }
testMpeg4Other1Perf0640x0480()491     public void testMpeg4Other1Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, OTHER, 1); }
testMpeg4Other2Qual0640x0480()492     public void testMpeg4Other2Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, OTHER, 2); }
testMpeg4Other2Perf0640x0480()493     public void testMpeg4Other2Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, OTHER, 2); }
testMpeg4Other3Qual0640x0480()494     public void testMpeg4Other3Qual0640x0480() throws Exception { qual(MPEG4, 640, 480, OTHER, 3); }
testMpeg4Other3Perf0640x0480()495     public void testMpeg4Other3Perf0640x0480() throws Exception { perf(MPEG4, 640, 480, OTHER, 3); }
testMpeg4Count1280x0720()496     public void testMpeg4Count1280x0720() throws Exception { count(MPEG4, 1280, 720, 2, 4); }
testMpeg4Goog0Qual1280x0720()497     public void testMpeg4Goog0Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, GOOG, 0); }
testMpeg4Goog0Perf1280x0720()498     public void testMpeg4Goog0Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, GOOG, 0); }
testMpeg4Goog1Qual1280x0720()499     public void testMpeg4Goog1Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, GOOG, 1); }
testMpeg4Goog1Perf1280x0720()500     public void testMpeg4Goog1Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, GOOG, 1); }
501 
testMpeg4Other0Qual1280x0720()502     public void testMpeg4Other0Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, OTHER, 0); }
testMpeg4Other0Perf1280x0720()503     public void testMpeg4Other0Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, OTHER, 0); }
testMpeg4Other1Qual1280x0720()504     public void testMpeg4Other1Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, OTHER, 1); }
testMpeg4Other1Perf1280x0720()505     public void testMpeg4Other1Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, OTHER, 1); }
testMpeg4Other2Qual1280x0720()506     public void testMpeg4Other2Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, OTHER, 2); }
testMpeg4Other2Perf1280x0720()507     public void testMpeg4Other2Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, OTHER, 2); }
testMpeg4Other3Qual1280x0720()508     public void testMpeg4Other3Qual1280x0720() throws Exception { qual(MPEG4, 1280, 720, OTHER, 3); }
testMpeg4Other3Perf1280x0720()509     public void testMpeg4Other3Perf1280x0720() throws Exception { perf(MPEG4, 1280, 720, OTHER, 3); }
510 
511     // VP8 tests
testVp8Count0320x0180()512     public void testVp8Count0320x0180() throws Exception { count(VP8, 320, 180, 2, 2); }
testVp8Goog0Qual0320x0180()513     public void testVp8Goog0Qual0320x0180() throws Exception { qual(VP8, 320, 180, GOOG, 0); }
testVp8Goog0Perf0320x0180()514     public void testVp8Goog0Perf0320x0180() throws Exception { perf(VP8, 320, 180, GOOG, 0); }
testVp8Goog1Qual0320x0180()515     public void testVp8Goog1Qual0320x0180() throws Exception { qual(VP8, 320, 180, GOOG, 1); }
testVp8Goog1Perf0320x0180()516     public void testVp8Goog1Perf0320x0180() throws Exception { perf(VP8, 320, 180, GOOG, 1); }
517 
testVp8Other0Qual0320x0180()518     public void testVp8Other0Qual0320x0180() throws Exception { qual(VP8, 320, 180, OTHER, 0); }
testVp8Other0Perf0320x0180()519     public void testVp8Other0Perf0320x0180() throws Exception { perf(VP8, 320, 180, OTHER, 0); }
testVp8Other1Qual0320x0180()520     public void testVp8Other1Qual0320x0180() throws Exception { qual(VP8, 320, 180, OTHER, 1); }
testVp8Other1Perf0320x0180()521     public void testVp8Other1Perf0320x0180() throws Exception { perf(VP8, 320, 180, OTHER, 1); }
testVp8Count0640x0360()522     public void testVp8Count0640x0360() throws Exception { count(VP8, 640, 360, 2, 2); }
testVp8Goog0Qual0640x0360()523     public void testVp8Goog0Qual0640x0360() throws Exception { qual(VP8, 640, 360, GOOG, 0); }
testVp8Goog0Perf0640x0360()524     public void testVp8Goog0Perf0640x0360() throws Exception { perf(VP8, 640, 360, GOOG, 0); }
testVp8Goog1Qual0640x0360()525     public void testVp8Goog1Qual0640x0360() throws Exception { qual(VP8, 640, 360, GOOG, 1); }
testVp8Goog1Perf0640x0360()526     public void testVp8Goog1Perf0640x0360() throws Exception { perf(VP8, 640, 360, GOOG, 1); }
527 
testVp8Other0Qual0640x0360()528     public void testVp8Other0Qual0640x0360() throws Exception { qual(VP8, 640, 360, OTHER, 0); }
testVp8Other0Perf0640x0360()529     public void testVp8Other0Perf0640x0360() throws Exception { perf(VP8, 640, 360, OTHER, 0); }
testVp8Other1Qual0640x0360()530     public void testVp8Other1Qual0640x0360() throws Exception { qual(VP8, 640, 360, OTHER, 1); }
testVp8Other1Perf0640x0360()531     public void testVp8Other1Perf0640x0360() throws Exception { perf(VP8, 640, 360, OTHER, 1); }
testVp8Count1280x0720()532     public void testVp8Count1280x0720() throws Exception { count(VP8, 1280, 720, 2, 2); }
testVp8Goog0Qual1280x0720()533     public void testVp8Goog0Qual1280x0720() throws Exception { qual(VP8, 1280, 720, GOOG, 0); }
testVp8Goog0Perf1280x0720()534     public void testVp8Goog0Perf1280x0720() throws Exception { perf(VP8, 1280, 720, GOOG, 0); }
testVp8Goog1Qual1280x0720()535     public void testVp8Goog1Qual1280x0720() throws Exception { qual(VP8, 1280, 720, GOOG, 1); }
testVp8Goog1Perf1280x0720()536     public void testVp8Goog1Perf1280x0720() throws Exception { perf(VP8, 1280, 720, GOOG, 1); }
537 
testVp8Other0Qual1280x0720()538     public void testVp8Other0Qual1280x0720() throws Exception { qual(VP8, 1280, 720, OTHER, 0); }
testVp8Other0Perf1280x0720()539     public void testVp8Other0Perf1280x0720() throws Exception { perf(VP8, 1280, 720, OTHER, 0); }
testVp8Other1Qual1280x0720()540     public void testVp8Other1Qual1280x0720() throws Exception { qual(VP8, 1280, 720, OTHER, 1); }
testVp8Other1Perf1280x0720()541     public void testVp8Other1Perf1280x0720() throws Exception { perf(VP8, 1280, 720, OTHER, 1); }
testVp8Count1920x1080()542     public void testVp8Count1920x1080() throws Exception { count(VP8, 1920, 1080, 2, 2); }
testVp8Goog0Qual1920x1080()543     public void testVp8Goog0Qual1920x1080() throws Exception { qual(VP8, 1920, 1080, GOOG, 0); }
testVp8Goog0Perf1920x1080()544     public void testVp8Goog0Perf1920x1080() throws Exception { perf(VP8, 1920, 1080, GOOG, 0); }
testVp8Goog1Qual1920x1080()545     public void testVp8Goog1Qual1920x1080() throws Exception { qual(VP8, 1920, 1080, GOOG, 1); }
testVp8Goog1Perf1920x1080()546     public void testVp8Goog1Perf1920x1080() throws Exception { perf(VP8, 1920, 1080, GOOG, 1); }
547 
testVp8Other0Qual1920x1080()548     public void testVp8Other0Qual1920x1080() throws Exception { qual(VP8, 1920, 1080, OTHER, 0); }
testVp8Other0Perf1920x1080()549     public void testVp8Other0Perf1920x1080() throws Exception { perf(VP8, 1920, 1080, OTHER, 0); }
testVp8Other1Qual1920x1080()550     public void testVp8Other1Qual1920x1080() throws Exception { qual(VP8, 1920, 1080, OTHER, 1); }
testVp8Other1Perf1920x1080()551     public void testVp8Other1Perf1920x1080() throws Exception { perf(VP8, 1920, 1080, OTHER, 1); }
552 
553     // VP9 tests
testVp9Count0320x0180()554     public void testVp9Count0320x0180() throws Exception { count(VP9, 320, 180, 2, 4); }
testVp9Goog0Qual0320x0180()555     public void testVp9Goog0Qual0320x0180() throws Exception { qual(VP9, 320, 180, GOOG, 0); }
testVp9Goog0Perf0320x0180()556     public void testVp9Goog0Perf0320x0180() throws Exception { perf(VP9, 320, 180, GOOG, 0); }
testVp9Goog1Qual0320x0180()557     public void testVp9Goog1Qual0320x0180() throws Exception { qual(VP9, 320, 180, GOOG, 1); }
testVp9Goog1Perf0320x0180()558     public void testVp9Goog1Perf0320x0180() throws Exception { perf(VP9, 320, 180, GOOG, 1); }
559 
testVp9Other0Qual0320x0180()560     public void testVp9Other0Qual0320x0180() throws Exception { qual(VP9, 320, 180, OTHER, 0); }
testVp9Other0Perf0320x0180()561     public void testVp9Other0Perf0320x0180() throws Exception { perf(VP9, 320, 180, OTHER, 0); }
testVp9Other1Qual0320x0180()562     public void testVp9Other1Qual0320x0180() throws Exception { qual(VP9, 320, 180, OTHER, 1); }
testVp9Other1Perf0320x0180()563     public void testVp9Other1Perf0320x0180() throws Exception { perf(VP9, 320, 180, OTHER, 1); }
testVp9Other2Qual0320x0180()564     public void testVp9Other2Qual0320x0180() throws Exception { qual(VP9, 320, 180, OTHER, 2); }
testVp9Other2Perf0320x0180()565     public void testVp9Other2Perf0320x0180() throws Exception { perf(VP9, 320, 180, OTHER, 2); }
testVp9Other3Qual0320x0180()566     public void testVp9Other3Qual0320x0180() throws Exception { qual(VP9, 320, 180, OTHER, 3); }
testVp9Other3Perf0320x0180()567     public void testVp9Other3Perf0320x0180() throws Exception { perf(VP9, 320, 180, OTHER, 3); }
testVp9Count0640x0360()568     public void testVp9Count0640x0360() throws Exception { count(VP9, 640, 360, 2, 4); }
testVp9Goog0Qual0640x0360()569     public void testVp9Goog0Qual0640x0360() throws Exception { qual(VP9, 640, 360, GOOG, 0); }
testVp9Goog0Perf0640x0360()570     public void testVp9Goog0Perf0640x0360() throws Exception { perf(VP9, 640, 360, GOOG, 0); }
testVp9Goog1Qual0640x0360()571     public void testVp9Goog1Qual0640x0360() throws Exception { qual(VP9, 640, 360, GOOG, 1); }
testVp9Goog1Perf0640x0360()572     public void testVp9Goog1Perf0640x0360() throws Exception { perf(VP9, 640, 360, GOOG, 1); }
573 
testVp9Other0Qual0640x0360()574     public void testVp9Other0Qual0640x0360() throws Exception { qual(VP9, 640, 360, OTHER, 0); }
testVp9Other0Perf0640x0360()575     public void testVp9Other0Perf0640x0360() throws Exception { perf(VP9, 640, 360, OTHER, 0); }
testVp9Other1Qual0640x0360()576     public void testVp9Other1Qual0640x0360() throws Exception { qual(VP9, 640, 360, OTHER, 1); }
testVp9Other1Perf0640x0360()577     public void testVp9Other1Perf0640x0360() throws Exception { perf(VP9, 640, 360, OTHER, 1); }
testVp9Other2Qual0640x0360()578     public void testVp9Other2Qual0640x0360() throws Exception { qual(VP9, 640, 360, OTHER, 2); }
testVp9Other2Perf0640x0360()579     public void testVp9Other2Perf0640x0360() throws Exception { perf(VP9, 640, 360, OTHER, 2); }
testVp9Other3Qual0640x0360()580     public void testVp9Other3Qual0640x0360() throws Exception { qual(VP9, 640, 360, OTHER, 3); }
testVp9Other3Perf0640x0360()581     public void testVp9Other3Perf0640x0360() throws Exception { perf(VP9, 640, 360, OTHER, 3); }
testVp9Count1280x0720()582     public void testVp9Count1280x0720() throws Exception { count(VP9, 1280, 720, 2, 4); }
testVp9Goog0Qual1280x0720()583     public void testVp9Goog0Qual1280x0720() throws Exception { qual(VP9, 1280, 720, GOOG, 0); }
testVp9Goog0Perf1280x0720()584     public void testVp9Goog0Perf1280x0720() throws Exception { perf(VP9, 1280, 720, GOOG, 0); }
testVp9Goog1Qual1280x0720()585     public void testVp9Goog1Qual1280x0720() throws Exception { qual(VP9, 1280, 720, GOOG, 1); }
testVp9Goog1Perf1280x0720()586     public void testVp9Goog1Perf1280x0720() throws Exception { perf(VP9, 1280, 720, GOOG, 1); }
587 
testVp9Other0Qual1280x0720()588     public void testVp9Other0Qual1280x0720() throws Exception { qual(VP9, 1280, 720, OTHER, 0); }
testVp9Other0Perf1280x0720()589     public void testVp9Other0Perf1280x0720() throws Exception { perf(VP9, 1280, 720, OTHER, 0); }
testVp9Other1Qual1280x0720()590     public void testVp9Other1Qual1280x0720() throws Exception { qual(VP9, 1280, 720, OTHER, 1); }
testVp9Other1Perf1280x0720()591     public void testVp9Other1Perf1280x0720() throws Exception { perf(VP9, 1280, 720, OTHER, 1); }
testVp9Other2Qual1280x0720()592     public void testVp9Other2Qual1280x0720() throws Exception { qual(VP9, 1280, 720, OTHER, 2); }
testVp9Other2Perf1280x0720()593     public void testVp9Other2Perf1280x0720() throws Exception { perf(VP9, 1280, 720, OTHER, 2); }
testVp9Other3Qual1280x0720()594     public void testVp9Other3Qual1280x0720() throws Exception { qual(VP9, 1280, 720, OTHER, 3); }
testVp9Other3Perf1280x0720()595     public void testVp9Other3Perf1280x0720() throws Exception { perf(VP9, 1280, 720, OTHER, 3); }
testVp9Count1920x1080()596     public void testVp9Count1920x1080() throws Exception { count(VP9, 1920, 1080, 2, 4); }
testVp9Goog0Qual1920x1080()597     public void testVp9Goog0Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, GOOG, 0); }
testVp9Goog0Perf1920x1080()598     public void testVp9Goog0Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, GOOG, 0); }
testVp9Goog1Qual1920x1080()599     public void testVp9Goog1Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, GOOG, 1); }
testVp9Goog1Perf1920x1080()600     public void testVp9Goog1Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, GOOG, 1); }
601 
testVp9Other0Qual1920x1080()602     public void testVp9Other0Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, OTHER, 0); }
testVp9Other0Perf1920x1080()603     public void testVp9Other0Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, OTHER, 0); }
testVp9Other1Qual1920x1080()604     public void testVp9Other1Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, OTHER, 1); }
testVp9Other1Perf1920x1080()605     public void testVp9Other1Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, OTHER, 1); }
testVp9Other2Qual1920x1080()606     public void testVp9Other2Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, OTHER, 2); }
testVp9Other2Perf1920x1080()607     public void testVp9Other2Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, OTHER, 2); }
testVp9Other3Qual1920x1080()608     public void testVp9Other3Qual1920x1080() throws Exception { qual(VP9, 1920, 1080, OTHER, 3); }
testVp9Other3Perf1920x1080()609     public void testVp9Other3Perf1920x1080() throws Exception { perf(VP9, 1920, 1080, OTHER, 3); }
testVp9Count3840x2160()610     public void testVp9Count3840x2160() throws Exception { count(VP9, 3840, 2160, 2, 4); }
testVp9Goog0Qual3840x2160()611     public void testVp9Goog0Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, GOOG, 0); }
testVp9Goog0Perf3840x2160()612     public void testVp9Goog0Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, GOOG, 0); }
testVp9Goog1Qual3840x2160()613     public void testVp9Goog1Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, GOOG, 1); }
testVp9Goog1Perf3840x2160()614     public void testVp9Goog1Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, GOOG, 1); }
615 
testVp9Other0Qual3840x2160()616     public void testVp9Other0Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, OTHER, 0); }
testVp9Other0Perf3840x2160()617     public void testVp9Other0Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, OTHER, 0); }
testVp9Other1Qual3840x2160()618     public void testVp9Other1Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, OTHER, 1); }
testVp9Other1Perf3840x2160()619     public void testVp9Other1Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, OTHER, 1); }
testVp9Other2Qual3840x2160()620     public void testVp9Other2Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, OTHER, 2); }
testVp9Other2Perf3840x2160()621     public void testVp9Other2Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, OTHER, 2); }
testVp9Other3Qual3840x2160()622     public void testVp9Other3Qual3840x2160() throws Exception { qual(VP9, 3840, 2160, OTHER, 3); }
testVp9Other3Perf3840x2160()623     public void testVp9Other3Perf3840x2160() throws Exception { perf(VP9, 3840, 2160, OTHER, 3); }
624 
isSrcSemiPlanar()625     private boolean isSrcSemiPlanar() {
626         return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
627     }
628 
isSrcFlexYUV()629     private boolean isSrcFlexYUV() {
630         return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
631     }
632 
isDstSemiPlanar()633     private boolean isDstSemiPlanar() {
634         return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
635     }
636 
isDstFlexYUV()637     private boolean isDstFlexYUV() {
638         return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
639     }
640 
getColorFormat(CodecInfo info)641     private static int getColorFormat(CodecInfo info) {
642         if (info.mSupportSemiPlanar) {
643             return CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
644         } else if (info.mSupportPlanar) {
645             return CodecCapabilities.COLOR_FormatYUV420Planar;
646         } else {
647             // FlexYUV must be supported
648             return CodecCapabilities.COLOR_FormatYUV420Flexible;
649         }
650     }
651 
652     private static class RunResult {
653         public final int mNumFrames;
654         public final double mDurationMs;
655         public final double mRmsError;
656 
RunResult()657         RunResult() {
658             mNumFrames = 0;
659             mDurationMs = Double.NaN;
660             mRmsError = Double.NaN;
661         }
662 
RunResult(int numFrames, double durationMs)663         RunResult(int numFrames, double durationMs) {
664             mNumFrames = numFrames;
665             mDurationMs = durationMs;
666             mRmsError = Double.NaN;
667         }
668 
RunResult(int numFrames, double durationMs, double rmsError)669         RunResult(int numFrames, double durationMs, double rmsError) {
670             mNumFrames = numFrames;
671             mDurationMs = durationMs;
672             mRmsError = rmsError;
673         }
674     }
675 
doTest(String mimeType, int w, int h, boolean isPerf, boolean isGoog, int ix)676     private void doTest(String mimeType, int w, int h, boolean isPerf, boolean isGoog, int ix)
677             throws Exception {
678         if (TestArgs.shouldSkipMediaType(mimeType)) {
679             return;
680         }
681         MediaFormat format = MediaFormat.createVideoFormat(mimeType, w, h);
682         String[] encoderNames = MediaUtils.getEncoderNames(isGoog, format);
683         String kind = isGoog ? "Google" : "non-Google";
684         if (encoderNames.length == 0) {
685             MediaUtils.skipTest("No " + kind + " encoders for " + format);
686             return;
687         } else if (encoderNames.length <= ix) {
688             Log.i(TAG, "No more " + kind + " encoders for " + format);
689             return;
690         }
691 
692         if (isPerf) {
693             mTestConfig.initPerfTest();
694         }
695 
696         String encoderName = encoderNames[ix];
697         if (TestArgs.shouldSkipCodec(encoderName)) {
698             return;
699         }
700         CodecInfo infoEnc = CodecInfo.getSupportedFormatInfo(encoderName, mimeType, w, h, MAX_FPS);
701         assertNotNull(infoEnc);
702 
703         // Skip decoding pass for performance tests as bitstream complexity is not representative
704         String[] decoderNames = null;  // no decoding pass required by default
705         int codingPasses = 1;  // used for time limit. 1 for encoding pass
706         int numRuns = mTestConfig.mNumberOfRepeat;  // used for result array sizing
707         if (!isPerf) {
708             // consider all decoders for quality tests
709             decoderNames = MediaUtils.getDecoderNames(format);
710             if (decoderNames.length == 0) {
711                 MediaUtils.skipTest("No decoders for " + format);
712                 return;
713             }
714             numRuns *= decoderNames.length; // combine each decoder with the encoder
715             codingPasses += decoderNames.length;
716         }
717 
718         // be a bit conservative
719         mTestConfig.mMaxTimeMs = Math.min(
720                 mTestConfig.mMaxTimeMs, MAX_TEST_TIMEOUT_MS / 5 * 4 / codingPasses
721                         / mTestConfig.mNumberOfRepeat);
722         // reduce test-run on non-real devices
723         if (MediaUtils.onFrankenDevice()) {
724             mTestConfig.mMaxTimeMs /= 10;
725         }
726         Log.i(TAG, "current ABI is " + (isPreferredAbi() ? "" : "not ") + "a preferred one");
727 
728         mVideoWidth = w;
729         mVideoHeight = h;
730         mSrcColorFormat = getColorFormat(infoEnc);
731         Log.i(TAG, "Testing video resolution " + w + "x" + h + ": enc format " + mSrcColorFormat);
732 
733         initYUVPlane(w + YUV_PLANE_ADDITIONAL_LENGTH, h + YUV_PLANE_ADDITIONAL_LENGTH);
734 
735         // Adjust total number of frames to prevent OOM.
736         Runtime rt = Runtime.getRuntime();
737         long usedMemory = rt.totalMemory() - rt.freeMemory();
738         mTestConfig.mTotalFrames = Math.min(mTestConfig.mTotalFrames,
739                 (int) (rt.maxMemory() - usedMemory) / 4 * 3 /
740                 (infoEnc.mBitRate / 8 / infoEnc.mFps + 1));
741         Log.i(TAG, "Total testing frames " + mTestConfig.mTotalFrames);
742 
743         mEncoderFrameTimeUsDiff = new double[numRuns][mTestConfig.mTotalFrames - 1];
744         mEncoderFpsResults = new double[numRuns];
745 
746         if (decoderNames != null) {
747             mDecoderFrameTimeUsDiff = new double[numRuns][mTestConfig.mTotalFrames - 1];
748             mDecoderFpsResults = new double[numRuns];
749             mTotalFpsResults = new double[numRuns];
750             mDecoderRmsErrorResults = new double[numRuns];
751         }
752 
753         boolean success = true;
754         int runIx = 0;
755         for (int i = 0; i < mTestConfig.mNumberOfRepeat && success; i++) {
756             mCurrentTestRound = runIx;
757             format = new MediaFormat();
758             format.setString(MediaFormat.KEY_MIME, mimeType);
759             format.setInteger(MediaFormat.KEY_BIT_RATE, infoEnc.mBitRate);
760             format.setInteger(MediaFormat.KEY_BITRATE_MODE,
761                     MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);
762             format.setInteger(MediaFormat.KEY_WIDTH, w);
763             format.setInteger(MediaFormat.KEY_HEIGHT, h);
764             format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mSrcColorFormat);
765             format.setInteger(MediaFormat.KEY_FRAME_RATE, infoEnc.mFps);
766             mFrameRate = infoEnc.mFps;
767             format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, KEY_I_FRAME_INTERVAL);
768 
769             RunResult encodingResult =
770                 runEncoder(encoderName, format, mTestConfig.mTotalFrames, i);
771             double encodingTime = encodingResult.mDurationMs;
772             int framesEncoded = encodingResult.mNumFrames;
773 
774             if (decoderNames != null && decoderNames.length > 0) {
775                 for (String decoderName : decoderNames) {
776                     if (TestArgs.shouldSkipCodec(decoderName)) {
777                         continue;
778                     }
779                     CodecInfo infoDec =
780                         CodecInfo.getSupportedFormatInfo(decoderName, mimeType, w, h, MAX_FPS);
781                     assertNotNull(infoDec);
782                     mDstColorFormat = getColorFormat(infoDec);
783 
784                     // re-initialize format for decoder
785                     format = new MediaFormat();
786                     format.setString(MediaFormat.KEY_MIME, mimeType);
787                     format.setInteger(MediaFormat.KEY_WIDTH, w);
788                     format.setInteger(MediaFormat.KEY_HEIGHT, h);
789                     format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mDstColorFormat);
790                     RunResult decoderResult = runDecoder(decoderName, format, i);
791                     if (decoderResult == null) {
792                         success = false;
793                     } else {
794                         double decodingTime = decoderResult.mDurationMs;
795                         mDecoderRmsErrorResults[runIx] = decoderResult.mRmsError;
796                         mEncoderFpsResults[runIx] = framesEncoded / encodingTime;
797                         int framesDecoded = decoderResult.mNumFrames;
798                         mDecoderFpsResults[runIx] = framesDecoded / decodingTime;
799                         if (framesDecoded == framesEncoded) {
800                             mTotalFpsResults[runIx] =
801                                 framesEncoded / (encodingTime + decodingTime);
802                         }
803                     }
804                     ++runIx;
805                 }
806             } else {
807                 mEncoderFpsResults[runIx] = mTestConfig.mTotalFrames / encodingTime;
808                 ++runIx;
809             }
810 
811             // clear things for re-start
812             mEncodedOutputBuffer.clear();
813             // it will be good to clean everything to make every run the same.
814             System.gc();
815         }
816 
817         // log results before verification
818         double[] measuredFps = new double[numRuns];
819         if (isPerf) {
820             for (int i = 0; i < numRuns; i++) {
821                 measuredFps[i] = logPerformanceResults(encoderName, i);
822             }
823         }
824         if (mTestConfig.mTestPixels && decoderNames != null) {
825             logQualityResults(mimeType, encoderName, decoderNames);
826             for (int i = 0; i < numRuns; i++) {
827                 // make sure that rms error is not too big for all runs
828                 if (mDecoderRmsErrorResults[i] >= mRmsErrorMargin) {
829                     fail("rms error is bigger than the limit "
830                             + Arrays.toString(mDecoderRmsErrorResults) + " vs " + mRmsErrorMargin);
831                 }
832             }
833         }
834 
835         if (isPerf) {
836             // allow improvements in mainline-updated google-supplied software codecs.
837             boolean fasterIsOk =  mUpdatedSwCodec & encoderName.startsWith("c2.android.");
838             String error = MediaPerfUtils.verifyAchievableFrameRates(
839                     encoderName, mimeType, w, h, fasterIsOk, measuredFps);
840             // Performance numbers only make sense on real devices, so skip on non-real devices
841             //
842             // Also ignore verification on non-preferred ABIs due to the possibility of
843             // this being emulated. On some CPU-s 32-bit mode is emulated using big cores
844             // that results in the SW codecs also running much faster (perhaps they are
845             // scheduled for the big cores as well)
846             // TODO: still verify lower bound.
847             if ((MediaUtils.onFrankenDevice() || (infoEnc.mIsSoftware && !isPreferredAbi()))
848                     && error != null) {
849                 // ensure there is data, but don't insist that it is correct
850                 assertFalse(error, error.startsWith("Failed to get "));
851             } else {
852                 assertNull(error, error);
853             }
854         }
855         assertTrue(success);
856     }
857 
logQualityResults(String mimeType, String encoderName, String[] decoderNames)858     private void logQualityResults(String mimeType, String encoderName, String[] decoderNames) {
859         String streamName = "video_encoder_decoder_quality";
860         DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, streamName);
861         log.addValue("encoder_name", encoderName, ResultType.NEUTRAL, ResultUnit.NONE);
862         log.addValues("decoder_names", Arrays.asList(decoderNames), ResultType.NEUTRAL, ResultUnit.NONE);
863         log.addValue("mime_type", mimeType, ResultType.NEUTRAL, ResultUnit.NONE);
864         log.addValue("width", mVideoWidth, ResultType.NEUTRAL, ResultUnit.NONE);
865         log.addValue("height", mVideoHeight, ResultType.NEUTRAL, ResultUnit.NONE);
866         log.addValues("encoder_fps", mEncoderFpsResults, ResultType.HIGHER_BETTER,
867                 ResultUnit.FPS);
868         log.addValues("rms_error", mDecoderRmsErrorResults, ResultType.LOWER_BETTER,
869                 ResultUnit.NONE);
870         log.addValues("decoder_fps", mDecoderFpsResults, ResultType.HIGHER_BETTER,
871                 ResultUnit.FPS);
872         log.addValues("encoder_decoder_fps", mTotalFpsResults, ResultType.HIGHER_BETTER,
873                 ResultUnit.FPS);
874         log.addValue("encoder_average_fps", Stat.getAverage(mEncoderFpsResults),
875                 ResultType.HIGHER_BETTER, ResultUnit.FPS);
876         log.addValue("decoder_average_fps", Stat.getAverage(mDecoderFpsResults),
877                 ResultType.HIGHER_BETTER, ResultUnit.FPS);
878         log.setSummary("encoder_decoder_average_fps", Stat.getAverage(mTotalFpsResults),
879                 ResultType.HIGHER_BETTER, ResultUnit.FPS);
880         log.submit(getInstrumentation());
881     }
882 
logPerformanceResults(String encoderName, int round)883     private double logPerformanceResults(String encoderName, int round) {
884         String streamName = "video_encoder_performance";
885         DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, streamName);
886         String message = MediaPerfUtils.addPerformanceHeadersToLog(
887                 log, "encoder stats:", round, encoderName,
888                 mEncConfigFormat, mEncInputFormat, mEncOutputFormat);
889         double[] frameTimeUsDiff = mEncoderFrameTimeUsDiff[round];
890         double fps = MediaPerfUtils.addPerformanceStatsToLog(
891                 log, new MediaUtils.Stats(frameTimeUsDiff), message);
892 
893         if (mTestConfig.mReportFrameTime) {
894             double[] msDiff = new double[frameTimeUsDiff.length];
895             double nowUs = 0, lastMs = 0;
896             for (int i = 0; i < frameTimeUsDiff.length; ++i) {
897                 nowUs += frameTimeUsDiff[i];
898                 double nowMs = Math.round(nowUs) / 1000.;
899                 msDiff[i] = Math.round((nowMs - lastMs) * 1000) / 1000.;
900                 lastMs = nowMs;
901             }
902             log.addValues("encoder_raw_diff", msDiff, ResultType.NEUTRAL, ResultUnit.MS);
903         }
904 
905         log.submit(getInstrumentation());
906         return fps;
907     }
908 
909     /**
910      * run encoder benchmarking
911      * @param encoderName encoder name
912      * @param format format of media to encode
913      * @param totalFrames total number of frames to encode
914      * @return time taken in ms to encode the frames. This does not include initialization time.
915      */
runEncoder( String encoderName, MediaFormat format, int totalFrames, int runId)916     private RunResult runEncoder(
917             String encoderName, MediaFormat format, int totalFrames, int runId) {
918         MediaCodec codec = null;
919         try {
920             codec = MediaCodec.createByCodecName(encoderName);
921             mEncConfigFormat = format;
922             codec.configure(
923                     format,
924                     null /* surface */,
925                     null /* crypto */,
926                     MediaCodec.CONFIGURE_FLAG_ENCODE);
927         } catch (IllegalStateException e) {
928             Log.e(TAG, "codec '" + encoderName + "' failed configuration.");
929             codec.release();
930             assertTrue("codec '" + encoderName + "' failed configuration.", false);
931         } catch (IOException | NullPointerException e) {
932             Log.i(TAG, "could not find codec for " + format);
933             return new RunResult();
934         }
935         codec.start();
936         mEncInputFormat = codec.getInputFormat();
937         ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
938         MediaFormat inputFormat = codec.getInputFormat();
939         mVideoStride = inputFormat.containsKey(MediaFormat.KEY_STRIDE)
940                 ? inputFormat.getInteger(MediaFormat.KEY_STRIDE)
941                 : inputFormat.getInteger(MediaFormat.KEY_WIDTH);
942         mVideoVStride = inputFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)
943                 ? inputFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT)
944                 : inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
945 
946         int numBytesSubmitted = 0;
947         int numBytesDequeued = 0;
948         int inFramesCount = 0;
949         int outFramesCount = 0;
950         long lastOutputTimeUs = 0;
951         long start = System.currentTimeMillis();
952         while (true) {
953             int index;
954 
955             if (inFramesCount < totalFrames) {
956                 index = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
957                 if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
958                     int size;
959                     long elapsedMs = System.currentTimeMillis() - start;
960                     boolean eos = (inFramesCount == totalFrames - 1
961                             || elapsedMs > mTestConfig.mMaxTimeMs
962                             || (elapsedMs > mTestConfig.mMinTimeMs
963                                     && inFramesCount > mTestConfig.mMinNumFrames));
964 
965                     // when encoder only supports flexYUV, use Image only; otherwise,
966                     // use ByteBuffer & Image each on half of the frames to test both
967                     if (isSrcFlexYUV() || inFramesCount % 2 == 0) {
968                         Image image = codec.getInputImage(index);
969                         // image should always be available
970                         assertTrue(image != null);
971                         size = queueInputImageEncoder(
972                                 codec, image, index, inFramesCount,
973                                 eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0, runId);
974                     } else {
975                         ByteBuffer buffer = codec.getInputBuffer(index);
976                         size = queueInputBufferEncoder(
977                                 codec, buffer, index, inFramesCount,
978                                 eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0, runId);
979                     }
980                     inFramesCount++;
981                     numBytesSubmitted += size;
982                     if (VERBOSE) {
983                         Log.d(TAG, "queued " + size + " bytes of input data, frame " +
984                                 (inFramesCount - 1));
985                     }
986                 }
987             }
988             MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
989             index = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
990             if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
991             } else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
992                 mEncOutputFormat = codec.getOutputFormat();
993             } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
994                 codecOutputBuffers = codec.getOutputBuffers();
995             } else if (index >= 0) {
996                 long nowUs = (System.nanoTime() + 500) / 1000;
997                 dequeueOutputBufferEncoder(codec, codecOutputBuffers, index, info);
998                 if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
999                     int pos = outFramesCount - 1;
1000                     if (pos >= 0 && pos < mEncoderFrameTimeUsDiff[mCurrentTestRound].length) {
1001                         mEncoderFrameTimeUsDiff[mCurrentTestRound][pos] = nowUs - lastOutputTimeUs;
1002                     }
1003                     lastOutputTimeUs = nowUs;
1004 
1005                     numBytesDequeued += info.size;
1006                     ++outFramesCount;
1007                 }
1008                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
1009                     if (VERBOSE) {
1010                         Log.d(TAG, "dequeued output EOS.");
1011                     }
1012                     break;
1013                 }
1014                 if (VERBOSE) {
1015                     Log.d(TAG, "dequeued " + info.size + " bytes of output data.");
1016                 }
1017             }
1018         }
1019         long finish = System.currentTimeMillis();
1020         int validDataNum = Math.min(mEncodedOutputBuffer.size() - 1,
1021                 mEncoderFrameTimeUsDiff[mCurrentTestRound].length);
1022         mEncoderFrameTimeUsDiff[mCurrentTestRound] =
1023                 Arrays.copyOf(mEncoderFrameTimeUsDiff[mCurrentTestRound], validDataNum);
1024         if (VERBOSE) {
1025             Log.d(TAG, "queued a total of " + numBytesSubmitted + "bytes, "
1026                     + "dequeued " + numBytesDequeued + " bytes.");
1027         }
1028         codec.stop();
1029         codec.release();
1030         codec = null;
1031 
1032         mEncOutputFormat.setInteger(MediaFormat.KEY_BIT_RATE,
1033                 format.getInteger(MediaFormat.KEY_BIT_RATE));
1034         mEncOutputFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
1035                 format.getInteger(MediaFormat.KEY_FRAME_RATE));
1036         if (outFramesCount > 0) {
1037             mEncOutputFormat.setInteger(
1038                     "actual-bitrate",
1039                     (int)(numBytesDequeued * 8. * format.getInteger(MediaFormat.KEY_FRAME_RATE)
1040                             / outFramesCount));
1041         }
1042         return new RunResult(outFramesCount, (finish - start) / 1000.);
1043     }
1044 
1045     /**
1046      * Fills input buffer for encoder from YUV buffers.
1047      * @return size of enqueued data.
1048      */
queueInputBufferEncoder( MediaCodec codec, ByteBuffer buffer, int index, int frameCount, int flags, int runId)1049     private int queueInputBufferEncoder(
1050             MediaCodec codec, ByteBuffer buffer, int index, int frameCount, int flags, int runId) {
1051         buffer.clear();
1052 
1053         Point origin = getOrigin(frameCount, runId);
1054         // Y color first
1055         int srcOffsetY = origin.x + origin.y * mBufferWidth;
1056         final byte[] yBuffer = mYBuffer.array();
1057         for (int i = 0; i < mVideoHeight; i++) {
1058             buffer.position(i * mVideoStride);
1059             buffer.put(yBuffer, srcOffsetY, mVideoWidth);
1060             srcOffsetY += mBufferWidth;
1061         }
1062         if (isSrcSemiPlanar()) {
1063             int srcOffsetU = origin.y / 2 * mBufferWidth + origin.x / 2 * 2;
1064             final byte[] uvBuffer = mUVBuffer.array();
1065             for (int i = 0; i < mVideoHeight / 2; i++) {
1066                 buffer.position(mVideoVStride * mVideoStride + i * mVideoStride);
1067                 buffer.put(uvBuffer, srcOffsetU, mVideoWidth);
1068                 srcOffsetU += mBufferWidth;
1069             }
1070         } else {
1071             int srcOffsetU = origin.y / 2 * mBufferWidth / 2 + origin.x / 2;
1072             int srcOffsetV = srcOffsetU + mBufferWidth / 2 * mBufferHeight / 2;
1073             final byte[] uvBuffer = mUVBuffer.array();
1074             for (int i = 0; i < mVideoHeight / 2; i++) { //U only
1075                 buffer.position(mVideoVStride * mVideoStride + i * mVideoStride / 2);
1076                 buffer.put(uvBuffer, srcOffsetU, mVideoWidth / 2);
1077                 srcOffsetU += mBufferWidth / 2;
1078             }
1079             for (int i = 0; i < mVideoHeight / 2; i++) { //V only
1080                 buffer.position(mVideoVStride * mVideoStride * 5 / 4 + i * mVideoStride / 2);
1081                 buffer.put(uvBuffer, srcOffsetV, mVideoWidth / 2);
1082                 srcOffsetV += mBufferWidth / 2;
1083             }
1084         }
1085         // submit till end of the data
1086         int size = buffer.position();
1087         long ptsUsec = computePresentationTime(frameCount);
1088 
1089         codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
1090         if (VERBOSE && (frameCount == 0)) {
1091             printByteArray("Y ", mYBuffer.array(), 0, 20);
1092             printByteArray("UV ", mUVBuffer.array(), 0, 20);
1093             printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
1094         }
1095         return size;
1096     }
1097 
1098     /**
1099      * Fills input image for encoder from YUV buffers.
1100      * @return size of enqueued data.
1101      */
queueInputImageEncoder( MediaCodec codec, Image image, int index, int frameCount, int flags, int runId)1102     private int queueInputImageEncoder(
1103             MediaCodec codec, Image image, int index, int frameCount, int flags, int runId) {
1104         assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
1105 
1106 
1107         Point origin = getOrigin(frameCount, runId);
1108 
1109         // Y color first
1110         CodecImage srcImage = new YUVImage(
1111                 origin,
1112                 mVideoWidth, mVideoHeight,
1113                 mBufferWidth, mBufferHeight,
1114                 isSrcSemiPlanar(),
1115                 mYDirectBuffer, mUVDirectBuffer);
1116 
1117         CodecUtils.copyFlexYUVImage(image, srcImage);
1118 
1119         int size = mVideoHeight * mVideoWidth * 3 / 2;
1120         long ptsUsec = computePresentationTime(frameCount);
1121 
1122         codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
1123         if (VERBOSE && (frameCount == 0)) {
1124             printByteArray("Y ", mYBuffer.array(), 0, 20);
1125             printByteArray("UV ", mUVBuffer.array(), 0, 20);
1126             printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
1127         }
1128         return size;
1129     }
1130 
1131     /**
1132      * Dequeue encoded data from output buffer and store for later usage.
1133      */
dequeueOutputBufferEncoder( MediaCodec codec, ByteBuffer[] outputBuffers, int index, MediaCodec.BufferInfo info)1134     private void dequeueOutputBufferEncoder(
1135             MediaCodec codec, ByteBuffer[] outputBuffers,
1136             int index, MediaCodec.BufferInfo info) {
1137         ByteBuffer output = outputBuffers[index];
1138         int l = info.size;
1139         ByteBuffer copied = ByteBuffer.allocate(l);
1140         output.get(copied.array(), 0, l);
1141         BufferInfo savedInfo = new BufferInfo();
1142         savedInfo.set(0, l, info.presentationTimeUs, info.flags);
1143         mEncodedOutputBuffer.addLast(Pair.create(copied, savedInfo));
1144         codec.releaseOutputBuffer(index, false /* render */);
1145     }
1146 
1147     /**
1148      * run decoder benchmarking with encoded stream stored from encoding phase
1149      * @param decoderName decoder name
1150      * @param format format of media to decode
1151      * @return returns length-2 array with 0: time for decoding, 1 : rms error of pixels
1152      */
runDecoder(String decoderName, MediaFormat format, int runId)1153     private RunResult runDecoder(String decoderName, MediaFormat format, int runId) {
1154         MediaCodec codec = null;
1155         try {
1156             codec = MediaCodec.createByCodecName(decoderName);
1157         } catch (IOException | NullPointerException e) {
1158             Log.i(TAG, "could not find decoder for " + format);
1159             return null;
1160         }
1161         codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
1162         codec.start();
1163         ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
1164 
1165         double totalErrorSquared = 0;
1166 
1167         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
1168         boolean sawOutputEOS = false;
1169         int inputLeft = mEncodedOutputBuffer.size();
1170         int inputBufferCount = 0;
1171         int outFrameCount = 0;
1172         YUVValue expected = new YUVValue();
1173         YUVValue decoded = new YUVValue();
1174         long lastOutputTimeUs = 0;
1175         long start = System.currentTimeMillis();
1176         while (!sawOutputEOS) {
1177             if (inputLeft > 0) {
1178                 int inputBufIndex = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US);
1179 
1180                 if (inputBufIndex >= 0) {
1181                     ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
1182                     dstBuf.clear();
1183                     ByteBuffer src = mEncodedOutputBuffer.get(inputBufferCount).first;
1184                     BufferInfo srcInfo = mEncodedOutputBuffer.get(inputBufferCount).second;
1185                     int writeSize = src.capacity();
1186                     dstBuf.put(src.array(), 0, writeSize);
1187 
1188                     int flags = srcInfo.flags;
1189                     if ((System.currentTimeMillis() - start) > mTestConfig.mMaxTimeMs) {
1190                         flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
1191                     }
1192 
1193                     codec.queueInputBuffer(
1194                             inputBufIndex,
1195                             0 /* offset */,
1196                             writeSize,
1197                             srcInfo.presentationTimeUs,
1198                             flags);
1199                     inputLeft --;
1200                     inputBufferCount ++;
1201                 }
1202             }
1203 
1204             int res = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US);
1205             if (res >= 0) {
1206                 int outputBufIndex = res;
1207 
1208                 // only do YUV compare on EOS frame if the buffer size is none-zero
1209                 if (info.size > 0) {
1210                     long nowUs = (System.nanoTime() + 500) / 1000;
1211                     int pos = outFrameCount - 1;
1212                     if (pos >= 0 && pos < mDecoderFrameTimeUsDiff[mCurrentTestRound].length) {
1213                         mDecoderFrameTimeUsDiff[mCurrentTestRound][pos] = nowUs - lastOutputTimeUs;
1214                     }
1215                     lastOutputTimeUs = nowUs;
1216 
1217                     if (mTestConfig.mTestPixels) {
1218                         Point origin = getOrigin(outFrameCount, runId);
1219                         int i;
1220 
1221                         // if decoder supports planar or semiplanar, check output with
1222                         // ByteBuffer & Image each on half of the points
1223                         int pixelCheckPerFrame = PIXEL_CHECK_PER_FRAME;
1224                         if (!isDstFlexYUV()) {
1225                             pixelCheckPerFrame /= 2;
1226                             ByteBuffer buf = codec.getOutputBuffer(outputBufIndex);
1227                             if (VERBOSE && (outFrameCount == 0)) {
1228                                 printByteBuffer("Y ", buf, 0, 20);
1229                                 printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight, 20);
1230                                 printByteBuffer("UV ", buf,
1231                                         mVideoWidth * mVideoHeight + mVideoWidth * 60, 20);
1232                             }
1233                             for (i = 0; i < pixelCheckPerFrame; i++) {
1234                                 int w = mRandom.nextInt(mVideoWidth);
1235                                 int h = mRandom.nextInt(mVideoHeight);
1236                                 getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
1237                                 getPixelValuesFromOutputBuffer(buf, w, h, decoded);
1238                                 if (VERBOSE) {
1239                                     Log.i(TAG, outFrameCount + "-" + i + "- th round: ByteBuffer:"
1240                                             + " expected "
1241                                             + expected.mY + "," + expected.mU + "," + expected.mV
1242                                             + " decoded "
1243                                             + decoded.mY + "," + decoded.mU + "," + decoded.mV);
1244                                 }
1245                                 totalErrorSquared += expected.calcErrorSquared(decoded);
1246                             }
1247                         }
1248 
1249                         Image image = codec.getOutputImage(outputBufIndex);
1250                         assertTrue(image != null);
1251                         for (i = 0; i < pixelCheckPerFrame; i++) {
1252                             int w = mRandom.nextInt(mVideoWidth);
1253                             int h = mRandom.nextInt(mVideoHeight);
1254                             getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
1255                             getPixelValuesFromImage(image, w, h, decoded);
1256                             if (VERBOSE) {
1257                                 Log.i(TAG, outFrameCount + "-" + i + "- th round: FlexYUV:"
1258                                         + " expcted "
1259                                         + expected.mY + "," + expected.mU + "," + expected.mV
1260                                         + " decoded "
1261                                         + decoded.mY + "," + decoded.mU + "," + decoded.mV);
1262                             }
1263                             totalErrorSquared += expected.calcErrorSquared(decoded);
1264                         }
1265                     }
1266                     outFrameCount++;
1267                 }
1268                 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
1269                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
1270                     Log.d(TAG, "saw output EOS.");
1271                     sawOutputEOS = true;
1272                 }
1273             } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
1274                 mDecOutputFormat = codec.getOutputFormat();
1275                 Log.d(TAG, "output format has changed to " + mDecOutputFormat);
1276                 int colorFormat = mDecOutputFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
1277                 if (colorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar
1278                         || colorFormat == CodecCapabilities.COLOR_FormatYUV420Planar) {
1279                     mDstColorFormat = colorFormat;
1280                 } else {
1281                     mDstColorFormat = CodecCapabilities.COLOR_FormatYUV420Flexible;
1282                     Log.w(TAG, "output format changed to unsupported one " +
1283                             Integer.toHexString(colorFormat) + ", using FlexYUV");
1284                 }
1285                 mVideoStride = mDecOutputFormat.containsKey(MediaFormat.KEY_STRIDE)
1286                         ? mDecOutputFormat.getInteger(MediaFormat.KEY_STRIDE)
1287                         : mDecOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
1288                 mVideoVStride = mDecOutputFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)
1289                         ? mDecOutputFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT)
1290                         : mDecOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
1291             }
1292         }
1293         long finish = System.currentTimeMillis();
1294         int validDataNum = Math.min(outFrameCount - 1,
1295                 mDecoderFrameTimeUsDiff[mCurrentTestRound].length);
1296         mDecoderFrameTimeUsDiff[mCurrentTestRound] =
1297                 Arrays.copyOf(mDecoderFrameTimeUsDiff[mCurrentTestRound], validDataNum);
1298         codec.stop();
1299         codec.release();
1300         codec = null;
1301 
1302         // divide by 3 as sum is done for Y, U, V.
1303         double errorRms = Math.sqrt(totalErrorSquared / PIXEL_CHECK_PER_FRAME / outFrameCount / 3);
1304         return new RunResult(outFrameCount, (finish - start) / 1000., errorRms);
1305     }
1306 
1307     /**
1308      *  returns origin in the absolute frame for given frame count.
1309      *  The video scene is moving by moving origin per each frame.
1310      */
getOrigin(int frameCount, int runId)1311     private Point getOrigin(int frameCount, int runId) {
1312         // Translation is basically:
1313         //    x = A * sin(B * t) + C * t
1314         //    y = D * cos(E * t) + F * t
1315         //    'bouncing' in a [0, length] regions (constrained to [0, length] by mirroring at 0
1316         //    and length.)
1317         double x = (1 - Math.sin(frameCount / (7. + (runId % 2)))) * 0.1 + frameCount * 0.005;
1318         double y = (1 - Math.cos(frameCount / (10. + (runId & ~1))))
1319                 + frameCount * (0.01 + runId / 1000.);
1320 
1321         // At every 32nd or 13th frame out of 32, an additional varying offset is added to
1322         // produce a jerk.
1323         if (frameCount % 32 == 0) {
1324             x += ((frameCount % 64) / 32) + 0.3 + y;
1325         }
1326         if (frameCount % 32 == 13) {
1327             y += ((frameCount % 64) / 32) + 0.6 + x;
1328         }
1329 
1330         // constrain to region
1331         int xi = (int)((x % 2) * YUV_PLANE_ADDITIONAL_LENGTH);
1332         int yi = (int)((y % 2) * YUV_PLANE_ADDITIONAL_LENGTH);
1333         if (xi > YUV_PLANE_ADDITIONAL_LENGTH) {
1334             xi = 2 * YUV_PLANE_ADDITIONAL_LENGTH - xi;
1335         }
1336         if (yi > YUV_PLANE_ADDITIONAL_LENGTH) {
1337             yi = 2 * YUV_PLANE_ADDITIONAL_LENGTH - yi;
1338         }
1339         return new Point(xi, yi);
1340     }
1341 
1342     /**
1343      * initialize reference YUV plane
1344      * @param w This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
1345      *          to allow movements
1346      * @param h This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
1347      *          to allow movements
1348      * @param semiPlanarEnc
1349      * @param semiPlanarDec
1350      */
initYUVPlane(int w, int h)1351     private void initYUVPlane(int w, int h) {
1352         int bufferSizeY = w * h;
1353         mYBuffer = ByteBuffer.allocate(bufferSizeY);
1354         mUVBuffer = ByteBuffer.allocate(bufferSizeY / 2);
1355         mYDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY);
1356         mUVDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY / 2);
1357         mBufferWidth = w;
1358         mBufferHeight = h;
1359         final byte[] yArray = mYBuffer.array();
1360         final byte[] uvArray = mUVBuffer.array();
1361         for (int i = 0; i < h; i++) {
1362             for (int j = 0; j < w; j++) {
1363                 yArray[i * w + j]  = clampY((i + j) & 0xff);
1364             }
1365         }
1366         if (isSrcSemiPlanar()) {
1367             for (int i = 0; i < h/2; i++) {
1368                 for (int j = 0; j < w/2; j++) {
1369                     uvArray[i * w + 2 * j]  = (byte) (i & 0xff);
1370                     uvArray[i * w + 2 * j + 1]  = (byte) (j & 0xff);
1371                 }
1372             }
1373         } else { // planar, U first, then V
1374             int vOffset = bufferSizeY / 4;
1375             for (int i = 0; i < h/2; i++) {
1376                 for (int j = 0; j < w/2; j++) {
1377                     uvArray[i * w/2 + j]  = (byte) (i & 0xff);
1378                     uvArray[i * w/2 + vOffset + j]  = (byte) (j & 0xff);
1379                 }
1380             }
1381         }
1382         mYDirectBuffer.put(yArray);
1383         mUVDirectBuffer.put(uvArray);
1384         mYDirectBuffer.rewind();
1385         mUVDirectBuffer.rewind();
1386     }
1387 
1388     /**
1389      * class to store pixel values in YUV
1390      *
1391      */
1392     public class YUVValue {
1393         public byte mY;
1394         public byte mU;
1395         public byte mV;
YUVValue()1396         public YUVValue() {
1397         }
1398 
equalTo(YUVValue other)1399         public boolean equalTo(YUVValue other) {
1400             return (mY == other.mY) && (mU == other.mU) && (mV == other.mV);
1401         }
1402 
calcErrorSquared(YUVValue other)1403         public double calcErrorSquared(YUVValue other) {
1404             // Java's byte is signed but here we want to calculate difference in unsigned bytes.
1405             double yDelta = (mY & 0xFF) - (other.mY & 0xFF);
1406             double uDelta = (mU & 0xFF) - (other.mU & 0xFF);
1407             double vDelta = (mV & 0xFF) - (other.mV & 0xFF);
1408             return yDelta * yDelta + uDelta * uDelta + vDelta * vDelta;
1409         }
1410     }
1411 
1412     /**
1413      * Read YUV values from given position (x,y) for given origin (originX, originY)
1414      * The whole data is already available from YBuffer and UVBuffer.
1415      * @param result pass the result via this. This is for avoiding creating / destroying too many
1416      *               instances
1417      */
getPixelValuesFromYUVBuffers(int originX, int originY, int x, int y, YUVValue result)1418     private void getPixelValuesFromYUVBuffers(int originX, int originY, int x, int y,
1419             YUVValue result) {
1420         result.mY = mYBuffer.get((originY + y) * mBufferWidth + (originX + x));
1421         if (isSrcSemiPlanar()) {
1422             int index = (originY + y) / 2 * mBufferWidth + (originX + x) / 2 * 2;
1423             //Log.d(TAG, "YUV " + originX + "," + originY + "," + x + "," + y + "," + index);
1424             result.mU = mUVBuffer.get(index);
1425             result.mV = mUVBuffer.get(index + 1);
1426         } else {
1427             int vOffset = mBufferWidth * mBufferHeight / 4;
1428             int index = (originY + y) / 2 * mBufferWidth / 2 + (originX + x) / 2;
1429             result.mU = mUVBuffer.get(index);
1430             result.mV = mUVBuffer.get(vOffset + index);
1431         }
1432     }
1433 
1434     /**
1435      * Read YUV pixels from decoded output buffer for give (x, y) position
1436      * Output buffer is composed of Y parts followed by U/V
1437      * @param result pass the result via this. This is for avoiding creating / destroying too many
1438      *               instances
1439      */
getPixelValuesFromOutputBuffer(ByteBuffer buffer, int x, int y, YUVValue result)1440     private void getPixelValuesFromOutputBuffer(ByteBuffer buffer, int x, int y, YUVValue result) {
1441         result.mY = buffer.get(y * mVideoStride + x);
1442         if (isDstSemiPlanar()) {
1443             int index = mVideoStride * mVideoVStride + y / 2 * mVideoStride + x / 2 * 2;
1444             //Log.d(TAG, "Decoded " + x + "," + y + "," + index);
1445             result.mU = buffer.get(index);
1446             result.mV = buffer.get(index + 1);
1447         } else {
1448             int vOffset = mVideoStride * mVideoVStride / 4;
1449             int index = mVideoStride * mVideoVStride + y / 2 * mVideoStride / 2 + x / 2;
1450             result.mU = buffer.get(index);
1451             result.mV = buffer.get(index + vOffset);
1452         }
1453     }
1454 
getPixelValuesFromImage(Image image, int x, int y, YUVValue result)1455     private void getPixelValuesFromImage(Image image, int x, int y, YUVValue result) {
1456         assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
1457 
1458         Plane[] planes = image.getPlanes();
1459         assertTrue(planes.length == 3);
1460 
1461         result.mY = getPixelFromPlane(planes[0], x, y);
1462         result.mU = getPixelFromPlane(planes[1], x / 2, y / 2);
1463         result.mV = getPixelFromPlane(planes[2], x / 2, y / 2);
1464     }
1465 
getPixelFromPlane(Plane plane, int x, int y)1466     private byte getPixelFromPlane(Plane plane, int x, int y) {
1467         ByteBuffer buf = plane.getBuffer();
1468         return buf.get(y * plane.getRowStride() + x * plane.getPixelStride());
1469     }
1470 
1471     /**
1472      * Y cannot have full range. clamp it to prevent invalid value.
1473      */
clampY(int y)1474     private byte clampY(int y) {
1475         if (y < Y_CLAMP_MIN) {
1476             y = Y_CLAMP_MIN;
1477         } else if (y > Y_CLAMP_MAX) {
1478             y = Y_CLAMP_MAX;
1479         }
1480         return (byte) (y & 0xff);
1481     }
1482 
1483     // for debugging
printByteArray(String msg, byte[] data, int offset, int len)1484     private void printByteArray(String msg, byte[] data, int offset, int len) {
1485         StringBuilder builder = new StringBuilder();
1486         builder.append(msg);
1487         builder.append(":");
1488         for (int i = offset; i < offset + len; i++) {
1489             builder.append(Integer.toHexString(data[i]));
1490             builder.append(",");
1491         }
1492         builder.deleteCharAt(builder.length() - 1);
1493         Log.i(TAG, builder.toString());
1494     }
1495 
1496     // for debugging
printByteBuffer(String msg, ByteBuffer data, int offset, int len)1497     private void printByteBuffer(String msg, ByteBuffer data, int offset, int len) {
1498         StringBuilder builder = new StringBuilder();
1499         builder.append(msg);
1500         builder.append(":");
1501         for (int i = offset; i < offset + len; i++) {
1502             builder.append(Integer.toHexString(data.get(i)));
1503             builder.append(",");
1504         }
1505         builder.deleteCharAt(builder.length() - 1);
1506         Log.i(TAG, builder.toString());
1507     }
1508 
1509     /**
1510      * Generates the presentation time for frame N, in microseconds.
1511      */
computePresentationTime(int frameIndex)1512     private long computePresentationTime(int frameIndex) {
1513         return 132 + frameIndex * 1000000L / mFrameRate;
1514     }
1515 }
1516