OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/formats/mpeg/mp3_stream_parser.h" | 5 #include "media/formats/mpeg/mpeg1_audio_stream_parser.h" |
6 | 6 |
7 namespace media { | 7 namespace media { |
8 | 8 |
9 // static | |
10 const int MPEG1AudioStreamParser::kHeaderSize = 4u; | |
acolwell GONE FROM CHROMIUM
2014/09/04 22:20:53
nit: drop the u?
DaleCurtis
2014/09/04 23:01:14
Just make this an enum?
damienv1
2014/09/05 20:06:13
Done.
damienv1
2014/09/05 20:06:13
Done.
| |
11 | |
9 static const uint32 kMP3StartCodeMask = 0xffe00000; | 12 static const uint32 kMP3StartCodeMask = 0xffe00000; |
10 | 13 |
11 // Map that determines which bitrate_index & channel_mode combinations | 14 // Map that determines which bitrate_index & channel_mode combinations |
12 // are allowed. | 15 // are allowed. |
13 // Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html | 16 // Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html |
14 static const bool kIsAllowed[17][4] = { | 17 static const bool kIsAllowed[17][4] = { |
15 { true, true, true, true }, // free | 18 { true, true, true, true }, // free |
16 { true, false, false, false }, // 32 | 19 { true, false, false, false }, // 32 |
17 { true, false, false, false }, // 48 | 20 { true, false, false, false }, // 48 |
18 { true, false, false, false }, // 56 | 21 { true, false, false, false }, // 56 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 static const int kVersion2_5 = 0; | 88 static const int kVersion2_5 = 0; |
86 static const int kLayerReserved = 0; | 89 static const int kLayerReserved = 0; |
87 static const int kLayer1 = 3; | 90 static const int kLayer1 = 3; |
88 static const int kLayer2 = 2; | 91 static const int kLayer2 = 2; |
89 static const int kLayer3 = 1; | 92 static const int kLayer3 = 1; |
90 static const int kBitrateFree = 0; | 93 static const int kBitrateFree = 0; |
91 static const int kBitrateBad = 0xf; | 94 static const int kBitrateBad = 0xf; |
92 static const int kSampleRateReserved = 3; | 95 static const int kSampleRateReserved = 3; |
93 static const int kCodecDelay = 529; | 96 static const int kCodecDelay = 529; |
94 | 97 |
95 MP3StreamParser::MP3StreamParser() | 98 // static |
96 : MPEGAudioStreamParserBase(kMP3StartCodeMask, kCodecMP3, kCodecDelay) {} | 99 bool MPEG1AudioStreamParser::ParseHeader( |
97 | 100 const LogCB& log_cb, |
98 MP3StreamParser::~MP3StreamParser() {} | 101 const uint8* data, |
99 | 102 Header* header) { |
100 int MP3StreamParser::ParseFrameHeader(const uint8* data, | 103 BitReader reader(data, kHeaderSize); |
101 int size, | |
102 int* frame_size, | |
103 int* sample_rate, | |
104 ChannelLayout* channel_layout, | |
105 int* sample_count, | |
106 bool* metadata_frame) const { | |
107 DCHECK(data); | |
108 DCHECK_GE(size, 0); | |
109 DCHECK(frame_size); | |
110 | |
111 if (size < 4) | |
112 return 0; | |
113 | |
114 BitReader reader(data, size); | |
115 int sync; | 104 int sync; |
116 int version; | 105 int version; |
117 int layer; | 106 int layer; |
118 int is_protected; | 107 int is_protected; |
119 int bitrate_index; | 108 int bitrate_index; |
120 int sample_rate_index; | 109 int sample_rate_index; |
121 int has_padding; | 110 int has_padding; |
122 int is_private; | 111 int is_private; |
123 int channel_mode; | 112 int channel_mode; |
124 int other_flags; | 113 int other_flags; |
125 | 114 |
126 if (!reader.ReadBits(11, &sync) || | 115 if (!reader.ReadBits(11, &sync) || |
127 !reader.ReadBits(2, &version) || | 116 !reader.ReadBits(2, &version) || |
128 !reader.ReadBits(2, &layer) || | 117 !reader.ReadBits(2, &layer) || |
129 !reader.ReadBits(1, &is_protected) || | 118 !reader.ReadBits(1, &is_protected) || |
130 !reader.ReadBits(4, &bitrate_index) || | 119 !reader.ReadBits(4, &bitrate_index) || |
131 !reader.ReadBits(2, &sample_rate_index) || | 120 !reader.ReadBits(2, &sample_rate_index) || |
132 !reader.ReadBits(1, &has_padding) || | 121 !reader.ReadBits(1, &has_padding) || |
133 !reader.ReadBits(1, &is_private) || | 122 !reader.ReadBits(1, &is_private) || |
134 !reader.ReadBits(2, &channel_mode) || | 123 !reader.ReadBits(2, &channel_mode) || |
135 !reader.ReadBits(6, &other_flags)) { | 124 !reader.ReadBits(6, &other_flags)) { |
136 return -1; | 125 return false; |
137 } | 126 } |
138 | 127 |
139 DVLOG(2) << "Header data :" << std::hex | 128 DVLOG(2) << "Header data :" << std::hex |
140 << " sync 0x" << sync | 129 << " sync 0x" << sync |
141 << " version 0x" << version | 130 << " version 0x" << version |
142 << " layer 0x" << layer | 131 << " layer 0x" << layer |
143 << " bitrate_index 0x" << bitrate_index | 132 << " bitrate_index 0x" << bitrate_index |
144 << " sample_rate_index 0x" << sample_rate_index | 133 << " sample_rate_index 0x" << sample_rate_index |
145 << " channel_mode 0x" << channel_mode; | 134 << " channel_mode 0x" << channel_mode; |
146 | 135 |
147 if (sync != 0x7ff || | 136 if (sync != 0x7ff || |
148 version == kVersionReserved || | 137 version == kVersionReserved || |
149 layer == kLayerReserved || | 138 layer == kLayerReserved || |
150 bitrate_index == kBitrateFree || bitrate_index == kBitrateBad || | 139 bitrate_index == kBitrateFree || bitrate_index == kBitrateBad || |
151 sample_rate_index == kSampleRateReserved) { | 140 sample_rate_index == kSampleRateReserved) { |
152 MEDIA_LOG(log_cb()) << "Invalid header data :" << std::hex | 141 MEDIA_LOG(log_cb) << "Invalid header data :" << std::hex |
153 << " sync 0x" << sync | 142 << " sync 0x" << sync |
154 << " version 0x" << version | 143 << " version 0x" << version |
155 << " layer 0x" << layer | 144 << " layer 0x" << layer |
156 << " bitrate_index 0x" << bitrate_index | 145 << " bitrate_index 0x" << bitrate_index |
157 << " sample_rate_index 0x" << sample_rate_index | 146 << " sample_rate_index 0x" << sample_rate_index |
158 << " channel_mode 0x" << channel_mode; | 147 << " channel_mode 0x" << channel_mode; |
159 return -1; | 148 return false; |
160 } | 149 } |
161 | 150 |
162 if (layer == kLayer2 && kIsAllowed[bitrate_index][channel_mode]) { | 151 if (layer == kLayer2 && kIsAllowed[bitrate_index][channel_mode]) { |
163 MEDIA_LOG(log_cb()) << "Invalid (bitrate_index, channel_mode) combination :" | 152 MEDIA_LOG(log_cb) << "Invalid (bitrate_index, channel_mode) combination :" |
164 << std::hex | 153 << std::hex |
165 << " bitrate_index " << bitrate_index | 154 << " bitrate_index " << bitrate_index |
166 << " channel_mode " << channel_mode; | 155 << " channel_mode " << channel_mode; |
167 return -1; | 156 return false; |
168 } | 157 } |
169 | 158 |
170 int bitrate = kBitrateMap[bitrate_index][kVersionLayerMap[version][layer]]; | 159 int bitrate = kBitrateMap[bitrate_index][kVersionLayerMap[version][layer]]; |
171 | 160 |
172 if (bitrate == 0) { | 161 if (bitrate == 0) { |
173 MEDIA_LOG(log_cb()) << "Invalid bitrate :" << std::hex | 162 MEDIA_LOG(log_cb) << "Invalid bitrate :" << std::hex |
174 << " version " << version | 163 << " version " << version |
175 << " layer " << layer | 164 << " layer " << layer |
176 << " bitrate_index " << bitrate_index; | 165 << " bitrate_index " << bitrate_index; |
177 return -1; | 166 return false; |
178 } | 167 } |
179 | 168 |
180 DVLOG(2) << " bitrate " << bitrate; | 169 DVLOG(2) << " bitrate " << bitrate; |
181 | 170 |
182 int frame_sample_rate = kSampleRateMap[sample_rate_index][version]; | 171 int frame_sample_rate = kSampleRateMap[sample_rate_index][version]; |
183 if (frame_sample_rate == 0) { | 172 if (frame_sample_rate == 0) { |
184 MEDIA_LOG(log_cb()) << "Invalid sample rate :" << std::hex | 173 MEDIA_LOG(log_cb) << "Invalid sample rate :" << std::hex |
185 << " version " << version | 174 << " version " << version |
186 << " sample_rate_index " << sample_rate_index; | 175 << " sample_rate_index " << sample_rate_index; |
187 return -1; | 176 return false; |
188 } | 177 } |
189 | 178 header->sample_rate = frame_sample_rate; |
190 if (sample_rate) | |
191 *sample_rate = frame_sample_rate; | |
192 | 179 |
193 // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf | 180 // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf |
194 // Table 2.1.5 | 181 // Table 2.1.5 |
195 int samples_per_frame; | 182 int samples_per_frame; |
196 switch (layer) { | 183 switch (layer) { |
197 case kLayer1: | 184 case kLayer1: |
198 samples_per_frame = 384; | 185 samples_per_frame = 384; |
199 break; | 186 break; |
200 | 187 |
201 case kLayer2: | 188 case kLayer2: |
202 samples_per_frame = 1152; | 189 samples_per_frame = 1152; |
203 break; | 190 break; |
204 | 191 |
205 case kLayer3: | 192 case kLayer3: |
206 if (version == kVersion2 || version == kVersion2_5) | 193 if (version == kVersion2 || version == kVersion2_5) |
207 samples_per_frame = 576; | 194 samples_per_frame = 576; |
208 else | 195 else |
209 samples_per_frame = 1152; | 196 samples_per_frame = 1152; |
210 break; | 197 break; |
211 | 198 |
212 default: | 199 default: |
213 return -1; | 200 return false; |
214 } | 201 } |
215 | 202 header->sample_count = samples_per_frame; |
216 if (sample_count) | |
217 *sample_count = samples_per_frame; | |
218 | 203 |
219 // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf | 204 // http://teslabs.com/openplayer/docs/docs/specs/mp3_structure2.pdf |
220 // Text just below Table 2.1.5. | 205 // Text just below Table 2.1.5. |
221 if (layer == kLayer1) { | 206 if (layer == kLayer1) { |
222 // This formulation is a slight variation on the equation below, | 207 // This formulation is a slight variation on the equation below, |
223 // but has slightly different truncation characteristics to deal | 208 // but has slightly different truncation characteristics to deal |
224 // with the fact that Layer 1 has 4 byte "slots" instead of single | 209 // with the fact that Layer 1 has 4 byte "slots" instead of single |
225 // byte ones. | 210 // byte ones. |
226 *frame_size = 4 * (12 * bitrate * 1000 / frame_sample_rate); | 211 header->frame_size = 4 * (12 * bitrate * 1000 / frame_sample_rate); |
227 } else { | 212 } else { |
228 *frame_size = | 213 header->frame_size = |
229 ((samples_per_frame / 8) * bitrate * 1000) / frame_sample_rate; | 214 ((samples_per_frame / 8) * bitrate * 1000) / frame_sample_rate; |
230 } | 215 } |
231 | 216 |
232 if (has_padding) | 217 if (has_padding) |
233 *frame_size += (layer == kLayer1) ? 4 : 1; | 218 header->frame_size += (layer == kLayer1) ? 4 : 1; |
234 | 219 |
235 if (channel_layout) { | 220 // Map Stereo(0), Joint Stereo(1), and Dual Channel (2) to |
236 // Map Stereo(0), Joint Stereo(1), and Dual Channel (2) to | 221 // CHANNEL_LAYOUT_STEREO and Single Channel (3) to CHANNEL_LAYOUT_MONO. |
237 // CHANNEL_LAYOUT_STEREO and Single Channel (3) to CHANNEL_LAYOUT_MONO. | 222 header->channel_layout = |
238 *channel_layout = | 223 (channel_mode == 3) ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO; |
239 (channel_mode == 3) ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO; | |
240 } | |
241 | 224 |
225 header->version = version; | |
226 header->layer = layer; | |
227 header->channel_mode = channel_mode; | |
228 return true; | |
229 } | |
230 | |
231 | |
232 MPEG1AudioStreamParser::MPEG1AudioStreamParser() | |
233 : MPEGAudioStreamParserBase(kMP3StartCodeMask, kCodecMP3, kCodecDelay) {} | |
234 | |
235 MPEG1AudioStreamParser::~MPEG1AudioStreamParser() {} | |
236 | |
237 int MPEG1AudioStreamParser::ParseFrameHeader(const uint8* data, | |
238 int size, | |
239 int* frame_size, | |
240 int* sample_rate, | |
241 ChannelLayout* channel_layout, | |
242 int* sample_count, | |
243 bool* metadata_frame) const { | |
244 DCHECK(data); | |
245 DCHECK_GE(size, 0); | |
246 DCHECK(frame_size); | |
247 | |
248 if (size < static_cast<int>(kHeaderSize)) | |
acolwell GONE FROM CHROMIUM
2014/09/04 22:20:53
I don't think you need the cast here since kHeader
damienv1
2014/09/05 20:06:13
Done.
| |
249 return 0; | |
250 | |
251 Header header; | |
252 if (!ParseHeader(log_cb(), data, &header)) | |
253 return -1; | |
254 | |
255 *frame_size = header.frame_size; | |
256 if (sample_rate) | |
257 *sample_rate = header.sample_rate; | |
258 if (sample_count) | |
259 *sample_count = header.sample_count; | |
260 if (channel_layout) | |
261 *channel_layout = header.channel_layout; | |
242 if (metadata_frame) | 262 if (metadata_frame) |
243 *metadata_frame = false; | 263 *metadata_frame = false; |
244 | 264 |
245 const int header_bytes_read = reader.bits_read() / 8; | 265 const int header_bytes_read = kHeaderSize; |
246 if (layer != kLayer3) | 266 if (header.layer != kLayer3) |
247 return header_bytes_read; | 267 return header_bytes_read; |
248 | 268 |
249 // Check if this is a XING frame and tell the base parser to skip it if so. | 269 // Check if this is a XING frame and tell the base parser to skip it if so. |
250 const int xing_header_index = | 270 const int xing_header_index = |
251 kXingHeaderMap[version == kVersion2 || | 271 kXingHeaderMap[header.version == kVersion2 || |
252 version == kVersion2_5][channel_mode == 3]; | 272 header.version == kVersion2_5][header.channel_mode == 3]; |
253 uint32_t tag = 0; | 273 uint32_t tag = 0; |
254 | 274 |
255 // It's not a XING frame if the frame isn't big enough to be one. | 275 // It's not a XING frame if the frame isn't big enough to be one. |
256 if (*frame_size < | 276 if (*frame_size < |
257 header_bytes_read + xing_header_index + static_cast<int>(sizeof(tag))) { | 277 header_bytes_read + xing_header_index + static_cast<int>(sizeof(tag))) { |
258 return header_bytes_read; | 278 return header_bytes_read; |
259 } | 279 } |
260 | 280 |
261 // If we don't have enough data available to check, return 0 so frame parsing | 281 // If we don't have enough data available to check, return 0 so frame parsing |
262 // will be retried once more data is available. | 282 // will be retried once more data is available. |
283 BitReader reader(data + header_bytes_read, size - header_bytes_read); | |
263 if (!reader.SkipBits(xing_header_index * 8) || | 284 if (!reader.SkipBits(xing_header_index * 8) || |
264 !reader.ReadBits(sizeof(tag) * 8, &tag)) { | 285 !reader.ReadBits(sizeof(tag) * 8, &tag)) { |
265 return 0; | 286 return 0; |
266 } | 287 } |
267 | 288 |
268 // Check to see if the tag contains 'Xing' or 'Info' | 289 // Check to see if the tag contains 'Xing' or 'Info' |
269 if (tag == 0x496e666f || tag == 0x58696e67) { | 290 if (tag == 0x496e666f || tag == 0x58696e67) { |
270 MEDIA_LOG(log_cb()) << "Skipping XING header."; | 291 MEDIA_LOG(log_cb()) << "Skipping XING header."; |
271 if (metadata_frame) | 292 if (metadata_frame) |
272 *metadata_frame = true; | 293 *metadata_frame = true; |
273 return reader.bits_read() / 8; | 294 return header_bytes_read + reader.bits_read() / 8; |
274 } | 295 } |
275 | 296 |
276 // If it wasn't a XING frame, just return the number consumed bytes. | 297 // If it wasn't a XING frame, just return the number consumed bytes. |
277 return header_bytes_read; | 298 return header_bytes_read; |
278 } | 299 } |
279 | 300 |
280 } // namespace media | 301 } // namespace media |
OLD | NEW |