| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/formats/mpeg/adts_stream_parser.h" |
| |
| #include <stddef.h> |
| |
| #include "build/build_config.h" |
| #include "media/base/media_log.h" |
| #include "media/formats/mp4/aac.h" |
| #include "media/formats/mpeg/adts_constants.h" |
| |
| namespace media { |
| |
| constexpr uint32_t kADTSStartCodeMask = 0xfff00000; |
| |
| ADTSStreamParser::ADTSStreamParser() |
| : MPEGAudioStreamParserBase(kADTSStartCodeMask, kCodecAAC, 0) {} |
| |
| ADTSStreamParser::~ADTSStreamParser() = default; |
| |
| int ADTSStreamParser::ParseFrameHeader(const uint8_t* data, |
| int size, |
| int* frame_size, |
| int* sample_rate, |
| ChannelLayout* channel_layout, |
| int* sample_count, |
| bool* metadata_frame, |
| std::vector<uint8_t>* extra_data) { |
| DCHECK(data); |
| DCHECK_GE(size, 0); |
| |
| if (size < kADTSHeaderMinSize) |
| return 0; |
| |
| BitReader reader(data, size); |
| int sync; |
| int version; |
| int layer; |
| int protection_absent; |
| int profile; |
| size_t sample_rate_index; |
| size_t channel_layout_index; |
| int frame_length; |
| size_t num_data_blocks; |
| int unused; |
| |
| if (!reader.ReadBits(12, &sync) || |
| !reader.ReadBits(1, &version) || |
| !reader.ReadBits(2, &layer) || |
| !reader.ReadBits(1, &protection_absent) || |
| !reader.ReadBits(2, &profile) || |
| !reader.ReadBits(4, &sample_rate_index) || |
| !reader.ReadBits(1, &unused) || |
| !reader.ReadBits(3, &channel_layout_index) || |
| !reader.ReadBits(4, &unused) || |
| !reader.ReadBits(13, &frame_length) || |
| !reader.ReadBits(11, &unused) || |
| !reader.ReadBits(2, &num_data_blocks) || |
| (!protection_absent && !reader.ReadBits(16, &unused))) { |
| return -1; |
| } |
| |
| DVLOG(2) << "Header data :" << std::hex << " sync 0x" << sync << " version 0x" |
| << version << " layer 0x" << layer << " profile 0x" << profile |
| << " sample_rate_index 0x" << sample_rate_index |
| << " channel_layout_index 0x" << channel_layout_index; |
| |
| const int bytes_read = reader.bits_read() / 8; |
| if (sync != 0xfff || layer != 0 || frame_length < bytes_read || |
| sample_rate_index >= kADTSFrequencyTableSize || |
| channel_layout_index >= kADTSChannelLayoutTableSize) { |
| if (media_log()) { |
| LIMITED_MEDIA_LOG(DEBUG, media_log(), adts_parse_error_limit_, 5) |
| << "Invalid header data :" << std::hex << " sync 0x" << sync |
| << " version 0x" << version << " layer 0x" << layer |
| << " sample_rate_index 0x" << sample_rate_index |
| << " channel_layout_index 0x" << channel_layout_index; |
| } |
| return -1; |
| } |
| |
| if (sample_rate) |
| *sample_rate = kADTSFrequencyTable[sample_rate_index]; |
| |
| if (frame_size) |
| *frame_size = frame_length; |
| |
| if (sample_count) |
| *sample_count = (num_data_blocks + 1) * kSamplesPerAACFrame; |
| |
| if (channel_layout) |
| *channel_layout = kADTSChannelLayoutTable[channel_layout_index]; |
| |
| if (metadata_frame) |
| *metadata_frame = false; |
| |
| if (extra_data) { |
| // See mp4::AAC::Parse() for details. We don't need to worry about writing |
| // extensions since we can't have extended ADTS by this point (it's |
| // explicitly rejected as invalid above). |
| DCHECK_NE(sample_rate_index, 15u); |
| |
| // The following code is written according to ISO 14496 Part 3 Table 1.13 - |
| // Syntax of AudioSpecificConfig. |
| const uint16_t esds = (((((profile + 1) << 4) + sample_rate_index) << 4) + |
| channel_layout_index) |
| << 3; |
| extra_data->push_back(esds >> 8); |
| extra_data->push_back(esds & 0xFF); |
| } |
| |
| return bytes_read; |
| } |
| |
| } // namespace media |