Commit dbf96806 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi

Encoder explicit signaling

* AAC-Encoder

   - Revise explicit signaling method which is required for downsampled SBR.
     The parameter is optional and default configuration is implicit signaling
     for dualrate SBR as before. In case of downsampled SBR and HE-AAC explicit
     signaling is configured as default.
     Modified file(s):
        documentation\aacEncoder.pdf
        libAACenc\include\aacenc_lib.h
        libAACenc\src\aacenc_lib.cpp
        libMpegTPEnc\src\tpenc_asc.cpp
        libMpegTPEnc\src\version
        libSYS\include\FDK_audio.h
        libSYS\src\genericStds.cpp

Bug 9428126

Change-Id: I35138140346f17384d109ee5829be9ea5bab80fc
parent 3aec97e3
...@@ -938,14 +938,50 @@ typedef enum ...@@ -938,14 +938,50 @@ typedef enum
- n: Frame count period. */ - n: Frame count period. */
AACENC_SIGNALING_MODE = 0x0302, /*!< Signaling mode of the extension AOT: AACENC_SIGNALING_MODE = 0x0302, /*!< Signaling mode of the extension AOT:
- 0: Implicit backward compatible signaling. (default) - 0: Implicit backward compatible signaling (default for non-MPEG-4 based
- 1: Explicit SBR and implicit PS signaling. AOT's and for the transport formats ADIF and ADTS)
- 2: Explicit hierarchical signaling. - A stream that uses implicit signaling can be decoded by every AAC decoder, even AAC-LC-only decoders
- An AAC-LC-only decoder will only decode the low-frequency part of the stream, resulting in a band-limited output
The use of backward-compatible implicit signaling is recommended if the user specically - This method works with all transport formats
aims at preserving compatibility with decoders only capable of decoding AAC-LC. Otherwise - This method does not work with downsampled SBR
use non-backward-compatible explicit signaling. - 1: Explicit backward compatible signaling
Bitstream formats ADTS and ADIF can only do implicit signaling. */ - A stream that uses explicit backward compatible signaling can be decoded by every AAC decoder, even AAC-LC-only decoders
- An AAC-LC-only decoder will only decode the low-frequency part of the stream, resulting in a band-limited output
- A decoder not capable of decoding PS will only decode the AAC-LC+SBR part.
If the stream contained PS, the result will be a a decoded mono downmix
- This method does not work with ADIF or ADTS. For LOAS/LATM, it only works with AudioMuxVersion==1
- This method does work with downsampled SBR
- 2: Explicit hierarchical signaling (default for MPEG-4 based AOT's and for all transport formats excluding ADIF and ADTS)
- A stream that uses explicit hierarchical signaling can be decoded only by HE-AAC decoders
- An AAC-LC-only decoder will not decode a stream that uses explicit hierarchical signaling
- A decoder not capable of decoding PS will not decode the stream at all if it contained PS
- This method does not work with ADIF or ADTS. It works with LOAS/LATM and the MPEG-4 File format
- This method does work with downsampled SBR
For making sure that the listener always experiences the best audio quality,
explicit hierarchical signaling should be used.
This makes sure that only a full HE-AAC-capable decoder will decode those streams.
The audio is played at full bandwidth.
For best backwards compatibility, it is recommended to encode with implicit SBR signaling.
A decoder capable of AAC-LC only will then only decode the AAC part, which means the decoded
audio will sound band-limited.
For MPEG-2 transport types (ADTS,ADIF), only implicit signaling is possible.
For LOAS and LATM, explicit backwards compatible signaling only works together with AudioMuxVersion==1.
The reason is that, for explicit backwards compatible signaling, additional information will be appended to the ASC.
A decoder that is only capable of decoding AAC-LC will skip this part.
Nevertheless, for jumping to the end of the ASC, it needs to know the ASC length.
Transmitting the length of the ASC is a feature of AudioMuxVersion==1, it is not possible to transmit the
length of the ASC with AudioMuxVersion==0, therefore an AAC-LC-only decoder will not be able to parse a
LOAS/LATM stream that was being encoded with AudioMuxVersion==0.
For downsampled SBR, explicit signaling is mandatory. The reason for this is that the
extension sampling frequency (which is in case of SBR the sampling frequqncy of the SBR part)
can only be signaled in explicit mode.
For AAC-ELD, the SBR information is transmitted in the ELDSpecific Config, which is part of the
AudioSpecificConfig. Therefore, the settings here will have no effect on AAC-ELD.*/
AACENC_TPSUBFRAMES = 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1). AACENC_TPSUBFRAMES = 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1).
- ADTS: Maximum number of sub frames restricted to 4. - ADTS: Maximum number of sub frames restricted to 4.
......
...@@ -98,7 +98,7 @@ amm-info@iis.fraunhofer.de ...@@ -98,7 +98,7 @@ amm-info@iis.fraunhofer.de
/* Encoder library info */ /* Encoder library info */
#define AACENCODER_LIB_VL0 3 #define AACENCODER_LIB_VL0 3
#define AACENCODER_LIB_VL1 4 #define AACENCODER_LIB_VL1 4
#define AACENCODER_LIB_VL2 9 #define AACENCODER_LIB_VL2 10
#define AACENCODER_LIB_TITLE "AAC Encoder" #define AACENCODER_LIB_TITLE "AAC Encoder"
#define AACENCODER_LIB_BUILD_DATE __DATE__ #define AACENCODER_LIB_BUILD_DATE __DATE__
#define AACENCODER_LIB_BUILD_TIME __TIME__ #define AACENCODER_LIB_BUILD_TIME __TIME__
...@@ -270,6 +270,56 @@ static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) ...@@ -270,6 +270,56 @@ static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType)
return ( psUsed ); return ( psUsed );
} }
static SBR_PS_SIGNALING getSbrSignalingMode(
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) {
sbrSignaling = SIG_UNKNOWN; /* Needed parameters have not been set */
return sbrSignaling;
} else {
sbrSignaling = SIG_IMPLICIT; /* default: implicit signaling */
}
if ((audioObjectType==AOT_AAC_LC) || (audioObjectType==AOT_SBR) || (audioObjectType==AOT_PS) ||
(audioObjectType==AOT_MP2_AAC_LC) || (audioObjectType==AOT_MP2_SBR) || (audioObjectType==AOT_MP2_PS) ) {
switch (transportType) {
case TT_MP4_ADIF:
case TT_MP4_ADTS:
sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only implicit signaling is possible */
break;
case TT_MP4_RAW:
case TT_MP4_LATM_MCP1:
case TT_MP4_LATM_MCP0:
case TT_MP4_LOAS:
default:
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 */
}
} else {
/* User set parameters */
/* Attention: Backward compatible explicit signaling does only work with AMV1 for LATM/LOAS */
sbrSignaling = (SBR_PS_SIGNALING)transportSignaling;
}
break;
}
}
return sbrSignaling;
}
/**************************************************************************** /****************************************************************************
Allocate Encoder Allocate Encoder
****************************************************************************/ ****************************************************************************/
...@@ -283,8 +333,12 @@ C_ALLOC_MEM (_AacEncoder, AACENCODER, 1) ...@@ -283,8 +333,12 @@ C_ALLOC_MEM (_AacEncoder, AACENCODER, 1)
/* /*
* Map Encoder specific config structures to CODER_CONFIG. * Map Encoder specific config structures to CODER_CONFIG.
*/ */
static static void FDKaacEnc_MapConfig(
void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CONFIG hAacConfig) 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; AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT;
FDKmemclear(cc, sizeof(CODER_CONFIG)); FDKmemclear(cc, sizeof(CODER_CONFIG));
...@@ -321,17 +375,26 @@ void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CON ...@@ -321,17 +375,26 @@ void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CON
} }
/* Configure extension aot. */ /* Configure extension aot. */
if (extCfg->userTpSignaling==0) { if (sbrSignaling==SIG_IMPLICIT) {
cc->extAOT = AOT_NULL_OBJECT; /* implicit */ cc->extAOT = AOT_NULL_OBJECT; /* implicit */
} }
else { else {
if ( (extCfg->userTpSignaling==1) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) { if ( (sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) {
cc->extAOT = AOT_SBR; /* explicit backward compatible */ cc->extAOT = AOT_SBR; /* explicit backward compatible */
} }
else { else {
cc->extAOT = transport_AOT; /* explicit hierarchical */ 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;
}
}
cc->sbrSignaling = sbrSignaling;
cc->extSamplingRate = extCfg->userSamplerate; cc->extSamplingRate = extCfg->userSamplerate;
cc->bitRate = hAacConfig->bitRate; cc->bitRate = hAacConfig->bitRate;
cc->noChannels = hAacConfig->nChannels; cc->noChannels = hAacConfig->nChannels;
...@@ -368,7 +431,6 @@ void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CON ...@@ -368,7 +431,6 @@ void FDKaacEnc_MapConfig(CODER_CONFIG *cc, USER_PARAM *extCfg, HANDLE_AACENC_CON
case AOT_MP2_SBR: case AOT_MP2_SBR:
case AOT_MP2_PS: case AOT_MP2_PS:
cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */ cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */
//config->userTpSignaling=0;
cc->extAOT = AOT_NULL_OBJECT; cc->extAOT = AOT_NULL_OBJECT;
break; break;
default: default:
...@@ -428,7 +490,7 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, ...@@ -428,7 +490,7 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig,
/* make reasonable default settings */ /* make reasonable default settings */
FDKaacEnc_AacInitDefaultConfig (hAacConfig); FDKaacEnc_AacInitDefaultConfig (hAacConfig);
/* clear confure structure and copy default settings */ /* clear configuration structure and copy default settings */
FDKmemclear(config, sizeof(USER_PARAM)); FDKmemclear(config, sizeof(USER_PARAM));
/* copy encoder configuration settings */ /* copy encoder configuration settings */
...@@ -455,7 +517,7 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, ...@@ -455,7 +517,7 @@ AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig,
/* initialize transport parameters */ /* initialize transport parameters */
config->userTpType = TT_UNKNOWN; config->userTpType = TT_UNKNOWN;
config->userTpAmxv = 0; config->userTpAmxv = 0;
config->userTpSignaling = 0; /* default, implicit signaling */ config->userTpSignaling = 0xFF; /* choose signaling automatically */
config->userTpNsubFrames = 1; config->userTpNsubFrames = 1;
config->userTpProtection = 0; /* not crc protected*/ config->userTpProtection = 0; /* not crc protected*/
config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */ config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */
...@@ -651,9 +713,6 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, ...@@ -651,9 +713,6 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
case AOT_MP2_SBR: case AOT_MP2_SBR:
case AOT_MP2_PS: case AOT_MP2_PS:
hAacConfig->usePns = 0; hAacConfig->usePns = 0;
if (config->userTpSignaling!=0) {
return AACENC_INVALID_CONFIG; /* only implicit signaling allowed */
}
case AOT_AAC_LC: case AOT_AAC_LC:
case AOT_SBR: case AOT_SBR:
case AOT_PS: case AOT_PS:
...@@ -681,7 +740,7 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, ...@@ -681,7 +740,7 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0);
hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0);
hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0);
hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0); hAacConfig->syntaxFlags |= ((config->userSbrEnabled==1) ? AC_SBR_PRESENT : 0);
config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS;
hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512; hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512;
if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) { if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) {
...@@ -752,6 +811,26 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, ...@@ -752,6 +811,26 @@ AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
/* SBR ratio has been set by the user, so use it. */ /* SBR ratio has been set by the user, so use it. */
hAacConfig->sbrRatio = config->userSbrRatio; hAacConfig->sbrRatio = config->userSbrRatio;
} }
{
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;
}
}
/* We need the frame length to call aacEncoder_LimitBitrate() */ /* We need the frame length to call aacEncoder_LimitBitrate() */
hAacConfig->bitRate = aacEncoder_LimitBitrate( hAacConfig->bitRate = aacEncoder_LimitBitrate(
NULL, NULL,
...@@ -948,7 +1027,11 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, ...@@ -948,7 +1027,11 @@ static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder,
{ {
UINT flags = 0; UINT flags = 0;
FDKaacEnc_MapConfig(&hAacEncoder->coderConfig, config, hAacConfig); FDKaacEnc_MapConfig(
&hAacEncoder->coderConfig,
config,
getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, config->userTpSignaling, hAacConfig->sbrRatio),
hAacConfig);
/* create flags for transport encoder */ /* create flags for transport encoder */
if (config->userTpAmxv == 1) { if (config->userTpAmxv == 1) {
...@@ -1880,7 +1963,7 @@ UINT aacEncoder_GetParam( ...@@ -1880,7 +1963,7 @@ UINT aacEncoder_GetParam(
value = (UINT)settings->userTpType; value = (UINT)settings->userTpType;
break; break;
case AACENC_SIGNALING_MODE: case AACENC_SIGNALING_MODE:
value = (UINT)settings->userTpSignaling; value = (UINT)getSbrSignalingMode(hAacEncoder->aacConfig.audioObjectType, settings->userTpType, settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio);
break; break;
case AACENC_PROTECTION: case AACENC_PROTECTION:
value = (UINT)settings->userTpProtection; value = (UINT)settings->userTpProtection;
......
...@@ -474,7 +474,7 @@ int transportEnc_writeASC ( ...@@ -474,7 +474,7 @@ int transportEnc_writeASC (
break; break;
} }
if (config->extAOT == AOT_SBR || config->extAOT == AOT_PS) if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent)
writeAot(asc, config->extAOT); writeAot(asc, config->extAOT);
else else
writeAot(asc, config->aot); writeAot(asc, config->aot);
...@@ -492,7 +492,7 @@ int transportEnc_writeASC ( ...@@ -492,7 +492,7 @@ int transportEnc_writeASC (
FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 ); FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 );
if (config->extAOT == AOT_SBR || config->extAOT == AOT_PS) { if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) {
writeSampleRate(asc, config->extSamplingRate); writeSampleRate(asc, config->extSamplingRate);
writeAot(asc, config->aot); writeAot(asc, config->aot);
} }
...@@ -545,6 +545,26 @@ int transportEnc_writeASC ( ...@@ -545,6 +545,26 @@ int transportEnc_writeASC (
break; break;
} }
/* backward compatible explicit signaling of extension AOT */
if (config->sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE)
{
TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN;
if (config->sbrPresent) {
ascExtId=ASCEXT_SBR;
FDKwriteBits( asc, ascExtId, 11 );
writeAot(asc, config->extAOT);
FDKwriteBits( asc, 1, 1 ); /* sbrPresentFlag=1 */
writeSampleRate(asc, config->extSamplingRate);
if (config->psPresent) {
ascExtId=ASCEXT_PS;
FDKwriteBits( asc, ascExtId, 11 );
FDKwriteBits( asc, 1, 1 ); /* psPresentFlag=1 */
}
}
}
/* Make sure all bits are sync'ed */ /* Make sure all bits are sync'ed */
FDKsyncCache( asc ); FDKsyncCache( asc );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* library info */ /* library info */
#define TP_LIB_VL0 2 #define TP_LIB_VL0 2
#define TP_LIB_VL1 3 #define TP_LIB_VL1 3
#define TP_LIB_VL2 1 #define TP_LIB_VL2 2
#define TP_LIB_TITLE "MPEG Transport" #define TP_LIB_TITLE "MPEG Transport"
#define TP_LIB_BUILD_DATE __DATE__ #define TP_LIB_BUILD_DATE __DATE__
#define TP_LIB_BUILD_TIME __TIME__ #define TP_LIB_BUILD_TIME __TIME__
...@@ -272,6 +272,15 @@ typedef enum { ...@@ -272,6 +272,15 @@ typedef enum {
ACT_TOP /* Ts */ ACT_TOP /* Ts */
} AUDIO_CHANNEL_TYPE; } AUDIO_CHANNEL_TYPE;
typedef enum
{
SIG_UNKNOWN = -1,
SIG_IMPLICIT = 0,
SIG_EXPLICIT_BW_COMPATIBLE = 1,
SIG_EXPLICIT_HIERARCHICAL = 2
} SBR_PS_SIGNALING;
/** /**
* Audio Codec flags. * Audio Codec flags.
*/ */
...@@ -334,6 +343,10 @@ typedef struct { ...@@ -334,6 +343,10 @@ typedef struct {
UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */ UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */
UCHAR sbrMode; /**< USAC SBR mode */ UCHAR sbrMode; /**< USAC SBR mode */
SBR_PS_SIGNALING sbrSignaling;/**< 0: implicit signaling, 1: backwards compatible explicit signaling, 2: hierarcical explicit signaling */
UCHAR sbrPresent;
UCHAR psPresent;
} CODER_CONFIG; } CODER_CONFIG;
/** MP4 Element IDs. */ /** MP4 Element IDs. */
......
...@@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de ...@@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de
/* library info */ /* library info */
#define SYS_LIB_VL0 1 #define SYS_LIB_VL0 1
#define SYS_LIB_VL1 3 #define SYS_LIB_VL1 3
#define SYS_LIB_VL2 2 #define SYS_LIB_VL2 3
#define SYS_LIB_TITLE "System Integration Library" #define SYS_LIB_TITLE "System Integration Library"
#define SYS_LIB_BUILD_DATE __DATE__ #define SYS_LIB_BUILD_DATE __DATE__
#define SYS_LIB_BUILD_TIME __TIME__ #define SYS_LIB_BUILD_TIME __TIME__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment