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