1 /* 2 * Copyright (C) 2022 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 import static android.media.MediaFormat.PICTURE_TYPE_B; 21 import static android.media.MediaFormat.PICTURE_TYPE_I; 22 import static android.media.MediaFormat.PICTURE_TYPE_P; 23 import static android.media.MediaFormat.PICTURE_TYPE_UNKNOWN; 24 25 import android.annotation.TargetApi; 26 import android.media.MediaCodec; 27 import android.media.MediaFormat; 28 import android.os.Build; 29 import android.util.Pair; 30 31 import org.junit.Assert; 32 33 import java.nio.ByteBuffer; 34 import java.util.ArrayList; 35 import java.util.Map; 36 37 /** 38 * This class contains utility functions that parse compressed bitstream and returns metadata 39 * necessary for validation. This is by no means a thorough parser that is capable of parsing all 40 * syntax elements of a bitstream. This is designed to handle only the requirements of mediav2 41 * test suite. 42 * <p> 43 * Currently this class hosts utils that can, 44 * <ul> 45 * <li>Return frame type of the access units of avc, hevc, av1.</li> 46 * <li>Return profile/level information of avc, hevc, av1, vp9, mpeg4, h263, aac</li> 47 * </ul> 48 */ 49 public class BitStreamUtils { getHashMapVal(Map<Integer, Integer> obj, int key)50 private static int getHashMapVal(Map<Integer, Integer> obj, int key) { 51 Integer val = obj.get(key); 52 return val == null ? -1 : val; 53 } 54 55 static class ParsableBitArray { 56 protected final byte[] mData; 57 protected final int mOffset; 58 protected final int mLimit; 59 protected int mCurrByteOffset; 60 protected int mCurrBitOffset; 61 ParsableBitArray(byte[] data, int offset, int limit)62 ParsableBitArray(byte[] data, int offset, int limit) { 63 mData = data; 64 mOffset = offset; 65 mLimit = limit; 66 mCurrByteOffset = offset; 67 mCurrBitOffset = 0; 68 } 69 readBit()70 public boolean readBit() { 71 if (mCurrByteOffset >= mLimit) { 72 throw new ArrayIndexOutOfBoundsException( 73 String.format("Accessing bytes at offset %d, buffer limit %d", 74 mCurrByteOffset, mLimit)); 75 } 76 boolean returnValue = (mData[mCurrByteOffset] & (0x80 >> mCurrBitOffset)) != 0; 77 if (++mCurrBitOffset == 8) { 78 mCurrBitOffset = 0; 79 mCurrByteOffset++; 80 } 81 return returnValue; 82 } 83 readBits(int numBits)84 public int readBits(int numBits) { 85 if (numBits > 32) { 86 throw new IllegalArgumentException("readBits Exception: maximum storage space of " 87 + "return value of readBits : 32, less than bits to read : " + numBits); 88 } 89 int value = 0; 90 for (int i = 0; i < numBits; i++) { 91 value <<= 1; 92 value |= (readBit() ? 1 : 0); 93 } 94 return value; 95 } 96 readBitsLong(int numBits)97 public long readBitsLong(int numBits) { 98 if (numBits > 64) { 99 throw new IllegalArgumentException("readBitsLong Exception: maximum storage space " 100 + "of return value of readBits : 64, less than bits to read : " + numBits); 101 } 102 long value = 0; 103 for (int i = 0; i < numBits; i++) { 104 value <<= 1; 105 value |= (readBit() ? 1 : 0); 106 } 107 return value; 108 } 109 } 110 111 static class NalParsableBitArray extends ParsableBitArray { NalParsableBitArray(byte[] data, int offset, int limit)112 NalParsableBitArray(byte[] data, int offset, int limit) { 113 super(data, offset, limit); 114 } 115 116 @Override readBit()117 public boolean readBit() { 118 // emulation prevention 119 if (mCurrBitOffset == 0 && (mCurrByteOffset - 2 > mOffset) 120 && mData[mCurrByteOffset] == (byte) 0x03 121 && mData[mCurrByteOffset - 1] == (byte) 0x00 122 && mData[mCurrByteOffset - 2] == (byte) 0x00) { 123 mCurrByteOffset++; 124 } 125 return super.readBit(); 126 } 127 readUEV()128 public int readUEV() { 129 int leadingZeros = 0; 130 while (!readBit()) { 131 leadingZeros++; 132 } 133 return (1 << leadingZeros) - 1 + (leadingZeros > 0 ? readBits(leadingZeros) : 0); 134 } 135 } 136 137 static class ObuParsableBitArray extends ParsableBitArray { ObuParsableBitArray(byte[] data, int offset, int limit)138 ObuParsableBitArray(byte[] data, int offset, int limit) { 139 super(data, offset, limit); 140 } 141 uvlc()142 public long uvlc() { 143 int leadingZeros = 0; 144 while (true) { 145 boolean done = readBit(); 146 if (done) { 147 break; 148 } 149 leadingZeros++; 150 } 151 if (leadingZeros >= 32) { 152 return (1L << 32) - 1; 153 } 154 int value = readBits(leadingZeros); 155 return value + (1L << leadingZeros) - 1; 156 } 157 leb128()158 public int[] leb128() { 159 int value = 0, bytesRead = 0; 160 for (int count = 0; count < 8; count++) { 161 int leb128_byte = readBits(8); 162 value |= (leb128_byte & 0x7f) << (count * 7); 163 bytesRead++; 164 if ((leb128_byte & 0x80) == 0) break; 165 } 166 return new int[]{bytesRead, value}; 167 } 168 } 169 170 public abstract static class ParserBase { 171 protected byte[] mData; 172 protected int mOffset; 173 protected int mLimit; 174 set(byte[] data, int offset, int limit)175 protected void set(byte[] data, int offset, int limit) { 176 mData = data; 177 mOffset = offset; 178 mLimit = limit; 179 } 180 getFrameType()181 public abstract int getFrameType(); 182 getProfileLevel(boolean isCsd)183 public abstract Pair<Integer, Integer> getProfileLevel(boolean isCsd); 184 185 // .first = profile, .second = level plToPair(int profile, int level)186 public Pair<Integer, Integer> plToPair(int profile, int level) { 187 return Pair.create(profile, level); 188 } 189 } 190 191 static class Mpeg4Parser extends ParserBase { 192 @Override getFrameType()193 public int getFrameType() { 194 return PICTURE_TYPE_UNKNOWN; 195 } 196 197 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)198 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 199 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 200 Assert.assertEquals(0, bitArray.readBits(8)); 201 Assert.assertEquals(0, bitArray.readBits(8)); 202 Assert.assertEquals(1, bitArray.readBits(8)); 203 Assert.assertEquals(0xb0, bitArray.readBits(8)); 204 int profileLevel = bitArray.readBits(8); 205 switch (profileLevel) { 206 case 0x08: return plToPair(MPEG4ProfileSimple, MPEG4Level0); 207 case 0x01: return plToPair(MPEG4ProfileSimple, MPEG4Level1); 208 case 0x02: return plToPair(MPEG4ProfileSimple, MPEG4Level2); 209 case 0x03: return plToPair(MPEG4ProfileSimple, MPEG4Level3); 210 case 0xf0: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level0); 211 case 0xf1: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level1); 212 case 0xf2: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level2); 213 case 0xf3: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level3); 214 case 0xf7: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level3b); 215 case 0xf4: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level4); 216 case 0xf5: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level5); 217 default: return null; 218 } 219 } 220 } 221 222 static class H263Parser extends ParserBase { 223 @Override getFrameType()224 public int getFrameType() { 225 return PICTURE_TYPE_UNKNOWN; 226 } 227 228 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)229 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 230 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 231 Assert.assertEquals("bad psc", 0x20, bitArray.readBits(22)); 232 bitArray.readBits(8); // tr 233 Assert.assertEquals(1, bitArray.readBits(1)); 234 Assert.assertEquals(0, bitArray.readBits(1)); 235 bitArray.readBits(1); // split screen 236 bitArray.readBits(1); // camera indicator 237 bitArray.readBits(1); // freeze indicator 238 int sourceFormat = bitArray.readBits(3); 239 int picType; 240 int umv = 0, sac = 0, ap = 0, pb = 0; 241 int aic = 0, df = 0, ss = 0, rps = 0, isd = 0, aiv = 0, mq = 0; 242 int rpr = 0, rru = 0; 243 if (sourceFormat == 7) { 244 int ufep = bitArray.readBits(3); 245 if (ufep == 1) { 246 sourceFormat = bitArray.readBits(3); 247 bitArray.readBits(1); // custom pcf 248 umv = bitArray.readBits(1); 249 sac = bitArray.readBits(1); 250 ap = bitArray.readBits(1); 251 aic = bitArray.readBits(1); 252 df = bitArray.readBits(1); 253 ss = bitArray.readBits(1); 254 rps = bitArray.readBits(1); 255 isd = bitArray.readBits(1); 256 aiv = bitArray.readBits(1); 257 mq = bitArray.readBits(1); 258 Assert.assertEquals(1, bitArray.readBits(1)); 259 Assert.assertEquals(0, bitArray.readBits(3)); 260 } 261 picType = bitArray.readBits(3); 262 rpr = bitArray.readBits(1); 263 rru = bitArray.readBits(1); 264 bitArray.readBits(1); // rtype 265 Assert.assertEquals(0, bitArray.readBits(1)); // reserved 266 Assert.assertEquals(0, bitArray.readBits(1)); // reserved 267 Assert.assertEquals(1, bitArray.readBits(1)); // start code emulation 268 } else { 269 picType = bitArray.readBits(1); 270 umv = bitArray.readBits(1); 271 sac = bitArray.readBits(1); 272 ap = bitArray.readBits(1); 273 pb = bitArray.readBits(1); 274 } 275 int profile = H263ProfileBaseline; 276 if (ap == 1) profile = H263ProfileBackwardCompatible; 277 if (aic == 1 && df == 1 && ss == 1 && mq == 1) profile = H263ProfileISWV2; 278 return plToPair(profile, -1); 279 } 280 } 281 282 static class AvcParser extends ParserBase { 283 private static final int NO_NAL_UNIT_FOUND = -1; 284 private static final Map<Integer, Integer> LEVEL_MAP = Map.ofEntries( 285 Map.entry(10, AVCLevel1), 286 Map.entry(11, AVCLevel11), 287 Map.entry(12, AVCLevel12), 288 Map.entry(13, AVCLevel13), 289 Map.entry(20, AVCLevel2), 290 Map.entry(21, AVCLevel21), 291 Map.entry(22, AVCLevel22), 292 Map.entry(30, AVCLevel3), 293 Map.entry(31, AVCLevel31), 294 Map.entry(32, AVCLevel32), 295 Map.entry(40, AVCLevel4), 296 Map.entry(41, AVCLevel41), 297 Map.entry(42, AVCLevel42), 298 Map.entry(50, AVCLevel5), 299 Map.entry(51, AVCLevel51), 300 Map.entry(52, AVCLevel52), 301 Map.entry(60, AVCLevel6), 302 Map.entry(61, AVCLevel61), 303 Map.entry(62, AVCLevel62) 304 ); 305 getNalUnitStartOffset(byte[] dataArray, int start, int limit)306 private int getNalUnitStartOffset(byte[] dataArray, int start, int limit) { 307 for (int pos = start; pos + 3 < limit; pos++) { 308 if ((pos + 3) < limit && dataArray[pos] == 0 && dataArray[pos + 1] == 0 309 && dataArray[pos + 2] == 1) { 310 return pos + 3; 311 } else if ((pos + 4) < limit && dataArray[pos] == 0 && dataArray[pos + 1] == 0 312 && dataArray[pos + 2] == 0 && dataArray[pos + 3] == 1) { 313 return pos + 4; 314 } 315 } 316 return NO_NAL_UNIT_FOUND; 317 } 318 getNalUnitType(byte[] dataArray, int nalUnitOffset)319 private static int getNalUnitType(byte[] dataArray, int nalUnitOffset) { 320 return dataArray[nalUnitOffset] & 0x1F; 321 } 322 323 @Override getFrameType()324 public int getFrameType() { 325 for (int pos = mOffset; pos < mLimit; ) { 326 int offset = getNalUnitStartOffset(mData, pos, mLimit); 327 if (offset == NO_NAL_UNIT_FOUND) return PICTURE_TYPE_UNKNOWN; 328 int nalUnitType = getNalUnitType(mData, offset); 329 if (nalUnitType == 1 || nalUnitType == 2 || nalUnitType == 5) { // coded slice 330 NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit); 331 Assert.assertEquals(0, bitArray.readBits(1)); // forbidden zero bit 332 bitArray.readBits(7); // nal_ref_idc + nal_unit_type 333 bitArray.readUEV(); // first_mb_in_slice 334 int sliceType = bitArray.readUEV(); 335 if (sliceType % 5 == 0) { 336 return PICTURE_TYPE_P; 337 } else if (sliceType % 5 == 1) { 338 return PICTURE_TYPE_B; 339 } else if (sliceType % 5 == 2) { 340 return PICTURE_TYPE_I; 341 } else { 342 return PICTURE_TYPE_UNKNOWN; 343 } 344 } 345 pos = offset; 346 } 347 return PICTURE_TYPE_UNKNOWN; 348 } 349 350 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)351 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 352 for (int pos = mOffset; pos < mLimit; ) { 353 int offset = getNalUnitStartOffset(mData, pos, mLimit); 354 if (offset == NO_NAL_UNIT_FOUND) return null; 355 if (getNalUnitType(mData, offset) == 7) { // seq_parameter_set_rbsp 356 NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit); 357 Assert.assertEquals(0, bitArray.readBits(1)); // forbidden zero bit 358 bitArray.readBits(7); // nal_ref_idc + nal_unit_type 359 int profileIdc = bitArray.readBits(8); 360 int constraintSet0Flag = bitArray.readBits(1); 361 int constraintSet1Flag = bitArray.readBits(1); 362 int constraintSet2Flag = bitArray.readBits(1); 363 int constraintSet3Flag = bitArray.readBits(1); 364 int constraintSet4Flag = bitArray.readBits(1); 365 int constraintSet5Flag = bitArray.readBits(1); 366 Assert.assertEquals(0, bitArray.readBits(2)); // reserved zero 2 bits 367 int levelIdc = bitArray.readBits(8); 368 369 int profile = -1; 370 if (constraintSet0Flag == 1 || profileIdc == 66) { 371 profile = constraintSet1Flag == 1 ? AVCProfileConstrainedBaseline : 372 AVCProfileBaseline; 373 } else if (constraintSet1Flag == 1 || profileIdc == 77) { 374 profile = AVCProfileMain; 375 } else if (constraintSet2Flag == 1 || profileIdc == 88) { 376 profile = AVCProfileExtended; 377 } else if (profileIdc == 100) { 378 profile = (constraintSet4Flag == 1 && constraintSet5Flag == 1) 379 ? AVCProfileConstrainedHigh : AVCProfileHigh; 380 } else if (profileIdc == 110) { 381 profile = AVCProfileHigh10; 382 } else if (profileIdc == 122) { 383 profile = AVCProfileHigh422; 384 } else if (profileIdc == 244) { 385 profile = AVCProfileHigh444; 386 } 387 388 // In bitstreams conforming to the Baseline, Constrained Baseline, Main, or 389 // Extended profiles : 390 // - If level_idc is equal to 11 and constraint_set3_flag is equal to 1, the 391 // indicated level is level 1b. 392 // - Otherwise (level_idc is not equal to 11 or constraint_set3_flag is not 393 // equal to 1), level_idc is equal to a value of ten times the level number 394 // (of the indicated level) specified in Table A-1. 395 int level; 396 if ((levelIdc == 11) && (profile == AVCProfileBaseline 397 || profile == AVCProfileConstrainedBaseline || profile == AVCProfileMain 398 || profile == AVCProfileExtended)) { 399 level = constraintSet3Flag == 1 ? AVCLevel1b : AVCLevel11; 400 } else if ((levelIdc == 9) && (profile == AVCProfileHigh 401 || profile == AVCProfileHigh10 || profile == AVCProfileHigh422 402 || profile == AVCProfileHigh444)) { 403 // In bitstreams conforming to the High, High 10, High 4:2:2, High 4:4:4 404 // Predictive, High 10 Intra, High 4:2:2 Intra, High 4:4:4 Intra, or 405 // CAVLC 4:4:4 Intra profiles, 406 // - If level_idc is equal to 9, the indicated level is level 1b. 407 // - Otherwise (level_idc is not equal to 9), level_idc is equal to a 408 // value of ten times the level number (of the indicated level) specified 409 // in Table A-1 410 level = AVCLevel1b; 411 } else { 412 level = getHashMapVal(LEVEL_MAP, levelIdc); 413 } 414 return plToPair(profile, level); 415 } 416 pos = offset; 417 } 418 return null; 419 } 420 } 421 422 static class HevcParser extends ParserBase { 423 private static final int NO_NAL_UNIT_FOUND = -1; 424 private static final int TRAIL_N = 0; 425 private static final int RASL_R = 9; 426 private static final int BLA_W_LP = 16; 427 private static final int RSV_IRAP_VCL23 = 23; 428 private static final Map<Integer, Integer> LEVEL_MAP_MAIN_TIER = Map.ofEntries( 429 Map.entry(30, HEVCMainTierLevel1), 430 Map.entry(60, HEVCMainTierLevel2), 431 Map.entry(63, HEVCMainTierLevel21), 432 Map.entry(90, HEVCMainTierLevel3), 433 Map.entry(93, HEVCMainTierLevel31), 434 Map.entry(120, HEVCMainTierLevel4), 435 Map.entry(123, HEVCMainTierLevel41), 436 Map.entry(150, HEVCMainTierLevel5), 437 Map.entry(153, HEVCMainTierLevel51), 438 Map.entry(156, HEVCMainTierLevel52), 439 Map.entry(180, HEVCMainTierLevel6), 440 Map.entry(183, HEVCMainTierLevel61), 441 Map.entry(186, HEVCMainTierLevel62) 442 ); 443 private static final Map<Integer, Integer> LEVEL_MAP_HIGH_TIER = Map.ofEntries( 444 Map.entry(120, HEVCHighTierLevel4), 445 Map.entry(123, HEVCHighTierLevel41), 446 Map.entry(150, HEVCHighTierLevel5), 447 Map.entry(153, HEVCHighTierLevel51), 448 Map.entry(156, HEVCHighTierLevel52), 449 Map.entry(180, HEVCHighTierLevel6), 450 Map.entry(183, HEVCHighTierLevel61), 451 Map.entry(186, HEVCHighTierLevel62) 452 ); 453 getNalUnitStartOffset(byte[] dataArray, int start, int limit)454 private int getNalUnitStartOffset(byte[] dataArray, int start, int limit) { 455 for (int pos = start; pos + 3 < limit; pos++) { 456 if ((pos + 3) < limit && dataArray[pos] == 0 && dataArray[pos + 1] == 0 457 && dataArray[pos + 2] == 1) { 458 return pos + 3; 459 } else if ((pos + 4) < limit && dataArray[pos] == 0 && dataArray[pos + 1] == 0 460 && dataArray[pos + 2] == 0 && dataArray[pos + 3] == 1) { 461 return pos + 4; 462 } 463 } 464 return NO_NAL_UNIT_FOUND; 465 } 466 getNalUnitType(byte[] dataArray, int nalUnitOffset)467 private static int getNalUnitType(byte[] dataArray, int nalUnitOffset) { 468 return (dataArray[nalUnitOffset] & 0x7E) >> 1; 469 } 470 471 @Override getFrameType()472 public int getFrameType() { 473 for (int pos = mOffset; pos < mLimit; ) { 474 int offset = getNalUnitStartOffset(mData, pos, mLimit); 475 if (offset == NO_NAL_UNIT_FOUND) return PICTURE_TYPE_UNKNOWN; 476 int nalUnitType = getNalUnitType(mData, offset); 477 if ((nalUnitType >= TRAIL_N && nalUnitType <= RASL_R) || (nalUnitType >= BLA_W_LP 478 && nalUnitType <= RSV_IRAP_VCL23)) { // codec slice 479 NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit); 480 bitArray.readBits(16); // nal_unit_header 481 482 // Parsing slice_segment_header values from H.265/HEVC Table 7.3.6.1 483 boolean firstSliceSegmentInPicFlag = bitArray.readBit(); 484 if (!firstSliceSegmentInPicFlag) return PICTURE_TYPE_UNKNOWN; 485 if (nalUnitType >= BLA_W_LP && nalUnitType <= RSV_IRAP_VCL23) { 486 bitArray.readBit(); // no_output_of_prior_pics_flag 487 } 488 bitArray.readUEV(); // slice_pic_parameter_set_id 489 // FIXME: Assumes num_extra_slice_header_bits element of PPS data to be 0 490 int sliceType = bitArray.readUEV(); 491 if (sliceType == 0) { 492 return PICTURE_TYPE_B; 493 } else if (sliceType == 1) { 494 return PICTURE_TYPE_P; 495 } else if (sliceType == 2) { 496 return PICTURE_TYPE_I; 497 } else { 498 return PICTURE_TYPE_UNKNOWN; 499 } 500 } 501 pos = offset; 502 } 503 return PICTURE_TYPE_UNKNOWN; 504 } 505 506 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)507 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 508 for (int pos = mOffset; pos < mLimit; ) { 509 int offset = getNalUnitStartOffset(mData, pos, mLimit); 510 if (offset == NO_NAL_UNIT_FOUND) return null; 511 if (getNalUnitType(mData, offset) == 33) { // sps_nut 512 NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit); 513 bitArray.readBits(16); // nal unit header 514 bitArray.readBits(4); // sps video parameter set id 515 bitArray.readBits(3); // sps_max_sub_layers_minus1 516 bitArray.readBits(1); // sps temporal id nesting flag 517 // profile_tier_level 518 bitArray.readBits(2); // generalProfileSpace 519 int generalTierFlag = bitArray.readBits(1); 520 int generalProfileIdc = bitArray.readBits(5); 521 int[] generalProfileCompatibility = new int[32]; 522 for (int j = 0; j < generalProfileCompatibility.length; j++) { 523 generalProfileCompatibility[j] = bitArray.readBits(1); 524 } 525 bitArray.readBits(1); // general progressive source flag 526 bitArray.readBits(1); // general interlaced source flag 527 bitArray.readBits(1); // general non packed constraint flag 528 bitArray.readBits(1); // general frame only constraint flag 529 530 // interpretation of next 44 bits is dependent on generalProfileIdc and 531 // generalProfileCompatibility; but we do not use them in this validation 532 // process, so we're skipping over them. 533 bitArray.readBitsLong(44); 534 int generalLevelIdc = bitArray.readBits(8); 535 536 int profile = -1; 537 if (generalProfileIdc == 1 || generalProfileCompatibility[1] == 1) { 538 profile = HEVCProfileMain; 539 } else if (generalProfileIdc == 2 || generalProfileCompatibility[2] == 1) { 540 profile = HEVCProfileMain10; 541 } else if (generalProfileIdc == 3 || generalProfileCompatibility[3] == 1) { 542 profile = HEVCProfileMainStill; 543 } 544 545 return plToPair(profile, getHashMapVal( 546 generalTierFlag == 0 ? LEVEL_MAP_MAIN_TIER : LEVEL_MAP_HIGH_TIER, 547 generalLevelIdc)); 548 } 549 pos = offset; 550 } 551 return null; 552 } 553 } 554 555 static class Vp9Parser extends ParserBase { 556 private static final Map<Integer, Integer> PROFILE_MAP = Map.ofEntries( 557 Map.entry(0, VP9Profile0), 558 Map.entry(1, VP9Profile1), 559 Map.entry(2, VP9Profile2), 560 Map.entry(3, VP9Profile3) 561 ); 562 private static final Map<Integer, Integer> LEVEL_MAP = Map.ofEntries( 563 Map.entry(10, VP9Level1), 564 Map.entry(11, VP9Level11), 565 Map.entry(20, VP9Level2), 566 Map.entry(21, VP9Level21), 567 Map.entry(30, VP9Level3), 568 Map.entry(31, VP9Level31), 569 Map.entry(40, VP9Level4), 570 Map.entry(41, VP9Level41), 571 Map.entry(50, VP9Level5), 572 Map.entry(51, VP9Level51), 573 Map.entry(60, VP9Level6), 574 Map.entry(61, VP9Level61), 575 Map.entry(62, VP9Level62) 576 ); 577 getProfileLevelFromCSD()578 private Pair<Integer, Integer> getProfileLevelFromCSD() { // parse vp9 codecprivate 579 int profile = -1, level = -1; 580 for (int pos = mOffset; pos < mLimit; ) { 581 ParsableBitArray bitArray = new ParsableBitArray(mData, pos + mOffset, mLimit); 582 int id = bitArray.readBits(8); 583 int len = bitArray.readBits(8); 584 pos += 2; 585 int val = bitArray.readBits(len * 8); 586 pos += len; 587 if (id == 1 || id == 2) { 588 Assert.assertEquals(1, len); 589 if (id == 1) profile = val; 590 else level = val; 591 } 592 if (profile != -1 && level != -1) break; 593 } 594 return plToPair(getHashMapVal(PROFILE_MAP, profile), getHashMapVal(LEVEL_MAP, level)); 595 } 596 getProfileFromFrameHeader()597 private Pair<Integer, Integer> getProfileFromFrameHeader() { // parse uncompressed header 598 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 599 bitArray.readBits(2); // frame marker 600 int profileLBit = bitArray.readBits(1); 601 int profileHBit = bitArray.readBits(1); 602 int profile = profileHBit << 1 + profileLBit; 603 return plToPair(getHashMapVal(PROFILE_MAP, profile), -1); 604 } 605 606 @Override getFrameType()607 public int getFrameType() { 608 return PICTURE_TYPE_UNKNOWN; 609 } 610 611 @Override getProfileLevel(boolean isCsd)612 public Pair<Integer, Integer> getProfileLevel(boolean isCsd) { 613 return isCsd ? getProfileLevelFromCSD() : getProfileFromFrameHeader(); 614 } 615 } 616 617 static class Av1Parser extends ParserBase { 618 private static final int OBU_SEQUENCE_HEADER = 1; 619 private static final int OBU_FRAME_HEADER = 3; 620 private static final int OBU_FRAME = 6; 621 private static final int OBP_KEY_FRAME = 0; 622 private static final int OBP_INTER_FRAME = 1; 623 private static final int OBP_INTRA_ONLY_FRAME = 2; 624 private static final int OBP_SWITCH_FRAME = 3; 625 private static final int NUM_REF_FRAMES = 8; 626 627 static class ObuInfo { 628 private int mObuType; 629 private int mTemporalId; 630 private int mSpatialId; 631 private int mHeaderSize; 632 private int mSizeFieldSize; 633 private int mDataSize; 634 getTotalObuSize()635 int getTotalObuSize() { 636 return mHeaderSize + mSizeFieldSize + mDataSize; 637 } 638 getObuDataOffset()639 int getObuDataOffset() { 640 return mHeaderSize + mSizeFieldSize; 641 } 642 } 643 644 static class SeqHeaderObu { 645 public int seqProfile; 646 public int reducedStillPictureHeader; 647 public final int[] seqLevelIdx = new int[32]; 648 public int timingInfoPresentFlag; 649 public int equalPictureInterval; 650 public int decoderModelInfoPresentFlag; 651 public int bufferDelayLengthMinus1; 652 public int bufferRemovalTimeLengthMinus1; 653 public int framePresentationTimeLengthMinus1; 654 public int initialDisplayDelayPresentFlag; 655 public int operatingPointsCntMinus1; 656 public final int[] operatingPointIdc = new int[32]; 657 public final int[] seqTier = new int[32]; 658 public final int[] decoderModelPresentForThisOp = new int[32]; 659 public int frameIdNumbersPresentFlag; 660 public int deltaFrameIdLengthMinus2; 661 public int additionalFrameIdLengthMinus1; 662 public int seqForceScreenContentTools; 663 public int seqForceIntegerMv; 664 public int orderHintBits; 665 public int enableHighBitDepth; 666 } 667 668 static class FrameHeaderObu { 669 public int frameType; 670 public int showFrame; 671 public int showExistingFrame; 672 public int errorResilientMode; 673 } 674 675 private final SeqHeaderObu mSeqHeader = new SeqHeaderObu(); 676 private final int[] mRefFrameType = new int[NUM_REF_FRAMES]; 677 678 // obu header size, obu size field, obu size parseObuHeader(byte[] dataArray, int pos, int limit)679 private ObuInfo parseObuHeader(byte[] dataArray, int pos, int limit) { 680 int obuHeaderSize = 1; 681 ObuInfo obuDetails = new ObuInfo(); 682 ObuParsableBitArray bitArray = new ObuParsableBitArray(dataArray, pos, limit); 683 bitArray.readBits(1); // forbidden bit 684 obuDetails.mObuType = bitArray.readBits(4); // obu type 685 int extensionFlag = bitArray.readBits(1); 686 int hasSizeField = bitArray.readBits(1); 687 Assert.assertEquals(1, hasSizeField); 688 bitArray.readBits(1); // reserved 1bit 689 if (extensionFlag == 1) { 690 obuDetails.mTemporalId = bitArray.readBits(3); 691 obuDetails.mSpatialId = bitArray.readBits(2); 692 bitArray.readBits(3); 693 obuHeaderSize++; 694 } 695 int[] obuSizeInfo = bitArray.leb128(); 696 obuDetails.mHeaderSize = obuHeaderSize; 697 obuDetails.mSizeFieldSize = obuSizeInfo[0]; 698 obuDetails.mDataSize = obuSizeInfo[1]; 699 return obuDetails; 700 } 701 parseSequenceHeader(ObuParsableBitArray bitArray)702 private void parseSequenceHeader(ObuParsableBitArray bitArray) { 703 mSeqHeader.seqProfile = bitArray.readBits(3); 704 bitArray.readBits(1); // still picture 705 mSeqHeader.reducedStillPictureHeader = bitArray.readBits(1); 706 if (mSeqHeader.reducedStillPictureHeader == 1) { 707 mSeqHeader.seqLevelIdx[0] = bitArray.readBits(5); 708 } else { 709 mSeqHeader.timingInfoPresentFlag = bitArray.readBits(1); 710 if (mSeqHeader.timingInfoPresentFlag == 1) { 711 bitArray.readBitsLong(32); // num_units_in_display_tick 712 bitArray.readBitsLong(32); // time_scale 713 mSeqHeader.equalPictureInterval = bitArray.readBits(1); 714 if (mSeqHeader.equalPictureInterval == 1) { 715 bitArray.uvlc(); // num_ticks_per_picture_minus_1 716 } 717 mSeqHeader.decoderModelInfoPresentFlag = bitArray.readBits(1); 718 if (mSeqHeader.decoderModelInfoPresentFlag == 1) { 719 mSeqHeader.bufferDelayLengthMinus1 = bitArray.readBits(5); 720 bitArray.readBitsLong(32); // num_units_in_decoding_tick 721 mSeqHeader.bufferRemovalTimeLengthMinus1 = bitArray.readBits(5); 722 mSeqHeader.framePresentationTimeLengthMinus1 = bitArray.readBits(5); 723 } 724 } else { 725 mSeqHeader.decoderModelInfoPresentFlag = 0; 726 } 727 mSeqHeader.initialDisplayDelayPresentFlag = bitArray.readBits(1); 728 mSeqHeader.operatingPointsCntMinus1 = bitArray.readBits(5); 729 for (int i = 0; i <= mSeqHeader.operatingPointsCntMinus1; i++) { 730 mSeqHeader.operatingPointIdc[i] = bitArray.readBits(12); 731 mSeqHeader.seqLevelIdx[i] = bitArray.readBits(5); 732 if (mSeqHeader.seqLevelIdx[i] > 7) { 733 mSeqHeader.seqTier[i] = bitArray.readBits(1); 734 } 735 if (mSeqHeader.decoderModelInfoPresentFlag == 1) { 736 mSeqHeader.decoderModelPresentForThisOp[i] = bitArray.readBits(1); 737 if (mSeqHeader.decoderModelPresentForThisOp[i] == 1) { 738 int n = mSeqHeader.bufferDelayLengthMinus1 + 1; 739 bitArray.readBits(n); // decoder_buffer_delay 740 bitArray.readBits(n); // encoder_buffer_delay 741 bitArray.readBits(1); // low_delay_mode_flag 742 } 743 } else { 744 mSeqHeader.decoderModelPresentForThisOp[i] = 0; 745 } 746 if (mSeqHeader.initialDisplayDelayPresentFlag == 1) { 747 if (bitArray.readBits(1) == 1) { 748 bitArray.readBits(4); // initial_display_delay_minus_1 749 } 750 } 751 } 752 } 753 int frameWidthBitsMinus1 = bitArray.readBits(4); 754 int frameHeightBitsMinus1 = bitArray.readBits(4); 755 bitArray.readBits(frameWidthBitsMinus1 + 1); // max_frame_width_minus_1 756 bitArray.readBits(frameHeightBitsMinus1 + 1); // max_frame_height_minus_1 757 if (mSeqHeader.reducedStillPictureHeader == 1) { 758 mSeqHeader.frameIdNumbersPresentFlag = 0; 759 } else { 760 mSeqHeader.frameIdNumbersPresentFlag = bitArray.readBits(1); 761 } 762 if (mSeqHeader.frameIdNumbersPresentFlag == 1) { 763 mSeqHeader.deltaFrameIdLengthMinus2 = bitArray.readBits(4); 764 mSeqHeader.additionalFrameIdLengthMinus1 = bitArray.readBits(3); 765 } 766 bitArray.readBits(1); // use_128x128_superblock 767 bitArray.readBits(1); // enable_filter_intra 768 bitArray.readBits(1); // enable_intra_edge_filter 769 if (mSeqHeader.reducedStillPictureHeader == 1) { 770 mSeqHeader.seqForceScreenContentTools = 2; 771 mSeqHeader.seqForceIntegerMv = 2; 772 mSeqHeader.orderHintBits = 0; 773 } else { 774 bitArray.readBits(1); // enable_interintra_compound 775 bitArray.readBits(1); // enable_masked_compound 776 bitArray.readBits(1); // enable_warped_motion 777 bitArray.readBits(1); // enable_dual_filter 778 int enableOrderHint = bitArray.readBits(1); 779 if (enableOrderHint == 1) { 780 bitArray.readBits(1); // enable_jnt_comp 781 bitArray.readBits(1); // enable_ref_frame_mvs 782 } 783 int seqChooseScreenContentTools = bitArray.readBits(1); 784 if (seqChooseScreenContentTools == 1) { 785 mSeqHeader.seqForceScreenContentTools = 2; 786 } else { 787 mSeqHeader.seqForceScreenContentTools = bitArray.readBits(1); 788 } 789 if (mSeqHeader.seqForceScreenContentTools > 0) { 790 int seqChooseIntegerMv = bitArray.readBits(1); 791 if (seqChooseIntegerMv == 1) { 792 mSeqHeader.seqForceIntegerMv = 2; 793 } else { 794 mSeqHeader.seqForceIntegerMv = bitArray.readBits(1); 795 } 796 } else { 797 mSeqHeader.seqForceIntegerMv = 2; 798 } 799 if (enableOrderHint == 1) { 800 int orderHintBitsMinus1 = bitArray.readBits(3); 801 mSeqHeader.orderHintBits = orderHintBitsMinus1 + 1; 802 } else { 803 mSeqHeader.orderHintBits = 0; 804 } 805 } 806 bitArray.readBits(1); // enable super res 807 bitArray.readBits(1); // enable cdef 808 bitArray.readBits(1); // enable restoration 809 mSeqHeader.enableHighBitDepth = bitArray.readBits(1); 810 } 811 parseFrameHeader(ObuParsableBitArray bitArray, int temporalId, int spatialId)812 private FrameHeaderObu parseFrameHeader(ObuParsableBitArray bitArray, int temporalId, 813 int spatialId) { 814 FrameHeaderObu frameHeader = new FrameHeaderObu(); 815 int idLen = 0; 816 if (mSeqHeader.frameIdNumbersPresentFlag == 1) { 817 idLen = mSeqHeader.additionalFrameIdLengthMinus1 818 + mSeqHeader.deltaFrameIdLengthMinus2 + 3; 819 } 820 int allFrames = (1 << NUM_REF_FRAMES) - 1; 821 int refreshFrameFlags = 0; 822 int frameIsIntra; 823 if (mSeqHeader.reducedStillPictureHeader == 1) { 824 frameHeader.frameType = OBP_KEY_FRAME; 825 frameIsIntra = 1; 826 frameHeader.showFrame = 1; 827 } else { 828 frameHeader.showExistingFrame = bitArray.readBits(1); 829 if (frameHeader.showExistingFrame == 1) { 830 int frameToShowMapIdx = bitArray.readBits(3); 831 if (mSeqHeader.decoderModelInfoPresentFlag == 1 832 && mSeqHeader.equalPictureInterval == 0) { 833 int n = mSeqHeader.framePresentationTimeLengthMinus1 + 1; 834 bitArray.readBits(n); // frame_presentation_time 835 } 836 if (mSeqHeader.frameIdNumbersPresentFlag == 1) { 837 bitArray.readBits(idLen); // display_frame_id 838 } 839 frameHeader.frameType = mRefFrameType[frameToShowMapIdx]; 840 if (frameHeader.frameType == OBP_KEY_FRAME) { 841 refreshFrameFlags = allFrames; 842 } 843 return frameHeader; 844 } 845 frameHeader.frameType = bitArray.readBits(2); 846 frameIsIntra = (frameHeader.frameType == OBP_INTRA_ONLY_FRAME 847 || frameHeader.frameType == OBP_KEY_FRAME) ? 1 : 0; 848 frameHeader.showFrame = bitArray.readBits(1); 849 if (frameHeader.showFrame == 1 && mSeqHeader.decoderModelInfoPresentFlag == 1 850 && mSeqHeader.equalPictureInterval == 0) { 851 int n = mSeqHeader.framePresentationTimeLengthMinus1 + 1; 852 bitArray.readBits(n); // frame_presentation_time 853 } 854 if (frameHeader.showFrame == 0) { 855 bitArray.readBits(1); // showable_frame 856 } 857 if (frameHeader.frameType == OBP_SWITCH_FRAME || ( 858 frameHeader.frameType == OBP_KEY_FRAME && frameHeader.showFrame == 1)) { 859 frameHeader.errorResilientMode = 1; 860 } else { 861 frameHeader.errorResilientMode = bitArray.readBits(1); 862 } 863 } 864 bitArray.readBits(1); // disable_cdf_update 865 int allowScreenContentTools; 866 if (mSeqHeader.seqForceScreenContentTools == 2) { 867 allowScreenContentTools = bitArray.readBits(1); 868 } else { 869 allowScreenContentTools = mSeqHeader.seqForceScreenContentTools; 870 } 871 if (allowScreenContentTools == 1 && mSeqHeader.seqForceIntegerMv == 2) { 872 bitArray.readBits(1); // force_integer_mv 873 } 874 if (mSeqHeader.frameIdNumbersPresentFlag == 1) { 875 bitArray.readBits(idLen); // current_frame_id 876 } 877 if (frameHeader.frameType != OBP_SWITCH_FRAME 878 && mSeqHeader.reducedStillPictureHeader == 0) { 879 bitArray.readBits(1); // frame_size_override_flag 880 } 881 bitArray.readBits(mSeqHeader.orderHintBits); // order_hint 882 if (frameIsIntra != 1 && frameHeader.errorResilientMode == 0) { 883 bitArray.readBits(3); // primary_ref_frame 884 } 885 886 if (mSeqHeader.decoderModelInfoPresentFlag == 1) { 887 int bufferRemovalTimePresentFlag = bitArray.readBits(1); 888 if (bufferRemovalTimePresentFlag == 1) { 889 for (int i = 0; i <= mSeqHeader.operatingPointsCntMinus1; i++) { 890 if (mSeqHeader.decoderModelPresentForThisOp[i] == 1) { 891 int opPtIdc = mSeqHeader.operatingPointIdc[i]; 892 boolean inTemporalLayer = ((opPtIdc >> temporalId) & 1) == 1; 893 boolean inSpatialLayer = ((opPtIdc >> (spatialId + 8)) & 1) == 1; 894 if (opPtIdc == 0 || (inTemporalLayer && inSpatialLayer)) { 895 int n = mSeqHeader.bufferRemovalTimeLengthMinus1 + 1; 896 bitArray.readBits(n); // buffer_removal_time 897 } 898 } 899 } 900 } 901 } 902 903 if (frameHeader.frameType == OBP_SWITCH_FRAME || (frameHeader.frameType == OBP_KEY_FRAME 904 && frameHeader.showFrame == 1)) { 905 refreshFrameFlags = allFrames; 906 } else { 907 refreshFrameFlags = bitArray.readBits(8); 908 } 909 910 for (int i = 0; i < 8; i++) { 911 if ((refreshFrameFlags >> i & 1) == 1) { 912 mRefFrameType[i] = frameHeader.frameType; 913 } 914 } 915 return frameHeader; 916 } 917 918 // parse av1 codec configuration record getProfileLevelFromCSD()919 private Pair<Integer, Integer> getProfileLevelFromCSD() { 920 int profile = -1; 921 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 922 Assert.assertEquals(1, bitArray.readBits(1)); // marker 923 Assert.assertEquals(1, bitArray.readBits(7)); // version 924 int seqProfile = bitArray.readBits(3); 925 int seqLevelIdx0 = bitArray.readBits(5); 926 bitArray.readBits(1); // seqTier0 927 int highBitDepth = bitArray.readBits(1); 928 bitArray.readBits(1); // is input 12 bit; 929 if (seqProfile == 0) { 930 profile = highBitDepth == 0 ? AV1ProfileMain8 : AV1ProfileMain10; 931 } 932 933 int level = AV1Level2 << seqLevelIdx0; 934 return plToPair(profile, level); 935 } 936 937 // parse av1 sequence header getProfileLevelFromSeqHeader()938 private Pair<Integer, Integer> getProfileLevelFromSeqHeader() { 939 for (int pos = mOffset; pos < mLimit; ) { 940 ObuInfo obuDetails = parseObuHeader(mData, pos, mLimit); 941 ObuParsableBitArray bitArray = 942 new ObuParsableBitArray(mData, pos + obuDetails.getObuDataOffset(), 943 pos + obuDetails.getTotalObuSize()); 944 if (obuDetails.mObuType == OBU_SEQUENCE_HEADER) { 945 int profile = -1; 946 parseSequenceHeader(bitArray); 947 if (mSeqHeader.seqProfile == 0) { 948 profile = mSeqHeader.enableHighBitDepth == 0 ? AV1ProfileMain8 : 949 AV1ProfileMain10; 950 } 951 952 int level = AV1Level2 << mSeqHeader.seqLevelIdx[0]; 953 return plToPair(profile, level); 954 } 955 pos += obuDetails.getTotalObuSize(); 956 } 957 return null; 958 } 959 960 @Override getFrameType()961 public int getFrameType() { 962 ArrayList<FrameHeaderObu> headers = new ArrayList<>(); 963 for (int pos = mOffset; pos < mLimit; ) { 964 ObuInfo obuDetails = parseObuHeader(mData, pos, mLimit); 965 ObuParsableBitArray bitArray = 966 new ObuParsableBitArray(mData, pos + obuDetails.getObuDataOffset(), 967 pos + obuDetails.getTotalObuSize()); 968 if (obuDetails.mObuType == OBU_SEQUENCE_HEADER) { 969 parseSequenceHeader(bitArray); 970 } else if (obuDetails.mObuType == OBU_FRAME_HEADER 971 || obuDetails.mObuType == OBU_FRAME) { 972 FrameHeaderObu frameHeader = parseFrameHeader(bitArray, obuDetails.mTemporalId, 973 obuDetails.mSpatialId); 974 headers.add(frameHeader); 975 } 976 pos += obuDetails.getTotalObuSize(); 977 } 978 for (FrameHeaderObu frameHeader : headers) { 979 if (frameHeader.showFrame == 1 || frameHeader.showExistingFrame == 1) { 980 if (frameHeader.frameType == OBP_KEY_FRAME 981 || frameHeader.frameType == OBP_INTRA_ONLY_FRAME) { 982 return PICTURE_TYPE_I; 983 } else if (frameHeader.frameType == OBP_INTER_FRAME) { 984 return PICTURE_TYPE_P; 985 } 986 return PICTURE_TYPE_UNKNOWN; 987 } 988 } 989 return PICTURE_TYPE_UNKNOWN; 990 } 991 992 @Override getProfileLevel(boolean isCsd)993 public Pair<Integer, Integer> getProfileLevel(boolean isCsd) { 994 return isCsd ? getProfileLevelFromCSD() : getProfileLevelFromSeqHeader(); 995 } 996 } 997 998 static class AacParser extends ParserBase { 999 @Override getFrameType()1000 public int getFrameType() { 1001 return PICTURE_TYPE_UNKNOWN; 1002 } 1003 1004 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)1005 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 1006 // parse AudioSpecificConfig() of ISO 14496 Part 3 1007 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 1008 int audioObjectType = bitArray.readBits(5); 1009 if (audioObjectType == 31) { 1010 audioObjectType = 32 + bitArray.readBits(6); // audio object type ext 1011 } 1012 return plToPair(audioObjectType, -1); 1013 } 1014 } 1015 1016 static class ApvParser extends ParserBase { 1017 private static final Map<Integer, Integer> PROFILE_MAP = Map.ofEntries( 1018 Map.entry(33, APVProfile422_10)); 1019 getApvLevel(int level, int band)1020 private int getApvLevel(int level, int band) { 1021 switch (level) { 1022 case 30: 1023 switch (band) { 1024 case 0: 1025 return APVLevel1Band0; 1026 case 1: 1027 return APVLevel1Band1; 1028 case 2: 1029 return APVLevel1Band2; 1030 case 3: 1031 return APVLevel1Band3; 1032 } 1033 break; 1034 case 33: 1035 switch (band) { 1036 case 0: 1037 return APVLevel11Band0; 1038 case 1: 1039 return APVLevel11Band1; 1040 case 2: 1041 return APVLevel11Band2; 1042 case 3: 1043 return APVLevel11Band3; 1044 } 1045 break; 1046 case 60: 1047 switch (band) { 1048 case 0: 1049 return APVLevel2Band0; 1050 case 1: 1051 return APVLevel2Band1; 1052 case 2: 1053 return APVLevel2Band2; 1054 case 3: 1055 return APVLevel2Band3; 1056 } 1057 break; 1058 case 63: 1059 switch (band) { 1060 case 0: 1061 return APVLevel21Band0; 1062 case 1: 1063 return APVLevel21Band1; 1064 case 2: 1065 return APVLevel21Band2; 1066 case 3: 1067 return APVLevel21Band3; 1068 } 1069 break; 1070 case 90: 1071 switch (band) { 1072 case 0: 1073 return APVLevel3Band0; 1074 case 1: 1075 return APVLevel3Band1; 1076 case 2: 1077 return APVLevel3Band2; 1078 case 3: 1079 return APVLevel3Band3; 1080 } 1081 break; 1082 case 93: 1083 switch (band) { 1084 case 0: 1085 return APVLevel31Band0; 1086 case 1: 1087 return APVLevel31Band1; 1088 case 2: 1089 return APVLevel31Band2; 1090 case 3: 1091 return APVLevel31Band3; 1092 } 1093 break; 1094 case 120: 1095 switch (band) { 1096 case 0: 1097 return APVLevel4Band0; 1098 case 1: 1099 return APVLevel4Band1; 1100 case 2: 1101 return APVLevel4Band2; 1102 case 3: 1103 return APVLevel4Band3; 1104 } 1105 break; 1106 case 123: 1107 switch (band) { 1108 case 0: 1109 return APVLevel41Band0; 1110 case 1: 1111 return APVLevel41Band1; 1112 case 2: 1113 return APVLevel41Band2; 1114 case 3: 1115 return APVLevel41Band3; 1116 } 1117 break; 1118 case 150: 1119 switch (band) { 1120 case 0: 1121 return APVLevel5Band0; 1122 case 1: 1123 return APVLevel5Band1; 1124 case 2: 1125 return APVLevel5Band2; 1126 case 3: 1127 return APVLevel5Band3; 1128 } 1129 break; 1130 case 153: 1131 switch (band) { 1132 case 0: 1133 return APVLevel51Band0; 1134 case 1: 1135 return APVLevel51Band1; 1136 case 2: 1137 return APVLevel51Band2; 1138 case 3: 1139 return APVLevel51Band3; 1140 } 1141 break; 1142 case 180: 1143 switch (band) { 1144 case 0: 1145 return APVLevel6Band0; 1146 case 1: 1147 return APVLevel6Band1; 1148 case 2: 1149 return APVLevel6Band2; 1150 case 3: 1151 return APVLevel6Band3; 1152 } 1153 break; 1154 case 183: 1155 switch (band) { 1156 case 0: 1157 return APVLevel61Band0; 1158 case 1: 1159 return APVLevel61Band1; 1160 case 2: 1161 return APVLevel61Band2; 1162 case 3: 1163 return APVLevel61Band3; 1164 } 1165 break; 1166 case 210: 1167 switch (band) { 1168 case 0: 1169 return APVLevel7Band0; 1170 case 1: 1171 return APVLevel7Band1; 1172 case 2: 1173 return APVLevel7Band2; 1174 case 3: 1175 return APVLevel7Band3; 1176 } 1177 break; 1178 case 213: 1179 switch (band) { 1180 case 0: 1181 return APVLevel71Band0; 1182 case 1: 1183 return APVLevel71Band1; 1184 case 2: 1185 return APVLevel71Band2; 1186 case 3: 1187 return APVLevel71Band3; 1188 } 1189 break; 1190 } 1191 return APVLevel71Band3; 1192 } 1193 1194 @Override getFrameType()1195 public int getFrameType() { 1196 return PICTURE_TYPE_UNKNOWN; 1197 } 1198 1199 @Override getProfileLevel(@uppressWarnings"unused") boolean isCsd)1200 public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) { 1201 ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit); 1202 Assert.assertEquals(1, bitArray.readBits(8)); // configuration version 1203 int numConfigEntry = bitArray.readBits(8); 1204 1205 for (int i = 0; i < numConfigEntry; i++) { 1206 bitArray.readBits(8); // pbu_type 1207 int numFrameInfo = bitArray.readBits(8); 1208 for (int j = 0; j < numFrameInfo; j++) { 1209 bitArray.readBits(6); // reserved zero bits 1210 bitArray.readBits(1); // color description present flag 1211 bitArray.readBits(1); // capture time distance ignored 1212 int profile = bitArray.readBits(8); 1213 int level = bitArray.readBits(8); 1214 int band = bitArray.readBits(8); 1215 return plToPair(getHashMapVal(PROFILE_MAP, profile), getApvLevel(level, band)); 1216 } 1217 } 1218 return null; 1219 } 1220 } 1221 getParserObject(String mediaType)1222 public static ParserBase getParserObject(String mediaType) { 1223 switch (mediaType) { 1224 case MediaFormat.MIMETYPE_VIDEO_MPEG4: 1225 return new Mpeg4Parser(); 1226 case MediaFormat.MIMETYPE_VIDEO_H263: 1227 return new H263Parser(); 1228 case MediaFormat.MIMETYPE_VIDEO_AVC: 1229 return new AvcParser(); 1230 case MediaFormat.MIMETYPE_VIDEO_HEVC: 1231 return new HevcParser(); 1232 case MediaFormat.MIMETYPE_VIDEO_AV1: 1233 return new Av1Parser(); 1234 case MediaFormat.MIMETYPE_VIDEO_VP9: 1235 return new Vp9Parser(); 1236 case MediaFormat.MIMETYPE_AUDIO_AAC: 1237 return new AacParser(); 1238 case MediaFormat.MIMETYPE_VIDEO_APV: 1239 return new ApvParser(); 1240 } 1241 return null; 1242 } 1243 1244 @TargetApi(Build.VERSION_CODES.TIRAMISU) getFrameTypeFromBitStream(ByteBuffer buf, MediaCodec.BufferInfo info, ParserBase o)1245 public static int getFrameTypeFromBitStream(ByteBuffer buf, MediaCodec.BufferInfo info, 1246 ParserBase o) { 1247 if (o == null) return PICTURE_TYPE_UNKNOWN; 1248 byte[] dataArray = new byte[info.size]; 1249 buf.position(info.offset); 1250 buf.get(dataArray); 1251 o.set(dataArray, 0, info.size); 1252 return o.getFrameType(); 1253 } 1254 getProfileLevelFromBitStream(ByteBuffer buf, MediaCodec.BufferInfo info, ParserBase o)1255 public static Pair<Integer, Integer> getProfileLevelFromBitStream(ByteBuffer buf, 1256 MediaCodec.BufferInfo info, ParserBase o) { 1257 if (o == null) return null; 1258 byte[] dataArray = new byte[info.size]; 1259 buf.position(info.offset); 1260 buf.get(dataArray); 1261 o.set(dataArray, 0, info.size); 1262 return o.getProfileLevel((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0); 1263 } 1264 } 1265