Commit 47c680c6 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi

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
parent fa3eba16
...@@ -430,21 +430,58 @@ typedef enum { ...@@ -430,21 +430,58 @@ typedef enum {
typedef enum typedef enum
{ {
AAC_PCM_OUTPUT_INTERLEAVED = 0x0000, /*!< PCM output mode (1: interleaved (default); 0: not interleaved). */ 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 AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals: \n
upmixing is applied). \n 0: Leave both signals as they are (default). \n
-1: Disable up-/downmixing. The decoder output contains the same number of channels as the 1: Create a dual mono output signal from channel 1. \n
encoded bitstream. \n 2: Create a dual mono output signal from channel 2. \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.
3: Create a dual mono output signal by mixing both channels (L' = R' = 0.5*Ch1 + 0.5*Ch2). */ 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_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 AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n
0: Spectral muting. \n 0: Spectral muting. \n
......
...@@ -108,15 +108,15 @@ C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1) ...@@ -108,15 +108,15 @@ C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed /*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed
for the decoding of one aac channel. <br> for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */ 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 /*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed
for the decoding of one aac channel. <br> for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */ Dimension: #AacDecoderChannels */
C_ALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (6)) C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8))
/*! Overlap buffer */ /*! Overlap buffer */
C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6)) C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8))
C_ALLOC_MEM(DrcInfo, CDrcInfo, 1) C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
...@@ -128,7 +128,7 @@ 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, Dynamic memory areas, might be reused in other algorithm sections,
e.g. the sbr decoder 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) C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)
......
...@@ -1777,42 +1777,62 @@ const FIXP_TCC FDKaacDec_tnsCoeff4 [16] = ...@@ -1777,42 +1777,62 @@ const FIXP_TCC FDKaacDec_tnsCoeff4 [16] =
}; };
/* MPEG like mapping (no change). */ /* 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}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */ { 0, 1,255,255,255,255,255,255}, /* stereo */
{ 0, 1, 2,255,255,255,255,255}, /* 3ch */ { 0, 1, 2,255,255,255,255,255}, /* 3ch */
{ 0, 1, 2, 3,255,255,255,255}, /* 4ch */ { 0, 1, 2, 3,255,255,255,255}, /* 4ch */
{ 0, 1, 2, 3, 4,255,255,255}, /* 5ch */ { 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,255,255}, /* 5.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 front */
{ 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1ch */ { 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). */ /* 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}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */ { 0, 1,255,255,255,255,255,255}, /* stereo */
{ 2, 0, 1,255,255,255,255,255}, /* 3ch */ { 2, 0, 1,255,255,255,255,255}, /* 3ch */
{ 2, 0, 1, 3,255,255,255,255}, /* 4ch */ { 2, 0, 1, 3,255,255,255,255}, /* 4ch */
{ 2, 0, 1, 3, 4,255,255,255}, /* 5ch */ { 2, 0, 1, 3, 4,255,255,255}, /* 5ch */
{ 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */ { 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */
{ 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */ { 2, 6, 7, 0, 1, 4, 5, 3}, /* 7.1 front */
{ 2, 0, 1, 6, 7, 4, 5, 3} /* 7.1ch */ { 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 */ /* 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 */ /* 1 */ { 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 */ /* 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 */
{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 */
{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 */
{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 */
{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 */
{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 /*! Random sign bit used for concealment
......
...@@ -177,11 +177,12 @@ extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16]; ...@@ -177,11 +177,12 @@ extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16];
extern const FIXP_DBL pow2_div24minus1[47]; extern const FIXP_DBL pow2_div24minus1[47];
extern const int offsetTab[2][16]; extern const int offsetTab[2][16];
/* Channel mapping indices for time domain I/O. First dimension is channel count-1. */ /* Channel mapping indices for time domain I/O.
extern const UCHAR channelMappingTablePassthrough[8][8]; The first dimension is the channel configuration index. */
extern const UCHAR channelMappingTableWAV[8][8]; extern const UCHAR channelMappingTablePassthrough[15][8];
extern const UCHAR channelMappingTableWAV[15][8];
/* Lookup tables for elements in ER bitstream */ /* 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 */ #endif /* #ifndef AAC_ROM_H */
...@@ -539,7 +539,7 @@ static int aacDecoder_drcReadCompression ( ...@@ -539,7 +539,7 @@ static int aacDecoder_drcReadCompression (
UINT payloadPosition ) UINT payloadPosition )
{ {
int bitCnt = 0; int bitCnt = 0;
int dmxLevelsPresent, compressionPresent; int dmxLevelsPresent, extensionPresent, compressionPresent;
int coarseGrainTcPresent, fineGrainTcPresent; int coarseGrainTcPresent, fineGrainTcPresent;
/* Move to the beginning of the DRC payload field */ /* Move to the beginning of the DRC payload field */
...@@ -562,7 +562,8 @@ static int aacDecoder_drcReadCompression ( ...@@ -562,7 +562,8 @@ static int aacDecoder_drcReadCompression (
} }
FDKreadBits(bs, 2); /* dolby_surround_mode */ FDKreadBits(bs, 2); /* dolby_surround_mode */
FDKreadBits(bs, 2); /* presentation_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; return 0;
} }
...@@ -571,9 +572,7 @@ static int aacDecoder_drcReadCompression ( ...@@ -571,9 +572,7 @@ static int aacDecoder_drcReadCompression (
return 0; return 0;
} }
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */ extensionPresent = FDKreadBits(bs, 1); /* ancillary_data_extension_status; */
return 0;
}
compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */ coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */ fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
...@@ -631,6 +630,19 @@ static int aacDecoder_drcReadCompression ( ...@@ -631,6 +630,19 @@ static int aacDecoder_drcReadCompression (
bitCnt += 16; 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); return (bitCnt);
} }
......
...@@ -338,17 +338,22 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse ( ...@@ -338,17 +338,22 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
\return Error code \return Error code
*/ */
static AAC_DECODER_ERROR CDataStreamElement_Read ( static AAC_DECODER_ERROR CDataStreamElement_Read (
HANDLE_AACDECODER self,
HANDLE_FDK_BITSTREAM bs, HANDLE_FDK_BITSTREAM bs,
CAncData *ancData,
HANDLE_AAC_DRC hDrcInfo,
HANDLE_TRANSPORTDEC pTp,
UCHAR *elementInstanceTag, UCHAR *elementInstanceTag,
UINT alignmentAnchor ) UINT alignmentAnchor )
{ {
HANDLE_TRANSPORTDEC pTp;
CAncData *ancData;
AAC_DECODER_ERROR error = AAC_DEC_OK; AAC_DECODER_ERROR error = AAC_DEC_OK;
UINT dataStart; UINT dataStart, dseBits;
int dataByteAlignFlag, count; int dataByteAlignFlag, count;
FDK_ASSERT(self != NULL);
ancData = &self->ancData;
pTp = self->hInput;
int crcReg = transportDec_CrcStartReg(pTp, 0); int crcReg = transportDec_CrcStartReg(pTp, 0);
/* Element Instance Tag */ /* Element Instance Tag */
...@@ -361,6 +366,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read ( ...@@ -361,6 +366,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
if (count == 255) { if (count == 255) {
count += FDKreadBits(bs,8); /* EscCount */ count += FDKreadBits(bs,8); /* EscCount */
} }
dseBits = count*8;
if (dataByteAlignFlag) { if (dataByteAlignFlag) {
FDKbyteAlign(bs, alignmentAnchor); FDKbyteAlign(bs, alignmentAnchor);
...@@ -372,19 +378,29 @@ static AAC_DECODER_ERROR CDataStreamElement_Read ( ...@@ -372,19 +378,29 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
transportDec_CrcEndReg(pTp, crcReg); transportDec_CrcEndReg(pTp, crcReg);
{ {
INT readBits, dataBits = count<<3;
/* Move to the beginning of the data junk */ /* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs)); FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
/* Read Anc data if available */ /* Read Anc data if available */
readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA ); aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
}
{
PCMDMX_ERROR dmxErr = PCMDMX_OK;
if (readBits != dataBits) { /* Move to the beginning of the data junk */
/* Move to the end again. */ FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
/* 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; return error;
} }
...@@ -774,7 +790,7 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) ...@@ -774,7 +790,7 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
if (self == NULL) if (self == NULL)
return; return;
for (ch=0; ch<(6); ch++) { for (ch=0; ch<(8); ch++) {
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) { if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer); FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
...@@ -851,18 +867,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS ...@@ -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 */ /* valid number of channels -> copy program config element (PCE) from ASC */
FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig)); FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
/* Built element table */ /* Built element table */
el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, 7); el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, (8), &self->chMapIndex);
for (; el<7; el++) { for (; el<(8); el++) {
self->elements[el] = ID_NONE; self->elements[el] = ID_NONE;
} }
} else { } else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
} }
} else { } else {
self->chMapIndex = 0;
if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) { if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) {
/* set default max_channels for memory allocation because in implicit channel mapping mode /* 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(). */ we don't know the actual number of channels until we processed at least one raw_data_block(). */
ascChannels = (6); ascChannels = (8);
} else { } else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
} }
...@@ -874,26 +891,34 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS ...@@ -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: case 1: case 2: case 3: case 4: case 5: case 6:
ascChannels = asc->m_channelConfiguration; ascChannels = asc->m_channelConfiguration;
break; break;
case 7: case 11:
ascChannels = 7;
break;
case 7: case 12: case 14:
ascChannels = 8; ascChannels = 8;
break; break;
default: default:
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
} }
if (ascChannels > (8)) {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
/* Initialize constant mappings for channel config 1-7 */ /* Initialize constant mappings for channel config 1-7 */
if (asc->m_channelConfiguration > 0) { if (asc->m_channelConfiguration > 0) {
int el; int el;
FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7)); FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,(8)));
for (el=7; el<7; el++) { for (el=7; el<(8); el++) {
self->elements[el] = ID_NONE; self->elements[el] = ID_NONE;
} }
for (ch=0; ch<ascChannels; ch++) { for (ch=0; ch<ascChannels; ch++) {
self->chMapping[ch] = ch; self->chMapping[ch] = ch;
} }
for (; ch<(6); ch++) { for (; ch<(8); ch++) {
self->chMapping[ch] = 255; self->chMapping[ch] = 255;
} }
self->chMapIndex = asc->m_channelConfiguration;
} }
#ifdef TP_PCE_ENABLE #ifdef TP_PCE_ENABLE
else { else {
...@@ -909,9 +934,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS ...@@ -909,9 +934,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
self->streamInfo.channelConfig = asc->m_channelConfiguration; self->streamInfo.channelConfig = asc->m_channelConfiguration;
if (ascChannels > (6)) {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
if (self->streamInfo.aot != asc->m_aot) { if (self->streamInfo.aot != asc->m_aot) {
self->streamInfo.aot = asc->m_aot; self->streamInfo.aot = asc->m_aot;
ascChanged = 1; ascChanged = 1;
...@@ -1096,6 +1118,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1096,6 +1118,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
MP4_ELEMENT_ID type = ID_NONE; /* Current element type */ MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
INT aacChannels=0; /* Channel counter for channels found in the bitstream */ 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 */ 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( ...@@ -1119,12 +1142,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->streamInfo.channelConfig == 0) { if (self->streamInfo.channelConfig == 0) {
/* Init Channel/Element mapping table */ /* Init Channel/Element mapping table */
for (ch=0; ch<(6); ch++) { for (ch=0; ch<(8); ch++) {
self->chMapping[ch] = 255; self->chMapping[ch] = 255;
} }
if (!CProgramConfig_IsValid(pce)) { if (!CProgramConfig_IsValid(pce)) {
int el; int el;
for (el=0; el<7; el++) { for (el=0; el<(8); el++) {
self->elements[el] = ID_NONE; self->elements[el] = ID_NONE;
} }
} }
...@@ -1378,10 +1401,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1378,10 +1401,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
{ {
UCHAR element_instance_tag; UCHAR element_instance_tag;
CDataStreamElement_Read( bs, CDataStreamElement_Read( self,
&self->ancData, bs,
self->hDrcInfo,
self->hInput,
&element_instance_tag, &element_instance_tag,
auStartAnchor ); auStartAnchor );
...@@ -1401,29 +1422,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1401,29 +1422,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
//self->frameOK = 0; //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; break;
#ifdef TP_PCE_ENABLE #ifdef TP_PCE_ENABLE
...@@ -1442,9 +1440,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1442,9 +1440,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
} }
else if ( result > 1 ) { else if ( result > 1 ) {
/* Built element table */ /* 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 */ /* Reset the remaining tabs */
for ( ; elIdx<7; elIdx++) { for ( ; elIdx<(8); elIdx++) {
self->elements[elIdx] = ID_NONE; self->elements[elIdx] = ID_NONE;
} }
/* Make new number of channel persistant */ /* Make new number of channel persistant */
...@@ -1632,6 +1630,23 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1632,6 +1630,23 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
return ErrorStatus; 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 Inverse transform
*/ */
...@@ -1663,10 +1678,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1663,10 +1678,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Setup offset and stride for time buffer traversal. */ /* Setup offset and stride for time buffer traversal. */
if (interleaved) { if (interleaved) {
stride = aacChannels; stride = aacChannels;
offset = self->channelOutputMapping[aacChannels-1][c]; offset = self->channelOutputMapping[chOutMapIdx][c];
} else { } else {
stride = 1; 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( ...@@ -1746,8 +1761,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Reorder channel type information tables. */ /* Reorder channel type information tables. */
{ {
AUDIO_CHANNEL_TYPE types[(6)]; AUDIO_CHANNEL_TYPE types[(8)];
UCHAR idx[(6)]; UCHAR idx[(8)];
int c; int c;
FDK_ASSERT(sizeof(self->channelType) == sizeof(types)); FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
...@@ -1757,8 +1772,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ...@@ -1757,8 +1772,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(idx, self->channelIndices, sizeof(idx)); FDKmemcpy(idx, self->channelIndices, sizeof(idx));
for (c=0; c<aacChannels; c++) { for (c=0; c<aacChannels; c++) {
self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c]; self->channelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c];
self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c]; self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c];
} }
} }
......
...@@ -176,22 +176,23 @@ struct AAC_DECODER_INSTANCE { ...@@ -176,22 +176,23 @@ struct AAC_DECODER_INSTANCE {
UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */ 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 */ MP4_ELEMENT_ID elements[(8)]; /*!< Table where the element Id's are listed */
UCHAR elTags[7]; /*!< Table where the elements id Tags are listed */ UCHAR elTags[(8)]; /*!< Table where the elements id Tags are listed */
UCHAR chMapping[(6)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */ 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). */ AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< 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). */ 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() */ /* 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. */ 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; CProgramConfig pce;
CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */ CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */ CAacDecoderChannelInfo *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */ CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */
......
...@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de ...@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define AACDECODER_LIB_VL0 2 #define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 5 #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_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__ #define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__ #define AACDECODER_LIB_BUILD_TIME __TIME__
...@@ -420,8 +420,8 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode ...@@ -420,8 +420,8 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
self->outputInterleaved = value; self->outputInterleaved = value;
break; break;
case AAC_PCM_OUTPUT_CHANNELS: case AAC_PCM_MIN_OUTPUT_CHANNELS:
if (value < -1 || value > (6)) { if (value < -1 || value > (8)) {
return AAC_DEC_SET_PARAM_FAIL; return AAC_DEC_SET_PARAM_FAIL;
} }
{ {
...@@ -429,7 +429,30 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode ...@@ -429,7 +429,30 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam ( err = pcmDmx_SetParam (
hPcmDmx, 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 ); value );
switch (err) { switch (err) {
...@@ -449,7 +472,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode ...@@ -449,7 +472,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam ( err = pcmDmx_SetParam (
hPcmDmx, hPcmDmx,
DUAL_CHANNEL_DOWNMIX_MODE, DMX_DUAL_CHANNEL_MODE,
value ); value );
switch (err) { switch (err) {
...@@ -825,6 +848,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( ...@@ -825,6 +848,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->sbrEnabled) if (self->sbrEnabled)
{ {
SBR_ERROR sbrError = SBRDEC_OK; SBR_ERROR sbrError = SBRDEC_OK;
int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex;
/* set params */ /* set params */
sbrDecoder_SetParam ( self->hSbrDecoder, sbrDecoder_SetParam ( self->hSbrDecoder,
...@@ -838,7 +862,16 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( ...@@ -838,7 +862,16 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
(self->flags & AC_LD_MPS) ? 1 : 0 ); (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 */ /* apply SBR processing */
...@@ -846,7 +879,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( ...@@ -846,7 +879,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
pTimeData, pTimeData,
&self->streamInfo.numChannels, &self->streamInfo.numChannels,
&self->streamInfo.sampleRate, &self->streamInfo.sampleRate,
self->channelOutputMapping[self->streamInfo.numChannels-1], self->channelOutputMapping[chOutMapIdx],
interleaved, interleaved,
self->frameOK, self->frameOK,
&self->psPossible); &self->psPossible);
...@@ -870,19 +903,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( ...@@ -870,19 +903,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->channelType[1] = ACT_FRONT; self->channelType[1] = ACT_FRONT;
self->channelIndices[0] = 0; self->channelIndices[0] = 0;
self->channelIndices[1] = 1; self->channelIndices[1] = 1;
} else {
self->flags &= ~AC_PS_PRESENT;
} }
} }
} }
{
PCMDMX_ERROR dmxErr = PCMDMX_OK;
if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) { if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) {
/* delete data from the past (e.g. mixdown coeficients) */ /* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA ); pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA );
} }
/* do PCM post processing */ /* do PCM post processing */
pcmDmx_ApplyFrame ( dmxErr = pcmDmx_ApplyFrame (
self->hPcmUtils, self->hPcmUtils,
pTimeData, pTimeData,
self->streamInfo.frameSize, self->streamInfo.frameSize,
...@@ -890,9 +923,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( ...@@ -890,9 +923,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
interleaved, interleaved,
self->channelType, self->channelType,
self->channelIndices, 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. */ /* Signal interruption to take effect in next frame. */
......
...@@ -762,7 +762,6 @@ int ...@@ -762,7 +762,6 @@ int
CConcealment_UpdateState( hConcealmentInfo, CConcealment_UpdateState( hConcealmentInfo,
frameOk ); frameOk );
if ( !frameOk )
{ {
/* Create data for signal rendering according to the selected concealment method and decoder operating mode. */ /* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
...@@ -775,11 +774,13 @@ int ...@@ -775,11 +774,13 @@ int
{ {
default: default:
case ConcealMethodMute: case ConcealMethodMute:
/* Mute spectral data in case of errors */ if (!frameOk) {
FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); /* Mute spectral data in case of errors */
/* Set last window shape */ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape; /* Set last window shape */
appliedProcessing = 1; pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
appliedProcessing = 1;
}
break; break;
case ConcealMethodNoise: case ConcealMethodNoise:
...@@ -801,7 +802,7 @@ int ...@@ -801,7 +802,7 @@ int
pSamplingRateInfo, pSamplingRateInfo,
samplesPerFrame, samplesPerFrame,
0, /* don't use tonal improvement */ 0, /* don't use tonal improvement */
0); frameOk);
break; break;
} }
......
...@@ -146,12 +146,15 @@ typedef struct ...@@ -146,12 +146,15 @@ typedef struct
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
...@@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate ) ...@@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
*/ */
static inline int getNumberOfTotalChannels(int channelConfig) static inline int getNumberOfTotalChannels(int channelConfig)
{ {
if (channelConfig > 0 && channelConfig < 8) switch (channelConfig) {
return (channelConfig == 7)?8:channelConfig; case 1: case 2: case 3:
else case 4: case 5: case 6:
return channelConfig;
case 7: case 12: case 14:
return 8;
case 11:
return 7;
default:
return 0; return 0;
}
} }
static inline static inline
int getNumberOfEffectiveChannels(const int channelConfig) int getNumberOfEffectiveChannels(const int channelConfig)
{ { /* 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}; const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
return n[channelConfig]; return n[channelConfig];
} }
......
...@@ -151,6 +151,7 @@ typedef enum { ...@@ -151,6 +151,7 @@ typedef enum {
#define PC_ASSOCDATA_MAX 8 #define PC_ASSOCDATA_MAX 8
#define PC_CCEL_MAX 16 /* CC elements */ #define PC_CCEL_MAX 16 /* CC elements */
#define PC_COMMENTLENGTH 256 #define PC_COMMENTLENGTH 256
#define PC_NUM_HEIGHT_LAYER 3
/*! /*!
...@@ -239,14 +240,20 @@ int CProgramConfig_LookupElement( ...@@ -239,14 +240,20 @@ int CProgramConfig_LookupElement(
); );
/** /**
* \brief Get table of elements in canonical order. * \brief Get table of elements in canonical order from a
* \param pPce A valid program config structure. * give program config field.
* \param table An array where the element IDs are stored. * \param pPce A valid program config structure.
* \return Total element count including all SCE, CPE and LFE. * \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, int CProgramConfig_GetElementTable( const CProgramConfig *pPce,
MP4_ELEMENT_ID table[], MP4_ELEMENT_ID table[],
const INT elListSize ); const INT elListSize,
UCHAR *pChMapIdx );
/** /**
* \brief Initialize a given AudioSpecificConfig structure. * \brief Initialize a given AudioSpecificConfig structure.
......
...@@ -90,6 +90,9 @@ amm-info@iis.fraunhofer.de ...@@ -90,6 +90,9 @@ amm-info@iis.fraunhofer.de
#include "tpdec_lib.h" #include "tpdec_lib.h"
#include "tp_data.h" #include "tp_data.h"
#ifdef TP_PCE_ENABLE
#include "FDK_crc.h"
#endif
void CProgramConfig_Reset(CProgramConfig *pPce) void CProgramConfig_Reset(CProgramConfig *pPce)
...@@ -111,13 +114,75 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce ) ...@@ -111,13 +114,75 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce )
} }
#ifdef TP_PCE_ENABLE #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( void CProgramConfig_Read(
CProgramConfig *pPce, CProgramConfig *pPce,
HANDLE_FDK_BITSTREAM bs, HANDLE_FDK_BITSTREAM bs,
UINT alignmentAnchor UINT alignmentAnchor
) )
{ {
int i; int i, err = 0;
int commentBytes;
pPce->NumEffectiveChannels = 0; pPce->NumEffectiveChannels = 0;
pPce->NumChannels = 0; pPce->NumChannels = 0;
...@@ -190,8 +255,12 @@ void CProgramConfig_Read( ...@@ -190,8 +255,12 @@ void CProgramConfig_Read(
FDKbyteAlign(bs, alignmentAnchor); FDKbyteAlign(bs, alignmentAnchor);
pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8); pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8);
commentBytes = pPce->CommentFieldBytes;
/* Search for height info extension and read it if available */
err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor );
for (i=0; i < pPce->CommentFieldBytes; i++) for (i=0; i < commentBytes; i++)
{ {
UCHAR text; UCHAR text;
...@@ -203,7 +272,7 @@ void CProgramConfig_Read( ...@@ -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, ...@@ -235,6 +304,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else { } else {
int el, numCh1 = 0, numCh2 = 0; int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) { 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; numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1; numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1;
} }
...@@ -248,6 +321,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, ...@@ -248,6 +321,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else { } else {
int el, numCh1 = 0, numCh2 = 0; int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumSideChannelElements; el += 1) { 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; numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1; numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1;
} }
...@@ -261,6 +338,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, ...@@ -261,6 +338,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
} else { } else {
int el, numCh1 = 0, numCh2 = 0; int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumBackChannelElements; el += 1) { 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; numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1; numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1;
} }
...@@ -290,6 +371,44 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce, ...@@ -290,6 +371,44 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
switch (channelConfig) { 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 */ case 6: /* 3/0/2.1ch */
pPce->NumLfeChannelElements += 1; pPce->NumLfeChannelElements += 1;
pPce->NumChannels += 1; pPce->NumChannels += 1;
...@@ -348,10 +467,11 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce, ...@@ -348,10 +467,11 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
/** /**
* \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index * \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 * \param index MPEG channel order index
* \return audio channel type. * \return audio channel type.
*/ */
static
void getImplicitAudioChannelTypeAndIndex( void getImplicitAudioChannelTypeAndIndex(
AUDIO_CHANNEL_TYPE *chType, AUDIO_CHANNEL_TYPE *chType,
UCHAR *chIndex, UCHAR *chIndex,
...@@ -364,9 +484,9 @@ void getImplicitAudioChannelTypeAndIndex( ...@@ -364,9 +484,9 @@ void getImplicitAudioChannelTypeAndIndex(
*chIndex = index; *chIndex = index;
} else { } else {
switch (channelConfig) { switch (channelConfig) {
case MODE_1_2_1: case 4: /* SCE, CPE, SCE */
case MODE_1_2_2: case 5: /* SCE, CPE, CPE */
case MODE_1_2_2_1: case 6: /* SCE, CPE, CPE, LFE */
switch (index) { switch (index) {
case 3: case 3:
case 4: case 4:
...@@ -379,12 +499,12 @@ void getImplicitAudioChannelTypeAndIndex( ...@@ -379,12 +499,12 @@ void getImplicitAudioChannelTypeAndIndex(
break; break;
} }
break; break;
case MODE_1_2_2_2_1: case 7: /* SCE,CPE,CPE,CPE,LFE */
switch (index) { switch (index) {
case 3: case 3:
case 4: case 4:
*chType = ACT_SIDE; *chType = ACT_FRONT;
*chIndex = index - 3; *chIndex = index;
break; break;
case 5: case 5:
case 6: case 6:
...@@ -397,6 +517,42 @@ void getImplicitAudioChannelTypeAndIndex( ...@@ -397,6 +517,42 @@ void getImplicitAudioChannelTypeAndIndex(
break; break;
} }
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: default:
*chType = ACT_NONE; *chType = ACT_NONE;
break; break;
...@@ -467,7 +623,24 @@ int CProgramConfig_LookupElement( ...@@ -467,7 +623,24 @@ int CProgramConfig_LookupElement(
else { else {
/* Accept the additional channel(s), only if the tag is in the lists */ /* Accept the additional channel(s), only if the tag is in the lists */
int isCpe = 0, i; 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) switch (elType)
{ {
...@@ -476,87 +649,206 @@ int CProgramConfig_LookupElement( ...@@ -476,87 +649,206 @@ int CProgramConfig_LookupElement(
case ID_SCE: case ID_SCE:
/* search in front channels */ /* search in front channels */
for (i = 0; i < pPce->NumFrontChannelElements; i++) { for (i = 0; i < pPce->NumFrontChannelElements; i++) {
int heightLayer = pPce->FrontElementHeightInfo[i];
if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx; int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
chType[cc] = ACT_FRONT; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT);
chIndex[cc] = fc; 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;
}
}
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = fc[heightLayer];
if (isCpe) { if (isCpe) {
chMapping[cc+1] = channelIdx+1; chMapping[chIdx+1] = channelIdx+1;
chType[cc+1] = ACT_FRONT; chType[chIdx+1] = aChType;
chIndex[cc+1] = fc+1; chIndex[chIdx+1] = fc[heightLayer]+1;
} }
*elMapping = ec; *elMapping = elIdx;
return 1; return 1;
} }
ec++; ec[heightLayer] += 1;
if (pPce->FrontElementIsCpe[i]) { if (pPce->FrontElementIsCpe[i]) {
cc+=2; fc+=2; cc[heightLayer] += 2;
fc[heightLayer] += 2;
} else { } else {
cc++; fc++; cc[heightLayer] += 1;
fc[heightLayer] += 1;
} }
} }
/* search in side channels */ /* search in side channels */
for (i = 0; i < pPce->NumSideChannelElements; i++) { for (i = 0; i < pPce->NumSideChannelElements; i++) {
int heightLayer = pPce->SideElementHeightInfo[i];
if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx; int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
chType[cc] = ACT_SIDE; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE);
chIndex[cc] = sc; 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;
}
}
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = sc[heightLayer];
if (isCpe) { if (isCpe) {
chMapping[cc+1] = channelIdx+1; chMapping[chIdx+1] = channelIdx+1;
chType[cc+1] = ACT_SIDE; chType[chIdx+1] = aChType;
chIndex[cc+1] = sc+1; chIndex[chIdx+1] = sc[heightLayer]+1;
} }
*elMapping = ec; *elMapping = elIdx;
return 1; return 1;
} }
ec++; ec[heightLayer] += 1;
if (pPce->SideElementIsCpe[i]) { if (pPce->SideElementIsCpe[i]) {
cc+=2; sc+=2; cc[heightLayer] += 2;
sc[heightLayer] += 2;
} else { } else {
cc++; sc++; cc[heightLayer] += 1;
sc[heightLayer] += 1;
} }
} }
/* search in back channels */ /* search in back channels */
for (i = 0; i < pPce->NumBackChannelElements; i++) { for (i = 0; i < pPce->NumBackChannelElements; i++) {
int heightLayer = pPce->BackElementHeightInfo[i];
if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) {
chMapping[cc] = channelIdx; int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
chType[cc] = ACT_BACK; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK);
chIndex[cc] = bc; 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;
}
}
chMapping[chIdx] = channelIdx;
chType[chIdx] = aChType;
chIndex[chIdx] = bc[heightLayer];
if (isCpe) { if (isCpe) {
chMapping[cc+1] = channelIdx+1; chMapping[chIdx+1] = channelIdx+1;
chType[cc+1] = ACT_BACK; chType[chIdx+1] = aChType;
chIndex[cc+1] = bc+1; chIndex[chIdx+1] = bc[heightLayer]+1;
} }
*elMapping = ec; *elMapping = elIdx;
return 1; return 1;
} }
ec++; ec[heightLayer] += 1;
if (pPce->BackElementIsCpe[i]) { if (pPce->BackElementIsCpe[i]) {
cc+=2; bc+=2; cc[heightLayer] += 2;
bc[heightLayer] += 2;
} else { } else {
cc++; bc++; cc[heightLayer] += 1;
bc[heightLayer] += 1;
} }
} }
break; break;
case ID_LFE: case ID_LFE:
/* Initialize channel counter and element counter */ { /* Unfortunately we have to go through all normal height
cc = pPce->NumEffectiveChannels; layer elements to get the position of the LFE channels.
ec = pPce->NumFrontChannelElements+ pPce->NumSideChannelElements + pPce->NumBackChannelElements; 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 */ /* search in lfe channels */
for (i = 0; i < pPce->NumLfeChannelElements; i++) { 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 ) { if ( pPce->LfeElementTagSelect[i] == tag ) {
chMapping[cc] = channelIdx; chMapping[chIdx] = channelIdx;
*elMapping = ec; *elMapping = elIdx;
chType[cc] = ACT_LFE; chType[chIdx] = ACT_LFE;
chIndex[cc] = lc; chIndex[chIdx] = lc;
return 1; return 1;
} }
ec++; ec[0] += 1;
cc++; cc[0] += 1;
lc++; lc += 1;
} }
break; } break;
/* Non audio elements */ /* Non audio elements */
case ID_CCE: case ID_CCE:
...@@ -590,13 +882,19 @@ int CProgramConfig_LookupElement( ...@@ -590,13 +882,19 @@ int CProgramConfig_LookupElement(
int CProgramConfig_GetElementTable( int CProgramConfig_GetElementTable(
const CProgramConfig *pPce, const CProgramConfig *pPce,
MP4_ELEMENT_ID elList[], MP4_ELEMENT_ID elList[],
const INT elListSize const INT elListSize,
UCHAR *pChMapIdx
) )
{ {
int i, el = 0; int i, el = 0;
if ( elListSize FDK_ASSERT(elList != NULL);
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements FDK_ASSERT(pChMapIdx != NULL);
*pChMapIdx = 0;
if ( elListSize
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
) )
{ {
return 0; return 0;
...@@ -623,6 +921,47 @@ int CProgramConfig_GetElementTable( ...@@ -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; return el;
} }
#endif #endif
...@@ -714,7 +1053,7 @@ TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self, ...@@ -714,7 +1053,7 @@ TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self,
#ifdef TP_ELD_ENABLE #ifdef TP_ELD_ENABLE
static INT ld_sbr_header( const CSAudioSpecificConfig *asc, static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
HANDLE_FDK_BITSTREAM hBs, HANDLE_FDK_BITSTREAM hBs,
CSTpCallBacks *cb ) CSTpCallBacks *cb )
{ {
const int channelConfiguration = asc->m_channelConfiguration; const int channelConfiguration = asc->m_channelConfiguration;
...@@ -728,6 +1067,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc, ...@@ -728,6 +1067,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
} }
switch ( channelConfiguration ) { switch ( channelConfiguration ) {
case 14:
case 12:
case 7: case 7:
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_CPE, i++);
case 6: case 6:
...@@ -737,6 +1078,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc, ...@@ -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++); error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
break; 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: 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_CPE, i++);
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, 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( ...@@ -802,24 +1145,6 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse(
} }
switch (eldExtType) { 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: default:
for(cnt=0; cnt<len; cnt++) { for(cnt=0; cnt<len; cnt++) {
FDKreadBits(hBs, 8 ); FDKreadBits(hBs, 8 );
......
...@@ -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 3 #define TP_LIB_VL2 4
#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__
...@@ -146,12 +146,15 @@ typedef struct ...@@ -146,12 +146,15 @@ typedef struct
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
...@@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate ) ...@@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
*/ */
static inline int getNumberOfTotalChannels(int channelConfig) static inline int getNumberOfTotalChannels(int channelConfig)
{ {
if (channelConfig > 0 && channelConfig < 8) switch (channelConfig) {
return (channelConfig == 7)?8:channelConfig; case 1: case 2: case 3:
else case 4: case 5: case 6:
return channelConfig;
case 7: case 12: case 14:
return 8;
case 11:
return 7;
default:
return 0; return 0;
}
} }
static inline static inline
int getNumberOfEffectiveChannels(const int channelConfig) int getNumberOfEffectiveChannels(const int channelConfig)
{ { /* 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}; const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
return n[channelConfig]; return n[channelConfig];
} }
......
...@@ -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 3 #define TP_LIB_VL2 4
#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__
...@@ -95,69 +95,88 @@ amm-info@iis.fraunhofer.de ...@@ -95,69 +95,88 @@ amm-info@iis.fraunhofer.de
#include "machine_type.h" #include "machine_type.h"
#include "common_fix.h" #include "common_fix.h"
#include "FDK_audio.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: * * ERROR CODES: *
* ------------------------ */ * ------------------------ */
typedef enum typedef enum
{ {
PCMDMX_OK = 0x0, /*!< No error happened. */ 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 pcm_dmx_fatal_error_start,
party module. */ PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */
PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */ PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third
PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */ party module. */
PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and pcm_dmx_fatal_error_end,
thus no processing was performed. */
PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */ PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */
PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */ PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */
PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and thus
the value ist out of range. */ no processing was performed. */
PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */ 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; } 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: * * RUNTIME PARAMS: *
* ------------------------ */ * ------------------------ */
typedef enum typedef enum
{ {
DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to go
go by before the bitstream data expires. The value 0 by before the bitstream data expires. The value 0 disables
disables expiry. */ expiry. */
DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples compared
compared to the bitstream data. */ to the bitstream data. */
NUMBER_OF_OUTPUT_CHANNELS , /*!< The number of output channels (equals the number of MIN_NUMBER_OF_OUTPUT_CHANNELS, /*!< The minimum number of output channels. For all input
channels processed by the audio output setup). */ configurations that have less than the given channels the
DUAL_CHANNEL_DOWNMIX_MODE /*!< Downmix mode for two channel audio data. */ 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; } PCMDMX_PARAM;
/* Parameter value types */
typedef enum typedef enum
{ {
STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */ NEVER_DO_PS_DMX = -1, /*!< Never create a pseudo surround compatible downmix. */
CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */ AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if
CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */ signalled in bitstreams meta data. (Default) */
MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two channels. */ 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. */
} DUAL_CHANNEL_MODE; } DUAL_CHANNEL_MODE;
...@@ -178,7 +197,7 @@ extern "C" ...@@ -178,7 +197,7 @@ extern "C"
/** Open and initialize an instance of the PCM downmix module /** Open and initialize an instance of the PCM downmix module
* @param [out] Pointer to a buffer receiving the handle of the new instance. * @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 ( PCMDMX_ERROR pcmDmx_Open (
HANDLE_PCM_DOWNMIX *pSelf HANDLE_PCM_DOWNMIX *pSelf
...@@ -188,20 +207,46 @@ PCMDMX_ERROR pcmDmx_Open ( ...@@ -188,20 +207,46 @@ PCMDMX_ERROR pcmDmx_Open (
* @param [in] Handle of PCM downmix instance. * @param [in] Handle of PCM downmix instance.
* @param [in] Parameter to be set. * @param [in] Parameter to be set.
* @param [in] Parameter value. * @param [in] Parameter value.
* @returns Returns an error code. * @returns Returns an error code.
**/ **/
PCMDMX_ERROR pcmDmx_SetParam ( PCMDMX_ERROR pcmDmx_SetParam (
HANDLE_PCM_DOWNMIX self, HANDLE_PCM_DOWNMIX self,
PCMDMX_PARAM param, const PCMDMX_PARAM param,
UINT value const INT value
);
/** 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 the ancillary data transported in DSEs of DVB streams with MPEG-4 content /** 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] Handle of PCM downmix instance.
* @param [in] Pointer to ancillary data buffer. * @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. * @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 ( PCMDMX_ERROR pcmDmx_ReadDvbAncData (
HANDLE_PCM_DOWNMIX self, HANDLE_PCM_DOWNMIX self,
...@@ -211,12 +256,11 @@ PCMDMX_ERROR pcmDmx_ReadDvbAncData ( ...@@ -211,12 +256,11 @@ PCMDMX_ERROR pcmDmx_ReadDvbAncData (
); );
/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream. /** 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] Handle of PCM downmix instance.
* @param [in] Matrix mixdown index present flag extracted from PCE. * @param [in] Matrix mixdown index present flag extracted from PCE.
* @param [in] The 2 bit matrix mixdown index extracted from PCE. * @param [in] The 2 bit matrix mixdown index extracted from PCE.
* @param [in] The pseudo surround enable flag 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 ( PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce (
HANDLE_PCM_DOWNMIX self, HANDLE_PCM_DOWNMIX self,
...@@ -235,34 +279,42 @@ PCMDMX_ERROR pcmDmx_Reset ( ...@@ -235,34 +279,42 @@ PCMDMX_ERROR pcmDmx_Reset (
UINT flags 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 [in] Handle of PCM downmix module instance.
* \param [inout] Pointer to time buffer with decoded PCM samples. * \param [inout] Pointer to time buffer with decoded PCM samples.
* \param [in] Pointer where the amount of output samples is returned into. * \param [in] The I/O block size which is the number of samples per channel.
* \param [inout] Pointer where the amount of output channels is returned into. * \param [inout] Pointer to buffer that holds the number of input channels and where the
* \param [in] Flag which indicates if output time data are writtern interleaved or as subsequent blocks. * amount of output channels is written to.
* \param [inout] Array were the corresponding channel type for each output audio channel is stored into. * \param [in] Flag which indicates if output time data is writtern interleaved or as
* \param [inout] Array were the corresponding channel type index for each output audio channel is stored into. * subsequent blocks.
* \param [in] Array containing the output channel mapping to be used (From MPEG PCE ordering to whatever is required). * \param [inout] Array were the corresponding channel type for each output audio channel is
* * stored into.
* @returns Returns an error code. * \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 ( PCMDMX_ERROR pcmDmx_ApplyFrame (
HANDLE_PCM_DOWNMIX self, HANDLE_PCM_DOWNMIX self,
INT_PCM *pPcmBuf, INT_PCM *pPcmBuf,
UINT frameSize, UINT frameSize,
INT *nChannels, INT *nChannels,
int fInterleaved, int fInterleaved,
AUDIO_CHANNEL_TYPE channelType[], AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[], UCHAR channelIndices[],
const UCHAR channelMapping[][8] const UCHAR channelMapping[][8],
INT *pDmxOutScale
); );
/** Close an instance of the PCM downmix module. /** Close an instance of the PCM downmix module.
* @param [inout] Pointer to a buffer containing the handle of the instance. * @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 ( PCMDMX_ERROR pcmDmx_Close (
HANDLE_PCM_DOWNMIX *pSelf HANDLE_PCM_DOWNMIX *pSelf
...@@ -270,7 +322,7 @@ PCMDMX_ERROR pcmDmx_Close ( ...@@ -270,7 +322,7 @@ PCMDMX_ERROR pcmDmx_Close (
/** Get library info for this module. /** Get library info for this module.
* @param [out] Pointer to an allocated LIB_INFO structure. * @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 ); PCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info );
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -308,7 +308,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, ...@@ -308,7 +308,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
INT_PCM *timeData, INT_PCM *timeData,
int *numChannels, int *numChannels,
int *sampleRate, int *sampleRate,
const UCHAR channelMapping[(6)], const UCHAR channelMapping[(8)],
const int interleaved, const int interleaved,
const int coreDecodedOk, const int coreDecodedOk,
UCHAR *psDecoded ); UCHAR *psDecoded );
......
...@@ -107,19 +107,19 @@ amm-info@iis.fraunhofer.de ...@@ -107,19 +107,19 @@ amm-info@iis.fraunhofer.de
/*! SBR Decoder main structure */ /*! SBR Decoder main structure */
C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1) C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1)
/*! SBR Decoder element data <br> /*! SBR Decoder element data <br>
Dimension: (4) */ Dimension: (8) */
C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (4)) C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8))
/*! SBR Decoder individual channel data <br> /*! SBR Decoder individual channel data <br>
Dimension: (6) */ Dimension: (8) */
C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (6)+1) C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8)+1)
/*! Filter states for QMF-synthesis. <br> /*! Filter states for QMF-synthesis. <br>
Dimension: #(6) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */ Dimension: #(8) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */
C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (6)+1, SECT_DATA_L1) 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. /*! Delayed spectral data needed for the dynamic framing of SBR.
For mp3PRO, 1/3 of a frame is buffered (#(6) 6) */ 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 */ /*! Static Data of PS */
......
...@@ -118,8 +118,8 @@ typedef struct ...@@ -118,8 +118,8 @@ typedef struct
struct SBR_DECODER_INSTANCE struct SBR_DECODER_INSTANCE
{ {
SBR_DECODER_ELEMENT *pSbrElement[(4)]; SBR_DECODER_ELEMENT *pSbrElement[(8)];
SBR_HEADER_DATA sbrHeader[(4)][(1)+1]; /* Sbr header for each individual channel of an element */ SBR_HEADER_DATA sbrHeader[(8)][(1)+1]; /* Sbr header for each individual channel of an element */
FIXP_DBL *workBuffer1; FIXP_DBL *workBuffer1;
FIXP_DBL *workBuffer2; FIXP_DBL *workBuffer2;
......
...@@ -95,7 +95,7 @@ amm-info@iis.fraunhofer.de ...@@ -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 ) #define SBRDEC_MAX_DRC_BANDS ( 16 )
typedef struct typedef struct
......
...@@ -137,7 +137,7 @@ amm-info@iis.fraunhofer.de ...@@ -137,7 +137,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define SBRDECODER_LIB_VL0 2 #define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 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_TITLE "SBR Decoder"
#define SBRDECODER_LIB_BUILD_DATE __DATE__ #define SBRDECODER_LIB_BUILD_DATE __DATE__
#define SBRDECODER_LIB_BUILD_TIME __TIME__ #define SBRDECODER_LIB_BUILD_TIME __TIME__
...@@ -428,7 +428,7 @@ SBR_ERROR sbrDecoder_InitElement ( ...@@ -428,7 +428,7 @@ SBR_ERROR sbrDecoder_InitElement (
int nSbrElementsStart = self->numSbrElements; int nSbrElementsStart = self->numSbrElements;
/* Check core codec AOT */ /* Check core codec AOT */
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (4)) { if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG; sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail; goto bail;
} }
...@@ -615,7 +615,7 @@ INT sbrDecoder_Header ( ...@@ -615,7 +615,7 @@ INT sbrDecoder_Header (
SBR_ERROR sbrError = SBRDEC_OK; SBR_ERROR sbrError = SBRDEC_OK;
int headerIndex; int headerIndex;
if ( self == NULL || elementIndex > (4) ) if ( self == NULL || elementIndex > (8) )
{ {
return SBRDEC_UNSUPPORTED_CONFIG; return SBRDEC_UNSUPPORTED_CONFIG;
} }
...@@ -767,7 +767,7 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con ...@@ -767,7 +767,7 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
int elementIndex, elChanIdx=0, numCh=0; 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]; SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
int c, elChannels; int c, elChannels;
...@@ -829,7 +829,7 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, ...@@ -829,7 +829,7 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
if (self == NULL) { if (self == NULL) {
return SBRDEC_NOT_INITIALIZED; return SBRDEC_NOT_INITIALIZED;
} }
if (ch > (6) || pNextFact_mag == NULL) { if (ch > (8) || pNextFact_mag == NULL) {
return SBRDEC_SET_PARAM_FAIL; return SBRDEC_SET_PARAM_FAIL;
} }
...@@ -874,7 +874,7 @@ void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self, ...@@ -874,7 +874,7 @@ void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self,
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
if ( (self == NULL) if ( (self == NULL)
|| (ch > (6)) || (ch > (8))
|| (self->numSbrElements == 0) || (self->numSbrElements == 0)
|| (self->numSbrChannels == 0) ) { || (self->numSbrChannels == 0) ) {
return; return;
...@@ -1375,7 +1375,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, ...@@ -1375,7 +1375,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
INT_PCM *timeData, INT_PCM *timeData,
int *numChannels, int *numChannels,
int *sampleRate, int *sampleRate,
const UCHAR channelMapping[(6)], const UCHAR channelMapping[(8)],
const int interleaved, const int interleaved,
const int coreDecodedOk, const int coreDecodedOk,
UCHAR *psDecoded ) UCHAR *psDecoded )
...@@ -1496,7 +1496,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf ) ...@@ -1496,7 +1496,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
FreeRam_SbrDecWorkBuffer2(&self->workBuffer2); FreeRam_SbrDecWorkBuffer2(&self->workBuffer2);
} }
for (i = 0; i < (4); i++) { for (i = 0; i < (8); i++) {
sbrDecoder_DestroyElement( self, i ); sbrDecoder_DestroyElement( self, i );
} }
......
...@@ -263,17 +263,29 @@ typedef enum { ...@@ -263,17 +263,29 @@ typedef enum {
} CHANNEL_MODE; } 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 { typedef enum {
ACT_NONE, ACT_NONE = 0x00,
ACT_FRONT, ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */
ACT_SIDE, ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */
ACT_BACK, ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */
ACT_LFE, ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */
ACT_FRONT_TOP,
ACT_SIDE_TOP, ACT_TOP = 0x10, /*!< Top speaker area (for combination with speaker positions) */
ACT_BACK_TOP, ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */
ACT_TOP /* Ts */ 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; } AUDIO_CHANNEL_TYPE;
typedef enum typedef enum
......
...@@ -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 4 #define SYS_LIB_VL2 5
#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