shithub: openh264

Download patch

ref: d03150947476ea806c2de8c367f6c34b7b17efa5
parent: 1b1654e9c6393bfbb491c47f261934d20b7f252b
author: huili2 <[email protected]>
date: Sun Apr 20 04:20:12 EDT 2014

add DPB management if frame loss happens

--- a/codec/console/dec/src/h264dec.cpp
+++ b/codec/console/dec/src/h264dec.cpp
@@ -174,8 +174,8 @@
       fread (&iSliceSize, 1, sizeof (int32_t), fpTrack);
 #else
     for (i = 0; i < iFileSize; i++) {
-      if (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 &&
-          pBuf[iBufPos + i + 3] == 1 && i > 0) {
+      if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
+           && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
         break;
       }
     }
@@ -303,7 +303,7 @@
 }
 
 #if (defined(ANDROID_NDK)||defined(APPLE_IOS))
-int32_t DecMain(int32_t iArgC, char* pArgV[]) {
+int32_t DecMain (int32_t iArgC, char* pArgV[]) {
 #else
 int32_t main (int32_t iArgC, char* pArgV[]) {
 #endif
@@ -429,7 +429,8 @@
   int32_t iHeight = 0;
 
 
-  H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth, iHeight,
+  H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth,
+                      iHeight,
                       (!strOptionFile.empty() ? strOptionFile.c_str() : NULL));
 
   if (sDecParam.pFileNameRestructed != NULL) {
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -57,6 +57,10 @@
 static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic);
 static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx);
 static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx);
+#ifdef LONG_TERM_REF
+int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum);
+#endif
+static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx);
 
 static void SetUnRef (PPicture pRef) {
   if (NULL != pRef) {
@@ -211,7 +215,6 @@
 
   int32_t iRet = ERR_NONE;
 
-  pCtx->pDec->bUsedAsRef = true;
   pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
   pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
 
@@ -232,8 +235,14 @@
   } else {
     if (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag) {
       iRet = MMCO (pCtx, pRefPicMarking);
-      if (iRet != ERR_NONE)
-        return iRet;
+      if (iRet != ERR_NONE) {
+        if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
+          iRet = RemainOneBufferInDpbForEC (pCtx);
+        } else {
+          return iRet;
+        }
+      }
+
       if (pCtx->bLastHasMmco5) {
         pCtx->pDec->iFrameNum = 0;
         pCtx->pDec->iFramePoc = 0;
@@ -241,14 +250,23 @@
 
     } else {
       iRet = SlidingWindow (pCtx);
-      if (iRet != ERR_NONE)
-        return iRet;
+      if (iRet != ERR_NONE) {
+        if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
+          iRet = RemainOneBufferInDpbForEC (pCtx);
+        } else {
+          return iRet;
+        }
+      }
     }
   }
 
   if (!pCtx->pDec->bIsLongRef) {
     if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX(1,pCtx->pSps->iNumRefFrames)) {
-      return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
+      if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
+        iRet = RemainOneBufferInDpbForEC (pCtx);
+      } else {
+        return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
+      }
     }
     AddShortTermToList (pRefPic, pCtx->pDec);
   }
@@ -479,6 +497,53 @@
       iRet = AddLongTermToList (pRefPic, pPic, iLongTermFrameIdx);
       break;
     }
+  }
+
+  return iRet;
+}
+
+#ifdef LONG_TERM_REF
+int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum) {
+  int32_t iLTRFrameIndex = -1;
+  PPicture pPic;
+  for (int i = 0; i < pRefPic->uiLongRefCount[0]; ++i) {
+    pPic = pRefPic->pLongRefList[LIST_0][i];
+    if (pPic->iFrameNum == iAncLTRFrameNum) {
+      return (pPic->iLongTermFrameIdx);
+    }
+  }
+  return iLTRFrameIndex;
+}
+#endif
+
+static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx) {
+  int32_t iRet = ERR_NONE;
+  PRefPic pRefPic = &pCtx->sRefPic;
+  if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] < pCtx->pSps->iNumRefFrames)
+    return iRet;
+
+  if (pRefPic->uiShortRefCount[0] > 0) {
+    iRet = SlidingWindow (pCtx);
+  } else { //all LTR, remove the smallest long_term_frame_idx
+    uint32_t uiLongTermFrameIdx = 0;
+    uint32_t uiMaxLongTermFrameIdx = pRefPic->iMaxLongTermFrameIdx;
+#ifdef LONG_TERM_REF
+    uint32_t uiCurrLTRFrameIdx = GetLTRFrameIndex (pRefPic, pCtx->iFrameNumOfAuMarkedLtr);
+#endif
+    while ((pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) && (uiLongTermFrameIdx <= uiMaxLongTermFrameIdx)) {
+#ifdef LONG_TERM_REF
+      if (uiLongTermFrameIdx == uiCurrLTRFrameIdx) {
+        uiLongTermFrameIdx++;
+        continue;
+      }
+#endif
+      WelsDelLongFromListSetUnref (pRefPic, uiLongTermFrameIdx);
+      uiLongTermFrameIdx++;
+    }
+  }
+  if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) { //fail to remain one empty buffer in DPB
+    WelsLog (pCtx, WELS_LOG_WARNING, "RemainOneBufferInDpbForEC(): empty one DPB failed for EC!\n");
+    iRet = ERR_INFO_REF_COUNT_OVERFLOW;
   }
 
   return iRet;