• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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