AAC Decoder: support 6.1/7.1 decoded as 5.1

- Add 6.1 and 7.1 channel support including downmixer. Per default the
     decoder creates a 5.1 channel output for all streams with more than six
     encoded channels.
     Modified file(s):
        libPCMutils/include/pcmutils_lib.h
        libPCMutils/src/pcmutils_lib.cpp
        libAACdec/include/aacdecoder_lib.h
        libAACdec/src/aac_rom.h
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aac_ram.cpp
        libAACdec/src/aacdec_drc.cpp
        libAACdec/src/aacdecoder_lib.cpp
        libAACdec/src/aac_rom.cpp
        libAACdec/src/aacdecoder.h
        libSBRdec/include/sbrdecoder.h
        libSBRdec/src/sbrdec_drc.h
        libSBRdec/src/sbrdecoder.cpp
        libSBRdec/src/sbr_ram.cpp
        libSBRdec/src/sbr_ram.h
        libMpegTPDec/include/tp_data.h
        libMpegTPDec/include/tpdec_lib.h
        libMpegTPDec/src/version
        libMpegTPDec/src/tpdec_asc.cpp
        libMpegTPEnc/include/tp_data.h
        libMpegTPEnc/src/version
        libSYS/include/FDK_audio.h
        libSYS/src/genericStds.cpp

   - Fix error concealment modules fade-out/in mechanism.
     Modified file(s):
        libAACdec/src/conceal.cpp

Bug 9428126

Change-Id: I3230bd2072314b730911cd7ec1740e290cb1d254
This commit is contained in:
Jean-Michel Trivi 2013-12-27 16:13:22 -08:00
parent fa3eba1644
commit 47c680c622
25 changed files with 7613 additions and 7630 deletions

File diff suppressed because one or more lines are too long

View File

@ -430,21 +430,58 @@ typedef enum {
typedef enum
{
AAC_PCM_OUTPUT_INTERLEAVED = 0x0000, /*!< PCM output mode (1: interleaved (default); 0: not interleaved). */
AAC_PCM_OUTPUT_CHANNELS = 0x0001, /*!< Number of PCM output channels (if different from encoded audio channels, downmixing or
upmixing is applied). \n
-1: Disable up-/downmixing. The decoder output contains the same number of channels as the
encoded bitstream. \n
1: The decoder performs a mono matrix mix-down if the encoded audio channels are greater
than one. Thus it ouputs always exact one channel. \n
2: The decoder performs a stereo matrix mix-down if the encoded audio channels are greater
than two. If the encoded audio channels are smaller than two the decoder duplicates the
output. Thus it ouputs always exact two channels. \n */
AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals:
0: Leave both signals as they are (default).
1: Create a dual mono output signal from channel 1.
2: Create a dual mono output signal from channel 2.
AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals: \n
0: Leave both signals as they are (default). \n
1: Create a dual mono output signal from channel 1. \n
2: Create a dual mono output signal from channel 2. \n
3: Create a dual mono output signal by mixing both channels (L' = R' = 0.5*Ch1 + 0.5*Ch2). */
AAC_PCM_OUTPUT_CHANNEL_MAPPING = 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: WAV file channel order (default). */
AAC_PCM_MIN_OUTPUT_CHANNELS = 0x0011, /*!< Minimum number of PCM output channels. If higher than the number of encoded audio channels,
a simple channel extension is applied. \n
-1, 0: Disable channel extenstion feature. The decoder output contains the same number of
channels as the encoded bitstream. \n
1: This value is currently needed only together with the mix-down feature. See
::AAC_PCM_MAX_OUTPUT_CHANNELS and note 2 below. \n
2: Encoded mono signals will be duplicated to achieve a 2/0/0.0 channel output
configuration. \n
6: The decoder trys to reorder encoded signals with less than six channels to achieve
a 3/0/2.1 channel output signal. Missing channels will be filled with a zero signal.
If reordering is not possible the empty channels will simply be appended. Only
available if instance is configured to support multichannel output. \n
8: The decoder trys to reorder encoded signals with less than eight channels to
achieve a 3/0/4.1 channel output signal. Missing channels will be filled with a
zero signal. If reordering is not possible the empty channels will simply be
appended. Only available if instance is configured to support multichannel output.\n
NOTE: \n
1. The channel signalling (CStreamInfo::pChannelType and CStreamInfo::pChannelIndices)
will not be modified. Added empty channels will be signalled with channel type
AUDIO_CHANNEL_TYPE::ACT_NONE. \n
2. If the parameter value is greater than that of ::AAC_PCM_MAX_OUTPUT_CHANNELS both will
be set to the same value. \n
3. This parameter does not affect MPEG Surround processing. */
AAC_PCM_MAX_OUTPUT_CHANNELS = 0x0012, /*!< Maximum number of PCM output channels. If lower than the number of encoded audio channels,
downmixing is applied accordingly. If dedicated metadata is available in the stream it
will be used to achieve better mixing results. \n
-1, 0: Disable downmixing feature. The decoder output contains the same number of channels
as the encoded bitstream. \n
1: All encoded audio configurations with more than one channel will be mixed down to
one mono output signal. \n
2: The decoder performs a stereo mix-down if the number encoded audio channels is
greater than two. \n
6: If the number of encoded audio channels is greater than six the decoder performs a
mix-down to meet the target output configuration of 3/0/2.1 channels. Only
available if instance is configured to support multichannel output. \n
8: This value is currently needed only together with the channel extension feature.
See ::AAC_PCM_MIN_OUTPUT_CHANNELS and note 2 below. Only available if instance is
configured to support multichannel output. \n
NOTE: \n
1. Down-mixing of any seven or eight channel configuration not defined in ISO/IEC 14496-3
PDAM 4 is not supported by this software version. \n
2. If the parameter value is greater than zero but smaller than ::AAC_PCM_MIN_OUTPUT_CHANNELS
both will be set to same value. \n
3. The operating mode of the MPEG Surround module will be set accordingly. \n
4. Setting this param with any value will disable the binaural processing of the MPEG
Surround module (::AAC_MPEGS_BINAURAL_ENABLE=0). */
AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n
0: Spectral muting. \n

View File

@ -108,15 +108,15 @@ C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (6))
C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8))
/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
C_ALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (6))
C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8))
/*! Overlap buffer */
C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6))
C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8))
C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
@ -128,7 +128,7 @@ C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
Dynamic memory areas, might be reused in other algorithm sections,
e.g. the sbr decoder
*/
C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((6)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)

View File

