• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.mediav2.common.cts;
18 
19 import static android.media.MediaCodecInfo.CodecProfileLevel.*;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotEquals;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25 
26 import android.media.MediaCodec;
27 import android.media.MediaExtractor;
28 import android.media.MediaFormat;
29 import android.util.Log;
30 import android.util.Pair;
31 
32 import java.io.IOException;
33 import java.nio.ByteBuffer;
34 
35 /**
36  * Wrapper class for testing encoders support for profile and level
37  */
38 public class EncoderProfileLevelTestBase extends CodecEncoderTestBase {
39     private static final String LOG_TAG = EncoderProfileLevelTestBase.class.getSimpleName();
40 
divUp(int num, int den)41     private static int divUp(int num, int den) {
42         return (num + den - 1) / den;
43     }
44 
getMinLevel(String mediaType, int width, int height, int frameRate, int bitrate, int profile)45     public static int getMinLevel(String mediaType, int width, int height, int frameRate,
46             int bitrate, int profile) {
47         switch (mediaType) {
48             case MediaFormat.MIMETYPE_VIDEO_AVC:
49                 return getMinLevelAVC(width, height, frameRate, bitrate);
50             case MediaFormat.MIMETYPE_VIDEO_HEVC:
51                 return getMinLevelHEVC(width, height, frameRate, bitrate);
52             case MediaFormat.MIMETYPE_VIDEO_H263:
53                 return getMinLevelH263(width, height, frameRate, bitrate);
54             case MediaFormat.MIMETYPE_VIDEO_MPEG2:
55                 return getMinLevelMPEG2(width, height, frameRate, bitrate);
56             case MediaFormat.MIMETYPE_VIDEO_MPEG4:
57                 return getMinLevelMPEG4(width, height, frameRate, bitrate, profile);
58             case MediaFormat.MIMETYPE_VIDEO_VP9:
59                 return getMinLevelVP9(width, height, frameRate, bitrate);
60             case MediaFormat.MIMETYPE_VIDEO_AV1:
61                 return getMinLevelAV1(width, height, frameRate, bitrate);
62             default:
63                 return -1;
64         }
65     }
66 
getMinLevelAVC(int width, int height, int frameRate, int bitrate)67     private static int getMinLevelAVC(int width, int height, int frameRate, int bitrate) {
68         class LevelLimitAVC {
69             private LevelLimitAVC(int level, int mbsPerSec, long mbs, int bitrate) {
70                 this.mLevel = level;
71                 this.mMbsPerSec = mbsPerSec;
72                 this.mMbs = mbs;
73                 this.mBitrate = bitrate;
74             }
75 
76             private final int mLevel;
77             private final int mMbsPerSec;
78             private final long mMbs;
79             private final int mBitrate;
80         }
81         LevelLimitAVC[] limitsAVC = {
82                 new LevelLimitAVC(AVCLevel1, 1485, 99, 64000),
83                 new LevelLimitAVC(AVCLevel1b, 1485, 99, 128000),
84                 new LevelLimitAVC(AVCLevel11, 3000, 396, 192000),
85                 new LevelLimitAVC(AVCLevel12, 6000, 396, 384000),
86                 new LevelLimitAVC(AVCLevel13, 11880, 396, 768000),
87                 new LevelLimitAVC(AVCLevel2, 11880, 396, 2000000),
88                 new LevelLimitAVC(AVCLevel21, 19800, 792, 4000000),
89                 new LevelLimitAVC(AVCLevel22, 20250, 1620, 4000000),
90                 new LevelLimitAVC(AVCLevel3, 40500, 1620, 10000000),
91                 new LevelLimitAVC(AVCLevel31, 108000, 3600, 14000000),
92                 new LevelLimitAVC(AVCLevel32, 216000, 5120, 20000000),
93                 new LevelLimitAVC(AVCLevel4, 245760, 8192, 20000000),
94                 new LevelLimitAVC(AVCLevel41, 245760, 8192, 50000000),
95                 new LevelLimitAVC(AVCLevel42, 522240, 8704, 50000000),
96                 new LevelLimitAVC(AVCLevel5, 589824, 22080, 135000000),
97                 new LevelLimitAVC(AVCLevel51, 983040, 36864, 240000000),
98                 new LevelLimitAVC(AVCLevel52, 2073600, 36864, 240000000),
99                 new LevelLimitAVC(AVCLevel6, 4177920, 139264, 240000000),
100                 new LevelLimitAVC(AVCLevel61, 8355840, 139264, 480000000),
101                 new LevelLimitAVC(AVCLevel62, 16711680, 139264, 800000000),
102         };
103         int blockSize = 16;
104         int mbs = divUp(width, blockSize) * divUp(height, blockSize);
105         float mbsPerSec = mbs * frameRate;
106         for (LevelLimitAVC levelLimitsAVC : limitsAVC) {
107             if (mbs <= levelLimitsAVC.mMbs && mbsPerSec <= levelLimitsAVC.mMbsPerSec
108                     && bitrate <= levelLimitsAVC.mBitrate) {
109                 return levelLimitsAVC.mLevel;
110             }
111         }
112         // if none of the levels suffice, select the highest level
113         return AVCLevel62;
114     }
115 
getMinLevelHEVC(int width, int height, int frameRate, int bitrate)116     private static int getMinLevelHEVC(int width, int height, int frameRate, int bitrate) {
117         class LevelLimitHEVC {
118             private LevelLimitHEVC(int level, int frameRate, long samples, int bitrate) {
119                 this.mLevel = level;
120                 this.mFrameRate = frameRate;
121                 this.mSamples = samples;
122                 this.mBitrate = bitrate;
123             }
124 
125             private final int mLevel;
126             private final int mFrameRate;
127             private final long mSamples;
128             private final int mBitrate;
129         }
130         LevelLimitHEVC[] limitsHEVC = {
131                 new LevelLimitHEVC(HEVCMainTierLevel1, 15, 36864, 128000),
132                 new LevelLimitHEVC(HEVCMainTierLevel2, 30, 122880, 1500000),
133                 new LevelLimitHEVC(HEVCMainTierLevel21, 30, 245760, 3000000),
134                 new LevelLimitHEVC(HEVCMainTierLevel3, 30, 552960, 6000000),
135                 new LevelLimitHEVC(HEVCMainTierLevel31, 30, 983040, 10000000),
136                 new LevelLimitHEVC(HEVCMainTierLevel4, 30, 2228224, 12000000),
137                 new LevelLimitHEVC(HEVCHighTierLevel4, 30, 2228224, 30000000),
138                 new LevelLimitHEVC(HEVCMainTierLevel41, 60, 2228224, 20000000),
139                 new LevelLimitHEVC(HEVCHighTierLevel41, 60, 2228224, 50000000),
140                 new LevelLimitHEVC(HEVCMainTierLevel5, 30, 8912896, 25000000),
141                 new LevelLimitHEVC(HEVCHighTierLevel5, 30, 8912896, 100000000),
142                 new LevelLimitHEVC(HEVCMainTierLevel51, 60, 8912896, 40000000),
143                 new LevelLimitHEVC(HEVCHighTierLevel51, 60, 8912896, 160000000),
144                 new LevelLimitHEVC(HEVCMainTierLevel52, 120, 8912896, 60000000),
145                 new LevelLimitHEVC(HEVCHighTierLevel52, 120, 8912896, 240000000),
146                 new LevelLimitHEVC(HEVCMainTierLevel6, 30, 35651584, 60000000),
147                 new LevelLimitHEVC(HEVCHighTierLevel6, 30, 35651584, 240000000),
148                 new LevelLimitHEVC(HEVCMainTierLevel61, 60, 35651584, 120000000),
149                 new LevelLimitHEVC(HEVCHighTierLevel61, 60, 35651584, 480000000),
150                 new LevelLimitHEVC(HEVCMainTierLevel62, 120, 35651584, 240000000),
151                 new LevelLimitHEVC(HEVCHighTierLevel62, 120, 35651584, 800000000),
152         };
153         int blockSize = 8;
154         int blocks = divUp(width, blockSize) * divUp(height, blockSize);
155         int samples = blocks * blockSize * blockSize;
156         for (LevelLimitHEVC levelLimitsHEVC : limitsHEVC) {
157             if (samples <= levelLimitsHEVC.mSamples && frameRate <= levelLimitsHEVC.mFrameRate
158                     && bitrate <= levelLimitsHEVC.mBitrate) {
159                 return levelLimitsHEVC.mLevel;
160             }
161         }
162         // if none of the levels suffice, select the highest level
163         return HEVCHighTierLevel62;
164     }
165 
getMinLevelH263(int width, int height, int frameRate, int bitrate)166     private static int getMinLevelH263(int width, int height, int frameRate, int bitrate) {
167         class LevelLimitH263 {
168             private LevelLimitH263(int level, long sampleRate, int width, int height, int frameRate,
169                     int bitrate) {
170                 this.mLevel = level;
171                 this.mSampleRate = sampleRate;
172                 this.mWidth = width;
173                 this.mHeight = height;
174                 this.mFrameRate = frameRate;
175                 this.mBitrate = bitrate;
176             }
177 
178             private final int mLevel;
179             private final long mSampleRate;
180             private final int mWidth;
181             private final int mHeight;
182             private final int mFrameRate;
183             private final int mBitrate;
184         }
185         LevelLimitH263[] limitsH263 = {
186                 new LevelLimitH263(H263Level10, 380160, 176, 144, 15, 64000),
187                 new LevelLimitH263(H263Level45, 380160, 176, 144, 15, 128000),
188                 new LevelLimitH263(H263Level20, 1520640, 352, 288, 30, 128000),
189                 new LevelLimitH263(H263Level30, 3041280, 352, 288, 30, 384000),
190                 new LevelLimitH263(H263Level40, 3041280, 352, 288, 30, 2048000),
191                 new LevelLimitH263(H263Level50, 5068800, 352, 288, 60, 4096000),
192                 new LevelLimitH263(H263Level60, 10368000, 720, 288, 60, 8192000),
193                 new LevelLimitH263(H263Level70, 20736000, 720, 576, 60, 16384000),
194         };
195         int blockSize = 16;
196         int mbs = divUp(width, blockSize) * divUp(height, blockSize);
197         int size = mbs * blockSize * blockSize;
198         int sampleRate = size * frameRate;
199         for (LevelLimitH263 levelLimitsH263 : limitsH263) {
200             if (sampleRate <= levelLimitsH263.mSampleRate && height <= levelLimitsH263.mHeight
201                     && width <= levelLimitsH263.mWidth && frameRate <= levelLimitsH263.mFrameRate
202                     && bitrate <= levelLimitsH263.mBitrate) {
203                 return levelLimitsH263.mLevel;
204             }
205         }
206         // if none of the levels suffice, select the highest level
207         return H263Level70;
208     }
209 
getMinLevelVP9(int width, int height, int frameRate, int bitrate)210     private static int getMinLevelVP9(int width, int height, int frameRate, int bitrate) {
211         class LevelLimitVP9 {
212             private LevelLimitVP9(int level, long sampleRate, int size, int maxWH, int bitrate) {
213                 this.mLevel = level;
214                 this.mSampleRate = sampleRate;
215                 this.mSize = size;
216                 this.mMaxWH = maxWH;
217                 this.mBitrate = bitrate;
218             }
219 
220             private final int mLevel;
221             private final long mSampleRate;
222             private final int mSize;
223             private final int mMaxWH;
224             private final int mBitrate;
225         }
226         LevelLimitVP9[] limitsVP9 = {
227                 new LevelLimitVP9(VP9Level1, 829440, 36864, 512, 200000),
228                 new LevelLimitVP9(VP9Level11, 2764800, 73728, 768, 800000),
229                 new LevelLimitVP9(VP9Level2, 4608000, 122880, 960, 1800000),
230                 new LevelLimitVP9(VP9Level21, 9216000, 245760, 1344, 3600000),
231                 new LevelLimitVP9(VP9Level3, 20736000, 552960, 2048, 7200000),
232                 new LevelLimitVP9(VP9Level31, 36864000, 983040, 2752, 12000000),
233                 new LevelLimitVP9(VP9Level4, 83558400, 2228224, 4160, 18000000),
234                 new LevelLimitVP9(VP9Level41, 160432128, 2228224, 4160, 30000000),
235                 new LevelLimitVP9(VP9Level5, 311951360, 8912896, 8384, 60000000),
236                 new LevelLimitVP9(VP9Level51, 588251136, 8912896, 8384, 120000000),
237                 new LevelLimitVP9(VP9Level52, 1176502272, 8912896, 8384, 180000000),
238                 new LevelLimitVP9(VP9Level6, 1176502272, 35651584, 16832, 180000000),
239                 new LevelLimitVP9(VP9Level61, 2353004544L, 35651584, 16832, 240000000),
240                 new LevelLimitVP9(VP9Level62, 4706009088L, 35651584, 16832, 480000000),
241         };
242         int blockSize = 8;
243         int blocks = divUp(width, blockSize) * divUp(height, blockSize);
244         int size = blocks * blockSize * blockSize;
245         int sampleRate = size * frameRate;
246         int maxWH = Math.max(width, height);
247         for (LevelLimitVP9 levelLimitsVP9 : limitsVP9) {
248             if (sampleRate <= levelLimitsVP9.mSampleRate && size <= levelLimitsVP9.mSize
249                     && maxWH <= levelLimitsVP9.mMaxWH && bitrate <= levelLimitsVP9.mBitrate) {
250                 return levelLimitsVP9.mLevel;
251             }
252         }
253         // if none of the levels suffice, select the highest level
254         return VP9Level62;
255     }
256 
getMinLevelMPEG2(int width, int height, int frameRate, int bitrate)257     private static int getMinLevelMPEG2(int width, int height, int frameRate, int bitrate) {
258         class LevelLimitMPEG2 {
259             private LevelLimitMPEG2(int level, long sampleRate, int width, int height,
260                     int frameRate, int bitrate) {
261                 this.mLevel = level;
262                 this.mSampleRate = sampleRate;
263                 this.mWidth = width;
264                 this.mHeight = height;
265                 this.mFrameRate = frameRate;
266                 this.mBitrate = bitrate;
267             }
268 
269             private final int mLevel;
270             private final long mSampleRate;
271             private final int mWidth;
272             private final int mHeight;
273             private final int mFrameRate;
274             private final int mBitrate;
275         }
276         // main profile limits, higher profiles will also support selected level
277         LevelLimitMPEG2[] limitsMPEG2 = {
278                 new LevelLimitMPEG2(MPEG2LevelLL, 3041280, 352, 288, 30, 4000000),
279                 new LevelLimitMPEG2(MPEG2LevelML, 10368000, 720, 576, 30, 15000000),
280                 new LevelLimitMPEG2(MPEG2LevelH14, 47001600, 1440, 1088, 60, 60000000),
281                 new LevelLimitMPEG2(MPEG2LevelHL, 62668800, 1920, 1088, 60, 80000000),
282                 new LevelLimitMPEG2(MPEG2LevelHP, 125337600, 1920, 1088, 60, 80000000),
283         };
284         int blockSize = 16;
285         int mbs = divUp(width, blockSize) * divUp(height, blockSize);
286         int size = mbs * blockSize * blockSize;
287         int sampleRate = size * frameRate;
288         for (LevelLimitMPEG2 levelLimitsMPEG2 : limitsMPEG2) {
289             if (sampleRate <= levelLimitsMPEG2.mSampleRate && width <= levelLimitsMPEG2.mWidth
290                     && height <= levelLimitsMPEG2.mHeight
291                     && frameRate <= levelLimitsMPEG2.mFrameRate
292                     && bitrate <= levelLimitsMPEG2.mBitrate) {
293                 return levelLimitsMPEG2.mLevel;
294             }
295         }
296         // if none of the levels suffice, select the highest level
297         return MPEG2LevelHP;
298     }
299 
getMinLevelMPEG4(int width, int height, int frameRate, int bitrate, int profile)300     private static int getMinLevelMPEG4(int width, int height, int frameRate, int bitrate,
301             int profile) {
302         class LevelLimitMPEG4 {
303             private LevelLimitMPEG4(int profile, int level, long sampleRate, int width, int height,
304                     int frameRate, int bitrate) {
305                 this.mProfile = profile;
306                 this.mLevel = level;
307                 this.mSampleRate = sampleRate;
308                 this.mWidth = width;
309                 this.mHeight = height;
310                 this.mFrameRate = frameRate;
311                 this.mBitrate = bitrate;
312             }
313 
314             private final int mProfile;
315             private final int mLevel;
316             private final long mSampleRate;
317             private final int mWidth;
318             private final int mHeight;
319             private final int mFrameRate;
320             private final int mBitrate;
321         }
322         // simple profile limits, higher profiles will also support selected level
323         LevelLimitMPEG4[] limitsMPEG4 = {
324                 new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0, 380160, 176, 144, 15, 64000),
325                 new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level1, 380160, 176, 144, 30, 64000),
326                 new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0b, 380160, 176, 144, 15, 128000),
327                 new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level2, 1520640, 352, 288, 30, 128000),
328                 new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level3, 3041280, 352, 288, 30, 384000),
329                 new LevelLimitMPEG4(
330                         MPEG4ProfileSimple, MPEG4Level4a, 9216000, 640, 480, 30, 4000000),
331                 new LevelLimitMPEG4(
332                         MPEG4ProfileSimple, MPEG4Level5, 10368000, 720, 576, 30, 8000000),
333                 new LevelLimitMPEG4(
334                         MPEG4ProfileSimple, MPEG4Level6, 27648000, 1280, 720, 30, 12000000),
335                 new LevelLimitMPEG4(
336                         MPEG4ProfileAdvancedSimple, MPEG4Level1, 760320, 176, 144, 30, 128000),
337                 new LevelLimitMPEG4(
338                         MPEG4ProfileAdvancedSimple, MPEG4Level2, 1520640, 352, 288, 30, 384000),
339                 new LevelLimitMPEG4(
340                         MPEG4ProfileAdvancedSimple, MPEG4Level3, 3041280, 352, 288, 30, 768000),
341                 new LevelLimitMPEG4(
342                         MPEG4ProfileAdvancedSimple, MPEG4Level3b, 3041280, 352, 288, 30, 1500000),
343                 new LevelLimitMPEG4(
344                         MPEG4ProfileAdvancedSimple, MPEG4Level4, 6082560, 704, 576, 30, 3000000),
345                 new LevelLimitMPEG4(
346                         MPEG4ProfileAdvancedSimple, MPEG4Level5, 12441600, 720, 576, 30, 8000000),
347         };
348         int blockSize = 16;
349         int mbs = divUp(width, blockSize) * divUp(height, blockSize);
350         int size = mbs * blockSize * blockSize;
351         int sampleRate = size * frameRate;
352         if (profile != MPEG4ProfileAdvancedSimple && profile != MPEG4ProfileSimple) {
353             throw new RuntimeException("Unrecognized profile " + profile + " for "
354                     + MediaFormat.MIMETYPE_VIDEO_MPEG4);
355         }
356         for (LevelLimitMPEG4 levelLimitsMPEG4 : limitsMPEG4) {
357             if (profile == levelLimitsMPEG4.mProfile && sampleRate <= levelLimitsMPEG4.mSampleRate
358                     && width <= levelLimitsMPEG4.mWidth && height <= levelLimitsMPEG4.mHeight
359                     && frameRate <= levelLimitsMPEG4.mFrameRate
360                     && bitrate <= levelLimitsMPEG4.mBitrate) {
361                 return levelLimitsMPEG4.mLevel;
362             }
363         }
364         // if none of the levels suffice, select the highest level
365         return MPEG4Level6;
366     }
367 
getMinLevelAV1(int width, int height, int frameRate, int bitrate)368     private static int getMinLevelAV1(int width, int height, int frameRate, int bitrate) {
369         class LevelLimitAV1 {
370             private LevelLimitAV1(int level, int size, int width, int height, long sampleRate,
371                     int bitrate) {
372                 this.mLevel = level;
373                 this.mSize = size;
374                 this.mWidth = width;
375                 this.mHeight = height;
376                 this.mSampleRate = sampleRate;
377                 this.mBitrate = bitrate;
378             }
379 
380             private final int mLevel;
381             private final int mSize;
382             private final int mWidth;
383             private final int mHeight;
384             private final long mSampleRate;
385             private final int mBitrate;
386         }
387         // taking bitrate from main profile, will also be supported by high profile
388         LevelLimitAV1[] limitsAV1 = {
389                 new LevelLimitAV1(AV1Level2, 147456, 2048, 1152, 4423680, 1500000),
390                 new LevelLimitAV1(AV1Level21, 278784, 2816, 1584, 8363520, 3000000),
391                 new LevelLimitAV1(AV1Level3, 665856, 4352, 2448, 19975680, 6000000),
392                 new LevelLimitAV1(AV1Level31, 1065024, 5504, 3096, 31950720, 10000000),
393                 new LevelLimitAV1(AV1Level4, 2359296, 6144, 3456, 70778880, 12000000),
394                 new LevelLimitAV1(AV1Level41, 2359296, 6144, 3456, 141557760, 20000000),
395                 new LevelLimitAV1(AV1Level5, 8912896, 8192, 4352, 267386880, 30000000),
396                 new LevelLimitAV1(AV1Level51, 8912896, 8192, 4352, 534773760, 40000000),
397                 new LevelLimitAV1(AV1Level52, 8912896, 8192, 4352, 1069547520, 60000000),
398                 new LevelLimitAV1(AV1Level53, 8912896, 8192, 4352, 1069547520, 60000000),
399                 new LevelLimitAV1(AV1Level6, 35651584, 16384, 8704, 1069547520, 60000000),
400                 new LevelLimitAV1(AV1Level61, 35651584, 16384, 8704, 2139095040, 100000000),
401                 new LevelLimitAV1(AV1Level62, 35651584, 16384, 8704, 4278190080L, 160000000),
402                 new LevelLimitAV1(AV1Level63, 35651584, 16384, 8704, 4278190080L, 160000000),
403         };
404         int blockSize = 8;
405         int blocks = divUp(width, blockSize) * divUp(height, blockSize);
406         int size = blocks * blockSize * blockSize;
407         int sampleRate = size * frameRate;
408         for (LevelLimitAV1 levelLimitsAV1 : limitsAV1) {
409             if (size <= levelLimitsAV1.mSize && width <= levelLimitsAV1.mWidth
410                     && height <= levelLimitsAV1.mHeight && sampleRate <= levelLimitsAV1.mSampleRate
411                     && bitrate <= levelLimitsAV1.mBitrate) {
412                 return levelLimitsAV1.mLevel;
413             }
414         }
415         // if none of the levels suffice or high profile, select the highest level
416         return AV1Level73;
417     }
418 
419     protected BitStreamUtils.ParserBase mParser;
420     protected Pair<Integer, Integer> mProfileLevel;
421     protected boolean mGotCsd;
422 
EncoderProfileLevelTestBase(String encoder, String mediaType, EncoderConfigParams[] encCfgParams, String allTestParams)423     public EncoderProfileLevelTestBase(String encoder, String mediaType,
424             EncoderConfigParams[] encCfgParams, String allTestParams) {
425         super(encoder, mediaType, encCfgParams, allTestParams);
426     }
427 
428     @Override
resetContext(boolean isAsync, boolean signalEOSWithLastFrame)429     protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
430         super.resetContext(isAsync, signalEOSWithLastFrame);
431         mParser = BitStreamUtils.getParserObject(mMediaType);
432         mProfileLevel = null;
433         mGotCsd = false;
434     }
435 
436     @Override
dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info)437     protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
438         if (info.size > 0 && mProfileLevel == null) {
439             if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
440                 ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
441                 mProfileLevel = BitStreamUtils.getProfileLevelFromBitStream(buf, info, mParser);
442                 mGotCsd = true;
443             } else {
444                 if ((mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP9) || mMediaType.equals(
445                         MediaFormat.MIMETYPE_VIDEO_H263)) && mOutputCount == 0) {
446                     ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
447                     mProfileLevel = BitStreamUtils.getProfileLevelFromBitStream(buf, info, mParser);
448                 }
449             }
450         }
451         super.dequeueOutput(bufferIndex, info);
452     }
453 
getProfile(MediaFormat format, String msg)454     private int getProfile(MediaFormat format, String msg) {
455         // Query output profile. KEY_PROFILE gets precedence over KEY_AAC_PROFILE
456         int aacProfile = format.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
457         int profile = format.getInteger(MediaFormat.KEY_PROFILE, aacProfile);
458         if (profile != -1) {
459             return profile;
460         } else {
461             fail(msg + "profile key not present in format " + format + mTestConfig + mTestEnv);
462         }
463         return -1;
464     }
465 
getLevel(MediaFormat format, String msg)466     private int getLevel(MediaFormat format, String msg) {
467         assertTrue(msg + "level not present in format " + format + mTestConfig + mTestEnv,
468                 format.containsKey(MediaFormat.KEY_LEVEL));
469         return format.getInteger(MediaFormat.KEY_LEVEL);
470     }
471 
validateProfile(int exp, int got, String msg)472     protected void validateProfile(int exp, int got, String msg) {
473         if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
474             if (exp == AVCProfileBaseline || exp == AVCProfileConstrainedBaseline) {
475                 assertTrue(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
476                                 exp, got) + mTestConfig + mTestEnv,
477                         (got == AVCProfileBaseline || got == AVCProfileConstrainedBaseline));
478                 return;
479             } else if (exp == AVCProfileHigh || exp == AVCProfileConstrainedHigh) {
480                 assertTrue(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
481                                 exp, got) + mTestConfig + mTestEnv,
482                         (got == AVCProfileHigh || got == AVCProfileConstrainedHigh));
483                 return;
484             }
485         }
486         assertEquals(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
487                 exp, got) + mTestConfig + mTestEnv, exp, got);
488     }
489 
validateLevel(int exp, int got, String msg)490     protected void validateLevel(int exp, int got, String msg) {
491         assertEquals(String.format(msg + "Level information mismatch, Expected %d, Got %d ",
492                 exp, got) + mTestConfig + mTestEnv, exp, got);
493     }
494 
validateMinLevel(int min, int got, String msg)495     protected void validateMinLevel(int min, int got, String msg) {
496         String log = String.format(msg + "Level information unexpected, Expected at least %d,"
497                 + " Got %d ", min, got) + mTestConfig + mTestEnv;
498         // H263 level 45 is out of order.
499         if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_H263) && min == H263Level45) {
500             // If we are expecting a min level45, then any level other than the ones below
501             // level45 (level10) should be ok
502             assertNotEquals(log, H263Level10, got);
503         } else if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_H263) && got == H263Level45) {
504             // If we got level45, then min level must be level10 or level45
505             assertEquals(log, H263Level10, min);
506         } else {
507             assertTrue(log, min <= got);
508         }
509     }
510 
validateBitStreamForProfileAndLevel(int cfgProfile, int cfgLevel)511     protected void validateBitStreamForProfileAndLevel(int cfgProfile, int cfgLevel) {
512         if (mProfileLevel != null) {
513             validateProfile(cfgProfile, mProfileLevel.first, "Validating profile of bitstream : ");
514             if (mProfileLevel.second != -1) {
515                 validateMinLevel(cfgLevel, mProfileLevel.second,
516                         "Validating level of bitstream : ");
517             }
518         }
519     }
520 
validateFormatForProfileAndLevelWRTBitstream(MediaFormat format, String msg)521     protected void validateFormatForProfileAndLevelWRTBitstream(MediaFormat format, String msg) {
522         if (mProfileLevel != null) {
523             validateProfile(mProfileLevel.first, getProfile(format, msg), msg);
524             if (mProfileLevel.second != -1) {
525                 validateLevel(mProfileLevel.second, getLevel(format, msg), msg);
526             }
527         }
528     }
529 
validateFormatForProfileAndLevelWRTCfg(MediaFormat format, String msg)530     protected void validateFormatForProfileAndLevelWRTCfg(MediaFormat format, String msg) {
531         validateProfile(mActiveEncCfg.mProfile, getProfile(format, msg), msg);
532         if (mActiveEncCfg.mLevel != -1) {
533             validateMinLevel(mActiveEncCfg.mLevel, getLevel(format, msg), msg);
534         }
535     }
536 
validateFormatForProfileAndLevel(MediaFormat format, String msg)537     protected void validateFormatForProfileAndLevel(MediaFormat format, String msg) {
538         validateFormatForProfileAndLevelWRTBitstream(format, msg + " wrt to bitstream : ");
539         validateFormatForProfileAndLevelWRTCfg(format, msg + " wrt to cfg : ");
540     }
541 
validateProfileAndLevel()542     protected MediaFormat validateProfileAndLevel() throws IOException {
543         // check if bitstream is in accordance with configured profile and level info.
544         if (mProfileLevel != null) {
545             validateBitStreamForProfileAndLevel(mActiveEncCfg.mProfile, mActiveEncCfg.mLevel);
546         }
547 
548         // check if output format is in accordance with configured profile and level info.
549         if (mCodecName.toUpperCase().startsWith("OMX")) {
550             Log.i(LOG_TAG, "omx components don't present prof/level in outputformat");
551         } else {
552             validateFormatForProfileAndLevel(mOutFormat, "Testing output format : ");
553         }
554 
555         // check if extracted output profile and level information are in accordance with
556         // configured profile and level info
557         if (mMuxOutput && !mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_H263)) {
558             // Explicit signaling of header information such as profile, level etc is not
559             // directly available as HLS in H263 header. That information is conveyed through
560             // external means of RTP header
561             MediaExtractor extractor = new MediaExtractor();
562             extractor.setDataSource(mMuxedOutputFile);
563             assertEquals("Should be only 1 track \n" + mTestConfig + mTestEnv, 1,
564                     extractor.getTrackCount());
565             MediaFormat trackFormat = extractor.getTrackFormat(0);
566             extractor.release();
567             if (mGotCsd || (trackFormat.containsKey(MediaFormat.KEY_PROFILE)
568                     || trackFormat.containsKey(MediaFormat.KEY_LEVEL))) {
569                 validateFormatForProfileAndLevel(trackFormat, "Testing extractor format :- ");
570             }
571             return trackFormat;
572         }
573         return null;
574     }
575 }
576