| |
| /* ----------------------------------------------------------------------------------------------------------- |
| 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 3 |
| #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; |
| } |
| |