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