ref: 51a138eb9843625b5ebe7c7bc86e7c985acf0eb1
parent: be8e62ff47c9d7967e9f402baabe34de1482ec86
author: xiaotianshimail <xiaotianshimail@gmail.com>
date: Sat Feb 20 10:42:56 EST 2021
B Slice bitstream error concealment support. Fix OSS-FUZZ reported erors: 26285,26291,26296,26301,26302,26303,26319,26323,29431 and more
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -513,6 +513,7 @@
int16_t lastReadyHeightOffset[LIST_A][MAX_REF_PIC_COUNT]; //last ready reference MB offset
PPictInfo pPictInfoList;
PPictReoderingStatus pPictReoderingStatus;
+ SBufferInfo* pDstInfo;
} SWelsDecoderContext, *PWelsDecoderContext;
typedef struct tagSWelsDecThread {
--- a/codec/decoder/core/inc/mv_pred.h
+++ b/codec/decoder/core/inc/mv_pred.h
@@ -44,6 +44,10 @@
#include "dec_frame.h"
#include "decoder_context.h"
+#define RETURN_ERR_IF_NULL(pRefPic0) \
+if ( pRefPic0 == NULL) \
+ return GENERATE_ERROR_NO(ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX)
+
namespace WelsDec {
/*!
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -259,6 +259,7 @@
PPicBuff pPicBuf = NULL;
ResetReorderingPictureBuffers (pCtx->pPictReoderingStatus, pCtx->pPictInfoList, false);
+ if (pCtx->pDstInfo) pCtx->pDstInfo->iBufferStatus = 0;
if (NULL == ppPicBuf || NULL == *ppPicBuf)
return;
@@ -303,6 +304,7 @@
pPictInfo[i].bLastGOP = false;
pPictInfo[i].iPOC = IMinInt32;
}
+ pPictInfo->sBufferInfo.iBufferStatus = 0;
}
}
--- a/codec/decoder/core/src/parse_mb_syn_cabac.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cabac.cpp
@@ -774,6 +774,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
iRef[listIdx] = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -811,6 +812,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
ref_idx = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(pCtx->sRefPic.pRefList[listIdx][ref_idx]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -855,6 +857,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
ref_idx = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(pCtx->sRefPic.pRefList[listIdx][ref_idx]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -989,6 +992,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
iref = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(pCtx->sRefPic.pRefList[listIdx][iref]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
--- a/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
@@ -1390,6 +1390,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
ref_idx_list[listIdx][0] = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(ppRefPic[listIdx][ref_idx_list[listIdx][0]]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -1439,6 +1440,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
iRefIdx = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(ppRefPic[listIdx][iRefIdx]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -1498,6 +1500,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
iRefIdx = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(ppRefPic[listIdx][iRefIdx]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
@@ -1644,6 +1647,7 @@
if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
iref = 0;
pCtx->iErrorCode |= dsBitstreamError;
+ RETURN_ERR_IF_NULL(ppRefPic[listIdx][iref]);
} else {
return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
}
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -450,6 +450,7 @@
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
}
ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false);
+ if (pCtx->pDstInfo) pCtx->pDstInfo->iBufferStatus = 0;
}
return ERR_INFO_UNINIT;
}
@@ -461,6 +462,7 @@
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", pCtx->iErrorCode);
memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));
ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
+ if (pCtx->pDstInfo) pCtx->pDstInfo->iBufferStatus = 0;
CloseDecoderThreads();
UninitDecoder();
InitDecoder (&sPrevParam);
@@ -811,11 +813,6 @@
}
return dsErrorFree;
}
- if ((pDecContext->iErrorCode & (dsBitstreamError | dsDataErrorConcealed)) && pDecContext->eSliceType == B_SLICE) {
- ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
- WelsResetRefPic (pDecContext);
- return dsErrorFree;
- }
//for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
(VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) {
@@ -910,6 +907,7 @@
unsigned char** ppDst,
SBufferInfo* pDstInfo) {
PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
+ pDecContext->pDstInfo = pDstInfo;
return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo);
}