diff options
Diffstat (limited to 'chromium/media/formats/mp4/aac.cc')
-rw-r--r-- | chromium/media/formats/mp4/aac.cc | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/chromium/media/formats/mp4/aac.cc b/chromium/media/formats/mp4/aac.cc new file mode 100644 index 00000000000..71dededf552 --- /dev/null +++ b/chromium/media/formats/mp4/aac.cc @@ -0,0 +1,250 @@ +// 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/mp4/aac.h" + +#include <algorithm> + +#include "base/logging.h" +#include "media/base/bit_reader.h" +#include "media/base/media_log.h" +#include "media/formats/mp4/rcheck.h" +#include "media/formats/mpeg/adts_constants.h" + +namespace media { +namespace mp4 { + +AAC::AAC() + : profile_(0), frequency_index_(0), channel_config_(0), frequency_(0), + extension_frequency_(0), channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED) { +} + +AAC::~AAC() { +} + +bool AAC::Parse(const std::vector<uint8>& data, const LogCB& log_cb) { +#if defined(OS_ANDROID) + codec_specific_data_ = data; +#endif + if (data.empty()) + return false; + + BitReader reader(&data[0], data.size()); + uint8 extension_type = 0; + bool ps_present = false; + uint8 extension_frequency_index = 0xff; + + frequency_ = 0; + extension_frequency_ = 0; + + // The following code is written according to ISO 14496 Part 3 Table 1.13 - + // Syntax of AudioSpecificConfig. + + // Read base configuration + RCHECK(reader.ReadBits(5, &profile_)); + RCHECK(reader.ReadBits(4, &frequency_index_)); + if (frequency_index_ == 0xf) + RCHECK(reader.ReadBits(24, &frequency_)); + RCHECK(reader.ReadBits(4, &channel_config_)); + + // Read extension configuration. + if (profile_ == 5 || profile_ == 29) { + ps_present = (profile_ == 29); + extension_type = 5; + RCHECK(reader.ReadBits(4, &extension_frequency_index)); + if (extension_frequency_index == 0xf) + RCHECK(reader.ReadBits(24, &extension_frequency_)); + RCHECK(reader.ReadBits(5, &profile_)); + } + + MEDIA_LOG(log_cb) << "Audio codec: mp4a.40." + << std::hex << static_cast<int>(profile_); + + RCHECK(SkipDecoderGASpecificConfig(&reader)); + RCHECK(SkipErrorSpecificConfig()); + + // Read extension configuration again + // Note: The check for 16 available bits comes from the AAC spec. + if (extension_type != 5 && reader.bits_available() >= 16) { + uint16 sync_extension_type; + uint8 sbr_present_flag; + uint8 ps_present_flag; + + if (reader.ReadBits(11, &sync_extension_type) && + sync_extension_type == 0x2b7) { + if (reader.ReadBits(5, &extension_type) && extension_type == 5) { + RCHECK(reader.ReadBits(1, &sbr_present_flag)); + + if (sbr_present_flag) { + RCHECK(reader.ReadBits(4, &extension_frequency_index)); + + if (extension_frequency_index == 0xf) + RCHECK(reader.ReadBits(24, &extension_frequency_)); + + // Note: The check for 12 available bits comes from the AAC spec. + if (reader.bits_available() >= 12) { + RCHECK(reader.ReadBits(11, &sync_extension_type)); + if (sync_extension_type == 0x548) { + RCHECK(reader.ReadBits(1, &ps_present_flag)); + ps_present = ps_present_flag != 0; + } + } + } + } + } + } + + if (frequency_ == 0) { + RCHECK(frequency_index_ < kADTSFrequencyTableSize); + frequency_ = kADTSFrequencyTable[frequency_index_]; + } + + if (extension_frequency_ == 0 && extension_frequency_index != 0xff) { + RCHECK(extension_frequency_index < kADTSFrequencyTableSize); + extension_frequency_ = kADTSFrequencyTable[extension_frequency_index]; + } + + // When Parametric Stereo is on, mono will be played as stereo. + if (ps_present && channel_config_ == 1) { + channel_layout_ = CHANNEL_LAYOUT_STEREO; + } else { + RCHECK(channel_config_ < kADTSChannelLayoutTableSize); + channel_layout_ = kADTSChannelLayoutTable[channel_config_]; + } + + return frequency_ != 0 && channel_layout_ != CHANNEL_LAYOUT_NONE && + profile_ >= 1 && profile_ <= 4; +} + +int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const { + if (extension_frequency_ > 0) + return extension_frequency_; + + if (!sbr_in_mimetype) + return frequency_; + + // The following code is written according to ISO 14496 Part 3 Table 1.11 and + // Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers + // to SBR doubling the AAC sample rate.) + // TODO(acolwell) : Extend sample rate cap to 96kHz for Level 5 content. + DCHECK_GT(frequency_, 0); + return std::min(2 * frequency_, 48000); +} + +ChannelLayout AAC::GetChannelLayout(bool sbr_in_mimetype) const { + // Check for implicit signalling of HE-AAC and indicate stereo output + // if the mono channel configuration is signalled. + // See ISO-14496-3 Section 1.6.6.1.2 for details about this special casing. + if (sbr_in_mimetype && channel_config_ == 1) + return CHANNEL_LAYOUT_STEREO; + + return channel_layout_; +} + +bool AAC::ConvertEsdsToADTS(std::vector<uint8>* buffer) const { + size_t size = buffer->size() + kADTSHeaderMinSize; + + DCHECK(profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf && + channel_config_ <= 7); + + // ADTS header uses 13 bits for packet size. + if (size >= (1 << 13)) + return false; + + std::vector<uint8>& adts = *buffer; + + adts.insert(buffer->begin(), kADTSHeaderMinSize, 0); + adts[0] = 0xff; + adts[1] = 0xf1; + adts[2] = ((profile_ - 1) << 6) + (frequency_index_ << 2) + + (channel_config_ >> 2); + adts[3] = ((channel_config_ & 0x3) << 6) + (size >> 11); + adts[4] = (size & 0x7ff) >> 3; + adts[5] = ((size & 7) << 5) + 0x1f; + adts[6] = 0xfc; + + return true; +} + +// Currently this function only support GASpecificConfig defined in +// ISO 14496 Part 3 Table 4.1 - Syntax of GASpecificConfig() +bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const { + switch (profile_) { + case 1: + case 2: + case 3: + case 4: + case 6: + case 7: + case 17: + case 19: + case 20: + case 21: + case 22: + case 23: + return SkipGASpecificConfig(bit_reader); + default: + break; + } + + return false; +} + +bool AAC::SkipErrorSpecificConfig() const { + switch (profile_) { + case 17: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + return false; + default: + break; + } + + return true; +} + +// The following code is written according to ISO 14496 part 3 Table 4.1 - +// GASpecificConfig. +bool AAC::SkipGASpecificConfig(BitReader* bit_reader) const { + uint8 extension_flag = 0; + uint8 depends_on_core_coder; + uint16 dummy; + + RCHECK(bit_reader->ReadBits(1, &dummy)); // frameLengthFlag + RCHECK(bit_reader->ReadBits(1, &depends_on_core_coder)); + if (depends_on_core_coder == 1) + RCHECK(bit_reader->ReadBits(14, &dummy)); // coreCoderDelay + + RCHECK(bit_reader->ReadBits(1, &extension_flag)); + RCHECK(channel_config_ != 0); + + if (profile_ == 6 || profile_ == 20) + RCHECK(bit_reader->ReadBits(3, &dummy)); // layerNr + + if (extension_flag) { + if (profile_ == 22) { + RCHECK(bit_reader->ReadBits(5, &dummy)); // numOfSubFrame + RCHECK(bit_reader->ReadBits(11, &dummy)); // layer_length + } + + if (profile_ == 17 || profile_ == 19 || profile_ == 20 || profile_ == 23) { + RCHECK(bit_reader->ReadBits(3, &dummy)); // resilience flags + } + + RCHECK(bit_reader->ReadBits(1, &dummy)); // extensionFlag3 + } + + return true; +} + +} // namespace mp4 + +} // namespace media |