summaryrefslogtreecommitdiffstats
path: root/libAACenc/src/qc_main.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2012-07-11 10:15:24 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2012-07-11 10:15:24 -0700
commit2228e360595641dd906bf1773307f43d304f5b2e (patch)
tree57f3d390ebb0782cc0de0fb984c8ea7e45b4f386 /libAACenc/src/qc_main.cpp
downloadODR-AudioEnc-2228e360595641dd906bf1773307f43d304f5b2e.tar.gz
ODR-AudioEnc-2228e360595641dd906bf1773307f43d304f5b2e.tar.bz2
ODR-AudioEnc-2228e360595641dd906bf1773307f43d304f5b2e.zip
Snapshot 2bda038c163298531d47394bc2c09e1409c5d0db
Change-Id: If584e579464f28b97d50e51fc76ba654a5536c54
Diffstat (limited to 'libAACenc/src/qc_main.cpp')
-rw-r--r--libAACenc/src/qc_main.cpp1620
1 files changed, 1620 insertions, 0 deletions
diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp
new file mode 100644
index 0000000..749398a
--- /dev/null
+++ b/libAACenc/src/qc_main.cpp
@@ -0,0 +1,1620 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+ All rights reserved.
+
+ 1. INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
+the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
+This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
+audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
+independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
+of the MPEG specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
+may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
+individually for the purpose of encoding or decoding bit streams in products that are compliant with
+the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
+these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
+software may already be covered under those patent licenses when it is used for those licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
+are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
+applications information and documentation.
+
+2. COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification, are permitted without
+payment of copyright license fees provided that you satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
+your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation and/or other materials
+provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
+You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived from this library without
+prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
+software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
+and the date of any change. For modified versions of the FDK AAC Codec, the term
+"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
+"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+
+3. NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
+ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
+respect to this software.
+
+You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
+by appropriate patent licenses.
+
+4. DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
+"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
+of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
+including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
+or business interruption, however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of this software, even if
+advised of the possibility of such damage.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------------------------------------- */
+
+/******************************** MPEG Audio Encoder **************************
+
+ Initial author: M. Werner
+ contents/description: Quantizing & coding
+
+******************************************************************************/
+
+#include "qc_main.h"
+#include "quantize.h"
+#include "interface.h"
+#include "adj_thr.h"
+#include "sf_estim.h"
+#include "bit_cnt.h"
+#include "dyn_bits.h"
+#include "channel_map.h"
+#include "aacEnc_ram.h"
+
+#include "genericStds.h"
+
+
+typedef struct {
+ QCDATA_BR_MODE bitrateMode;
+ LONG vbrQualFactor;
+} TAB_VBR_QUAL_FACTOR;
+
+static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = {
+ {QCDATA_BR_MODE_CBR, FL2FXCONST_DBL(0.00f)},
+ {QCDATA_BR_MODE_VBR_1, FL2FXCONST_DBL(0.160f)}, /* 32 kbps mono AAC-LC + SBR + PS */
+ {QCDATA_BR_MODE_VBR_2, FL2FXCONST_DBL(0.148f)}, /* 64 kbps stereo AAC-LC + SBR */
+ {QCDATA_BR_MODE_VBR_3, FL2FXCONST_DBL(0.135f)}, /* 80 - 96 kbps stereo AAC-LC */
+ {QCDATA_BR_MODE_VBR_4, FL2FXCONST_DBL(0.111f)}, /* 128 kbps stereo AAC-LC */
+ {QCDATA_BR_MODE_VBR_5, FL2FXCONST_DBL(0.070f)}, /* 192 kbps stereo AAC-LC */
+ {QCDATA_BR_MODE_SFR, FL2FXCONST_DBL(0.00f)},
+ {QCDATA_BR_MODE_FF, FL2FXCONST_DBL(0.00f)}
+};
+
+static INT isConstantBitrateMode(
+ const QCDATA_BR_MODE bitrateMode
+ )
+{
+ return ( ((bitrateMode==QCDATA_BR_MODE_CBR) || (bitrateMode==QCDATA_BR_MODE_SFR) || (bitrateMode==QCDATA_BR_MODE_FF)) ? 1 : 0 );
+}
+
+
+
+typedef enum{
+ FRAME_LEN_BYTES_MODULO = 1,
+ FRAME_LEN_BYTES_INT = 2
+}FRAME_LEN_RESULT_MODE;
+
+/* forward declarations */
+
+static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt,
+ INT maxSfbPerGroup,
+ INT sfbPerGroup,
+ INT *RESTRICT sfbOffset,
+ SHORT *RESTRICT quantSpectrum,
+ UINT *RESTRICT maxValue);
+
+static void FDKaacEnc_crashRecovery(INT nChannels,
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT* qcOut,
+ QC_OUT_ELEMENT *qcElement,
+ INT bitsToSave,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig);
+
+static
+AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption(int* iterations,
+ const int maxIterations,
+ int gainAdjustment,
+ int* chConstraintsFulfilled,
+ int* calculateQuant,
+ int nChannels,
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT* qcOut,
+ QC_OUT_ELEMENT* qcOutElement,
+ ELEMENT_BITS* elBits,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig);
+
+
+void FDKaacEnc_QCClose (QC_STATE **phQCstate, QC_OUT **phQC);
+
+/*****************************************************************************
+
+ functionname: FDKaacEnc_calcFrameLen
+ description:
+ returns:
+ input:
+ output:
+
+*****************************************************************************/
+static INT FDKaacEnc_calcFrameLen(INT bitRate,
+ INT sampleRate,
+ INT granuleLength,
+ FRAME_LEN_RESULT_MODE mode)
+{
+
+ INT result;
+
+ result = ((granuleLength)>>3)*(bitRate);
+
+ switch(mode) {
+ case FRAME_LEN_BYTES_MODULO:
+ result %= sampleRate;
+ break;
+ case FRAME_LEN_BYTES_INT:
+ result /= sampleRate;
+ break;
+ }
+ return(result);
+}
+
+/*****************************************************************************
+
+ functionname:FDKaacEnc_framePadding
+ description: Calculates if padding is needed for actual frame
+ returns:
+ input:
+ output:
+
+*****************************************************************************/
+static INT FDKaacEnc_framePadding(INT bitRate,
+ INT sampleRate,
+ INT granuleLength,
+ INT *paddingRest)
+{
+ INT paddingOn;
+ INT difference;
+
+ paddingOn = 0;
+
+ difference = FDKaacEnc_calcFrameLen( bitRate,
+ sampleRate,
+ granuleLength,
+ FRAME_LEN_BYTES_MODULO );
+ *paddingRest-=difference;
+
+ if (*paddingRest <= 0 ) {
+ paddingOn = 1;
+ *paddingRest += sampleRate;
+ }
+
+ return( paddingOn );
+}
+
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_QCOutNew
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT **phQC,
+ const INT nElements,
+ const INT nChannels,
+ const INT nSubFrames
+ ,UCHAR *dynamic_RAM
+ )
+{
+ AAC_ENCODER_ERROR ErrorStatus;
+ int n, i;
+ int elInc = 0, chInc = 0;
+
+ for (n=0; n<nSubFrames; n++) {
+ phQC[n] = GetRam_aacEnc_QCout(n);
+ if (phQC[n] == NULL) {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCOutNew_bail;
+ }
+
+ for (i=0; i<nChannels; i++) {
+ phQC[n]->pQcOutChannels[i] = GetRam_aacEnc_QCchannel(chInc, dynamic_RAM);
+ if ( phQC[n]->pQcOutChannels[i] == NULL
+ )
+ {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCOutNew_bail;
+ }
+ chInc++;
+ } /* nChannels */
+
+ for (i=0; i<nElements; i++) {
+ phQC[n]->qcElement[i] = GetRam_aacEnc_QCelement(elInc);
+ if (phQC[n]->qcElement[i] == NULL)
+ {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCOutNew_bail;
+ }
+ elInc++;
+ } /* nElements */
+
+ } /* nSubFrames */
+
+
+ return AAC_ENC_OK;
+
+QCOutNew_bail:
+ return ErrorStatus;
+}
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_QCOutInit
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT *phQC[(1)],
+ const INT nSubFrames,
+ const CHANNEL_MAPPING *cm)
+{
+ INT n,i,ch;
+
+ for (n=0; n<nSubFrames; n++) {
+ INT chInc = 0;
+ for (i=0; i<cm->nElements; i++) {
+ for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
+ phQC[n]->qcElement[i]->qcOutChannel[ch] = phQC[n]->pQcOutChannels[chInc];
+ chInc++;
+ } /* chInEl */
+ } /* nElements */
+ } /* nSubFrames */
+
+ return AAC_ENC_OK;
+}
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_QCNew
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE **phQC,
+ INT nElements
+ ,UCHAR* dynamic_RAM
+ )
+{
+ AAC_ENCODER_ERROR ErrorStatus;
+ int i;
+
+ QC_STATE* hQC = GetRam_aacEnc_QCstate();
+ *phQC = hQC;
+ if (hQC == NULL) {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCNew_bail;
+ }
+
+ if (FDKaacEnc_AdjThrNew(&hQC->hAdjThr, nElements)) {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCNew_bail;
+ }
+
+ if (FDKaacEnc_BCNew(&(hQC->hBitCounter), dynamic_RAM)) {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCNew_bail;
+ }
+
+ for (i=0; i<nElements; i++) {
+ hQC->elementBits[i] = GetRam_aacEnc_ElementBits(i);
+ if (hQC->elementBits[i] == NULL) {
+ ErrorStatus = AAC_ENC_NO_MEMORY;
+ goto QCNew_bail;
+ }
+ }
+
+ return AAC_ENC_OK;
+
+QCNew_bail:
+ FDKaacEnc_QCClose(phQC, NULL);
+ return ErrorStatus;
+}
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_QCInit
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC,
+ struct QC_INIT *init)
+{
+ hQC->maxBitsPerFrame = init->maxBits;
+ hQC->minBitsPerFrame = init->minBits;
+ hQC->nElements = init->channelMapping->nElements;
+ hQC->bitResTotMax = init->bitRes;
+ hQC->bitResTot = init->bitRes;
+ hQC->maxBitFac = init->maxBitFac;
+ hQC->bitrateMode = init->bitrateMode;
+ hQC->invQuant = init->invQuant;
+ hQC->maxIterations = init->maxIterations;
+
+ if ( isConstantBitrateMode(hQC->bitrateMode) ) {
+ INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff);
+ /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
+ hQC->bitDistributenMode = (bitresPerChannel>50) ? 0 : (bitresPerChannel>0) ? 1 : 2;
+ }
+ else {
+ hQC->bitDistributenMode = 0; /* full bitreservoir */
+ }
+
+
+ hQC->padding.paddingRest = init->padding.paddingRest;
+
+ hQC->globHdrBits = init->staticBits; /* Bit overhead due to transport */
+
+ FDKaacEnc_InitElementBits(hQC,
+ init->channelMapping,
+ init->bitrate,
+ (init->averageBits/init->nSubFrames) - hQC->globHdrBits,
+ hQC->maxBitsPerFrame/init->channelMapping->nChannelsEff);
+
+ switch(hQC->bitrateMode){
+ case QCDATA_BR_MODE_CBR:
+ case QCDATA_BR_MODE_VBR_1:
+ case QCDATA_BR_MODE_VBR_2:
+ case QCDATA_BR_MODE_VBR_3:
+ case QCDATA_BR_MODE_VBR_4:
+ case QCDATA_BR_MODE_VBR_5:
+ case QCDATA_BR_MODE_SFR:
+ case QCDATA_BR_MODE_FF:
+ if((int)hQC->bitrateMode < (int)(sizeof(tableVbrQualFactor)/sizeof(TAB_VBR_QUAL_FACTOR))){
+ hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[hQC->bitrateMode].vbrQualFactor;
+ } else {
+ hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); /* default setting */
+ }
+ break;
+ case QCDATA_BR_MODE_INVALID:
+ default:
+ hQC->vbrQualFactor = FL2FXCONST_DBL(0.f);
+ break;
+ }
+
+ FDKaacEnc_AdjThrInit(hQC->hAdjThr,
+ init->meanPe,
+ hQC->elementBits, /* or channelBitrates, was: channelBitrate */
+ init->channelMapping->nElements,
+ hQC->vbrQualFactor);
+
+ return AAC_ENC_OK;
+}
+
+
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_QCMainPrepare
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare(ELEMENT_INFO *elInfo,
+ ATS_ELEMENT* RESTRICT adjThrStateElement,
+ PSY_OUT_ELEMENT* RESTRICT psyOutElement,
+ QC_OUT_ELEMENT* RESTRICT qcOutElement,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig
+ )
+{
+ AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
+ INT nChannels = elInfo->nChannelsInEl;
+
+ PSY_OUT_CHANNEL** RESTRICT psyOutChannel = psyOutElement->psyOutChannel; /* may be modified in-place */
+
+ FDKaacEnc_CalcFormFactor(qcOutElement->qcOutChannel, psyOutChannel, nChannels);
+
+ /* prepare and calculate PE without reduction */
+ FDKaacEnc_peCalculation(&qcOutElement->peData, psyOutChannel, qcOutElement->qcOutChannel, &psyOutElement->toolsInfo, adjThrStateElement, nChannels);
+
+ ErrorStatus = FDKaacEnc_ChannelElementWrite( NULL, elInfo, NULL,
+ psyOutElement,
+ psyOutElement->psyOutChannel,
+ syntaxFlags,
+ aot,
+ epConfig,
+ &qcOutElement->staticBitsUsed,
+ 0 );
+
+ return ErrorStatus;
+}
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_AdjustBitrate
+ description: adjusts framelength via padding on a frame to frame basis,
+ to achieve a bitrate that demands a non byte aligned
+ framelength
+ return: errorcode
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate(QC_STATE *RESTRICT hQC,
+ CHANNEL_MAPPING *RESTRICT cm,
+ INT *avgTotalBits,
+ INT bitRate, /* total bitrate */
+ INT sampleRate, /* output sampling rate */
+ INT granuleLength) /* frame length */
+{
+ INT paddingOn;
+ INT frameLen;
+
+ /* Do we need an extra padding byte? */
+ paddingOn = FDKaacEnc_framePadding(bitRate,
+ sampleRate,
+ granuleLength,
+ &hQC->padding.paddingRest);
+
+ frameLen = paddingOn + FDKaacEnc_calcFrameLen(bitRate,
+ sampleRate,
+ granuleLength,
+ FRAME_LEN_BYTES_INT);
+
+ *avgTotalBits = frameLen<<3;
+
+ return AAC_ENC_OK;
+}
+
+static AAC_ENCODER_ERROR FDKaacEnc_distributeElementDynBits(QC_STATE* hQC,
+ QC_OUT_ELEMENT* qcElement[(6)],
+ CHANNEL_MAPPING* cm,
+ INT codeBits)
+{
+
+ INT i, firstEl = cm->nElements-1;
+ INT totalBits = 0;
+
+ for (i=(cm->nElements-1); i>=0; i--) {
+ if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) ||
+ (cm->elInfo[i].elType == ID_LFE))
+ {
+ qcElement[i]->grantedDynBits = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)codeBits);
+ totalBits += qcElement[i]->grantedDynBits;
+ firstEl = i;
+ }
+ }
+ qcElement[firstEl]->grantedDynBits += codeBits - totalBits;
+
+ return AAC_ENC_OK;
+}
+
+/**
+ * \brief Verify whether minBitsPerFrame criterion can be satisfied.
+ *
+ * This function evaluates the bit consumption only if minBitsPerFrame parameter is not 0.
+ * In hyperframing mode the difference between grantedDynBits and usedDynBits of all sub frames
+ * results the number of fillbits to be written.
+ * This bits can be distrubitued in superframe to reach minBitsPerFrame bit consumption in single AU's.
+ * The return value denotes if enough desired fill bits are available to achieve minBitsPerFrame in all frames.
+ * This check can only be used within superframes.
+ *
+ * \param qcOut Pointer to coding data struct.
+ * \param minBitsPerFrame Minimal number of bits to be consumed in each frame.
+ * \param nSubFrames Number of frames in superframe
+ *
+ * \return
+ * - 1: all fine
+ * - 0: criterion not fulfilled
+ */
+static int checkMinFrameBitsDemand(
+ QC_OUT** qcOut,
+ const INT minBitsPerFrame,
+ const INT nSubFrames
+ )
+{
+ int result = 1; /* all fine*/
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*********************************************************************************
+
+ functionname: FDKaacEnc_getMinimalStaticBitdemand
+ description: calculate minmal size of static bits by reduction ,
+ to zero spectrum and deactivating tns and MS
+ return: number of static bits
+
+**********************************************************************************/
+static int FDKaacEnc_getMinimalStaticBitdemand(CHANNEL_MAPPING* cm,
+ PSY_OUT** psyOut)
+{
+ AUDIO_OBJECT_TYPE aot = AOT_AAC_LC;
+ UINT syntaxFlags = 0;
+ SCHAR epConfig = -1;
+ int i, bitcount = 0;
+
+ for (i=0; i<cm->nElements; i++) {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+
+ if ( (elInfo.elType == ID_SCE)
+ || (elInfo.elType == ID_CPE)
+ || (elInfo.elType == ID_LFE) )
+ {
+ INT minElBits = 0;
+
+ FDKaacEnc_ChannelElementWrite( NULL, &elInfo, NULL,
+ psyOut[0]->psyOutElement[i],
+ psyOut[0]->psyOutElement[i]->psyOutChannel,
+ syntaxFlags,
+ aot,
+ epConfig,
+ &minElBits,
+ 1 );
+ bitcount += minElBits;
+ }
+ }
+
+ return bitcount;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution(QC_STATE* hQC,
+ PSY_OUT** psyOut,
+ QC_OUT** qcOut,
+ CHANNEL_MAPPING* cm,
+ QC_OUT_ELEMENT* qcElement[(1)][(6)],
+ INT avgTotalBits,
+ INT *totalAvailableBits,
+ INT *avgTotalDynBits)
+{
+ int i;
+ /* get maximal allowed dynamic bits */
+ qcOut[0]->grantedDynBits = (fixMin(hQC->maxBitsPerFrame, avgTotalBits) - hQC->globHdrBits)&~7;
+ qcOut[0]->grantedDynBits -= (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits);
+ qcOut[0]->maxDynBits = ((hQC->maxBitsPerFrame)&~7) - (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits);
+ /* assure that enough bits are available */
+ if ((qcOut[0]->grantedDynBits+hQC->bitResTot) < 0) {
+ /* crash recovery allows to reduce static bits to a minimum */
+ if ( (qcOut[0]->grantedDynBits+hQC->bitResTot) < (FDKaacEnc_getMinimalStaticBitdemand(cm, psyOut)-qcOut[0]->staticBits) )
+ return AAC_ENC_BITRES_TOO_LOW;
+ }
+
+ /* distribute dynamic bits to each element */
+ FDKaacEnc_distributeElementDynBits(hQC,
+ qcElement[0],
+ cm,
+ qcOut[0]->grantedDynBits);
+
+ *avgTotalDynBits = 0; /*frameDynBits;*/
+
+ *totalAvailableBits = avgTotalBits;
+
+ /* sum up corrected granted PE */
+ qcOut[0]->totalGrantedPeCorr = 0;
+
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+ int nChannels = elInfo.nChannelsInEl;
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ /* for ( all sub frames ) ... */
+ FDKaacEnc_DistributeBits(hQC->hAdjThr,
+ hQC->hAdjThr->adjThrStateElem[i],
+ psyOut[0]->psyOutElement[i]->psyOutChannel,
+ &qcElement[0][i]->peData,
+ &qcElement[0][i]->grantedPe,
+ &qcElement[0][i]->grantedPeCorr,
+ nChannels,
+ psyOut[0]->psyOutElement[i]->commonWindow,
+ qcElement[0][i]->grantedDynBits,
+ hQC->elementBits[i]->bitResLevelEl,
+ hQC->elementBits[i]->maxBitResBitsEl,
+ hQC->maxBitFac,
+ hQC->bitDistributenMode);
+
+ *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl;
+ /* get total corrected granted PE */
+ qcOut[0]->totalGrantedPeCorr += qcElement[0][i]->grantedPeCorr;
+ } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
+
+ } /* -end- element loop */
+
+ *totalAvailableBits = FDKmin(hQC->maxBitsPerFrame, (*totalAvailableBits));
+
+ return AAC_ENC_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static AAC_ENCODER_ERROR FDKaacEnc_updateUsedDynBits(INT* sumDynBitsConsumed,
+ QC_OUT_ELEMENT* qcElement[(6)],
+ CHANNEL_MAPPING* cm)
+{
+ INT i;
+
+ *sumDynBitsConsumed = 0;
+
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ /* sum up bits consumed */
+ *sumDynBitsConsumed += qcElement[i]->dynBitsUsed;
+ } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
+
+ } /* -end- element loop */
+
+ return AAC_ENC_OK;
+}
+
+
+static INT FDKaacEnc_getTotalConsumedDynBits(QC_OUT** qcOut,
+ INT nSubFrames)
+{
+ INT c, totalBits=0;
+
+ /* sum up bit consumption for all sub frames */
+ for (c=0; c<nSubFrames; c++)
+ {
+ /* bit consumption not valid if dynamic bits
+ not available in one sub frame */
+ if (qcOut[c]->usedDynBits==-1) return -1;
+ totalBits += qcOut[c]->usedDynBits;
+ }
+
+ return totalBits;
+
+}
+
+static INT FDKaacEnc_getTotalConsumedBits(QC_OUT** qcOut,
+ QC_OUT_ELEMENT* qcElement[(1)][(6)],
+ CHANNEL_MAPPING* cm,
+ INT globHdrBits,
+ INT nSubFrames)
+{
+ int c, i;
+ int totalUsedBits = 0;
+
+ for (c = 0 ; c < nSubFrames ; c++ )
+ {
+ int dataBits = 0;
+ for (i=0; i<cm->nElements; i++)
+ {
+ if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) ||
+ (cm->elInfo[i].elType == ID_LFE))
+ {
+ dataBits += qcElement[c][i]->dynBitsUsed + qcElement[c][i]->staticBitsUsed + qcElement[c][i]->extBitsUsed;
+ }
+ }
+ dataBits += qcOut[c]->globalExtBits;
+
+ totalUsedBits += (8 - (dataBits) % 8) % 8;
+ totalUsedBits += dataBits + globHdrBits; /* header bits for every frame */
+ }
+ return totalUsedBits;
+}
+
+static AAC_ENCODER_ERROR FDKaacEnc_BitResRedistribution(
+ QC_STATE *const hQC,
+ const CHANNEL_MAPPING *const cm,
+ const INT avgTotalBits
+ )
+{
+ /* check bitreservoir fill level */
+ if (hQC->bitResTot < 0) {
+ return AAC_ENC_BITRES_TOO_LOW;
+ }
+ else if (hQC->bitResTot > hQC->bitResTotMax) {
+ return AAC_ENC_BITRES_TOO_HIGH;
+ }
+ else {
+ INT i, firstEl = cm->nElements-1;
+ INT totalBits = 0, totalBits_max = 0;
+
+ int totalBitreservoir = FDKmin(hQC->bitResTot, (hQC->maxBitsPerFrame-avgTotalBits));
+ int totalBitreservoirMax = FDKmin(hQC->bitResTotMax, (hQC->maxBitsPerFrame-avgTotalBits));
+
+ int sc_bitResTot = CountLeadingBits(totalBitreservoir);
+ int sc_bitResTotMax = CountLeadingBits(totalBitreservoirMax);
+
+ for (i=(cm->nElements-1); i>=0; i--) {
+ if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) ||
+ (cm->elInfo[i].elType == ID_LFE))
+ {
+ hQC->elementBits[i]->bitResLevelEl = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)(totalBitreservoir<<sc_bitResTot))>>sc_bitResTot;
+ totalBits += hQC->elementBits[i]->bitResLevelEl;
+
+ hQC->elementBits[i]->maxBitResBitsEl = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)(totalBitreservoirMax<<sc_bitResTotMax))>>sc_bitResTotMax;
+ totalBits_max += hQC->elementBits[i]->maxBitResBitsEl;
+
+ firstEl = i;
+ }
+ }
+ hQC->elementBits[firstEl]->bitResLevelEl += totalBitreservoir - totalBits;
+ hQC->elementBits[firstEl]->maxBitResBitsEl += totalBitreservoirMax - totalBits_max;
+ }
+
+ return AAC_ENC_OK;
+}
+
+
+AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC,
+ PSY_OUT** psyOut,
+ QC_OUT** qcOut,
+ INT avgTotalBits,
+ CHANNEL_MAPPING* cm
+ ,AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig
+ )
+{
+ int i, c;
+ AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
+ INT avgTotalDynBits = 0; /* maximal allowd dynamic bits for all frames */
+ INT totalAvailableBits = 0;
+ INT nSubFrames = 1;
+
+ /*-------------------------------------------- */
+ /* redistribute total bitreservoir to elements */
+ ErrorStatus = FDKaacEnc_BitResRedistribution(hQC, cm, avgTotalBits);
+ if (ErrorStatus != AAC_ENC_OK) {
+ return ErrorStatus;
+ }
+
+ /*-------------------------------------------- */
+ /* fastenc needs one time threshold simulation,
+ in case of multiple frames, one more guess has to be calculated */
+
+ /*-------------------------------------------- */
+ /* helper pointer */
+ QC_OUT_ELEMENT* qcElement[(1)][(6)];
+
+ /* work on a copy of qcChannel and qcElement */
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ /* for ( all sub frames ) ... */
+ for (c = 0 ; c < nSubFrames ; c++ )
+ {
+ {
+ qcElement[c][i] = qcOut[c]->qcElement[i];
+ }
+ }
+ }
+ }
+
+ /*-------------------------------------------- */
+ /*-------------------------------------------- */
+ if ( isConstantBitrateMode(hQC->bitrateMode) )
+ {
+ /* calc granted dynamic bits for sub frame and
+ distribute it to each element */
+ ErrorStatus = FDKaacEnc_prepareBitDistribution(
+ hQC,
+ psyOut,
+ qcOut,
+ cm,
+ qcElement,
+ avgTotalBits,
+ &totalAvailableBits,
+ &avgTotalDynBits);
+
+ if (ErrorStatus != AAC_ENC_OK) {
+ return ErrorStatus;
+ }
+ }
+ else {
+ qcOut[0]->grantedDynBits = ((hQC->maxBitsPerFrame - (hQC->globHdrBits))&~7)
+ - (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits);
+ qcOut[0]->maxDynBits = qcOut[0]->grantedDynBits;
+
+ totalAvailableBits = hQC->maxBitsPerFrame;
+ avgTotalDynBits = 0;
+ }
+
+#ifdef PNS_PRECOUNT_ENABLE
+ /* Calculate estimated pns bits and substract them from grantedDynBits to get a more accurate number of available bits. */
+ if (syntaxFlags & (AC_LD|AC_ELD))
+ {
+ int estimatedPnsBits = 0, ch;
+
+ for (ch=0; ch<cm->nChannels; ch++) {
+ qcOut[0]->pQcOutChannels[ch]->sectionData.noiseNrgBits = noisePreCount(psyOut[0]->pPsyOutChannels[ch]->noiseNrg, psyOut[0]->pPsyOutChannels[ch]->maxSfbPerGroup);
+ estimatedPnsBits += qcOut[0]->pQcOutChannels[ch]->sectionData.noiseNrgBits;
+ }
+ qcOut[0]->grantedDynBits -= estimatedPnsBits;
+ }
+#endif
+
+ /* for ( all sub frames ) ... */
+ for (c = 0 ; c < nSubFrames ; c++ )
+ {
+ /* for CBR and VBR mode */
+ FDKaacEnc_AdjustThresholds(hQC->hAdjThr->adjThrStateElem,
+ qcElement[c],
+ qcOut[c],
+ psyOut[c]->psyOutElement,
+ isConstantBitrateMode(hQC->bitrateMode),
+ cm);
+
+ } /* -end- sub frame counter */
+
+ /*-------------------------------------------- */
+ INT iterations[(1)][(6)];
+ INT chConstraintsFulfilled[(1)][(6)][(2)];
+ INT calculateQuant[(1)][(6)][(2)];
+ INT constraintsFulfilled[(1)][(6)];
+ /*-------------------------------------------- */
+
+
+ /* for ( all sub frames ) ... */
+ for (c = 0 ; c < nSubFrames ; c++ )
+ {
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+ INT ch, nChannels = elInfo.nChannelsInEl;
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ /* Turn thresholds into scalefactors, optimize bit consumption and verify conformance */
+ FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel,
+ qcElement[c][i]->qcOutChannel,
+ hQC->invQuant,
+ cm->elInfo[i].nChannelsInEl);
+
+
+ /*-------------------------------------------- */
+ constraintsFulfilled[c][i] = 1;
+ iterations[c][i] = 0 ;
+
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ chConstraintsFulfilled[c][i][ch] = 1;
+ calculateQuant[c][i][ch] = 1;
+ }
+
+ /*-------------------------------------------- */
+
+ } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
+
+ } /* -end- element loop */
+
+ qcOut[c]->usedDynBits = -1;
+
+ } /* -end- sub frame counter */
+
+
+
+ INT quantizationDone = 0;
+ INT sumDynBitsConsumedTotal = 0;
+ INT decreaseBitConsumption = -1; /* no direction yet! */
+
+ /*-------------------------------------------- */
+ /* -start- Quantization loop ... */
+ /*-------------------------------------------- */
+ do /* until max allowed bits per frame and maxDynBits!=-1*/
+ {
+ quantizationDone = 0;
+
+ c = 0; /* get frame to process */
+
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+ INT ch, nChannels = elInfo.nChannelsInEl;
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ do /* until spectral values < MAX_QUANT */
+ {
+ /*-------------------------------------------- */
+ if (!constraintsFulfilled[c][i])
+ {
+ FDKaacEnc_reduceBitConsumption(&iterations[c][i],
+ hQC->maxIterations,
+ (decreaseBitConsumption) ? 1 : -1,
+ chConstraintsFulfilled[c][i],
+ calculateQuant[c][i],
+ nChannels,
+ psyOut[c]->psyOutElement[i],
+ qcOut[c],
+ qcElement[c][i],
+ hQC->elementBits[i],
+ aot,
+ syntaxFlags,
+ epConfig);
+ }
+
+ /*-------------------------------------------- */
+ /*-------------------------------------------- */
+ constraintsFulfilled[c][i] = 1 ;
+
+ /*-------------------------------------------- */
+ /* quantize spectrum (per each channel) */
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ /*-------------------------------------------- */
+ chConstraintsFulfilled[c][i][ch] = 1;
+
+ /*-------------------------------------------- */
+
+ if (calculateQuant[c][i][ch])
+ {
+ QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch];
+ PSY_OUT_CHANNEL* psyOutCh = psyOut[c]->psyOutElement[i]->psyOutChannel[ch];
+
+ calculateQuant[c][i][ch] = 0; /* calculate quantization only if necessary */
+
+ /*-------------------------------------------- */
+ FDKaacEnc_QuantizeSpectrum(psyOutCh->sfbCnt,
+ psyOutCh->maxSfbPerGroup,
+ psyOutCh->sfbPerGroup,
+ psyOutCh->sfbOffsets,
+ qcOutCh->mdctSpectrum,
+ qcOutCh->globalGain,
+ qcOutCh->scf,
+ qcOutCh->quantSpec) ;
+
+ /*-------------------------------------------- */
+ if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt,
+ psyOutCh->maxSfbPerGroup,
+ psyOutCh->sfbPerGroup,
+ psyOutCh->sfbOffsets,
+ qcOutCh->quantSpec,
+ qcOutCh->maxValueInSfb) > MAX_QUANT)
+ {
+ chConstraintsFulfilled[c][i][ch] = 0;
+ constraintsFulfilled[c][i] = 0 ;
+ /* if quanizted value out of range; increase global gain! */
+ decreaseBitConsumption = 1;
+ }
+
+ /*-------------------------------------------- */
+
+ } /* if calculateQuant[c][i][ch] */
+
+ } /* channel loop */
+
+ /*-------------------------------------------- */
+ /* quantize spectrum (per each channel) */
+
+ /*-------------------------------------------- */
+
+ } while (!constraintsFulfilled[c][i]) ; /* does not regard bit consumption */
+
+
+ /*-------------------------------------------- */
+ /*-------------------------------------------- */
+ qcElement[c][i]->dynBitsUsed = 0 ; /* reset dynamic bits */
+
+ /* quantization valid in current channel! */
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch];
+ PSY_OUT_CHANNEL *psyOutCh = psyOut[c]->psyOutElement[i]->psyOutChannel[ch];
+
+ /* count dynamic bits */
+ INT chDynBits = FDKaacEnc_dynBitCount(hQC->hBitCounter,
+ qcOutCh->quantSpec,
+ qcOutCh->maxValueInSfb,
+ qcOutCh->scf,
+ psyOutCh->lastWindowSequence,
+ psyOutCh->sfbCnt,
+ psyOutCh->maxSfbPerGroup,
+ psyOutCh->sfbPerGroup,
+ psyOutCh->sfbOffsets,
+ &qcOutCh->sectionData,
+ psyOutCh->noiseNrg,
+ psyOutCh->isBook,
+ psyOutCh->isScale,
+ syntaxFlags) ;
+
+ /* sum up dynamic channel bits */
+ qcElement[c][i]->dynBitsUsed += chDynBits;
+ }
+
+ /* save dynBitsUsed for correction of bits2pe relation */
+ if(hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast==-1) {
+ hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast = qcElement[c][i]->dynBitsUsed;
+ }
+ } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */
+
+ } /* -end- element loop */
+
+ /* update dynBits of current subFrame */
+ FDKaacEnc_updateUsedDynBits(&qcOut[c]->usedDynBits,
+ qcElement[c],
+ cm);
+
+ /* get total consumed bits, dyn bits in all sub frames have to be valid */
+ sumDynBitsConsumedTotal = FDKaacEnc_getTotalConsumedDynBits(qcOut, nSubFrames);
+
+ if (sumDynBitsConsumedTotal==-1)
+ {
+ quantizationDone = 0; /* bit consumption not valid in all sub frames */
+ }
+ else
+ {
+ int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits(qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames);
+
+ /* in all frames are valid dynamic bits */
+ if (sumBitsConsumedTotal < totalAvailableBits && (decreaseBitConsumption==1) && checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames)
+ /*()*/ )
+ {
+ quantizationDone = 1; /* exit bit adjustment */
+ }
+ if (sumBitsConsumedTotal > totalAvailableBits && (decreaseBitConsumption==0) )
+// /*()*/ )
+ {
+ quantizationDone = 0; /* reset! */
+ break;
+ }
+ }
+
+
+ /*-------------------------------------------- */
+
+ int emergencyIterations = 1;
+ int dynBitsOvershoot = 0;
+
+ for (c = 0 ; c < nSubFrames ; c++ )
+ {
+ for (i=0; i<cm->nElements; i++)
+ {
+ ELEMENT_INFO elInfo = cm->elInfo[i];
+
+ if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
+ (elInfo.elType == ID_LFE))
+ {
+ /* iteration limitation */
+ emergencyIterations &= ((iterations[c][i] < hQC->maxIterations) ? 0 : 1);
+ }
+ }
+ /* detection if used dyn bits exceeds the maximal allowed criterion */
+ dynBitsOvershoot |= ((qcOut[c]->usedDynBits > qcOut[c]->maxDynBits) ? 1 : 0);
+ }
+
+ if (quantizationDone==0 || dynBitsOvershoot)
+ {
+
+ int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits(qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames);
+
+ if ( (sumDynBitsConsumedTotal >= avgTotalDynBits) || (sumDynBitsConsumedTotal==0) ) {
+ quantizationDone = 1;
+ }
+ if (emergencyIterations && (sumBitsConsumedTotal < totalAvailableBits)) {
+ quantizationDone = 1;
+ }
+ if ((sumBitsConsumedTotal > totalAvailableBits) || !checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames)) {
+ quantizationDone = 0;
+ }
+ if ((sumBitsConsumedTotal < totalAvailableBits) && checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames)) {
+ decreaseBitConsumption = 0;
+ }
+ else {
+ decreaseBitConsumption = 1;
+ }
+
+ if (dynBitsOvershoot) {
+ quantizationDone = 0;
+ decreaseBitConsumption = 1;
+ }
+
+ /* reset constraints fullfilled flags */
+ FDKmemclear(constraintsFulfilled, sizeof(constraintsFulfilled));
+ FDKmemclear(chConstraintsFulfilled, sizeof(chConstraintsFulfilled));
+
+
+ }/* quantizationDone */
+
+ } while (!quantizationDone) ;
+
+ /*-------------------------------------------- */
+ /* ... -end- Quantization loop */
+ /*-------------------------------------------- */
+
+ /*-------------------------------------------- */
+ /*-------------------------------------------- */
+
+ return AAC_ENC_OK;
+}
+
+
+static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption(int* iterations,
+ const int maxIterations,
+ int gainAdjustment,
+ int* chConstraintsFulfilled,
+ int* calculateQuant,
+ int nChannels,
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT* qcOut,
+ QC_OUT_ELEMENT* qcOutElement,
+ ELEMENT_BITS* elBits,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig)
+{
+ int ch;
+
+ /** SOLVING PROBLEM **/
+ if ((*iterations)++ >= maxIterations)
+ {
+ if (qcOutElement->dynBitsUsed==0) {
+ }
+ /* crash recovery */
+ else {
+ INT bitsToSave = 0;
+ if ( (bitsToSave = fixMax((qcOutElement->dynBitsUsed + 8) - (elBits->bitResLevelEl + qcOutElement->grantedDynBits),
+ (qcOutElement->dynBitsUsed + qcOutElement->staticBitsUsed + 8) - (elBits->maxBitsEl))) > 0 )
+ {
+ FDKaacEnc_crashRecovery(nChannels,
+ psyOutElement,
+ qcOut,
+ qcOutElement,
+ bitsToSave,
+ aot,
+ syntaxFlags,
+ epConfig) ;
+ }
+ else
+ {
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ qcOutElement->qcOutChannel[ch]->globalGain += 1;
+ }
+ }
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ calculateQuant[ch] = 1;
+ }
+ }
+ }
+ else /* iterations >= maxIterations */
+ {
+ /* increase gain (+ next iteration) */
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ if(!chConstraintsFulfilled[ch])
+ {
+ qcOutElement->qcOutChannel[ch]->globalGain += gainAdjustment ;
+ calculateQuant[ch] = 1; /* global gain has changed, recalculate quantization in next iteration! */
+ }
+ }
+ }
+
+ return AAC_ENC_OK;
+}
+
+AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm,
+ QC_STATE* qcKernel,
+ ELEMENT_BITS* RESTRICT elBits[(6)],
+ QC_OUT** qcOut)
+{
+ switch (qcKernel->bitrateMode) {
+ case QCDATA_BR_MODE_SFR:
+ break;
+
+ case QCDATA_BR_MODE_FF:
+ break;
+
+ case QCDATA_BR_MODE_VBR_1:
+ case QCDATA_BR_MODE_VBR_2:
+ case QCDATA_BR_MODE_VBR_3:
+ case QCDATA_BR_MODE_VBR_4:
+ case QCDATA_BR_MODE_VBR_5:
+ qcOut[0]->totFillBits = (qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits)&7; /* precalculate alignment bits */
+ break;
+
+ case QCDATA_BR_MODE_CBR:
+ case QCDATA_BR_MODE_INVALID:
+ default:
+ INT bitResSpace = qcKernel->bitResTotMax - qcKernel->bitResTot ;
+ /* processing fill-bits */
+ INT deltaBitRes = qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits ;
+ qcOut[0]->totFillBits = fixMax((deltaBitRes&7), (deltaBitRes - (fixMax(0,bitResSpace-7)&~7)));
+ break;
+ } /* switch (qcKernel->bitrateMode) */
+
+ return AAC_ENC_OK;
+}
+
+
+
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_calcMaxValueInSfb
+ description:
+ return:
+
+**********************************************************************************/
+
+static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt,
+ INT maxSfbPerGroup,
+ INT sfbPerGroup,
+ INT *RESTRICT sfbOffset,
+ SHORT *RESTRICT quantSpectrum,
+ UINT *RESTRICT maxValue)
+{
+ INT sfbOffs,sfb;
+ INT maxValueAll = 0;
+
+ for (sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup)
+ for (sfb = 0; sfb < maxSfbPerGroup; sfb++)
+ {
+ INT line;
+ INT maxThisSfb = 0;
+ for (line = sfbOffset[sfbOffs+sfb]; line < sfbOffset[sfbOffs+sfb+1]; line++)
+ {
+ INT tmp = fixp_abs(quantSpectrum[line]);
+ maxThisSfb = fixMax(tmp, maxThisSfb);
+ }
+
+ maxValue[sfbOffs+sfb] = maxThisSfb;
+ maxValueAll = fixMax(maxThisSfb, maxValueAll);
+ }
+ return maxValueAll;
+}
+
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_updateBitres
+ description:
+ return:
+
+**********************************************************************************/
+void FDKaacEnc_updateBitres(CHANNEL_MAPPING *cm,
+ QC_STATE* qcKernel,
+ QC_OUT** qcOut)
+{
+ switch (qcKernel->bitrateMode) {
+ case QCDATA_BR_MODE_FF:
+ case QCDATA_BR_MODE_VBR_1:
+ case QCDATA_BR_MODE_VBR_2:
+ case QCDATA_BR_MODE_VBR_3:
+ case QCDATA_BR_MODE_VBR_4:
+ case QCDATA_BR_MODE_VBR_5:
+ /* variable bitrate */
+ qcKernel->bitResTot = FDKmin(qcKernel->maxBitsPerFrame, qcKernel->bitResTotMax);
+ break;
+
+ case QCDATA_BR_MODE_CBR:
+ case QCDATA_BR_MODE_SFR:
+ case QCDATA_BR_MODE_INVALID:
+ default:
+ int c = 0;
+ /* constant bitrate */
+ {
+ qcKernel->bitResTot += qcOut[c]->grantedDynBits - (qcOut[c]->usedDynBits + qcOut[c]->totFillBits + qcOut[c]->alignBits);
+ }
+ break;
+ }
+}
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_FinalizeBitConsumption
+ description:
+ return:
+
+**********************************************************************************/
+AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption(CHANNEL_MAPPING *cm,
+ QC_STATE *qcKernel,
+ QC_OUT *qcOut,
+ QC_OUT_ELEMENT** qcElement,
+ HANDLE_TRANSPORTENC hTpEnc,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig)
+{
+ QC_OUT_EXTENSION fillExtPayload;
+ INT totFillBits, alignBits;
+
+ {
+ int exactTpBits;
+ int max_iter = 3;
+
+ /* Get total consumed bits in AU */
+ qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + qcOut->totFillBits +
+ qcOut->elementExtBits + qcOut->globalExtBits;
+
+ /* Now we can get the exact transport bit amount, and hopefully it is equal to the estimated value */
+ exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits);
+
+ if (exactTpBits != qcKernel->globHdrBits) {
+ INT diffFillBits = 0;
+
+ /* Number of bits which can be moved to bitreservoir. */
+ INT bitsToBitres = qcKernel->globHdrBits - exactTpBits;
+
+ if (bitsToBitres>0) {
+ /* if bitreservoir can not take all bits, move ramaining bits to fillbits */
+ diffFillBits = FDKmax(0, bitsToBitres - (qcKernel->bitResTotMax-qcKernel->bitResTot));
+ }
+ else if (bitsToBitres<0) {
+ /* if bits mus be taken from bitreservoir, reduce fillbits first. */
+ diffFillBits = (FDKmax(FDKmax(bitsToBitres, -qcKernel->bitResTot), -qcOut->totFillBits));
+ }
+
+ diffFillBits = (diffFillBits+7)&~7; /* assure previous alignment */
+
+ qcOut->totFillBits += diffFillBits;
+ qcOut->totalBits += diffFillBits;
+ qcOut->grantedDynBits += diffFillBits;
+
+ /* new header bits */
+ qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits);
+ }
+ }
+
+ /* Save total fill bits and distribut to alignment and fill bits */
+ totFillBits = qcOut->totFillBits;
+
+ /* fake a fill extension payload */
+ FDKmemclear(&fillExtPayload, sizeof(QC_OUT_EXTENSION));
+
+ fillExtPayload.type = EXT_FILL_DATA;
+ fillExtPayload.nPayloadBits = totFillBits;
+
+ /* ask bitstream encoder how many of that bits can be written in a fill extension data entity */
+ qcOut->totFillBits = FDKaacEnc_writeExtensionData( NULL,
+ &fillExtPayload,
+ 0, 0,
+ syntaxFlags,
+ aot,
+ epConfig );
+
+ /* now distribute extra fillbits and alignbits */
+ alignBits = 7 - (qcOut->staticBits + qcOut->usedDynBits + qcOut->elementExtBits
+ + qcOut->totFillBits + qcOut->globalExtBits -1)%8;
+
+ /* Maybe we could remove this */
+ if( ((alignBits + qcOut->totFillBits - totFillBits)==8) && (qcOut->totFillBits>8) )
+ qcOut->totFillBits -= 8;
+
+ qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + qcOut->totFillBits +
+ alignBits + qcOut->elementExtBits + qcOut->globalExtBits;
+
+ if ( (qcOut->totalBits>qcKernel->maxBitsPerFrame) || (qcOut->totalBits<qcKernel->minBitsPerFrame) ) {
+ return AAC_ENC_QUANT_ERROR;
+ }
+
+ qcOut->alignBits = alignBits;
+
+ return AAC_ENC_OK;
+}
+
+
+
+/*********************************************************************************
+
+ functionname: FDKaacEnc_crashRecovery
+ description: fulfills constraints by means of brute force...
+ => bits are saved by cancelling out spectral lines!!
+ (beginning at the highest frequencies)
+ return: errorcode
+
+**********************************************************************************/
+
+static void FDKaacEnc_crashRecovery(INT nChannels,
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT* qcOut,
+ QC_OUT_ELEMENT *qcElement,
+ INT bitsToSave,
+ AUDIO_OBJECT_TYPE aot,
+ UINT syntaxFlags,
+ SCHAR epConfig)
+{
+ INT ch ;
+ INT savedBits = 0 ;
+ INT sfb, sfbGrp ;
+ INT bitsPerScf[(2)][MAX_GROUPED_SFB] ;
+ INT sectionToScf[(2)][MAX_GROUPED_SFB] ;
+ INT *sfbOffset ;
+ INT sect, statBitsNew ;
+ QC_OUT_CHANNEL **qcChannel = qcElement->qcOutChannel;
+ PSY_OUT_CHANNEL **psyChannel = psyOutElement->psyOutChannel;
+
+ /* create a table which converts frq-bins to bit-demand... [bitsPerScf] */
+ /* ...and another one which holds the corresponding sections [sectionToScf] */
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ sfbOffset = psyChannel[ch]->sfbOffsets ;
+
+ for (sect = 0; sect < qcChannel[ch]->sectionData.noOfSections; sect++)
+ {
+ INT sfb ;
+ INT codeBook = qcChannel[ch]->sectionData.huffsection[sect].codeBook ;
+
+ for (sfb = qcChannel[ch]->sectionData.huffsection[sect].sfbStart;
+ sfb < qcChannel[ch]->sectionData.huffsection[sect].sfbStart +
+ qcChannel[ch]->sectionData.huffsection[sect].sfbCnt;
+ sfb++)
+ {
+ bitsPerScf[ch][sfb] = 0;
+ if ( (codeBook != CODE_BOOK_PNS_NO) /*&&
+ (sfb < (qcChannel[ch]->sectionData.noOfGroups*qcChannel[ch]->sectionData.maxSfbPerGroup))*/ )
+ {
+ INT sfbStartLine = sfbOffset[sfb] ;
+ INT noOfLines = sfbOffset[sfb+1] - sfbStartLine ;
+ bitsPerScf[ch][sfb] = FDKaacEnc_countValues(&(qcChannel[ch]->quantSpec[sfbStartLine]), noOfLines, codeBook) ;
+ }
+ sectionToScf[ch][sfb] = sect ;
+ }
+
+ }
+ }
+
+ /* LOWER [maxSfb] IN BOTH CHANNELS!! */
+ /* Attention: in case of stereo: maxSfbL == maxSfbR, GroupingL == GroupingR ; */
+
+ for (sfb = qcChannel[0]->sectionData.maxSfbPerGroup-1; sfb >= 0; sfb--)
+ {
+ for (sfbGrp = 0; sfbGrp < psyChannel[0]->sfbCnt; sfbGrp += psyChannel[0]->sfbPerGroup)
+ {
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ int sect = sectionToScf[ch][sfbGrp+sfb];
+ qcChannel[ch]->sectionData.huffsection[sect].sfbCnt-- ;
+ savedBits += bitsPerScf[ch][sfbGrp+sfb] ;
+
+ if (qcChannel[ch]->sectionData.huffsection[sect].sfbCnt == 0) {
+ savedBits += (psyChannel[ch]->lastWindowSequence!=SHORT_WINDOW) ? FDKaacEnc_sideInfoTabLong[0]
+ : FDKaacEnc_sideInfoTabShort[0];
+ }
+ }
+ }
+
+ /* ...have enough bits been saved? */
+ if (savedBits >= bitsToSave)
+ break ;
+
+ } /* sfb loop */
+
+ /* if not enough bits saved,
+ clean whole spectrum and remove side info overhead */
+ if (sfb == -1) {
+ sfb = 0 ;
+ }
+
+ for (ch = 0; ch < nChannels; ch++)
+ {
+ qcChannel[ch]->sectionData.maxSfbPerGroup = sfb ;
+ psyChannel[ch]->maxSfbPerGroup = sfb ;
+ /* when no spectrum is coded save tools info in bitstream */
+ if(sfb==0) {
+ FDKmemclear(&psyChannel[ch]->tnsInfo, sizeof(TNS_INFO));
+ FDKmemclear(&psyOutElement->toolsInfo, sizeof(TOOLSINFO));
+ }
+ }
+ /* dynamic bits will be updated in iteration loop */
+
+ { /* if stop sfb has changed save bits in side info, e.g. MS or TNS coding */
+ ELEMENT_INFO elInfo;
+
+ FDKmemclear(&elInfo, sizeof(ELEMENT_INFO));
+ elInfo.nChannelsInEl = nChannels;
+ elInfo.elType = (nChannels == 2) ? ID_CPE : ID_SCE;
+
+ FDKaacEnc_ChannelElementWrite( NULL, &elInfo, NULL,
+ psyOutElement,
+ psyChannel,
+ syntaxFlags,
+ aot,
+ epConfig,
+ &statBitsNew,
+ 0 );
+ }
+
+ savedBits = qcElement->staticBitsUsed - statBitsNew;
+
+ /* update static and dynamic bits */
+ qcElement->staticBitsUsed -= savedBits;
+ qcElement->grantedDynBits += savedBits;
+
+ qcOut->staticBits -= savedBits;
+ qcOut->grantedDynBits += savedBits;
+ qcOut->maxDynBits += savedBits;
+
+
+}
+
+
+
+void FDKaacEnc_QCClose (QC_STATE **phQCstate, QC_OUT **phQC)
+{
+ int n, i;
+
+ if (phQC!=NULL) {
+
+ for (n=0;n<(1);n++) {
+ if (phQC[n] != NULL) {
+ QC_OUT *hQC = phQC[n];
+ for (i=0; i<(6); i++) {
+ }
+
+ for (i=0; i<(6); i++) {
+ if (hQC->qcElement[i])
+ FreeRam_aacEnc_QCelement(&hQC->qcElement[i]);
+ }
+
+ FreeRam_aacEnc_QCout(&phQC[n]);
+ }
+ }
+ }
+
+ if (phQCstate!=NULL) {
+ if (*phQCstate != NULL) {
+ QC_STATE *hQCstate = *phQCstate;
+
+ if (hQCstate->hAdjThr != NULL)
+ FDKaacEnc_AdjThrClose(&hQCstate->hAdjThr);
+
+ if (hQCstate->hBitCounter != NULL)
+ FDKaacEnc_BCClose(&hQCstate->hBitCounter);
+
+ for (i=0; i<(6); i++) {
+ if (hQCstate->elementBits[i]!=NULL) {
+ FreeRam_aacEnc_ElementBits(&hQCstate->elementBits[i]);
+ }
+ }
+ FreeRam_aacEnc_QCstate(phQCstate);
+ }
+ }
+}
+