summaryrefslogtreecommitdiffstats
path: root/libAACenc/src/aacenc_lib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACenc/src/aacenc_lib.cpp')
-rw-r--r--libAACenc/src/aacenc_lib.cpp1888
1 files changed, 1888 insertions, 0 deletions
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
new file mode 100644
index 0000000..cbb0e2a
--- /dev/null
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -0,0 +1,1888 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+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-4 HE-AAC Encoder *************************
+
+ Initial author: M. Lohwasser
+ contents/description: FDK HE-AAC Encoder interface library functions
+
+****************************************************************************/
+
+#include "aacenc_lib.h"
+#include "FDK_audio.h"
+#include "aacenc.h"
+
+#include "aacEnc_ram.h"
+#include "FDK_core.h" /* FDK_tools versioning info */
+
+/* Encoder library info */
+#define AACENCODER_LIB_VL0 3
+#define AACENCODER_LIB_VL1 3
+#define AACENCODER_LIB_VL2 1
+#define AACENCODER_LIB_TITLE "AAC Encoder"
+#define AACENCODER_LIB_BUILD_DATE __DATE__
+#define AACENCODER_LIB_BUILD_TIME __TIME__
+
+
+#include "sbr_encoder.h"
+#include "../src/sbr_ram.h"
+#include "channel_map.h"
+
+#include "psy_const.h"
+#include "bitenc.h"
+
+#include "tpenc_lib.h"
+
+#include "metadata_main.h"
+
+#define SBL(fl) (fl/8) /*!< Short block length (hardcoded to 8 short blocks per long block) */
+#define BSLA(fl) (4*SBL(fl)+SBL(fl)/2) /*!< AAC block switching look-ahead */
+#define DELAY_AAC(fl) (fl+BSLA(fl)) /*!< MDCT + blockswitching */
+#define DELAY_AACELD(fl) ( (fl) + ((fl)/2) ) /*!< ELD FB delay */
+
+#define INPUTBUFFER_SIZE (1537+100+2048)
+
+////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Flags to characterize encoder modules to be supported in present instance.
+ */
+enum {
+ ENC_MODE_FLAG_AAC = 0x0001,
+ ENC_MODE_FLAG_SBR = 0x0002,
+ ENC_MODE_FLAG_PS = 0x0004,
+ ENC_MODE_FLAG_SAC = 0x0008,
+ ENC_MODE_FLAG_META = 0x0010
+};
+
+////////////////////////////////////////////////////////////////////////////////////
+typedef struct {
+ AUDIO_OBJECT_TYPE userAOT; /*!< Audio Object Type. */
+ UINT userSamplerate; /*!< Sampling frequency. */
+ UINT nChannels; /*!< will be set via channelMode. */
+ CHANNEL_MODE userChannelMode;
+ UINT userBitrate;
+ UINT userBitrateMode;
+ UINT userBandwidth;
+ UINT userAfterburner;
+ UINT userFramelength;
+ UINT userAncDataRate;
+
+ UCHAR userTns; /*!< Use TNS coding. */
+ UCHAR userPns; /*!< Use PNS coding. */
+ UCHAR userIntensity; /*!< Use Intensity coding. */
+
+ TRANSPORT_TYPE userTpType; /*!< Transport type */
+ UCHAR userTpSignaling; /*!< Extension AOT signaling mode. */
+ UCHAR userTpNsubFrames; /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1). */
+ UCHAR userTpAmxv; /*!< AudioMuxVersion to be used for LATM (default 0). */
+ UCHAR userTpProtection;
+ UCHAR userTpHeaderPeriod; /*!< Parameter used to configure LATM/LOAS SMC rate. Moreover this parameters is
+ used to configure repetition rate of PCE in raw_data_block. */
+
+ UCHAR userErTools; /*!< Use VCB11, HCR and/or RVLC ER tool. */
+ UINT userPceAdditions; /*!< Configure additional bits in PCE. */
+
+ UCHAR userMetaDataMode; /*!< Meta data library configuration. */
+
+ UCHAR userSbrEnabled;
+
+} USER_PARAM;
+
+////////////////////////////////////////////////////////////////////////////////////
+
+/****************************************************************************
+ Structure Definitions
+****************************************************************************/
+
+typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG;
+
+
+struct AACENCODER
+{
+ USER_PARAM extParam;
+ CODER_CONFIG coderConfig;
+
+ /* AAC */
+ AACENC_CONFIG aacConfig;
+ HANDLE_AAC_ENC hAacEnc;
+
+ /* SBR */
+ HANDLE_SBR_ENCODER hEnvEnc;
+
+ /* Meta Data */
+ HANDLE_FDK_METADATA_ENCODER hMetadataEnc;
+ INT metaDataAllowed; /* Signal whether chosen configuration allows metadata. Necessary for delay
+ compensation. Metadata mode is a separate parameter. */
+
+ /* Transport */
+ HANDLE_TRANSPORTENC hTpEnc;
+
+ /* Output */
+ UCHAR *outBuffer; /* Internal bitstream buffer */
+ INT outBufferInBytes; /* Size of internal bitstream buffer*/
+
+ /* Input */
+ INT_PCM *inputBuffer; /* Internal input buffer. Input source for AAC encoder */
+ INT inputBufferOffset; /* Where to write new input samples. */
+
+ INT nSamplesToRead; /* number of input samples neeeded for encoding one frame */
+ INT nSamplesRead; /* number of input samples already in input buffer */
+ INT nZerosAppended; /* appended zeros at end of file*/
+ INT nDelay; /* encoder delay */
+
+ AACENC_EXT_PAYLOAD extPayload [MAX_TOTAL_EXT_PAYLOADS];
+ /* Extension payload */
+ UCHAR extPayloadData [(1)][(6)][MAX_PAYLOAD_SIZE];
+ UINT extPayloadSize [(1)][(6)]; /* payload sizes in bits */
+
+ ULONG InitFlags; /* internal status to treggier re-initialization */
+
+
+ /* Memory allocation info. */
+ INT nMaxAacElements;
+ INT nMaxAacChannels;
+ INT nMaxSbrElements;
+ INT nMaxSbrChannels;
+ UINT nMaxSubFrames;
+
+ UINT encoder_modis;
+
+ /* Capabity flags */
+ UINT CAPF_tpEnc;
+
+} ;
+
+////////////////////////////////////////////////////////////////////////////////////
+
+static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig)
+{
+ INT sbrUsed = 0;
+
+ if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS)
+ || (hAacConfig->audioObjectType==AOT_MP2_SBR) || (hAacConfig->audioObjectType==AOT_MP2_PS)
+ || (hAacConfig->audioObjectType==AOT_DABPLUS_SBR) || (hAacConfig->audioObjectType==AOT_DABPLUS_PS)
+ || (hAacConfig->audioObjectType==AOT_DRM_SBR) || (hAacConfig->audioObjectType==AOT_DRM_MPEG_PS) )
+ {
+ sbrUsed = 1;
+ }
+ if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && (hAacConfig->syntaxFlags & AC_SBR_PRESENT))
+ {
+ sbrUsed = 1;
+ }
+
+ return ( sbrUsed );
+}
+
+/****************************************************************************
+ Allocate Encoder
+****************************************************************************/
+
+H_ALLOC_MEM (_AacEncoder, AACENCODER)
+C_ALLOC_MEM (_AacEncoder, AACENCODER, 1)
+
+
+
+
+/*
+ * Map Encoder specific config structures to CODER_CONFIG.
+ */
+static
+void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CONFIG hAacConfig)
+{
+ AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT;
+ FDKmemclear(cc, sizeof(CODER_CONFIG));
+
+ cc->flags = 0;
+
+ /* Map virtual aot to transport aot. */
+ switch (hAacConfig->audioObjectType) {
+ case AOT_MP2_AAC_LC:
+ transport_AOT = AOT_AAC_LC;
+ break;
+ case AOT_MP2_SBR:
+ transport_AOT = AOT_SBR;
+ cc->flags |= CC_SBR;
+ break;
+ case AOT_MP2_PS:
+ transport_AOT = AOT_PS;
+ cc->flags |= CC_SBR;
+ break;
+ default:
+ transport_AOT = hAacConfig->audioObjectType;
+ }
+
+ if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) {
+ cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0;
+ }
+
+ /* transport type is usually AAC-LC. */
+ if ( (transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS) ) {
+ cc->aot = AOT_AAC_LC;
+ }
+ else {
+ cc->aot = transport_AOT;
+ }
+
+ /* Configure extension aot. */
+ if (extCfg->userTpSignaling==0) {
+ cc->extAOT = AOT_NULL_OBJECT; /* implicit */
+ }
+ else {
+ if ( (extCfg->userTpSignaling==1) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) {
+ cc->extAOT = AOT_SBR; /* explicit backward compatible */
+ }
+ else {
+ cc->extAOT = transport_AOT; /* explicit hierarchical */
+ }
+ }
+ cc->extSamplingRate = extCfg->userSamplerate;
+ cc->bitRate = hAacConfig->bitRate;
+ cc->noChannels = hAacConfig->nChannels;
+ cc->flags |= CC_IS_BASELAYER;
+ cc->channelMode = hAacConfig->channelMode;
+
+ cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1)
+ ? hAacConfig->nSubFrames
+ : extCfg->userTpNsubFrames;
+
+ cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0;
+
+ if (extCfg->userTpHeaderPeriod!=0xFF) {
+ cc->headerPeriod = extCfg->userTpHeaderPeriod;
+ }
+ else { /* auto-mode */
+ switch (extCfg->userTpType) {
+ case TT_MP4_ADTS:
+ case TT_MP4_LOAS:
+ case TT_MP4_LATM_MCP1:
+ cc->headerPeriod = 10;
+ break;
+ default:
+ cc->headerPeriod = 0;
+ }
+ }
+
+ cc->samplesPerFrame = hAacConfig->framelength;
+ cc->samplingRate = hAacConfig->sampleRate;
+
+ /* Mpeg-4 signaling for transport library. */
+ switch ( hAacConfig->audioObjectType ) {
+ case AOT_MP2_AAC_LC:
+ case AOT_MP2_SBR:
+ case AOT_MP2_PS:
+ cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */
+ //config->userTpSignaling=0;
+ cc->extAOT = AOT_NULL_OBJECT;
+ break;
+ default:
+ cc->flags |= CC_MPEG_ID;
+ }
+
+ /* ER-tools signaling. */
+ cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0;
+ cc->flags |= (hAacConfig->syntaxFlags & AC_ER_HCR) ? CC_HCR : 0;
+ cc->flags |= (hAacConfig->syntaxFlags & AC_ER_RVLC) ? CC_RVLC : 0;
+
+ /* Matrix mixdown coefficient configuration. */
+ if ( (extCfg->userPceAdditions&0x1) && (hAacConfig->epConfig==-1)
+ && ((cc->channelMode==MODE_1_2_2)||(cc->channelMode==MODE_1_2_2_1)) )
+ {
+ cc->matrixMixdownA = ((extCfg->userPceAdditions>>1)&0x3)+1;
+ cc->flags |= (extCfg->userPceAdditions>>3)&0x1 ? CC_PSEUDO_SURROUND : 0;
+ }
+ else {
+ cc->matrixMixdownA = 0;
+ }
+}
+
+/*
+ * Examine buffer descriptor regarding choosen identifier.
+ *
+ * \param pBufDesc Pointer to buffer descriptor
+ * \param identifier Buffer identifier to look for.
+
+ * \return - Buffer descriptor index.
+ * -1, if there is no entry available.
+ */
+static INT getBufDescIdx(
+ const AACENC_BufDesc *pBufDesc,
+ const AACENC_BufferIdentifier identifier
+)
+{
+ INT i, idx = -1;
+
+ for (i=0; i<pBufDesc->numBufs; i++) {
+ if ( (AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == identifier ) {
+ idx = i;
+ break;
+ }
+ }
+ return idx;
+}
+
+
+/****************************************************************************
+ Function Declarations
+****************************************************************************/
+
+AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig,
+ USER_PARAM *config)
+{
+ /* make reasonable default settings */
+ FDKaacEnc_AacInitDefaultConfig (hAacConfig);
+
+ /* clear confure structure and copy default settings */
+ FDKmemclear(config, sizeof(USER_PARAM));
+
+ /* copy encoder configuration settings */
+ config->nChannels = hAacConfig->nChannels;
+ config->userAOT = hAacConfig->audioObjectType = AOT_AAC_LC;
+ config->userSamplerate = hAacConfig->sampleRate;
+ config->userChannelMode = hAacConfig->channelMode;
+ config->userBitrate = hAacConfig->bitRate;
+ config->userBitrateMode = hAacConfig->bitrateMode;
+ config->userBandwidth = hAacConfig->bandWidth;
+ config->userTns = hAacConfig->useTns;
+ config->userPns = hAacConfig->usePns;
+ config->userIntensity = hAacConfig->useIS;
+ config->userAfterburner = hAacConfig->useRequant;
+ config->userFramelength = (UINT)-1;
+
+ if (hAacConfig->syntaxFlags & AC_ER_VCB11) {
+ config->userErTools |= 0x01;
+ }
+ if (hAacConfig->syntaxFlags & AC_ER_HCR) {
+ config->userErTools |= 0x02;
+ }
+
+ /* initialize transport parameters */
+ config->userTpType = TT_UNKNOWN;
+ config->userTpAmxv = 0;
+ config->userTpSignaling = 0; /* default, implicit signaling */
+ config->userTpNsubFrames = 1;
+ config->userTpProtection = 0; /* not crc protected*/
+ config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */
+ config->userPceAdditions = 0; /* no matrix mixdown coefficient */
+ config->userMetaDataMode = 0; /* do not embed any meta data info */
+
+ config->userAncDataRate = 0;
+
+ 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
+ * encoder configuration struct.
+ *
+ * \hAacEncoder Internal encoder config which is to be updated
+ * \param config User provided config (public struct)
+ * \return ´returns always AAC_ENC_OK
+ */
+static
+AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
+ USER_PARAM *config)
+{
+ AACENC_ERROR err = AACENC_OK;
+
+ /* Get struct pointers. */
+ HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig;
+
+ hAacConfig->nChannels = config->nChannels;
+
+ /* Encoder settings update. */
+ hAacConfig->sampleRate = config->userSamplerate;
+ hAacConfig->useTns = config->userTns;
+ hAacConfig->usePns = config->userPns;
+ hAacConfig->useIS = config->userIntensity;
+ hAacConfig->bitRate = config->userBitrate;
+ hAacConfig->channelMode = config->userChannelMode;
+ hAacConfig->bitrateMode = config->userBitrateMode;
+ hAacConfig->bandWidth = config->userBandwidth;
+ hAacConfig->useRequant = config->userAfterburner;
+
+ hAacConfig->audioObjectType = config->userAOT;
+ hAacConfig->anc_Rate = config->userAncDataRate;
+ hAacConfig->syntaxFlags = 0;
+ hAacConfig->epConfig = -1;
+
+ /* Adapt internal AOT when necessary. */
+ switch ( hAacConfig->audioObjectType ) {
+ case AOT_MP2_AAC_LC:
+ case AOT_MP2_SBR:
+ case AOT_MP2_PS:
+ hAacConfig->usePns = 0;
+ if (config->userTpSignaling!=0) {
+ return AACENC_INVALID_CONFIG; /* only implicit signaling allowed */
+ }
+ case AOT_AAC_LC:
+ case AOT_SBR:
+ case AOT_PS:
+ config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_ADTS;
+ hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 1024;
+ if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) {
+ return AACENC_INVALID_CONFIG;
+ }
+ break;
+ case AOT_ER_AAC_LC:
+ hAacConfig->epConfig = 0;
+ hAacConfig->syntaxFlags |= AC_ER;
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
+ config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
+ hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 1024;
+ if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) {
+ return AACENC_INVALID_CONFIG;
+ }
+ break;
+ case AOT_ER_AAC_LD:
+ hAacConfig->epConfig = 0;
+ hAacConfig->syntaxFlags |= AC_ER|AC_LD;
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0);
+ config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
+ hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512;
+ if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) {
+ return AACENC_INVALID_CONFIG;
+ }
+ break;
+ case AOT_ER_AAC_ELD:
+ hAacConfig->epConfig = 0;
+ hAacConfig->syntaxFlags |= AC_ER|AC_ELD;
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
+ hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0);
+ hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0);
+ config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
+ hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512;
+ if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) {
+ return AACENC_INVALID_CONFIG;
+ }
+ break;
+ default:
+ 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:
+ if (config->userBitrateMode==8) {
+ hAacConfig->bitrateMode = 0;
+ }
+ if (config->userBitrateMode==0) {
+ hAacConfig->bitreservoir = 50*config->nChannels; /* default, reduced bitreservoir */
+ }
+ if (hAacConfig->bitrateMode!=0) {
+ return AACENC_INVALID_CONFIG;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (hAacConfig->epConfig >= 0) {
+ hAacConfig->syntaxFlags |= AC_ER;
+ if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) {
+ return AACENC_INVALID_CONFIG; /* Cannel config 0 not supported. */
+ }
+ }
+
+ if ( FDKaacEnc_DetermineEncoderMode(&hAacConfig->channelMode, hAacConfig->nChannels) != AAC_ENC_OK) {
+ return AACENC_INVALID_CONFIG; /* nChannels doesn't match chMode, this is just a check-up */
+ }
+
+ if ( (hAacConfig->nChannels > hAacEncoder->nMaxAacChannels)
+ || ( (FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff > hAacEncoder->nMaxSbrChannels) &&
+ isSbrActive(hAacConfig) )
+ )
+ {
+ return AACENC_INVALID_CONFIG; /* not enough channels allocated */
+ }
+
+ /* get bitrate in VBR configuration */
+ if ( (hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5) ) {
+ /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. */
+ hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, hAacConfig->channelMode);
+ }
+
+
+
+ /* Set default bitrate if no external bitrate declared. */
+ if (hAacConfig->bitRate==-1) {
+ INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff * hAacConfig->sampleRate;
+ switch (hAacConfig->audioObjectType)
+ {
+ case AOT_AAC_LC:
+ hAacConfig->bitRate = bitrate + (bitrate>>1); /* 1.5 bits per sample */
+ break;
+ case AOT_SBR:
+ hAacConfig->bitRate = (bitrate + (bitrate>>2))>>1; /* 0.625 bits per sample */
+ break;
+ case AOT_PS:
+ hAacConfig->bitRate = (bitrate>>1); /* 0.5 bit per sample */
+ break;
+ default:
+ hAacConfig->bitRate = bitrate;
+ break;
+ }
+ }
+
+ /* Configure PNS */
+ if ( ((hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5)) /* VBR without PNS. */
+ || (hAacConfig->useTns == 0) ) /* TNS required. */
+ {
+ hAacConfig->usePns = 0;
+ }
+
+ /* Meta data restriction. */
+ switch (hAacConfig->audioObjectType)
+ {
+ /* Allow metadata support */
+ case AOT_AAC_LC:
+ case AOT_SBR:
+ hAacEncoder->metaDataAllowed = 1;
+ if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) {
+ config->userMetaDataMode = 0;
+ }
+ break;
+ /* Prohibit metadata support */
+ default:
+ hAacEncoder->metaDataAllowed = 0;
+ }
+
+ return err;
+}
+
+static
+INT aacenc_SbrCallback(
+ void * self,
+ HANDLE_FDK_BITSTREAM hBs,
+ const INT sampleRateIn,
+ const INT sampleRateOut,
+ const INT samplesPerFrame,
+ const AUDIO_OBJECT_TYPE coreCodec,
+ const MP4_ELEMENT_ID elementID,
+ const INT elementIndex
+ )
+{
+ HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self;
+
+ sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0);
+
+ return 0;
+}
+
+static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
+ ULONG InitFlags,
+ USER_PARAM *config)
+{
+ AACENC_ERROR err = AACENC_OK;
+
+ INT aacBufferOffset = 0;
+ HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc;
+ HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig;
+
+ hAacEncoder->nZerosAppended = 0; /* count appended zeros */
+
+ INT frameLength = hAacConfig->framelength;
+
+ if ( (InitFlags & AACENC_INIT_CONFIG) )
+ {
+ CHANNEL_MODE prevChMode = hAacConfig->channelMode;
+
+ /* Verify settings and update: config -> heAacEncoder */
+ if ( (err=FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK ) {
+ return err;
+ }
+ frameLength = hAacConfig->framelength; /* adapt temporal framelength */
+
+ /* Seamless channel reconfiguration in sbr not fully implemented */
+ if ( (prevChMode!=hAacConfig->channelMode) && isSbrActive(hAacConfig) ) {
+ InitFlags |= AACENC_INIT_STATES;
+ }
+ }
+
+ /* Clear input buffer */
+ if ( (InitFlags == AACENC_INIT_ALL) ) {
+ FDKmemclear(hAacEncoder->inputBuffer, sizeof(INT_PCM)*hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE);
+ }
+
+ if ( (InitFlags & AACENC_INIT_CONFIG) )
+ {
+ aacBufferOffset = 0;
+ if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) {
+ hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength);
+ } else
+ {
+ hAacEncoder->nDelay = DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */
+ }
+ hAacConfig->ancDataBitRate = 0;
+ }
+
+ if ( isSbrActive(hAacConfig) &&
+ ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) )
+ {
+ INT sbrError;
+ SBR_ELEMENT_INFO sbrElInfo[(6)];
+ CHANNEL_MAPPING channelMapping;
+
+ AUDIO_OBJECT_TYPE aot = hAacConfig->audioObjectType;
+
+ if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode,
+ hAacConfig->channelOrder,
+ &channelMapping) != AAC_ENC_OK )
+ {
+ return AACENC_INIT_ERROR;
+ }
+
+ /* Check return value and if the SBR encoder can handle enough elements */
+ if (channelMapping.nElements > (6)) {
+ return AACENC_INIT_ERROR;
+ }
+
+ aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate);
+
+ UINT initFlag = 0;
+ initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0;
+
+ /* Let the SBR encoder take a look at the configuration and change if required. */
+ sbrError = sbrEncoder_Init(
+ *hSbrEncoder,
+ sbrElInfo,
+ channelMapping.nElements,
+ hAacEncoder->inputBuffer,
+ &hAacConfig->bandWidth,
+ &aacBufferOffset,
+ &hAacConfig->nChannels,
+ &hAacConfig->sampleRate,
+ &frameLength,
+ &hAacConfig->audioObjectType,
+ &hAacEncoder->nDelay,
+ (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC,
+ initFlag
+ );
+
+ /* Suppress AOT reconfiguration and check error status. */
+ if ( sbrError || (hAacConfig->audioObjectType!=aot) ) {
+ return AACENC_INIT_SBR_ERROR;
+ }
+
+ if (hAacConfig->nChannels == 1) {
+ hAacConfig->channelMode = MODE_1;
+ }
+
+ /* Never use PNS if SBR is active */
+ if ( hAacConfig->usePns ) {
+ hAacConfig->usePns = 0;
+ }
+
+ /* estimated bitrate consumed by SBR or PS */
+ hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder) ;
+
+ } /* sbr initialization */
+
+
+ /*
+ * Initialize Transport - Module.
+ */
+ if ( (InitFlags & AACENC_INIT_TRANSPORT) )
+ {
+ UINT flags = 0;
+
+ FDKaacEnc_MapConfig(&hAacEncoder->coderConfig, config, hAacConfig);
+
+ /* create flags for transport encoder */
+ if (config->userTpAmxv == 1) {
+ flags |= TP_FLAG_LATM_AMV;
+ }
+ /* Clear output buffer */
+ FDKmemclear(hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes*sizeof(UCHAR));
+
+ /* Initialize Bitstream encoder */
+ if ( transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes, config->userTpType, &hAacEncoder->coderConfig, flags) != 0) {
+ return AACENC_INIT_TP_ERROR;
+ }
+
+ } /* transport initialization */
+
+ /*
+ * Initialize AAC - Core.
+ */
+ if ( (InitFlags & AACENC_INIT_CONFIG) ||
+ (InitFlags & AACENC_INIT_STATES) )
+ {
+ AAC_ENCODER_ERROR err;
+ err = FDKaacEnc_Initialize(hAacEncoder->hAacEnc,
+ hAacConfig,
+ hAacEncoder->hTpEnc,
+ (InitFlags & AACENC_INIT_STATES) ? 1 : 0);
+
+ if (err != AAC_ENC_OK) {
+ return AACENC_INIT_AAC_ERROR;
+ }
+
+ } /* aac initialization */
+
+ /*
+ * Initialize Meta Data - Encoder.
+ */
+ if ( hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed!=0) &&
+ ((InitFlags & AACENC_INIT_CONFIG) ||(InitFlags & AACENC_INIT_STATES)) )
+ {
+ INT inputDataDelay = DELAY_AAC(hAacConfig->framelength);
+
+ if ( isSbrActive(hAacConfig) && hSbrEncoder!=NULL) {
+ inputDataDelay = 2*inputDataDelay + sbrEncoder_GetInputDataDelay(*hSbrEncoder);
+ }
+
+ if ( FDK_MetadataEnc_Init(hAacEncoder->hMetadataEnc,
+ ((InitFlags&AACENC_INIT_STATES) ? 1 : 0),
+ config->userMetaDataMode,
+ inputDataDelay,
+ frameLength,
+ config->userSamplerate,
+ config->nChannels,
+ config->userChannelMode,
+ hAacConfig->channelOrder) != 0)
+ {
+ return AACENC_INIT_META_ERROR;
+ }
+
+ hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc);
+ }
+
+ /*
+ * Update pointer to working buffer.
+ */
+ if ( (InitFlags & AACENC_INIT_CONFIG) )
+ {
+ hAacEncoder->inputBufferOffset = aacBufferOffset;
+
+ hAacEncoder->nSamplesToRead = frameLength * config->nChannels;
+
+ /* Make nDelay comparison compatible with config->nSamplesRead */
+ hAacEncoder->nDelay *= config->nChannels;
+
+ } /* parameter changed */
+
+ return AACENC_OK;
+}
+
+
+AACENC_ERROR aacEncOpen(
+ HANDLE_AACENCODER *phAacEncoder,
+ const UINT encModules,
+ const UINT maxChannels
+ )
+{
+ AACENC_ERROR err = AACENC_OK;
+ HANDLE_AACENCODER hAacEncoder = NULL;
+
+ if (phAacEncoder == NULL) {
+ err = AACENC_INVALID_HANDLE;
+ goto bail;
+ }
+
+ /* allocate memory */
+ hAacEncoder = Get_AacEncoder();
+
+ if (hAacEncoder == NULL) {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+
+ FDKmemclear(hAacEncoder, sizeof(AACENCODER));
+
+ /* Specify encoder modules to be allocated. */
+ if (encModules==0) {
+ hAacEncoder->encoder_modis = ENC_MODE_FLAG_AAC;
+ hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR;
+ hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS;
+ hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META;
+ }
+ else {
+ /* consider SAC and PS module */
+ hAacEncoder->encoder_modis = encModules;
+ }
+
+ /* Determine max channel configuration. */
+ if (maxChannels==0) {
+ hAacEncoder->nMaxAacChannels = (6);
+ hAacEncoder->nMaxSbrChannels = (6);
+ }
+ else {
+ hAacEncoder->nMaxAacChannels = (maxChannels&0x00FF);
+ if ( (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) ) {
+ hAacEncoder->nMaxSbrChannels = (maxChannels&0xFF00) ? (maxChannels>>8) : hAacEncoder->nMaxAacChannels;
+ }
+
+ if ( (hAacEncoder->nMaxAacChannels>(6)) || (hAacEncoder->nMaxSbrChannels>(6)) ) {
+ err = AACENC_INVALID_CONFIG;
+ goto bail;
+ }
+ } /* maxChannels==0 */
+
+ /* Max number of elements could be tuned any more. */
+ hAacEncoder->nMaxAacElements = fixMin((6), hAacEncoder->nMaxAacChannels);
+ hAacEncoder->nMaxSbrElements = fixMin((6), hAacEncoder->nMaxSbrChannels);
+ hAacEncoder->nMaxSubFrames = (1);
+
+
+ /* In case of memory overlay, allocate memory out of libraries */
+
+ hAacEncoder->inputBuffer = (INT_PCM*)FDKcalloc(hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE, sizeof(INT_PCM));
+
+ /* Open SBR Encoder */
+ if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) {
+ if ( sbrEncoder_Open(&hAacEncoder->hEnvEnc,
+ hAacEncoder->nMaxSbrElements,
+ hAacEncoder->nMaxSbrChannels,
+ (hAacEncoder->encoder_modis&ENC_MODE_FLAG_PS) ? 1 : 0 ) )
+ {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+ } /* (encoder_modis&ENC_MODE_FLAG_SBR) */
+
+
+ /* Open Aac Encoder */
+ if ( FDKaacEnc_Open(&hAacEncoder->hAacEnc,
+ hAacEncoder->nMaxAacElements,
+ hAacEncoder->nMaxAacChannels,
+ (1)) != AAC_ENC_OK )
+ {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+
+ { /* Get bitstream outputbuffer size */
+ UINT ld_M;
+ for (ld_M=1; (UINT)(1<<ld_M) < (hAacEncoder->nMaxSubFrames*hAacEncoder->nMaxAacChannels*6144)>>3; ld_M++) ;
+ hAacEncoder->outBufferInBytes = (1<<ld_M); /* buffer has to be 2^n */
+ }
+ hAacEncoder->outBuffer = GetRam_bsOutbuffer();
+ if (OUTPUTBUFFER_SIZE < hAacEncoder->outBufferInBytes ) {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+
+ /* Open Meta Data Encoder */
+ if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_META) {
+ if ( FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc) )
+ {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+ } /* (encoder_modis&ENC_MODE_FLAG_META) */
+
+ /* Open Transport Encoder */
+ if ( transportEnc_Open(&hAacEncoder->hTpEnc) != 0 )
+ {
+ err = AACENC_MEMORY_ERROR;
+ goto bail;
+ }
+ else {
+ C_ALLOC_SCRATCH_START(pLibInfo, LIB_INFO, FDK_MODULE_LAST);
+
+ FDKinitLibInfo( pLibInfo);
+ transportEnc_GetLibInfo( pLibInfo );
+
+ /* Get capabilty flag for transport encoder. */
+ hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities( pLibInfo, FDK_TPENC);
+
+ C_ALLOC_SCRATCH_END(pLibInfo, LIB_INFO, FDK_MODULE_LAST);
+ }
+ if ( transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, hAacEncoder) != 0 ) {
+ err = AACENC_INIT_TP_ERROR;
+ goto bail;
+ }
+
+ /* Initialize encoder instance with default parameters. */
+ aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam);
+
+ /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */
+ hAacEncoder->coderConfig.headerPeriod = hAacEncoder->extParam.userTpHeaderPeriod;
+
+ /* All encoder modules have to be initialized */
+ hAacEncoder->InitFlags = AACENC_INIT_ALL;
+
+ /* Return encoder instance */
+ *phAacEncoder = hAacEncoder;
+
+ return err;
+
+bail:
+ aacEncClose(&hAacEncoder);
+
+ return err;
+}
+
+
+
+AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder)
+{
+ AACENC_ERROR err = AACENC_OK;
+
+ if (phAacEncoder == NULL) {
+ err = AACENC_INVALID_HANDLE;
+ goto bail;
+ }
+
+ if (*phAacEncoder != NULL) {
+ HANDLE_AACENCODER hAacEncoder = *phAacEncoder;
+
+
+ if (hAacEncoder->inputBuffer!=NULL) {
+ FDKfree(hAacEncoder->inputBuffer);
+ hAacEncoder->inputBuffer = NULL;
+ }
+
+ if (hAacEncoder->outBuffer) {
+ FreeRam_bsOutbuffer(&hAacEncoder->outBuffer);
+ }
+
+ if (hAacEncoder->hEnvEnc) {
+ sbrEncoder_Close (&hAacEncoder->hEnvEnc);
+ }
+ if (hAacEncoder->hAacEnc) {
+ FDKaacEnc_Close (&hAacEncoder->hAacEnc);
+ }
+
+ transportEnc_Close(&hAacEncoder->hTpEnc);
+
+ if (hAacEncoder->hMetadataEnc) {
+ FDK_MetadataEnc_Close (&hAacEncoder->hMetadataEnc);
+ }
+
+ Free_AacEncoder(phAacEncoder);
+ }
+
+bail:
+ return err;
+}
+
+AACENC_ERROR aacEncEncode(
+ const HANDLE_AACENCODER hAacEncoder,
+ const AACENC_BufDesc *inBufDesc,
+ const AACENC_BufDesc *outBufDesc,
+ const AACENC_InArgs *inargs,
+ AACENC_OutArgs *outargs
+ )
+{
+ AACENC_ERROR err = AACENC_OK;
+ INT i, nBsBytes = 0;
+ INT outBytes[(1)];
+ int nExtensions = 0;
+ int ancDataExtIdx = -1;
+
+ /* deal with valid encoder handle */
+ if (hAacEncoder==NULL) {
+ err = AACENC_INVALID_HANDLE;
+ goto bail;
+ }
+
+
+ /*
+ * Adjust user settings and trigger reinitialization.
+ */
+ if (hAacEncoder->InitFlags!=0) {
+
+ err = aacEncInit(hAacEncoder,
+ hAacEncoder->InitFlags,
+ &hAacEncoder->extParam);
+
+ if (err!=AACENC_OK) {
+ /* keep init flags alive! */
+ goto bail;
+ }
+ hAacEncoder->InitFlags = AACENC_INIT_NONE;
+ }
+
+ if (outargs!=NULL) {
+ FDKmemclear(outargs, sizeof(AACENC_OutArgs));
+ }
+
+ if (outBufDesc!=NULL) {
+ for (i=0; i<outBufDesc->numBufs; i++) {
+ if (outBufDesc->bufs[i]!=NULL) {
+ FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]);
+ }
+ }
+ }
+
+ /*
+ * If only encoder handle given, independent (re)initialization can be triggered.
+ */
+ if ( (hAacEncoder!=NULL) & (inBufDesc==NULL) && (outBufDesc==NULL) && (inargs==NULL) && (outargs==NULL) ) {
+ goto bail;
+ }
+
+ /* reset buffer wich signals number of valid bytes in output bitstream buffer */
+ FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames*sizeof(INT));
+
+ /*
+ * Manage incoming audio samples.
+ */
+ if ( (inargs->numInSamples > 0) && (getBufDescIdx(inBufDesc,IN_AUDIO_DATA) != -1) )
+ {
+ /* Fetch data until nSamplesToRead reached */
+ INT idx = getBufDescIdx(inBufDesc,IN_AUDIO_DATA);
+ INT newSamples = fixMax(0,fixMin(inargs->numInSamples, hAacEncoder->nSamplesToRead-hAacEncoder->nSamplesRead));
+ INT_PCM *pIn = hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead;
+
+ /* Copy new input samples to internal buffer */
+ if (inBufDesc->bufElSizes[idx]==(INT)sizeof(INT_PCM)) {
+ FDKmemcpy(pIn, (INT_PCM*)inBufDesc->bufs[idx], newSamples*sizeof(INT_PCM)); /* Fast copy. */
+ }
+ else if (inBufDesc->bufElSizes[idx]>(INT)sizeof(INT_PCM)) {
+ for (i=0; i<newSamples; i++) {
+ pIn[i] = (INT_PCM)(((LONG*)inBufDesc->bufs[idx])[i]>>16); /* Convert 32 to 16 bit. */
+ }
+ }
+ else {
+ for (i=0; i<newSamples; i++) {
+ pIn[i] = ((INT_PCM)(((SHORT*)inBufDesc->bufs[idx])[i]))<<16; /* Convert 16 to 32 bit. */
+ }
+ }
+ hAacEncoder->nSamplesRead += newSamples;
+
+ /* Number of fetched input buffer samples. */
+ outargs->numInSamples = newSamples;
+ }
+
+ /* input buffer completely filled ? */
+ if (hAacEncoder->nSamplesRead < hAacEncoder->nSamplesToRead)
+ {
+ /* - eof reached and flushing enabled, or
+ - return to main and wait for further incoming audio samples */
+ if (inargs->numInSamples==-1)
+ {
+ if ( (hAacEncoder->nZerosAppended < hAacEncoder->nDelay)
+ )
+ {
+ int nZeros = hAacEncoder->nSamplesToRead - hAacEncoder->nSamplesRead;
+
+ FDK_ASSERT(nZeros >= 0);
+
+ /* clear out until end-of-buffer */
+ if (nZeros) {
+ FDKmemclear(hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead, sizeof(INT_PCM)*nZeros );
+ hAacEncoder->nZerosAppended += nZeros;
+ hAacEncoder->nSamplesRead = hAacEncoder->nSamplesToRead;
+ }
+ }
+ else { /* flushing completed */
+ err = AACENC_ENCODE_EOF; /* eof reached */
+ goto bail;
+ }
+ }
+ else { /* inargs->numInSamples!= -1 */
+ goto bail; /* not enough samples in input buffer and no flushing enabled */
+ }
+ }
+
+ /* init payload */
+ FDKmemclear(hAacEncoder->extPayload, sizeof(AACENC_EXT_PAYLOAD) * MAX_TOTAL_EXT_PAYLOADS);
+ for (i = 0; i < MAX_TOTAL_EXT_PAYLOADS; i++) {
+ hAacEncoder->extPayload[i].associatedChElement = -1;
+ }
+ FDKmemclear(hAacEncoder->extPayloadData, sizeof(hAacEncoder->extPayloadData));
+ FDKmemclear(hAacEncoder->extPayloadSize, sizeof(hAacEncoder->extPayloadSize));
+
+
+ /*
+ * Calculate Meta Data info.
+ */
+ if ( (hAacEncoder->hMetadataEnc!=NULL) && (hAacEncoder->metaDataAllowed!=0) ) {
+
+ const AACENC_MetaData *pMetaData = NULL;
+ AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL;
+ UINT nMetaDataExtensions = 0;
+ INT matrix_mixdown_idx = 0;
+
+ /* New meta data info available ? */
+ if ( getBufDescIdx(inBufDesc,IN_METADATA_SETUP) != -1 ) {
+ pMetaData = (AACENC_MetaData*)inBufDesc->bufs[getBufDescIdx(inBufDesc,IN_METADATA_SETUP)];
+ }
+
+ FDK_MetadataEnc_Process(hAacEncoder->hMetadataEnc,
+ hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset,
+ hAacEncoder->nSamplesRead,
+ pMetaData,
+ &pMetaDataExtPayload,
+ &nMetaDataExtensions,
+ &matrix_mixdown_idx
+ );
+
+ for (i=0; i<(INT)nMetaDataExtensions; i++) { /* Get meta data extension payload. */
+ hAacEncoder->extPayload[nExtensions++] = pMetaDataExtPayload[i];
+ }
+ if (matrix_mixdown_idx!=-1) { /* Set matrix mixdown coefficient. */
+ UINT pceValue = (UINT)( (1<<3) | ((matrix_mixdown_idx&0x2)<<1) | 1 );
+ if (hAacEncoder->extParam.userPceAdditions != pceValue) {
+ hAacEncoder->extParam.userPceAdditions = pceValue;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ }
+ }
+
+
+ if ( isSbrActive(&hAacEncoder->aacConfig) ) {
+
+ INT nPayload = 0;
+
+ /*
+ * Encode SBR data.
+ */
+ if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc,
+ hAacEncoder->inputBuffer,
+ hAacEncoder->extParam.nChannels,
+ hAacEncoder->extPayloadSize[nPayload],
+ hAacEncoder->extPayloadData[nPayload]
+#if defined(EVAL_PACKAGE_SILENCE) || defined(EVAL_PACKAGE_SBR_SILENCE)
+ ,hAacEncoder->hAacEnc->clearOutput
+#endif
+ ))
+ {
+ err = AACENC_ENCODE_ERROR;
+ goto bail;
+ }
+ else {
+ /* Add SBR extension payload */
+ for (i = 0; i < (6); i++) {
+ if (hAacEncoder->extPayloadSize[nPayload][i] > 0) {
+ hAacEncoder->extPayload[nExtensions].pData = hAacEncoder->extPayloadData[nPayload][i];
+ {
+ hAacEncoder->extPayload[nExtensions].dataSize = hAacEncoder->extPayloadSize[nPayload][i];
+ hAacEncoder->extPayload[nExtensions].associatedChElement = i;
+ }
+ hAacEncoder->extPayload[nExtensions].dataType = EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set EXT_SBR_DATA_CRC */
+ nExtensions++; /* or EXT_SBR_DATA according to configuration. */
+ FDK_ASSERT(nExtensions<=MAX_TOTAL_EXT_PAYLOADS);
+ }
+ }
+ nPayload++;
+ }
+ } /* sbrEnabled */
+
+ if ( (inargs->numAncBytes > 0) && ( getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA)!=-1 ) ) {
+ INT idx = getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA);
+ hAacEncoder->extPayload[nExtensions].dataSize = inargs->numAncBytes * 8;
+ hAacEncoder->extPayload[nExtensions].pData = (UCHAR*)inBufDesc->bufs[idx];
+ hAacEncoder->extPayload[nExtensions].dataType = EXT_DATA_ELEMENT;
+ hAacEncoder->extPayload[nExtensions].associatedChElement = -1;
+ ancDataExtIdx = nExtensions; /* store index */
+ nExtensions++;
+ }
+
+ /*
+ * Encode AAC - Core.
+ */
+ if ( FDKaacEnc_EncodeFrame( hAacEncoder->hAacEnc,
+ hAacEncoder->hTpEnc,
+ hAacEncoder->inputBuffer,
+ outBytes,
+ hAacEncoder->extPayload
+ ) != AAC_ENC_OK )
+ {
+ err = AACENC_ENCODE_ERROR;
+ goto bail;
+ }
+
+ if (ancDataExtIdx >= 0) {
+ outargs->numAncBytes = inargs->numAncBytes - (hAacEncoder->extPayload[ancDataExtIdx].dataSize>>3);
+ }
+
+ /* samples exhausted */
+ hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead;
+
+ /*
+ * Delay balancing buffer handling
+ */
+ if (isSbrActive(&hAacEncoder->aacConfig)) {
+ sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer);
+ }
+
+ /*
+ * Make bitstream public
+ */
+ if (outBufDesc->numBufs>=1) {
+
+ INT bsIdx = getBufDescIdx(outBufDesc,OUT_BITSTREAM_DATA);
+ INT auIdx = getBufDescIdx(outBufDesc,OUT_AU_SIZES);
+
+ for (i=0,nBsBytes=0; i<hAacEncoder->aacConfig.nSubFrames; i++) {
+ nBsBytes += outBytes[i];
+
+ if (auIdx!=-1) {
+ ((INT*)outBufDesc->bufs[auIdx])[i] = outBytes[i];
+ }
+ }
+
+ if ( (bsIdx!=-1) && (outBufDesc->bufSizes[bsIdx]>=nBsBytes) ) {
+ FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, sizeof(UCHAR)*nBsBytes);
+ outargs->numOutBytes = nBsBytes;
+ }
+ else {
+ /* output buffer too small, can't write valid bitstream */
+ err = AACENC_ENCODE_ERROR;
+ goto bail;
+ }
+ }
+
+bail:
+ if (err == AACENC_ENCODE_ERROR) {
+ /* All encoder modules have to be initialized */
+ hAacEncoder->InitFlags = AACENC_INIT_ALL;
+ }
+
+ return err;
+}
+
+static
+AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder,
+ UINT *size,
+ UCHAR *confBuffer)
+{
+ FDK_BITSTREAM tmpConf;
+ UINT confType;
+ UCHAR buf[64];
+ int err;
+
+ /* Init bit buffer */
+ FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER);
+
+ /* write conf in tmp buffer */
+ err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, &tmpConf, &confType);
+
+ /* copy data to outbuffer: length in bytes */
+ FDKbyteAlign(&tmpConf, 0);
+
+ /* Check buffer size */
+ if (FDKgetValidBits(&tmpConf) > ((*size)<<3))
+ return AAC_ENC_UNKNOWN;
+
+ FDKfetchBuffer(&tmpConf, confBuffer, size);
+
+ if (err != 0)
+ return AAC_ENC_UNKNOWN;
+ else
+ return AAC_ENC_OK;
+}
+
+
+AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info)
+{
+ int i = 0;
+
+ if (info == NULL) {
+ return AACENC_INVALID_HANDLE;
+ }
+
+ FDK_toolsGetLibInfo( info );
+ transportEnc_GetLibInfo( info );
+
+ sbrEncoder_GetLibInfo( info );
+
+ /* search for next free tab */
+ for (i = 0; i < FDK_MODULE_LAST; i++) {
+ if (info[i].module_id == FDK_NONE) break;
+ }
+ if (i == FDK_MODULE_LAST) {
+ return AACENC_INIT_ERROR;
+ }
+
+ info[i].module_id = FDK_AACENC;
+ info[i].build_date = (char*)AACENCODER_LIB_BUILD_DATE;
+ info[i].build_time = (char*)AACENCODER_LIB_BUILD_TIME;
+ info[i].title = (char*)AACENCODER_LIB_TITLE;
+ info[i].version = LIB_VERSION(AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2);;
+ LIB_VERSION_STRING(&info[i]);
+
+ /* Capability flags */
+ info[i].flags = 0
+ | CAPF_AAC_1024 | CAPF_AAC_LC
+ | CAPF_AAC_512
+ | CAPF_AAC_480
+ | CAPF_AAC_DRC
+ ;
+ /* End of flags */
+
+ return AACENC_OK;
+}
+
+AACENC_ERROR aacEncoder_SetParam(
+ const HANDLE_AACENCODER hAacEncoder,
+ const AACENC_PARAM param,
+ const UINT value
+ )
+{
+ AACENC_ERROR err = AACENC_OK;
+ USER_PARAM *settings = &hAacEncoder->extParam;
+
+ /* check encoder handle */
+ if (hAacEncoder == NULL) {
+ err = AACENC_INVALID_HANDLE;
+ goto bail;
+ }
+
+ /* apply param value */
+ switch (param)
+ {
+ case AACENC_AOT:
+ if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) {
+ /* check if AOT matches the allocated modules */
+ switch ( value ) {
+ case AOT_PS:
+ case AOT_MP2_PS:
+ if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) {
+ err = AACENC_INVALID_CONFIG;
+ goto bail;
+ }
+ case AOT_SBR:
+ case AOT_MP2_SBR:
+ if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) {
+ err = AACENC_INVALID_CONFIG;
+ goto bail;
+ }
+ case AOT_AAC_LC:
+ case AOT_MP2_AAC_LC:
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LD:
+ case AOT_ER_AAC_ELD:
+ if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) {
+ err = AACENC_INVALID_CONFIG;
+ goto bail;
+ }
+ break;
+ default:
+ err = AACENC_INVALID_CONFIG;
+ goto bail;
+ }/* switch value */
+ settings->userAOT = (AUDIO_OBJECT_TYPE)value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_BITRATE:
+ if (settings->userBitrate != value) {
+ settings->userBitrate = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_BITRATEMODE:
+ if (settings->userBitrateMode != value) {
+ switch ( value ) {
+ case 0:
+ case 8:
+ settings->userBitrateMode = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
+ break;
+ default:
+ err = AACENC_INVALID_CONFIG;
+ break;
+ } /* switch value */
+ }
+ break;
+ case AACENC_SAMPLERATE:
+ if (settings->userSamplerate != value) {
+ if ( !( (value==8000) || (value==11025) || (value==12000) || (value==16000) || (value==22050) || (value==24000) ||
+ (value==32000) || (value==44100) || (value==48000) || (value==64000) || (value==88200) || (value==96000) ) )
+ {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userSamplerate = value;
+ hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_CHANNELMODE:
+ if (settings->userChannelMode != (CHANNEL_MODE)value) {
+ const CHANNEL_MODE_CONFIG_TAB* pConfig = FDKaacEnc_GetChannelModeConfiguration((CHANNEL_MODE)value);
+ if (pConfig==NULL) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ if ( (pConfig->nElements > hAacEncoder->nMaxAacElements)
+ || (pConfig->nChannelsEff > hAacEncoder->nMaxAacChannels)
+ || !((value>=1) && (value<=6))
+ )
+ {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+
+ settings->userChannelMode = (CHANNEL_MODE)value;
+ settings->nChannels = pConfig->nChannels;
+ hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_BANDWIDTH:
+ if (settings->userBandwidth != value) {
+ settings->userBandwidth = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
+ }
+ break;
+ case AACENC_CHANNELORDER:
+ if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) {
+ if (! ((value==0) || (value==1)) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ hAacEncoder->aacConfig.channelOrder = (CHANNEL_ORDER)value;
+ hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_AFTERBURNER:
+ if (settings->userAfterburner != value) {
+ if (! ((value==0) || (value==1)) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userAfterburner = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
+ }
+ break;
+ case AACENC_GRANULE_LENGTH:
+ if (settings->userFramelength != value) {
+ switch (value) {
+ case 1024:
+ case 512:
+ case 480:
+ settings->userFramelength = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
+ break;
+ default:
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ }
+ break;
+ case AACENC_SBR_MODE:
+ if (settings->userSbrEnabled != value) {
+ settings->userSbrEnabled = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_TRANSMUX:
+ if (settings->userTpType != (TRANSPORT_TYPE)value) {
+
+ TRANSPORT_TYPE type = (TRANSPORT_TYPE)value;
+ UINT flags = hAacEncoder->CAPF_tpEnc;
+
+ if ( !( ((type==TT_MP4_ADIF) && (flags&CAPF_ADIF))
+ || ((type==TT_MP4_ADTS) && (flags&CAPF_ADTS))
+ || ((type==TT_MP4_LATM_MCP0) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS)))
+ || ((type==TT_MP4_LATM_MCP1) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS)))
+ || ((type==TT_MP4_LOAS) && (flags&CAPF_LOAS))
+ || ((type==TT_MP4_RAW) && (flags&CAPF_RAWPACKETS))
+ ) )
+ {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userTpType = (TRANSPORT_TYPE)value;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_SIGNALING_MODE:
+ if (settings->userTpSignaling != value) {
+ if ( !((value==0) || (value==1) || (value==2)) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userTpSignaling = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_PROTECTION:
+ if (settings->userTpProtection != value) {
+ if ( !((value==0) || (value==1)) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userTpProtection = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_HEADER_PERIOD:
+ if (settings->userTpHeaderPeriod != value) {
+ settings->userTpHeaderPeriod = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_TPSUBFRAMES:
+ if (settings->userTpNsubFrames != value) {
+ if (! ( (value>=1) && (value<=4) ) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userTpNsubFrames = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
+ }
+ break;
+ case AACENC_ANCILLARY_BITRATE:
+ if (settings->userAncDataRate != value) {
+ settings->userAncDataRate = value;
+ }
+ break;
+ case AACENC_CONTROL_STATE:
+ if (hAacEncoder->InitFlags != value) {
+ if (value&AACENC_RESET_INBUFFER) {
+ hAacEncoder->nSamplesRead = 0;
+ }
+ hAacEncoder->InitFlags = value;
+ }
+ break;
+ case AACENC_METADATA_MODE:
+ if ((UINT)settings->userMetaDataMode != value) {
+ if ( !((value>=0) && (value<=2)) ) {
+ err = AACENC_INVALID_CONFIG;
+ break;
+ }
+ settings->userMetaDataMode = value;
+ hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
+ }
+ break;
+ default:
+ err = AACENC_UNSUPPORTED_PARAMETER;
+ break;
+ } /* switch(param) */
+
+bail:
+ return err;
+}
+
+UINT aacEncoder_GetParam(
+ const HANDLE_AACENCODER hAacEncoder,
+ const AACENC_PARAM param
+ )
+{
+ UINT value = 0;
+ USER_PARAM *settings = &hAacEncoder->extParam;
+
+ /* check encoder handle */
+ if (hAacEncoder == NULL) {
+ goto bail;
+ }
+
+ /* apply param value */
+ switch (param)
+ {
+ case AACENC_AOT:
+ value = (UINT)hAacEncoder->aacConfig.audioObjectType;
+ break;
+ case AACENC_BITRATE:
+ value = (UINT)((hAacEncoder->aacConfig.bitrateMode==AACENC_BR_MODE_CBR) ? hAacEncoder->aacConfig.bitRate : -1);
+ break;
+ case AACENC_BITRATEMODE:
+ value = (UINT)hAacEncoder->aacConfig.bitrateMode;
+ break;
+ case AACENC_SAMPLERATE:
+ value = (UINT)settings->userSamplerate;
+ break;
+ case AACENC_CHANNELMODE:
+ value = (UINT)hAacEncoder->aacConfig.channelMode;
+ break;
+ case AACENC_BANDWIDTH:
+ value = (UINT)hAacEncoder->aacConfig.bandWidth;
+ break;
+ case AACENC_CHANNELORDER:
+ value = (UINT)hAacEncoder->aacConfig.channelOrder;
+ break;
+ case AACENC_AFTERBURNER:
+ value = (UINT)hAacEncoder->aacConfig.useRequant;
+ break;
+ case AACENC_GRANULE_LENGTH:
+ value = (UINT)hAacEncoder->aacConfig.framelength;
+ break;
+ case AACENC_SBR_MODE:
+ value = (UINT) (hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0;
+ break;
+ case AACENC_TRANSMUX:
+ value = (UINT)settings->userTpType;
+ break;
+ case AACENC_SIGNALING_MODE:
+ value = (UINT)settings->userTpSignaling;
+ break;
+ case AACENC_PROTECTION:
+ value = (UINT)settings->userTpProtection;
+ break;
+ case AACENC_HEADER_PERIOD:
+ value = (UINT)hAacEncoder->coderConfig.headerPeriod;
+ break;
+ case AACENC_TPSUBFRAMES:
+ value = (UINT)settings->userTpNsubFrames;
+ break;
+ case AACENC_ANCILLARY_BITRATE:
+ value = (UINT)hAacEncoder->aacConfig.anc_Rate;
+ break;
+ case AACENC_CONTROL_STATE:
+ value = (UINT)hAacEncoder->InitFlags;
+ break;
+ case AACENC_METADATA_MODE:
+ value = (hAacEncoder->metaDataAllowed==0) ? 0 : (UINT)settings->userMetaDataMode;
+ break;
+ default:
+ //err = MPS_INVALID_PARAMETER;
+ break;
+ } /* switch(param) */
+
+bail:
+ return value;
+}
+
+AACENC_ERROR aacEncInfo(
+ const HANDLE_AACENCODER hAacEncoder,
+ AACENC_InfoStruct *pInfo
+ )
+{
+ AACENC_ERROR err = AACENC_OK;
+
+ FDKmemclear(pInfo, sizeof(AACENC_InfoStruct));
+ pInfo->confSize = 64; /* pre-initialize */
+
+ pInfo->maxOutBufBytes = ((hAacEncoder->nMaxAacChannels*6144)+7)>>3;
+ pInfo->maxAncBytes = hAacEncoder->aacConfig.maxAncBytesPerAU;
+ pInfo->inBufFillLevel = hAacEncoder->nSamplesRead/hAacEncoder->extParam.nChannels;
+ pInfo->inputChannels = hAacEncoder->extParam.nChannels;
+ pInfo->frameLength = hAacEncoder->nSamplesToRead/hAacEncoder->extParam.nChannels;
+ pInfo->encoderDelay = hAacEncoder->nDelay/hAacEncoder->extParam.nChannels;
+
+ /* Get encoder configuration */
+ if ( aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != AAC_ENC_OK) {
+ err = AACENC_INIT_ERROR;
+ goto bail;
+ }
+bail:
+ return err;
+}
+