shithub: openh264

Download patch

ref: 2e5243e5fcc89f7301f69af4ac03dd889390523d
parent: f48b2e55ba2fba3e6c88d0fc75b645832a0d5c21
author: dong zhang <dongzha@cisco.com>
date: Tue Nov 25 09:25:08 EST 2014

add timestamp in decoder

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -577,6 +577,8 @@
   unsigned char* pDstBuff;                     ///< outputted dst buffer for parsed bitstream
   int iSpsWidthInPixel;                        ///< required SPS width info
   int iSpsHeightInPixel;                       ///< required SPS height info
+  unsigned long long uiInBsTimeStamp;               ///< input BS timestamp
+  unsigned long long uiOutBsTimeStamp;             ///< output BS timestamp
 } SParserBsInfo, *PParserBsInfo;
 
 /**
--- a/codec/api/svc/codec_def.h
+++ b/codec/api/svc/codec_def.h
@@ -196,7 +196,8 @@
 */
 typedef struct TagBufferInfo {
   int iBufferStatus;             ///< 0: one frame data is not ready; 1: one frame data is ready
-
+  unsigned long long uiInBsTimeStamp;     ///< input BS timestamp
+  unsigned long long uiOutYuvTimeStamp;     ///< output YUV timestamp, when bufferstatus is 1
   union {
     SSysMEMBuffer sSystemBuffer; ///<  memory info for one picture
   } UsrData;                     ///<  output buffer info
--- a/codec/console/dec/src/h264dec.cpp
+++ b/codec/console/dec/src/h264dec.cpp
@@ -74,7 +74,7 @@
   FILE* fpTrack = fopen ("3.len", "rb");
   unsigned long pInfo[4];
 #endif// STICK_STREAM_SIZE
-
+  unsigned long long uiTimeStamp = 0;
   int64_t iStart = 0, iEnd = 0, iTotal = 0;
   int32_t iSliceSize;
   int32_t iSliceIndex = 0;
@@ -208,8 +208,9 @@
     pData[0] = NULL;
     pData[1] = NULL;
     pData[2] = NULL;
+    uiTimeStamp ++;
     memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
-
+    sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
     pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
 
     if (sDstBufInfo.iBufferStatus == 1) {
@@ -242,6 +243,7 @@
     pData[1] = NULL;
     pData[2] = NULL;
     memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
+    sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
     pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
     if (sDstBufInfo.iBufferStatus == 1) {
       pDst[0] = pData[0];
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -402,6 +402,7 @@
 SDecoderStatistics sDecoderStatistics;// For real time debugging
 int32_t iECMVs[16][2];
 PPicture pECRefPic[16];
+unsigned long long uiTimeStamp;
 } SWelsDecoderContext, *PWelsDecoderContext;
 
 static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
--- a/codec/decoder/core/inc/nalu.h
+++ b/codec/decoder/core/inc/nalu.h
@@ -57,7 +57,7 @@
   } sVclNal;
   SPrefixNalUnit	sPrefixNal;
 } sNalData;
-
+unsigned long long uiTimeStamp;
 } SNalUnit, *PNalUnit;
 
 ///////////////////////////////////ACCESS Unit level///////////////////////////////////
--- a/codec/decoder/core/inc/picture.h
+++ b/codec/decoder/core/inc/picture.h
@@ -77,6 +77,7 @@
 
 int32_t     iSpsId; //against mosaic caused by cross-IDR interval reference.
 int32_t     iPpsId;
+unsigned long long uiTimeStamp;
 } SPicture, *PPicture;	// "Picture" declaration is comflict with Mac system
 
 } // namespace WelsDec
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -187,6 +187,7 @@
 
   case NAL_UNIT_PREFIX:
     pCurNal = &pCtx->sPrefixNal;
+    pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
 
     if (iNalSize < NAL_UNIT_HEADER_EXT_SIZE) {
       PAccessUnit pCurAu	   = pCtx->pAccessUnitList;
@@ -256,7 +257,7 @@
       pCtx->iErrorCode	|= dsOutOfMemory;
       return NULL;
     }
