shithub: openh264

Download patch

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);
 }