OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/formats/ac3/ac3_util.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/macros.h" | |
9 #include "media/base/bit_reader.h" | |
10 | |
11 namespace media { | |
12 | |
13 namespace { | |
14 | |
15 // The size in byte of a (E-)AC3 synchronization frame header. | |
16 const int kHeaderSizeInByte = 8; | |
17 // The number of new samples per (E-)AC3 audio block. | |
18 const int kAudioSamplesPerAudioBlock = 256; | |
19 // Each synchronization frame has 6 blocks that provide 256 new audio samples. | |
20 const int kAudioSamplePerAc3SyncFrame = 6 * kAudioSamplesPerAudioBlock; | |
21 // Number of audio blocks per E-AC3 synchronization frame, indexed by | |
22 // numblkscod. | |
23 const int kBlocksPerSyncFrame[] = {1, 2, 3, 6}; | |
24 // Sample rates, indexed by fscod. | |
25 const int kSampleRate[] = {48000, 44100, 32000}; | |
26 // Nominal bitrates in kbps, indexed by frmsizecod / 2. | |
27 const int kBitrate[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, | |
28 192, 224, 256, 320, 384, 448, 512, 576, 640}; | |
29 // 16-bit words per synchronization frame, indexed by frmsizecod. | |
30 const int kSyncFrameSizeInWordsFor44kHz[] = { | |
31 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, | |
32 209, 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558, | |
33 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394}; | |
34 | |
35 // Utility for unpacking (E-)AC3 header. Note that all fields are encoded. | |
36 class Ac3Header { | |
37 public: | |
38 Ac3Header(const uint8_t* data, int size); | |
39 | |
40 const uint32_t eac3_frame_size_code() { return eac3_frame_size_code_; } | |
41 | |
42 const uint32_t sample_rate_code() { return sample_rate_code_; } | |
43 | |
44 const uint32_t eac3_number_of_audio_block_code() { | |
45 DCHECK(sample_rate_code_ != 3); | |
46 return eac3_number_of_audio_block_code_; | |
47 } | |
48 | |
49 const uint32_t ac3_frame_size_code() { return ac3_frame_size_code_; } | |
50 | |
51 private: | |
52 // bit[5:15] for E-AC3 | |
53 uint32_t eac3_frame_size_code_; | |
54 // bit[16:17] for (E-)AC3 | |
55 uint32_t sample_rate_code_; | |
56 // bit[18:23] for AC3 | |
57 uint32_t ac3_frame_size_code_; | |
58 // bit[18:19] for E-AC3 | |
59 uint32_t eac3_number_of_audio_block_code_; | |
60 }; | |
61 | |
62 Ac3Header::Ac3Header(const uint8_t* data, int size) { | |
63 DCHECK_GE(size, kHeaderSizeInByte); | |
64 | |
65 BitReader reader(data, size); | |
66 uint16_t sync_word; | |
67 reader.ReadBits(16, &sync_word); | |
68 DCHECK(sync_word == 0x0B77); | |
69 | |
70 reader.SkipBits(5); | |
71 reader.ReadBits(11, &eac3_frame_size_code_); | |
72 reader.ReadBits(2, &sample_rate_code_); | |
73 reader.ReadBits(6, &ac3_frame_size_code_); | |
74 eac3_number_of_audio_block_code_ = ac3_frame_size_code_ >> 4; | |
75 } | |
76 | |
77 // Search for next synchronization word, wihch is 0x0B-0x77. | |
78 const uint8_t* FindNextSyncWord(const uint8_t* const begin, | |
79 const uint8_t* const end) { | |
80 DCHECK(begin); | |
81 DCHECK(end); | |
82 DCHECK_LE(begin, end); | |
83 | |
84 const uint8_t* current = begin; | |
85 | |
86 while (current < end - 1) { | |
87 if (current[0] == 0x0B && current[1] == 0x77) { | |
88 if (current != begin) | |
89 DVLOG(2) << __FUNCTION__ << " skip " << current - begin << " bytes."; | |
90 | |
91 return current; | |
92 } else if (current[1] != 0x0B) { | |
93 current += 2; | |
94 } else { | |
95 ++current; | |
96 } | |
97 } | |
98 | |
99 return nullptr; | |
100 } | |
101 | |
102 // Returns the number of audio samples represented by the given E-AC3 | |
103 // synchronization frame. | |
104 int ParseEac3SyncFrameSampleCount(Ac3Header& header) { | |
105 unsigned blocks = | |
106 header.sample_rate_code() == 0x03 | |
107 ? 6 | |
108 : kBlocksPerSyncFrame[header.eac3_number_of_audio_block_code()]; | |
109 return kAudioSamplesPerAudioBlock * blocks; | |
110 } | |
111 | |
112 // Returns the size in bytes of the given E-AC3 synchronization frame. | |
113 int ParseEac3SyncFrameSize(Ac3Header& header) { | |
114 return 2 * (header.eac3_frame_size_code() + 1); | |
115 } | |
116 | |
117 // Returns the number of audio samples in an AC3 synchronization frame. | |
118 int GetAc3SyncFrameSampleCount() { | |
119 return kAudioSamplePerAc3SyncFrame; | |
120 } | |
121 | |
122 // Returns the size in bytes of the given AC3 synchronization frame. | |
123 int ParseAc3SyncFrameSize(Ac3Header& header) { | |
124 if (header.sample_rate_code() >= arraysize(kSampleRate) || | |
125 Ac3Header.ac3_frame_size_code() >= | |
126 arraysize(kSyncFrameSizeInWordsFor44kHz)) { | |
127 DVLOG(2) << __FUNCTION__ << " Invalid frame header." | |
128 << " fscod:" << Ac3Header.sample_rate_code() | |
129 << " frmsizecod:" << Ac3Header.ac3_frame_size_code(); | |
130 return -1; | |
131 } | |
132 | |
133 int sample_rate = kSampleRate[Ac3Header.sample_rate_code()]; | |
134 if (sample_rate == 44100) { | |
135 return 2 * kSyncFrameSizeInWordsFor44kHz[Ac3Header.ac3_frame_size_code()]; | |
chcunningham
2017/05/05 18:57:18
Can you document where the 2, 6, and 4 (LHS of ret
AndyWu
2017/05/06 01:46:48
Done.
| |
136 } | |
137 | |
138 int bitrate = kBitrate[Ac3Header.ac3_frame_size_code() / 2]; | |
139 if (sample_rate == 32000) { | |
140 return 6 * bitrate; | |
141 } | |
142 | |
143 // sample_rate == 48000 | |
144 return 4 * bitrate; | |
145 } | |
146 | |
147 // Returns the total number of audio samples in the given buffer, which contains | |
148 // several complete (E-)AC3 syncframes. | |
149 int ParseTotalSampleCount(const uint8_t* data, size_t size, bool is_eac3) { | |
150 DCHECK(data); | |
151 | |
152 if (size < kHeaderSizeInByte) { | |
153 return 0; | |
154 } | |
155 | |
156 const uint8_t* const end = data + size; | |
157 const uint8_t* current = FindNextSyncWord(data, end); | |
158 int total_sample_count = 0; | |
159 | |
160 while (current && end - current > kHeaderSizeInByte) { | |
161 Ac3Header header(current, end - current); | |
162 | |
163 int frame_size = is_eac3 ? ParseEac3SyncFrameSize(header) | |
164 : ParseAc3SyncFrameSize(header); | |
165 int sample_count = is_eac3 ? ParseEac3SyncFrameSampleCount(header) | |
166 : GetAc3SyncFrameSampleCount(); | |
167 | |
168 if (frame_size > 0 && sample_count > 0) { | |
169 current += frame_size; | |
170 if (current > end) { | |
171 DVLOG(2) << __FUNCTION__ << " Incomplete frame, missing " | |
172 << current - end << " bytes."; | |
173 break; | |
174 } | |
175 | |
176 total_sample_count += sample_count; | |
177 } else { | |
178 DVLOG(2) | |
179 << __FUNCTION__ | |
180 << " Invalid frame, skip 2 bytes to find next synchronization word."; | |
181 current += 2; | |
182 } | |
183 | |
184 current = FindNextSyncWord(current, end); | |
185 } | |
186 | |
187 return total_sample_count; | |
188 } | |
189 | |
190 } // namespace anonymous | |
191 | |
192 // static | |
193 int Ac3Util::ParseTotalAc3SampleCount(const uint8_t* data, size_t size) { | |
194 return ParseTotalSampleCount(data, size, false); | |
195 } | |
196 | |
197 // static | |
198 int Ac3Util::ParseTotalEac3SampleCount(const uint8_t* data, size_t size) { | |
199 return ParseTotalSampleCount(data, size, true); | |
200 } | |
201 | |
202 } // namespace media | |
OLD | NEW |