• 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.Nullable;
19 import com.google.android.exoplayer2.Format;
20 import com.google.android.exoplayer2.drm.DrmInitData;
21 import com.google.android.exoplayer2.util.MimeTypes;
22 import com.google.android.exoplayer2.util.ParsableBitArray;
23 import java.nio.ByteBuffer;
24 import java.util.Arrays;
25 
26 /**
27  * Utility methods for parsing DTS frames.
28  */
29 public final class DtsUtil {
30 
31   /**
32    * Maximum rate for a DTS audio stream, in bytes per second.
33    *
34    * <p>DTS allows an 'open' bitrate, but we assume the maximum listed value: 1536 kbit/s.
35    */
36   public static final int DTS_MAX_RATE_BYTES_PER_SECOND = 1536 * 1000 / 8;
37   /** Maximum rate for a DTS-HD audio stream, in bytes per second. */
38   public static final int DTS_HD_MAX_RATE_BYTES_PER_SECOND = 18000 * 1000 / 8;
39 
40   private static final int SYNC_VALUE_BE = 0x7FFE8001;
41   private static final int SYNC_VALUE_14B_BE = 0x1FFFE800;
42   private static final int SYNC_VALUE_LE = 0xFE7F0180;
43   private static final int SYNC_VALUE_14B_LE = 0xFF1F00E8;
44   private static final byte FIRST_BYTE_BE = (byte) (SYNC_VALUE_BE >>> 24);
45   private static final byte FIRST_BYTE_14B_BE = (byte) (SYNC_VALUE_14B_BE >>> 24);
46   private static final byte FIRST_BYTE_LE = (byte) (SYNC_VALUE_LE >>> 24);
47   private static final byte FIRST_BYTE_14B_LE = (byte) (SYNC_VALUE_14B_LE >>> 24);
48 
49   /**
50    * Maps AMODE to the number of channels. See ETSI TS 102 114 table 5.4.
51    */
52   private static final int[] CHANNELS_BY_AMODE = new int[] {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6,
53       7, 8, 8};
54 
55   /**
56    * Maps SFREQ to the sampling frequency in Hz. See ETSI TS 102 144 table 5.5.
57    */
58   private static final int[] SAMPLE_RATE_BY_SFREQ = new int[] {-1, 8000, 16000, 32000, -1, -1,
59       11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1};
60 
61   /**
62    * Maps RATE to 2 * bitrate in kbit/s. See ETSI TS 102 144 table 5.7.
63    */
64   private static final int[] TWICE_BITRATE_KBPS_BY_RATE = new int[] {64, 112, 128, 192, 224, 256,
65       384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 2048, 2304, 2560, 2688, 2816,
66       2823, 2944, 3072, 3840, 4096, 6144, 7680};
67 
68   /**
69    * Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are
70    * defined in ETSI TS 102 114 V1.1.1 (2002-08), Section 5.3.
71    *
72    * @param word An integer.
73    * @return Whether a given integer matches a DTS sync word.
74    */
isSyncWord(int word)75   public static boolean isSyncWord(int word) {
76     return word == SYNC_VALUE_BE
77         || word == SYNC_VALUE_LE
78         || word == SYNC_VALUE_14B_BE
79         || word == SYNC_VALUE_14B_LE;
80   }
81 
82   /**
83    * Returns the DTS format given {@code data} containing the DTS frame according to ETSI TS 102 114
84    * subsections 5.3/5.4.
85    *
86    * @param frame The DTS frame to parse.
87    * @param trackId The track identifier to set on the format.
88    * @param language The language to set on the format.
89    * @param drmInitData {@link DrmInitData} to be included in the format.
90    * @return The DTS format parsed from data in the header.
91    */
parseDtsFormat( byte[] frame, @Nullable String trackId, @Nullable String language, @Nullable DrmInitData drmInitData)92   public static Format parseDtsFormat(
93       byte[] frame,
94       @Nullable String trackId,
95       @Nullable String language,
96       @Nullable DrmInitData drmInitData) {
97     ParsableBitArray frameBits = getNormalizedFrameHeader(frame);
98     frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14); // SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE
99     int amode = frameBits.readBits(6);
100     int channelCount = CHANNELS_BY_AMODE[amode];
101     int sfreq = frameBits.readBits(4);
102     int sampleRate = SAMPLE_RATE_BY_SFREQ[sfreq];
103     int rate = frameBits.readBits(5);
104     int bitrate = rate >= TWICE_BITRATE_KBPS_BY_RATE.length ? Format.NO_VALUE
105         : TWICE_BITRATE_KBPS_BY_RATE[rate] * 1000 / 2;
106     frameBits.skipBits(10); // MIX, DYNF, TIMEF, AUXF, HDCD, EXT_AUDIO_ID, EXT_AUDIO, ASPF
107     channelCount += frameBits.readBits(2) > 0 ? 1 : 0; // LFF
108     return new Format.Builder()
109         .setId(trackId)
110         .setSampleMimeType(MimeTypes.AUDIO_DTS)
111         .setAverageBitrate(bitrate)
112         .setChannelCount(channelCount)
113         .setSampleRate(sampleRate)
114         .setDrmInitData(drmInitData)
115         .setLanguage(language)
116         .build();
117   }
118 
119   /**
120    * Returns the number of audio samples represented by the given DTS frame.
121    *
122    * @param data The frame to parse.
123    * @return The number of audio samples represented by the frame.
124    */
parseDtsAudioSampleCount(byte[] data)125   public static int parseDtsAudioSampleCount(byte[] data) {
126     int nblks;
127     switch (data[0]) {
128       case FIRST_BYTE_LE:
129         nblks = ((data[5] & 0x01) << 6) | ((data[4] & 0xFC) >> 2);
130         break;
131       case FIRST_BYTE_14B_LE:
132         nblks = ((data[4] & 0x07) << 4) | ((data[7] & 0x3C) >> 2);
133         break;
134       case FIRST_BYTE_14B_BE:
135         nblks = ((data[5] & 0x07) << 4) | ((data[6] & 0x3C) >> 2);
136         break;
137       default:
138         // We blindly assume FIRST_BYTE_BE if none of the others match.
139         nblks = ((data[4] & 0x01) << 6) | ((data[5] & 0xFC) >> 2);
140     }
141     return (nblks + 1) * 32;
142   }
143 
144   /**
145    * Like {@link #parseDtsAudioSampleCount(byte[])} but reads from a {@link ByteBuffer}. The
146    * buffer's position is not modified.
147    *
148    * @param buffer The {@link ByteBuffer} from which to read.
149    * @return The number of audio samples represented by the syncframe.
150    */
parseDtsAudioSampleCount(ByteBuffer buffer)151   public static int parseDtsAudioSampleCount(ByteBuffer buffer) {
152     // See ETSI TS 102 114 subsection 5.4.1.
153     int position = buffer.position();
154     int nblks;
155     switch (buffer.get(position)) {
156       case FIRST_BYTE_LE:
157         nblks = ((buffer.get(position + 5) & 0x01) << 6) | ((buffer.get(position + 4) & 0xFC) >> 2);
158         break;
159       case FIRST_BYTE_14B_LE:
160         nblks = ((buffer.get(position + 4) & 0x07) << 4) | ((buffer.get(position + 7) & 0x3C) >> 2);
161         break;
162       case FIRST_BYTE_14B_BE:
163         nblks = ((buffer.get(position + 5) & 0x07) << 4) | ((buffer.get(position + 6) & 0x3C) >> 2);
164         break;
165       default:
166         // We blindly assume FIRST_BYTE_BE if none of the others match.
167         nblks = ((buffer.get(position + 4) & 0x01) << 6) | ((buffer.get(position + 5) & 0xFC) >> 2);
168     }
169     return (nblks + 1) * 32;
170   }
171 
172   /**
173    * Returns the size in bytes of the given DTS frame.
174    *
175    * @param data The frame to parse.
176    * @return The frame's size in bytes.
177    */
getDtsFrameSize(byte[] data)178   public static int getDtsFrameSize(byte[] data) {
179     int fsize;
180     boolean uses14BitPerWord = false;
181     switch (data[0]) {
182       case FIRST_BYTE_14B_BE:
183         fsize = (((data[6] & 0x03) << 12) | ((data[7] & 0xFF) << 4) | ((data[8] & 0x3C) >> 2)) + 1;
184         uses14BitPerWord = true;
185         break;
186       case FIRST_BYTE_LE:
187         fsize = (((data[4] & 0x03) << 12) | ((data[7] & 0xFF) << 4) | ((data[6] & 0xF0) >> 4)) + 1;
188         break;
189       case FIRST_BYTE_14B_LE:
190         fsize = (((data[7] & 0x03) << 12) | ((data[6] & 0xFF) << 4) | ((data[9] & 0x3C) >> 2)) + 1;
191         uses14BitPerWord = true;
192         break;
193       default:
194         // We blindly assume FIRST_BYTE_BE if none of the others match.
195         fsize = (((data[5] & 0x03) << 12) | ((data[6] & 0xFF) << 4) | ((data[7] & 0xF0) >> 4)) + 1;
196     }
197 
198     // If the frame is stored in 14-bit mode, adjust the frame size to reflect the actual byte size.
199     return uses14BitPerWord ? fsize * 16 / 14 : fsize;
200   }
201 
getNormalizedFrameHeader(byte[] frameHeader)202   private static ParsableBitArray getNormalizedFrameHeader(byte[] frameHeader) {
203     if (frameHeader[0] == FIRST_BYTE_BE) {
204       // The frame is already 16-bit mode, big endian.
205       return new ParsableBitArray(frameHeader);
206     }
207     // Data is not normalized, but we don't want to modify frameHeader.
208     frameHeader = Arrays.copyOf(frameHeader, frameHeader.length);
209     if (isLittleEndianFrameHeader(frameHeader)) {
210       // Change endianness.
211       for (int i = 0; i < frameHeader.length - 1; i += 2) {
212         byte temp = frameHeader[i];
213         frameHeader[i] = frameHeader[i + 1];
214         frameHeader[i + 1] = temp;
215       }
216     }
217     ParsableBitArray frameBits = new ParsableBitArray(frameHeader);
218     if (frameHeader[0] == (byte) (SYNC_VALUE_14B_BE >> 24)) {
219       // Discard the 2 most significant bits of each 16 bit word.
220       ParsableBitArray scratchBits = new ParsableBitArray(frameHeader);
221       while (scratchBits.bitsLeft() >= 16) {
222         scratchBits.skipBits(2);
223         frameBits.putInt(scratchBits.readBits(14), 14);
224       }
225     }
226     frameBits.reset(frameHeader);
227     return frameBits;
228   }
229 
isLittleEndianFrameHeader(byte[] frameHeader)230   private static boolean isLittleEndianFrameHeader(byte[] frameHeader) {
231     return frameHeader[0] == FIRST_BYTE_LE || frameHeader[0] == FIRST_BYTE_14B_LE;
232   }
233 
DtsUtil()234   private DtsUtil() {}
235 
236 }
237