diff options
Diffstat (limited to 'libAACenc/src/aacenc_lib.cpp')
-rw-r--r-- | libAACenc/src/aacenc_lib.cpp | 3473 |
1 files changed, 1918 insertions, 1555 deletions
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index 64445b9..11db3da 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© Copyright 1995 - 2018 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,14 +90,15 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/**************************** MPEG-4 HE-AAC Encoder ************************* +/**************************** AAC encoder library ****************************** - Initial author: M. Lohwasser - contents/description: FDK HE-AAC Encoder interface library functions + Author(s): M. Lohwasser -****************************************************************************/ + Description: FDK HE-AAC Encoder interface library functions + +*******************************************************************************/ #include "aacenc_lib.h" #include "FDK_audio.h" @@ -96,9 +108,9 @@ amm-info@iis.fraunhofer.de #include "FDK_core.h" /* FDK_tools versioning info */ /* Encoder library info */ -#define AACENCODER_LIB_VL0 3 -#define AACENCODER_LIB_VL1 4 -#define AACENCODER_LIB_VL2 22 +#define AACENCODER_LIB_VL0 4 +#define AACENCODER_LIB_VL1 0 +#define AACENCODER_LIB_VL2 0 #define AACENCODER_LIB_TITLE "AAC Encoder" #ifdef __ANDROID__ #define AACENCODER_LIB_BUILD_DATE "" @@ -108,9 +120,10 @@ amm-info@iis.fraunhofer.de #define AACENCODER_LIB_BUILD_TIME __TIME__ #endif +#include "pcm_utils.h" #include "sbr_encoder.h" -#include "../src/sbr_ram.h" +#include "../src/sbrenc_ram.h" #include "channel_map.h" #include "psy_const.h" @@ -119,260 +132,297 @@ amm-info@iis.fraunhofer.de #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)/2) /*!< ELD FB delay (no framing delay included) */ - -#define INPUTBUFFER_SIZE (1537+100+2048) - -#define DEFAULT_HEADER_PERIOD_REPETITION_RATE 10 /*!< Default header repetition rate used in transport library and for SBR header. */ +#include "mps_main.h" +#include "sacenc_lib.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_AACLD(fl) (fl) /*!< MDCT delay (no framing delay included) */ +#define DELAY_AACELD(fl) \ + ((fl) / 2) /*!< ELD FB delay (no framing delay included) */ + +#define MAX_DS_DELAY (100) /*!< Maximum downsampler delay in SBR. */ +#define INPUTBUFFER_SIZE \ + (2 * (1024) + MAX_DS_DELAY + 1537) /*!< Audio input samples + downsampler \ + delay + sbr/aac delay compensation */ + +#define DEFAULT_HEADER_PERIOD_REPETITION_RATE \ + 10 /*!< Default header repetition rate used in transport library and for SBR \ + header. */ //////////////////////////////////////////////////////////////////////////////////// /** * 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 + 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; - UINT userPeakBitrate; - - 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; /*!< Enable SBR for ELD. */ - UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */ + 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; + UINT userPeakBitrate; + + 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; /*!< Enable SBR for ELD. */ + UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */ + + UINT userDownscaleFactor; } USER_PARAM; +/** + * SBR extenxion payload struct provides buffers to be filled in SBR encoder + * library. + */ +typedef struct { + UCHAR data[(1)][(8)][MAX_PAYLOAD_SIZE]; /*!< extension payload data buffer */ + UINT dataSize[(1)][(8)]; /*!< extension payload data size in bits */ +} SBRENC_EXT_PAYLOAD; + //////////////////////////////////////////////////////////////////////////////////// /**************************************************************************** Structure Definitions ****************************************************************************/ -typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG; +typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG; +struct AACENCODER { + USER_PARAM extParam; + CODER_CONFIG coderConfig; -struct AACENCODER -{ - USER_PARAM extParam; - CODER_CONFIG coderConfig; - - /* AAC */ - AACENC_CONFIG aacConfig; - HANDLE_AAC_ENC hAacEnc; - - /* SBR */ - HANDLE_SBR_ENCODER hEnvEnc; + /* AAC */ + AACENC_CONFIG aacConfig; + HANDLE_AAC_ENC hAacEnc; - /* 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. */ + /* SBR */ + HANDLE_SBR_ENCODER hEnvEnc; /* SBR encoder */ + SBRENC_EXT_PAYLOAD *pSbrPayload; /* SBR extension payload */ - /* Transport */ - HANDLE_TRANSPORTENC hTpEnc; + /* 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. */ - /* Output */ - UCHAR *outBuffer; /* Internal bitstream buffer */ - INT outBufferInBytes; /* Size of internal bitstream buffer*/ + HANDLE_MPS_ENCODER hMpsEnc; - /* Input */ - INT_PCM *inputBuffer; /* Internal input buffer. Input source for AAC encoder */ - INT inputBufferOffset; /* Where to write new input samples. */ + /* Transport */ + HANDLE_TRANSPORTENC hTpEnc; - 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 */ + INT_PCM + *inputBuffer; /* Internal input buffer. Input source for AAC encoder */ + UCHAR *outBuffer; /* Internal bitstream buffer */ - AACENC_EXT_PAYLOAD extPayload [MAX_TOTAL_EXT_PAYLOADS]; - /* Extension payload */ - UCHAR extPayloadData [(1)][(8)][MAX_PAYLOAD_SIZE]; - UINT extPayloadSize [(1)][(8)]; /* payload sizes in bits */ + INT inputBufferSize; /* Size of internal input buffer */ + INT inputBufferSizePerChannel; /* Size of internal input buffer per channel */ + INT outBufferInBytes; /* Size of internal bitstream buffer*/ - ULONG InitFlags; /* internal status to treggier re-initialization */ + 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; /* codec delay */ + INT nDelayCore; /* codec delay, w/o the SBR decoder delay */ - /* Memory allocation info. */ - INT nMaxAacElements; - INT nMaxAacChannels; - INT nMaxSbrElements; - INT nMaxSbrChannels; - UINT nMaxSubFrames; + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]; - UINT encoder_modis; + ULONG InitFlags; /* internal status to treggier re-initialization */ - /* Capability flags */ - UINT CAPF_tpEnc; + /* Memory allocation info. */ + INT nMaxAacElements; + INT nMaxAacChannels; + INT nMaxSbrElements; + INT nMaxSbrChannels; -} ; + UINT encoder_modis; -typedef struct -{ - ULONG samplingRate; /*!< Encoder output sampling rate. */ - ULONG bitrateRange; /*!< Lower bitrate range for config entry. */ + /* Capability flags */ + UINT CAPF_tpEnc; +}; - UCHAR lowDelaySbr; /*!< 0: ELD sbr off, - 1: ELD sbr on */ +typedef struct { + /* input */ + ULONG nChannels; /*!< Number of audio channels. */ + ULONG samplingRate; /*!< Encoder output sampling rate. */ + ULONG bitrateRange; /*!< Lower bitrate range for config entry. */ - UCHAR downsampledSbr; /*!< 0: ELD with dualrate sbr, - 1: ELD with downsampled sbr */ + /* output*/ + UCHAR sbrMode; /*!< 0: ELD sbr off, + 1: ELD with downsampled sbr, + 2: ELD with dualrate sbr. */ + CHANNEL_MODE chMode; /*!< Channel mode. */ } ELD_SBR_CONFIGURATOR; /** * \brief This table defines ELD/SBR default configurations. */ -static const ELD_SBR_CONFIGURATOR eldSbrAutoConfigTab[] = -{ - { 48000, 0, 1, 0 }, - { 48000, 64001, 0, 0 }, +static const ELD_SBR_CONFIGURATOR eldSbrAutoConfigTab[] = { + {1, 48000, 0, 2, MODE_1}, {1, 48000, 64000, 0, MODE_1}, + + {1, 44100, 0, 2, MODE_1}, {1, 44100, 64000, 0, MODE_1}, + + {1, 32000, 0, 2, MODE_1}, {1, 32000, 28000, 1, MODE_1}, + {1, 32000, 56000, 0, MODE_1}, - { 44100, 0, 1, 0 }, - { 44100, 64001, 0, 0 }, + {1, 24000, 0, 1, MODE_1}, {1, 24000, 40000, 0, MODE_1}, - { 32000, 0, 1, 0 }, - { 32000, 28000, 1, 1 }, - { 32000, 56000, 0, 0 }, + {1, 16000, 0, 1, MODE_1}, {1, 16000, 28000, 0, MODE_1}, - { 24000, 0, 1, 1 }, - { 24000, 40000, 0, 0 }, + {1, 15999, 0, 0, MODE_1}, - { 16000, 0, 1, 1 }, - { 16000, 28000, 0, 0 } + {2, 48000, 0, 2, MODE_2}, {2, 48000, 44000, 2, MODE_2}, + {2, 48000, 128000, 0, MODE_2}, + + {2, 44100, 0, 2, MODE_2}, {2, 44100, 44000, 2, MODE_2}, + {2, 44100, 128000, 0, MODE_2}, + + {2, 32000, 0, 2, MODE_2}, {2, 32000, 32000, 2, MODE_2}, + {2, 32000, 68000, 1, MODE_2}, {2, 32000, 96000, 0, MODE_2}, + + {2, 24000, 0, 1, MODE_2}, {2, 24000, 48000, 1, MODE_2}, + {2, 24000, 80000, 0, MODE_2}, + + {2, 16000, 0, 1, MODE_2}, {2, 16000, 32000, 1, MODE_2}, + {2, 16000, 64000, 0, MODE_2}, + + {2, 15999, 0, 0, MODE_2} }; /* * \brief Configure SBR for ELD configuration. * - * This function finds default SBR configuration for ELD based on sampling rate and channel bitrate. - * Outputparameters are SBR on/off, and SBR ratio. + * This function finds default SBR configuration for ELD based on number of + * channels, sampling rate and bitrate. * + * \param nChannels Number of audio channels. * \param samplingRate Audio signal sampling rate. - * \param channelMode Channel configuration to be used. - * \param totalBitrate Overall bitrate. - * \param eldSbr Pointer to eldSbr parameter, filled on return. - * \param eldSbrRatio Pointer to eldSbrRatio parameter, filled on return. + * \param bitrate Encoder bitrate. * - * \return - AACENC_OK, all fine. - * - AACENC_INVALID_CONFIG, on failure. + * \return - pointer to eld sbr configuration. + * - NULL, on failure. */ -static AACENC_ERROR eldSbrConfigurator( - const ULONG samplingRate, - const CHANNEL_MODE channelMode, - const ULONG totalBitrate, - UINT * const eldSbr, - UINT * const eldSbrRatio - ) -{ - AACENC_ERROR err = AACENC_OK; - int i, cfgIdx = -1; - const ULONG channelBitrate = totalBitrate / FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; - - for (i=0; i<(int)(sizeof(eldSbrAutoConfigTab)/sizeof(ELD_SBR_CONFIGURATOR)); i++) { - if ( (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) - && (channelBitrate >= eldSbrAutoConfigTab[i].bitrateRange) ) - { - cfgIdx = i; - } - } - - if (cfgIdx != -1) { - *eldSbr = (eldSbrAutoConfigTab[cfgIdx].lowDelaySbr==0) ? 0 : 1; - *eldSbrRatio = (eldSbrAutoConfigTab[cfgIdx].downsampledSbr==0) ? 2 : 1; - } - else { - err = AACENC_INVALID_CONFIG; /* no default configuration for eld-sbr available. */ +static const ELD_SBR_CONFIGURATOR *eldSbrConfigurator(const ULONG nChannels, + const ULONG samplingRate, + const ULONG bitrate) { + int i; + const ELD_SBR_CONFIGURATOR *pSetup = NULL; + + for (i = 0; + i < (int)(sizeof(eldSbrAutoConfigTab) / sizeof(ELD_SBR_CONFIGURATOR)); + i++) { + if ((nChannels == eldSbrAutoConfigTab[i].nChannels) && + (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) && + (bitrate >= eldSbrAutoConfigTab[i].bitrateRange)) { + pSetup = &eldSbrAutoConfigTab[i]; } + } - return err; + return pSetup; } -static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) -{ - INT sbrUsed = 0; +static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { + INT sbrUsed = 0; - if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS) ) - { - sbrUsed = 1; - } - if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && (hAacConfig->syntaxFlags & AC_SBR_PRESENT)) - { - sbrUsed = 1; - } + /* Note: Even if implicit signalling was selected, The AOT itself here is not + * AOT_AAC_LC */ + if ((hAacConfig->audioObjectType == AOT_SBR) || + (hAacConfig->audioObjectType == AOT_PS) || + (hAacConfig->audioObjectType == AOT_MP2_SBR)) { + sbrUsed = 1; + } + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && + (hAacConfig->syntaxFlags & AC_SBR_PRESENT)) { + sbrUsed = 1; + } - return ( sbrUsed ); + return (sbrUsed); } -static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) -{ - INT psUsed = 0; +static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) { + INT psUsed = 0; - if ( (audioObjectType==AOT_PS) ) - { - psUsed = 1; - } + if (audioObjectType == AOT_PS) { + psUsed = 1; + } - return ( psUsed ); + return (psUsed); +} + +static CHANNEL_MODE GetCoreChannelMode( + const CHANNEL_MODE channelMode, const AUDIO_OBJECT_TYPE audioObjectType) { + CHANNEL_MODE mappedChannelMode = channelMode; + if ((isPsActive(audioObjectType) && (channelMode == MODE_2)) || + (channelMode == MODE_212)) { + mappedChannelMode = MODE_1; + } + return mappedChannelMode; } static SBR_PS_SIGNALING getSbrSignalingMode( - const AUDIO_OBJECT_TYPE audioObjectType, - const TRANSPORT_TYPE transportType, - const UCHAR transportSignaling, - const UINT sbrRatio - ) + const AUDIO_OBJECT_TYPE audioObjectType, const TRANSPORT_TYPE transportType, + const UCHAR transportSignaling, const UINT sbrRatio) { SBR_PS_SIGNALING sbrSignaling; - if (transportType==TT_UNKNOWN || sbrRatio==0) { + if (transportType == TT_UNKNOWN || sbrRatio == 0) { sbrSignaling = SIG_UNKNOWN; /* Needed parameters have not been set */ return sbrSignaling; } else { - sbrSignaling = SIG_IMPLICIT; /* default: implicit signaling */ + sbrSignaling = + SIG_EXPLICIT_HIERARCHICAL; /* default: explicit hierarchical signaling + */ } - if ( (audioObjectType==AOT_AAC_LC) || (audioObjectType==AOT_SBR) || (audioObjectType==AOT_PS) ) { + if ((audioObjectType == AOT_AAC_LC) || (audioObjectType == AOT_SBR) || + (audioObjectType == AOT_PS) || (audioObjectType == AOT_MP2_AAC_LC) || + (audioObjectType == AOT_MP2_SBR)) { switch (transportType) { case TT_MP4_ADIF: case TT_MP4_ADTS: - sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only implicit signaling is possible */ + sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only + implicit signaling is possible */ break; case TT_MP4_RAW: @@ -380,16 +430,13 @@ static SBR_PS_SIGNALING getSbrSignalingMode( case TT_MP4_LATM_MCP0: case TT_MP4_LOAS: default: - if ( transportSignaling==0xFF ) { + if (transportSignaling == 0xFF) { /* Defaults */ - if ( sbrRatio==1 ) { - sbrSignaling = SIG_EXPLICIT_HIERARCHICAL; /* For downsampled SBR, explicit signaling is mandatory */ - } else { - sbrSignaling = SIG_IMPLICIT; /* For dual-rate SBR, implicit signaling is default */ - } + sbrSignaling = SIG_EXPLICIT_HIERARCHICAL; } else { /* User set parameters */ - /* Attention: Backward compatible explicit signaling does only work with AMV1 for LATM/LOAS */ + /* Attention: Backward compatible explicit signaling does only work + * with AMV1 for LATM/LOAS */ sbrSignaling = (SBR_PS_SIGNALING)transportSignaling; } break; @@ -403,78 +450,90 @@ static SBR_PS_SIGNALING getSbrSignalingMode( Allocate Encoder ****************************************************************************/ -H_ALLOC_MEM (_AacEncoder, AACENCODER) -C_ALLOC_MEM (_AacEncoder, AACENCODER, 1) - - - +H_ALLOC_MEM(_AacEncoder, AACENCODER) +C_ALLOC_MEM(_AacEncoder, struct AACENCODER, 1) /* * Map Encoder specific config structures to CODER_CONFIG. */ -static void FDKaacEnc_MapConfig( - CODER_CONFIG *const cc, - const USER_PARAM *const extCfg, - const SBR_PS_SIGNALING sbrSignaling, - const HANDLE_AACENC_CONFIG hAacConfig - ) -{ +static void FDKaacEnc_MapConfig(CODER_CONFIG *const cc, + const USER_PARAM *const extCfg, + const SBR_PS_SIGNALING sbrSignaling, + const HANDLE_AACENC_CONFIG hAacConfig) { AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT; FDKmemclear(cc, sizeof(CODER_CONFIG)); cc->flags = 0; - transport_AOT = hAacConfig->audioObjectType; + cc->samplesPerFrame = hAacConfig->framelength; + cc->samplingRate = hAacConfig->sampleRate; + cc->extSamplingRate = extCfg->userSamplerate; + + /* 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; + default: + transport_AOT = hAacConfig->audioObjectType; + } if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_LD_MPS) ? CC_SAC : 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; + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->aot = AOT_AAC_LC; + } else { + cc->aot = transport_AOT; } /* Configure extension aot. */ - if (sbrSignaling==SIG_IMPLICIT) { - cc->extAOT = AOT_NULL_OBJECT; /* implicit */ - } - else { - if ( (sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) { - cc->extAOT = AOT_SBR; /* explicit backward compatible */ - } - else { - cc->extAOT = transport_AOT; /* explicit hierarchical */ + if (sbrSignaling == SIG_IMPLICIT) { + cc->extAOT = AOT_NULL_OBJECT; /* implicit */ + } else { + if ((sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) && + ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS))) { + cc->extAOT = AOT_SBR; /* explicit backward compatible */ + } else { + cc->extAOT = transport_AOT; /* explicit hierarchical */ } } - if ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) { - cc->sbrPresent=1; - if (transport_AOT==AOT_PS) { - cc->psPresent=1; + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->sbrPresent = 1; + if (transport_AOT == AOT_PS) { + cc->psPresent = 1; } } - cc->sbrSignaling = sbrSignaling; + cc->sbrSignaling = sbrSignaling; - cc->extSamplingRate = extCfg->userSamplerate; - cc->bitRate = hAacConfig->bitRate; - cc->noChannels = hAacConfig->nChannels; - cc->flags |= CC_IS_BASELAYER; - cc->channelMode = hAacConfig->channelMode; + if (hAacConfig->downscaleFactor > 1) { + cc->downscaleSamplingRate = cc->samplingRate; + cc->samplingRate *= hAacConfig->downscaleFactor; + cc->extSamplingRate *= hAacConfig->downscaleFactor; + } + + 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; + ? hAacConfig->nSubFrames + : extCfg->userTpNsubFrames; - cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; + cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; - if (extCfg->userTpHeaderPeriod!=0xFF) { - cc->headerPeriod = extCfg->userTpHeaderPeriod; - } - else { /* auto-mode */ + if (extCfg->userTpHeaderPeriod != 0xFF) { + cc->headerPeriod = extCfg->userTpHeaderPeriod; + } else { /* auto-mode */ switch (extCfg->userTpType) { case TT_MP4_ADTS: case TT_MP4_LOAS: @@ -486,27 +545,65 @@ static void FDKaacEnc_MapConfig( } } - cc->samplesPerFrame = hAacConfig->framelength; - cc->samplingRate = hAacConfig->sampleRate; - /* Mpeg-4 signaling for transport library. */ - cc->flags |= CC_MPEG_ID; + switch (hAacConfig->audioObjectType) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */ + 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; + 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 { + 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; } + + cc->channelConfigZero = 0; +} + +/* + * Validate prefilled pointers within buffer descriptor. + * + * \param pBufDesc Pointer to buffer descriptor + + * \return - AACENC_OK, all fine. + * - AACENC_INVALID_HANDLE, on missing pointer initializiation. + * - AACENC_UNSUPPORTED_PARAMETER, on incorrect buffer descriptor + initialization. + */ +static AACENC_ERROR validateBufDesc(const AACENC_BufDesc *pBufDesc) { + AACENC_ERROR err = AACENC_OK; + + if (pBufDesc != NULL) { + int i; + if ((pBufDesc->bufferIdentifiers == NULL) || (pBufDesc->bufSizes == NULL) || + (pBufDesc->bufElSizes == NULL) || (pBufDesc->bufs == NULL)) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + for (i = 0; i < pBufDesc->numBufs; i++) { + if (pBufDesc->bufs[i] == NULL) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + } + } else { + err = AACENC_INVALID_HANDLE; + } +bail: + return err; } /* @@ -518,195 +615,172 @@ static void FDKaacEnc_MapConfig( * \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 ) { +static INT getBufDescIdx(const AACENC_BufDesc *pBufDesc, + const AACENC_BufferIdentifier identifier) { + INT i, idx = -1; + + if (pBufDesc != NULL) { + for (i = 0; i < pBufDesc->numBufs; i++) { + if ((AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == + identifier) { idx = i; break; } } - return idx; + } + return idx; } - /**************************************************************************** Function Declarations ****************************************************************************/ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, - USER_PARAM *config) -{ - /* make reasonable default settings */ - FDKaacEnc_AacInitDefaultConfig (hAacConfig); - - /* clear configuration 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->userPeakBitrate = (UINT)-1; - 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 = 0xFF; /* choose signaling automatically */ - 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; - - /* SBR rate is set to 0 here, which means it should be set automatically - in FDKaacEnc_AdjustEncSettings() if the user did not set a rate - expilicitely. */ - config->userSbrRatio = 0; - - /* SBR enable set to -1 means to inquire ELD audio configurator for reasonable configuration. */ - config->userSbrEnabled = -1; - - return AAC_ENC_OK; + USER_PARAM *config) { + /* make reasonable default settings */ + FDKaacEnc_AacInitDefaultConfig(hAacConfig); + + /* clear configuration 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->userPeakBitrate = (UINT)-1; + config->userBandwidth = hAacConfig->bandWidth; + config->userTns = hAacConfig->useTns; + config->userPns = hAacConfig->usePns; + config->userIntensity = hAacConfig->useIS; + config->userAfterburner = hAacConfig->useRequant; + config->userFramelength = (UINT)-1; + + config->userDownscaleFactor = 1; + + /* initialize transport parameters */ + config->userTpType = TT_UNKNOWN; + config->userTpAmxv = 0; + config->userTpSignaling = 0xFF; /* choose signaling automatically */ + 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; + + /* SBR rate is set to 0 here, which means it should be set automatically + in FDKaacEnc_AdjustEncSettings() if the user did not set a rate + expilicitely. */ + config->userSbrRatio = 0; + + /* SBR enable set to -1 means to inquire ELD audio configurator for reasonable + * configuration. */ + config->userSbrEnabled = (UCHAR)-1; + + return AAC_ENC_OK; } -static -void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, SBR_ELEMENT_INFO *sbrElInfo, INT bitRate) -{ +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; + 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 = + fMultIfloor(channelMapping->elInfo[el].relativeBits, bitRate); + sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag; + sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl; + sbrElInfo[el].fParametricStereo = 0; + sbrElInfo[el].fDualMono = 0; + + 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 INT sbrDownSampleRate, - const AUDIO_OBJECT_TYPE aot - ) -{ +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 INT sbrDownSampleRate, + const UINT syntaxFlags, + const AUDIO_OBJECT_TYPE aot) { INT coreSamplingRate; CHANNEL_MAPPING cm; FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm); if (sbrActive) { - coreSamplingRate = samplingRate >> (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate-1):1); + coreSamplingRate = + samplingRate >> + (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate - 1) : 1); } 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 - ); + bitRate = FDKaacEnc_LimitBitrate(hTpEnc, aot, coreSamplingRate, frameLength, + nChannels, cm.nChannelsEff, bitRate, -1, + NULL, AACENC_BR_MODE_INVALID, nSubFrames); /* Limit bit rate in respect to available SBR modes if active */ - if (sbrActive) - { + if (sbrActive) { int numIterations = 0; INT initialBitrate, adjustedBitrate; - initialBitrate = adjustedBitrate = bitRate; + adjustedBitrate = bitRate; - /* Find total bitrate which provides valid configuration for each SBR element. */ + /* Find total bitrate which provides valid configuration for each SBR + * element. */ do { int e; - SBR_ELEMENT_INFO sbrElInfo[(8)]; - FDK_ASSERT(cm.nElements <= (8)); + SBR_ELEMENT_INFO sbrElInfo[((8))]; + FDK_ASSERT(cm.nElements <= ((8))); initialBitrate = adjustedBitrate; /* Get bit rate for each SBR element */ aacEncDistributeSbrBits(&cm, sbrElInfo, initialBitrate); - for (e=0; e<cm.nElements; e++) - { + 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); + + sbrBitRateOut = sbrEncoder_LimitBitRate(sbrElementBitRateIn, + cm.elInfo[e].nChannelsInEl, + coreSamplingRate, aot); + if (sbrBitRateOut == 0) { return 0; } - /* If bitrates don't match, distribution and limiting needs to be determined again. - Abort element loop and restart with adapted bitrate. */ + /* If bitrates don't match, distribution and limiting needs to be + determined again. Abort element loop and restart with adapted + bitrate. */ if (sbrElementBitRateIn != sbrBitRateOut) { - if (sbrElementBitRateIn < sbrBitRateOut) { - adjustedBitrate = fMax(initialBitrate, (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut+8), cm.elInfo[e].relativeBits)); + adjustedBitrate = fMax(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut + 8), + cm.elInfo[e].relativeBits)); break; } if (sbrElementBitRateIn > sbrBitRateOut) { - adjustedBitrate = fMin(initialBitrate, (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut-8), cm.elInfo[e].relativeBits)); + adjustedBitrate = fMin(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut - 8), + cm.elInfo[e].relativeBits)); break; } @@ -716,289 +790,422 @@ INT aacEncoder_LimitBitrate( numIterations++; /* restrict iteration to worst case of num elements */ - } while ( (initialBitrate!=adjustedBitrate) && (numIterations<=cm.nElements) ); + } while ((initialBitrate != adjustedBitrate) && + (numIterations <= cm.nElements)); /* Unequal bitrates mean that no reasonable bitrate configuration found. */ - bitRate = (initialBitrate==adjustedBitrate) ? adjustedBitrate : 0; + bitRate = (initialBitrate == adjustedBitrate) ? adjustedBitrate : 0; } - FDK_ASSERT(bitRate > 0); + /* Limit bit rate in respect to available MPS modes if active */ + if ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS) && + (channelMode == MODE_1)) { + bitRate = FDK_MpegsEnc_GetClosestBitRate( + aot, MODE_212, samplingRate, (sbrActive) ? sbrDownSampleRate : 0, + bitRate); + } return bitRate; } /* + * \brief Get CBR bitrate + * + * \hAacConfig Internal encoder config + * \return Bitrate + */ +static INT FDKaacEnc_GetCBRBitrate(const HANDLE_AACENC_CONFIG hAacConfig, + const INT userSbrRatio) { + INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff * + hAacConfig->sampleRate; + + if (isPsActive(hAacConfig->audioObjectType)) { + bitrate = 1 * bitrate; /* 0.5 bit per sample */ + } else if (isSbrActive(hAacConfig)) { + if ((userSbrRatio == 2) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType != AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 2)) >> 1; /* 0.625 bits per sample */ + } + if ((userSbrRatio == 1) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 3)); /* 1.125 bits per sample */ + } + } else { + bitrate = bitrate + (bitrate >> 1); /* 1.5 bits per sample */ + } + + 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 + * \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; - - if (config->userTpType==TT_MP4_LATM_MCP1 || config->userTpType==TT_MP4_LATM_MCP0 || config->userTpType==TT_MP4_LOAS) { - hAacConfig->audioMuxVersion = config->userTpAmxv; - } - else { - hAacConfig->audioMuxVersion = -1; - } +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; + + /* Encoder settings update. */ + hAacConfig->sampleRate = config->userSamplerate; + if (config->userDownscaleFactor > 1) { + hAacConfig->useTns = 0; + hAacConfig->usePns = 0; + hAacConfig->useIS = 0; + } else { + hAacConfig->useTns = config->userTns; + hAacConfig->usePns = config->userPns; + hAacConfig->useIS = config->userIntensity; + } - /* Adapt internal AOT when necessary. */ - switch ( hAacConfig->audioObjectType ) { - 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) { - 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==1) ? 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; - } + hAacConfig->audioObjectType = config->userAOT; + hAacConfig->channelMode = + GetCoreChannelMode(config->userChannelMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannels; + hAacConfig->bitrateMode = (AACENC_BITRATE_MODE)config->userBitrateMode; + hAacConfig->bandWidth = config->userBandwidth; + hAacConfig->useRequant = config->userAfterburner; + + hAacConfig->anc_Rate = config->userAncDataRate; + hAacConfig->syntaxFlags = 0; + hAacConfig->epConfig = -1; + + if (hAacConfig->audioObjectType != AOT_ER_AAC_ELD && + config->userDownscaleFactor > 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + */ + } + if (config->userDownscaleFactor > 1 && config->userSbrEnabled == 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + w/o SBR */ + } + if (config->userDownscaleFactor > 1 && config->userChannelMode == 128) { + return AACENC_INVALID_CONFIG; /* disallow downscaling for AAC-ELDv2 */ + } + + if (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) { + hAacConfig->audioMuxVersion = config->userTpAmxv; + } else { + hAacConfig->audioMuxVersion = -1; + } + + /* Adapt internal AOT when necessary. */ + switch (config->userAOT) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacConfig->usePns = 0; + 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_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 == 1) ? AC_SBR_PRESENT : 0); + hAacConfig->syntaxFlags |= + ((config->userChannelMode == MODE_212) ? AC_LD_MPS : 0); + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = + (config->userFramelength != (UINT)-1) ? config->userFramelength : 512; + + hAacConfig->downscaleFactor = config->userDownscaleFactor; + + switch (config->userDownscaleFactor) { + case 1: break; - default: + case 2: + case 4: + hAacConfig->syntaxFlags |= AC_ELD_DOWNSCALE; break; - } - - switch ( hAacConfig->audioObjectType ) { - case AOT_ER_AAC_LD: - case AOT_ER_AAC_ELD: - if (config->userBitrateMode==0) { - /* bitreservoir = (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; */ - if ( isLowDelay(hAacConfig->audioObjectType) ) { - INT bitreservoir; - INT brPerChannel = hAacConfig->bitRate/hAacConfig->nChannels; - brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); - FIXP_DBL slope = fDivNorm((brPerChannel-BITRATE_MIN_LD), BITRATE_MAX_LD-BITRATE_MIN_LD); /* calc slope for interpolation */ - bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD-BITRES_MIN_LD)) + BITRES_MIN_LD; /* interpolate */ - hAacConfig->bitreservoir = bitreservoir & ~7; /* align to bytes */ - } - } - if (hAacConfig->bitrateMode!=0) { + default: return AACENC_INVALID_CONFIG; - } - break; - default: - break; - } + } - hAacConfig->bitRate = config->userBitrate; + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480 && + hAacConfig->framelength != 256 && hAacConfig->framelength != 240 && + hAacConfig->framelength != 128 && hAacConfig->framelength != 120) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } - /* 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); + /* Initialize SBR parameters */ + if ((config->userSbrRatio == 0) && (isSbrActive(hAacConfig))) { + /* Automatic SBR ratio configuration + * - downsampled SBR for ELD + * - otherwise always dualrate SBR + */ + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + hAacConfig->sbrRatio = ((hAacConfig->syntaxFlags & AC_LD_MPS) && + (hAacConfig->sampleRate >= 27713)) + ? 2 + : 1; + } else { + hAacConfig->sbrRatio = 2; } + } else { + /* SBR ratio has been set by the user, so use it. */ + hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; + } + /* Set default bitrate */ + hAacConfig->bitRate = config->userBitrate; + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + /* Set default bitrate if no external bitrate declared. */ + if (config->userBitrate == (UINT)-1) { + hAacConfig->bitRate = + FDKaacEnc_GetCBRBitrate(hAacConfig, config->userSbrRatio); + } + hAacConfig->averageBits = -1; + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* Get bitrate in VBR configuration */ + /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. + */ + hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, + hAacConfig->channelMode); + break; + default: + return AACENC_INVALID_CONFIG; + } - /* Set default bitrate if no external bitrate declared. */ - if ( (hAacConfig->bitrateMode==0) && (config->userBitrate==(UINT)-1) ) { - INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff * hAacConfig->sampleRate; - - if ( isPsActive(hAacConfig->audioObjectType) ) { - hAacConfig->bitRate = (bitrate>>1); /* 0.5 bit per sample */ - } - else if ( isSbrActive(hAacConfig) ) - { - if ( (config->userSbrRatio==2) || ((config->userSbrRatio==0)&&(hAacConfig->audioObjectType!=AOT_ER_AAC_ELD)) ) { - hAacConfig->bitRate = (bitrate + (bitrate>>2))>>1; /* 0.625 bits per sample */ - } - if ( (config->userSbrRatio==1) || ((config->userSbrRatio==0)&&(hAacConfig->audioObjectType==AOT_ER_AAC_ELD)) ) { - hAacConfig->bitRate = (bitrate + (bitrate>>3)); /* 1.125 bits per sample */ - } - } else - { - hAacConfig->bitRate = bitrate + (bitrate>>1); /* 1.5 bits per sample */ - } - } - - if ((hAacConfig->bitrateMode >= 0) && (hAacConfig->bitrateMode <= 5)) { + /* set bitreservoir size */ + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + case AACENC_BR_MODE_CBR: if ((INT)config->userPeakBitrate != -1) { - hAacConfig->maxBitsPerFrame = (FDKaacEnc_CalcBitsPerFrame(fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), hAacConfig->framelength, hAacConfig->sampleRate) + 7)&~7; - } - else { + hAacConfig->maxBitsPerFrame = + (FDKaacEnc_CalcBitsPerFrame( + fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), + hAacConfig->framelength, hAacConfig->sampleRate) + + 7) & + ~7; + } else { hAacConfig->maxBitsPerFrame = -1; } - if (hAacConfig->audioMuxVersion==2) { - hAacConfig->minBitsPerFrame = fMin(32*8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, hAacConfig->framelength, hAacConfig->sampleRate))&~7; - } - } - - /* Initialize SBR parameters */ - if ( (hAacConfig->audioObjectType==AOT_ER_AAC_ELD) - && (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio==0) ) - { - UINT eldSbr = 0; - UINT eldSbrRatio = 0; - - if ( AACENC_OK!=(err=eldSbrConfigurator( - hAacConfig->sampleRate, - hAacConfig->channelMode, - hAacConfig->bitRate, - &eldSbr, - &eldSbrRatio)) ) - { - return err; + if (hAacConfig->audioMuxVersion == 2) { + hAacConfig->minBitsPerFrame = + fMin(32 * 8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, + hAacConfig->framelength, + hAacConfig->sampleRate)) & + ~7; } + break; + default: + return AACENC_INVALID_CONFIG; + } - hAacConfig->syntaxFlags |= ((eldSbr) ? AC_SBR_PRESENT : 0); - hAacConfig->sbrRatio = eldSbrRatio; - } - else - if ( (config->userSbrRatio==0) && (isSbrActive(hAacConfig)) ) { - /* Automatic SBR ratio configuration - * - downsampled SBR for ELD - * - otherwise always dualrate SBR - */ - hAacConfig->sbrRatio = (hAacConfig->audioObjectType==AOT_ER_AAC_ELD) ? 1 : 2; - } - else { - /* SBR ratio has been set by the user, so use it. */ - hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; + /* Max bits per frame limitation depending on transport format. */ + if ((config->userTpNsubFrames > 1)) { + int maxFrameLength = 8 * hAacEncoder->outBufferInBytes; + switch (config->userTpType) { + case TT_MP4_LOAS: + maxFrameLength = + fMin(maxFrameLength, 8 * (1 << 13)) / config->userTpNsubFrames; + break; + case TT_MP4_ADTS: + maxFrameLength = fMin(maxFrameLength, 8 * ((1 << 13) - 1)) / + config->userTpNsubFrames; + break; + default: + maxFrameLength = -1; } - - { - UCHAR tpSignaling=getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, config->userTpSignaling, hAacConfig->sbrRatio); - - if ( (hAacConfig->audioObjectType==AOT_AAC_LC || hAacConfig->audioObjectType==AOT_SBR || hAacConfig->audioObjectType==AOT_PS) && - (config->userTpType==TT_MP4_LATM_MCP1 || config->userTpType==TT_MP4_LATM_MCP0 || config->userTpType==TT_MP4_LOAS) && - (tpSignaling==1) && (config->userTpAmxv==0) ) { - /* For backward compatible explicit signaling, AMV1 has to be active */ - return AACENC_INVALID_CONFIG; + if (maxFrameLength != -1) { + if (hAacConfig->maxBitsPerFrame > maxFrameLength) { + return AACENC_INVALID_CONFIG; + } else if (hAacConfig->maxBitsPerFrame == -1) { + hAacConfig->maxBitsPerFrame = maxFrameLength; } + } + } - if ( (hAacConfig->audioObjectType==AOT_AAC_LC || hAacConfig->audioObjectType==AOT_SBR || hAacConfig->audioObjectType==AOT_PS) && - (tpSignaling==0) && (hAacConfig->sbrRatio==1)) { - /* Downsampled SBR has to be signaled explicitely (for transmission of SBR sampling fequency) */ - return AACENC_INVALID_CONFIG; - } + if ((hAacConfig->audioObjectType == AOT_ER_AAC_ELD) && + !(hAacConfig->syntaxFlags & AC_ELD_DOWNSCALE) && + (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio == 0) && + ((hAacConfig->syntaxFlags & AC_LD_MPS) == 0)) { + const ELD_SBR_CONFIGURATOR *pConfig = NULL; + + if (NULL != + (pConfig = eldSbrConfigurator( + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels, + hAacConfig->sampleRate, hAacConfig->bitRate))) { + hAacConfig->syntaxFlags |= (pConfig->sbrMode == 0) ? 0 : AC_SBR_PRESENT; + hAacConfig->syntaxFlags |= (pConfig->chMode == MODE_212) ? AC_LD_MPS : 0; + hAacConfig->channelMode = + GetCoreChannelMode(pConfig->chMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels; + hAacConfig->sbrRatio = + (pConfig->sbrMode == 0) ? 0 : (pConfig->sbrMode == 1) ? 1 : 2; } + } + { + UCHAR tpSignaling = + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio); + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) && + (tpSignaling == 1) && (config->userTpAmxv == 0)) { + /* For backward compatible explicit signaling, AMV1 has to be active */ + return AACENC_INVALID_CONFIG; + } + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (tpSignaling == 0) && (hAacConfig->sbrRatio == 1)) { + /* Downsampled SBR has to be signaled explicitely (for transmission of SBR + * sampling fequency) */ + return AACENC_INVALID_CONFIG; + } + } + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* We need the frame length to call aacEncoder_LimitBitrate() */ + if (0 >= (hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, hAacConfig->sampleRate, hAacConfig->framelength, + hAacConfig->nChannels, hAacConfig->channelMode, + hAacConfig->bitRate, hAacConfig->nSubFrames, + isSbrActive(hAacConfig), hAacConfig->sbrRatio, + hAacConfig->syntaxFlags, hAacConfig->audioObjectType))) { + 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, - hAacConfig->bitRate, - hAacConfig->nSubFrames, - isSbrActive(hAacConfig), - hAacConfig->sbrRatio, - hAacConfig->audioObjectType - ); - - /* Configure PNS */ - if ( ((hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5)) /* VBR without PNS. */ - || (hAacConfig->useTns == 0) ) /* TNS required. */ - { - hAacConfig->usePns = 0; - } + /* Configure PNS */ + if (AACENC_BR_MODE_IS_VBR(hAacConfig->bitrateMode) /* VBR without PNS. */ + || (hAacConfig->useTns == 0)) /* TNS required. */ + { + hAacConfig->usePns = 0; + } - 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 (hAacConfig->epConfig >= 0) { + hAacConfig->syntaxFlags |= AC_ER; + if (((INT)hAacConfig->channelMode < 1) || + ((INT)hAacConfig->channelMode > 14)) { + return AACENC_INVALID_CONFIG; /* Channel 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->syntaxFlags & AC_LD_MPS) == 0) { + 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 */ - } + if ((hAacConfig->nChannels > hAacEncoder->nMaxAacChannels) || + ((FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff > hAacEncoder->nMaxSbrChannels) && + isSbrActive(hAacConfig))) { + return AACENC_INVALID_CONFIG; /* not enough channels allocated */ + } - /* Meta data restriction. */ - switch (hAacConfig->audioObjectType) - { - /* Allow metadata support */ - case AOT_AAC_LC: - case AOT_SBR: - case AOT_PS: - hAacEncoder->metaDataAllowed = 1; - if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) { - config->userMetaDataMode = 0; - } - break; - /* Prohibit metadata support */ - default: - hAacEncoder->metaDataAllowed = 0; - } + /* Meta data restriction. */ + switch (hAacConfig->audioObjectType) { + /* Allow metadata support */ + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacEncoder->metaDataAllowed = 1; + if (!((((INT)hAacConfig->channelMode >= 1) && + ((INT)hAacConfig->channelMode <= 14)) || + (MODE_7_1_REAR_SURROUND == hAacConfig->channelMode) || + (MODE_7_1_FRONT_CENTER == hAacConfig->channelMode))) { + config->userMetaDataMode = 0; + } + break; + /* Prohibit metadata support */ + default: + hAacEncoder->metaDataAllowed = 0; + } - return err; + 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 - ) -{ +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, const UCHAR harmonicSbr, + const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0); @@ -1006,725 +1213,835 @@ INT aacenc_SbrCallback( return 0; } -static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, - ULONG InitFlags, - USER_PARAM *config) -{ - AACENC_ERROR err = AACENC_OK; +INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged) { + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; - INT aacBufferOffset = 0; - HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc; - HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + return (FDK_MpegsEnc_WriteSpatialSpecificConfig(hAacEncoder->hMpsEnc, hBs)); +} - hAacEncoder->nZerosAppended = 0; /* count appended zeros */ +static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, ULONG InitFlags, + USER_PARAM *config) { + AACENC_ERROR err = AACENC_OK; - INT frameLength = hAacConfig->framelength; + INT aacBufferOffset = 0; + HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc; + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; - if ( (InitFlags & AACENC_INIT_CONFIG) ) - { - CHANNEL_MODE prevChMode = hAacConfig->channelMode; + hAacEncoder->nZerosAppended = 0; /* count appended zeros */ - /* Verify settings and update: config -> heAacEncoder */ - if ( (err=FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK ) { - return err; - } - frameLength = hAacConfig->framelength; /* adapt temporal framelength */ + INT frameLength = hAacConfig->framelength; - /* Seamless channel reconfiguration in sbr not fully implemented */ - if ( (prevChMode!=hAacConfig->channelMode) && isSbrActive(hAacConfig) ) { - InitFlags |= AACENC_INIT_STATES; - } - } + if ((InitFlags & AACENC_INIT_CONFIG)) { + CHANNEL_MODE prevChMode = hAacConfig->channelMode; - /* Clear input buffer */ - if ( InitFlags == AACENC_INIT_ALL ) { - FDKmemclear(hAacEncoder->inputBuffer, sizeof(INT_PCM)*hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE); + /* Verify settings and update: config -> heAacEncoder */ + if ((err = FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK) { + return err; } + frameLength = hAacConfig->framelength; /* adapt temporal framelength */ - 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; + /* Seamless channel reconfiguration in sbr not fully implemented */ + if ((prevChMode != hAacConfig->channelMode) && isSbrActive(hAacConfig)) { + InitFlags |= AACENC_INIT_STATES; } + } - if ( isSbrActive(hAacConfig) && - ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) ) - { - INT sbrError; - SBR_ELEMENT_INFO sbrElInfo[(8)]; - CHANNEL_MAPPING channelMapping; - - if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode, - hAacConfig->channelOrder, - &channelMapping) != AAC_ENC_OK ) - { - return AACENC_INIT_ERROR; - } + /* Clear input buffer */ + if (InitFlags == AACENC_INIT_ALL) { + FDKmemclear(hAacEncoder->inputBuffer, + sizeof(INT_PCM) * hAacEncoder->inputBufferSize); + } - /* Check return value and if the SBR encoder can handle enough elements */ - if (channelMapping.nElements > (8)) { - return AACENC_INIT_ERROR; - } + if ((InitFlags & AACENC_INIT_CONFIG)) { + aacBufferOffset = 0; + switch (hAacConfig->audioObjectType) { + case AOT_ER_AAC_LD: + hAacEncoder->nDelay = DELAY_AACLD(hAacConfig->framelength); + break; + case AOT_ER_AAC_ELD: + hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength); + break; + default: + hAacEncoder->nDelay = + DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */ + } - 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, - &hAacConfig->sbrRatio, - &frameLength, - hAacConfig->audioObjectType, - &hAacEncoder->nDelay, - (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC, - (config->userTpHeaderPeriod!=0xFF) ? config->userTpHeaderPeriod : DEFAULT_HEADER_PERIOD_REPETITION_RATE, - initFlag - ); - - /* Suppress AOT reconfiguration and check error status. */ - if (sbrError) { - return AACENC_INIT_SBR_ERROR; - } + hAacConfig->ancDataBitRate = 0; + } - if (hAacConfig->nChannels == 1) { - hAacConfig->channelMode = MODE_1; - } + if ((NULL != hAacEncoder->hEnvEnc) && isSbrActive(hAacConfig) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES))) { + INT sbrError; + UINT initFlag = 0; + SBR_ELEMENT_INFO sbrElInfo[(8)]; + CHANNEL_MAPPING channelMapping; + CHANNEL_MODE channelMode = isPsActive(hAacConfig->audioObjectType) + ? config->userChannelMode + : hAacConfig->channelMode; + INT numChannels = isPsActive(hAacConfig->audioObjectType) + ? config->nChannels + : hAacConfig->nChannels; - /* Never use PNS if SBR is active */ - if ( hAacConfig->usePns ) { - hAacConfig->usePns = 0; - } + if (FDKaacEnc_InitChannelMapping(channelMode, hAacConfig->channelOrder, + &channelMapping) != AAC_ENC_OK) { + return AACENC_INIT_ERROR; + } - /* estimated bitrate consumed by SBR or PS */ - hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder) ; + /* Check return value and if the SBR encoder can handle enough elements */ + if (channelMapping.nElements > (8)) { + return AACENC_INIT_ERROR; + } - } /* sbr initialization */ + aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate); + initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0; - /* - * Initialize Transport - Module. - */ - if ( (InitFlags & AACENC_INIT_TRANSPORT) ) - { - UINT flags = 0; - - FDKaacEnc_MapConfig( - &hAacEncoder->coderConfig, - config, - getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, config->userTpSignaling, hAacConfig->sbrRatio), - hAacConfig); - - /* create flags for transport encoder */ - if (config->userTpAmxv != 0) { - flags |= TP_FLAG_LATM_AMV; - } - /* Clear output buffer */ - FDKmemclear(hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes*sizeof(UCHAR)); + /* Let the SBR encoder take a look at the configuration and change if + * required. */ + sbrError = sbrEncoder_Init( + *hSbrEncoder, sbrElInfo, channelMapping.nElements, + hAacEncoder->inputBuffer, hAacEncoder->inputBufferSizePerChannel, + &hAacConfig->bandWidth, &aacBufferOffset, &numChannels, + hAacConfig->syntaxFlags, &hAacConfig->sampleRate, &hAacConfig->sbrRatio, + &frameLength, hAacConfig->audioObjectType, &hAacEncoder->nDelay, + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC, + (config->userTpHeaderPeriod != 0xFF) + ? config->userTpHeaderPeriod + : DEFAULT_HEADER_PERIOD_REPETITION_RATE, + initFlag); - /* Initialize Bitstream encoder */ - if ( transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes, config->userTpType, &hAacEncoder->coderConfig, flags) != 0) { - return AACENC_INIT_TP_ERROR; - } + /* Suppress AOT reconfiguration and check error status. */ + if ((sbrError) || (numChannels != hAacConfig->nChannels)) { + return AACENC_INIT_SBR_ERROR; + } - } /* transport initialization */ + if (numChannels == 1) { + hAacConfig->channelMode = MODE_1; + } - /* - * 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; - } + /* Never use PNS if SBR is active */ + if (hAacConfig->usePns) { + hAacConfig->usePns = 0; + } - } /* aac initialization */ + /* estimated bitrate consumed by SBR or PS */ + hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder); - /* - * Initialize Meta Data - Encoder. - */ - if ( hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed!=0) && - ((InitFlags & AACENC_INIT_CONFIG) ||(InitFlags & AACENC_INIT_STATES)) ) - { - INT inputDataDelay = DELAY_AAC(hAacConfig->framelength); + } /* sbr initialization */ - if ( isSbrActive(hAacConfig) && hSbrEncoder!=NULL) { - inputDataDelay = hAacConfig->sbrRatio*inputDataDelay + sbrEncoder_GetInputDataDelay(*hSbrEncoder); - } + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + int coreCoderDelay = DELAY_AACELD(hAacConfig->framelength); - 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; - } + if (isSbrActive(hAacConfig)) { + coreCoderDelay = hAacConfig->sbrRatio * coreCoderDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } - hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc); + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Init(hAacEncoder->hMpsEnc, hAacConfig->audioObjectType, + config->userSamplerate, hAacConfig->bitRate, + isSbrActive(hAacConfig) ? hAacConfig->sbrRatio : 0, + frameLength, /* for dual rate sbr this value is + already multiplied by 2 */ + hAacEncoder->inputBufferSizePerChannel, + coreCoderDelay)) { + return AACENC_INIT_MPS_ERROR; } + } + hAacEncoder->nDelay = + fMax(FDK_MpegsEnc_GetDelay(hAacEncoder->hMpsEnc), hAacEncoder->nDelay); - /* - * Update pointer to working buffer. - */ - if ( (InitFlags & AACENC_INIT_CONFIG) ) - { - hAacEncoder->inputBufferOffset = aacBufferOffset; + /* + * Initialize Transport - Module. + */ + if ((InitFlags & AACENC_INIT_TRANSPORT)) { + UINT flags = 0; - hAacEncoder->nSamplesToRead = frameLength * config->nChannels; + FDKaacEnc_MapConfig( + &hAacEncoder->coderConfig, config, + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio), + hAacConfig); - /* Make nDelay comparison compatible with config->nSamplesRead */ - hAacEncoder->nDelay *= config->nChannels; + /* create flags for transport encoder */ + if (config->userTpAmxv != 0) { + 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; + } - } /* parameter changed */ + } /* transport initialization */ - return AACENC_OK; -} + /* + * Initialize AAC - Core. + */ + if ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) { + if (FDKaacEnc_Initialize( + hAacEncoder->hAacEnc, hAacConfig, hAacEncoder->hTpEnc, + (InitFlags & AACENC_INIT_STATES) ? 1 : 0) != AAC_ENC_OK) { + return AACENC_INIT_AAC_ERROR; + } + } /* aac initialization */ -AACENC_ERROR aacEncOpen( - HANDLE_AACENCODER *phAacEncoder, - const UINT encModules, - const UINT maxChannels - ) -{ - AACENC_ERROR err = AACENC_OK; - HANDLE_AACENCODER hAacEncoder = NULL; + /* + * 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 (phAacEncoder == NULL) { - err = AACENC_INVALID_HANDLE; - goto bail; + if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + inputDataDelay = hAacConfig->sbrRatio * inputDataDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); } - /* allocate memory */ - hAacEncoder = Get_AacEncoder(); - - if (hAacEncoder == NULL) { - err = AACENC_MEMORY_ERROR; - goto bail; + 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; } - FDKmemclear(hAacEncoder, sizeof(AACENCODER)); + hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc); + } - /* 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; - } + /* Get custom delay, i.e. the codec delay w/o the decoder's SBR- or MPS delay + */ + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, FDK_MpegsEnc_GetDecDelay(hAacEncoder->hMpsEnc)); + } else if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, sbrEncoder_GetSbrDecDelay(hAacEncoder->hEnvEnc)); + } else { + hAacEncoder->nDelayCore = hAacEncoder->nDelay; + } - /* Determine max channel configuration. */ - if (maxChannels==0) { - hAacEncoder->nMaxAacChannels = (8); - hAacEncoder->nMaxSbrChannels = (8); - } - else { - hAacEncoder->nMaxAacChannels = (maxChannels&0x00FF); - if ( (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) ) { - hAacEncoder->nMaxSbrChannels = (maxChannels&0xFF00) ? (maxChannels>>8) : hAacEncoder->nMaxAacChannels; - } + /* + * Update pointer to working buffer. + */ + if ((InitFlags & AACENC_INIT_CONFIG)) { + hAacEncoder->inputBufferOffset = aacBufferOffset; - if ( (hAacEncoder->nMaxAacChannels>(8)) || (hAacEncoder->nMaxSbrChannels>(8)) ) { - err = AACENC_INVALID_CONFIG; - goto bail; - } - } /* maxChannels==0 */ + hAacEncoder->nSamplesToRead = frameLength * config->nChannels; - /* Max number of elements could be tuned any more. */ - hAacEncoder->nMaxAacElements = fixMin((8), hAacEncoder->nMaxAacChannels); - hAacEncoder->nMaxSbrElements = fixMin((8), hAacEncoder->nMaxSbrChannels); - hAacEncoder->nMaxSubFrames = (1); + } /* parameter changed */ + return AACENC_OK; +} - /* In case of memory overlay, allocate memory out of libraries */ +AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules, + const UINT maxChannels) { + AACENC_ERROR err = AACENC_OK; + HANDLE_AACENCODER hAacEncoder = NULL; - hAacEncoder->inputBuffer = (INT_PCM*)FDKcalloc(hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE, sizeof(INT_PCM)); + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } - /* 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) */ + /* allocate memory */ + hAacEncoder = Get_AacEncoder(); + if (hAacEncoder == NULL) { + err = AACENC_MEMORY_ERROR; + goto bail; + } - /* Open Aac Encoder */ - if ( FDKaacEnc_Open(&hAacEncoder->hAacEnc, - hAacEncoder->nMaxAacElements, - hAacEncoder->nMaxAacChannels, - (1)) != AAC_ENC_OK ) - { - err = AACENC_MEMORY_ERROR; - goto bail; - } + FDKmemclear(hAacEncoder, sizeof(AACENCODER)); + + /* Specify encoder modules to be allocated. */ + if (encModules == 0) { + C_ALLOC_SCRATCH_START(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; + FDKinitLibInfo(*pLibInfo); + aacEncGetLibInfo(*pLibInfo); - { /* 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->encoder_modis = ENC_MODE_FLAG_AAC; + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_HQ) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR; } - hAacEncoder->outBuffer = GetRam_bsOutbuffer(); - if (OUTPUTBUFFER_SIZE < hAacEncoder->outBufferInBytes ) { - err = AACENC_MEMORY_ERROR; - goto bail; + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_PS_MPEG) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS; } - - /* 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; + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_AACENC) & CAPF_AAC_DRC) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META; } - else { - C_ALLOC_SCRATCH_START(pLibInfo, LIB_INFO, FDK_MODULE_LAST); + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SAC; - 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) + } else { + hAacEncoder->encoder_modis = encModules; + } - C_ALLOC_SCRATCH_END(pLibInfo, LIB_INFO, FDK_MODULE_LAST); + /* Determine max channel configuration. */ + if (maxChannels == 0) { + hAacEncoder->nMaxAacChannels = (8); + hAacEncoder->nMaxSbrChannels = (8); + } else { + hAacEncoder->nMaxAacChannels = (maxChannels & 0x00FF); + if ((hAacEncoder->encoder_modis & ENC_MODE_FLAG_SBR)) { + hAacEncoder->nMaxSbrChannels = (maxChannels & 0xFF00) + ? (maxChannels >> 8) + : hAacEncoder->nMaxAacChannels; } - if ( transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, hAacEncoder) != 0 ) { - err = AACENC_INIT_TP_ERROR; + + if ((hAacEncoder->nMaxAacChannels > (8)) || + (hAacEncoder->nMaxSbrChannels > (8))) { + err = AACENC_INVALID_CONFIG; goto bail; } + } /* maxChannels==0 */ - /* Initialize encoder instance with default parameters. */ - aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam); + /* Max number of elements could be tuned any more. */ + hAacEncoder->nMaxAacElements = fixMin(((8)), hAacEncoder->nMaxAacChannels); + hAacEncoder->nMaxSbrElements = fixMin((8), hAacEncoder->nMaxSbrChannels); - /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */ - hAacEncoder->coderConfig.headerPeriod = hAacEncoder->extParam.userTpHeaderPeriod; + /* In case of memory overlay, allocate memory out of libraries */ - /* All encoder modules have to be initialized */ - hAacEncoder->InitFlags = AACENC_INIT_ALL; + if (hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR | ENC_MODE_FLAG_PS)) + hAacEncoder->inputBufferSizePerChannel = INPUTBUFFER_SIZE; + else + hAacEncoder->inputBufferSizePerChannel = (1024); - /* Return encoder instance */ - *phAacEncoder = hAacEncoder; + hAacEncoder->inputBufferSize = + hAacEncoder->nMaxAacChannels * hAacEncoder->inputBufferSizePerChannel; - return err; + if (NULL == (hAacEncoder->inputBuffer = (INT_PCM *)FDKcalloc( + hAacEncoder->inputBufferSize, sizeof(INT_PCM)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } -bail: - aacEncClose(&hAacEncoder); + /* 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; + } - return err; -} + if (NULL == (hAacEncoder->pSbrPayload = (SBRENC_EXT_PAYLOAD *)FDKcalloc( + 1, sizeof(SBRENC_EXT_PAYLOAD)))) { + 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; + } + /* Bitstream output buffer */ + hAacEncoder->outBufferInBytes = + 1 << (DFRACT_BITS - CntLeadingZeros(fixMax( + 1, ((1) * hAacEncoder->nMaxAacChannels * 6144) >> + 3))); /* buffer has to be 2^n */ + if (NULL == (hAacEncoder->outBuffer = (UCHAR *)FDKcalloc( + hAacEncoder->outBufferInBytes, sizeof(UCHAR)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } -AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder) -{ - AACENC_ERROR err = AACENC_OK; + /* Open Meta Data Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_META) { + if (FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc, + (UINT)hAacEncoder->nMaxAacChannels)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_META) */ - if (phAacEncoder == NULL) { - err = AACENC_INVALID_HANDLE; - goto bail; + /* Open MPEG Surround Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_SAC) { + if (MPS_ENCODER_OK != FDK_MpegsEnc_Open(&hAacEncoder->hMpsEnc)) { + err = AACENC_MEMORY_ERROR; + goto bail; } + } /* (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SAC) */ - if (*phAacEncoder != NULL) { - HANDLE_AACENCODER hAacEncoder = *phAacEncoder; + /* 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) + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; - if (hAacEncoder->inputBuffer!=NULL) { - FDKfree(hAacEncoder->inputBuffer); - hAacEncoder->inputBuffer = NULL; - } + FDKinitLibInfo(*pLibInfo); + transportEnc_GetLibInfo(*pLibInfo); - if (hAacEncoder->outBuffer) { - FreeRam_bsOutbuffer(&hAacEncoder->outBuffer); - } + /* Get capabilty flag for transport encoder. */ + hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities(*pLibInfo, FDK_TPENC); - if (hAacEncoder->hEnvEnc) { - sbrEncoder_Close (&hAacEncoder->hEnvEnc); - } - if (hAacEncoder->hAacEnc) { - FDKaacEnc_Close (&hAacEncoder->hAacEnc); - } + 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; + } + if (transportEnc_RegisterSscCallback(hAacEncoder->hTpEnc, aacenc_SscCallback, + hAacEncoder) != 0) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } - transportEnc_Close(&hAacEncoder->hTpEnc); + /* Initialize encoder instance with default parameters. */ + aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam); - if (hAacEncoder->hMetadataEnc) { - FDK_MetadataEnc_Close (&hAacEncoder->hMetadataEnc); - } + /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */ + hAacEncoder->coderConfig.headerPeriod = + hAacEncoder->extParam.userTpHeaderPeriod; - Free_AacEncoder(phAacEncoder); - } + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + + /* Return encoder instance */ + *phAacEncoder = hAacEncoder; + + return err; bail: - return err; -} + aacEncClose(&hAacEncoder); -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; - } + return err; +} +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder) { + AACENC_ERROR err = AACENC_OK; - /* - * Adjust user settings and trigger reinitialization. - */ - if (hAacEncoder->InitFlags!=0) { + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } - err = aacEncInit(hAacEncoder, - hAacEncoder->InitFlags, - &hAacEncoder->extParam); + if (*phAacEncoder != NULL) { + HANDLE_AACENCODER hAacEncoder = *phAacEncoder; - if (err!=AACENC_OK) { - /* keep init flags alive! */ - goto bail; - } - hAacEncoder->InitFlags = AACENC_INIT_NONE; + if (hAacEncoder->inputBuffer != NULL) { + FDKfree(hAacEncoder->inputBuffer); + hAacEncoder->inputBuffer = NULL; } - - if (outargs!=NULL) { - FDKmemclear(outargs, sizeof(AACENC_OutArgs)); + if (hAacEncoder->outBuffer != NULL) { + FDKfree(hAacEncoder->outBuffer); + hAacEncoder->outBuffer = NULL; } - if (outBufDesc!=NULL) { - for (i=0; i<outBufDesc->numBufs; i++) { - if (outBufDesc->bufs[i]!=NULL) { - FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]); - } - } + if (hAacEncoder->hEnvEnc) { + sbrEncoder_Close(&hAacEncoder->hEnvEnc); + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKfree(hAacEncoder->pSbrPayload); + hAacEncoder->pSbrPayload = NULL; + } + if (hAacEncoder->hAacEnc) { + FDKaacEnc_Close(&hAacEncoder->hAacEnc); } - /* - * If only encoder handle given, independent (re)initialization can be triggered. - */ - if ( (hAacEncoder!=NULL) & (inBufDesc==NULL) && (outBufDesc==NULL) && (inargs==NULL) && (outargs==NULL) ) { - goto bail; + transportEnc_Close(&hAacEncoder->hTpEnc); + + if (hAacEncoder->hMetadataEnc) { + FDK_MetadataEnc_Close(&hAacEncoder->hMetadataEnc); + } + if (hAacEncoder->hMpsEnc) { + FDK_MpegsEnc_Close(&hAacEncoder->hMpsEnc); } - /* reset buffer wich signals number of valid bytes in output bitstream buffer */ - FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames*sizeof(INT)); + Free_AacEncoder(phAacEncoder); + } - /* - * 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; +bail: + return err; +} - /* Number of fetched input buffer samples. */ - outargs->numInSamples = newSamples; - } +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; + } - /* 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 */ - } - } + /* + * Adjust user settings and trigger reinitialization. + */ + if (hAacEncoder->InitFlags != 0) { + err = + aacEncInit(hAacEncoder, hAacEncoder->InitFlags, &hAacEncoder->extParam); - /* 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; + if (err != AACENC_OK) { + /* keep init flags alive! */ + goto bail; } - FDKmemclear(hAacEncoder->extPayloadData, sizeof(hAacEncoder->extPayloadData)); - FDKmemclear(hAacEncoder->extPayloadSize, sizeof(hAacEncoder->extPayloadSize)); + hAacEncoder->InitFlags = AACENC_INIT_NONE; + } + if (outargs != NULL) { + FDKmemclear(outargs, sizeof(AACENC_OutArgs)); + } - /* - * Calculate Meta Data info. - */ - if ( (hAacEncoder->hMetadataEnc!=NULL) && (hAacEncoder->metaDataAllowed!=0) ) { + if (outBufDesc != NULL) { + for (i = 0; i < outBufDesc->numBufs; i++) { + if (outBufDesc->bufs[i] != NULL) { + FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]); + } + } + } - const AACENC_MetaData *pMetaData = NULL; - AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL; - UINT nMetaDataExtensions = 0; - INT matrix_mixdown_idx = 0; + /* + * If only encoder handle given, independent (re)initialization can be + * triggered. + */ + if ((inBufDesc == NULL) && (outBufDesc == NULL) && (inargs == NULL) && + (outargs == NULL)) { + goto bail; + } - /* New meta data info available ? */ - if ( getBufDescIdx(inBufDesc,IN_METADATA_SETUP) != -1 ) { - pMetaData = (AACENC_MetaData*)inBufDesc->bufs[getBufDescIdx(inBufDesc,IN_METADATA_SETUP)]; - } + /* check if buffer descriptors are filled out properly. */ + if ((AACENC_OK != validateBufDesc(inBufDesc)) || + (AACENC_OK != validateBufDesc(outBufDesc)) || (inargs == NULL) || + (outargs == NULL)) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } - 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]; - } + /* reset buffer wich signals number of valid bytes in output bitstream buffer + */ + FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames * sizeof(INT)); + + /* + * Manage incoming audio samples. + */ + if ((inBufDesc != NULL) && (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) / + hAacEncoder->aacConfig.nChannels; + + /* Copy new input samples to internal buffer */ + if (inBufDesc->bufElSizes[idx] == (INT)sizeof(INT_PCM)) { + FDK_deinterleave((INT_PCM *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else if (inBufDesc->bufElSizes[idx] > (INT)sizeof(INT_PCM)) { + FDK_deinterleave((LONG *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else { + FDK_deinterleave((SHORT *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } + hAacEncoder->nSamplesRead += newSamples; + + /* Number of fetched input buffer samples. */ + outargs->numInSamples = newSamples; + } - if ( (matrix_mixdown_idx!=-1) - && ((hAacEncoder->extParam.userChannelMode==MODE_1_2_2)||(hAacEncoder->extParam.userChannelMode==MODE_1_2_2_1)) ) - { - /* Set matrix mixdown coefficient. */ - UINT pceValue = (UINT)( (0<<3) | ((matrix_mixdown_idx&0x3)<<1) | 1 ); - if (hAacEncoder->extParam.userPceAdditions != pceValue) { - hAacEncoder->extParam.userPceAdditions = pceValue; - hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + /* 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) / + hAacEncoder->extParam.nChannels; + + FDK_ASSERT(nZeros >= 0); + + /* clear out until end-of-buffer */ + if (nZeros) { + for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) { + FDKmemclear(hAacEncoder->inputBuffer + + i * hAacEncoder->inputBufferSizePerChannel + + (hAacEncoder->inputBufferOffset + + hAacEncoder->nSamplesRead) / + hAacEncoder->extParam.nChannels, + 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; + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKmemclear(hAacEncoder->pSbrPayload, sizeof(*hAacEncoder->pSbrPayload)); + } - 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 < (8); 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++; + /* + * 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->coderConfig.noChannels, + hAacEncoder->inputBufferSizePerChannel, 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) && + ((hAacEncoder->extParam.userChannelMode == MODE_1_2_2) || + (hAacEncoder->extParam.userChannelMode == MODE_1_2_2_1))) { + /* Set matrix mixdown coefficient. */ + UINT pceValue = (UINT)((0 << 3) | ((matrix_mixdown_idx & 0x3) << 1) | 1); + if (hAacEncoder->extParam.userPceAdditions != pceValue) { + hAacEncoder->extParam.userPceAdditions = pceValue; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } } + } - /* - * Encode AAC - Core. - */ - if ( FDKaacEnc_EncodeFrame( hAacEncoder->hAacEnc, - hAacEncoder->hTpEnc, - hAacEncoder->inputBuffer, - outBytes, - hAacEncoder->extPayload - ) != AAC_ENC_OK ) - { - err = AACENC_ENCODE_ERROR; - goto bail; + /* + * Encode MPS data. + */ + if ((hAacEncoder->hMpsEnc != NULL) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + AACENC_EXT_PAYLOAD mpsExtensionPayload; + FDKmemclear(&mpsExtensionPayload, sizeof(AACENC_EXT_PAYLOAD)); + + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Process( + hAacEncoder->hMpsEnc, + hAacEncoder->inputBuffer + hAacEncoder->inputBufferOffset / + hAacEncoder->coderConfig.noChannels, + hAacEncoder->nSamplesRead, &mpsExtensionPayload)) { + err = AACENC_ENCODE_ERROR; + goto bail; } - if (ancDataExtIdx >= 0) { - outargs->numAncBytes = inargs->numAncBytes - (hAacEncoder->extPayload[ancDataExtIdx].dataSize>>3); + if ((mpsExtensionPayload.pData != NULL) && + ((mpsExtensionPayload.dataSize != 0))) { + hAacEncoder->extPayload[nExtensions++] = mpsExtensionPayload; } + } - /* samples exhausted */ - hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead; + if ((NULL != hAacEncoder->hEnvEnc) && (NULL != hAacEncoder->pSbrPayload) && + isSbrActive(&hAacEncoder->aacConfig)) { + INT nPayload = 0; /* - * Delay balancing buffer handling + * Encode SBR data. */ - if (isSbrActive(&hAacEncoder->aacConfig)) { - sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer); - } + if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, + hAacEncoder->pSbrPayload->dataSize[nPayload], + hAacEncoder->pSbrPayload->data[nPayload])) { + err = AACENC_ENCODE_ERROR; + goto bail; + } else { + /* Add SBR extension payload */ + for (i = 0; i < (8); i++) { + if (hAacEncoder->pSbrPayload->dataSize[nPayload][i] > 0) { + hAacEncoder->extPayload[nExtensions].pData = + hAacEncoder->pSbrPayload->data[nPayload][i]; + { + hAacEncoder->extPayload[nExtensions].dataSize = + hAacEncoder->pSbrPayload->dataSize[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++; + } - /* - * Make bitstream public - */ - if (outBufDesc->numBufs>=1) { + /* + * Encode AAC - Core. + */ + if (FDKaacEnc_EncodeFrame(hAacEncoder->hAacEnc, hAacEncoder->hTpEnc, + hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, outBytes, + hAacEncoder->extPayload) != AAC_ENC_OK) { + err = AACENC_ENCODE_ERROR; + goto bail; + } - INT bsIdx = getBufDescIdx(outBufDesc,OUT_BITSTREAM_DATA); - INT auIdx = getBufDescIdx(outBufDesc,OUT_AU_SIZES); + if (ancDataExtIdx >= 0) { + outargs->numAncBytes = + inargs->numAncBytes - + (hAacEncoder->extPayload[ancDataExtIdx].dataSize >> 3); + } - for (i=0,nBsBytes=0; i<hAacEncoder->aacConfig.nSubFrames; i++) { - nBsBytes += outBytes[i]; + /* samples exhausted */ + hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead; - if (auIdx!=-1) { - ((INT*)outBufDesc->bufs[auIdx])[i] = outBytes[i]; - } - } + /* + * Delay balancing buffer handling + */ + if (isSbrActive(&hAacEncoder->aacConfig)) { + sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel); + } - 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; - } + /* + * Make bitstream public + */ + if ((outBufDesc != NULL) && (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]; + } } -bail: - if (err == AACENC_ENCODE_ERROR) { - /* All encoder modules have to be initialized */ - hAacEncoder->InitFlags = AACENC_INIT_ALL; + if ((bsIdx != -1) && (outBufDesc->bufSizes[bsIdx] >= nBsBytes)) { + FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, + sizeof(UCHAR) * nBsBytes); + outargs->numOutBytes = nBsBytes; + outargs->bitResState = + FDKaacEnc_GetBitReservoirState(hAacEncoder->hAacEnc); + } 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; + return err; } -static -AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder, - UINT *size, - UCHAR *confBuffer) -{ - FDK_BITSTREAM tmpConf; - UINT confType; - UCHAR buf[64]; - int 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); + /* Init bit buffer */ + FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER); - /* write conf in tmp buffer */ - err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, &tmpConf, &confType); + /* write conf in tmp buffer */ + err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, + &tmpConf, &confType); - /* copy data to outbuffer: length in bytes */ - FDKbyteAlign(&tmpConf, 0); + /* copy data to outbuffer: length in bytes */ + FDKbyteAlign(&tmpConf, 0); - /* Check buffer size */ - if (FDKgetValidBits(&tmpConf) > ((*size)<<3)) - return AAC_ENC_UNKNOWN; + /* Check buffer size */ + if (FDKgetValidBits(&tmpConf) > ((*size) << 3)) return AAC_ENC_UNKNOWN; - FDKfetchBuffer(&tmpConf, confBuffer, size); + FDKfetchBuffer(&tmpConf, confBuffer, size); - if (err != 0) - return AAC_ENC_UNKNOWN; - else - return AAC_ENC_OK; + if (err != 0) + return AAC_ENC_UNKNOWN; + else + return AAC_ENC_OK; } - -AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) -{ +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 ); + FDK_toolsGetLibInfo(info); + transportEnc_GetLibInfo(info); + sbrEncoder_GetLibInfo(info); + FDK_MpegsEnc_GetLibInfo(info); /* search for next free tab */ for (i = 0; i < FDK_MODULE_LAST; i++) { @@ -1735,405 +2052,451 @@ AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) } 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);; + info[i].build_date = AACENCODER_LIB_BUILD_DATE; + info[i].build_time = AACENCODER_LIB_BUILD_TIME; + info[i].title = 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 - ; + info[i].flags = 0 | CAPF_AAC_1024 | CAPF_AAC_LC | CAPF_AAC_512 | + CAPF_AAC_480 | CAPF_AAC_DRC | CAPF_AAC_ELD_DOWNSCALE; /* 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; +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; - } + /* check encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } - /* apply param value */ - switch (param) - { + /* 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: - if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { - err = AACENC_INVALID_CONFIG; - goto bail; - } - case AOT_SBR: - if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { - err = AACENC_INVALID_CONFIG; - goto bail; - } - case AOT_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; + if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) { + /* check if AOT matches the allocated modules */ + switch (value) { + case AOT_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_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; + 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 1: case 2: case 3: case 4: case 5: - case 8: - settings->userBitrateMode = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; - break; - default: - err = AACENC_INVALID_CONFIG; - break; - } /* switch value */ - } - break; + if (settings->userBitrateMode != value) { + switch (value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + 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; + 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; } - 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<=7))||((value>=33) && (value<=34))) - ) - { - err = AACENC_INVALID_CONFIG; - break; - } + if (settings->userChannelMode != (CHANNEL_MODE)value) { + if (((CHANNEL_MODE)value == MODE_212) && + (NULL != hAacEncoder->hMpsEnc)) { + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = 2; + } else { + 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)) { + 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; + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = pConfig->nChannels; } - break; - case AACENC_BANDWIDTH: - if (settings->userBandwidth != value) { - settings->userBandwidth = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + if (!((value >= 1) && (value <= 6))) { + hAacEncoder->InitFlags |= AACENC_INIT_STATES; } - break; + } + 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; + if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; } - 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; + if (settings->userAfterburner != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; } - 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; - } + if (settings->userFramelength != value) { + switch (value) { + case 1024: + case 512: + case 480: + case 256: + case 240: + case 128: + case 120: + if ((value << 1) == 480 || (value << 1) == 512) { + settings->userDownscaleFactor = 2; + } else if ((value << 2) == 480 || (value << 2) == 512) { + settings->userDownscaleFactor = 4; + } + settings->userFramelength = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; } - break; + } + break; case AACENC_SBR_RATIO: - if (settings->userSbrRatio != value) { - if (! ((value==0) || (value==1) || (value==2)) ) { - err = AACENC_INVALID_CONFIG; - break; - } - settings->userSbrRatio = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + if (settings->userSbrRatio != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; } - break; + settings->userSbrRatio = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; case AACENC_SBR_MODE: - if (settings->userSbrEnabled != value) { - settings->userSbrEnabled = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; - } - break; + if ((settings->userSbrEnabled != value) && + (NULL != hAacEncoder->hEnvEnc)) { + 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; + 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; } - 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; + if (settings->userTpSignaling != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; } - 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; + if (settings->userTpProtection != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; } - 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; + if (settings->userTpHeaderPeriod != value) { + if (!(((INT)value >= 0) && (value <= 255))) { + err = AACENC_INVALID_CONFIG; + break; } - break; + settings->userTpHeaderPeriod = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; case AACENC_AUDIOMUXVER: - if (settings->userTpAmxv != value) { - if ( !((value==0) || (value==1) || (value==2)) ) { - err = AACENC_INVALID_CONFIG; - break; - } - settings->userTpAmxv = value; - hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + if (settings->userTpAmxv != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; } - break; + settings->userTpAmxv = 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; + if (settings->userTpNsubFrames != value) { + if (!((value >= 1) && (value <= 4))) { + err = AACENC_INVALID_CONFIG; + break; } - break; + settings->userTpNsubFrames = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; case AACENC_ANCILLARY_BITRATE: - if (settings->userAncDataRate != value) { - settings->userAncDataRate = value; - } - break; + 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; + if (hAacEncoder->InitFlags != value) { + if (value & AACENC_RESET_INBUFFER) { + hAacEncoder->nSamplesRead = 0; } - break; + hAacEncoder->InitFlags = value; + } + break; case AACENC_METADATA_MODE: - if ((UINT)settings->userMetaDataMode != value) { - if ( !(((INT)value>=0) && ((INT)value<=2)) ) { - err = AACENC_INVALID_CONFIG; - break; - } - settings->userMetaDataMode = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + if ((UINT)settings->userMetaDataMode != value) { + if (!(((INT)value >= 0) && ((INT)value <= 3))) { + err = AACENC_INVALID_CONFIG; + break; } - break; + settings->userMetaDataMode = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; case AACENC_PEAK_BITRATE: - if (settings->userPeakBitrate != value) { - settings->userPeakBitrate = value; - hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; - } - break; + if (settings->userPeakBitrate != value) { + settings->userPeakBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; default: err = AACENC_UNSUPPORTED_PARAMETER; break; - } /* switch(param) */ + } /* switch(param) */ bail: - return err; + return err; } -UINT aacEncoder_GetParam( - const HANDLE_AACENCODER hAacEncoder, - const AACENC_PARAM param - ) -{ - UINT value = 0; - USER_PARAM *settings = &hAacEncoder->extParam; +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; - } + /* check encoder handle */ + if (hAacEncoder == NULL) { + goto bail; + } - /* apply param value */ - switch (param) - { + /* apply param value */ + switch (param) { case AACENC_AOT: - value = (UINT)hAacEncoder->aacConfig.audioObjectType; - break; + value = (UINT)hAacEncoder->aacConfig.audioObjectType; + break; case AACENC_BITRATE: - value = (UINT)((hAacEncoder->aacConfig.bitrateMode==AACENC_BR_MODE_CBR) ? hAacEncoder->aacConfig.bitRate : -1); - break; + switch (hAacEncoder->aacConfig.bitrateMode) { + case AACENC_BR_MODE_CBR: + value = (UINT)hAacEncoder->aacConfig.bitRate; + break; + default: + value = (UINT)-1; + } + break; case AACENC_BITRATEMODE: - value = (UINT)hAacEncoder->aacConfig.bitrateMode; - break; + value = (UINT)((hAacEncoder->aacConfig.bitrateMode != AACENC_BR_MODE_FF) + ? hAacEncoder->aacConfig.bitrateMode + : AACENC_BR_MODE_CBR); + break; case AACENC_SAMPLERATE: - value = (UINT)hAacEncoder->coderConfig.extSamplingRate; - break; + value = (UINT)hAacEncoder->coderConfig.extSamplingRate; + break; case AACENC_CHANNELMODE: + if ((MODE_1 == hAacEncoder->aacConfig.channelMode) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + value = MODE_212; + } else { value = (UINT)hAacEncoder->aacConfig.channelMode; - break; + } + break; case AACENC_BANDWIDTH: - value = (UINT)hAacEncoder->aacConfig.bandWidth; - break; + value = (UINT)hAacEncoder->aacConfig.bandWidth; + break; case AACENC_CHANNELORDER: - value = (UINT)hAacEncoder->aacConfig.channelOrder; - break; + value = (UINT)hAacEncoder->aacConfig.channelOrder; + break; case AACENC_AFTERBURNER: - value = (UINT)hAacEncoder->aacConfig.useRequant; - break; + value = (UINT)hAacEncoder->aacConfig.useRequant; + break; case AACENC_GRANULE_LENGTH: - value = (UINT)hAacEncoder->aacConfig.framelength; - break; + value = (UINT)hAacEncoder->aacConfig.framelength; + break; case AACENC_SBR_RATIO: - value = isSbrActive(&hAacEncoder->aacConfig) ? hAacEncoder->aacConfig.sbrRatio : 0; - break; + value = isSbrActive(&hAacEncoder->aacConfig) + ? hAacEncoder->aacConfig.sbrRatio + : 0; + break; case AACENC_SBR_MODE: - value = (UINT) (hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0; - break; + value = + (UINT)(hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0; + break; case AACENC_TRANSMUX: - value = (UINT)settings->userTpType; - break; + value = (UINT)settings->userTpType; + break; case AACENC_SIGNALING_MODE: - value = (UINT)getSbrSignalingMode(hAacEncoder->aacConfig.audioObjectType, settings->userTpType, settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio); - break; + value = (UINT)getSbrSignalingMode( + hAacEncoder->aacConfig.audioObjectType, settings->userTpType, + settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio); + break; case AACENC_PROTECTION: - value = (UINT)settings->userTpProtection; - break; + value = (UINT)settings->userTpProtection; + break; case AACENC_HEADER_PERIOD: - value = (UINT)hAacEncoder->coderConfig.headerPeriod; - break; + value = (UINT)hAacEncoder->coderConfig.headerPeriod; + break; case AACENC_AUDIOMUXVER: - value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; - break; + value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; + break; case AACENC_TPSUBFRAMES: - value = (UINT)settings->userTpNsubFrames; - break; + value = (UINT)settings->userTpNsubFrames; + break; case AACENC_ANCILLARY_BITRATE: - value = (UINT)hAacEncoder->aacConfig.anc_Rate; - break; + value = (UINT)hAacEncoder->aacConfig.anc_Rate; + break; case AACENC_CONTROL_STATE: - value = (UINT)hAacEncoder->InitFlags; - break; + value = (UINT)hAacEncoder->InitFlags; + break; case AACENC_METADATA_MODE: - value = (hAacEncoder->metaDataAllowed==0) ? 0 : (UINT)settings->userMetaDataMode; - break; + value = (hAacEncoder->metaDataAllowed == 0) + ? 0 + : (UINT)settings->userMetaDataMode; + break; case AACENC_PEAK_BITRATE: - value = (UINT)-1; /* peak bitrate parameter is meaningless */ - if ( ((INT)hAacEncoder->extParam.userPeakBitrate!=-1) ) { - value = (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, hAacEncoder->aacConfig.bitRate)); /* peak bitrate parameter is in use */ - } - break; + value = (UINT)-1; /* peak bitrate parameter is meaningless */ + if (((INT)hAacEncoder->extParam.userPeakBitrate != -1)) { + value = + (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, + hAacEncoder->aacConfig + .bitRate)); /* peak bitrate parameter is in use */ + } + break; + default: - //err = MPS_INVALID_PARAMETER; + // err = MPS_INVALID_PARAMETER; break; - } /* switch(param) */ + } /* switch(param) */ bail: - return value; + 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; - } +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->nDelay = hAacEncoder->nDelay; + pInfo->nDelayCore = hAacEncoder->nDelayCore; + + /* Get encoder configuration */ + if (aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != + AAC_ENC_OK) { + err = AACENC_INIT_ERROR; + goto bail; + } bail: - return err; + return err; } - |