Chromium Code Reviews| 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/mp3_stream_parser.h" |
| 6 | 6 |
| 7 namespace media { | 7 namespace media { |
| 8 | 8 |
| 9 // static | |
| 10 const int MP3StreamParser::kMpeg1AudioHeaderSize = 4u; | |
|
damienv1
2014/09/03 17:43:43
Should be 4 (not 4u)
| |
| 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 MP3StreamParser::ParserMpeg1AudioFrameHeader( |
| 97 | 100 const LogCB& log_cb, |
| 98 MP3StreamParser::~MP3StreamParser() {} | 101 const uint8* data, |
| 99 | 102 Mpeg1AudioHeader* header) { |
| 100 int MP3StreamParser::ParseFrameHeader(const uint8* data, | 103 BitReader reader(data, kMpeg1AudioHeaderSize); |
| 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 MP3StreamParser::MP3StreamParser() | |
| 233 : MPEGAudioStreamParserBase(kMP3StartCodeMask, kCodecMP3, kCodecDelay) {} | |
| 234 | |
| 235 MP3StreamParser::~MP3StreamParser() {} | |
| 236 | |
| 237 int MP3StreamParser::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>(kMpeg1AudioHeaderSize)) | |
| 249 return 0; | |
| 250 | |
| 251 Mpeg1AudioHeader header; | |
| 252 if (!ParserMpeg1AudioFrameHeader(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 = kMpeg1AudioHeaderSize; |
| 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 |