Files
Bento4/Source/C++/Codecs/Ap4Mp4AudioInfo.cpp

334 lines
13 KiB
C++

/*****************************************************************
|
| 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<<chunk_size)-1);
result = (result << chunk_size) | chunk_bits;
n -= chunk_size;
m_Position += chunk_size;
}
return result;
}
private:
AP4_DataBuffer m_Data;
unsigned int m_Position;
};
/*----------------------------------------------------------------------
| AP4_Mp4AudioDecoderConfig::AP4_Mp4AudioDecoderConfig
+---------------------------------------------------------------------*/
AP4_Mp4AudioDecoderConfig::AP4_Mp4AudioDecoderConfig()
{
Reset();
}
/*----------------------------------------------------------------------
| AP4_Mp4AudioDecoderConfig::Reset
+---------------------------------------------------------------------*/
void
AP4_Mp4AudioDecoderConfig::Reset()
{
m_ObjectType = 0;
m_SamplingFrequencyIndex = 0;
m_SamplingFrequency = 0;
m_ChannelCount = 0;
m_ChannelConfiguration = CHANNEL_CONFIG_NONE;
m_FrameLengthFlag = false;
m_DependsOnCoreCoder = false;
m_CoreCoderDelay = 0;
m_Extension.m_SbrPresent = false;
m_Extension.m_PsPresent = false;
m_Extension.m_ObjectType = 0;
m_Extension.m_SamplingFrequencyIndex = 0;
m_Extension.m_SamplingFrequency = 0;
}
/*----------------------------------------------------------------------
| AP4_Mp4AudioDecoderConfig::ParseAudioObjectType
+---------------------------------------------------------------------*/
AP4_Result
AP4_Mp4AudioDecoderConfig::ParseAudioObjectType(AP4_Mp4AudioDsiParser& parser, AP4_UI08& object_type)
{
if (parser.BitsLeft() < 5) return AP4_ERROR_INVALID_FORMAT;
object_type = (AP4_UI08)parser.ReadBits(5);
if ((int)object_type == 31) {
if (parser.BitsLeft() < 6) return AP4_ERROR_INVALID_FORMAT;
object_type = (AP4_UI08)(32 + parser.ReadBits(6));
}
return AP4_SUCCESS;
}
/*----------------------------------------------------------------------
| AP4_Mp4AudioDecoderConfig::ParseExtension
+---------------------------------------------------------------------*/
AP4_Result
AP4_Mp4AudioDecoderConfig::ParseExtension(AP4_Mp4AudioDsiParser& parser)
{
if (parser.BitsLeft() < 16) return AP4_ERROR_INVALID_FORMAT;
unsigned int sync_extension_type = parser.ReadBits(11);
if (sync_extension_type == 0x2b7) {
AP4_Result result = ParseAudioObjectType(parser, m_Extension.m_ObjectType);
if (AP4_FAILED(result)) return result;
if (m_Extension.m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR) {
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;
if (parser.BitsLeft() >= 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) {
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:
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;
}