shithub: openh264

Download patch

ref: 79ed7449234d5f076bf3fd950a203cae2944294a
parent: f141bd6170ffa57665e793ae95376b0460e6a768
author: Licai Guo <guolicai@gmail.com>
date: Wed Apr 16 14:27:08 EDT 2014

overwriteactivesps

--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -156,6 +156,13 @@
   PExpandPictureFunc pExpandChromaPicture[2];
 } SExpandPicFunc;
 
+enum {
+  OVERWRITE_NONE = 0,
+  OVERWRITE_PPS = 1,
+  OVERWRITE_SPS = 1 << 1,
+  OVERWRITE_SUBSETSPS = 1 << 2
+};
+
 /*
  *	SWelsDecoderContext: to maintail all modules data over decoder@framework
  */
@@ -230,14 +237,14 @@
 
   SPosOffset	sFrameCrop;
 
-  SSps				sSpsBuffer[MAX_SPS_COUNT];
-  SPps				sPpsBuffer[MAX_PPS_COUNT];
+  SSps				sSpsBuffer[MAX_SPS_COUNT + 1];
+  SPps				sPpsBuffer[MAX_PPS_COUNT + 1];
   PSliceHeader		pSliceHeader;
 
   PPicBuff	        pPicBuff[LIST_A];	// Initially allocated memory for pictures which are used in decoding.
   int32_t				iPicQueueNumber;
 
-  SSubsetSps			sSubsetSpsBuffer[MAX_SPS_COUNT];
+  SSubsetSps			sSubsetSpsBuffer[MAX_SPS_COUNT + 1];
   SNalUnit            sPrefixNal;
 
   PAccessUnit			pAccessUnitList;	// current access unit list to be performed
@@ -278,6 +285,7 @@
   uint16_t            uiCurIdrPicId;
 #endif
   bool       bNewSeqBegin;
+  int        iOverwriteFlags;
   int32_t iErrorConMethod; //
   PGetIntraPredFunc pGetI16x16LumaPredFunc[7];		//h264_predict_copy_16x16;
   PGetIntraPredFunc pGetI4x4LumaPredFunc[14];		// h264_predict_4x4_t
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -174,8 +174,6 @@
 
   switch (pNalUnitHeader->eNalUnitType) {
   case NAL_UNIT_SEI:
-  case NAL_UNIT_SPS:
-  case NAL_UNIT_PPS:
     if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
       pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
       pCtx->bAuReadyFlag = true;
@@ -730,6 +728,14 @@
   return NULL;
 }
 
+bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps) {
+  for (int i = 0; i < MAX_LAYER_NUM; i++) {
+    if (pCtx->pActiveLayerSps[i] == pSps)
+      return true;
+  }
+  return false;
+}
+
 #define  SPS_LOG2_MAX_FRAME_NUM_MINUS4_MAX 12
 #define  SPS_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4_MAX 12
 #define  SPS_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE_MAX 255
@@ -792,15 +798,9 @@
     return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_SPS_ID_OVERFLOW);
   }
   iSpsId		= uiCode;
-
-  if (kbUseSubsetFlag) {
-    pCtx->bSubspsAvailFlags[iSpsId]	= false;
-  } else {
-    pCtx->bSpsAvailFlags[iSpsId] = false;
-  }
   pSubsetSps = &sTempSubsetSps;
   pSps = &sTempSubsetSps.sSps;
-  memset (pSubsetSps, 0, sizeof(SSubsetSps));
+  memset (pSubsetSps, 0, sizeof (SSubsetSps));
   const SLevelLimits* pSLevelLimits = GetLevelLimits (uiLevelIdc, bConstraintSetFlags[3]);
   if (NULL == pSLevelLimits) {
     WelsLog (pCtx, WELS_LOG_WARNING, "ParseSps(): level_idx (%d).\n", uiLevelIdc);
@@ -897,7 +897,7 @@
     WelsLog (pCtx, WELS_LOG_ERROR, "pic_width_in_mbs(%d) exceeds the maximum allowed!\n", pSps->iMbWidth);
     return  GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
   }
