shithub: openh264

Download patch

ref: 2294b786cf028234c1ebae956be0287af1e0152f
parent: 9ea4d5bd73f1ade5a2a41f4fb72422687e5ee5cb
parent: b6e28495dde19724b6c4854d5013ce72cd6b5b66
author: sijchen <sijchen@cisco.com>
date: Fri Feb 27 12:44:03 EST 2015

Merge pull request #1774 from huili2/dec_flowchart_ec

modify decoder flowchart for non vcl AU check

--- a/codec/decoder/core/inc/decoder_core.h
+++ b/codec/decoder/core/inc/decoder_core.h
@@ -153,6 +153,7 @@
 
 int32_t WelsDecodeAccessUnitStart (PWelsDecoderContext pCtx);
 void WelsDecodeAccessUnitEnd (PWelsDecoderContext pCtx);
+void DecodeFinishUpdate (PWelsDecoderContext pCtx);
 
 void ForceResetCurrentAccessUnit (PAccessUnit pAu);
 void ForceClearCurrentNal (PAccessUnit pAu);
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -178,6 +178,7 @@
 
 
   switch (pNalUnitHeader->eNalUnitType) {
+  case NAL_UNIT_AU_DELIMITER:
   case NAL_UNIT_SEI:
     if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
       pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -661,25 +661,24 @@
                                0; // set 4 reserved bytes to zero
           pNalPayload	= ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
           if (pNalPayload) { //parse correct
-            if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
-              CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
-            }
             if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
               iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
             }
-            if (pCtx->bAuReadyFlag) {
+            CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
+            if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
               ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
+            }
+          }
+          DecodeFinishUpdate (pCtx);
 
-              if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
+          if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
 #ifdef LONG_TERM_REF
-                pCtx->bParamSetsLostFlag = true;
+            pCtx->bParamSetsLostFlag = true;
 #else
-                pCtx->bReferenceLostAtT0Flag = true;
+            pCtx->bReferenceLostAtT0Flag = true;
 #endif
-                if (dsOutOfMemory & pCtx->iErrorCode) {
-                  return pCtx->iErrorCode;
-                }
-              }
+            if (dsOutOfMemory & pCtx->iErrorCode) {
+              return pCtx->iErrorCode;
             }
           }
           if (iRet) {
@@ -720,24 +719,23 @@
     pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
     if (pNalPayload) { //parse correct
-      if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
-        CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
-      }
       if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
         iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
       }
-      if (pCtx->bAuReadyFlag) {
+      CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
+      if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
         ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
+      }
+    }
+    DecodeFinishUpdate (pCtx);
 
-        if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
+    if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
 #ifdef LONG_TERM_REF
-          pCtx->bParamSetsLostFlag = true;
+      pCtx->bParamSetsLostFlag = true;
 #else
-          pCtx->bReferenceLostAtT0Flag = true;
+      pCtx->bReferenceLostAtT0Flag = true;
 #endif
-          return pCtx->iErrorCode;
-        }
-      }
+      return pCtx->iErrorCode;
     }
     if (iRet) {
       iRet = 0;
@@ -760,15 +758,16 @@
       pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
 
       ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
+    }
+    DecodeFinishUpdate (pCtx);
 
-      if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
+    if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
 #ifdef LONG_TERM_REF
-        pCtx->bParamSetsLostFlag = true;
+      pCtx->bParamSetsLostFlag = true;
 #else
-        pCtx->bReferenceLostAtT0Flag = true;
+      pCtx->bReferenceLostAtT0Flag = true;
 #endif
-        return pCtx->iErrorCode;
-      }
+      return pCtx->iErrorCode;
     }
   }
 
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -571,17 +571,7 @@
     return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_PPS_ID);
   }
 
