1 /* 2 * Copyright (C) 2016 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 package com.google.android.exoplayer2.audio; 17 18 import androidx.annotation.IntDef; 19 import androidx.annotation.Nullable; 20 import com.google.android.exoplayer2.C; 21 import com.google.android.exoplayer2.Format; 22 import com.google.android.exoplayer2.audio.Ac3Util.SyncFrameInfo.StreamType; 23 import com.google.android.exoplayer2.drm.DrmInitData; 24 import com.google.android.exoplayer2.util.MimeTypes; 25 import com.google.android.exoplayer2.util.ParsableBitArray; 26 import com.google.android.exoplayer2.util.ParsableByteArray; 27 import com.google.android.exoplayer2.util.Util; 28 import java.lang.annotation.Documented; 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.nio.ByteBuffer; 32 33 /** 34 * Utility methods for parsing Dolby TrueHD and (E-)AC-3 syncframes. (E-)AC-3 parsing follows the 35 * definition in ETSI TS 102 366 V1.4.1. 36 */ 37 public final class Ac3Util { 38 39 /** Holds sample format information as presented by a syncframe header. */ 40 public static final class SyncFrameInfo { 41 42 /** 43 * AC3 stream types. See also E.1.3.1.1. One of {@link #STREAM_TYPE_UNDEFINED}, {@link 44 * #STREAM_TYPE_TYPE0}, {@link #STREAM_TYPE_TYPE1} or {@link #STREAM_TYPE_TYPE2}. 45 */ 46 @Documented 47 @Retention(RetentionPolicy.SOURCE) 48 @IntDef({STREAM_TYPE_UNDEFINED, STREAM_TYPE_TYPE0, STREAM_TYPE_TYPE1, STREAM_TYPE_TYPE2}) 49 public @interface StreamType {} 50 /** Undefined AC3 stream type. */ 51 public static final int STREAM_TYPE_UNDEFINED = -1; 52 /** Type 0 AC3 stream type. */ 53 public static final int STREAM_TYPE_TYPE0 = 0; 54 /** Type 1 AC3 stream type. */ 55 public static final int STREAM_TYPE_TYPE1 = 1; 56 /** Type 2 AC3 stream type. */ 57 public static final int STREAM_TYPE_TYPE2 = 2; 58 59 /** 60 * The sample mime type of the bitstream. One of {@link MimeTypes#AUDIO_AC3} and {@link 61 * MimeTypes#AUDIO_E_AC3}. 62 */ 63 @Nullable public final String mimeType; 64 /** 65 * The type of the stream if {@link #mimeType} is {@link MimeTypes#AUDIO_E_AC3}, or {@link 66 * #STREAM_TYPE_UNDEFINED} otherwise. 67 */ 68 public final @StreamType int streamType; 69 /** 70 * The audio sampling rate in Hz. 71 */ 72 public final int sampleRate; 73 /** 74 * The number of audio channels 75 */ 76 public final int channelCount; 77 /** 78 * The size of the frame. 79 */ 80 public final int frameSize; 81 /** 82 * Number of audio samples in the frame. 83 */ 84 public final int sampleCount; 85 SyncFrameInfo( @ullable String mimeType, @StreamType int streamType, int channelCount, int sampleRate, int frameSize, int sampleCount)86 private SyncFrameInfo( 87 @Nullable String mimeType, 88 @StreamType int streamType, 89 int channelCount, 90 int sampleRate, 91 int frameSize, 92 int sampleCount) { 93 this.mimeType = mimeType; 94 this.streamType = streamType; 95 this.channelCount = channelCount; 96 this.sampleRate = sampleRate; 97 this.frameSize = frameSize; 98 this.sampleCount = sampleCount; 99 } 100 101 } 102 103 /** Maximum rate for an AC-3 audio stream, in bytes per second. */ 104 public static final int AC3_MAX_RATE_BYTES_PER_SECOND = 640 * 1000 / 8; 105 /** Maximum rate for an E-AC-3 audio stream, in bytes per second. */ 106 public static final int E_AC3_MAX_RATE_BYTES_PER_SECOND = 6144 * 1000 / 8; 107 /** Maximum rate for a TrueHD audio stream, in bytes per second. */ 108 public static final int TRUEHD_MAX_RATE_BYTES_PER_SECOND = 24500 * 1000 / 8; 109 110 /** 111 * The number of samples to store in each output chunk when rechunking TrueHD streams. The number 112 * of samples extracted from the container corresponding to one syncframe must be an integer 113 * multiple of this value. 114 */ 115 public static final int TRUEHD_RECHUNK_SAMPLE_COUNT = 16; 116 /** 117 * The number of bytes that must be parsed from a TrueHD syncframe to calculate the sample count. 118 */ 119 public static final int TRUEHD_SYNCFRAME_PREFIX_LENGTH = 10; 120 121 /** 122 * The number of new samples per (E-)AC-3 audio block. 123 */ 124 private static final int AUDIO_SAMPLES_PER_AUDIO_BLOCK = 256; 125 /** Each syncframe has 6 blocks that provide 256 new audio samples. See subsection 4.1. */ 126 private static final int AC3_SYNCFRAME_AUDIO_SAMPLE_COUNT = 6 * AUDIO_SAMPLES_PER_AUDIO_BLOCK; 127 /** 128 * Number of audio blocks per E-AC-3 syncframe, indexed by numblkscod. 129 */ 130 private static final int[] BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD = new int[] {1, 2, 3, 6}; 131 /** 132 * Sample rates, indexed by fscod. 133 */ 134 private static final int[] SAMPLE_RATE_BY_FSCOD = new int[] {48000, 44100, 32000}; 135 /** 136 * Sample rates, indexed by fscod2 (E-AC-3). 137 */ 138 private static final int[] SAMPLE_RATE_BY_FSCOD2 = new int[] {24000, 22050, 16000}; 139 /** 140 * Channel counts, indexed by acmod. 141 */ 142 private static final int[] CHANNEL_COUNT_BY_ACMOD = new int[] {2, 1, 2, 3, 3, 4, 4, 5}; 143 /** Nominal bitrates in kbps, indexed by frmsizecod / 2. (See table 4.13.) */ 144 private static final int[] BITRATE_BY_HALF_FRMSIZECOD = 145 new int[] { 146 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640 147 }; 148 /** 16-bit words per syncframe, indexed by frmsizecod / 2. (See table 4.13.) */ 149 private static final int[] SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1 = 150 new int[] { 151 69, 87, 104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 152 1393 153 }; 154 155 /** 156 * Returns the AC-3 format given {@code data} containing the AC3SpecificBox according to Annex F. 157 * The reading position of {@code data} will be modified. 158 * 159 * @param data The AC3SpecificBox to parse. 160 * @param trackId The track identifier to set on the format. 161 * @param language The language to set on the format. 162 * @param drmInitData {@link DrmInitData} to be included in the format. 163 * @return The AC-3 format parsed from data in the header. 164 */ parseAc3AnnexFFormat( ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData)165 public static Format parseAc3AnnexFFormat( 166 ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) { 167 int fscod = (data.readUnsignedByte() & 0xC0) >> 6; 168 int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; 169 int nextByte = data.readUnsignedByte(); 170 int channelCount = CHANNEL_COUNT_BY_ACMOD[(nextByte & 0x38) >> 3]; 171 if ((nextByte & 0x04) != 0) { // lfeon 172 channelCount++; 173 } 174 return new Format.Builder() 175 .setId(trackId) 176 .setSampleMimeType(MimeTypes.AUDIO_AC3) 177 .setChannelCount(channelCount) 178 .setSampleRate(sampleRate) 179 .setDrmInitData(drmInitData) 180 .setLanguage(language) 181 .build(); 182 } 183 184 /** 185 * Returns the E-AC-3 format given {@code data} containing the EC3SpecificBox according to Annex 186 * F. The reading position of {@code data} will be modified. 187 * 188 * @param data The EC3SpecificBox to parse. 189 * @param trackId The track identifier to set on the format. 190 * @param language The language to set on the format. 191 * @param drmInitData {@link DrmInitData} to be included in the format. 192 * @return The E-AC-3 format parsed from data in the header. 193 */ parseEAc3AnnexFFormat( ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData)194 public static Format parseEAc3AnnexFFormat( 195 ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) { 196 data.skipBytes(2); // data_rate, num_ind_sub 197 198 // Read the first independent substream. 199 int fscod = (data.readUnsignedByte() & 0xC0) >> 6; 200 int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; 201 int nextByte = data.readUnsignedByte(); 202 int channelCount = CHANNEL_COUNT_BY_ACMOD[(nextByte & 0x0E) >> 1]; 203 if ((nextByte & 0x01) != 0) { // lfeon 204 channelCount++; 205 } 206 207 // Read the first dependent substream. 208 nextByte = data.readUnsignedByte(); 209 int numDepSub = ((nextByte & 0x1E) >> 1); 210 if (numDepSub > 0) { 211 int lowByteChanLoc = data.readUnsignedByte(); 212 // Read Lrs/Rrs pair 213 // TODO: Read other channel configuration 214 if ((lowByteChanLoc & 0x02) != 0) { 215 channelCount += 2; 216 } 217 } 218 String mimeType = MimeTypes.AUDIO_E_AC3; 219 if (data.bytesLeft() > 0) { 220 nextByte = data.readUnsignedByte(); 221 if ((nextByte & 0x01) != 0) { // flag_ec3_extension_type_a 222 mimeType = MimeTypes.AUDIO_E_AC3_JOC; 223 } 224 } 225 return new Format.Builder() 226 .setId(trackId) 227 .setSampleMimeType(mimeType) 228 .setChannelCount(channelCount) 229 .setSampleRate(sampleRate) 230 .setDrmInitData(drmInitData) 231 .setLanguage(language) 232 .build(); 233 } 234 235 /** 236 * Returns (E-)AC-3 format information given {@code data} containing a syncframe. The reading 237 * position of {@code data} will be modified. 238 * 239 * @param data The data to parse, positioned at the start of the syncframe. 240 * @return The (E-)AC-3 format data parsed from the header. 241 */ parseAc3SyncframeInfo(ParsableBitArray data)242 public static SyncFrameInfo parseAc3SyncframeInfo(ParsableBitArray data) { 243 int initialPosition = data.getPosition(); 244 data.skipBits(40); 245 // Parse the bitstream ID for AC-3 and E-AC-3 (see subsections 4.3, E.1.2 and E.1.3.1.6). 246 boolean isEac3 = data.readBits(5) > 10; 247 data.setPosition(initialPosition); 248 @Nullable String mimeType; 249 @StreamType int streamType = SyncFrameInfo.STREAM_TYPE_UNDEFINED; 250 int sampleRate; 251 int acmod; 252 int frameSize; 253 int sampleCount; 254 boolean lfeon; 255 int channelCount; 256 if (isEac3) { 257 // Subsection E.1.2. 258 data.skipBits(16); // syncword 259 switch (data.readBits(2)) { // strmtyp 260 case 0: 261 streamType = SyncFrameInfo.STREAM_TYPE_TYPE0; 262 break; 263 case 1: 264 streamType = SyncFrameInfo.STREAM_TYPE_TYPE1; 265 break; 266 case 2: 267 streamType = SyncFrameInfo.STREAM_TYPE_TYPE2; 268 break; 269 default: 270 streamType = SyncFrameInfo.STREAM_TYPE_UNDEFINED; 271 break; 272 } 273 data.skipBits(3); // substreamid 274 frameSize = (data.readBits(11) + 1) * 2; // See frmsiz in subsection E.1.3.1.3. 275 int fscod = data.readBits(2); 276 int audioBlocks; 277 int numblkscod; 278 if (fscod == 3) { 279 numblkscod = 3; 280 sampleRate = SAMPLE_RATE_BY_FSCOD2[data.readBits(2)]; 281 audioBlocks = 6; 282 } else { 283 numblkscod = data.readBits(2); 284 audioBlocks = BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD[numblkscod]; 285 sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; 286 } 287 sampleCount = AUDIO_SAMPLES_PER_AUDIO_BLOCK * audioBlocks; 288 acmod = data.readBits(3); 289 lfeon = data.readBit(); 290 channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0); 291 data.skipBits(5 + 5); // bsid, dialnorm 292 if (data.readBit()) { // compre 293 data.skipBits(8); // compr 294 } 295 if (acmod == 0) { 296 data.skipBits(5); // dialnorm2 297 if (data.readBit()) { // compr2e 298 data.skipBits(8); // compr2 299 } 300 } 301 if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE1 && data.readBit()) { // chanmape 302 data.skipBits(16); // chanmap 303 } 304 if (data.readBit()) { // mixmdate 305 if (acmod > 2) { 306 data.skipBits(2); // dmixmod 307 } 308 if ((acmod & 0x01) != 0 && acmod > 2) { 309 data.skipBits(3 + 3); // ltrtcmixlev, lorocmixlev 310 } 311 if ((acmod & 0x04) != 0) { 312 data.skipBits(6); // ltrtsurmixlev, lorosurmixlev 313 } 314 if (lfeon && data.readBit()) { // lfemixlevcode 315 data.skipBits(5); // lfemixlevcod 316 } 317 if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE0) { 318 if (data.readBit()) { // pgmscle 319 data.skipBits(6); //pgmscl 320 } 321 if (acmod == 0 && data.readBit()) { // pgmscl2e 322 data.skipBits(6); // pgmscl2 323 } 324 if (data.readBit()) { // extpgmscle 325 data.skipBits(6); // extpgmscl 326 } 327 int mixdef = data.readBits(2); 328 if (mixdef == 1) { 329 data.skipBits(1 + 1 + 3); // premixcmpsel, drcsrc, premixcmpscl 330 } else if (mixdef == 2) { 331 data.skipBits(12); // mixdata 332 } else if (mixdef == 3) { 333 int mixdeflen = data.readBits(5); 334 if (data.readBit()) { // mixdata2e 335 data.skipBits(1 + 1 + 3); // premixcmpsel, drcsrc, premixcmpscl 336 if (data.readBit()) { // extpgmlscle 337 data.skipBits(4); // extpgmlscl 338 } 339 if (data.readBit()) { // extpgmcscle 340 data.skipBits(4); // extpgmcscl 341 } 342 if (data.readBit()) { // extpgmrscle 343 data.skipBits(4); // extpgmrscl 344 } 345 if (data.readBit()) { // extpgmlsscle 346 data.skipBits(4); // extpgmlsscl 347 } 348 if (data.readBit()) { // extpgmrsscle 349 data.skipBits(4); // extpgmrsscl 350 } 351 if (data.readBit()) { // extpgmlfescle 352 data.skipBits(4); // extpgmlfescl 353 } 354 if (data.readBit()) { // dmixscle 355 data.skipBits(4); // dmixscl 356 } 357 if (data.readBit()) { // addche 358 if (data.readBit()) { // extpgmaux1scle 359 data.skipBits(4); // extpgmaux1scl 360 } 361 if (data.readBit()) { // extpgmaux2scle 362 data.skipBits(4); // extpgmaux2scl 363 } 364 } 365 } 366 if (data.readBit()) { // mixdata3e 367 data.skipBits(5); // spchdat 368 if (data.readBit()) { // addspchdate 369 data.skipBits(5 + 2); // spchdat1, spchan1att 370 if (data.readBit()) { // addspdat1e 371 data.skipBits(5 + 3); // spchdat2, spchan2att 372 } 373 } 374 } 375 data.skipBits(8 * (mixdeflen + 2)); // mixdata 376 data.byteAlign(); // mixdatafill 377 } 378 if (acmod < 2) { 379 if (data.readBit()) { // paninfoe 380 data.skipBits(8 + 6); // panmean, paninfo 381 } 382 if (acmod == 0) { 383 if (data.readBit()) { // paninfo2e 384 data.skipBits(8 + 6); // panmean2, paninfo2 385 } 386 } 387 } 388 if (data.readBit()) { // frmmixcfginfoe 389 if (numblkscod == 0) { 390 data.skipBits(5); // blkmixcfginfo[0] 391 } else { 392 for (int blk = 0; blk < audioBlocks; blk++) { 393 if (data.readBit()) { // blkmixcfginfoe 394 data.skipBits(5); // blkmixcfginfo[blk] 395 } 396 } 397 } 398 } 399 } 400 } 401 if (data.readBit()) { // infomdate 402 data.skipBits(3 + 1 + 1); // bsmod, copyrightb, origbs 403 if (acmod == 2) { 404 data.skipBits(2 + 2); // dsurmod, dheadphonmod 405 } 406 if (acmod >= 6) { 407 data.skipBits(2); // dsurexmod 408 } 409 if (data.readBit()) { // audioprodie 410 data.skipBits(5 + 2 + 1); // mixlevel, roomtyp, adconvtyp 411 } 412 if (acmod == 0 && data.readBit()) { // audioprodi2e 413 data.skipBits(5 + 2 + 1); // mixlevel2, roomtyp2, adconvtyp2 414 } 415 if (fscod < 3) { 416 data.skipBit(); // sourcefscod 417 } 418 } 419 if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE0 && numblkscod != 3) { 420 data.skipBit(); // convsync 421 } 422 if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE2 423 && (numblkscod == 3 || data.readBit())) { // blkid 424 data.skipBits(6); // frmsizecod 425 } 426 mimeType = MimeTypes.AUDIO_E_AC3; 427 if (data.readBit()) { // addbsie 428 int addbsil = data.readBits(6); 429 if (addbsil == 1 && data.readBits(8) == 1) { // addbsi 430 mimeType = MimeTypes.AUDIO_E_AC3_JOC; 431 } 432 } 433 } else /* is AC-3 */ { 434 mimeType = MimeTypes.AUDIO_AC3; 435 data.skipBits(16 + 16); // syncword, crc1 436 int fscod = data.readBits(2); 437 if (fscod == 3) { 438 // fscod '11' indicates that the decoder should not attempt to decode audio. We invalidate 439 // the mime type to prevent association with a renderer. 440 mimeType = null; 441 } 442 int frmsizecod = data.readBits(6); 443 frameSize = getAc3SyncframeSize(fscod, frmsizecod); 444 data.skipBits(5 + 3); // bsid, bsmod 445 acmod = data.readBits(3); 446 if ((acmod & 0x01) != 0 && acmod != 1) { 447 data.skipBits(2); // cmixlev 448 } 449 if ((acmod & 0x04) != 0) { 450 data.skipBits(2); // surmixlev 451 } 452 if (acmod == 2) { 453 data.skipBits(2); // dsurmod 454 } 455 sampleRate = 456 fscod < SAMPLE_RATE_BY_FSCOD.length ? SAMPLE_RATE_BY_FSCOD[fscod] : Format.NO_VALUE; 457 sampleCount = AC3_SYNCFRAME_AUDIO_SAMPLE_COUNT; 458 lfeon = data.readBit(); 459 channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0); 460 } 461 return new SyncFrameInfo( 462 mimeType, streamType, channelCount, sampleRate, frameSize, sampleCount); 463 } 464 465 /** 466 * Returns the size in bytes of the given (E-)AC-3 syncframe. 467 * 468 * @param data The syncframe to parse. 469 * @return The syncframe size in bytes. {@link C#LENGTH_UNSET} if the input is invalid. 470 */ 471 public static int parseAc3SyncframeSize(byte[] data) { 472 if (data.length < 6) { 473 return C.LENGTH_UNSET; 474 } 475 // Parse the bitstream ID for AC-3 and E-AC-3 (see subsections 4.3, E.1.2 and E.1.3.1.6). 476 boolean isEac3 = ((data[5] & 0xF8) >> 3) > 10; 477 if (isEac3) { 478 int frmsiz = (data[2] & 0x07) << 8; // Most significant 3 bits. 479 frmsiz |= data[3] & 0xFF; // Least significant 8 bits. 480 return (frmsiz + 1) * 2; // See frmsiz in subsection E.1.3.1.3. 481 } else { 482 int fscod = (data[4] & 0xC0) >> 6; 483 int frmsizecod = data[4] & 0x3F; 484 return getAc3SyncframeSize(fscod, frmsizecod); 485 } 486 } 487 488 /** 489 * Reads the number of audio samples represented by the given (E-)AC-3 syncframe. The buffer's 490 * position is not modified. 491 * 492 * @param buffer The {@link ByteBuffer} from which to read the syncframe. 493 * @return The number of audio samples represented by the syncframe. 494 */ parseAc3SyncframeAudioSampleCount(ByteBuffer buffer)495 public static int parseAc3SyncframeAudioSampleCount(ByteBuffer buffer) { 496 // Parse the bitstream ID for AC-3 and E-AC-3 (see subsections 4.3, E.1.2 and E.1.3.1.6). 497 boolean isEac3 = ((buffer.get(buffer.position() + 5) & 0xF8) >> 3) > 10; 498 if (isEac3) { 499 int fscod = (buffer.get(buffer.position() + 4) & 0xC0) >> 6; 500 int numblkscod = fscod == 0x03 ? 3 : (buffer.get(buffer.position() + 4) & 0x30) >> 4; 501 return BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD[numblkscod] * AUDIO_SAMPLES_PER_AUDIO_BLOCK; 502 } else { 503 return AC3_SYNCFRAME_AUDIO_SAMPLE_COUNT; 504 } 505 } 506 507 /** 508 * Returns the offset relative to the buffer's position of the start of a TrueHD syncframe, or 509 * {@link C#INDEX_UNSET} if no syncframe was found. The buffer's position is not modified. 510 * 511 * @param buffer The {@link ByteBuffer} within which to find a syncframe. 512 * @return The offset relative to the buffer's position of the start of a TrueHD syncframe, or 513 * {@link C#INDEX_UNSET} if no syncframe was found. 514 */ findTrueHdSyncframeOffset(ByteBuffer buffer)515 public static int findTrueHdSyncframeOffset(ByteBuffer buffer) { 516 int startIndex = buffer.position(); 517 int endIndex = buffer.limit() - TRUEHD_SYNCFRAME_PREFIX_LENGTH; 518 for (int i = startIndex; i <= endIndex; i++) { 519 // The syncword ends 0xBA for TrueHD or 0xBB for MLP. 520 if ((Util.getBigEndianInt(buffer, i + 4) & 0xFFFFFFFE) == 0xF8726FBA) { 521 return i - startIndex; 522 } 523 } 524 return C.INDEX_UNSET; 525 } 526 527 /** 528 * Returns the number of audio samples represented by the given TrueHD syncframe, or 0 if the 529 * buffer is not the start of a syncframe. 530 * 531 * @param syncframe The bytes from which to read the syncframe. Must be at least {@link 532 * #TRUEHD_SYNCFRAME_PREFIX_LENGTH} bytes long. 533 * @return The number of audio samples represented by the syncframe, or 0 if the buffer doesn't 534 * contain the start of a syncframe. 535 */ parseTrueHdSyncframeAudioSampleCount(byte[] syncframe)536 public static int parseTrueHdSyncframeAudioSampleCount(byte[] syncframe) { 537 // See "Dolby TrueHD (MLP) high-level bitstream description" on the Dolby developer site, 538 // subsections 2.2 and 4.2.1. The syncword ends 0xBA for TrueHD or 0xBB for MLP. 539 if (syncframe[4] != (byte) 0xF8 540 || syncframe[5] != (byte) 0x72 541 || syncframe[6] != (byte) 0x6F 542 || (syncframe[7] & 0xFE) != 0xBA) { 543 return 0; 544 } 545 boolean isMlp = (syncframe[7] & 0xFF) == 0xBB; 546 return 40 << ((syncframe[isMlp ? 9 : 8] >> 4) & 0x07); 547 } 548 549 /** 550 * Reads the number of audio samples represented by a TrueHD syncframe. The buffer's position is 551 * not modified. 552 * 553 * @param buffer The {@link ByteBuffer} from which to read the syncframe. 554 * @param offset The offset of the start of the syncframe relative to the buffer's position. 555 * @return The number of audio samples represented by the syncframe. 556 */ parseTrueHdSyncframeAudioSampleCount(ByteBuffer buffer, int offset)557 public static int parseTrueHdSyncframeAudioSampleCount(ByteBuffer buffer, int offset) { 558 // TODO: Link to specification if available. 559 boolean isMlp = (buffer.get(buffer.position() + offset + 7) & 0xFF) == 0xBB; 560 return 40 << ((buffer.get(buffer.position() + offset + (isMlp ? 9 : 8)) >> 4) & 0x07); 561 } 562 getAc3SyncframeSize(int fscod, int frmsizecod)563 private static int getAc3SyncframeSize(int fscod, int frmsizecod) { 564 int halfFrmsizecod = frmsizecod / 2; 565 if (fscod < 0 || fscod >= SAMPLE_RATE_BY_FSCOD.length || frmsizecod < 0 566 || halfFrmsizecod >= SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1.length) { 567 // Invalid values provided. 568 return C.LENGTH_UNSET; 569 } 570 int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; 571 if (sampleRate == 44100) { 572 return 2 * (SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1[halfFrmsizecod] + (frmsizecod % 2)); 573 } 574 int bitrate = BITRATE_BY_HALF_FRMSIZECOD[halfFrmsizecod]; 575 if (sampleRate == 32000) { 576 return 6 * bitrate; 577 } else { // sampleRate == 48000 578 return 4 * bitrate; 579 } 580 } 581 Ac3Util()582 private Ac3Util() {} 583 584 } 585