-  if (((uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbWidth) > (uint64_t)(8 * pSLevelLimits->iMaxFS)) {
+  if (((uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbWidth) > (uint64_t) (8 * pSLevelLimits->iMaxFS)) {
     WelsLog (pCtx, WELS_LOG_WARNING, " the pic_width_in_mbs exceeds the level limits!\n");
   }
   WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_height_in_map_units_minus1
@@ -978,12 +978,45 @@
 
   *pPicWidth	= pSps->iMbWidth << 4;
   *pPicHeight	= pSps->iMbHeight << 4;
+  PSps pTmpSps = NULL;
   if (kbUseSubsetFlag) {
-    memcpy (&pCtx->sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof(SSubsetSps));
+    pTmpSps = &pCtx->sSubsetSpsBuffer[iSpsId].sSps;
+  } else {
+    pTmpSps = &pCtx->sSpsBuffer[iSpsId];
+  }
+  if (CheckSpsActive (pCtx, pTmpSps)) {
+    // we are overwriting the active sps, copy a temp buffer
+    if (kbUseSubsetFlag) {
+      if (memcmp (&pCtx->sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps)) != 0) {
+        if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
+          memcpy (&pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT], pSubsetSps, sizeof (SSubsetSps));
+          pCtx->bAuReadyFlag = true;
+          pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
+          pCtx->iOverwriteFlags |= OVERWRITE_SUBSETSPS;
+        } else {
+          memcpy (&pCtx->sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps));
+        }
+      }
+    } else {
+      if (memcmp (&pCtx->sSpsBuffer[iSpsId], pSps, sizeof (SSps)) != 0) {
+        if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
+          memcpy (&pCtx->sSpsBuffer[MAX_SPS_COUNT], pSps, sizeof (SSps));
+          pCtx->iOverwriteFlags |= OVERWRITE_SPS;
+          pCtx->bAuReadyFlag = true;
+          pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
+        } else {
+          memcpy (&pCtx->sSpsBuffer[iSpsId], pSps, sizeof (SSps));
+        }
+      }
+    }
+  }
+  // Not overwrite active sps, just copy to final place
+  else if (kbUseSubsetFlag) {
+    memcpy (&pCtx->sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps));
     pCtx->bSubspsAvailFlags[iSpsId]	= true;
     pCtx->bSubspsExistAheadFlag	= true;
   } else {
-    memcpy (&pCtx->sSpsBuffer[iSpsId], pSps, sizeof(SSps));
+    memcpy (&pCtx->sSpsBuffer[iSpsId], pSps, sizeof (SSps));
     pCtx->bSpsAvailFlags[iSpsId] = true;
     pCtx->bSpsExistAheadFlag		= true;
   }
@@ -1018,10 +1051,8 @@
   if (uiPpsId >= MAX_PPS_COUNT) {
     return ERR_INFO_PPS_ID_OVERFLOW;
   }
-
-  pCtx->bPpsAvailFlags[uiPpsId] = false;
   pPps = &sTempPps;
-  memset (pPps, 0, sizeof(SPps));
+  memset (pPps, 0, sizeof (SPps));
 
   pPps->iPpsId = uiPpsId;
   WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); //seq_parameter_set_id
@@ -1102,10 +1133,23 @@
   pPps->bConstainedIntraPredFlag              = !!uiCode;
   WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //redundant_pic_cnt_present_flag
   pPps->bRedundantPicCntPresentFlag           = !!uiCode;
-
-  memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof(SPps));
-  pCtx->bPpsAvailFlags[uiPpsId] = true;
-
+  if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
+    PNalUnit pLastNalUnit = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - 1];
+    PPps pLastPps = pLastNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pPps;
+    // the active pps is overwrite, write to a temp place
+    if (pLastPps == &pCtx->sPpsBuffer[uiPpsId] && memcmp (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (*pPps)) != 0) {
+      memcpy (&pCtx->sPpsBuffer[MAX_PPS_COUNT], pPps, sizeof (SPps));
+      pCtx->iOverwriteFlags |= OVERWRITE_PPS;
+      pCtx->bAuReadyFlag = true;
+      pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
+    } else {
+      memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
+      pCtx->bPpsAvailFlags[uiPpsId] = true;
+    }
+  } else {
+    memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
+    pCtx->bPpsAvailFlags[uiPpsId] = true;
+  }
   return ERR_NONE;
 }
 
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -61,7 +61,7 @@
 extern void FreePicture (PPicture pPic);
 
 inline void GetValueOf4Bytes (uint8_t* pDstNal, int32_t iDdstIdx) {
-  ST32(pDstNal, iDdstIdx);
+  ST32 (pDstNal, iDdstIdx);
 }
 
 static int32_t CreatePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiSize,
@@ -421,7 +421,7 @@
     int32_t iSrcConsumed   = 0; // consumed bit count of source bs
     int32_t iDstIdx        = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal
     int32_t iSrcLength     = 0;	//the total size of current AU or NAL
-
+    int32_t iRet = 0;
     int32_t iConsumedBytes = 0;
     int32_t iOffset        = 0;
 
@@ -461,7 +461,9 @@
 
           iConsumedBytes = 0;
           pNalPayload	= ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
-
+          if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
+            iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
+          }
           if (pCtx->bAuReadyFlag) {
             ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
 
@@ -480,20 +482,17 @@
             //Do error concealment here
             ImplementErrorCon (pCtx);
           }