-
+    pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
     pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
     pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc		  = pNalUnitHeader->uiNalRefIdc;
     pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType	  = pNalUnitHeader->eNalUnitType;
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -90,6 +90,7 @@
 
   if (!pCtx->bParseOnly) {
     //////output:::normal path
+    pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
     ppDst[0]      = pPic->pData[0];
     ppDst[1]      = pPic->pData[1];
     ppDst[2]      = pPic->pData[2];
@@ -1742,7 +1743,7 @@
       int32_t iIdx = pCurAu->uiStartPos;
       int32_t iEndIdx = pCurAu->uiEndPos;
       uint8_t* pNalBs = NULL;
-
+      pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0;
       pParser->iNalNum = 0;
       pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4);
       pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4);
@@ -1774,6 +1775,7 @@
         pDstBuf += iNalLen;
       }
     } else { //error
+      pCtx->pParserBsInfo->uiOutBsTimeStamp = 0;
       pCtx->pParserBsInfo->iNalNum = 0;
       pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
       pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
@@ -1935,6 +1937,7 @@
         return ERR_INFO_REF_COUNT_OVERFLOW;
       }
     }
+    pCtx->pDec->uiTimeStamp = pNalCur->uiTimeStamp;
 
     if (pCtx->iTotalNumMbRec == 0) { //Picture start to decode
       for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i)
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -412,8 +412,9 @@
   ppDst[0] = ppDst[1] = ppDst[2] = NULL;
   m_pDecContext->iErrorCode             = dsErrorFree; //initialize at the starting of AU decoding.
   m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
+  unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
   memset (pDstInfo, 0, sizeof (SBufferInfo));
-
+  pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
 #ifdef LONG_TERM_REF
   m_pDecContext->bReferenceLostAtT0Flag       = false; //initialize for LTR
   m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
@@ -422,7 +423,12 @@
 #endif
 
   m_pDecContext->iFeedbackTidInAu             = -1; //initialize
-
+  if (pDstInfo) {
+    pDstInfo->uiOutYuvTimeStamp = 0;
+    m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
+  } else {
+    m_pDecContext->uiTimeStamp = 0;
+  }
   WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
                 pDstInfo, NULL); //iErrorCode has been modified in this function
   m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
@@ -524,6 +530,12 @@
   m_pDecContext->pParserBsInfo = pDstInfo;
   pDstInfo->iNalNum = 0;
   pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
+  if(pDstInfo) {
+    m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
+    pDstInfo->uiOutBsTimeStamp = 0;
+  } else {
+    m_pDecContext->uiTimeStamp = 0;
+  }
   WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
 
   return (DECODING_STATE) m_pDecContext->iErrorCode;
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -1032,6 +1032,53 @@
   (void) iSkipedBytes;
 }
 
+TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
+  EncodeDecodeFileParamBase p = GetParam();
+  prepareParam (1, p.slicenum,  p.width, p.height, p.frameRate);
+  encoder_->Uninitialize();
+  int rv = encoder_->InitializeExt (&param_);
+  ASSERT_TRUE (rv == cmResultSuccess);
+  
+  InitialEncDec (p.width, p.height);
+  int32_t iTraceLevel = WELS_LOG_QUIET;
+  encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+  decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+  int32_t iSpsPpsIdAddition = 1;
+  encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+  int32_t iIDRPeriod = 60;
+  encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+  SLTRConfig sLtrConfigVal;
+  sLtrConfigVal.bEnableLongTermReference = 1;
+  sLtrConfigVal.iLTRRefNum = 1;
+  encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+  int32_t iLtrPeriod = 2;
+  encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+  int iIdx = 0;
+  int iSkipedBytes;
+  unsigned long long uiEncTimeStamp = 100;
+  while (iIdx <= p.numframes) {
+    EncodeOneFrame (1);
+    //decoding after each encoding frame
+    int len = 0;
+    encToDecData (info, len);
+    unsigned char* pData[3] = { NULL };
+    memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+    uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
+    decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+    dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+    rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+    memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+    dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+    rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+    if(dstBufInfo_.iBufferStatus == 1) {
+      EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp);
+    }
+    iIdx++;
+    uiEncTimeStamp++;
+  }
+  (void) iSkipedBytes;
+}
+
 TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;