1. use WELS_CLIP1 to replace table look-up;

2. fix bugs about buffer overflow
3. add more boundary checks
This commit is contained in:
Licai Guo 2014-01-23 00:07:21 -08:00
parent 99412b0fc2
commit fc56c7d007
7 changed files with 106 additions and 79 deletions

View File

@ -81,7 +81,7 @@ void_t H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, co
int32_t iColorFormat = videoFormatInternal;
static int32_t iFrameNum = 0;
EDecodeMode eDecoderMode = AUTO_MODE;
EDecodeMode eDecoderMode = SW_MODE;
EBufferProperty eOutputProperty = BUFFER_DEVICE;
CUtils cOutputModule;

View File

@ -57,7 +57,7 @@ ERR_BOUND = 31,
*
*/
#define GENERATE_ERROR_NO(iErrLevel, iErrInfo) ((iErrLevel << 16) | (iErrInfo & 0xFFFF))
#define ERR_INVALID_INTRA4X4_MODE -1
/* ERR_LEVEL */
//-----------------------------------------------------------------------------------------------------------

View File

@ -56,82 +56,82 @@ namespace WelsDec {
#define CHROMA_AC 5
typedef struct TagReadBitsCache {
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
} SReadBitsCache;
#define SHIFT_BUFFER(pBitsCache) { pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits)); }
#define POP_BUFFER(pBitsCache, iCount) { pBitsCache->uiCache32Bit <<= iCount; pBitsCache->uiRemainBits -= iCount; }
static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
};
typedef struct TagI16PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
} SI16PredInfo;
static const SI16PredInfo g_ksI16PredInfo[4] = {
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
};
static const SI16PredInfo g_ksChromaPredInfo[4] = {
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
};
typedef struct TagI4PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
// int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
} SI4PredInfo;
static const SI4PredInfo g_ksI4PredInfo[9] = {
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
};
static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47}; //reference to JM
typedef struct TagPartMbInfo {
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
} SPartMbInfo;
static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
};
static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
};
void_t GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer);

View File

@ -220,6 +220,21 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
}
DecodeNalHeaderExt (pCurNal, pNal);
if ((pCurNal->sNalHeaderExt.uiQualityId != 0) || (pCurNal->sNalHeaderExt.bUseRefBasePicFlag != 0)) {
WelsLog (pCtx, WELS_LOG_WARNING,
"ParseNalHeader() in Prefix Nal Unit:uiQualityId (%d) != 0, bUseRefBasePicFlag (%d) != 0, not supported!\n",
pCurNal->sNalHeaderExt.uiQualityId, pCurNal->sNalHeaderExt.bUseRefBasePicFlag);
PAccessUnit pCurAu = pCtx->pAccessUnitList;
uint32_t uiAvailNalNum = pCurAu->uiAvailUnitsNum;
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
pCtx->bAuReadyFlag = true;
}
pCtx->iErrorCode |= dsInvalidArgument;
return NULL;
}
pNal += NAL_UNIT_HEADER_EXT_SIZE;
iNalSize -= NAL_UNIT_HEADER_EXT_SIZE;

View File

@ -93,13 +93,13 @@ void_t IdctResAddPred_c (uint8_t* pPred, const int32_t kiStride, int16_t* pRs) {
int32_t kT3 = (32 + kT1 + kT2) >> 6;
int32_t kT4 = (32 + kT1 - kT2) >> 6;
pDst[i] = pClip[ kT3 + pPred[i] ];
pDst[i + kiStride3] = pClip[ kT4 + pPred[i + kiStride3] ];
pDst[i] = WELS_CLIP1( kT3 + pPred[i] );
pDst[i + kiStride3] = WELS_CLIP1( kT4 + pPred[i + kiStride3] );
kT1 = iSrc[i] - iSrc[i + 8];
kT2 = (iSrc[i + 4] >> 1) - iSrc[i + 12];
pDst[i + kiStride] = pClip[ ((32 + kT1 + kT2) >> 6) + pDst[i + kiStride] ];
pDst[i + kiStride2] = pClip[ ((32 + kT1 - kT2) >> 6) + pDst[i + kiStride2] ];
pDst[i + kiStride] = WELS_CLIP1( ((32 + kT1 + kT2) >> 6) + pDst[i + kiStride] );
pDst[i + kiStride2] = WELS_CLIP1( ((32 + kT1 - kT2) >> 6) + pDst[i + kiStride2] );
}
}
@ -124,4 +124,4 @@ void_t GetI4LumaIChromaAddrTable (int32_t* pBlockOffset, const int32_t kiYStride
}
}
} // namespace WelsDec
} // namespace WelsDec

