2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------------------------------------
|
|
|
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
|
|
2013-08-09 02:26:40 +02:00
|
|
|
|
<EFBFBD> Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur F<EFBFBD>rderung der angewandten Forschung e.V.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
1. INTRODUCTION
|
|
|
|
|
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
|
|
|
|
|
the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
|
|
|
|
|
This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
|
|
|
|
|
|
|
|
|
|
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
|
|
|
|
|
audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
|
|
|
|
|
independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
|
|
|
|
|
of the MPEG specifications.
|
|
|
|
|
|
|
|
|
|
Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
|
|
|
|
|
may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
|
|
|
|
|
individually for the purpose of encoding or decoding bit streams in products that are compliant with
|
|
|
|
|
the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
|
|
|
|
|
these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
|
|
|
|
|
software may already be covered under those patent licenses when it is used for those licensed purposes only.
|
|
|
|
|
|
|
|
|
|
Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
|
|
|
|
|
are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
|
|
|
|
|
applications information and documentation.
|
|
|
|
|
|
|
|
|
|
2. COPYRIGHT LICENSE
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted without
|
|
|
|
|
payment of copyright license fees provided that you satisfy the following conditions:
|
|
|
|
|
|
|
|
|
|
You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
|
|
|
|
|
your modifications thereto in source code form.
|
|
|
|
|
|
|
|
|
|
You must retain the complete text of this software license in the documentation and/or other materials
|
|
|
|
|
provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
|
|
|
|
|
You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
|
|
|
|
|
modifications thereto to recipients of copies in binary form.
|
|
|
|
|
|
|
|
|
|
The name of Fraunhofer may not be used to endorse or promote products derived from this library without
|
|
|
|
|
prior written permission.
|
|
|
|
|
|
|
|
|
|
You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
|
|
|
|
|
software or your modifications thereto.
|
|
|
|
|
|
|
|
|
|
Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
|
|
|
|
|
and the date of any change. For modified versions of the FDK AAC Codec, the term
|
|
|
|
|
"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
|
|
|
|
|
"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
|
|
|
|
|
|
|
|
|
|
3. NO PATENT LICENSE
|
|
|
|
|
|
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
|
|
|
|
|
ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
|
|
|
|
|
respect to this software.
|
|
|
|
|
|
|
|
|
|
You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
|
|
|
|
|
by appropriate patent licenses.
|
|
|
|
|
|
|
|
|
|
4. DISCLAIMER
|
|
|
|
|
|
|
|
|
|
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
|
|
|
|
|
"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
|
|
|
|
|
of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
|
|
|
|
|
including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
|
|
|
|
|
or business interruption, however caused and on any theory of liability, whether in contract, strict
|
|
|
|
|
liability, or tort (including negligence), arising in any way out of the use of this software, even if
|
|
|
|
|
advised of the possibility of such damage.
|
|
|
|
|
|
|
|
|
|
5. CONTACT INFORMATION
|
|
|
|
|
|
|
|
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
|
|
|
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
|
|
|
|
Am Wolfsmantel 33
|
|
|
|
|
91058 Erlangen, Germany
|
|
|
|
|
|
|
|
|
|
www.iis.fraunhofer.de/amm
|
|
|
|
|
amm-info@iis.fraunhofer.de
|
|
|
|
|
----------------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**************************** MPEG-4 HE-AAC Encoder *************************
|
|
|
|
|
|
|
|
|
|
Initial author: M. Lohwasser
|
|
|
|
|
contents/description: FDK HE-AAC Encoder interface library functions
|
|
|
|
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "aacenc_lib.h"
|
|
|
|
|
#include "FDK_audio.h"
|
|
|
|
|
#include "aacenc.h"
|
|
|
|
|
|
|
|
|
|
#include "aacEnc_ram.h"
|
|
|
|
|
#include "FDK_core.h" /* FDK_tools versioning info */
|
|
|
|
|
|
|
|
|
|
/* Encoder library info */
|
|
|
|
|
#define AACENCODER_LIB_VL0 3
|
2013-08-09 02:26:40 +02:00
|
|
|
|
#define AACENCODER_LIB_VL1 4
|
2013-08-29 21:24:04 +02:00
|
|
|
|
#define AACENCODER_LIB_VL2 9
|
2012-07-11 19:15:24 +02:00
|
|
|
|
#define AACENCODER_LIB_TITLE "AAC Encoder"
|
|
|
|
|
#define AACENCODER_LIB_BUILD_DATE __DATE__
|
|
|
|
|
#define AACENCODER_LIB_BUILD_TIME __TIME__
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "sbr_encoder.h"
|
|
|
|
|
#include "../src/sbr_ram.h"
|
|
|
|
|
#include "channel_map.h"
|
|
|
|
|
|
|
|
|
|
#include "psy_const.h"
|
|
|
|
|
#include "bitenc.h"
|
|
|
|
|
|
|
|
|
|
#include "tpenc_lib.h"
|
|
|
|
|
|
|
|
|
|
#include "metadata_main.h"
|
|
|
|
|
|
|
|
|
|
#define SBL(fl) (fl/8) /*!< Short block length (hardcoded to 8 short blocks per long block) */
|
|
|
|
|
#define BSLA(fl) (4*SBL(fl)+SBL(fl)/2) /*!< AAC block switching look-ahead */
|
|
|
|
|
#define DELAY_AAC(fl) (fl+BSLA(fl)) /*!< MDCT + blockswitching */
|
2013-08-29 21:24:04 +02:00
|
|
|
|
#define DELAY_AACELD(fl) ((fl)/2) /*!< ELD FB delay (no framing delay included) */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
#define INPUTBUFFER_SIZE (1537+100+2048)
|
|
|
|
|
|
2013-08-09 03:25:28 +02:00
|
|
|
|
#define DEFAULT_HEADER_PERIOD_REPETITION_RATE 10 /*!< Default header repetition rate used in transport library and for SBR header. */
|
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/**
|
|
|
|
|
* Flags to characterize encoder modules to be supported in present instance.
|
|
|
|
|
*/
|
|
|
|
|
enum {
|
|
|
|
|
ENC_MODE_FLAG_AAC = 0x0001,
|
|
|
|
|
ENC_MODE_FLAG_SBR = 0x0002,
|
|
|
|
|
ENC_MODE_FLAG_PS = 0x0004,
|
|
|
|
|
ENC_MODE_FLAG_SAC = 0x0008,
|
|
|
|
|
ENC_MODE_FLAG_META = 0x0010
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
typedef struct {
|
|
|
|
|
AUDIO_OBJECT_TYPE userAOT; /*!< Audio Object Type. */
|
|
|
|
|
UINT userSamplerate; /*!< Sampling frequency. */
|
|
|
|
|
UINT nChannels; /*!< will be set via channelMode. */
|
|
|
|
|
CHANNEL_MODE userChannelMode;
|
|
|
|
|
UINT userBitrate;
|
|
|
|
|
UINT userBitrateMode;
|
|
|
|
|
UINT userBandwidth;
|
|
|
|
|
UINT userAfterburner;
|
|
|
|
|
UINT userFramelength;
|
|
|
|
|
UINT userAncDataRate;
|
|
|
|
|
|
|
|
|
|
UCHAR userTns; /*!< Use TNS coding. */
|
|
|
|
|
UCHAR userPns; /*!< Use PNS coding. */
|
|
|
|
|
UCHAR userIntensity; /*!< Use Intensity coding. */
|
|
|
|
|
|
|
|
|
|
TRANSPORT_TYPE userTpType; /*!< Transport type */
|
|
|
|
|
UCHAR userTpSignaling; /*!< Extension AOT signaling mode. */
|
|
|
|
|
UCHAR userTpNsubFrames; /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1). */
|
|
|
|
|
UCHAR userTpAmxv; /*!< AudioMuxVersion to be used for LATM (default 0). */
|
|
|
|
|
UCHAR userTpProtection;
|
|
|
|
|
UCHAR userTpHeaderPeriod; /*!< Parameter used to configure LATM/LOAS SMC rate. Moreover this parameters is
|
|
|
|
|
used to configure repetition rate of PCE in raw_data_block. */
|
|
|
|
|
|
|
|
|
|
UCHAR userErTools; /*!< Use VCB11, HCR and/or RVLC ER tool. */
|
|
|
|
|
UINT userPceAdditions; /*!< Configure additional bits in PCE. */
|
|
|
|
|
|
|
|
|
|
UCHAR userMetaDataMode; /*!< Meta data library configuration. */
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
UCHAR userSbrEnabled; /*!< Enable SBR for ELD. */
|
|
|
|
|
UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
} USER_PARAM;
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
Structure Definitions
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct AACENCODER
|
|
|
|
|
{
|
|
|
|
|
USER_PARAM extParam;
|
|
|
|
|
CODER_CONFIG coderConfig;
|
|
|
|
|
|
|
|
|
|
/* AAC */
|
|
|
|
|
AACENC_CONFIG aacConfig;
|
|
|
|
|
HANDLE_AAC_ENC hAacEnc;
|
|
|
|
|
|
|
|
|
|
/* SBR */
|
|
|
|
|
HANDLE_SBR_ENCODER hEnvEnc;
|
|
|
|
|
|
|
|
|
|
/* Meta Data */
|
|
|
|
|
HANDLE_FDK_METADATA_ENCODER hMetadataEnc;
|
|
|
|
|
INT metaDataAllowed; /* Signal whether chosen configuration allows metadata. Necessary for delay
|
|
|
|
|
compensation. Metadata mode is a separate parameter. */
|
|
|
|
|
|
|
|
|
|
/* Transport */
|
|
|
|
|
HANDLE_TRANSPORTENC hTpEnc;
|
|
|
|
|
|
|
|
|
|
/* Output */
|
|
|
|
|
UCHAR *outBuffer; /* Internal bitstream buffer */
|
|
|
|
|
INT outBufferInBytes; /* Size of internal bitstream buffer*/
|
|
|
|
|
|
|
|
|
|
/* Input */
|
|
|
|
|
INT_PCM *inputBuffer; /* Internal input buffer. Input source for AAC encoder */
|
|
|
|
|
INT inputBufferOffset; /* Where to write new input samples. */
|
|
|
|
|
|
|
|
|
|
INT nSamplesToRead; /* number of input samples neeeded for encoding one frame */
|
|
|
|
|
INT nSamplesRead; /* number of input samples already in input buffer */
|
|
|
|
|
INT nZerosAppended; /* appended zeros at end of file*/
|
|
|
|
|
INT nDelay; /* encoder delay */
|
|
|
|
|
|
|
|
|
|
AACENC_EXT_PAYLOAD extPayload [MAX_TOTAL_EXT_PAYLOADS];
|
|
|
|
|
/* Extension payload */
|
|
|
|
|
UCHAR extPayloadData [(1)][(6)][MAX_PAYLOAD_SIZE];
|
|
|
|
|
UINT extPayloadSize [(1)][(6)]; /* payload sizes in bits */
|
|
|
|
|
|
|
|
|
|
ULONG InitFlags; /* internal status to treggier re-initialization */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Memory allocation info. */
|
|
|
|
|
INT nMaxAacElements;
|
|
|
|
|
INT nMaxAacChannels;
|
|
|
|
|
INT nMaxSbrElements;
|
|
|
|
|
INT nMaxSbrChannels;
|
|
|
|
|
UINT nMaxSubFrames;
|
|
|
|
|
|
|
|
|
|
UINT encoder_modis;
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
/* Capability flags */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
UINT CAPF_tpEnc;
|
|
|
|
|
|
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig)
|
|
|
|
|
{
|
|
|
|
|
INT sbrUsed = 0;
|
|
|
|
|
|
|
|
|
|
if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS)
|
|
|
|
|
|| (hAacConfig->audioObjectType==AOT_MP2_SBR) || (hAacConfig->audioObjectType==AOT_MP2_PS)
|
|
|
|
|
|| (hAacConfig->audioObjectType==AOT_DABPLUS_SBR) || (hAacConfig->audioObjectType==AOT_DABPLUS_PS)
|
|
|
|
|
|| (hAacConfig->audioObjectType==AOT_DRM_SBR) || (hAacConfig->audioObjectType==AOT_DRM_MPEG_PS) )
|
|
|
|
|
{
|
|
|
|
|
sbrUsed = 1;
|
|
|
|
|
}
|
|
|
|
|
if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && (hAacConfig->syntaxFlags & AC_SBR_PRESENT))
|
|
|
|
|
{
|
|
|
|
|
sbrUsed = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ( sbrUsed );
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType)
|
|
|
|
|
{
|
|
|
|
|
INT psUsed = 0;
|
|
|
|
|
|
|
|
|
|
if ( (audioObjectType==AOT_PS)
|
|
|
|
|
|| (audioObjectType==AOT_MP2_PS)
|
|
|
|
|
|| (audioObjectType==AOT_DABPLUS_PS)
|
|
|
|
|
|| (audioObjectType==AOT_DRM_MPEG_PS) )
|
|
|
|
|
{
|
|
|
|
|
psUsed = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ( psUsed );
|
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
/****************************************************************************
|
|
|
|
|
Allocate Encoder
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
H_ALLOC_MEM (_AacEncoder, AACENCODER)
|
|
|
|
|
C_ALLOC_MEM (_AacEncoder, AACENCODER, 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Map Encoder specific config structures to CODER_CONFIG.
|
|
|
|
|
*/
|
|
|
|
|
static
|
|
|
|
|
void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CONFIG hAacConfig)
|
|
|
|
|
{
|
|
|
|
|
AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT;
|
|
|
|
|
FDKmemclear(cc, sizeof(CODER_CONFIG));
|
|
|
|
|
|
|
|
|
|
cc->flags = 0;
|
|
|
|
|
|
|
|
|
|
/* Map virtual aot to transport aot. */
|
|
|
|
|
switch (hAacConfig->audioObjectType) {
|
|
|
|
|
case AOT_MP2_AAC_LC:
|
|
|
|
|
transport_AOT = AOT_AAC_LC;
|
|
|
|
|
break;
|
|
|
|
|
case AOT_MP2_SBR:
|
|
|
|
|
transport_AOT = AOT_SBR;
|
|
|
|
|
cc->flags |= CC_SBR;
|
|
|
|
|
break;
|
|
|
|
|
case AOT_MP2_PS:
|
|
|
|
|
transport_AOT = AOT_PS;
|
|
|
|
|
cc->flags |= CC_SBR;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
transport_AOT = hAacConfig->audioObjectType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) {
|
|
|
|
|
cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* transport type is usually AAC-LC. */
|
|
|
|
|
if ( (transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS) ) {
|
|
|
|
|
cc->aot = AOT_AAC_LC;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cc->aot = transport_AOT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Configure extension aot. */
|
|
|
|
|
if (extCfg->userTpSignaling==0) {
|
|
|
|
|
cc->extAOT = AOT_NULL_OBJECT; /* implicit */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if ( (extCfg->userTpSignaling==1) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) {
|
|
|
|
|
cc->extAOT = AOT_SBR; /* explicit backward compatible */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cc->extAOT = transport_AOT; /* explicit hierarchical */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cc->extSamplingRate = extCfg->userSamplerate;
|
|
|
|
|
cc->bitRate = hAacConfig->bitRate;
|
|
|
|
|
cc->noChannels = hAacConfig->nChannels;
|
|
|
|
|
cc->flags |= CC_IS_BASELAYER;
|
|
|
|
|
cc->channelMode = hAacConfig->channelMode;
|
|
|
|
|
|
|
|
|
|
cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1)
|
|
|
|
|
? hAacConfig->nSubFrames
|
|
|
|
|
: extCfg->userTpNsubFrames;
|
|
|
|
|
|
|
|
|
|
cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0;
|
|
|
|
|
|
|
|
|
|
if (extCfg->userTpHeaderPeriod!=0xFF) {
|
|
|
|
|
cc->headerPeriod = extCfg->userTpHeaderPeriod;
|
|
|
|
|
}
|
|
|
|
|
else { /* auto-mode */
|
|
|
|
|
switch (extCfg->userTpType) {
|
|
|
|
|
case TT_MP4_ADTS:
|
|
|
|
|
case TT_MP4_LOAS:
|
|
|
|
|
case TT_MP4_LATM_MCP1:
|
2013-08-09 03:25:28 +02:00
|
|
|
|
cc->headerPeriod = DEFAULT_HEADER_PERIOD_REPETITION_RATE;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
cc->headerPeriod = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cc->samplesPerFrame = hAacConfig->framelength;
|
|
|
|
|
cc->samplingRate = hAacConfig->sampleRate;
|
|
|
|
|
|
|
|
|
|
/* Mpeg-4 signaling for transport library. */
|
|
|
|
|
switch ( hAacConfig->audioObjectType ) {
|
|
|
|
|
case AOT_MP2_AAC_LC:
|
|
|
|
|
case AOT_MP2_SBR:
|
|
|
|
|
case AOT_MP2_PS:
|
|
|
|
|
cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */
|
|
|
|
|
//config->userTpSignaling=0;
|
|
|
|
|
cc->extAOT = AOT_NULL_OBJECT;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
cc->flags |= CC_MPEG_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ER-tools signaling. */
|
|
|
|
|
cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0;
|
|
|
|
|
cc->flags |= (hAacConfig->syntaxFlags & AC_ER_HCR) ? CC_HCR : 0;
|
|
|
|
|
cc->flags |= (hAacConfig->syntaxFlags & AC_ER_RVLC) ? CC_RVLC : 0;
|
|
|
|
|
|
|
|
|
|
/* Matrix mixdown coefficient configuration. */
|
|
|
|
|
if ( (extCfg->userPceAdditions&0x1) && (hAacConfig->epConfig==-1)
|
|
|
|
|
&& ((cc->channelMode==MODE_1_2_2)||(cc->channelMode==MODE_1_2_2_1)) )
|
|
|
|
|
{
|
|
|
|
|
cc->matrixMixdownA = ((extCfg->userPceAdditions>>1)&0x3)+1;
|
|
|
|
|
cc->flags |= (extCfg->userPceAdditions>>3)&0x1 ? CC_PSEUDO_SURROUND : 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cc->matrixMixdownA = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Examine buffer descriptor regarding choosen identifier.
|
|
|
|
|
*
|
|
|
|
|
* \param pBufDesc Pointer to buffer descriptor
|
|
|
|
|
* \param identifier Buffer identifier to look for.
|
|
|
|
|
|
|
|
|
|
* \return - Buffer descriptor index.
|
|
|
|
|
* -1, if there is no entry available.
|
|
|
|
|
*/
|
|
|
|
|
static INT getBufDescIdx(
|
|
|
|
|
const AACENC_BufDesc *pBufDesc,
|
|
|
|
|
const AACENC_BufferIdentifier identifier
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
INT i, idx = -1;
|
|
|
|
|
|
|
|
|
|
for (i=0; i<pBufDesc->numBufs; i++) {
|
|
|
|
|
if ( (AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == identifier ) {
|
|
|
|
|
idx = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
Function Declarations
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig,
|
|
|
|
|
USER_PARAM *config)
|
|
|
|
|
{
|
|
|
|
|
/* make reasonable default settings */
|
|
|
|
|
FDKaacEnc_AacInitDefaultConfig (hAacConfig);
|
|
|
|
|
|
|
|
|
|
/* clear confure structure and copy default settings */
|
|
|
|
|
FDKmemclear(config, sizeof(USER_PARAM));
|
|
|
|
|
|
|
|
|
|
/* copy encoder configuration settings */
|
|
|
|
|
config->nChannels = hAacConfig->nChannels;
|
|
|
|
|
config->userAOT = hAacConfig->audioObjectType = AOT_AAC_LC;
|
|
|
|
|
config->userSamplerate = hAacConfig->sampleRate;
|
|
|
|
|
config->userChannelMode = hAacConfig->channelMode;
|
|
|
|
|
config->userBitrate = hAacConfig->bitRate;
|
|
|
|
|
config->userBitrateMode = hAacConfig->bitrateMode;
|
|
|
|
|
config->userBandwidth = hAacConfig->bandWidth;
|
|
|
|
|
config->userTns = hAacConfig->useTns;
|
|
|
|
|
config->userPns = hAacConfig->usePns;
|
|
|
|
|
config->userIntensity = hAacConfig->useIS;
|
|
|
|
|
config->userAfterburner = hAacConfig->useRequant;
|
|
|
|
|
config->userFramelength = (UINT)-1;
|
|
|
|
|
|
|
|
|
|
if (hAacConfig->syntaxFlags & AC_ER_VCB11) {
|
|
|
|
|
config->userErTools |= 0x01;
|
|
|
|
|
}
|
|
|
|
|
if (hAacConfig->syntaxFlags & AC_ER_HCR) {
|
|
|
|
|
config->userErTools |= 0x02;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* initialize transport parameters */
|
|
|
|
|
config->userTpType = TT_UNKNOWN;
|
|
|
|
|
config->userTpAmxv = 0;
|
|
|
|
|
config->userTpSignaling = 0; /* default, implicit signaling */
|
|
|
|
|
config->userTpNsubFrames = 1;
|
|
|
|
|
config->userTpProtection = 0; /* not crc protected*/
|
|
|
|
|
config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */
|
|
|
|
|
config->userPceAdditions = 0; /* no matrix mixdown coefficient */
|
|
|
|
|
config->userMetaDataMode = 0; /* do not embed any meta data info */
|
|
|
|
|
|
|
|
|
|
config->userAncDataRate = 0;
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
/* 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;
|
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
return AAC_ENC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, SBR_ELEMENT_INFO *sbrElInfo, INT bitRate)
|
|
|
|
|
{
|
|
|
|
|
INT codebits = bitRate;
|
|
|
|
|
int el;
|
|
|
|
|
|
|
|
|
|
/* Copy Element info */
|
|
|
|
|
for (el=0; el<channelMapping->nElements; el++) {
|
|
|
|
|
sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0];
|
|
|
|
|
sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1];
|
|
|
|
|
sbrElInfo[el].elType = channelMapping->elInfo[el].elType;
|
|
|
|
|
sbrElInfo[el].bitRate = (INT)(fMultNorm(channelMapping->elInfo[el].relativeBits, (FIXP_DBL)bitRate));
|
|
|
|
|
sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag;
|
|
|
|
|
sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl;
|
|
|
|
|
|
|
|
|
|
codebits -= sbrElInfo[el].bitRate;
|
|
|
|
|
}
|
|
|
|
|
sbrElInfo[0].bitRate += codebits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
INT aacEncoder_LimitBitrate(
|
|
|
|
|
const HANDLE_TRANSPORTENC hTpEnc,
|
|
|
|
|
const INT samplingRate,
|
|
|
|
|
const INT frameLength,
|
|
|
|
|
const INT nChannels,
|
|
|
|
|
const CHANNEL_MODE channelMode,
|
|
|
|
|
INT bitRate,
|
|
|
|
|
const INT nSubFrames,
|
|
|
|
|
const INT sbrActive,
|
2013-08-29 21:24:04 +02:00
|
|
|
|
const INT sbrDownSampleRate,
|
2012-07-11 19:15:24 +02:00
|
|
|
|
const AUDIO_OBJECT_TYPE aot
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
INT coreSamplingRate;
|
|
|
|
|
CHANNEL_MAPPING cm;
|
|
|
|
|
|
|
|
|
|
FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm);
|
|
|
|
|
|
|
|
|
|
if (sbrActive) {
|
2013-08-29 21:24:04 +02:00
|
|
|
|
coreSamplingRate = samplingRate >> (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate-1):1);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
} 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);*/
|
|
|
|
|
}
|
2013-08-09 02:32:50 +02:00
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
/* Limit bit rate in respect to the core coder */
|
|
|
|
|
bitRate = FDKaacEnc_LimitBitrate(
|
|
|
|
|
hTpEnc,
|
|
|
|
|
coreSamplingRate,
|
|
|
|
|
frameLength,
|
|
|
|
|
nChannels,
|
|
|
|
|
cm.nChannelsEff,
|
|
|
|
|
bitRate,
|
|
|
|
|
-1,
|
|
|
|
|
NULL,
|
|
|
|
|
-1,
|
|
|
|
|
nSubFrames
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* Limit bit rate in respect to available SBR modes if active */
|
|
|
|
|
if (sbrActive)
|
|
|
|
|
{
|
2013-08-09 02:57:01 +02:00
|
|
|
|
int numIterations = 0;
|
|
|
|
|
INT initialBitrate, adjustedBitrate;
|
|
|
|
|
initialBitrate = adjustedBitrate = bitRate;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
2013-08-09 02:57:01 +02:00
|
|
|
|
/* Find total bitrate which provides valid configuration for each SBR element. */
|
|
|
|
|
do {
|
|
|
|
|
int e;
|
|
|
|
|
SBR_ELEMENT_INFO sbrElInfo[(6)];
|
|
|
|
|
FDK_ASSERT(cm.nElements <= (6));
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
2013-08-09 02:57:01 +02:00
|
|
|
|
initialBitrate = adjustedBitrate;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
2013-08-09 02:57:01 +02:00
|
|
|
|
/* Get bit rate for each SBR element */
|
|
|
|
|
aacEncDistributeSbrBits(&cm, sbrElInfo, initialBitrate);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
2013-08-09 02:57:01 +02:00
|
|
|
|
for (e=0; e<cm.nElements; e++)
|
2012-07-11 19:15:24 +02:00
|
|
|
|
{
|
2013-08-09 02:57:01 +02:00
|
|
|
|
INT sbrElementBitRateIn, sbrBitRateOut;
|
|
|
|
|
|
|
|
|
|
if (cm.elInfo[e].elType != ID_SCE && cm.elInfo[e].elType != ID_CPE) {
|
|
|
|
|
continue;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
}
|
2013-08-09 02:57:01 +02:00
|
|
|
|
sbrElementBitRateIn = sbrElInfo[e].bitRate;
|
|
|
|
|
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 (sbrElementBitRateIn != sbrBitRateOut) {
|
|
|
|
|
|
|
|
|
|
if (sbrElementBitRateIn < sbrBitRateOut) {
|
|
|
|
|
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));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} /* sbrElementBitRateIn != sbrBitRateOut */
|
|
|
|
|
|
|
|
|
|
} /* elements */
|
|
|
|
|
|
|
|
|
|
numIterations++; /* restrict iteration to worst case of num elements */
|
|
|
|
|
|
|
|
|
|
} while ( (initialBitrate!=adjustedBitrate) && (numIterations<=cm.nElements) );
|
|
|
|
|
|
|
|
|
|
/* Unequal bitrates mean that no reasonable bitrate configuration found. */
|
|
|
|
|
bitRate = (initialBitrate==adjustedBitrate) ? adjustedBitrate : 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDK_ASSERT(bitRate > 0);
|
|
|
|
|
|
|
|
|
|
return bitRate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* \brief Consistency check of given USER_PARAM struct and
|
|
|
|
|
* copy back configuration from public struct into internal
|
|
|
|
|
* encoder configuration struct.
|
|
|
|
|
*
|
|
|
|
|
* \hAacEncoder Internal encoder config which is to be updated
|
|
|
|
|
* \param config User provided config (public struct)
|
|
|
|
|
* \return <EFBFBD>returns always AAC_ENC_OK
|
|
|
|
|
*/
|
|
|
|
|
static
|
|
|
|
|
AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
USER_PARAM *config)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
|
|
|
|
|
/* Get struct pointers. */
|
|
|
|
|
HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig;
|
|
|
|
|
|
|
|
|
|
hAacConfig->nChannels = config->nChannels;
|
|
|
|
|
|
|
|
|
|
/* Encoder settings update. */
|
|
|
|
|
hAacConfig->sampleRate = config->userSamplerate;
|
|
|
|
|
hAacConfig->useTns = config->userTns;
|
|
|
|
|
hAacConfig->usePns = config->userPns;
|
|
|
|
|
hAacConfig->useIS = config->userIntensity;
|
|
|
|
|
hAacConfig->bitRate = config->userBitrate;
|
|
|
|
|
hAacConfig->channelMode = config->userChannelMode;
|
|
|
|
|
hAacConfig->bitrateMode = config->userBitrateMode;
|
|
|
|
|
hAacConfig->bandWidth = config->userBandwidth;
|
|
|
|
|
hAacConfig->useRequant = config->userAfterburner;
|
|
|
|
|
|
|
|
|
|
hAacConfig->audioObjectType = config->userAOT;
|
|
|
|
|
hAacConfig->anc_Rate = config->userAncDataRate;
|
|
|
|
|
hAacConfig->syntaxFlags = 0;
|
|
|
|
|
hAacConfig->epConfig = -1;
|
|
|
|
|
|
|
|
|
|
/* Adapt internal AOT when necessary. */
|
|
|
|
|
switch ( hAacConfig->audioObjectType ) {
|
|
|
|
|
case AOT_MP2_AAC_LC:
|
|
|
|
|
case AOT_MP2_SBR:
|
|
|
|
|
case AOT_MP2_PS:
|
|
|
|
|
hAacConfig->usePns = 0;
|
|
|
|
|
if (config->userTpSignaling!=0) {
|
|
|
|
|
return AACENC_INVALID_CONFIG; /* only implicit signaling allowed */
|
|
|
|
|
}
|
|
|
|
|
case AOT_AAC_LC:
|
|
|
|
|
case AOT_SBR:
|
|
|
|
|
case AOT_PS:
|
|
|
|
|
config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_ADTS;
|
|
|
|
|
hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 1024;
|
2013-08-09 02:32:50 +02:00
|
|
|
|
if (hAacConfig->framelength != 1024) {
|
2012-07-11 19:15:24 +02:00
|
|
|
|
return AACENC_INVALID_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AOT_ER_AAC_LD:
|
|
|
|
|
hAacConfig->epConfig = 0;
|
|
|
|
|
hAacConfig->syntaxFlags |= AC_ER|AC_LD;
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0);
|
|
|
|
|
config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
|
|
|
|
|
hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512;
|
|
|
|
|
if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) {
|
|
|
|
|
return AACENC_INVALID_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AOT_ER_AAC_ELD:
|
|
|
|
|
hAacConfig->epConfig = 0;
|
|
|
|
|
hAacConfig->syntaxFlags |= AC_ER|AC_ELD;
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0);
|
|
|
|
|
hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0);
|
|
|
|
|
config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
|
|
|
|
|
hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512;
|
|
|
|
|
if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) {
|
|
|
|
|
return AACENC_INVALID_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ( hAacConfig->audioObjectType ) {
|
|
|
|
|
case AOT_ER_AAC_LD:
|
|
|
|
|
case AOT_ER_AAC_ELD:
|
|
|
|
|
if (config->userBitrateMode==8) {
|
|
|
|
|
hAacConfig->bitrateMode = 0;
|
|
|
|
|
}
|
|
|
|
|
if (config->userBitrateMode==0) {
|
2013-08-29 02:54:51 +02:00
|
|
|
|
hAacConfig->bitreservoir = 100*config->nChannels; /* default, reduced bitreservoir */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
}
|
|
|
|
|
if (hAacConfig->bitrateMode!=0) {
|
|
|
|
|
return AACENC_INVALID_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
hAacConfig->bitRate = config->userBitrate;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
/* get bitrate in VBR configuration */
|
|
|
|
|
if ( (hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5) ) {
|
|
|
|
|
/* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. */
|
|
|
|
|
hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, hAacConfig->channelMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set default bitrate if no external bitrate declared. */
|
2013-08-29 21:24:04 +02:00
|
|
|
|
if ( (hAacConfig->bitrateMode==0) && (config->userBitrate==(UINT)-1) ) {
|
2012-07-11 19:15:24 +02:00
|
|
|
|
INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff * hAacConfig->sampleRate;
|
2013-08-29 21:24:04 +02:00
|
|
|
|
|
|
|
|
|
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
|
2012-07-11 19:15:24 +02:00
|
|
|
|
{
|
|
|
|
|
hAacConfig->bitRate = bitrate + (bitrate>>1); /* 1.5 bits per sample */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
/* Initialize SBR parameters */
|
|
|
|
|
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 = config->userSbrRatio;
|
|
|
|
|
}
|
|
|
|
|
/* 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
|
|
|
|
|
);
|
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
/* Configure PNS */
|
|
|
|
|
if ( ((hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5)) /* VBR without PNS. */
|
|
|
|
|
|| (hAacConfig->useTns == 0) ) /* TNS required. */
|
|
|
|
|
{
|
|
|
|
|
hAacConfig->usePns = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 21:24:04 +02:00
|
|
|
|
if (hAacConfig->epConfig >= 0) {
|
|
|
|
|
hAacConfig->syntaxFlags |= AC_ER;
|
|
|
|
|
if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) {
|
|
|
|
|
return AACENC_INVALID_CONFIG; /* Cannel config 0 not supported. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( FDKaacEnc_DetermineEncoderMode(&hAacConfig->channelMode, hAacConfig->nChannels) != AAC_ENC_OK) {
|
|
|
|
|
return AACENC_INVALID_CONFIG; /* nChannels doesn't match chMode, this is just a check-up */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (hAacConfig->nChannels > hAacEncoder->nMaxAacChannels)
|
|
|
|
|
|| ( (FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff > hAacEncoder->nMaxSbrChannels) &&
|
|
|
|
|
isSbrActive(hAacConfig) )
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return AACENC_INVALID_CONFIG; /* not enough channels allocated */
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
/* Meta data restriction. */
|
|
|
|
|
switch (hAacConfig->audioObjectType)
|
|
|
|
|
{
|
|
|
|
|
/* Allow metadata support */
|
|
|
|
|
case AOT_AAC_LC:
|
|
|
|
|
case AOT_SBR:
|
2013-08-09 03:32:55 +02:00
|
|
|
|
case AOT_PS:
|
2012-07-11 19:15:24 +02:00
|
|
|
|
hAacEncoder->metaDataAllowed = 1;
|
|
|
|
|
if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) {
|
|
|
|
|
config->userMetaDataMode = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
/* Prohibit metadata support */
|
|
|
|
|
default:
|
|
|
|
|
hAacEncoder->metaDataAllowed = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
INT aacenc_SbrCallback(
|
|
|
|
|
void * self,
|
|
|
|
|
HANDLE_FDK_BITSTREAM hBs,
|
|
|
|
|
const INT sampleRateIn,
|
|
|
|
|
const INT sampleRateOut,
|
|
|
|
|
const INT samplesPerFrame,
|
|
|
|
|
const AUDIO_OBJECT_TYPE coreCodec,
|
|
|
|
|
const MP4_ELEMENT_ID elementID,
|
|
|
|
|
const INT elementIndex
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self;
|
|
|
|
|
|
|
|
|
|
sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
ULONG InitFlags,
|
|
|
|
|
USER_PARAM *config)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
|
|
|
|
|
INT aacBufferOffset = 0;
|
|
|
|
|
HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc;
|
|
|
|
|
HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig;
|
|
|
|
|
|
|
|
|
|
hAacEncoder->nZerosAppended = 0; /* count appended zeros */
|
|
|
|
|
|
|
|
|
|
INT frameLength = hAacConfig->framelength;
|
|
|
|
|
|
|
|
|
|
if ( (InitFlags & AACENC_INIT_CONFIG) )
|
|
|
|
|
{
|
|
|
|
|
CHANNEL_MODE prevChMode = hAacConfig->channelMode;
|
|
|
|
|
|
|
|
|
|
/* Verify settings and update: config -> heAacEncoder */
|
|
|
|
|
if ( (err=FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK ) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
frameLength = hAacConfig->framelength; /* adapt temporal framelength */
|
|
|
|
|
|
|
|
|
|
/* Seamless channel reconfiguration in sbr not fully implemented */
|
|
|
|
|
if ( (prevChMode!=hAacConfig->channelMode) && isSbrActive(hAacConfig) ) {
|
|
|
|
|
InitFlags |= AACENC_INIT_STATES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear input buffer */
|
|
|
|
|
if ( (InitFlags == AACENC_INIT_ALL) ) {
|
|
|
|
|
FDKmemclear(hAacEncoder->inputBuffer, sizeof(INT_PCM)*hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (InitFlags & AACENC_INIT_CONFIG) )
|
|
|
|
|
{
|
|
|
|
|
aacBufferOffset = 0;
|
|
|
|
|
if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) {
|
|
|
|
|
hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength);
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
hAacEncoder->nDelay = DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */
|
|
|
|
|
}
|
|
|
|
|
hAacConfig->ancDataBitRate = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( isSbrActive(hAacConfig) &&
|
|
|
|
|
((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) )
|
|
|
|
|
{
|
|
|
|
|
INT sbrError;
|
|
|
|
|
SBR_ELEMENT_INFO sbrElInfo[(6)];
|
|
|
|
|
CHANNEL_MAPPING channelMapping;
|
2013-08-09 02:57:01 +02:00
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
|
if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode,
|
|
|
|
|
hAacConfig->channelOrder,
|
|
|
|
|
&channelMapping) != AAC_ENC_OK )
|
|
|
|
|
{
|
|
|
|
|
return AACENC_INIT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check return value and if the SBR encoder can handle enough elements */
|
|
|
|
|
if (channelMapping.nElements > (6)) {
|
|
|
|
|
return AACENC_INIT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate);
|
|
|
|
|
|
|
|
|
|
UINT initFlag = 0;
|
|
|
|
|
initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
/* Let the SBR encoder take a look at the configuration and change if required. */
|
|
|
|
|
sbrError = sbrEncoder_Init(
|
|
|
|
|
*hSbrEncoder,
|
|
|
|
|
sbrElInfo,
|
|
|
|
|
channelMapping.nElements,
|
|
|
|
|
hAacEncoder->inputBuffer,
|
|
|
|
|
&hAacConfig->bandWidth,
|
|
|
|
|
&aacBufferOffset,
|
|
|
|
|
&hAacConfig->nChannels,
|
|
|
|
|
&hAacConfig->sampleRate,
|
2013-08-29 21:24:04 +02:00
|
|
|
|
&hAacConfig->sbrRatio,
|
2012-07-11 19:15:24 +02:00
|
|
|
|
&frameLength,
|
2013-08-29 21:24:04 +02:00
|
|
|
|
hAacConfig->audioObjectType,
|
2012-07-11 19:15:24 +02:00
|
|
|
|
&hAacEncoder->nDelay,
|
|
|
|
|
(hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC,
|
2013-08-09 03:25:28 +02:00
|
|
|
|
(config->userTpHeaderPeriod!=0xFF) ? config->userTpHeaderPeriod : DEFAULT_HEADER_PERIOD_REPETITION_RATE,
|
2012-07-11 19:15:24 +02:00
|
|
|
|
initFlag
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* Suppress AOT reconfiguration and check error status. */
|
2013-08-29 21:24:04 +02:00
|
|
|
|
if (sbrError) {
|
2012-07-11 19:15:24 +02:00
|
|
|
|
return AACENC_INIT_SBR_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hAacConfig->nChannels == 1) {
|
|
|
|
|
hAacConfig->channelMode = MODE_1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Never use PNS if SBR is active */
|
|
|
|
|
if ( hAacConfig->usePns ) {
|
|
|
|
|
hAacConfig->usePns = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* estimated bitrate consumed by SBR or PS */
|
|
|
|
|
hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder) ;
|
|
|
|
|
|
|
|
|
|
} /* sbr initialization */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize Transport - Module.
|
|
|
|
|
*/
|
|
|
|
|
if ( (InitFlags & AACENC_INIT_TRANSPORT) )
|
|
|
|
|
{
|
|
|
|
|
UINT flags = 0;
|
|
|
|
|
|
|
|
|
|
FDKaacEnc_MapConfig(&hAacEncoder->coderConfig, config, hAacConfig);
|
|
|
|
|
|
|
|
|
|
/* create flags for transport encoder */
|
|
|
|
|
if (config->userTpAmxv == 1) {
|
|
|
|
|
flags |= TP_FLAG_LATM_AMV;
|
|
|
|
|
}
|
|
|
|
|
/* Clear output buffer */
|
|
|
|
|
FDKmemclear(hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes*sizeof(UCHAR));
|
|
|
|
|
|
|
|
|
|
/* Initialize Bitstream encoder */
|
|
|
|
|
if ( transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes, config->userTpType, &hAacEncoder->coderConfig, flags) != 0) {
|
|
|
|
|
return AACENC_INIT_TP_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} /* transport initialization */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize AAC - Core.
|
|
|
|
|
*/
|
|
|
|
|
if ( (InitFlags & AACENC_INIT_CONFIG) ||
|
|
|
|
|
(InitFlags & AACENC_INIT_STATES) )
|
|
|
|
|
{
|
|
|
|
|
AAC_ENCODER_ERROR err;
|
|
|
|
|
err = FDKaacEnc_Initialize(hAacEncoder->hAacEnc,
|
|
|
|
|
hAacConfig,
|
|
|
|
|
hAacEncoder->hTpEnc,
|
|
|
|
|
(InitFlags & AACENC_INIT_STATES) ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
if (err != AAC_ENC_OK) {
|
|
|
|
|
return AACENC_INIT_AAC_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} /* aac initialization */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize Meta Data - Encoder.
|
|
|
|
|
*/
|
|
|
|
|
if ( hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed!=0) &&
|
|
|
|
|
((InitFlags & AACENC_INIT_CONFIG) ||(InitFlags & AACENC_INIT_STATES)) )
|
|
|
|
|
{
|
|
|
|
|
INT inputDataDelay = DELAY_AAC(hAacConfig->framelength);
|
|
|
|
|
|
|
|
|
|
if ( isSbrActive(hAacConfig) && hSbrEncoder!=NULL) {
|
2013-08-29 21:24:04 +02:00
|
|
|
|
inputDataDelay = hAacConfig->sbrRatio*inputDataDelay + sbrEncoder_GetInputDataDelay(*hSbrEncoder);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( FDK_MetadataEnc_Init(hAacEncoder->hMetadataEnc,
|
|
|
|
|
((InitFlags&AACENC_INIT_STATES) ? 1 : 0),
|
|
|
|
|
config->userMetaDataMode,
|
|
|
|
|
inputDataDelay,
|
|
|
|
|
frameLength,
|
|
|
|
|
config->userSamplerate,
|
|
|
|
|
config->nChannels,
|
|
|
|
|
config->userChannelMode,
|
|
|
|
|
hAacConfig->channelOrder) != 0)
|
|
|
|
|
{
|
|
|
|
|
return AACENC_INIT_META_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update pointer to working buffer.
|
|
|
|
|
*/
|
|
|
|
|
if ( (InitFlags & AACENC_INIT_CONFIG) )
|
|
|
|
|
{
|
|
|
|
|
hAacEncoder->inputBufferOffset = aacBufferOffset;
|
|
|
|
|
|
|
|
|
|
hAacEncoder->nSamplesToRead = frameLength * config->nChannels;
|
|
|
|
|
|
|
|
|
|
/* Make nDelay comparison compatible with config->nSamplesRead */
|
|
|
|
|
hAacEncoder->nDelay *= config->nChannels;
|
|
|
|
|
|
|
|
|
|
} /* parameter changed */
|
|
|
|
|
|
|
|
|
|
return AACENC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncOpen(
|
|
|
|
|
HANDLE_AACENCODER *phAacEncoder,
|
|
|
|
|
const UINT encModules,
|
|
|
|
|
const UINT maxChannels
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
HANDLE_AACENCODER hAacEncoder = NULL;
|
|
|
|
|
|
|
|
|
|
if (phAacEncoder == NULL) {
|
|
|
|
|
err = AACENC_INVALID_HANDLE;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* allocate memory */
|
|
|
|
|
hAacEncoder = Get_AacEncoder();
|
|
|
|
|
|
|
|
|
|
if (hAacEncoder == NULL) {
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDKmemclear(hAacEncoder, sizeof(AACENCODER));
|
|
|
|
|
|
|
|
|
|
/* Specify encoder modules to be allocated. */
|
|
|
|
|
if (encModules==0) {
|
|
|
|
|
hAacEncoder->encoder_modis = ENC_MODE_FLAG_AAC;
|
|
|
|
|
hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR;
|
|
|
|
|
hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS;
|
|
|
|
|
hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* consider SAC and PS module */
|
|
|
|
|
hAacEncoder->encoder_modis = encModules;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Determine max channel configuration. */
|
|
|
|
|
if (maxChannels==0) {
|
|
|
|
|
hAacEncoder->nMaxAacChannels = (6);
|
|
|
|
|
hAacEncoder->nMaxSbrChannels = (6);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
hAacEncoder->nMaxAacChannels = (maxChannels&0x00FF);
|
|
|
|
|
if ( (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) ) {
|
|
|
|
|
hAacEncoder->nMaxSbrChannels = (maxChannels&0xFF00) ? (maxChannels>>8) : hAacEncoder->nMaxAacChannels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (hAacEncoder->nMaxAacChannels>(6)) || (hAacEncoder->nMaxSbrChannels>(6)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
} /* maxChannels==0 */
|
|
|
|
|
|
|
|
|
|
/* Max number of elements could be tuned any more. */
|
|
|
|
|
hAacEncoder->nMaxAacElements = fixMin((6), hAacEncoder->nMaxAacChannels);
|
|
|
|
|
hAacEncoder->nMaxSbrElements = fixMin((6), hAacEncoder->nMaxSbrChannels);
|
|
|
|
|
hAacEncoder->nMaxSubFrames = (1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* In case of memory overlay, allocate memory out of libraries */
|
|
|
|
|
|
|
|
|
|
hAacEncoder->inputBuffer = (INT_PCM*)FDKcalloc(hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE, sizeof(INT_PCM));
|
|
|
|
|
|
|
|
|
|
/* Open SBR Encoder */
|
|
|
|
|
if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) {
|
|
|
|
|
if ( sbrEncoder_Open(&hAacEncoder->hEnvEnc,
|
|
|
|
|
hAacEncoder->nMaxSbrElements,
|
|
|
|
|
hAacEncoder->nMaxSbrChannels,
|
|
|
|
|
(hAacEncoder->encoder_modis&ENC_MODE_FLAG_PS) ? 1 : 0 ) )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
} /* (encoder_modis&ENC_MODE_FLAG_SBR) */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Open Aac Encoder */
|
|
|
|
|
if ( FDKaacEnc_Open(&hAacEncoder->hAacEnc,
|
|
|
|
|
hAacEncoder->nMaxAacElements,
|
|
|
|
|
hAacEncoder->nMaxAacChannels,
|
|
|
|
|
(1)) != AAC_ENC_OK )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{ /* Get bitstream outputbuffer size */
|
|
|
|
|
UINT ld_M;
|
|
|
|
|
for (ld_M=1; (UINT)(1<<ld_M) < (hAacEncoder->nMaxSubFrames*hAacEncoder->nMaxAacChannels*6144)>>3; ld_M++) ;
|
|
|
|
|
hAacEncoder->outBufferInBytes = (1<<ld_M); /* buffer has to be 2^n */
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->outBuffer = GetRam_bsOutbuffer();
|
|
|
|
|
if (OUTPUTBUFFER_SIZE < hAacEncoder->outBufferInBytes ) {
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open Meta Data Encoder */
|
|
|
|
|
if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_META) {
|
|
|
|
|
if ( FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc) )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
} /* (encoder_modis&ENC_MODE_FLAG_META) */
|
|
|
|
|
|
|
|
|
|
/* Open Transport Encoder */
|
|
|
|
|
if ( transportEnc_Open(&hAacEncoder->hTpEnc) != 0 )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_MEMORY_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-08-09 02:57:01 +02:00
|
|
|
|
C_ALLOC_SCRATCH_START(pLibInfo, LIB_INFO, FDK_MODULE_LAST);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
|
|
FDKinitLibInfo( pLibInfo);
|
|
|
|
|
transportEnc_GetLibInfo( pLibInfo );
|
|
|
|
|
|
|
|
|
|
/* Get capabilty flag for transport encoder. */
|
|
|
|
|
hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities( pLibInfo, FDK_TPENC);
|
|
|
|
|
|
|
|
|
|
C_ALLOC_SCRATCH_END(pLibInfo, LIB_INFO, FDK_MODULE_LAST);
|
|
|
|
|
}
|
|
|
|
|
if ( transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, hAacEncoder) != 0 ) {
|
|
|
|
|
err = AACENC_INIT_TP_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize encoder instance with default parameters. */
|
|
|
|
|
aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam);
|
|
|
|
|
|
|
|
|
|
/* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */
|
|
|
|
|
hAacEncoder->coderConfig.headerPeriod = hAacEncoder->extParam.userTpHeaderPeriod;
|
|
|
|
|
|
|
|
|
|
/* All encoder modules have to be initialized */
|
|
|
|
|
hAacEncoder->InitFlags = AACENC_INIT_ALL;
|
|
|
|
|
|
|
|
|
|
/* Return encoder instance */
|
|
|
|
|
*phAacEncoder = hAacEncoder;
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
aacEncClose(&hAacEncoder);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
|
|
|
|
|
if (phAacEncoder == NULL) {
|
|
|
|
|
err = AACENC_INVALID_HANDLE;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*phAacEncoder != NULL) {
|
|
|
|
|
HANDLE_AACENCODER hAacEncoder = *phAacEncoder;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hAacEncoder->inputBuffer!=NULL) {
|
|
|
|
|
FDKfree(hAacEncoder->inputBuffer);
|
|
|
|
|
hAacEncoder->inputBuffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hAacEncoder->outBuffer) {
|
|
|
|
|
FreeRam_bsOutbuffer(&hAacEncoder->outBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hAacEncoder->hEnvEnc) {
|
|
|
|
|
sbrEncoder_Close (&hAacEncoder->hEnvEnc);
|
|
|
|
|
}
|
|
|
|
|
if (hAacEncoder->hAacEnc) {
|
|
|
|
|
FDKaacEnc_Close (&hAacEncoder->hAacEnc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transportEnc_Close(&hAacEncoder->hTpEnc);
|
|
|
|
|
|
|
|
|
|
if (hAacEncoder->hMetadataEnc) {
|
|
|
|
|
FDK_MetadataEnc_Close (&hAacEncoder->hMetadataEnc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Free_AacEncoder(phAacEncoder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncEncode(
|
|
|
|
|
const HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
const AACENC_BufDesc *inBufDesc,
|
|
|
|
|
const AACENC_BufDesc *outBufDesc,
|
|
|
|
|
const AACENC_InArgs *inargs,
|
|
|
|
|
AACENC_OutArgs *outargs
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
INT i, nBsBytes = 0;
|
|
|
|
|
INT outBytes[(1)];
|
|
|
|
|
int nExtensions = 0;
|
|
|
|
|
int ancDataExtIdx = -1;
|
|
|
|
|
|
|
|
|
|
/* deal with valid encoder handle */
|
|
|
|
|
if (hAacEncoder==NULL) {
|
|
|
|
|
err = AACENC_INVALID_HANDLE;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Adjust user settings and trigger reinitialization.
|
|
|
|
|
*/
|
|
|
|
|
if (hAacEncoder->InitFlags!=0) {
|
|
|
|
|
|
|
|
|
|
err = aacEncInit(hAacEncoder,
|
|
|
|
|
hAacEncoder->InitFlags,
|
|
|
|
|
&hAacEncoder->extParam);
|
|
|
|
|
|
|
|
|
|
if (err!=AACENC_OK) {
|
|
|
|
|
/* keep init flags alive! */
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->InitFlags = AACENC_INIT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (outargs!=NULL) {
|
|
|
|
|
FDKmemclear(outargs, sizeof(AACENC_OutArgs));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (outBufDesc!=NULL) {
|
|
|
|
|
for (i=0; i<outBufDesc->numBufs; i++) {
|
|
|
|
|
if (outBufDesc->bufs[i]!=NULL) {
|
|
|
|
|
FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If only encoder handle given, independent (re)initialization can be triggered.
|
|
|
|
|
*/
|
|
|
|
|
if ( (hAacEncoder!=NULL) & (inBufDesc==NULL) && (outBufDesc==NULL) && (inargs==NULL) && (outargs==NULL) ) {
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reset buffer wich signals number of valid bytes in output bitstream buffer */
|
|
|
|
|
FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames*sizeof(INT));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Manage incoming audio samples.
|
|
|
|
|
*/
|
|
|
|
|
if ( (inargs->numInSamples > 0) && (getBufDescIdx(inBufDesc,IN_AUDIO_DATA) != -1) )
|
|
|
|
|
{
|
|
|
|
|
/* Fetch data until nSamplesToRead reached */
|
|
|
|
|
INT idx = getBufDescIdx(inBufDesc,IN_AUDIO_DATA);
|
|
|
|
|
INT newSamples = fixMax(0,fixMin(inargs->numInSamples, hAacEncoder->nSamplesToRead-hAacEncoder->nSamplesRead));
|
|
|
|
|
INT_PCM *pIn = hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead;
|
|
|
|
|
|
|
|
|
|
/* Copy new input samples to internal buffer */
|
|
|
|
|
if (inBufDesc->bufElSizes[idx]==(INT)sizeof(INT_PCM)) {
|
|
|
|
|
FDKmemcpy(pIn, (INT_PCM*)inBufDesc->bufs[idx], newSamples*sizeof(INT_PCM)); /* Fast copy. */
|
|
|
|
|
}
|
|
|
|
|
else if (inBufDesc->bufElSizes[idx]>(INT)sizeof(INT_PCM)) {
|
|
|
|
|
for (i=0; i<newSamples; i++) {
|
|
|
|
|
pIn[i] = (INT_PCM)(((LONG*)inBufDesc->bufs[idx])[i]>>16); /* Convert 32 to 16 bit. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (i=0; i<newSamples; i++) {
|
|
|
|
|
pIn[i] = ((INT_PCM)(((SHORT*)inBufDesc->bufs[idx])[i]))<<16; /* Convert 16 to 32 bit. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->nSamplesRead += newSamples;
|
|
|
|
|
|
|
|
|
|
/* Number of fetched input buffer samples. */
|
|
|
|
|
outargs->numInSamples = newSamples;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* input buffer completely filled ? */
|
|
|
|
|
if (hAacEncoder->nSamplesRead < hAacEncoder->nSamplesToRead)
|
|
|
|
|
{
|
|
|
|
|
/* - eof reached and flushing enabled, or
|
|
|
|
|
- return to main and wait for further incoming audio samples */
|
|
|
|
|
if (inargs->numInSamples==-1)
|
|
|
|
|
{
|
|
|
|
|
if ( (hAacEncoder->nZerosAppended < hAacEncoder->nDelay)
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
int nZeros = hAacEncoder->nSamplesToRead - hAacEncoder->nSamplesRead;
|
|
|
|
|
|
|
|
|
|
FDK_ASSERT(nZeros >= 0);
|
|
|
|
|
|
|
|
|
|
/* clear out until end-of-buffer */
|
|
|
|
|
if (nZeros) {
|
|
|
|
|
FDKmemclear(hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead, sizeof(INT_PCM)*nZeros );
|
|
|
|
|
hAacEncoder->nZerosAppended += nZeros;
|
|
|
|
|
hAacEncoder->nSamplesRead = hAacEncoder->nSamplesToRead;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { /* flushing completed */
|
|
|
|
|
err = AACENC_ENCODE_EOF; /* eof reached */
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { /* inargs->numInSamples!= -1 */
|
|
|
|
|
goto bail; /* not enough samples in input buffer and no flushing enabled */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* init payload */
|
|
|
|
|
FDKmemclear(hAacEncoder->extPayload, sizeof(AACENC_EXT_PAYLOAD) * MAX_TOTAL_EXT_PAYLOADS);
|
|
|
|
|
for (i = 0; i < MAX_TOTAL_EXT_PAYLOADS; i++) {
|
|
|
|
|
hAacEncoder->extPayload[i].associatedChElement = -1;
|
|
|
|
|
}
|
|
|
|
|
FDKmemclear(hAacEncoder->extPayloadData, sizeof(hAacEncoder->extPayloadData));
|
|
|
|
|
FDKmemclear(hAacEncoder->extPayloadSize, sizeof(hAacEncoder->extPayloadSize));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Calculate Meta Data info.
|
|
|
|
|
*/
|
|
|
|
|
if ( (hAacEncoder->hMetadataEnc!=NULL) && (hAacEncoder->metaDataAllowed!=0) ) {
|
|
|
|
|
|
|
|
|
|
const AACENC_MetaData *pMetaData = NULL;
|
|
|
|
|
AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL;
|
|
|
|
|
UINT nMetaDataExtensions = 0;
|
|
|
|
|
INT matrix_mixdown_idx = 0;
|
|
|
|
|
|
|
|
|
|
/* New meta data info available ? */
|
|
|
|
|
if ( getBufDescIdx(inBufDesc,IN_METADATA_SETUP) != -1 ) {
|
|
|
|
|
pMetaData = (AACENC_MetaData*)inBufDesc->bufs[getBufDescIdx(inBufDesc,IN_METADATA_SETUP)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDK_MetadataEnc_Process(hAacEncoder->hMetadataEnc,
|
|
|
|
|
hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset,
|
|
|
|
|
hAacEncoder->nSamplesRead,
|
|
|
|
|
pMetaData,
|
|
|
|
|
&pMetaDataExtPayload,
|
|
|
|
|
&nMetaDataExtensions,
|
|
|
|
|
&matrix_mixdown_idx
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<(INT)nMetaDataExtensions; i++) { /* Get meta data extension payload. */
|
|
|
|
|
hAacEncoder->extPayload[nExtensions++] = pMetaDataExtPayload[i];
|
|
|
|
|
}
|
2013-08-09 03:32:55 +02:00
|
|
|
|
|
|
|
|
|
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)( (1<<3) | ((matrix_mixdown_idx&0x3)<<1) | 1 );
|
2012-07-11 19:15:24 +02:00
|
|
|
|
if (hAacEncoder->extParam.userPceAdditions != pceValue) {
|
|
|
|
|
hAacEncoder->extParam.userPceAdditions = pceValue;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( isSbrActive(&hAacEncoder->aacConfig) ) {
|
|
|
|
|
|
|
|
|
|
INT nPayload = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Encode SBR data.
|
|
|
|
|
*/
|
|
|
|
|
if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc,
|
|
|
|
|
hAacEncoder->inputBuffer,
|
|
|
|
|
hAacEncoder->extParam.nChannels,
|
|
|
|
|
hAacEncoder->extPayloadSize[nPayload],
|
|
|
|
|
hAacEncoder->extPayloadData[nPayload]
|
|
|
|
|
#if defined(EVAL_PACKAGE_SILENCE) || defined(EVAL_PACKAGE_SBR_SILENCE)
|
|
|
|
|
,hAacEncoder->hAacEnc->clearOutput
|
|
|
|
|
#endif
|
|
|
|
|
))
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_ENCODE_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Add SBR extension payload */
|
|
|
|
|
for (i = 0; i < (6); i++) {
|
|
|
|
|
if (hAacEncoder->extPayloadSize[nPayload][i] > 0) {
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].pData = hAacEncoder->extPayloadData[nPayload][i];
|
|
|
|
|
{
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].dataSize = hAacEncoder->extPayloadSize[nPayload][i];
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].associatedChElement = i;
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].dataType = EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set EXT_SBR_DATA_CRC */
|
|
|
|
|
nExtensions++; /* or EXT_SBR_DATA according to configuration. */
|
|
|
|
|
FDK_ASSERT(nExtensions<=MAX_TOTAL_EXT_PAYLOADS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nPayload++;
|
|
|
|
|
}
|
|
|
|
|
} /* sbrEnabled */
|
|
|
|
|
|
|
|
|
|
if ( (inargs->numAncBytes > 0) && ( getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA)!=-1 ) ) {
|
|
|
|
|
INT idx = getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA);
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].dataSize = inargs->numAncBytes * 8;
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].pData = (UCHAR*)inBufDesc->bufs[idx];
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].dataType = EXT_DATA_ELEMENT;
|
|
|
|
|
hAacEncoder->extPayload[nExtensions].associatedChElement = -1;
|
|
|
|
|
ancDataExtIdx = nExtensions; /* store index */
|
|
|
|
|
nExtensions++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Encode AAC - Core.
|
|
|
|
|
*/
|
|
|
|
|
if ( FDKaacEnc_EncodeFrame( hAacEncoder->hAacEnc,
|
|
|
|
|
hAacEncoder->hTpEnc,
|
|
|
|
|
hAacEncoder->inputBuffer,
|
|
|
|
|
outBytes,
|
|
|
|
|
hAacEncoder->extPayload
|
|
|
|
|
) != AAC_ENC_OK )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_ENCODE_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ancDataExtIdx >= 0) {
|
|
|
|
|
outargs->numAncBytes = inargs->numAncBytes - (hAacEncoder->extPayload[ancDataExtIdx].dataSize>>3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* samples exhausted */
|
|
|
|
|
hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Delay balancing buffer handling
|
|
|
|
|
*/
|
|
|
|
|
if (isSbrActive(&hAacEncoder->aacConfig)) {
|
|
|
|
|
sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make bitstream public
|
|
|
|
|
*/
|
|
|
|
|
if (outBufDesc->numBufs>=1) {
|
|
|
|
|
|
|
|
|
|
INT bsIdx = getBufDescIdx(outBufDesc,OUT_BITSTREAM_DATA);
|
|
|
|
|
INT auIdx = getBufDescIdx(outBufDesc,OUT_AU_SIZES);
|
|
|
|
|
|
|
|
|
|
for (i=0,nBsBytes=0; i<hAacEncoder->aacConfig.nSubFrames; i++) {
|
|
|
|
|
nBsBytes += outBytes[i];
|
|
|
|
|
|
|
|
|
|
if (auIdx!=-1) {
|
|
|
|
|
((INT*)outBufDesc->bufs[auIdx])[i] = outBytes[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (bsIdx!=-1) && (outBufDesc->bufSizes[bsIdx]>=nBsBytes) ) {
|
|
|
|
|
FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, sizeof(UCHAR)*nBsBytes);
|
|
|
|
|
outargs->numOutBytes = nBsBytes;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* output buffer too small, can't write valid bitstream */
|
|
|
|
|
err = AACENC_ENCODE_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
if (err == AACENC_ENCODE_ERROR) {
|
|
|
|
|
/* All encoder modules have to be initialized */
|
|
|
|
|
hAacEncoder->InitFlags = AACENC_INIT_ALL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
UINT *size,
|
|
|
|
|
UCHAR *confBuffer)
|
|
|
|
|
{
|
|
|
|
|
FDK_BITSTREAM tmpConf;
|
|
|
|
|
UINT confType;
|
|
|
|
|
UCHAR buf[64];
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
/* Init bit buffer */
|
|
|
|
|
FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER);
|
|
|
|
|
|
|
|
|
|
/* write conf in tmp buffer */
|
|
|
|
|
err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, &tmpConf, &confType);
|
|
|
|
|
|
|
|
|
|
/* copy data to outbuffer: length in bytes */
|
|
|
|
|
FDKbyteAlign(&tmpConf, 0);
|
|
|
|
|
|
|
|
|
|
/* Check buffer size */
|
|
|
|
|
if (FDKgetValidBits(&tmpConf) > ((*size)<<3))
|
|
|
|
|
return AAC_ENC_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
FDKfetchBuffer(&tmpConf, confBuffer, size);
|
|
|
|
|
|
|
|
|
|
if (err != 0)
|
|
|
|
|
return AAC_ENC_UNKNOWN;
|
|
|
|
|
else
|
|
|
|
|
return AAC_ENC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
if (info == NULL) {
|
|
|
|
|
return AACENC_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDK_toolsGetLibInfo( info );
|
|
|
|
|
transportEnc_GetLibInfo( info );
|
|
|
|
|
|
|
|
|
|
sbrEncoder_GetLibInfo( info );
|
|
|
|
|
|
|
|
|
|
/* search for next free tab */
|
|
|
|
|
for (i = 0; i < FDK_MODULE_LAST; i++) {
|
|
|
|
|
if (info[i].module_id == FDK_NONE) break;
|
|
|
|
|
}
|
|
|
|
|
if (i == FDK_MODULE_LAST) {
|
|
|
|
|
return AACENC_INIT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info[i].module_id = FDK_AACENC;
|
|
|
|
|
info[i].build_date = (char*)AACENCODER_LIB_BUILD_DATE;
|
|
|
|
|
info[i].build_time = (char*)AACENCODER_LIB_BUILD_TIME;
|
|
|
|
|
info[i].title = (char*)AACENCODER_LIB_TITLE;
|
|
|
|
|
info[i].version = LIB_VERSION(AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2);;
|
|
|
|
|
LIB_VERSION_STRING(&info[i]);
|
|
|
|
|
|
|
|
|
|
/* Capability flags */
|
|
|
|
|
info[i].flags = 0
|
|
|
|
|
| CAPF_AAC_1024 | CAPF_AAC_LC
|
|
|
|
|
| CAPF_AAC_512
|
|
|
|
|
| CAPF_AAC_480
|
|
|
|
|
| CAPF_AAC_DRC
|
|
|
|
|
;
|
|
|
|
|
/* End of flags */
|
|
|
|
|
|
|
|
|
|
return AACENC_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncoder_SetParam(
|
|
|
|
|
const HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
const AACENC_PARAM param,
|
|
|
|
|
const UINT value
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
USER_PARAM *settings = &hAacEncoder->extParam;
|
|
|
|
|
|
|
|
|
|
/* check encoder handle */
|
|
|
|
|
if (hAacEncoder == NULL) {
|
|
|
|
|
err = AACENC_INVALID_HANDLE;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* apply param value */
|
|
|
|
|
switch (param)
|
|
|
|
|
{
|
|
|
|
|
case AACENC_AOT:
|
|
|
|
|
if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) {
|
|
|
|
|
/* check if AOT matches the allocated modules */
|
|
|
|
|
switch ( value ) {
|
|
|
|
|
case AOT_PS:
|
|
|
|
|
case AOT_MP2_PS:
|
|
|
|
|
if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
case AOT_SBR:
|
|
|
|
|
case AOT_MP2_SBR:
|
|
|
|
|
if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
case AOT_AAC_LC:
|
|
|
|
|
case AOT_MP2_AAC_LC:
|
|
|
|
|
case AOT_ER_AAC_LD:
|
|
|
|
|
case AOT_ER_AAC_ELD:
|
|
|
|
|
if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
goto bail;
|
|
|
|
|
}/* switch value */
|
|
|
|
|
settings->userAOT = (AUDIO_OBJECT_TYPE)value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BITRATE:
|
|
|
|
|
if (settings->userBitrate != value) {
|
|
|
|
|
settings->userBitrate = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BITRATEMODE:
|
|
|
|
|
if (settings->userBitrateMode != value) {
|
|
|
|
|
switch ( value ) {
|
|
|
|
|
case 0:
|
|
|
|
|
case 8:
|
|
|
|
|
settings->userBitrateMode = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
} /* switch value */
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_SAMPLERATE:
|
|
|
|
|
if (settings->userSamplerate != value) {
|
|
|
|
|
if ( !( (value==8000) || (value==11025) || (value==12000) || (value==16000) || (value==22050) || (value==24000) ||
|
|
|
|
|
(value==32000) || (value==44100) || (value==48000) || (value==64000) || (value==88200) || (value==96000) ) )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userSamplerate = value;
|
|
|
|
|
hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_CHANNELMODE:
|
|
|
|
|
if (settings->userChannelMode != (CHANNEL_MODE)value) {
|
|
|
|
|
const CHANNEL_MODE_CONFIG_TAB* pConfig = FDKaacEnc_GetChannelModeConfiguration((CHANNEL_MODE)value);
|
|
|
|
|
if (pConfig==NULL) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( (pConfig->nElements > hAacEncoder->nMaxAacElements)
|
|
|
|
|
|| (pConfig->nChannelsEff > hAacEncoder->nMaxAacChannels)
|
|
|
|
|
|| !((value>=1) && (value<=6))
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings->userChannelMode = (CHANNEL_MODE)value;
|
|
|
|
|
settings->nChannels = pConfig->nChannels;
|
|
|
|
|
hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BANDWIDTH:
|
|
|
|
|
if (settings->userBandwidth != value) {
|
|
|
|
|
settings->userBandwidth = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_CHANNELORDER:
|
|
|
|
|
if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) {
|
|
|
|
|
if (! ((value==0) || (value==1)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->aacConfig.channelOrder = (CHANNEL_ORDER)value;
|
|
|
|
|
hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_AFTERBURNER:
|
|
|
|
|
if (settings->userAfterburner != value) {
|
|
|
|
|
if (! ((value==0) || (value==1)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userAfterburner = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_GRANULE_LENGTH:
|
|
|
|
|
if (settings->userFramelength != value) {
|
|
|
|
|
switch (value) {
|
|
|
|
|
case 1024:
|
|
|
|
|
case 512:
|
|
|
|
|
case 480:
|
|
|
|
|
settings->userFramelength = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2013-08-29 21:24:04 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
case AACENC_SBR_MODE:
|
|
|
|
|
if (settings->userSbrEnabled != value) {
|
|
|
|
|
settings->userSbrEnabled = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_TRANSMUX:
|
|
|
|
|
if (settings->userTpType != (TRANSPORT_TYPE)value) {
|
|
|
|
|
|
|
|
|
|
TRANSPORT_TYPE type = (TRANSPORT_TYPE)value;
|
|
|
|
|
UINT flags = hAacEncoder->CAPF_tpEnc;
|
|
|
|
|
|
|
|
|
|
if ( !( ((type==TT_MP4_ADIF) && (flags&CAPF_ADIF))
|
|
|
|
|
|| ((type==TT_MP4_ADTS) && (flags&CAPF_ADTS))
|
|
|
|
|
|| ((type==TT_MP4_LATM_MCP0) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS)))
|
|
|
|
|
|| ((type==TT_MP4_LATM_MCP1) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS)))
|
|
|
|
|
|| ((type==TT_MP4_LOAS) && (flags&CAPF_LOAS))
|
|
|
|
|
|| ((type==TT_MP4_RAW) && (flags&CAPF_RAWPACKETS))
|
|
|
|
|
) )
|
|
|
|
|
{
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userTpType = (TRANSPORT_TYPE)value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_SIGNALING_MODE:
|
|
|
|
|
if (settings->userTpSignaling != value) {
|
|
|
|
|
if ( !((value==0) || (value==1) || (value==2)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userTpSignaling = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_PROTECTION:
|
|
|
|
|
if (settings->userTpProtection != value) {
|
|
|
|
|
if ( !((value==0) || (value==1)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userTpProtection = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_HEADER_PERIOD:
|
|
|
|
|
if (settings->userTpHeaderPeriod != value) {
|
|
|
|
|
settings->userTpHeaderPeriod = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_TPSUBFRAMES:
|
|
|
|
|
if (settings->userTpNsubFrames != value) {
|
|
|
|
|
if (! ( (value>=1) && (value<=4) ) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userTpNsubFrames = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_ANCILLARY_BITRATE:
|
|
|
|
|
if (settings->userAncDataRate != value) {
|
|
|
|
|
settings->userAncDataRate = value;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_CONTROL_STATE:
|
|
|
|
|
if (hAacEncoder->InitFlags != value) {
|
|
|
|
|
if (value&AACENC_RESET_INBUFFER) {
|
|
|
|
|
hAacEncoder->nSamplesRead = 0;
|
|
|
|
|
}
|
|
|
|
|
hAacEncoder->InitFlags = value;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_METADATA_MODE:
|
|
|
|
|
if ((UINT)settings->userMetaDataMode != value) {
|
|
|
|
|
if ( !((value>=0) && (value<=2)) ) {
|
|
|
|
|
err = AACENC_INVALID_CONFIG;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
settings->userMetaDataMode = value;
|
|
|
|
|
hAacEncoder->InitFlags |= AACENC_INIT_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
err = AACENC_UNSUPPORTED_PARAMETER;
|
|
|
|
|
break;
|
|
|
|
|
} /* switch(param) */
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT aacEncoder_GetParam(
|
|
|
|
|
const HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
const AACENC_PARAM param
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UINT value = 0;
|
|
|
|
|
USER_PARAM *settings = &hAacEncoder->extParam;
|
|
|
|
|
|
|
|
|
|
/* check encoder handle */
|
|
|
|
|
if (hAacEncoder == NULL) {
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* apply param value */
|
|
|
|
|
switch (param)
|
|
|
|
|
{
|
|
|
|
|
case AACENC_AOT:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.audioObjectType;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BITRATE:
|
|
|
|
|
value = (UINT)((hAacEncoder->aacConfig.bitrateMode==AACENC_BR_MODE_CBR) ? hAacEncoder->aacConfig.bitRate : -1);
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BITRATEMODE:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.bitrateMode;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_SAMPLERATE:
|
2013-08-29 21:24:04 +02:00
|
|
|
|
value = (UINT)hAacEncoder->coderConfig.extSamplingRate;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
break;
|
|
|
|
|
case AACENC_CHANNELMODE:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.channelMode;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_BANDWIDTH:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.bandWidth;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_CHANNELORDER:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.channelOrder;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_AFTERBURNER:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.useRequant;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_GRANULE_LENGTH:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.framelength;
|
|
|
|
|
break;
|
2013-08-29 21:24:04 +02:00
|
|
|
|
case AACENC_SBR_RATIO:
|
|
|
|
|
value = isSbrActive(&hAacEncoder->aacConfig) ? hAacEncoder->aacConfig.sbrRatio : 0;
|
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
case AACENC_SBR_MODE:
|
|
|
|
|
value = (UINT) (hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_TRANSMUX:
|
|
|
|
|
value = (UINT)settings->userTpType;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_SIGNALING_MODE:
|
|
|
|
|
value = (UINT)settings->userTpSignaling;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_PROTECTION:
|
|
|
|
|
value = (UINT)settings->userTpProtection;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_HEADER_PERIOD:
|
|
|
|
|
value = (UINT)hAacEncoder->coderConfig.headerPeriod;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_TPSUBFRAMES:
|
|
|
|
|
value = (UINT)settings->userTpNsubFrames;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_ANCILLARY_BITRATE:
|
|
|
|
|
value = (UINT)hAacEncoder->aacConfig.anc_Rate;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_CONTROL_STATE:
|
|
|
|
|
value = (UINT)hAacEncoder->InitFlags;
|
|
|
|
|
break;
|
|
|
|
|
case AACENC_METADATA_MODE:
|
|
|
|
|
value = (hAacEncoder->metaDataAllowed==0) ? 0 : (UINT)settings->userMetaDataMode;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
//err = MPS_INVALID_PARAMETER;
|
|
|
|
|
break;
|
|
|
|
|
} /* switch(param) */
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AACENC_ERROR aacEncInfo(
|
|
|
|
|
const HANDLE_AACENCODER hAacEncoder,
|
|
|
|
|
AACENC_InfoStruct *pInfo
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
AACENC_ERROR err = AACENC_OK;
|
|
|
|
|
|
|
|
|
|
FDKmemclear(pInfo, sizeof(AACENC_InfoStruct));
|
|
|
|
|
pInfo->confSize = 64; /* pre-initialize */
|
|
|
|
|
|
|
|
|
|
pInfo->maxOutBufBytes = ((hAacEncoder->nMaxAacChannels*6144)+7)>>3;
|
|
|
|
|
pInfo->maxAncBytes = hAacEncoder->aacConfig.maxAncBytesPerAU;
|
|
|
|
|
pInfo->inBufFillLevel = hAacEncoder->nSamplesRead/hAacEncoder->extParam.nChannels;
|
|
|
|
|
pInfo->inputChannels = hAacEncoder->extParam.nChannels;
|
|
|
|
|
pInfo->frameLength = hAacEncoder->nSamplesToRead/hAacEncoder->extParam.nChannels;
|
|
|
|
|
pInfo->encoderDelay = hAacEncoder->nDelay/hAacEncoder->extParam.nChannels;
|
|
|
|
|
|
|
|
|
|
/* Get encoder configuration */
|
|
|
|
|
if ( aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != AAC_ENC_OK) {
|
|
|
|
|
err = AACENC_INIT_ERROR;
|
|
|
|
|
goto bail;
|
|
|
|
|
}
|
|
|
|
|
bail:
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|