-  if (pCtx->iOverwriteFlags & OVERWRITE_PPS) {
-    if (pCtx->pAccessUnitList->uiAvailUnitsNum > 1 || pCtx->iTotalNumMbRec > 0) {
-      pPps    = &pCtx->sPpsBuffer[MAX_PPS_COUNT];
-    } else {
-      memcpy (&pCtx->sPpsBuffer[pCtx->sPpsBuffer[MAX_PPS_COUNT].iPpsId], &pCtx->sPpsBuffer[MAX_PPS_COUNT], sizeof (SPps));
-      pCtx->iOverwriteFlags ^= OVERWRITE_PPS;
-      pPps = &pCtx->sPpsBuffer[iPpsId];
-    }
-  } else {
-    pPps    = &pCtx->sPpsBuffer[iPpsId];
-  }
+  pPps    = &pCtx->sPpsBuffer[iPpsId];
 
   if (pPps->uiNumSliceGroups == 0) {
     WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid PPS referenced");
@@ -590,19 +580,7 @@
   }
 
   if (kbExtensionFlag) {
-    if (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS) {
-      if (pCtx->pAccessUnitList->uiAvailUnitsNum > 1 || pCtx->iTotalNumMbRec > 0) {
-        pSubsetSps	= &pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT];
-      } else {
-        memcpy (&pCtx->sSubsetSpsBuffer[pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT].sSps.iSpsId],
-                &pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT], sizeof (SSubsetSps));
-        pCtx->iOverwriteFlags ^= OVERWRITE_SUBSETSPS;
-        pSubsetSps	= &pCtx->sSubsetSpsBuffer[pPps->iSpsId];
-        ResetActiveSPSForEachLayer (pCtx);
-      }
-    } else {
-      pSubsetSps      = &pCtx->sSubsetSpsBuffer[pPps->iSpsId];
-    }
+    pSubsetSps      = &pCtx->sSubsetSpsBuffer[pPps->iSpsId];
     pSps		= &pSubsetSps->sSps;
     if (pCtx->bSubspsAvailFlags[pPps->iSpsId] == false) {
       WelsLog (pLogCtx, WELS_LOG_ERROR, "SPS id is invalid!");
@@ -615,18 +593,7 @@
       pCtx->iErrorCode |= dsNoParamSets;
       return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SPS_ID);
     }
-    if (pCtx->iOverwriteFlags & OVERWRITE_SPS) {
-      if (pCtx->pAccessUnitList->uiAvailUnitsNum > 1 || pCtx->iTotalNumMbRec > 0) {
-        pSps		= &pCtx->sSpsBuffer[MAX_SPS_COUNT];
-      } else {
-        memcpy (&pCtx->sSpsBuffer[pCtx->sSpsBuffer[MAX_SPS_COUNT].iSpsId], &pCtx->sSpsBuffer[MAX_SPS_COUNT], sizeof (SSps));
-        pCtx->iOverwriteFlags ^= OVERWRITE_SPS;
-        pSps		= &pCtx->sSpsBuffer[pPps->iSpsId];
-        ResetActiveSPSForEachLayer (pCtx);
-      }
-    } else {
-      pSps		= &pCtx->sSpsBuffer[pPps->iSpsId];
-    }
+    pSps		= &pCtx->sSpsBuffer[pPps->iSpsId];
   }
   pSliceHead->iPpsId = iPpsId;
   pSliceHead->iSpsId = pPps->iSpsId;
@@ -1722,7 +1689,23 @@
   }
   pCtx->iOverwriteFlags = OVERWRITE_NONE;
 }