View File

@ -519,6 +519,11 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
if (uiSliceType > 4)
uiSliceType -= 5;
if((eNalType == NAL_UNIT_CODED_SLICE_IDR) && (uiSliceType != 2)){
WelsLog (pCtx, WELS_LOG_WARNING, "Invalid slice type(%d) in IDR picture. \n", uiSliceType);
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE);
}
if (kbExtensionFlag) {
if (uiSliceType > 2) {
WelsLog (pCtx, WELS_LOG_WARNING, "Invalid slice type(%d).\n", uiSliceType);

View File

@ -390,7 +390,7 @@ int32_t CheckIntra16x16PredMode (uint8_t uiSampleAvail, int8_t* pMode) {
int32_t bLeftTopAvail = uiSampleAvail & 0x02;
int32_t iTopAvail = uiSampleAvail & 0x01;
if (*pMode > MAX_PRED_MODE_ID_I16x16) {
if ((*pMode < 0) || (*pMode > MAX_PRED_MODE_ID_I16x16)) {
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
@ -419,10 +419,6 @@ int32_t CheckIntraChromaPredMode (uint8_t uiSampleAvail, int8_t* pMode) {
int32_t bLeftTopAvail = uiSampleAvail & 0x02;
int32_t iTopAvail = uiSampleAvail & 0x01;
if (*pMode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
if (C_PRED_DC == *pMode) {
if (iLeftAvail && iTopAvail) {
return 0;
@ -451,8 +447,8 @@ int32_t CheckIntra4x4PredMode (int32_t* pSampleAvail, int8_t* pMode, int32_t iIn
int8_t iFinalMode;
if (*pMode > MAX_PRED_MODE_ID_I4x4) {
return -1;
if ((*pMode < 0) || (*pMode > MAX_PRED_MODE_ID_I4x4)) {
return ERR_INVALID_INTRA4X4_MODE;
}
if (I4_PRED_DC == *pMode) {
@ -468,7 +464,7 @@ int32_t CheckIntra4x4PredMode (int32_t* pSampleAvail, int8_t* pMode, int32_t iIn
} else {
bool_t bModeAvail = CHECK_I4_MODE (*pMode, iLeftAvail, iTopAvail, bLeftTopAvail);
if (0 == bModeAvail) {
return -1;
return ERR_INVALID_INTRA4X4_MODE;
}
iFinalMode = *pMode;
@ -746,7 +742,7 @@ int32_t WelsResidualBlockCavlc (SVlcTable* pVlcTable, uint8_t* pNonZeroCountCach
iZerosLeft = 0;
}
if (iZerosLeft < 0) {
if ((iZerosLeft < 0) || ((iZerosLeft + uiTotalCoeff) > iMaxNumCoeff)) {
return ERR_INFO_CAVLC_INVALID_ZERO_LEFT;
}
if ((i = CavlcGetRunBefore (iRun, &sReadBitsCache, uiTotalCoeff, pVlcTable, iZerosLeft)) == -1) {
@ -803,7 +799,7 @@ int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPred
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiTmp;
if (pNeighAvail->iLeftAvail) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
@ -842,7 +838,7 @@ int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPred
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode < 0) {
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
@ -856,9 +852,12 @@ int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPred
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
pCurDqLayer->pChromaPredMode[iMbXy] = BsGetUe (pBs);
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
uiTmp = BsGetUe (pBs);
if (uiTmp > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiTmp;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
@ -872,7 +871,7 @@ int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPred
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiTmp;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
@ -911,7 +910,7 @@ int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPred
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode < 0) {
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
@ -925,10 +924,12 @@ int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPred
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
pCurDqLayer->pChromaPredMode[iMbXy] = BsGetUe (pBs);
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
uiTmp = BsGetUe (pBs);
if (uiTmp > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiTmp;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
@ -938,7 +939,7 @@ int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPred
int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiTmp;
if (pNeighAvail->iLeftAvail) {
uiNeighAvail = (1 << 2);
}
@ -953,10 +954,13 @@ int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pB
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = BsGetUe (pBs);
uiTmp = BsGetUe (pBs);
if (uiTmp > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiTmp;
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
@ -966,7 +970,7 @@ int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pB
int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiTmp;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
uiNeighAvail = (1 << 2);
}
@ -981,10 +985,13 @@ int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pB
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = BsGetUe (pBs);
uiTmp = BsGetUe (pBs);
if (uiTmp > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiTmp;
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}