/***************************************************************** | | AP4 - AAC Info | | Copyright 2002-2009 Axiomatic Systems, LLC | | | This file is part of Bento4/AP4 (MP4 Atom Processing Library). | | Unless you have obtained Bento4 under a difference license, | this version of Bento4 is Bento4|GPL. | Bento4|GPL is free software; you can redistribute it and/or modify | it under the terms of the GNU General Public License as published by | the Free Software Foundation; either version 2, or (at your option) | any later version. | | Bento4|GPL is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU General Public License | along with Bento4|GPL; see the file COPYING. If not, write to the | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA | 02111-1307, USA. | ****************************************************************/ /*---------------------------------------------------------------------- | includes +---------------------------------------------------------------------*/ #include "Ap4BitStream.h" #include "Ap4Mp4AudioInfo.h" #include "Ap4DataBuffer.h" #include "Ap4SampleDescription.h" /*---------------------------------------------------------------------- | constants +---------------------------------------------------------------------*/ const unsigned int AP4_AAC_MAX_SAMPLING_FREQUENCY_INDEX = 12; static const unsigned int AP4_AacSamplingFreqTable[13] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; /*---------------------------------------------------------------------- | AP4_Mp4AudioDsiParser +---------------------------------------------------------------------*/ class AP4_Mp4AudioDsiParser { public: AP4_Mp4AudioDsiParser(const AP4_UI08* data, AP4_Size data_size) : m_Data(data, data_size), m_Position(0) {} AP4_Size BitsLeft() { return 8*m_Data.GetDataSize()-m_Position; } AP4_UI32 ReadBits(unsigned int n) { AP4_UI32 result = 0; const AP4_UI08* data = m_Data.GetData(); while (n) { unsigned int bits_avail = 8-(m_Position%8); unsigned int chunk_size = bits_avail >= n ? n : bits_avail; unsigned int chunk_bits = (((unsigned int)(data[m_Position/8]))>>(bits_avail-chunk_size))&((1<= 12) { sync_extension_type = parser.ReadBits(11); if (sync_extension_type == 0x548) { m_Extension.m_PsPresent = (parser.ReadBits(1) == 1); } } } } else if (m_Extension.m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) { if (parser.BitsLeft() < 1+4) return AP4_ERROR_INVALID_FORMAT; m_Extension.m_SbrPresent = (parser.ReadBits(1) == 1); if (m_Extension.m_SbrPresent) { result = ParseSamplingFrequency(parser, m_Extension.m_SamplingFrequencyIndex, m_Extension.m_SamplingFrequency); if (AP4_FAILED(result)) return result; } parser.ReadBits(4); // extensionChannelConfiguration } } return AP4_SUCCESS; } /*---------------------------------------------------------------------- | AP4_Mp4AudioDecoderConfig::ParseGASpecificInfo +---------------------------------------------------------------------*/ AP4_Result AP4_Mp4AudioDecoderConfig::ParseGASpecificInfo(AP4_Mp4AudioDsiParser& parser) { if (parser.BitsLeft() < 2) return AP4_ERROR_INVALID_FORMAT; m_FrameLengthFlag = (parser.ReadBits(1) == 1); m_DependsOnCoreCoder = (parser.ReadBits(1) == 1); if (m_DependsOnCoreCoder) { if (parser.BitsLeft() < 14) return AP4_ERROR_INVALID_FORMAT; m_CoreCoderDelay = parser.ReadBits(14); } else { m_CoreCoderDelay = 0; } if (parser.BitsLeft() < 1) return AP4_ERROR_INVALID_FORMAT; unsigned int extensionFlag = parser.ReadBits(1); if (m_ChannelConfiguration == CHANNEL_CONFIG_NONE) { /*program_config_element (); */ return AP4_ERROR_NOT_SUPPORTED; } if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SCALABLE || m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE) { if (parser.BitsLeft() < 3) return AP4_ERROR_INVALID_FORMAT; parser.ReadBits(3); // layerNr } if (extensionFlag) { if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) { if (parser.BitsLeft() < 16) return AP4_ERROR_INVALID_FORMAT; parser.ReadBits(16); // numOfSubFrame (5); layer_length (11) } if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LC || m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE || m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LD) { if (parser.BitsLeft() < 3) return AP4_ERROR_INVALID_FORMAT; parser.ReadBits(3); // aacSectionDataResilienceFlag (1) // aacScalefactorDataResilienceFlag (1) // aacSpectralDataResilienceFlag (1) } if (parser.BitsLeft() < 1) return AP4_ERROR_INVALID_FORMAT; unsigned int extensionFlag3 = parser.ReadBits(1); if (extensionFlag3) { return AP4_ERROR_NOT_SUPPORTED; } } return AP4_SUCCESS; } /*---------------------------------------------------------------------- | AP4_Mp4AudioDecoderConfig::ParseSamplingFrequency +---------------------------------------------------------------------*/ AP4_Result AP4_Mp4AudioDecoderConfig::ParseSamplingFrequency(AP4_Mp4AudioDsiParser& parser, unsigned int& sampling_frequency_index, unsigned int& sampling_frequency) { if (parser.BitsLeft() < 4) { return AP4_ERROR_INVALID_FORMAT; } sampling_frequency_index = parser.ReadBits(4); if (sampling_frequency_index == 0xF) { if (parser.BitsLeft() < 24) { return AP4_ERROR_INVALID_FORMAT; } sampling_frequency = parser.ReadBits(24); } else if (sampling_frequency_index <= AP4_AAC_MAX_SAMPLING_FREQUENCY_INDEX) { sampling_frequency = AP4_AacSamplingFreqTable[sampling_frequency_index]; } else { sampling_frequency = 0; return AP4_ERROR_INVALID_FORMAT; } return AP4_SUCCESS; } /*---------------------------------------------------------------------- | AP4_Mp4AudioDecoderConfig::Parse +---------------------------------------------------------------------*/ AP4_Result AP4_Mp4AudioDecoderConfig::Parse(const unsigned char* data, AP4_Size data_size) { AP4_Result result; AP4_Mp4AudioDsiParser bits(data, data_size); // default config Reset(); // parse the audio object type result = ParseAudioObjectType(bits, m_ObjectType); if (AP4_FAILED(result)) return result; // parse the sampling frequency result = ParseSamplingFrequency(bits, m_SamplingFrequencyIndex, m_SamplingFrequency); if (AP4_FAILED(result)) return result; if (bits.BitsLeft() < 4) { return AP4_ERROR_INVALID_FORMAT; } m_ChannelConfiguration = (ChannelConfiguration)bits.ReadBits(4); m_ChannelCount = (unsigned int)m_ChannelConfiguration; if (m_ChannelCount == 7) { m_ChannelCount = 8; } else if (m_ChannelCount > 7) { m_ChannelCount = 0; } if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR || m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_PS) { m_Extension.m_ObjectType = AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR; m_Extension.m_SbrPresent = true; m_Extension.m_PsPresent = m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_PS; result = ParseSamplingFrequency(bits, m_Extension.m_SamplingFrequencyIndex, m_Extension.m_SamplingFrequency); if (AP4_FAILED(result)) return result; result = ParseAudioObjectType(bits, m_ObjectType); if (AP4_FAILED(result)) return result; if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) { if (bits.BitsLeft() < 4) return AP4_ERROR_INVALID_FORMAT; bits.ReadBits(4); // extensionChannelConfiguration (4) } } else { m_Extension.m_ObjectType = 0; m_Extension.m_SamplingFrequency = 0; m_Extension.m_SamplingFrequencyIndex = 0; m_Extension.m_SbrPresent = false; m_Extension.m_PsPresent = false; } switch (m_ObjectType) { case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_MAIN: case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LC: case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SSR: case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LTP: case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SCALABLE: case AP4_MPEG4_AUDIO_OBJECT_TYPE_TWINVQ: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LC: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LTP: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LD: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_TWINVQ: case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC: case AP4_MPEG4_AUDIO_OBJECT_TYPE_USAC: result = ParseGASpecificInfo(bits); if (result == AP4_SUCCESS) { if (m_Extension.m_ObjectType != AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR && bits.BitsLeft() >= 16) { result = ParseExtension(bits); } } if (result == AP4_ERROR_NOT_SUPPORTED) { // not a fatal error result = AP4_SUCCESS; } if (result != AP4_SUCCESS) return result; break; default: return AP4_ERROR_NOT_SUPPORTED; } return AP4_SUCCESS; }