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