Introduce additional sanity checks to validate program config element.

Bug: 176246647
Test: atest android.media.cts.DecoderTestAacFormat android.media.cts.DecoderTestXheAac android.media.cts.DecoderTestAacDrc
Change-Id: I3e04480ab5a74da1a9d09af5da95afb2000b3117
This commit is contained in:
Fraunhofer IIS FDK 2020-04-09 17:58:42 +02:00 committed by Ray Essick
parent baa3203971
commit 82f6f3dac6
1 changed files with 156 additions and 11 deletions

View File

@ -266,11 +266,118 @@ static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce,
return (err); 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, void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
UINT alignmentAnchor) { UINT alignmentAnchor) {
int i, err = 0; int i;
int commentBytes; int commentBytes;
UCHAR tag, isCpe;
UCHAR checkElementTagSelect[3][PC_FSB_CHANNELS_MAX] = {{0}};
pPce->isValid = 1;
pPce->NumEffectiveChannels = 0; pPce->NumEffectiveChannels = 0;
pPce->NumChannels = 0; pPce->NumChannels = 0;
pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4); 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++) { for (i = 0; i < pPce->NumFrontChannelElements; i++) {
pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); pPce->FrontElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->FrontElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; 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++) { for (i = 0; i < pPce->NumSideChannelElements; i++) {
pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); pPce->SideElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->SideElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; 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++) { for (i = 0; i < pPce->NumBackChannelElements; i++) {
pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); pPce->BackElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->BackElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; 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; pPce->NumEffectiveChannels = pPce->NumChannels;
for (i = 0; i < pPce->NumLfeChannelElements; i++) { 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; 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++) { for (i = 0; i < pPce->NumAssocDataElements; i++) {
@ -336,7 +475,15 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
commentBytes = pPce->CommentFieldBytes; commentBytes = pPce->CommentFieldBytes;
/* Search for height info extension and read it if available */ /* 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++) { for (i = 0; i < commentBytes; i++) {
UCHAR text; UCHAR text;
@ -347,8 +494,6 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
pPce->Comment[i] = text; pPce->Comment[i] = text;
} }
} }
pPce->isValid = (err) ? 0 : 1;
} }
/* /*