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 == <20><>0111<31><31>) {
|
||
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 == <20><>0111<31><31> ) {
|
||
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);
|
||
}
|