shithub: openh264

Download patch

ref: e6a6b09dba1a008fbb17b01bbb9d48e74deb29cb
parent: 6ba85394e0adfaaa506da900bc93e449e436fb26
author: huili2 <huili2@cisco.com>
date: Tue Nov 8 05:01:29 EST 2016

fix parseonly issues when bs is very large

--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -104,11 +104,19 @@
           pCtx->bParamSetsLostFlag = false;
           //find required sps, pps and write into dst buff
           pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId];
+          pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
+          if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) {
+            WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
+                     "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen,
+                     pPpsBs->uiPpsBsLen);
+            pCtx->iErrorCode |= dsOutOfMemory;
+            pCtx->pParserBsInfo->iNalNum = 0;
+            return ERR_INFO_OUT_OF_MEMORY;
+          }
           memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen);
           pParser->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen;
           pCtx->iNalLenInByte[pCtx->iNalNum ++] = pSpsBs->uiSpsBsLen;
           pDstBuf += pSpsBs->uiSpsBsLen;
-          pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
           memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen);
           pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen;
           pDstBuf += pPpsBs->uiPpsBsLen;
@@ -121,6 +129,15 @@
         iNalLen = pCurNal->sNalData.sVclNal.iNalLength;
         pNalBs = pCurNal->sNalData.sVclNal.pNalPos;
         pParser->iNalLenInByte [pParser->iNalNum ++] = iNalLen;
+        if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) {
+          WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
+                   "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. \n",
+                   (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY);
+          pCtx->iErrorCode |= dsOutOfMemory;
+          pCtx->pParserBsInfo->iNalNum = 0;
+          return ERR_INFO_OUT_OF_MEMORY;
+        }
+
         memcpy (pDstBuf, pNalBs, iNalLen);
         pDstBuf += iNalLen;
       }
@@ -497,6 +514,8 @@
   int32_t iNewBuffLen = WELS_MAX ((kiSrcLen * MAX_BUFFERED_NUM), (pCtx->iMaxBsBufferSizeInByte << iExpandStepShift));
   //allocate new bs buffer
   CMemoryAlign* pMa = pCtx->pMemAlign;
+
+  //Realloc sRawData
   uint8_t* pNewBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sRawData.pHead"));
   if (pNewBsBuff == NULL)
     return ERR_INFO_OUT_OF_MEMORY;
@@ -511,12 +530,28 @@
 
   //Copy current buffer status to new buffer
   memcpy (pNewBsBuff, pCtx->sRawData.pHead, pCtx->iMaxBsBufferSizeInByte);
-  pCtx->iMaxBsBufferSizeInByte = iNewBuffLen;
   pCtx->sRawData.pStartPos = pNewBsBuff + (pCtx->sRawData.pStartPos - pCtx->sRawData.pHead);
-  pCtx->sRawData.pCurPos = pNewBsBuff + (pCtx->sRawData.pCurPos - pCtx->sRawData.pHead);
-  pCtx->sRawData.pEnd = pNewBsBuff + iNewBuffLen;
+  pCtx->sRawData.pCurPos   = pNewBsBuff + (pCtx->sRawData.pCurPos   - pCtx->sRawData.pHead);
+  pCtx->sRawData.pEnd      = pNewBsBuff + iNewBuffLen;
   pMa->WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData.pHead");
   pCtx->sRawData.pHead = pNewBsBuff;
+
+  if (pCtx->pParam->bParseOnly) {
+    //Realloc sSavedData
+    uint8_t* pNewSavedBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sSavedData.pHead"));
+    if (pNewSavedBsBuff == NULL)
+      return ERR_INFO_OUT_OF_MEMORY;
+
+    //Copy current buffer status to new buffer
+    memcpy (pNewSavedBsBuff, pCtx->sSavedData.pHead, pCtx->iMaxBsBufferSizeInByte);
+    pCtx->sSavedData.pStartPos = pNewSavedBsBuff + (pCtx->sSavedData.pStartPos - pCtx->sSavedData.pHead);
+    pCtx->sSavedData.pCurPos   = pNewSavedBsBuff + (pCtx->sSavedData.pCurPos   - pCtx->sSavedData.pHead);
+    pCtx->sSavedData.pEnd      = pNewSavedBsBuff + iNewBuffLen;
+    pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData.pHead");
+    pCtx->sSavedData.pHead = pNewSavedBsBuff;
+  }
+
+  pCtx->iMaxBsBufferSizeInByte = iNewBuffLen;
   return ERR_NONE;
 }
 
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -458,7 +458,10 @@
     return dsInvalidArgument;
   }
   if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
-    return dsOutOfMemory;
+    if (ResetDecoder())
+      return dsOutOfMemory;
+
+    return dsErrorFree;
   }
   if (kiSrcLen > 0 && kpSrc != NULL) {
 #ifdef OUTPUT_BIT_STREAM
@@ -513,6 +516,8 @@
     if (m_pDecContext->iErrorCode & dsOutOfMemory) {
       if (ResetDecoder())
         return dsOutOfMemory;
+
+      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) ||
@@ -611,7 +616,10 @@
     return dsInvalidArgument;
   }
   if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
-    return dsOutOfMemory;
+    if (ResetDecoder())
+      return dsOutOfMemory;
+
+    return dsErrorFree;
   }
   if (kiSrcLen > 0 && kpSrc != NULL) {
 #ifdef OUTPUT_BITSTREAM