diff options
Diffstat (limited to 'libAACenc/src/aacenc_lib.cpp')
-rw-r--r-- | libAACenc/src/aacenc_lib.cpp | 164 |
1 files changed, 147 insertions, 17 deletions
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index 65a9bfc..7984c13 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -388,6 +388,138 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, return AAC_ENC_OK; } +static +void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, SBR_ELEMENT_INFO *sbrElInfo, INT bitRate) +{ + INT codebits = bitRate; + int el; + + /* Copy Element info */ + for (el=0; el<channelMapping->nElements; el++) { + sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0]; + sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1]; + sbrElInfo[el].elType = channelMapping->elInfo[el].elType; + sbrElInfo[el].bitRate = (INT)(fMultNorm(channelMapping->elInfo[el].relativeBits, (FIXP_DBL)bitRate)); + sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag; + sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl; + + codebits -= sbrElInfo[el].bitRate; + } + sbrElInfo[0].bitRate += codebits; +} + + +static +INT aacEncoder_LimitBitrate( + const HANDLE_TRANSPORTENC hTpEnc, + const INT samplingRate, + const INT frameLength, + const INT nChannels, + const CHANNEL_MODE channelMode, + INT bitRate, + const INT nSubFrames, + const INT sbrActive, + const AUDIO_OBJECT_TYPE aot + ) +{ + INT coreSamplingRate; + CHANNEL_MAPPING cm; + + FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm); + + if (sbrActive) { + /* Assume SBR rate ratio of 2:1 */ + coreSamplingRate = samplingRate / 2; + } else { + coreSamplingRate = samplingRate; + } + + /* Consider bandwidth channel bit rate limit (see bandwidth.cpp: GetBandwidthEntry()) */ + if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) { + bitRate = FDKmin(360000*nChannels, bitRate); + bitRate = FDKmax(8000*nChannels, bitRate); + } + + if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) { + bitRate = FDKmin(576000*nChannels, bitRate); + /*bitRate = FDKmax(0*nChannels, bitRate);*/ + } + + + /* Limit bit rate in respect to the core coder */ + bitRate = FDKaacEnc_LimitBitrate( + hTpEnc, + coreSamplingRate, + frameLength, + nChannels, + cm.nChannelsEff, + bitRate, + -1, + NULL, + -1, + nSubFrames + ); + + /* Limit bit rate in respect to available SBR modes if active */ + if (sbrActive) + { + SBR_ELEMENT_INFO sbrElInfo[6]; + INT sbrBitRate = 0; + int e, tooBig=-1; + + FDK_ASSERT(cm.nElements <= (6)); + + /* Get bit rate for each SBR element */ + aacEncDistributeSbrBits(&cm, sbrElInfo, bitRate); + + for (e=0; e<cm.nElements; e++) + { + INT sbrElementBitRateIn, sbrBitRateOut; + + if (cm.elInfo[e].elType != ID_SCE && cm.elInfo[e].elType != ID_CPE) { + continue; + } + sbrElementBitRateIn = sbrElInfo[e].bitRate; + sbrBitRateOut = sbrEncoder_LimitBitRate(sbrElementBitRateIn , cm.elInfo[e].nChannelsInEl, coreSamplingRate, aot); + if (sbrBitRateOut == 0) { + return 0; + } + if (sbrElementBitRateIn < sbrBitRateOut) { + FDK_ASSERT(tooBig != 1); + tooBig = 0; + if (e == 0) { + sbrBitRate = 0; + } + } + if (sbrElementBitRateIn > sbrBitRateOut) { + FDK_ASSERT(tooBig != 0); + tooBig = 1; + if (e == 0) { + sbrBitRate = 5000000; + } + } + if (tooBig != -1) + { + INT sbrBitRateLimit = (INT)fDivNorm((FIXP_DBL)sbrBitRateOut, cm.elInfo[e].relativeBits); + if (tooBig) { + sbrBitRate = fMin(sbrBitRate, sbrBitRateLimit-16); + FDK_ASSERT( (INT)fMultNorm(cm.elInfo[e].relativeBits, (FIXP_DBL)sbrBitRate) < sbrBitRateOut); + } else { + sbrBitRate = fMax(sbrBitRate, sbrBitRateLimit+16); + FDK_ASSERT( (INT)fMultNorm(cm.elInfo[e].relativeBits, (FIXP_DBL)sbrBitRate) >= sbrBitRateOut); + } + } + } + if (tooBig != -1) { + bitRate = sbrBitRate; + } + } + + FDK_ASSERT(bitRate > 0); + + return bitRate; +} + /* * \brief Consistency check of given USER_PARAM struct and * copy back configuration from public struct into internal @@ -482,6 +614,19 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, break; } + /* We need the frame length to call aacEncoder_LimitBitrate() */ + hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, + hAacConfig->sampleRate, + hAacConfig->framelength, + hAacConfig->nChannels, + hAacConfig->channelMode, + config->userBitrate, + hAacConfig->nSubFrames, + isSbrActive(hAacConfig), + hAacConfig->audioObjectType + ); + switch ( hAacConfig->audioObjectType ) { case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: @@ -605,7 +750,6 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, INT frameLength = hAacConfig->framelength; - if ( (InitFlags & AACENC_INIT_CONFIG) ) { CHANNEL_MODE prevChMode = hAacConfig->channelMode; @@ -645,9 +789,7 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, INT sbrError; SBR_ELEMENT_INFO sbrElInfo[(6)]; CHANNEL_MAPPING channelMapping; - int el; - INT codebits = hAacConfig->bitRate; - INT bitrateSc = CountLeadingBits(codebits); + AUDIO_OBJECT_TYPE aot = hAacConfig->audioObjectType; if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode, @@ -662,19 +804,7 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, return AACENC_INIT_ERROR; } - /* Copy Element info */ - for (el=0; el<channelMapping.nElements; el++) { - sbrElInfo[el].ChannelIndex[0] = channelMapping.elInfo[el].ChannelIndex[0]; - sbrElInfo[el].ChannelIndex[1] = channelMapping.elInfo[el].ChannelIndex[1]; - sbrElInfo[el].elType = channelMapping.elInfo[el].elType; - sbrElInfo[el].bitRate = (INT)(fMult(channelMapping.elInfo[el].relativeBits, (FIXP_DBL)(hAacConfig->bitRate<<bitrateSc))>>(bitrateSc)); - sbrElInfo[el].instanceTag = channelMapping.elInfo[el].instanceTag; - sbrElInfo[el].nChannelsInEl = channelMapping.elInfo[el].nChannelsInEl; - - sbrElInfo[el].bitRate = fMult(channelMapping.elInfo[el].relativeBits, (FIXP_DBL)hAacConfig->bitRate); - codebits -= sbrElInfo[el].bitRate; - } - sbrElInfo[0].bitRate += codebits; + aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate); UINT initFlag = 0; initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0; |