-
-          if ((IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) || IS_SEI_NAL (pCtx->sCurNalHead.eNalUnitType)) &&
-              pNalPayload) {
-            if (ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes)) {
-              if (dsNoParamSets & pCtx->iErrorCode) {
+          if (iRet) {
+            iRet = 0;
+            if (dsNoParamSets & pCtx->iErrorCode) {
 #ifdef LONG_TERM_REF
-                pCtx->bParamSetsLostFlag = true;
+              pCtx->bParamSetsLostFlag = true;
 #else
-                pCtx->bReferenceLostAtT0Flag = true;
+              pCtx->bReferenceLostAtT0Flag = true;
 #endif
-                ResetParameterSetsState (pCtx);
-              }
-              return pCtx->iErrorCode;
+              ResetParameterSetsState (pCtx);
             }
+            return pCtx->iErrorCode;
           }
 
           pDstNal += iDstIdx; //update current position
@@ -520,7 +519,9 @@
 
     iConsumedBytes = 0;
     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
-
+    if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
+      iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
+    }
     if (pCtx->bAuReadyFlag) {
       ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
 
@@ -536,22 +537,18 @@
       //Do error concealment here
       ImplementErrorCon (pCtx);
     }
-
-    if ((IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) || IS_SEI_NAL (pCtx->sCurNalHead.eNalUnitType))
-        && pNalPayload) {
-      if (ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes)) {
-        if (dsNoParamSets & pCtx->iErrorCode) {
+    if (iRet) {
+      iRet = 0;
+      if (dsNoParamSets & pCtx->iErrorCode) {
 #ifdef LONG_TERM_REF
-          pCtx->bParamSetsLostFlag = true;
+        pCtx->bParamSetsLostFlag = true;
 #else
-          pCtx->bReferenceLostAtT0Flag = true;
+        pCtx->bReferenceLostAtT0Flag = true;
 #endif
-          ResetParameterSetsState (pCtx);
-        }
-        return pCtx->iErrorCode;
+        ResetParameterSetsState (pCtx);
       }
+      return pCtx->iErrorCode;
     }
-
     pDstNal += iDstIdx;
     pRawData->pCurPos = pDstNal; //init the pCurPos for next NAL(s) storage
   } else { /* no supplementary picture payload input, but stored a picture */
@@ -574,7 +571,6 @@
         ResetParameterSetsState (pCtx);
         return pCtx->iErrorCode;
       }
-      //Do error concealment here
       ImplementErrorCon (pCtx);
     }
   }
@@ -662,7 +658,7 @@
   pCtx->pIdctResAddPredFunc	= IdctResAddPred_c;
 
 #if defined(HAVE_NEON)
-  if ( pCtx->uiCpuFlag & WELS_CPU_NEON ) {
+  if (pCtx->uiCpuFlag & WELS_CPU_NEON) {
     pCtx->pIdctResAddPredFunc	= IdctResAddPred_neon;
 
     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_neon;
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -1505,6 +1505,20 @@
   return bNewSeq;
 }
 
+static void WriteBackActiveParameters(PWelsDecoderContext pCtx) {
+  if (pCtx->iOverwriteFlags & OVERWRITE_PPS) {
+    memcpy(&pCtx->sPpsBuffer[pCtx->sPpsBuffer[MAX_PPS_COUNT].iPpsId], &pCtx->sPpsBuffer[MAX_PPS_COUNT], sizeof(SPps));
+    pCtx->bNewSeqBegin = true;
+  }
+  if (pCtx->iOverwriteFlags & OVERWRITE_SPS) {
+    memcpy(&pCtx->sSpsBuffer[pCtx->sSpsBuffer[MAX_SPS_COUNT].iSpsId], &pCtx->sSpsBuffer[MAX_SPS_COUNT], sizeof(SSps));
+    pCtx->bNewSeqBegin = true;
+  }
+  if (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS) {
+    memcpy(&pCtx->sSubsetSpsBuffer[pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT].sSps.iSpsId], &pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT], sizeof(SSubsetSps));
+  }
+  pCtx->iOverwriteFlags = OVERWRITE_NONE;
+}
 /*
  * ConstructAccessUnit
  * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to
@@ -1522,12 +1536,12 @@
   int32_t iWidth;
   int32_t iHeight;
   int32_t iStride[2] = { 0 };
-
   PAccessUnit pCurAu = pCtx->pAccessUnitList;
 
   pCtx->bAuReadyFlag = false;
   pCtx->bLastHasMmco5 = false;
-  pCtx->bNewSeqBegin = CheckNewSeqBeginAndUpdateActiveLayerSps(pCtx);
+  bool bTmpNewSeqBegin = CheckNewSeqBeginAndUpdateActiveLayerSps(pCtx);
+  pCtx->bNewSeqBegin = pCtx->bNewSeqBegin && bTmpNewSeqBegin;
   iErr = WelsDecodeAccessUnitStart (pCtx);
   GetVclNalTemporalId (pCtx);
 
@@ -1558,6 +1572,7 @@
 
   WelsDecodeAccessUnitEnd (pCtx);
   pCtx->bNewSeqBegin = false;
+  WriteBackActiveParameters(pCtx);
   if (ERR_NONE != iErr) {
     WelsLog (pCtx, WELS_LOG_INFO, "returned error from decoding:[0x%x]\n", iErr);