shithub: openh264

Download patch

ref: 8fb4048241690ce25bdc79c6d20bbbf65bac9ca5
parent: d422ee59ad5c88ff0f87c47945c7f780b042b9c2
parent: 57043d16ad069bda72a555b84166510bcbd0636a
author: huili2 <huili2@cisco.com>
date: Mon Dec 15 12:39:36 EST 2014

Merge pull request #1627 from HaiboZhu/Debug_potential_out_of_memory

Reset parameter set status and clear AU list when out of memory

--- a/codec/decoder/core/inc/decoder.h
+++ b/codec/decoder/core/inc/decoder.h
@@ -143,6 +143,8 @@
 void UpdateDecStatNoFreezingInfo (PWelsDecoderContext pCtx);
 //update decoder statistics information
 void UpdateDecStat (PWelsDecoderContext pCtx, const bool kbOutput);
+//Destroy picutre buffer
+void DestroyPicBuff (PPicBuff* ppPicBuf);
 #ifdef __cplusplus
 }
 #endif//__cplusplus
--- a/codec/decoder/core/inc/decoder_core.h
+++ b/codec/decoder/core/inc/decoder_core.h
@@ -158,6 +158,8 @@
 void ForceClearCurrentNal (PAccessUnit pAu);
 
 bool bCheckRefPicturesComplete (PWelsDecoderContext pCtx); // Check whether all ref pictures are complete
+
+void ForceResetParaSetStatusAndAUList(PWelsDecoderContext pCtx);
 } // namespace WelsDec
 
 #endif//WELS_DECODER_CORE_H__
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -76,20 +76,26 @@
   pPicBuf->ppPic = (PPicture*)WelsMalloc (kiSize * sizeof (PPicture), "PPicture*");
 
   if (NULL == pPicBuf->ppPic) {
+    pPicBuf->iCapacity = 0;
+    DestroyPicBuff (&pPicBuf);
     return 1;
   }
+
   for (iPicIdx = 0; iPicIdx < kiSize; ++ iPicIdx) {
     PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
     if (NULL == pPic) {
+      // init capacity first for free memory
+      pPicBuf->iCapacity = iPicIdx;
+      DestroyPicBuff (&pPicBuf);
       return 1;
     }
     pPicBuf->ppPic[iPicIdx] = pPic;
   }
 
-  // initialize context in queue
+// initialize context in queue
   pPicBuf->iCapacity	 = kiSize;
   pPicBuf->iCurrentIdx = 0;
-  *ppPicBuf			 = pPicBuf;
+  * ppPicBuf			 = pPicBuf;
 
   return 0;
 }
@@ -112,26 +118,32 @@
   pPicNewBuf->ppPic = (PPicture*)WelsMalloc (kiNewSize * sizeof (PPicture), "PPicture*");
 
   if (NULL == pPicNewBuf->ppPic) {
+    pPicNewBuf->iCapacity = 0;
+    DestroyPicBuff (&pPicNewBuf);
     return 1;
   }
-  // copy old PicBuf to new PicBuf
-  memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof (PPicture));
 
-
   // increase new PicBuf
   for (iPicIdx = kiOldSize; iPicIdx < kiNewSize; ++ iPicIdx) {
     PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
     if (NULL == pPic) {
+      // Set maximum capacity as the new malloc memory at the tail
+      pPicNewBuf->iCapacity = iPicIdx;
+      DestroyPicBuff (&pPicNewBuf);
       return 1;
     }
     pPicNewBuf->ppPic[iPicIdx] = pPic;
   }
-  // initialize context in queue
+
+  // copy old PicBuf to new PicBuf
+  memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof (PPicture));
+
+// initialize context in queue
   pPicNewBuf->iCapacity	 = kiNewSize;
   pPicNewBuf->iCurrentIdx = pPicOldBuf->iCurrentIdx;
