665 lines
19 KiB
C
665 lines
19 KiB
C
|
#include "mpeg4-aac.h"
|
|||
|
#include "mpeg4-bits.h"
|
|||
|
#include <assert.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <errno.h>
|
|||
|
|
|||
|
// Table 4.85 - Syntactic elements (p533)
|
|||
|
enum {
|
|||
|
ID_SCE = 0x0, // single channel element()
|
|||
|
ID_CPE = 0x1, // channel_pair_element()
|
|||
|
ID_CCE = 0x2, // coupling_channel_element()
|
|||
|
ID_LFE = 0x3, // lfe_channel_element()
|
|||
|
ID_DSE = 0x4, // data_stream_element()
|
|||
|
ID_PCE = 0x5, // program_config_element()
|
|||
|
ID_FIL = 0x6, // fill_element()
|
|||
|
ID_END = 0x7,
|
|||
|
};
|
|||
|
|
|||
|
// ISO-14496-3 4.4.1.1 Program config element (p488)
|
|||
|
// There may be up to 16 such elements per raw data block, each one must have a unique element_instance_tag
|
|||
|
// PCEs must come before all other syntactic elements in a raw_data_block().
|
|||
|
/*
|
|||
|
program_config_element()
|
|||
|
{
|
|||
|
element_instance_tag; 4 uimsbf
|
|||
|
object_type; 2 uimsbf
|
|||
|
sampling_frequency_index; 4 uimsbf
|
|||
|
num_front_channel_elements; 4 uimsbf
|
|||
|
num_side_channel_elements; 4 uimsbf
|
|||
|
num_back_channel_elements; 4 uimsbf
|
|||
|
num_lfe_channel_elements; 2 uimsbf
|
|||
|
num_assoc_data_elements; 3 uimsbf
|
|||
|
num_valid_cc_elements; 4 uimsbf
|
|||
|
mono_mixdown_present; 1 uimsbf
|
|||
|
if (mono_mixdown_present == 1 )
|
|||
|
mono_mixdown_element_number; 4 uimsbf
|
|||
|
stereo_mixdown_present; 1 uimsbf
|
|||
|
if (stereo_mixdown_present == 1 )
|
|||
|
stereo_mixdown_element_number; 4 uimsbf
|
|||
|
matrix_mixdown_idx_present; 1 uimsbf
|
|||
|
if (matrix_mixdown_idx_present == 1 ) {
|
|||
|
matrix_mixdown_idx ; 2 uimsbf
|
|||
|
pseudo_surround_enable; 1 uimsbf
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_front_channel_elements; i++) {
|
|||
|
front_element_is_cpe[i]; 1 bslbf
|
|||
|
front_element_tag_select[i]; 4 uimsbf
|
|||
|
}
|
|||
|
for (i = 0; i < num_side_channel_elements; i++) {
|
|||
|
side_element_is_cpe[i]; 1 bslbf
|
|||
|
side_element_tag_select[i]; 4 uimsbf
|
|||
|
}
|
|||
|
for (i = 0; i < num_back_channel_elements; i++) {
|
|||
|
back_element_is_cpe[i]; 1 bslbf
|
|||
|
back_element_tag_select[i]; 4 uimsbf
|
|||
|
}
|
|||
|
for (i = 0; i < num_lfe_channel_elements; i++)
|
|||
|
lfe_element_tag_select[i]; 4 uimsbf
|
|||
|
for ( i = 0; i < num_assoc_data_elements; i++)
|
|||
|
assoc_data_element_tag_select[i]; 4 uimsbf
|
|||
|
for (i = 0; i < num_valid_cc_elements; i++) {
|
|||
|
cc_element_is_ind_sw[i]; 1 uimsbf
|
|||
|
valid_cc_element_tag_select[i]; 4 uimsbf
|
|||
|
}
|
|||
|
byte_alignment(); Note 1
|
|||
|
comment_field_bytes; 8 uimsbf
|
|||
|
for (i = 0; i < comment_field_bytes; i++)
|
|||
|
comment_field_data[i]; 8 uimsbf
|
|||
|
}
|
|||
|
*/
|
|||
|
static inline uint64_t mpeg4_bits_copy(struct mpeg4_bits_t* dst, struct mpeg4_bits_t* src, int n)
|
|||
|
{
|
|||
|
uint64_t v;
|
|||
|
v = mpeg4_bits_read_n(src, n);
|
|||
|
mpeg4_bits_write_n(dst, v, n);
|
|||
|
return v;
|
|||
|
}
|
|||
|
|
|||
|
static int mpeg4_aac_pce_load(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac, struct mpeg4_bits_t* pce)
|
|||
|
{
|
|||
|
uint64_t i, cpe, tag;
|
|||
|
uint64_t element_instance_tag;
|
|||
|
uint64_t object_type;
|
|||
|
uint64_t sampling_frequency_index;
|
|||
|
uint64_t num_front_channel_elements;
|
|||
|
uint64_t num_side_channel_elements;
|
|||
|
uint64_t num_back_channel_elements;
|
|||
|
uint64_t num_lfe_channel_elements;
|
|||
|
uint64_t num_assoc_data_elements;
|
|||
|
uint64_t num_valid_cc_elements;
|
|||
|
uint64_t comment_field_bytes;
|
|||
|
|
|||
|
aac->channels = 0;
|
|||
|
element_instance_tag = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
object_type = mpeg4_bits_copy(pce, bits, 2);
|
|||
|
sampling_frequency_index = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
num_front_channel_elements = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
num_side_channel_elements = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
num_back_channel_elements = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
num_lfe_channel_elements = mpeg4_bits_copy(pce, bits, 2);
|
|||
|
num_assoc_data_elements = mpeg4_bits_copy(pce, bits, 3);
|
|||
|
num_valid_cc_elements = mpeg4_bits_copy(pce, bits, 4);
|
|||
|
|
|||
|
if (mpeg4_bits_copy(pce, bits, 1))
|
|||
|
mpeg4_bits_copy(pce, bits, 4); // MONO
|
|||
|
if (mpeg4_bits_copy(pce, bits, 1))
|
|||
|
mpeg4_bits_copy(pce, bits, 4); // STEREO
|
|||
|
if (mpeg4_bits_copy(pce, bits, 1))
|
|||
|
mpeg4_bits_copy(pce, bits, 3); // Matrix, Pseudo surround
|
|||
|
|
|||
|
for (i = 0; i < num_front_channel_elements; i++)
|
|||
|
{
|
|||
|
cpe = mpeg4_bits_copy(pce, bits, 1); // front_element_is_cpe
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // front_element_tag_select
|
|||
|
aac->channels += (cpe || aac->ps) ? 2 : 1;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_side_channel_elements; i++)
|
|||
|
{
|
|||
|
cpe = mpeg4_bits_copy(pce, bits, 1); // side_element_is_cpe
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // side_element_tag_select
|
|||
|
aac->channels += (cpe || aac->ps) ? 2 : 1;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_back_channel_elements; i++)
|
|||
|
{
|
|||
|
cpe = mpeg4_bits_copy(pce, bits, 1); // back_element_is_cpe
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // back_element_tag_select
|
|||
|
aac->channels += (cpe || aac->ps) ? 2 : 1;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_lfe_channel_elements; i++)
|
|||
|
{
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // lfe_element_tag_select
|
|||
|
aac->channels += 1;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_assoc_data_elements; i++)
|
|||
|
{
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // assoc_data_element_tag_select
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < num_valid_cc_elements; i++)
|
|||
|
{
|
|||
|
cpe = mpeg4_bits_copy(pce, bits, 1); // cc_element_is_ind_sw
|
|||
|
tag = mpeg4_bits_copy(pce, bits, 4); // valid_cc_element_tag_select
|
|||
|
}
|
|||
|
|
|||
|
mpeg4_bits_aligment(bits, 8); // byte_alignment();
|
|||
|
mpeg4_bits_aligment(pce, 8);
|
|||
|
|
|||
|
comment_field_bytes = mpeg4_bits_copy(pce, bits, 8);
|
|||
|
for (i = 0; i < comment_field_bytes; i++)
|
|||
|
mpeg4_bits_copy(pce, bits, 8); // comment_field_data
|
|||
|
|
|||
|
assert(aac->sampling_frequency_index == sampling_frequency_index);
|
|||
|
assert(aac->profile == object_type + 1);
|
|||
|
return (int)((pce->bits + 7) / 8);
|
|||
|
}
|
|||
|
|
|||
|
// 4.4.1 Decoder configuration (GASpecificConfig) (p487)
|
|||
|
/*
|
|||
|
GASpecificConfig (samplingFrequencyIndex, channelConfiguration, audioObjectType)
|
|||
|
{
|
|||
|
frameLengthFlag; 1 bslbf
|
|||
|
dependsOnCoreCoder; 1 bslbf
|
|||
|
if (dependsOnCoreCoder) {
|
|||
|
coreCoderDelay; 14 uimsbf
|
|||
|
}
|
|||
|
extensionFlag; 1 bslbf
|
|||
|
if (! channelConfiguration) {
|
|||
|
program_config_element ();
|
|||
|
}
|
|||
|
if ((audioObjectType == 6) || (audioObjectType == 20)) {
|
|||
|
layerNr; 3 uimsbf
|
|||
|
}
|
|||
|
if (extensionFlag) {
|
|||
|
if (audioObjectType == 22) {
|
|||
|
numOfSubFrame; 5 bslbf
|
|||
|
layer_length; 11 bslbf
|
|||
|
}
|
|||
|
if (audioObjectType == 17 || audioObjectType == 19 || audioObjectType == 20 || audioObjectType == 23) {
|
|||
|
aacSectionDataResilienceFlag; 1 bslbf
|
|||
|
aacScalefactorDataResilienceFlag; 1 bslbf
|
|||
|
aacSpectralDataResilienceFlag; 1 bslbf
|
|||
|
}
|
|||
|
extensionFlag3; 1 bslbf
|
|||
|
if (extensionFlag3) {
|
|||
|
// tbd in version 3
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
static int mpeg4_aac_ga_specific_config_load(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
int extensionFlag;
|
|||
|
struct mpeg4_bits_t pce;
|
|||
|
|
|||
|
mpeg4_bits_read(bits); // frameLengthFlag
|
|||
|
if (mpeg4_bits_read(bits)) // dependsOnCoreCoder
|
|||
|
mpeg4_bits_read_uint16(bits, 14); // coreCoderDelay
|
|||
|
extensionFlag = mpeg4_bits_read(bits); // extensionFlag
|
|||
|
|
|||
|
if (0 == aac->channel_configuration)
|
|||
|
{
|
|||
|
mpeg4_bits_init(&pce, aac->pce, sizeof(aac->pce));
|
|||
|
aac->npce = mpeg4_aac_pce_load(bits, aac, &pce); // update channel count
|
|||
|
}
|
|||
|
|
|||
|
if (6 == aac->profile || 20 == aac->profile)
|
|||
|
mpeg4_bits_read_uint8(bits, 3); // layerNr
|
|||
|
|
|||
|
if (extensionFlag)
|
|||
|
{
|
|||
|
if (22 == aac->profile)
|
|||
|
{
|
|||
|
mpeg4_bits_read_uint8(bits, 5); // numOfSubFrame
|
|||
|
mpeg4_bits_read_uint16(bits, 11); // layer_length
|
|||
|
}
|
|||
|
|
|||
|
if (17 == aac->profile || 19 == aac->profile || 20 == aac->profile || 23 == aac->profile)
|
|||
|
{
|
|||
|
mpeg4_bits_read(bits); // aacSectionDataResilienceFlag
|
|||
|
mpeg4_bits_read(bits); // aacScalefactorDataResilienceFlag
|
|||
|
mpeg4_bits_read(bits); // aacSpectralDataResilienceFlag
|
|||
|
}
|
|||
|
|
|||
|
if (mpeg4_bits_read(bits)) // extensionFlag3
|
|||
|
{
|
|||
|
// tbd in version 3
|
|||
|
assert(0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return mpeg4_bits_error(bits);
|
|||
|
}
|
|||
|
|
|||
|
static int mpeg4_aac_celp_specific_config_load(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
int ExcitationMode;
|
|||
|
if (mpeg4_bits_read(bits)) // isBaseLayer
|
|||
|
{
|
|||
|
// CelpHeader
|
|||
|
|
|||
|
ExcitationMode = mpeg4_bits_read(bits);
|
|||
|
mpeg4_bits_read(bits); // SampleRateMode
|
|||
|
mpeg4_bits_read(bits); // FineRateControl
|
|||
|
|
|||
|
// Table 3.50 - Description of ExcitationMode
|
|||
|
if (ExcitationMode == 1 /*RPE*/)
|
|||
|
{
|
|||
|
mpeg4_bits_read_n(bits, 3); // RPE_Configuration
|
|||
|
}
|
|||
|
if (ExcitationMode == 0 /*MPE*/)
|
|||
|
{
|
|||
|
mpeg4_bits_read_n(bits, 5); // MPE_Configuration
|
|||
|
mpeg4_bits_read_n(bits, 2); // NumEnhLayers
|
|||
|
mpeg4_bits_read(bits); // BandwidthScalabilityMode
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (mpeg4_bits_read(bits)) // isBWSLayer
|
|||
|
mpeg4_bits_read_n(bits, 2); // BWS_configuration
|
|||
|
else
|
|||
|
mpeg4_bits_read_n(bits, 2); // CELP-BRS-id
|
|||
|
}
|
|||
|
|
|||
|
(void)aac;
|
|||
|
return mpeg4_bits_error(bits);
|
|||
|
}
|
|||
|
|
|||
|
// ISO/IEC 23003-1 Table 9.1 <20><> Syntax of SpatialSpecificConfig()
|
|||
|
/*
|
|||
|
SpatialSpecificConfig()
|
|||
|
{
|
|||
|
bsSamplingFrequencyIndex; 4 uimsbf
|
|||
|
if ( bsSamplingFrequencyIndex == 0xf ) {
|
|||
|
bsSamplingFrequency; 24 uimsbf
|
|||
|
}
|
|||
|
bsFrameLength; 7 uimsbf
|
|||
|
bsFreqRes; 3 uimsbf
|
|||
|
bsTreeConfig; 4 uimsbf
|
|||
|
if (bsTreeConfig == <EFBFBD><EFBFBD>0111<EFBFBD><EFBFBD>) {
|
|||
|
bsNumInCh; 4 uimsbf
|
|||
|
bsNumLFE 2 uimsbf
|
|||
|
bsHasSpeakerConfig 1 uimsbf
|
|||
|
if ( bsHasSpeakerConfig == 1 ) {
|
|||
|
audioChannelLayout = SpeakerConfig3d(); Note 1
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bsQuantMode; 2 uimsbf
|
|||
|
bsOneIcc; 1 uimsbf
|
|||
|
bsArbitraryDownmix; 1 uimsbf
|
|||
|
bsFixedGainSur; 3 uimsbf
|
|||
|
bsFixedGainLFE; 3 uimsbf
|
|||
|
bsFixedGainDMX; 3 uimsbf
|
|||
|
bsMatrixMode; 1 uimsbf
|
|||
|
bsTempShapeConfig; 2 uimsbf
|
|||
|
bsDecorrConfig; 2 uimsbf
|
|||
|
bs3DaudioMode; 1 uimsbf
|
|||
|
|
|||
|
if ( bsTreeConfig == <EFBFBD><EFBFBD>0111<EFBFBD><EFBFBD> ) {
|
|||
|
for (i=0; i< NumInCh - NumLfe; i++) {
|
|||
|
defaultCld[i] = 1;
|
|||
|
ottModelfe[i] = 0;
|
|||
|
}
|
|||
|
for (i= NumInCh - NumLfe; i< NumInCh; i++) {
|
|||
|
defaultCld[i] = 1;
|
|||
|
ottModelfe[i] = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (i=0; i<numOttBoxes; i++) { Note 2
|
|||
|
OttConfig(i);
|
|||
|
}
|
|||
|
for (i=0; i<numTttBoxes; i++) { Note 2
|
|||
|
TttConfig(i);
|
|||
|
}
|
|||
|
if (bsTempShapeConfig == 2) {
|
|||
|
bsEnvQuantMode 1 uimsbf
|
|||
|
}
|
|||
|
if (bs3DaudioMode) {
|
|||
|
bs3DaudioHRTFset; 2 uimsbf
|
|||
|
if (bs3DaudioHRTFset==0) {
|
|||
|
ParamHRTFset();
|
|||
|
}
|
|||
|
}
|
|||
|
ByteAlign();
|
|||
|
SpatialExtensionConfig();
|
|||
|
}
|
|||
|
*/
|
|||
|
static int SpatialSpecificConfig(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
static inline uint8_t mpeg4_aac_get_audio_object_type(struct mpeg4_bits_t* bits)
|
|||
|
{
|
|||
|
uint8_t audioObjectType;
|
|||
|
audioObjectType = mpeg4_bits_read_uint8(bits, 5);
|
|||
|
if (31 == audioObjectType)
|
|||
|
audioObjectType = 32 + mpeg4_bits_read_uint8(bits, 6);
|
|||
|
return audioObjectType;
|
|||
|
}
|
|||
|
|
|||
|
static inline uint8_t mpeg4_aac_get_sampling_frequency(struct mpeg4_bits_t* bits)
|
|||
|
{
|
|||
|
uint8_t samplingFrequencyIndex;
|
|||
|
uint32_t samplingFrequency;
|
|||
|
samplingFrequencyIndex = mpeg4_bits_read_uint8(bits, 4);
|
|||
|
if (0x0F == samplingFrequencyIndex)
|
|||
|
samplingFrequency = mpeg4_bits_read_uint32(bits, 24);
|
|||
|
return samplingFrequencyIndex;
|
|||
|
}
|
|||
|
|
|||
|
/// @return asc bits
|
|||
|
static size_t mpeg4_aac_audio_specific_config_load3(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
uint16_t syncExtensionType;
|
|||
|
// uint8_t audioObjectType;
|
|||
|
// uint8_t samplingFrequencyIndex = 0;
|
|||
|
uint8_t extensionSamplingFrequencyIndex = 0;
|
|||
|
// uint8_t channelConfiguration = 0;
|
|||
|
uint8_t epConfig;
|
|||
|
size_t offset;
|
|||
|
|
|||
|
offset = bits->bits;
|
|||
|
aac->profile = mpeg4_aac_get_audio_object_type(bits);
|
|||
|
aac->sampling_frequency_index = mpeg4_aac_get_sampling_frequency(bits);
|
|||
|
aac->channel_configuration = mpeg4_bits_read_uint8(bits, 4);
|
|||
|
aac->channels = mpeg4_aac_channel_count(aac->channel_configuration);
|
|||
|
aac->sampling_frequency = mpeg4_aac_audio_frequency_to(aac->sampling_frequency_index);
|
|||
|
aac->extension_frequency = aac->sampling_frequency;
|
|||
|
aac->extension_channel_configuration = aac->channel_configuration;
|
|||
|
|
|||
|
if (5 == aac->profile || 29 == aac->profile)
|
|||
|
{
|
|||
|
aac->extension_audio_object_type = 5;
|
|||
|
aac->sbr = 1;
|
|||
|
if (29 == aac->profile)
|
|||
|
aac->ps = 1;
|
|||
|
extensionSamplingFrequencyIndex = mpeg4_aac_get_sampling_frequency(bits);
|
|||
|
aac->extension_frequency = mpeg4_aac_audio_frequency_to(extensionSamplingFrequencyIndex);
|
|||
|
aac->profile = mpeg4_aac_get_audio_object_type(bits);
|
|||
|
if (22 == aac->profile)
|
|||
|
aac->extension_channel_configuration = mpeg4_bits_read_uint8(bits, 4);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
aac->extension_audio_object_type = 0;
|
|||
|
}
|
|||
|
|
|||
|
switch (aac->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:
|
|||
|
mpeg4_aac_ga_specific_config_load(bits, aac);
|
|||
|
break;
|
|||
|
|
|||
|
case 8:
|
|||
|
mpeg4_aac_celp_specific_config_load(bits, aac);
|
|||
|
break;
|
|||
|
|
|||
|
case 30:
|
|||
|
/*sacPayloadEmbedding=*/ mpeg4_bits_read(bits);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
assert(0);
|
|||
|
return bits->bits - offset;
|
|||
|
}
|
|||
|
|
|||
|
switch (aac->profile)
|
|||
|
{
|
|||
|
case 17: case 19: case 20: case 21: case 22:
|
|||
|
case 23: case 24: case 25: case 26: case 27: case 39:
|
|||
|
epConfig = mpeg4_bits_read_uint8(bits, 2);
|
|||
|
if (2 == epConfig || 3 == epConfig)
|
|||
|
{
|
|||
|
// 1.8.2.1 Error protection specific configuration (p96)
|
|||
|
// TODO: ErrorProtectionSpecificConfig();
|
|||
|
assert(0);
|
|||
|
}
|
|||
|
if (3 == epConfig)
|
|||
|
{
|
|||
|
if (mpeg4_bits_read(bits)) // directMapping
|
|||
|
{
|
|||
|
// tbd
|
|||
|
assert(0);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break; // do nothing;
|
|||
|
}
|
|||
|
|
|||
|
if (5 != aac->extension_audio_object_type && mpeg4_bits_remain(bits) >= 16)
|
|||
|
{
|
|||
|
syncExtensionType = mpeg4_bits_read_uint16(bits, 11);
|
|||
|
if (0x2b7 == syncExtensionType)
|
|||
|
{
|
|||
|
aac->extension_audio_object_type = mpeg4_aac_get_audio_object_type(bits);
|
|||
|
if (5 == aac->extension_audio_object_type)
|
|||
|
{
|
|||
|
aac->sbr = mpeg4_bits_read(bits);
|
|||
|
if (aac->sbr)
|
|||
|
{
|
|||
|
extensionSamplingFrequencyIndex = mpeg4_aac_get_sampling_frequency(bits);
|
|||
|
aac->extension_frequency = mpeg4_aac_audio_frequency_to(extensionSamplingFrequencyIndex);
|
|||
|
if (mpeg4_bits_remain(bits) >= 12)
|
|||
|
{
|
|||
|
syncExtensionType = mpeg4_bits_read_uint16(bits, 11);
|
|||
|
if (0x548 == syncExtensionType)
|
|||
|
aac->ps = mpeg4_bits_read(bits);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (22 == aac->extension_audio_object_type)
|
|||
|
{
|
|||
|
aac->sbr = mpeg4_bits_read(bits);
|
|||
|
if (aac->sbr)
|
|||
|
{
|
|||
|
extensionSamplingFrequencyIndex = mpeg4_aac_get_sampling_frequency(bits);
|
|||
|
aac->extension_frequency = mpeg4_aac_audio_frequency_to(extensionSamplingFrequencyIndex);
|
|||
|
}
|
|||
|
aac->extension_channel_configuration = mpeg4_bits_read_uint8(bits, 4);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return bits->bits - offset;
|
|||
|
}
|
|||
|
|
|||
|
int mpeg4_aac_audio_specific_config_load2(const uint8_t* data, size_t bytes, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
struct mpeg4_bits_t bits;
|
|||
|
mpeg4_bits_init(&bits, (void*)data, bytes);
|
|||
|
mpeg4_aac_audio_specific_config_load3(&bits, aac);
|
|||
|
mpeg4_bits_aligment(&bits, 8);
|
|||
|
return mpeg4_bits_error(&bits) ? -1 : (int)(bits.bits / 8);
|
|||
|
}
|
|||
|
|
|||
|
int mpeg4_aac_audio_specific_config_save2(const struct mpeg4_aac_t* aac, uint8_t* data, size_t bytes)
|
|||
|
{
|
|||
|
if (bytes < 2 + (size_t)aac->npce)
|
|||
|
return -1;
|
|||
|
|
|||
|
memcpy(data + 2, aac->pce, aac->npce);
|
|||
|
return 2 + aac->npce;
|
|||
|
//data[2 + aac->npce] = 0x56;
|
|||
|
//data[2 + aac->npce + 1] = 0xe5;
|
|||
|
//data[2 + aac->npce + 2] = 0x00;
|
|||
|
//return 2 + aac->npce + 3;
|
|||
|
}
|
|||
|
|
|||
|
int mpeg4_aac_adts_pce_load(const uint8_t* data, size_t bytes, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
int i;
|
|||
|
size_t offset = 7;
|
|||
|
struct mpeg4_bits_t bits, pce;
|
|||
|
|
|||
|
if (0 == (data[1] & 0x01)) // protection_absent
|
|||
|
{
|
|||
|
// number_of_raw_data_blocks_in_frame
|
|||
|
for (i = 1; i <= (data[6] & 0x03); i++)
|
|||
|
offset += 2; // raw_data_block_position 16-bits
|
|||
|
offset += 2; // crc_check 16-bits
|
|||
|
}
|
|||
|
|
|||
|
if (bytes <= offset)
|
|||
|
return (int)offset;
|
|||
|
|
|||
|
mpeg4_bits_init(&bits, (uint8_t*)data + offset, bytes - offset);
|
|||
|
if (ID_PCE == mpeg4_bits_read_uint8(&bits, 3))
|
|||
|
{
|
|||
|
mpeg4_bits_init(&pce, aac->pce, sizeof(aac->pce));
|
|||
|
aac->npce = mpeg4_aac_pce_load(&bits, aac, &pce);
|
|||
|
return mpeg4_bits_error(&bits) ? -1 : (int)(7 + (pce.bits + 7) / 8);
|
|||
|
}
|
|||
|
return 7;
|
|||
|
}
|
|||
|
|
|||
|
int mpeg4_aac_adts_pce_save(uint8_t* data, size_t bytes, const struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
struct mpeg4_aac_t src;
|
|||
|
struct mpeg4_bits_t pce, adts;
|
|||
|
if ((size_t)aac->npce + 7 > bytes)
|
|||
|
return 0;
|
|||
|
memcpy(&src, aac, sizeof(src));
|
|||
|
// assert(data[1] & 0x01); // disable protection_absent
|
|||
|
mpeg4_bits_init(&pce, (uint8_t*)aac->pce, aac->npce);
|
|||
|
mpeg4_bits_init(&adts, (uint8_t*)data + 7, bytes - 7);
|
|||
|
mpeg4_bits_write_uint8(&adts, ID_PCE, 3);
|
|||
|
mpeg4_aac_pce_load(&pce, &src, &adts);
|
|||
|
assert(src.channels == aac->channels && (adts.bits + 7) / 8 <= bytes);
|
|||
|
return mpeg4_bits_error(&pce) ? 0 : (int)((adts.bits+7) / 8);
|
|||
|
}
|
|||
|
|
|||
|
static size_t mpeg4_aac_stream_mux_config_load3(struct mpeg4_bits_t* bits, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
uint8_t audioMuxVersion = 0;
|
|||
|
uint8_t numSubFrames;
|
|||
|
uint8_t numProgram;
|
|||
|
uint8_t numLayer;
|
|||
|
uint8_t allStreamsSameTimeFraming;
|
|||
|
uint8_t profile = 0;
|
|||
|
uint64_t ascLen;
|
|||
|
size_t offset;
|
|||
|
int streamCnt, prog, lay;
|
|||
|
|
|||
|
offset = bits->bits;
|
|||
|
audioMuxVersion = (uint8_t)mpeg4_bits_read(bits);
|
|||
|
if (!audioMuxVersion || 0 == mpeg4_bits_read(bits))
|
|||
|
{
|
|||
|
if (1 == audioMuxVersion)
|
|||
|
/*taraBufferFullness =*/ mpeg4_bits_read_latm(bits);
|
|||
|
|
|||
|
streamCnt = 0;
|
|||
|
allStreamsSameTimeFraming = (uint8_t)mpeg4_bits_read(bits);
|
|||
|
numSubFrames = (uint8_t)mpeg4_bits_read_n(bits, 6);
|
|||
|
numProgram = (uint8_t)mpeg4_bits_read_n(bits, 4);
|
|||
|
for (prog = 0; prog <= numProgram; prog++)
|
|||
|
{
|
|||
|
numLayer = (uint8_t)mpeg4_bits_read_n(bits, 3);
|
|||
|
for (lay = 0; lay <= numLayer; lay++)
|
|||
|
{
|
|||
|
//progSIndx[streamCnt] = prog;
|
|||
|
//laySIndx[streamCnt] = lay;
|
|||
|
//streamID[prog][lay] = streamCnt++;
|
|||
|
if ( (prog == 0 && lay == 0) || 0 == (uint8_t)mpeg4_bits_read(bits))
|
|||
|
{
|
|||
|
profile = aac->profile; // previous profile
|
|||
|
if (audioMuxVersion == 0) {
|
|||
|
mpeg4_aac_audio_specific_config_load3(bits, aac);
|
|||
|
} else {
|
|||
|
ascLen = mpeg4_bits_read_latm(bits);
|
|||
|
ascLen -= mpeg4_aac_audio_specific_config_load3(bits, aac);
|
|||
|
mpeg4_bits_skip(bits, (size_t)ascLen);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//frameLengthType[streamID[prog][lay]] = (uint8_t)mpeg4_bits_read_n(bits, 3);
|
|||
|
//switch (frameLengthType[streamID[prog][lay]])
|
|||
|
switch (mpeg4_bits_read_n(bits, 3))
|
|||
|
{
|
|||
|
case 0:
|
|||
|
/*latmBufferFullness[streamID[prog][lay]] =*/ (uint8_t)mpeg4_bits_read_n(bits, 8);
|
|||
|
if (!allStreamsSameTimeFraming)
|
|||
|
{
|
|||
|
// fixme
|
|||
|
//if ((AudioObjectType[lay] == 6 || AudioObjectType[lay] == 20) &&
|
|||
|
// (AudioObjectType[lay - 1] == 8 || AudioObjectType[lay - 1] == 24))
|
|||
|
if( (aac->profile == 6 || aac->profile == 20) && (profile == 8 || profile == 24) )
|
|||
|
{
|
|||
|
/*coreFrameOffset =*/ (uint8_t)mpeg4_bits_read_n(bits, 6);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 1:
|
|||
|
/*frameLength[streamID[prog][lay]] =*/ (uint16_t)mpeg4_bits_read_n(bits, 9);
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
case 4:
|
|||
|
case 5:
|
|||
|
/*CELPframeLengthTableIndex[streamID[prog][lay]] =*/ (uint16_t)mpeg4_bits_read_n(bits, 6);
|
|||
|
break;
|
|||
|
|
|||
|
case 6:
|
|||
|
case 7:
|
|||
|
/*HVXCframeLengthTableIndex[streamID[prog][lay]] =*/ (uint16_t)mpeg4_bits_read_n(bits, 1);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
// nothing to do
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// otherDataPresent
|
|||
|
if (mpeg4_bits_read(bits))
|
|||
|
{
|
|||
|
if (audioMuxVersion == 1)
|
|||
|
{
|
|||
|
/*otherDataLenBits =*/ mpeg4_bits_read_latm(bits);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*otherDataLenBits =*/ mpeg4_bits_read_n(bits, 8); /* helper variable 32bit */
|
|||
|
while(mpeg4_bits_read(bits))
|
|||
|
{
|
|||
|
/*otherDataLenBits <<= 8;
|
|||
|
otherDataLenBits +=*/ mpeg4_bits_read_n(bits, 8);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// crcCheckPresent
|
|||
|
if (mpeg4_bits_read(bits))
|
|||
|
/*crcCheckSum =*/ mpeg4_bits_read_n(bits, 8);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*tbd*/
|
|||
|
}
|
|||
|
|
|||
|
return bits->bits - offset;
|
|||
|
}
|
|||
|
|
|||
|
int mpeg4_aac_stream_mux_config_load2(const uint8_t* data, size_t bytes, struct mpeg4_aac_t* aac)
|
|||
|
{
|
|||
|
struct mpeg4_bits_t bits;
|
|||
|
mpeg4_bits_init(&bits, (void*)data, bytes);
|
|||
|
mpeg4_aac_stream_mux_config_load3(&bits, aac);
|
|||
|
mpeg4_bits_aligment(&bits, 8);
|
|||
|
return mpeg4_bits_error(&bits) ? -1 : (int)(bits.bits / 8);
|
|||
|
}
|