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