diff options
author | Dave Burke <daveburke@google.com> | 2012-04-17 09:51:45 -0700 |
---|---|---|
committer | Dave Burke <daveburke@google.com> | 2012-04-17 23:04:43 -0700 |
commit | 9bf37cc9712506b2483650c82d3c41152337ef7e (patch) | |
tree | 77db44e2bae06e3d144b255628be2b7a55c581d3 /libMpegTPDec/src/tpdec_asc.cpp | |
parent | a37315fe10ee143d6d0b28c19d41a476a23e63ea (diff) | |
download | fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.gz fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.bz2 fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.zip |
Fraunhofer AAC codec.
License boilerplate update to follow.
Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
Diffstat (limited to 'libMpegTPDec/src/tpdec_asc.cpp')
-rw-r--r-- | libMpegTPDec/src/tpdec_asc.cpp | 867 |
1 files changed, 867 insertions, 0 deletions
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp new file mode 100644 index 0000000..ee7c7cf --- /dev/null +++ b/libMpegTPDec/src/tpdec_asc.cpp @@ -0,0 +1,867 @@ +/***************************** MPEG-4 AAC Decoder ************************** + + (C) Copyright Fraunhofer IIS (2004) + All Rights Reserved + + Please be advised that this software and/or program delivery is + Confidential Information of Fraunhofer and subject to and covered by the + + Fraunhofer IIS Software Evaluation Agreement + between Google Inc. and Fraunhofer + effective and in full force since March 1, 2012. + + You may use this software and/or program only under the terms and + conditions described in the above mentioned Fraunhofer IIS Software + Evaluation Agreement. Any other and/or further use requires a separate agreement. + + + $Id$ + Author(s): Daniel Homm + Description: + + This software and/or program is protected by copyright law and international + treaties. Any reproduction or distribution of this software and/or program, + or any portion of it, may result in severe civil and criminal penalties, and + will be prosecuted to the maximum extent possible under law. + +******************************************************************************/ + +#include "tpdec_lib.h" +#include "tp_data.h" + + +void CProgramConfig_Reset(CProgramConfig *pPce) +{ + pPce->elCounter = 0; +} + +void CProgramConfig_Init(CProgramConfig *pPce) +{ + FDKmemclear(pPce, sizeof(CProgramConfig)); +#ifdef TP_PCE_ENABLE + pPce->SamplingFrequencyIndex = 0xf; +#endif +} + +int CProgramConfig_IsValid ( const CProgramConfig *pPce ) +{ + return ( (pPce->isValid) ? 1 : 0); +} + +#ifdef TP_PCE_ENABLE +void CProgramConfig_Read( + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + UINT alignmentAnchor + ) +{ + int i; + + pPce->NumEffectiveChannels = 0; + pPce->NumChannels = 0; + pPce->ElementInstanceTag = (UCHAR) FDKreadBits(bs,4); + pPce->Profile = (UCHAR) FDKreadBits(bs,2); + pPce->SamplingFrequencyIndex = (UCHAR) FDKreadBits(bs,4); + pPce->NumFrontChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumSideChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumBackChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumLfeChannelElements = (UCHAR) FDKreadBits(bs,2); + pPce->NumAssocDataElements = (UCHAR) FDKreadBits(bs,3); + pPce->NumValidCcElements = (UCHAR) FDKreadBits(bs,4); + + if ((pPce->MonoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->MonoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + } + + if ((pPce->StereoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->StereoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + } + + if ((pPce->MatrixMixdownIndexPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->MatrixMixdownIndex = (UCHAR) FDKreadBits(bs,2); + pPce->PseudoSurroundEnable = (UCHAR) FDKreadBits(bs,1); + } + + for (i=0; i < pPce->NumFrontChannelElements; i++) + { + pPce->FrontElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->FrontElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; + } + + for (i=0; i < pPce->NumSideChannelElements; i++) + { + pPce->SideElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->SideElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; + } + + for (i=0; i < pPce->NumBackChannelElements; i++) + { + pPce->BackElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->BackElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; + } + + pPce->NumEffectiveChannels = pPce->NumChannels; + + for (i=0; i < pPce->NumLfeChannelElements; i++) + { + pPce->LfeElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += 1; + } + + for (i=0; i < pPce->NumAssocDataElements; i++) + { + pPce->AssocDataElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + } + + for (i=0; i < pPce->NumValidCcElements; i++) + { + pPce->CcElementIsIndSw[i] = (UCHAR) FDKreadBits(bs,1); + pPce->ValidCcElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + } + + FDKbyteAlign(bs, alignmentAnchor); + + pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8); + + for (i=0; i < pPce->CommentFieldBytes; i++) + { + UCHAR text; + + text = (UCHAR)FDKreadBits(bs,8); + + if (i < PC_COMMENTLENGTH) + { + pPce->Comment[i] = text; + } + } + + pPce->isValid = 1; +} +#endif /* TP_PCE_ENABLE */ + +/** + * \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index + * \param channelConfig MPEG channelConfiguration from 1 upto 7 + * \param index MPEG channel order index + * \return audio channel type. + */ +void getImplicitAudioChannelTypeAndIndex( + AUDIO_CHANNEL_TYPE *chType, + UCHAR *chIndex, + UINT channelConfig, + UINT index + ) +{ + if (index < 3) { + *chType = ACT_FRONT; + *chIndex = index; + } else { + switch (channelConfig) { + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case MODE_1_2_2_2_1: + switch (index) { + case 3: + case 4: + *chType = ACT_SIDE; + *chIndex = index - 3; + break; + case 5: + case 6: + *chType = ACT_BACK; + *chIndex = index - 5; + break; + case 7: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + default: + *chType = ACT_NONE; + break; + } + } +} + +int CProgramConfig_LookupElement( + CProgramConfig *pPce, + const UINT channelConfig, + const UINT tag, + const UINT channelIdx, + UCHAR chMapping[], + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], + UCHAR *elMapping, + MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType + ) +{ + if (channelConfig > 0) + { + /* Constant channel mapping must have + been set during initialization. */ + if ( elType == ID_SCE + || elType == ID_CPE + || elType == ID_LFE ) + { + *elMapping = pPce->elCounter; + if (elList[pPce->elCounter] != elType) { + /* Not in the list */ + return 0; + } + /* Assume all front channels */ + getImplicitAudioChannelTypeAndIndex(&chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); + if (elType == ID_CPE) { + chType[channelIdx+1] = chType[channelIdx]; + chIndex[channelIdx+1] = chIndex[channelIdx]+1; + } + pPce->elCounter++; + } + /* Accept all non-channel elements, too. */ + return 1; + } + else + { +#ifdef TP_PCE_ENABLE + if (!pPce->isValid) +#endif /* TP_PCE_ENABLE */ + { + /* Implicit channel mapping. */ + if ( elType == ID_SCE + || elType == ID_CPE + || elType == ID_LFE ) + { + /* Store all channel element IDs */ + elList[pPce->elCounter] = elType; + *elMapping = pPce->elCounter++; + } + } +#ifdef TP_PCE_ENABLE + else { + /* Accept the additional channel(s), only if the tag is in the lists */ + int isCpe = 0, i; + int cc = 0, fc = 0, sc = 0, bc = 0, lc = 0, ec = 0; /* Channel and element counters */ + + switch (elType) + { + case ID_CPE: + isCpe = 1; + case ID_SCE: + /* search in front channels */ + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { + chMapping[cc] = channelIdx; + chType[cc] = ACT_FRONT; + chIndex[cc] = fc; + if (isCpe) { + chMapping[cc+1] = channelIdx+1; + chType[cc+1] = ACT_FRONT; + chIndex[cc+1] = fc+1; + } + *elMapping = ec; + return 1; + } + ec++; + if (pPce->FrontElementIsCpe[i]) { + cc+=2; fc+=2; + } else { + cc++; fc++; + } + } + /* search in side channels */ + for (i = 0; i < pPce->NumSideChannelElements; i++) { + if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { + chMapping[cc] = channelIdx; + chType[cc] = ACT_SIDE; + chIndex[cc] = sc; + if (isCpe) { + chMapping[cc+1] = channelIdx+1; + chType[cc+1] = ACT_SIDE; + chIndex[cc+1] = sc+1; + } + *elMapping = ec; + return 1; + } + ec++; + if (pPce->SideElementIsCpe[i]) { + cc+=2; sc+=2; + } else { + cc++; sc++; + } + } + /* search in back channels */ + for (i = 0; i < pPce->NumBackChannelElements; i++) { + if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { + chMapping[cc] = channelIdx; + chType[cc] = ACT_BACK; + chIndex[cc] = bc; + if (isCpe) { + chMapping[cc+1] = channelIdx+1; + chType[cc+1] = ACT_BACK; + chIndex[cc+1] = bc+1; + } + *elMapping = ec; + return 1; + } + ec++; + if (pPce->BackElementIsCpe[i]) { + cc+=2; bc+=2; + } else { + cc++; bc++; + } + } + break; + + case ID_LFE: + /* Initialize channel counter and element counter */ + cc = pPce->NumEffectiveChannels; + ec = pPce->NumFrontChannelElements+ pPce->NumSideChannelElements + pPce->NumBackChannelElements; + /* search in lfe channels */ + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + if ( pPce->LfeElementTagSelect[i] == tag ) { + chMapping[cc] = channelIdx; + *elMapping = ec; + chType[cc] = ACT_LFE; + chIndex[cc] = lc; + return 1; + } + ec++; + cc++; + lc++; + } + break; + + /* Non audio elements */ + case ID_CCE: + /* search in cce channels */ + for (i = 0; i < pPce->NumValidCcElements; i++) { + if (pPce->ValidCcElementTagSelect[i] == tag) { + return 1; + } + } + break; + case ID_DSE: + /* search associated data elements */ + for (i = 0; i < pPce->NumAssocDataElements; i++) { + if (pPce->AssocDataElementTagSelect[i] == tag) { + return 1; + } + } + break; + default: + return 0; + } + return 0; /* not found in any list */ + } +#endif /* TP_PCE_ENABLE */ + } + + return 1; +} + +#ifdef TP_PCE_ENABLE +int CProgramConfig_GetElementTable( + const CProgramConfig *pPce, + MP4_ELEMENT_ID elList[] + ) +{ + int i, el = 0; + + for (i=0; i < pPce->NumFrontChannelElements; i++) + { + elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumSideChannelElements; i++) + { + elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumBackChannelElements; i++) + { + elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumLfeChannelElements; i++) + { + elList[el++] = ID_LFE; + } + + + return el; +} +#endif + +static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) +{ + int tmp = 0; + + tmp = FDKreadBits(bs,5); + if (tmp == AOT_ESCAPE) { + int tmp2 = FDKreadBits(bs,6); + tmp = 32 + tmp2; + } + + return (AUDIO_OBJECT_TYPE)tmp; +} + +static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) +{ + INT sampleRate; + int idx; + + idx = FDKreadBits(bs, nBits); + if( idx == (1<<nBits)-1 ) { + if(FDKgetValidBits(bs) < 24) { + return 0; + } + sampleRate = FDKreadBits(bs,24); + } else { + sampleRate = SamplingRateTable[idx]; + } + + *index = idx; + + return sampleRate; +} + +#ifdef TP_GA_ENABLE +static +TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self, + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM bs, + UINT ascStartAnchor ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + self->m_frameLengthFlag = FDKreadBits(bs,1); + + self->m_dependsOnCoreCoder = FDKreadBits(bs,1); + + if( self->m_dependsOnCoreCoder ) + self->m_coreCoderDelay = FDKreadBits(bs,14); + + self->m_extensionFlag = FDKreadBits(bs,1); + + if( asc->m_channelConfiguration == 0 ) { + CProgramConfig_Read(&asc->m_progrConfigElement, bs, ascStartAnchor); + } + + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + self->m_layer = FDKreadBits(bs,3); + } + + if (self->m_extensionFlag) { + if (asc->m_aot == AOT_ER_BSAC) { + self->m_numOfSubFrame = FDKreadBits(bs,5); + self->m_layerLength = FDKreadBits(bs,11); + } + + if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || + (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) + { + asc->m_vcb11Flag = FDKreadBits(bs,1); /* aacSectionDataResilienceFlag */ + asc->m_rvlcFlag = FDKreadBits(bs,1); /* aacScalefactorDataResilienceFlag */ + asc->m_hcrFlag = FDKreadBits(bs,1); /* aacSpectralDataResilienceFlag */ + } + + self->m_extensionFlag3 = FDKreadBits(bs,1); + + } + return (ErrorStatus); +} +#endif /* TP_GA_ENABLE */ + + + + + +#ifdef TP_ELD_ENABLE + +static INT ld_sbr_header( const CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb ) +{ + const int channelConfiguration = asc->m_channelConfiguration; + int i = 0; + INT error = 0; + + if (channelConfiguration == 2) { + error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + } else { + error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); + } + + switch ( channelConfiguration ) { + case 5: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + case 3: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + break; + + case 7: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); + case 6: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + case 4: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + break; + } + + return error; +} + +static +TRANSPORTDEC_ERROR EldSpecificConfig_Parse( + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig; + ASC_ELD_EXT_TYPE eldExtType; + int eldExtLen, len, cnt; + + FDKmemclear(esc, sizeof(CSEldSpecificConfig)); + + esc->m_frameLengthFlag = FDKreadBits(hBs, 1 ); + if (esc->m_frameLengthFlag) { + asc->m_samplesPerFrame = 480; + } else { + asc->m_samplesPerFrame = 512; + } + + asc->m_vcb11Flag = FDKreadBits(hBs, 1 ); + asc->m_rvlcFlag = FDKreadBits(hBs, 1 ); + asc->m_hcrFlag = FDKreadBits(hBs, 1 ); + + esc->m_sbrPresentFlag = FDKreadBits(hBs, 1 ); + + if (esc->m_sbrPresentFlag == 1) { + esc->m_sbrSamplingRate = FDKreadBits(hBs, 1 ); /* 0: single rate, 1: dual rate */ + esc->m_sbrCrcFlag = FDKreadBits(hBs, 1 ); + + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency << esc->m_sbrSamplingRate; + + if (cb->cbSbr != NULL){ + if ( 0 != ld_sbr_header(asc, hBs, cb) ) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } + esc->m_useLdQmfTimeAlign = 0; + + /* new ELD syntax */ + /* parse ExtTypeConfigData */ + while ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4 )) != ELDEXT_TERM) { + eldExtLen = len = FDKreadBits(hBs, 4 ); + if ( len == 0xf ) { + len = FDKreadBits(hBs, 8 ); + eldExtLen += len; + + if ( len == 0xff ) { + len = FDKreadBits(hBs, 16 ); + eldExtLen += len; + } + } + + switch (eldExtType) { + case ELDEXT_LDSAC: + esc->m_useLdQmfTimeAlign = 1; + if (cb->cbSsc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, + hBs, + asc->m_aot, + asc->m_samplingFrequency, + 1, /* muxMode */ + len + ); + } else { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + if (ErrorStatus != TRANSPORTDEC_OK) { + goto bail; + } + break; + default: + for(cnt=0; cnt<len; cnt++) { + FDKreadBits(hBs, 8 ); + } + break; + /* add future eld extension configs here */ + } + } +bail: + return (ErrorStatus); +} +#endif /* TP_ELD_ENABLE */ + + +static +TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse(CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) +{ + TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; + INT bitsAvailable = (INT)FDKgetValidBits(bs); + + while (bitsAvailable >= 11) + { + lastAscExt = ascExtId; + ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); + bitsAvailable -= 11; + + switch (ascExtId) { + case ASCEXT_SBR: /* 0x2b7 */ + if ( (self->m_extensionAudioObjectType != AOT_SBR) && (bitsAvailable >= 5) ) { + self->m_extensionAudioObjectType = getAOT(bs); + + if ( (self->m_extensionAudioObjectType == AOT_SBR) + || (self->m_extensionAudioObjectType == AOT_ER_BSAC) ) + { /* Get SBR extension configuration */ + self->m_sbrPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + + if ( self->m_sbrPresentFlag == 1 ) { + self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + + if ((INT)self->m_extensionSamplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + if ( self->m_extensionAudioObjectType == AOT_ER_BSAC ) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + bitsAvailable -= 4; + } + } + /* Update counter because of variable length fields (AOT and sampling rate) */ + bitsAvailable = (INT)FDKgetValidBits(bs); + } + break; + case ASCEXT_PS: /* 0x548 */ + if ( (lastAscExt == ASCEXT_SBR) + && (self->m_extensionAudioObjectType == AOT_SBR) + && (bitsAvailable > 0) ) + { /* Get PS extension configuration */ + self->m_psPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + } + break; + case ASCEXT_MPS: /* 0x76a */ + if ( self->m_extensionAudioObjectType == AOT_MPEGS ) + break; + case ASCEXT_LDMPS: /* 0x7cc */ + if ( (ascExtId == ASCEXT_LDMPS) + && (self->m_extensionAudioObjectType == AOT_LD_MPEGS) ) + break; + if (bitsAvailable >= 1) + { + bitsAvailable -= 1; + if ( FDKreadBits(bs, 1) ) { /* self->m_mpsPresentFlag */ + int sscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (sscLen == 0xFF) { + sscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + if (cb->cbSsc != NULL) { + cb->cbSsc( + cb->cbSscData, + bs, + self->m_aot, + self->m_samplingFrequency, + 1, + sscLen + ); + } else + FDKpushFor(bs, sscLen); /* Skip SSC to be able to read the next extension if there is one. */ + + bitsAvailable -= sscLen*8; + } + } + break; + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } + + return TRANSPORTDEC_OK; +} + +/* + * API Functions + */ + +void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) +{ + FDKmemclear(asc, sizeof(CSAudioSpecificConfig)); + + /* Init all values that should not be zero. */ + asc->m_aot = AOT_NONE; + asc->m_samplingFrequencyIndex = 0xf; + asc->m_epConfig = -1; + asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; +#ifdef TP_PCE_ENABLE + CProgramConfig_Init(&asc->m_progrConfigElement); +#endif +} + +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *self, + HANDLE_FDK_BITSTREAM bs, + int fExplicitBackwardCompatible, + CSTpCallBacks *cb + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT ascStartAnchor = FDKgetValidBits(bs); + int frameLengthFlag = -1; + + AudioSpecificConfig_Init(self); + + self->m_aot = getAOT(bs); + self->m_samplingFrequency = getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); + if (self->m_samplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + self->m_channelConfiguration = FDKreadBits(bs,4); + + /* SBR extension ( explicit non-backwards compatible mode ) */ + self->m_sbrPresentFlag = 0; + self->m_psPresentFlag = 0; + + if ( self->m_aot == AOT_SBR || self->m_aot == AOT_PS ) { + self->m_extensionAudioObjectType = AOT_SBR; + + self->m_sbrPresentFlag = 1; + if ( self->m_aot == AOT_PS ) { + self->m_psPresentFlag = 1; + } + + self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + self->m_aot = getAOT(bs); + + } else { + self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + } + + /* Parse whatever specific configs */ + switch (self->m_aot) + { +#ifdef TP_GA_ENABLE + case AOT_AAC_LC: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, self, bs, ascStartAnchor)) != TRANSPORTDEC_OK ) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; + break; +#endif /* TP_GA_ENABLE */ + case AOT_MPEGS: + if (cb->cbSsc != NULL) { + cb->cbSsc( + cb->cbSscData, + bs, + self->m_aot, + self->m_samplingFrequency, + 1, + 0 /* don't know the length */ + ); + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + break; +#ifdef TP_ELD_ENABLE + case AOT_ER_AAC_ELD: + if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK ) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; + self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; + self->m_extensionSamplingFrequency = (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate+1) * self->m_samplingFrequency; + break; +#endif /* TP_ELD_ENABLE */ + + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + break; + } + + /* Frame length */ + switch (self->m_aot) + { +#if defined(TP_GA_ENABLE) || defined(TP_USAC_ENABLE) + case AOT_AAC_LC: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + /*case AOT_USAC:*/ + if (!frameLengthFlag) + self->m_samplesPerFrame = 1024; + else + self->m_samplesPerFrame = 960; + break; +#endif /* TP_GA_ENABLE */ +#if defined(TP_GA_ENABLE) + case AOT_ER_AAC_LD: + if (!frameLengthFlag) + self->m_samplesPerFrame = 512; + else + self->m_samplesPerFrame = 480; + break; +#endif /* defined(TP_GA_ENABLE) */ + default: + break; + } + + switch (self->m_aot) + { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_SCAL: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_BSAC: + self->m_epConfig = FDKreadBits(bs,2); + + if (self->m_epConfig > 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; + } + break; + default: + break; + } + + if (fExplicitBackwardCompatible) { + ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); + } + + return (ErrorStatus); +} + + |