@ -1777,42 +1777,62 @@ const FIXP_TCC FDKaacDec_tnsCoeff4 [16] =
};
/* MPEG like mapping (no change). */
const UCHAR channelMappingTablePassthrough[8][8] =
const UCHAR channelMappingTablePassthrough[15][8] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 0, 1, 2,255,255,255,255,255}, /* 3ch */
{ 0, 1, 2, 3,255,255,255,255}, /* 4ch */
{ 0, 1, 2, 3, 4,255,255,255}, /* 5ch */
{ 0, 1, 2, 3, 4, 5,255,255}, /* 5.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
{ 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 front */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6,255}, /* 6.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 rear */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1 top */
};
/* WAV file like mapping (from MPEG mapping). */
const UCHAR channelMappingTableWAV[8][8] =
const UCHAR channelMappingTableWAV[15][8] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 2, 0, 1,255,255,255,255,255}, /* 3ch */
{ 2, 0, 1, 3,255,255,255,255}, /* 4ch */
{ 2, 0, 1, 3, 4,255,255,255}, /* 5ch */
{ 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
{ 2, 0, 1, 6, 7, 4, 5, 3} /* 7.1ch */
{ 2, 6, 7, 0, 1, 4, 5, 3}, /* 7.1 front */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 2, 0, 1, 4, 5, 6, 3,255}, /* 6.1ch */
{ 2, 0, 1, 6, 7, 4, 5, 3}, /* 7.1 rear */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
{ 2, 0, 1, 4, 5, 3, 6, 7} /* 7.1 top */
};
/* Lookup tables for elements in ER bitstream */
const MP4_ELEMENT_ID elementsTab[8][7] =
const MP4_ELEMENT_ID elementsTab[15][7] =
{
{ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE }, /* 1 channel */
{ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE } /* 2 channels */
,
{ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE,ID_NONE }, /* 3 channels */
{ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 4 channels */
{ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 5 channels */
{ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE }, /* 6 channels */
{ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END} /* 8 channels */
/* 1 */ { ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* 1 channel */
/* 2 */ { ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE } /* 2 channels */
/* 3 */ ,{ ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE }, /* 3 channels */
/* 4 */ { ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 4 channels */
/* 5 */ { ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 5 channels */
/* 6 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE } /* 6 channels */
/* 7 */ ,{ ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
/* 8 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
/* 9 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
/* 10 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
/* 11 */ { ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, ID_END }, /* 7 channels */
/* 12 */ { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
/* 13 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
/* 14 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, ID_END } /* 8 channels */
};
/*! Random sign bit used for concealment

View File

@ -177,11 +177,12 @@ extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16];
extern const FIXP_DBL pow2_div24minus1[47];
extern const int offsetTab[2][16];
/* Channel mapping indices for time domain I/O. First dimension is channel count-1. */
extern const UCHAR channelMappingTablePassthrough[8][8];
extern const UCHAR channelMappingTableWAV[8][8];
/* Channel mapping indices for time domain I/O.
The first dimension is the channel configuration index. */
extern const UCHAR channelMappingTablePassthrough[15][8];
extern const UCHAR channelMappingTableWAV[15][8];
/* Lookup tables for elements in ER bitstream */
extern const MP4_ELEMENT_ID elementsTab[8][7];
extern const MP4_ELEMENT_ID elementsTab[15][7];
#endif /* #ifndef AAC_ROM_H */

View File

@ -539,7 +539,7 @@ static int aacDecoder_drcReadCompression (
UINT payloadPosition )
{
int bitCnt = 0;
int dmxLevelsPresent, compressionPresent;
int dmxLevelsPresent, extensionPresent, compressionPresent;
int coarseGrainTcPresent, fineGrainTcPresent;
/* Move to the beginning of the DRC payload field */
@ -562,7 +562,8 @@ static int aacDecoder_drcReadCompression (
}
FDKreadBits(bs, 2); /* dolby_surround_mode */
FDKreadBits(bs, 2); /* presentation_mode */
if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
FDKreadBits(bs, 1); /* stereo_downmix_mode */
if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
return 0;
}
@ -571,9 +572,7 @@ static int aacDecoder_drcReadCompression (
return 0;
}
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
return 0;
}
extensionPresent = FDKreadBits(bs, 1); /* ancillary_data_extension_status; */
compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
@ -631,6 +630,19 @@ static int aacDecoder_drcReadCompression (
bitCnt += 16;
}
/* Read extension just to get the right amount of bits. */
if (extensionPresent) {
int extBits = 8;
FDKreadBits(bs, 1); /* reserved, set to 0 */
if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_levels_status */
if (FDKreadBits(bs, 1)) extBits += 16; /* ext_downmixing_global_gains_status */
if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_lfe_level_status */
FDKpushFor(bs, extBits - 4); /* skip the extension payload remainder. */
bitCnt += extBits;
}
return (bitCnt);
}

View File

@ -338,17 +338,22 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
\return Error code
*/
static AAC_DECODER_ERROR CDataStreamElement_Read (
HANDLE_AACDECODER self,
HANDLE_FDK_BITSTREAM bs,
CAncData *ancData,
HANDLE_AAC_DRC hDrcInfo,
HANDLE_TRANSPORTDEC pTp,
UCHAR *elementInstanceTag,
UINT alignmentAnchor )
{
HANDLE_TRANSPORTDEC pTp;
CAncData *ancData;
AAC_DECODER_ERROR error = AAC_DEC_OK;
UINT dataStart;
UINT dataStart, dseBits;
int dataByteAlignFlag, count;
FDK_ASSERT(self != NULL);
ancData = &self->ancData;
pTp = self->hInput;
int crcReg = transportDec_CrcStartReg(pTp, 0);
/* Element Instance Tag */
@ -361,6 +366,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
if (count == 255) {
count += FDKreadBits(bs,8); /* EscCount */
}
dseBits = count*8;
if (dataByteAlignFlag) {
FDKbyteAlign(bs, alignmentAnchor);
@ -372,20 +378,30 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
{
INT readBits, dataBits = count<<3;
/* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
/* Read Anc data if available */
readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA );
if (readBits != dataBits) {
/* Move to the end again. */
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
}
aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
}
{
PCMDMX_ERROR dmxErr = PCMDMX_OK;
/* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
/* Read DMX meta-data */
dmxErr = pcmDmx_Parse (
self->hPcmUtils,
bs,
dseBits,
0 /* not mpeg2 */ );
}
/* Move to the very end of the element. */
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dseBits);
return error;
}
@ -774,7 +790,7 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
if (self == NULL)
return;
for (ch=0; ch<(6); ch++) {
for (ch=0; ch<(8); ch++) {
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
@ -851,18 +867,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
/* valid number of channels -> copy program config element (PCE) from ASC */
FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
/* Built element table */
el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, 7);
for (; el<7; el++) {
el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, (8), &self->chMapIndex);
for (; el<(8); el++) {
self->elements[el] = ID_NONE;
}
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
} else {
self->chMapIndex = 0;
if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) {
/* set default max_channels for memory allocation because in implicit channel mapping mode
we don't know the actual number of channels until we processed at least one raw_data_block(). */
ascChannels = (6);
ascChannels = (8);
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
@ -874,26 +891,34 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
case 1: case 2: case 3: case 4: case 5: case 6:
ascChannels = asc->m_channelConfiguration;
break;
case 7:
case 11:
ascChannels = 7;
break;
case 7: case 12: case 14:
ascChannels = 8;
break;
default:
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
if (ascChannels > (8)) {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
/* Initialize constant mappings for channel config 1-7 */
if (asc->m_channelConfiguration > 0) {
int el;
FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7));
for (el=7; el<7; el++) {
FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,(8)));
for (el=7; el<(8); el++) {
self->elements[el] = ID_NONE;
}
for (ch=0; ch<ascChannels; ch++) {
self->chMapping[ch] = ch;
}
for (; ch<(6); ch++) {
for (; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
self->chMapIndex = asc->m_channelConfiguration;
}
#ifdef TP_PCE_ENABLE
else {
@ -909,9 +934,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
self->streamInfo.channelConfig = asc->m_channelConfiguration;
if (ascChannels > (6)) {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
if (self->streamInfo.aot != asc->m_aot) {
self->streamInfo.aot = asc->m_aot;
ascChanged = 1;
@ -1096,6 +1118,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
INT aacChannels=0; /* Channel counter for channels found in the bitstream */
int chOutMapIdx; /* Output channel mapping index (see comment below) */
INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */
@ -1119,12 +1142,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->streamInfo.channelConfig == 0) {
/* Init Channel/Element mapping table */
for (ch=0; ch<(6); ch++) {
for (ch=0; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
if (!CProgramConfig_IsValid(pce)) {
int el;
for (el=0; el<7; el++) {
for (el=0; el<(8); el++) {
self->elements[el] = ID_NONE;
}
}
@ -1378,10 +1401,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
{
UCHAR element_instance_tag;
CDataStreamElement_Read( bs,
&self->ancData,
self->hDrcInfo,
self->hInput,
CDataStreamElement_Read( self,
bs,
&element_instance_tag,
auStartAnchor );
@ -1401,29 +1422,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
//self->frameOK = 0;
}
}
{
UCHAR *pDvbAncData = NULL;
AAC_DECODER_ERROR ancErr;
int ancIndex;
int dvbAncDataSize = 0;
/* Ask how many anc data elements are in buffer */
ancIndex = self->ancData.nrElements - 1;
/* Get the last one (if available) */
ancErr = CAacDecoder_AncDataGet( &self->ancData,
ancIndex,
&pDvbAncData,
&dvbAncDataSize );
if (ancErr == AAC_DEC_OK) {
pcmDmx_ReadDvbAncData (
self->hPcmUtils,
pDvbAncData,
dvbAncDataSize,
0 /* not mpeg2 */ );
}
}
break;
#ifdef TP_PCE_ENABLE
@ -1442,9 +1440,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
}
else if ( result > 1 ) {
/* Built element table */
int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
int elIdx = CProgramConfig_GetElementTable(pce, self->elements, (8), &self->chMapIndex);
/* Reset the remaining tabs */
for ( ; elIdx<7; elIdx++) {
for ( ; elIdx<(8); elIdx++) {
self->elements[elIdx] = ID_NONE;
}
/* Make new number of channel persistant */
@ -1632,6 +1630,23 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
return ErrorStatus;
}
/* Setup the output channel mapping. The table below shows the four possibilities:
* # | chCfg | PCE | cChCfg | chOutMapIdx
* ---+-------+-----+--------+------------------
* 1 | > 0 | no | - | chCfg
* 2 | 0 | yes | > 0 | cChCfg
* 3 | 0 | yes | 0 | aacChannels || 0
* 4 | 0 | no | - | aacChannels || 0
* ---+-------+-----+--------+------------------
* Where chCfg is the channel configuration index from ASC and cChCfg is a corresponding chCfg
* derived from a given PCE. The variable aacChannels represents the number of channel found
* during bitstream decoding. Due to the structure of the mapping table it can only be used for
* mapping if its value is smaller than 7. Otherwise we use the fallback (0) which is a simple
* pass-through. The possibility #4 should appear only with MPEG-2 (ADTS) streams. This is
* mode is called "implicit channel mapping".
*/
chOutMapIdx = ((self->chMapIndex==0) && (aacChannels<7)) ? aacChannels : self->chMapIndex;
/*
Inverse transform
*/
@ -1663,10 +1678,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Setup offset and stride for time buffer traversal. */
if (interleaved) {
stride = aacChannels;
offset = self->channelOutputMapping[aacChannels-1][c];
offset = self->channelOutputMapping[chOutMapIdx][c];
} else {
stride = 1;
offset = self->channelOutputMapping[aacChannels-1][c] * self->streamInfo.aacSamplesPerFrame;
offset = self->channelOutputMapping[chOutMapIdx][c] * self->streamInfo.aacSamplesPerFrame;
}
@ -1746,8 +1761,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Reorder channel type information tables. */
{
AUDIO_CHANNEL_TYPE types[(6)];
UCHAR idx[(6)];
AUDIO_CHANNEL_TYPE types[(8)];
UCHAR idx[(8)];
int c;
FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
@ -1757,8 +1772,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(idx, self->channelIndices, sizeof(idx));
for (c=0; c<aacChannels; c++) {
self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c];
self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c];
self->channelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c];
self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c];
}
}

View File

@ -176,22 +176,23 @@ struct AAC_DECODER_INSTANCE {
UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */
MP4_ELEMENT_ID elements[7]; /*!< Table where the element Id's are listed */
UCHAR elTags[7]; /*!< Table where the elements id Tags are listed */
UCHAR chMapping[(6)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
MP4_ELEMENT_ID elements[(8)]; /*!< Table where the element Id's are listed */
UCHAR elTags[(8)]; /*!< Table where the elements id Tags are listed */
UCHAR chMapping[(8)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
AUDIO_CHANNEL_TYPE channelType[(6)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
UCHAR channelIndices[(6)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
/* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
const UCHAR (*channelOutputMapping)[8]; /*!< Table for MPEG canonical order to output channel order mapping. */
UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping table. This is required
because not all 8 channel configurations have the same output mapping. */
CProgramConfig pce;
CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */
CAacDecoderChannelInfo *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */

View File

@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 5
#define AACDECODER_LIB_VL2 5
#define AACDECODER_LIB_VL2 6
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__
@ -420,8 +420,8 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
self->outputInterleaved = value;
break;
case AAC_PCM_OUTPUT_CHANNELS:
if (value < -1 || value > (6)) {
case AAC_PCM_MIN_OUTPUT_CHANNELS:
if (value < -1 || value > (8)) {
return AAC_DEC_SET_PARAM_FAIL;
}
{
@ -429,7 +429,30 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
NUMBER_OF_OUTPUT_CHANNELS,
MIN_NUMBER_OF_OUTPUT_CHANNELS,
value );
switch (err) {
case PCMDMX_OK:
break;
case PCMDMX_INVALID_HANDLE:
return AAC_DEC_INVALID_HANDLE;
default:
return AAC_DEC_SET_PARAM_FAIL;
}
}
break;
case AAC_PCM_MAX_OUTPUT_CHANNELS:
if (value < -1 || value > (8)) {
return AAC_DEC_SET_PARAM_FAIL;
}
{
PCMDMX_ERROR err;
err = pcmDmx_SetParam (
hPcmDmx,
MAX_NUMBER_OF_OUTPUT_CHANNELS,
value );
switch (err) {
@ -449,7 +472,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
DUAL_CHANNEL_DOWNMIX_MODE,
DMX_DUAL_CHANNEL_MODE,
value );
switch (err) {
@ -825,6 +848,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->sbrEnabled)
{
SBR_ERROR sbrError = SBRDEC_OK;
int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex;
/* set params */
sbrDecoder_SetParam ( self->hSbrDecoder,
@ -838,7 +862,16 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
(self->flags & AC_LD_MPS) ? 1 : 0 );
}
{
PCMDMX_ERROR dmxErr;
INT maxOutCh = 0;
dmxErr = pcmDmx_GetParam(self->hPcmUtils, MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh);
if ( (dmxErr == PCMDMX_OK) && (maxOutCh == 1) ) {
/* Disable PS processing if we have to create a mono output signal. */
self->psPossible = 0;
}
}
/* apply SBR processing */
@ -846,7 +879,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
pTimeData,
&self->streamInfo.numChannels,
&self->streamInfo.sampleRate,
self->channelOutputMapping[self->streamInfo.numChannels-1],
self->channelOutputMapping[chOutMapIdx],
interleaved,
self->frameOK,
&self->psPossible);
@ -870,19 +903,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->channelType[1] = ACT_FRONT;
self->channelIndices[0] = 0;
self->channelIndices[1] = 1;
} else {
self->flags &= ~AC_PS_PRESENT;
}
}
}
{
PCMDMX_ERROR dmxErr = PCMDMX_OK;
if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) {
/* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA );
}
/* do PCM post processing */
pcmDmx_ApplyFrame (
dmxErr = pcmDmx_ApplyFrame (
self->hPcmUtils,
pTimeData,
self->streamInfo.frameSize,
@ -890,9 +923,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
interleaved,
self->channelType,
self->channelIndices,
self->channelOutputMapping
self->channelOutputMapping,
NULL
);
if (dmxErr == PCMDMX_INVALID_MODE) {
/* Announce the framework that the current combination of channel configuration and downmix
* settings are not know to produce a predictable behavior and thus maybe produce strange output. */
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
}
/* Signal interruption to take effect in next frame. */

View File

@ -762,7 +762,6 @@ int
CConcealment_UpdateState( hConcealmentInfo,
frameOk );
if ( !frameOk )
{
/* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
@ -775,11 +774,13 @@ int
{
default:
case ConcealMethodMute:
/* Mute spectral data in case of errors */
FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
/* Set last window shape */
pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
appliedProcessing = 1;
if (!frameOk) {
/* Mute spectral data in case of errors */
FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
/* Set last window shape */
pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
appliedProcessing = 1;
}
break;
case ConcealMethodNoise:
@ -801,7 +802,7 @@ int
pSamplingRateInfo,
samplesPerFrame,
0, /* don't use tonal improvement */
0);
frameOk);
break;
}

View File

@ -146,12 +146,15 @@ typedef struct
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
*/
static inline int getNumberOfTotalChannels(int channelConfig)
{
if (channelConfig > 0 && channelConfig < 8)
return (channelConfig == 7)?8:channelConfig;
else
switch (channelConfig) {
case 1: case 2: case 3:
case 4: case 5: case 6:
return channelConfig;
case 7: case 12: case 14:
return 8;
case 11:
return 7;
default:
return 0;
}
}
static inline
int getNumberOfEffectiveChannels(const int channelConfig)
{
const int n[] = {0,1,2,3,4,5,5,7};
{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */
const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
return n[channelConfig];
}

View File

@ -151,6 +151,7 @@ typedef enum {
#define PC_ASSOCDATA_MAX 8
#define PC_CCEL_MAX 16 /* CC elements */
#define PC_COMMENTLENGTH 256
#define PC_NUM_HEIGHT_LAYER 3
/*!
@ -239,14 +240,20 @@ int CProgramConfig_LookupElement(
);
/**
* \brief Get table of elements in canonical order.
* \param pPce A valid program config structure.
* \param table An array where the element IDs are stored.
* \return Total element count including all SCE, CPE and LFE.
* \brief Get table of elements in canonical order from a
* give program config field.
* \param pPce A valid program config structure.
* \param table An array where the element IDs are stored.
* \param elListSize The length of the table array.
* \param pChMapIdx Pointer to a field receiving the corresponding
* implicit channel configuration index of the given
* PCE. If none can be found it receives the value 0.
* \return Total element count including all SCE, CPE and LFE.
*/
int CProgramConfig_GetElementTable( const CProgramConfig *pPce,
MP4_ELEMENT_ID table[],
const INT elListSize );
const INT elListSize,
UCHAR *pChMapIdx );
/**
* \brief Initialize a given AudioSpecificConfig structure.

View File

@ -90,6 +90,9 @@ amm-info@iis.fraunhofer.de
#include "tpdec_lib.h"
#include "tp_data.h"
#ifdef TP_PCE_ENABLE
#include "FDK_crc.h"
#endif
void CProgramConfig_Reset(CProgramConfig *pPce)
@ -111,13 +114,75 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce )
}
#ifdef TP_PCE_ENABLE
#define PCE_HEIGHT_EXT_SYNC ( 0xAC )
/*
* Read the extension for height info.
* return 0 if successfull or -1 if the CRC failed.
*/
static
int CProgramConfig_ReadHeightExt(
CProgramConfig *pPce,
HANDLE_FDK_BITSTREAM bs,
int * const bytesAvailable,
const UINT alignmentAnchor
)
{
int err = 0;
FDK_CRCINFO crcInfo; /* CRC state info */
INT crcReg;
FDKcrcInit(&crcInfo, 0x07, 0xFF, 8);
crcReg = FDKcrcStartReg(&crcInfo, bs, 0);
UINT startAnchor = FDKgetValidBits(bs);
FDK_ASSERT(pPce != NULL);
FDK_ASSERT(bs != NULL);
FDK_ASSERT(bytesAvailable != NULL);
if ( (startAnchor >= 24) && (*bytesAvailable >= 3)
&& (FDKreadBits(bs,8) == PCE_HEIGHT_EXT_SYNC) )
{
int i;
for (i=0; i < pPce->NumFrontChannelElements; i++)
{
pPce->FrontElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
}
for (i=0; i < pPce->NumSideChannelElements; i++)
{
pPce->SideElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
}
for (i=0; i < pPce->NumBackChannelElements; i++)
{
pPce->BackElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
}
FDKbyteAlign(bs, alignmentAnchor);
FDKcrcEndReg(&crcInfo, bs, crcReg);
if ((USHORT)FDKreadBits(bs,8) != FDKcrcGetCRC(&crcInfo)) {
/* CRC failed */
err = -1;
}
}
else {
/* No valid extension data found -> restore the initial bitbuffer state */
FDKpushBack(bs, startAnchor - FDKgetValidBits(bs));
}
/* Always report the bytes read. */
*bytesAvailable -= (startAnchor - FDKgetValidBits(bs)) >> 3;
return (err);
}
void CProgramConfig_Read(
CProgramConfig *pPce,
HANDLE_FDK_BITSTREAM bs,
UINT alignmentAnchor
)
{
int i;
int i, err = 0;
int commentBytes;
pPce->NumEffectiveChannels = 0;
pPce->NumChannels = 0;
@ -190,8 +255,12 @@ void CProgramConfig_Read(
FDKbyteAlign(bs, alignmentAnchor);
pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8);
commentBytes = pPce->CommentFieldBytes;
for (i=0; i < pPce->CommentFieldBytes; i++)
/* Search for height info extension and read it if available */
err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor );
for (i=0; i < commentBytes; i++)
{
UCHAR text;
@ -203,7 +272,7 @@ void CProgramConfig_Read(
}
}
pPce->isValid = 1;
pPce->isValid = (err) ? 0 : 1;
}
/*
@ -235,6 +304,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) {
if (pPce1->FrontElementHeightInfo[el] != pPce2->FrontElementHeightInfo[el]) {
result = 2; /* different height info */
break;
}
numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1;
}
@ -248,6 +321,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumSideChannelElements; el += 1) {
if (pPce1->SideElementHeightInfo[el] != pPce2->SideElementHeightInfo[el]) {
result = 2; /* different height info */
break;
}
numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1;
}
@ -261,6 +338,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumBackChannelElements; el += 1) {
if (pPce1->BackElementHeightInfo[el] != pPce2->BackElementHeightInfo[el]) {
result = 2; /* different height info */
break;
}
numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1;
}
@ -290,6 +371,44 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
switch (channelConfig) {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */
pPce->NumFrontChannelElements = 2;
pPce->FrontElementIsCpe[0] = 0;
pPce->FrontElementIsCpe[1] = 1;
pPce->NumSideChannelElements = 1;
pPce->SideElementIsCpe[0] = 1;
pPce->NumBackChannelElements = 1;
pPce->BackElementIsCpe[0] = 1;
pPce->NumLfeChannelElements = 1;
pPce->NumChannels = 8;
pPce->NumEffectiveChannels = 7;
pPce->isValid = 1;
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 12: /* 3/0/4.1ch surround back */
pPce->BackElementIsCpe[1] = 1;
pPce->NumChannels += 1;
pPce->NumEffectiveChannels += 1;
case 11: /* 3/0/3.1ch */
pPce->NumFrontChannelElements += 2;
pPce->FrontElementIsCpe[0] = 0;
pPce->FrontElementIsCpe[1] = 1;
pPce->NumBackChannelElements += 2;
pPce->BackElementIsCpe[0] = 1;
pPce->BackElementIsCpe[1] += 0;
pPce->NumLfeChannelElements += 1;
pPce->NumChannels += 7;
pPce->NumEffectiveChannels += 6;
pPce->isValid = 1;
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 14: /* 2/0/0-3/0/2-0.1ch front height */
pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */
case 7: /* 5/0/2.1ch front */
pPce->NumFrontChannelElements += 1;
pPce->FrontElementIsCpe[2] = 1;
pPce->NumChannels += 2;
pPce->NumEffectiveChannels += 2;
case 6: /* 3/0/2.1ch */
pPce->NumLfeChannelElements += 1;
pPce->NumChannels += 1;
@ -348,10 +467,11 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
/**
* \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index
* \param channelConfig MPEG channelConfiguration from 1 upto 7
* \param channelConfig MPEG channelConfiguration from 1 upto 14
* \param index MPEG channel order index
* \return audio channel type.
*/
static
void getImplicitAudioChannelTypeAndIndex(
AUDIO_CHANNEL_TYPE *chType,
UCHAR *chIndex,
@ -364,9 +484,9 @@ void getImplicitAudioChannelTypeAndIndex(
*chIndex = index;
} else {
switch (channelConfig) {
case MODE_1_2_1:
case MODE_1_2_2:
case MODE_1_2_2_1:
case 4: /* SCE, CPE, SCE */
case 5: /* SCE, CPE, CPE */
case 6: /* SCE, CPE, CPE, LFE */
switch (index) {
case 3:
case 4:
@ -379,12 +499,12 @@ void getImplicitAudioChannelTypeAndIndex(
break;
}
break;
case MODE_1_2_2_2_1:
case 7: /* SCE,CPE,CPE,CPE,LFE */
switch (index) {
case 3:
case 4:
*chType = ACT_SIDE;
*chIndex = index - 3;
*chType = ACT_FRONT;
*chIndex = index;
break;
case 5:
case 6:
@ -397,6 +517,42 @@ void getImplicitAudioChannelTypeAndIndex(
break;
}
break;
case 11: /* SCE,CPE,CPE,SCE,LFE */
if (index < 6) {
*chType = ACT_BACK;
*chIndex = index - 3;
} else {
*chType = ACT_LFE;
*chIndex = 0;
}
break;
case 12: /* SCE,CPE,CPE,CPE,LFE */
if (index < 7) {
*chType = ACT_BACK;
*chIndex = index - 3;
} else {
*chType = ACT_LFE;
*chIndex = 0;
}
break;
case 14: /* SCE,CPE,CPE,LFE,CPE */
switch (index) {
case 3:
case 4:
*chType = ACT_BACK;
*chIndex = index - 3;
break;
case 5:
*chType = ACT_LFE;
*chIndex = 0;
break;
case 6:
case 7:
*chType = ACT_FRONT_TOP;
*chIndex = index - 6; /* handle the top layer independently */
break;
}
break;
default:
*chType = ACT_NONE;
break;
@ -467,7 +623,24 @@ int CProgramConfig_LookupElement(
else {
/* Accept the additional channel(s), only if the tag is in the lists */
int isCpe = 0, i;
int cc = 0, fc = 0, sc = 0, bc = 0, lc = 0, ec = 0; /* Channel and element counters */
/* Element counter */
int ec[PC_NUM_HEIGHT_LAYER] = {0};
/* Channel counters */
int cc[PC_NUM_HEIGHT_LAYER] = {0};
int fc[PC_NUM_HEIGHT_LAYER] = {0};
int sc[PC_NUM_HEIGHT_LAYER] = {0};
int bc[PC_NUM_HEIGHT_LAYER] = {0};
int lc = 0;;
/* General MPEG (PCE) composition rules:
- Over all:
<normal height channels><top height channels><bottom height channels>
- Within each height layer:
<front channels><side channels><back channels>
- Exception:
The LFE channels have no height info and thus they are arranged at the very
end of the normal height layer channels.
*/
switch (elType)
{
@ -476,87 +649,206 @@ int CProgramConfig_LookupElement(
case ID_SCE:
/* search in front channels */
for (i = 0; i < pPce->NumFrontChannelElements; i++) {
int heightLayer = pPce->FrontElementHeightInfo[i];
if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx;
chType[cc] = ACT_FRONT;
chIndex[cc] = fc;
if (isCpe) {
chMapping[cc+1] = channelIdx+1;
chType[cc+1] = ACT_FRONT;
chIndex[cc+1] = fc+1;
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT);
for (h = heightLayer-1; h >= 0; h-=1) {
int el;
/* Count front channels/elements */
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
if (pPce->FrontElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
}
}
/* Count side channels/elements */
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
if (pPce->SideElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
}
}
/* Count back channels/elements */
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
if (pPce->BackElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
}
}
if (h == 0) { /* normal height */
elIdx += pPce->NumLfeChannelElements;
chIdx += pPce->NumLfeChannelElements;
}
}
*elMapping = ec;
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = fc[heightLayer];
if (isCpe) {
chMapping[chIdx+1] = channelIdx+1;
chType[chIdx+1] = aChType;
chIndex[chIdx+1] = fc[heightLayer]+1;
}
*elMapping = elIdx;
return 1;
}
ec++;
ec[heightLayer] += 1;
if (pPce->FrontElementIsCpe[i]) {
cc+=2; fc+=2;
cc[heightLayer] += 2;
fc[heightLayer] += 2;
} else {
cc++; fc++;
cc[heightLayer] += 1;
fc[heightLayer] += 1;
}
}
/* search in side channels */
for (i = 0; i < pPce->NumSideChannelElements; i++) {
int heightLayer = pPce->SideElementHeightInfo[i];
if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx;
chType[cc] = ACT_SIDE;
chIndex[cc] = sc;
if (isCpe) {
chMapping[cc+1] = channelIdx+1;
chType[cc+1] = ACT_SIDE;
chIndex[cc+1] = sc+1;
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE);
for (h = heightLayer-1; h >= 0; h-=1) {
int el;
/* Count front channels/elements */
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
if (pPce->FrontElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
}
}
/* Count side channels/elements */
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
if (pPce->SideElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
}
}
/* Count back channels/elements */
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
if (pPce->BackElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
}
}
if (h == 0) { /* LFE channels belong to the normal height layer */
elIdx += pPce->NumLfeChannelElements;
chIdx += pPce->NumLfeChannelElements;
}
}
*elMapping = ec;
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = sc[heightLayer];
if (isCpe) {
chMapping[chIdx+1] = channelIdx+1;
chType[chIdx+1] = aChType;
chIndex[chIdx+1] = sc[heightLayer]+1;
}
*elMapping = elIdx;
return 1;
}
ec++;
ec[heightLayer] += 1;
if (pPce->SideElementIsCpe[i]) {
cc+=2; sc+=2;
cc[heightLayer] += 2;
sc[heightLayer] += 2;
} else {
cc++; sc++;
cc[heightLayer] += 1;
sc[heightLayer] += 1;
}
}
/* search in back channels */
for (i = 0; i < pPce->NumBackChannelElements; i++) {
int heightLayer = pPce->BackElementHeightInfo[i];
if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx;
chType[cc] = ACT_BACK;
chIndex[cc] = bc;
if (isCpe) {
chMapping[cc+1] = channelIdx+1;
chType[cc+1] = ACT_BACK;
chIndex[cc+1] = bc+1;
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK);
for (h = heightLayer-1; h >= 0; h-=1) {
int el;
/* Count front channels/elements */
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
if (pPce->FrontElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
}
}
/* Count side channels/elements */
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
if (pPce->SideElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
}
}
/* Count back channels/elements */
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
if (pPce->BackElementHeightInfo[el] == h) {
elIdx += 1;
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
}
}
if (h == 0) { /* normal height */
elIdx += pPce->NumLfeChannelElements;
chIdx += pPce->NumLfeChannelElements;
}
}
*elMapping = ec;
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = bc[heightLayer];
if (isCpe) {
chMapping[chIdx+1] = channelIdx+1;
chType[chIdx+1] = aChType;
chIndex[chIdx+1] = bc[heightLayer]+1;
}
*elMapping = elIdx;
return 1;
}
ec++;
ec[heightLayer] += 1;
if (pPce->BackElementIsCpe[i]) {
cc+=2; bc+=2;
cc[heightLayer] += 2;
bc[heightLayer] += 2;
} else {
cc++; bc++;
cc[heightLayer] += 1;
bc[heightLayer] += 1;
}
}
break;
case ID_LFE:
/* Initialize channel counter and element counter */
cc = pPce->NumEffectiveChannels;
ec = pPce->NumFrontChannelElements+ pPce->NumSideChannelElements + pPce->NumBackChannelElements;
{ /* Unfortunately we have to go through all normal height
layer elements to get the position of the LFE channels.
Start with counting the front channels/elements at normal height */
for (i = 0; i < pPce->NumFrontChannelElements; i+=1) {
int heightLayer = pPce->FrontElementHeightInfo[i];
ec[heightLayer] += 1;
cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1;
}
/* Count side channels/elements at normal height */
for (i = 0; i < pPce->NumSideChannelElements; i+=1) {
int heightLayer = pPce->SideElementHeightInfo[i];
ec[heightLayer] += 1;
cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1;
}
/* Count back channels/elements at normal height */
for (i = 0; i < pPce->NumBackChannelElements; i+=1) {
int heightLayer = pPce->BackElementHeightInfo[i];
ec[heightLayer] += 1;
cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1;
}
/* search in lfe channels */
for (i = 0; i < pPce->NumLfeChannelElements; i++) {
int elIdx = ec[0]; /* LFE channels belong to the normal height layer */
int chIdx = cc[0];
if ( pPce->LfeElementTagSelect[i] == tag ) {
chMapping[cc] = channelIdx;
*elMapping = ec;
chType[cc] = ACT_LFE;
chIndex[cc] = lc;
chMapping[chIdx] = channelIdx;
*elMapping = elIdx;
chType[chIdx] = ACT_LFE;
chIndex[chIdx] = lc;
return 1;
}
ec++;
cc++;
lc++;
ec[0] += 1;
cc[0] += 1;
lc += 1;
}
break;
} break;
/* Non audio elements */
case ID_CCE:
@ -590,13 +882,19 @@ int CProgramConfig_LookupElement(
int CProgramConfig_GetElementTable(
const CProgramConfig *pPce,
MP4_ELEMENT_ID elList[],
const INT elListSize
const INT elListSize,
UCHAR *pChMapIdx
)
{
int i, el = 0;
if ( elListSize
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
FDK_ASSERT(elList != NULL);
FDK_ASSERT(pChMapIdx != NULL);
*pChMapIdx = 0;
if ( elListSize
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
)
{
return 0;
@ -623,6 +921,47 @@ int CProgramConfig_GetElementTable(
}
/* Find an corresponding channel configuration if possible */
switch (pPce->NumChannels) {
case 1: case 2: case 3: case 4: case 5: case 6:
/* One and two channels have no alternatives. The other ones are mapped directly to the
corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */
*pChMapIdx = pPce->NumChannels;
break;
case 7:
{
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
/* Create a PCE for the config to test ... */
CProgramConfig_GetDefault(tmpPce, 11);
/* ... and compare it with the given one. */
*pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0;
/* If compare result is 0 or 1 we can be sure that it is channel config 11. */
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
}
break;
case 8:
{ /* Try the four possible 7.1ch configurations. One after the other. */
UCHAR testCfg[4] = { 32, 14, 12, 7};
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
for (i=0; i<4; i+=1) {
/* Create a PCE for the config to test ... */
CProgramConfig_GetDefault(tmpPce, testCfg[i]);
/* ... and compare it with the given one. */
if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) {
/* If the compare result is 0 or 1 than the two channel configurations match. */
/* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */
*pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i];
}
}
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
}
break;
default:
/* The PCE does not match any predefined channel configuration. */
*pChMapIdx = 0;
break;
}
return el;
}
#endif
@ -714,7 +1053,7 @@ TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self,
#ifdef TP_ELD_ENABLE
static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
HANDLE_FDK_BITSTREAM hBs,
HANDLE_FDK_BITSTREAM hBs,
CSTpCallBacks *cb )
{
const int channelConfiguration = asc->m_channelConfiguration;
@ -728,6 +1067,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
}
switch ( channelConfiguration ) {
case 14:
case 12:
case 7:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
case 6:
@ -737,6 +1078,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
break;
case 11:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
case 4:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++);
@ -802,24 +1145,6 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse(
}
switch (eldExtType) {
case ELDEXT_LDSAC:
esc->m_useLdQmfTimeAlign = 1;
if (cb->cbSsc != NULL) {
ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc(
cb->cbSscData,
hBs,
asc->m_aot,
asc->m_samplingFrequency,
1, /* muxMode */
len
);
} else {
ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
}
if (ErrorStatus != TRANSPORTDEC_OK) {
goto bail;
}
break;
default:
for(cnt=0; cnt<len; cnt++) {
FDKreadBits(hBs, 8 );

View File

@ -2,7 +2,7 @@
/* library info */
#define TP_LIB_VL0 2
#define TP_LIB_VL1 3
#define TP_LIB_VL2 3
#define TP_LIB_VL2 4
#define TP_LIB_TITLE "MPEG Transport"
#define TP_LIB_BUILD_DATE __DATE__
#define TP_LIB_BUILD_TIME __TIME__

View File

@ -146,12 +146,15 @@ typedef struct
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
*/
static inline int getNumberOfTotalChannels(int channelConfig)
{
if (channelConfig > 0 && channelConfig < 8)
return (channelConfig == 7)?8:channelConfig;
else
switch (channelConfig) {
case 1: case 2: case 3:
case 4: case 5: case 6:
return channelConfig;
case 7: case 12: case 14:
return 8;
case 11:
return 7;
default:
return 0;
}
}
static inline
int getNumberOfEffectiveChannels(const int channelConfig)
{
const int n[] = {0,1,2,3,4,5,5,7};
{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */
const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
return n[channelConfig];
}

View File

@ -2,7 +2,7 @@
/* library info */
#define TP_LIB_VL0 2
#define TP_LIB_VL1 3
#define TP_LIB_VL2 3
#define TP_LIB_VL2 4
#define TP_LIB_TITLE "MPEG Transport"
#define TP_LIB_BUILD_DATE __DATE__
#define TP_LIB_BUILD_TIME __TIME__

View File

@ -95,69 +95,88 @@ amm-info@iis.fraunhofer.de
#include "machine_type.h"
#include "common_fix.h"
#include "FDK_audio.h"
#include "FDK_bitstream.h"
/* ------------------------ *
* MODULE SETTINGS: *
* ------------------------ */
/* #define PCM_UPMIX_ENABLE */ /*!< Generally enable up mixing. */
#define PCM_DOWNMIX_ENABLE /*!< Generally enable down mixing. */
#define DVB_MIXDOWN_ENABLE /*!< Enable this to support DVB ancillary data for encoder
assisted downmixing of MPEG-4 AAC and
MPEG-1/2 layer 2 streams. PCM_DOWNMIX_ENABLE has to
be enabled, too! */
#define MPEG_PCE_MIXDOWN_ENABLE /*!< Enable this to support MPEG matrix mixdown with a
coefficient carried in the PCE. PCM_DOWNMIX_ENABLE
has to be enabled, too! */
/* #define ARIB_MIXDOWN_ENABLE */ /*!< Enable modifications to the MPEG PCE mixdown method
to fulfill ARIB standard. MPEG_PCE_MIXDOWN_ENABLE has
to be set. */
/* ------------------------ *
* ERROR CODES: *
* ------------------------ */
typedef enum
{
PCMDMX_OK = 0x0, /*!< No error happened. */
PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */
PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third
party module. */
PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */
PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */
PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and
thus no processing was performed. */
PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */
PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */
PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably
the value ist out of range. */
PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */
PCMDMX_OK = 0x0, /*!< No error happened. */
pcm_dmx_fatal_error_start,
PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */
PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third
party module. */
pcm_dmx_fatal_error_end,
PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */
PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */
PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and thus
no processing was performed. */
PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */
PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */
PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably the
value ist out of range. */
PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */
} PCMDMX_ERROR;
/** Macro to identify fatal errors. */
#define PCMDMX_IS_FATAL_ERROR(err) ( (((err)>=pcm_dmx_fatal_error_start) && ((err)<=pcm_dmx_fatal_error_end)) ? 1 : 0)
/* ------------------------ *
* RUNTIME PARAMS: *
* ------------------------ */
typedef enum
{
DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to
go by before the bitstream data expires. The value 0
disables expiry. */
DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples
compared to the bitstream data. */
NUMBER_OF_OUTPUT_CHANNELS , /*!< The number of output channels (equals the number of
channels processed by the audio output setup). */
DUAL_CHANNEL_DOWNMIX_MODE /*!< Downmix mode for two channel audio data. */
DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to go
by before the bitstream data expires. The value 0 disables
expiry. */
DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples compared
to the bitstream data. */
MIN_NUMBER_OF_OUTPUT_CHANNELS, /*!< The minimum number of output channels. For all input
configurations that have less than the given channels the
module will modify the output automatically to obtain the
given number of output channels. Mono signals will be
duplicated. If more than two output channels are desired
the module just adds empty channels. The parameter value
must be either -1, 0, 1, 2, 6 or 8. If the value is
greater than zero and exceeds the value of parameter
MAX_NUMBER_OF_OUTPUT_CHANNELS the latter will be set to
the same value. Both values -1 and 0 disable the feature. */
MAX_NUMBER_OF_OUTPUT_CHANNELS, /*!< The maximum number of output channels. For all input
configurations that have more than the given channels the
module will apply a mixdown automatically to obtain the
given number of output channels. The value must be either
-1, 0, 1, 2, 6 or 8. If it is greater than zero and lower
or equal than the value of MIN_NUMBER_OF_OUTPUT_CHANNELS
parameter the latter will be set to the same value.
The values -1 and 0 disable the feature. */
DMX_DUAL_CHANNEL_MODE, /*!< Downmix mode for two channel audio data. */
DMX_PSEUDO_SURROUND_MODE /*!< Defines how module handles pseudo surround compatible
signals. See PSEUDO_SURROUND_MODE type for details. */
} PCMDMX_PARAM;
/* Parameter value types */
typedef enum
{
NEVER_DO_PS_DMX = -1, /*!< Never create a pseudo surround compatible downmix. */
AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if
signalled in bitstreams meta data. (Default) */
FORCE_PS_DMX = 1 /*!< Always create a pseudo surround compatible downmix.
CAUTION: This can lead to excessive signal cancellations
and signal level differences for non-compatible signals. */
} PSEUDO_SURROUND_MODE;
typedef enum
{
STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */
CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */
CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */
MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two channels. */
STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */
CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */
CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */
MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two
channels. */
} DUAL_CHANNEL_MODE;
@ -178,7 +197,7 @@ extern "C"
/** Open and initialize an instance of the PCM downmix module
* @param [out] Pointer to a buffer receiving the handle of the new instance.
* @returns Returns an error code.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_Open (
HANDLE_PCM_DOWNMIX *pSelf
@ -188,20 +207,46 @@ PCMDMX_ERROR pcmDmx_Open (
* @param [in] Handle of PCM downmix instance.
* @param [in] Parameter to be set.
* @param [in] Parameter value.
* @returns Returns an error code.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_SetParam (
HANDLE_PCM_DOWNMIX self,
PCMDMX_PARAM param,
UINT value
const PCMDMX_PARAM param,
const INT value
);
/** Read the ancillary data transported in DSEs of DVB streams with MPEG-4 content
/** Get one parameter value of one PCM downmix module instance.
* @param [in] Handle of PCM downmix module instance.
* @param [in] Parameter to be set.
* @param [out] Pointer to buffer receiving the parameter value.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_GetParam (
HANDLE_PCM_DOWNMIX self,
const PCMDMX_PARAM param,
INT * const pValue
);
/** Read downmix meta-data directly from a given bitstream.
* @param [in] Handle of PCM downmix instance.
* @param [in] Handle of FDK bitstream buffer.
* @param [in] Length of ancillary data in bits.
* @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_Parse (
HANDLE_PCM_DOWNMIX self,
HANDLE_FDK_BITSTREAM hBitStream,
UINT ancDataBits,
int isMpeg2
);
/** Read downmix meta-data from a given data buffer.
* @param [in] Handle of PCM downmix instance.
* @param [in] Pointer to ancillary data buffer.
* @param [in] Size of ancillary data.
* @param [in] Size of ancillary data in bytes.
* @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream.
* @returns Returns an error code.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_ReadDvbAncData (
HANDLE_PCM_DOWNMIX self,
@ -211,12 +256,11 @@ PCMDMX_ERROR pcmDmx_ReadDvbAncData (
);
/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream.
* Note: Call only if matrix_mixdown_idx_present is true.
* @param [in] Handle of PCM downmix instance.
* @param [in] Matrix mixdown index present flag extracted from PCE.
* @param [in] The 2 bit matrix mixdown index extracted from PCE.
* @param [in] The pseudo surround enable flag extracted from PCE.
* @returns Returns an error code.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce (
HANDLE_PCM_DOWNMIX self,
@ -235,34 +279,42 @@ PCMDMX_ERROR pcmDmx_Reset (
UINT flags
);
/** Apply down or up mixing.
/** Create a mixdown, bypass or extend the output signal depending on the modules settings and the
* respective given input configuration.
*
* \param [in] Handle of PCM downmix module instance.
* \param [inout] Pointer to time buffer with decoded PCM samples.
* \param [in] Pointer where the amount of output samples is returned into.
* \param [inout] Pointer where the amount of output channels is returned into.
* \param [in] Flag which indicates if output time data are writtern interleaved or as subsequent blocks.
* \param [inout] Array were the corresponding channel type for each output audio channel is stored into.
* \param [inout] Array were the corresponding channel type index for each output audio channel is stored into.
* \param [in] Array containing the output channel mapping to be used (From MPEG PCE ordering to whatever is required).
*
* @returns Returns an error code.
* \param [in] The I/O block size which is the number of samples per channel.
* \param [inout] Pointer to buffer that holds the number of input channels and where the
* amount of output channels is written to.
* \param [in] Flag which indicates if output time data is writtern interleaved or as
* subsequent blocks.
* \param [inout] Array were the corresponding channel type for each output audio channel is
* stored into.
* \param [inout] Array were the corresponding channel type index for each output audio channel
* is stored into.
* \param [in] Array containing the output channel mapping to be used (from MPEG PCE ordering
* to whatever is required).
* \param [out] Pointer on a field receiving the scale factor that has to be applied on all
* samples afterwards. If the handed pointer is NULL the final scaling is done
* internally.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_ApplyFrame (
HANDLE_PCM_DOWNMIX self,
INT_PCM *pPcmBuf,
UINT frameSize,
INT *nChannels,
int fInterleaved,
AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[],
const UCHAR channelMapping[][8]
const UCHAR channelMapping[][8],
INT *pDmxOutScale
);
/** Close an instance of the PCM downmix module.
* @param [inout] Pointer to a buffer containing the handle of the instance.
* @returns Returns an error code.
* @returns Returns an error code.
**/
PCMDMX_ERROR pcmDmx_Close (
HANDLE_PCM_DOWNMIX *pSelf
@ -270,7 +322,7 @@ PCMDMX_ERROR pcmDmx_Close (
/** Get library info for this module.
* @param [out] Pointer to an allocated LIB_INFO structure.
* @returns Returns an error code.
* @returns Returns an error code.
*/
PCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info );

File diff suppressed because it is too large Load Diff

View File

@ -308,7 +308,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
INT_PCM *timeData,
int *numChannels,
int *sampleRate,
const UCHAR channelMapping[(6)],
const UCHAR channelMapping[(8)],
const int interleaved,
const int coreDecodedOk,
UCHAR *psDecoded );

View File

@ -107,19 +107,19 @@ amm-info@iis.fraunhofer.de
/*! SBR Decoder main structure */
C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1)
/*! SBR Decoder element data <br>
Dimension: (4) */
C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (4))
Dimension: (8) */
C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8))
/*! SBR Decoder individual channel data <br>
Dimension: (6) */
C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (6)+1)
Dimension: (8) */
C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8)+1)
/*! Filter states for QMF-synthesis. <br>
Dimension: #(6) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */
C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (6)+1, SECT_DATA_L1)
Dimension: #(8) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */
C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (8)+1, SECT_DATA_L1)
/*! Delayed spectral data needed for the dynamic framing of SBR.
For mp3PRO, 1/3 of a frame is buffered (#(6) 6) */
C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (6)+1)
C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (8)+1)
/*! Static Data of PS */

