aboutsummaryrefslogtreecommitdiffstats
path: root/libMpegTPDec/src/tpdec_asc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libMpegTPDec/src/tpdec_asc.cpp')
-rw-r--r--libMpegTPDec/src/tpdec_asc.cpp243
1 files changed, 220 insertions, 23 deletions
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index bb4094b..8f77017 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -266,11 +266,118 @@ static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce,
return (err);
}
+/**
+ * \brief Sanity checks for program config element.
+ * Check order of elements according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.5.1
+ *
+ * \param pPce pointer to program config element.
+ *
+ * \return 0 if successful, otherwise 1.
+ */
+static int CProgramConfig_Check(CProgramConfig *pPce) {
+ INT i;
+ INT err = 0;
+ INT numBackChannels[3] = {0};
+ INT numSideChannels[3] = {0};
+ INT numFrontChannels[3] = {0};
+ UCHAR *pCpeFront = pPce->FrontElementIsCpe;
+ UCHAR *pCpeSide = pPce->SideElementIsCpe;
+ UCHAR *pCpeBack = pPce->BackElementIsCpe;
+ UCHAR *pHeight;
+
+ pHeight = pPce->BackElementHeightInfo;
+ for (i = 0; i < pPce->NumBackChannelElements; i++) {
+ numBackChannels[*pHeight] += pPce->BackElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+ pHeight = pPce->SideElementHeightInfo;
+ for (i = 0; i < pPce->NumSideChannelElements; i++) {
+ numSideChannels[*pHeight] += pPce->SideElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+ pHeight = pPce->FrontElementHeightInfo;
+ for (i = 0; i < pPce->NumFrontChannelElements; i++) {
+ numFrontChannels[*pHeight] += pPce->FrontElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+
+ /* 0 = normal height channels, 1 = top height channels, 2 = bottom height
+ * channels */
+ for (i = 0; i < 3; i++) {
+ /* if number of channels is odd => first element must be a SCE (front center
+ * channel) */
+ if (numFrontChannels[i] & 1) {
+ if (*pCpeFront++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ numFrontChannels[i]--;
+ }
+ while (numFrontChannels[i] > 0) {
+ /* must be CPE or paired SCE */
+ if (*pCpeFront++ == ID_SCE) {
+ if (*pCpeFront++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numFrontChannels[i] -= 2;
+ };
+
+ /* in case that a top center surround channel (Ts) is transmitted the number
+ * of channels can be odd */
+ if (i != 1) {
+ /* number of channels must be even */
+ if (numSideChannels[i] & 1) {
+ err = 1;
+ goto bail;
+ }
+ while (numSideChannels[i] > 0) {
+ /* must be CPE or paired SCE */
+ if (*pCpeSide++ == ID_SCE) {
+ if (*pCpeSide++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numSideChannels[i] -= 2;
+ };
+ }
+
+ while (numBackChannels[i] > 1) {
+ /* must be CPE or paired SCE */
+ if (*pCpeBack++ == ID_SCE) {
+ if (*pCpeBack++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numBackChannels[i] -= 2;
+ };
+ /* if number of channels is odd => last element must be a SCE (back center
+ * channel) */
+ if (numBackChannels[i]) {
+ if (*pCpeBack++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ }
+
+bail:
+
+ return err;
+}
+
void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
UINT alignmentAnchor) {
- int i, err = 0;
+ int i;
int commentBytes;
+ UCHAR tag, isCpe;
+ UCHAR checkElementTagSelect[3][PC_FSB_CHANNELS_MAX] = {{0}};
+ pPce->isValid = 1;
pPce->NumEffectiveChannels = 0;
pPce->NumChannels = 0;
pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4);
@@ -297,28 +404,60 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
}
for (i = 0; i < pPce->NumFrontChannelElements; i++) {
- pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->FrontElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->FrontElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumSideChannelElements; i++) {
- pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->SideElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->SideElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumBackChannelElements; i++) {
- pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->BackElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->BackElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
pPce->NumEffectiveChannels = pPce->NumChannels;
for (i = 0; i < pPce->NumLfeChannelElements; i++) {
- pPce->LfeElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->LfeElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[2][tag] == 0) {
+ checkElementTagSelect[2][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumAssocDataElements; i++) {
@@ -336,7 +475,15 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
commentBytes = pPce->CommentFieldBytes;
/* Search for height info extension and read it if available */
- err = CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor);
+ if (CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor)) {
+ pPce->isValid = 0;
+ }
+
+ /* Check order of elements according to ISO / IEC 13818 - 7:2003(E),
+ * chapter 8.5.1 */
+ if (CProgramConfig_Check(pPce)) {
+ pPce->isValid = 0;
+ }
for (i = 0; i < commentBytes; i++) {
UCHAR text;
@@ -347,8 +494,6 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
pPce->Comment[i] = text;
}
}
-
- pPce->isValid = (err) ? 0 : 1;
}
/*
@@ -1415,7 +1560,7 @@ static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc,
cb->cbSscData, hBs, asc->m_aot,
asc->m_samplingFrequency << esc->m_sbrSamplingRate,
asc->m_samplesPerFrame << esc->m_sbrSamplingRate,
- 1, /* stereoConfigIndex */
+ asc->m_channelConfiguration, 1, /* stereoConfigIndex */
-1, /* nTimeSlots: read from bitstream */
eldExtLen, asc->configMode, &asc->SacConfigChanged);
if (ErrorStatus != TRANSPORTDEC_OK) {
@@ -1549,7 +1694,7 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
const AUDIO_OBJECT_TYPE aot) {
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
- int usacExtElementType = escapedValue(hBs, 4, 8, 16);
+ UINT usacExtElementType = escapedValue(hBs, 4, 8, 16);
/* recurve extension elements which are invalid for USAC */
if (aot == AOT_USAC) {
@@ -1566,7 +1711,6 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
}
}
- extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType;
int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16);
extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength;
INT bsAnchor;
@@ -1600,8 +1744,10 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
}
} break;
default:
+ usacExtElementType = ID_EXT_ELE_UNKNOWN;
break;
}
+ extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType;
/* Adjust bit stream position. This is required because of byte alignment and
* unhandled extensions. */
@@ -1630,8 +1776,12 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
int numConfigExtensions;
- int usacConfigExtType;
+ UINT usacConfigExtType;
int usacConfigExtLength;
+ int loudnessInfoSetIndex =
+ -1; /* index of loudnessInfoSet config extension. -1 if not contained. */
+ int tmp_subStreamIndex = 0;
+ AUDIO_OBJECT_TYPE tmp_aot = AOT_USAC;
numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1;
for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) {
@@ -1661,10 +1811,12 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
cb->cbUniDrcData, hBs, usacConfigExtLength,
1, /* loudnessInfoSet */
- 0, loudnessInfoSetConfigExtensionPosition, AOT_USAC);
+ tmp_subStreamIndex, loudnessInfoSetConfigExtensionPosition,
+ tmp_aot);
if (ErrorStatus != TRANSPORTDEC_OK) {
return ErrorStatus;
}
+ loudnessInfoSetIndex = confExtIdx;
}
} break;
default:
@@ -1680,6 +1832,17 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
FDKpushFor(hBs, usacConfigExtLength);
}
+ if (loudnessInfoSetIndex == -1 && cb->cbUniDrc != NULL) {
+ /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+ * an empty config extension */
+ ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, tmp_subStreamIndex,
+ 0, tmp_aot);
+ if (ErrorStatus != TRANSPORTDEC_OK) {
+ return ErrorStatus;
+ }
+ }
+
return ErrorStatus;
}
@@ -1696,6 +1859,8 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
int channelElementIdx =
0; /* index for elements which contain audio channels (sce, cpe, lfe) */
SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0};
+ int uniDrcElement =
+ -1; /* index of uniDrc extension element. -1 if not contained. */
numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1;
usc->m_usacNumElements = numberOfElements;
@@ -1826,6 +1991,8 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
/* Mps212Config() ISO/IEC FDIS 23003-3 */
if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot,
asc->m_extensionSamplingFrequency, samplesPerFrame,
+ 1, /* only downmix channels (residual channels are
+ not counted) */
usc->element[i].m_stereoConfigIndex,
usc->m_coreSbrFrameLengthIndex,
0, /* don't know the length */
@@ -1869,6 +2036,10 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
case ID_USAC_EXT:
ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0,
asc->m_samplesPerFrame, 0, asc->m_aot);
+ if (usc->element[i].extElement.usacExtElementType ==
+ ID_EXT_ELE_UNI_DRC) {
+ uniDrcElement = i;
+ }
if (ErrorStatus) {
return ErrorStatus;
@@ -1897,6 +2068,18 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
}
}
+ if (uniDrcElement == -1 && cb->cbUniDrc != NULL) {
+ /* no uniDrcConfig contained. Clear the uniDrcConfig struct by feeding an
+ * empty extension element */
+ int subStreamIndex = 0;
+ ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 0 /* uniDrcConfig */, subStreamIndex, 0,
+ asc->m_aot);
+ if (ErrorStatus != TRANSPORTDEC_OK) {
+ return ErrorStatus;
+ }
+ }
+
return ErrorStatus;
}
@@ -1983,6 +2166,14 @@ static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc,
if (err != TRANSPORTDEC_OK) {
return err;
}
+ } else if (cb->cbUniDrc != NULL) {
+ /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+ * an empty config extension */
+ err = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, 0, 0, asc->m_aot);
+ if (err != TRANSPORTDEC_OK) {
+ return err;
+ }
}
/* sanity check whether number of channels signaled in UsacDecoderConfig()
@@ -1995,9 +2186,11 @@ static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc,
/* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */
INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits;
- StoreConfigAsBitstream(hBs, configSize_bits,
- asc->m_sc.m_usacConfig.UsacConfig,
- TP_USAC_MAX_CONFIG_LEN);
+ if (StoreConfigAsBitstream(hBs, configSize_bits,
+ asc->m_sc.m_usacConfig.UsacConfig,
+ TP_USAC_MAX_CONFIG_LEN)) {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits);
return err;
@@ -2218,7 +2411,7 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
case AOT_MPEGS:
if (cb->cbSsc != NULL) {
if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency,
- self->m_samplesPerFrame, 1,
+ self->m_samplesPerFrame, self->m_channelConfiguration, 1,
-1, /* nTimeSlots: read from bitstream */
0, /* don't know the length */
self->configMode, &self->SacConfigChanged)) {
@@ -2299,8 +2492,10 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
/* Copy config() to asc->config[] buffer. */
if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) {
INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor;
- StoreConfigAsBitstream(bs, configSize_bits, self->config,
- TP_USAC_MAX_CONFIG_LEN);
+ if (StoreConfigAsBitstream(bs, configSize_bits, self->config,
+ TP_USAC_MAX_CONFIG_LEN)) {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
self->configBits = fAbs(configSize_bits);
}
@@ -2414,6 +2609,8 @@ static TRANSPORTDEC_ERROR Drm_xHEAACDecoderConfig(
cb->cbSscData, hBs,
AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */
asc->m_extensionSamplingFrequency, samplesPerFrame,
+ 1, /* only downmix channels (residual channels are not
+ counted) */
usc->element[elemIdx].m_stereoConfigIndex,
usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */
asc->configMode, &asc->SacConfigChanged);