-  *ppPicBuf			 = pPicNewBuf;
-  
-  for(int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
+  * ppPicBuf			 = pPicNewBuf;
+
+  for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
     pPicNewBuf->ppPic[i]->bUsedAsRef = false;
     pPicNewBuf->ppPic[i]->bIsLongRef = false;
     pPicNewBuf->ppPic[i]->uiRefCount = 0;
@@ -138,7 +150,7 @@
     pPicNewBuf->ppPic[i]->bAvailableFlag = true;
     pPicNewBuf->ppPic[i]->bIsComplete = false;
   }
-  // remove old PicBuf
+// remove old PicBuf
   if (pPicOldBuf->ppPic != NULL) {
     WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
     pPicOldBuf->ppPic	= NULL;
@@ -168,6 +180,8 @@
   pPicNewBuf->ppPic = (PPicture*)WelsMalloc (kiNewSize * sizeof (PPicture), "PPicture*");
 
   if (NULL == pPicNewBuf->ppPic) {
+    pPicNewBuf->iCapacity	 = 0;
+    DestroyPicBuff (&pPicNewBuf);
     return 1;
   }
 
@@ -203,7 +217,7 @@
   pPicNewBuf->iCapacity	 = kiNewSize;
   *ppPicBuf			 = pPicNewBuf;
 
-  for(int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
+  for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
     pPicNewBuf->ppPic[i]->bUsedAsRef = false;
     pPicNewBuf->ppPic[i]->bIsLongRef = false;
     pPicNewBuf->ppPic[i]->uiRefCount = 0;
@@ -223,7 +237,7 @@
   return 0;
 }
 
-static void DestroyPicBuff (PPicBuff* ppPicBuf) {
+void DestroyPicBuff (PPicBuff* ppPicBuf) {
   PPicBuff pPicBuf = NULL;
 
   if (NULL == ppPicBuf || NULL == *ppPicBuf)
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -1318,6 +1318,18 @@
     -- pAu->uiAvailUnitsNum;
 }
 
+void ForceResetParaSetStatusAndAUList (PWelsDecoderContext pCtx) {
+  pCtx->bSpsExistAheadFlag = false;
+  pCtx->bSubspsExistAheadFlag = false;
+  pCtx->bPpsExistAheadFlag = false;
+
+  // Force clear the AU list
+  pCtx->pAccessUnitList->uiAvailUnitsNum	= 0;
+  pCtx->pAccessUnitList->uiActualUnitsNum	= 0;
+  pCtx->pAccessUnitList->uiStartPos		= 0;
+  pCtx->pAccessUnitList->uiEndPos		= 0;
+  pCtx->pAccessUnitList->bCompletedAuFlag	= false;
+}
 
 void CheckAvailNalUnitsListContinuity (PWelsDecoderContext pCtx, int32_t iStartIdx, int32_t iEndIdx) {
   PAccessUnit pCurAu = pCtx->pAccessUnitList;
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -375,7 +375,8 @@
     pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
         (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
     pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
-    (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum + m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
+        (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum +
+         m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
     return cmResultSuccess;
   }
 
@@ -439,6 +440,9 @@
 
     eNalType	= m_pDecContext->sCurNalHead.eNalUnitType;
 
+    if (m_pDecContext->iErrorCode & dsOutOfMemory) {
+      ForceResetParaSetStatusAndAUList (m_pDecContext);
+    }
     //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 == m_pDecContext->eVideoType)) {
@@ -480,11 +484,19 @@
         m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
       }
       int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum;
-      m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ? (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) :((m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((iMbConcealedNum * 100) / m_pDecContext->iMbNum));
-      m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ? (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) :((m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
+      m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ?
+          (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
+                m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
+                      iMbConcealedNum * 100) / m_pDecContext->iMbNum));
+      m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ?
+          (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
+                m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
+                      m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
       m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
-      m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0? 0 : m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
-      m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0? 0 :  m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
+      m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
+          m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
+      m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
+          m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
     }
     iEnd = WelsTime();
     m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;