View File

@ -118,8 +118,8 @@ typedef struct
struct SBR_DECODER_INSTANCE
{
SBR_DECODER_ELEMENT *pSbrElement[(4)];
SBR_HEADER_DATA sbrHeader[(4)][(1)+1]; /* Sbr header for each individual channel of an element */
SBR_DECODER_ELEMENT *pSbrElement[(8)];
SBR_HEADER_DATA sbrHeader[(8)][(1)+1]; /* Sbr header for each individual channel of an element */
FIXP_DBL *workBuffer1;
FIXP_DBL *workBuffer2;

View File

@ -95,7 +95,7 @@ amm-info@iis.fraunhofer.de
#define SBRDEC_MAX_DRC_CHANNELS (6)
#define SBRDEC_MAX_DRC_CHANNELS (8)
#define SBRDEC_MAX_DRC_BANDS ( 16 )
typedef struct

View File

@ -137,7 +137,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 2
#define SBRDECODER_LIB_VL2 3
#define SBRDECODER_LIB_VL2 4
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#define SBRDECODER_LIB_BUILD_DATE __DATE__
#define SBRDECODER_LIB_BUILD_TIME __TIME__
@ -428,7 +428,7 @@ SBR_ERROR sbrDecoder_InitElement (
int nSbrElementsStart = self->numSbrElements;
/* Check core codec AOT */
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (4)) {
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail;
}
@ -615,7 +615,7 @@ INT sbrDecoder_Header (
SBR_ERROR sbrError = SBRDEC_OK;
int headerIndex;
if ( self == NULL || elementIndex > (4) )
if ( self == NULL || elementIndex > (8) )
{
return SBRDEC_UNSUPPORTED_CONFIG;
}
@ -767,7 +767,7 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
int elementIndex, elChanIdx=0, numCh=0;
for (elementIndex = 0; (elementIndex < (4)) && (numCh <= channel); elementIndex++)
for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++)
{
SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
int c, elChannels;
@ -829,7 +829,7 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
if (self == NULL) {
return SBRDEC_NOT_INITIALIZED;
}
if (ch > (6) || pNextFact_mag == NULL) {
if (ch > (8) || pNextFact_mag == NULL) {
return SBRDEC_SET_PARAM_FAIL;
}
@ -874,7 +874,7 @@ void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self,
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
if ( (self == NULL)
|| (ch > (6))
|| (ch > (8))
|| (self->numSbrElements == 0)
|| (self->numSbrChannels == 0) ) {
return;
@ -1375,7 +1375,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
INT_PCM *timeData,
int *numChannels,
int *sampleRate,
const UCHAR channelMapping[(6)],
const UCHAR channelMapping[(8)],
const int interleaved,
const int coreDecodedOk,
UCHAR *psDecoded )
@ -1496,7 +1496,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
FreeRam_SbrDecWorkBuffer2(&self->workBuffer2);
}
for (i = 0; i < (4); i++) {
for (i = 0; i < (8); i++) {
sbrDecoder_DestroyElement( self, i );
}

View File

@ -263,17 +263,29 @@ typedef enum {
} CHANNEL_MODE;
/** Speaker description tags */
/**
* Speaker description tags.
* Do not change the enumeration values unless it keeps the following segmentation:
* - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe)
* - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom)
*/
typedef enum {
ACT_NONE,
ACT_FRONT,
ACT_SIDE,
ACT_BACK,
ACT_LFE,
ACT_FRONT_TOP,
ACT_SIDE_TOP,
ACT_BACK_TOP,
ACT_TOP /* Ts */
ACT_NONE = 0x00,
ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */
ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */
ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */
ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */
ACT_TOP = 0x10, /*!< Top speaker area (for combination with speaker positions) */
ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */
ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */
ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */
ACT_BOTTOM = 0x20, /*!< Bottom speaker area (for combination with speaker positions) */
ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */
ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */
ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */
} AUDIO_CHANNEL_TYPE;
typedef enum

View File

@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de
/* library info */
#define SYS_LIB_VL0 1
#define SYS_LIB_VL1 3
#define SYS_LIB_VL2 4
#define SYS_LIB_VL2 5
#define SYS_LIB_TITLE "System Integration Library"
#define SYS_LIB_BUILD_DATE __DATE__
#define SYS_LIB_BUILD_TIME __TIME__