+
 /*
+ * DecodeFinishUpdate
+ * decoder finish decoding, update active parameter sets and new seq status
+ *
+ */
+
+void DecodeFinishUpdate (PWelsDecoderContext pCtx) {
+  pCtx->bNewSeqBegin = false;
+  WriteBackActiveParameters (pCtx);
+  pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin;
+  pCtx->bNextNewSeqBegin = false; // reset it
+  if (pCtx->bNewSeqBegin)
+    ResetActiveSPSForEachLayer (pCtx);
+}
+
+/*
  * ConstructAccessUnit
  * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to
  * joint a collective access unit.
@@ -1824,12 +1807,6 @@
 
   WelsDecodeAccessUnitEnd (pCtx);
 
-  pCtx->bNewSeqBegin = false;
-  WriteBackActiveParameters (pCtx);
-  pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin;
-  pCtx->bNextNewSeqBegin = false; // reset it
-  if (pCtx->bNewSeqBegin)
-    ResetActiveSPSForEachLayer (pCtx);
   if (ERR_NONE != iErr) {
     WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "returned error from decoding:[0x%x]", iErr);
     return iErr;
@@ -2195,36 +2172,52 @@
 
 bool CheckAndFinishLastPic (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) {
   PAccessUnit pAu = pCtx->pAccessUnitList;
-  if (pAu->uiAvailUnitsNum == 0)
-    return true;
-  PNalUnit pCurNal = pAu->pNalUnitsList[pAu->uiEndPos];
-  if ((pCtx->iTotalNumMbRec != 0)
-      && (CheckAccessUnitBoundaryExt (&pCtx->sLastNalHdrExt, &pCurNal->sNalHeaderExt, &pCtx->sLastSliceHeader,
-                                      &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader))) {
-    //Do Error Concealment here
-    if (NeedErrorCon (pCtx)) { //should always be true!
-      if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
-        ImplementErrorCon (pCtx);
-        pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
-        pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
-        pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
+  bool bAuBoundaryFlag = false;
+  if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) { //VCL data, AU list should have data
+    PNalUnit pCurNal = pAu->pNalUnitsList[pAu->uiEndPos];
+    bAuBoundaryFlag = (pCtx->iTotalNumMbRec != 0)
+                      && (CheckAccessUnitBoundaryExt (&pCtx->sLastNalHdrExt, &pCurNal->sNalHeaderExt, &pCtx->sLastSliceHeader,
+                          &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader));
+  } else { //non VCL
+    if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_AU_DELIMITER) {
+      bAuBoundaryFlag = true;
+    } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SEI) {
+      bAuBoundaryFlag = true;
+    } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SPS) {
+      bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_SPS);
+    } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SUBSET_SPS) {
+      bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS);
+    } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_PPS) {
+      bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_PPS);
+    }
+    if (bAuBoundaryFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) { //Construct remaining data first
+      ConstructAccessUnit (pCtx, ppDst, pDstInfo);
+    }
+  }
 
-        DecodeFrameConstruction (pCtx, ppDst, pDstInfo);
-        pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use
-        if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
-          MarkECFrameAsRef (pCtx);
-        }
-      } else {
-        if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
-          pCtx->pDec = NULL;
-          return false;
-        }
+  //Do Error Concealment here
+  if (bAuBoundaryFlag && (pCtx->iTotalNumMbRec != 0) && NeedErrorCon (pCtx)) { //AU ready but frame not completely reconed
+    if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
+      ImplementErrorCon (pCtx);
+      pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
+      pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
+      pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
+
+      DecodeFrameConstruction (pCtx, ppDst, pDstInfo);
+      pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use
+      if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
+        MarkECFrameAsRef (pCtx);
       }
-      pCtx->pDec = NULL;
-      pCtx->iPrevFrameNum = pCtx->sLastSliceHeader.iFrameNum; //save frame_num
-      if (pCtx->bLastHasMmco5)
-        pCtx->iPrevFrameNum = 0;
+    } else {
+      if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
+        pCtx->pDec = NULL;
+        return false;
+      }
     }
+    pCtx->pDec = NULL;
+    pCtx->iPrevFrameNum = pCtx->sLastSliceHeader.iFrameNum; //save frame_num
+    if (pCtx->bLastHasMmco5)
+      pCtx->iPrevFrameNum = 0;
   }
   return ERR_NONE;
 }