shithub: openh264

Download patch

ref: 8652028620269cb9f3415cc405c67e5af1492621
parent: 736128e4e372bc026019b6a1169619ca6cc97a7b
author: Karina <ruil2@cisco.com>
date: Mon Dec 19 06:45:25 EST 2016

modify LTR interface and support LTR request for each layer

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -235,6 +235,7 @@
   unsigned int uiIDRPicId;           ///< distinguish request from different IDR
   int          iLastCorrectFrameNum;
   int          iCurrentFrameNum;     ///< specify current decoder frame_num.
+  int          iLayerId;           //specify the layer for recovery request
 } SLTRRecoverRequest;
 
 /**
@@ -244,6 +245,7 @@
   unsigned int  uiFeedbackType; ///< mark failed or successful
   unsigned int  uiIDRPicId;     ///< distinguish request from different IDR
   int           iLTRFrameNum;   ///< specify current decoder frame_num
+  int           iLayerId;        //specify the layer for LTR marking feedback
 } SLTRMarkingFeedback;
 
 /**
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -199,7 +199,7 @@
   int32_t           iSliceBufferSize[MAX_DEPENDENCY_LAYER];
 
   bool              bRefOfCurTidIsLtr[MAX_DEPENDENCY_LAYER][MAX_TEMPORAL_LEVEL];
-  uint16_t          uiIdrPicId;           // IDR picture id: [0, 65535], this one is used for LTR
+ // uint16_t          uiIdrPicId;           // IDR picture id: [0, 65535], this one is used for LTR
   int32_t           iMaxSliceCount;// maximal count number of slices for all layers observation
   int16_t           iActiveThreadsNum;      // number of threads active so far
 
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -86,7 +86,7 @@
   int8_t        iHighestTemporalId;
   float         fInputFrameRate;                // input frame rate
   float         fOutputFrameRate;               // output frame rate
- // uint16_t          uiIdrPicId;           // IDR picture id: [0, 65535], this one is used for LTR
+  uint16_t          uiIdrPicId;           // IDR picture id: [0, 65535], this one is used for LTR
   int32_t           iCodingIndex;
   int32_t           iFrameIndex;            // count how many frames elapsed during coding context currently
   bool              bEncCurFrmAsIdrFlag;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -1170,6 +1170,7 @@
     pParamInternal->iFrameIndex = 0;
     pParamInternal->iFrameNum = 0;
     pParamInternal->iPOC = 0;
+    pParamInternal->uiIdrPicId = 0;
     pParamInternal->bEncCurFrmAsIdrFlag = true;  // make sure first frame is IDR
     // pDq layers list
     pDqLayer = (SDqLayer*)pMa->WelsMallocz (sizeof (SDqLayer), "pDqLayer");
@@ -2658,7 +2659,7 @@
   int32_t iCurSpsId = pDqIdc->iSpsId;
 
   iCurPpsId = pCtx->pFuncList->pParametersetStrategy->GetCurrentPpsId (iCurPpsId,
-              WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT);
+              WELS_ABS (pParamInternal->uiIdrPicId - 1) % MAX_PPS_COUNT);
 
   pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId       = iCurPpsId;
   pCurDq->sLayerInfo.pPpsP                              =
@@ -3243,7 +3244,14 @@
   int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS;
   iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iNonVclSize);
   WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
-
+  for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
+    SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iSpatialId];
+    if (pParamInternal->uiIdrPicId < 65535) {
+      ++ pParamInternal->uiIdrPicId;
+    } else {
+      pParamInternal->uiIdrPicId = 0;
+    }
+  }
   pLayerBsInfo->uiSpatialId     = 0;
   pLayerBsInfo->uiTemporalId    = 0;
   pLayerBsInfo->uiQualityId     = 0;
@@ -3359,7 +3367,15 @@
   iNonVclSize = 0;
 
   for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
+    SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iSpatialId];
+    if (pParamInternal->uiIdrPicId < 65535) {
+      ++ pParamInternal->uiIdrPicId;
+    } else {
+      pParamInternal->uiIdrPicId = 0;
+    }
+
     iCountNal = 0;
+
     for (int32_t iIdx = 0; iIdx < pCtx->iSpsNum; iIdx++) {
       //writing one NAL
       int32_t iNalSize = 0;
@@ -3456,7 +3472,7 @@
     pEncCtx->eSliceType   = P_SLICE;
     //pEncCtx->eNalPriority = pEncCtx->eLastNalPriority; //not need this since eNalPriority will be updated at the beginning of coding a frame
   } else if (keFrameType == videoFrameTypeIDR) {
-    pEncCtx->uiIdrPicId --;
+    pParamInternal->uiIdrPicId --;
 
     //set the next frame to be IDR
     ForceCodingIDR (pEncCtx, pEncCtx->uiDependencyId);
@@ -3510,7 +3526,7 @@
   } else {
     SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iCurDid];
 
-    iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[iCurDid], pParamInternal->iCodingIndex,
+    iCurTid = GetTemporalLevel (pParamInternal, pParamInternal->iCodingIndex,
                                 pSvcParam->uiGopSize);
     pCtx->uiTemporalId = iCurTid;
     if (eFrameType == videoFrameTypeIDR) {
@@ -3519,15 +3535,14 @@
       if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
         if (pSvcParam->bSimulcastAVC) {
           pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
-          ++ pCtx->uiIdrPicId;
+          ++ pParamInternal->uiIdrPicId;
         } else {
           pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
-          ++ pCtx->uiIdrPicId;
         }
       } else {
         pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
 
-        ++ pCtx->uiIdrPicId;
+
       }
     }
   }
@@ -4331,7 +4346,12 @@
     int32_t iOldSpsPpsIdStrategy = pOldParam->eSpsPpsIdStrategy;
     SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
     int32_t  iTmpPpsIdList[MAX_DQ_LAYER_NUM * MAX_PPS_COUNT];
-    uint16_t uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;//this is for LTR!
+    //for LTR or SPS,PPS ID update
+    uint16_t uiMaxIdrPicId = 0;
+    for (iIndexD = 0; iIndexD < pOldParam->iSpatialLayerNum; iIndexD++) {
+      if (pOldParam->sDependencyLayers[iIndexD].uiIdrPicId > uiMaxIdrPicId)
+        uiMaxIdrPicId = pOldParam->sDependencyLayers[iIndexD].uiIdrPicId;
+    }
 
     SEncoderStatistics sTempEncoderStatistics[MAX_DEPENDENCY_LAYER];
     memcpy (sTempEncoderStatistics, (*ppCtx)->sEncoderStatistics, sizeof (sTempEncoderStatistics));
@@ -4355,8 +4375,10 @@
     if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx, pExistingParasetList))
       return 1;
     //if WelsInitEncoderExt succeed
-    //for LTR
-    (*ppCtx)->uiIdrPicId = uiTmpIdrPicId ;//this is for LTR!; //this is for LTR!
+    //for LTR or SPS,PPS ID update
+    for (iIndexD = 0; iIndexD < pNewParam->iSpatialLayerNum; iIndexD++) {
+      pNewParam->sDependencyLayers[iIndexD].uiIdrPicId = uiMaxIdrPicId;
+    }
 
     //for sEncoderStatistics
     memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics));
@@ -4446,7 +4468,6 @@
       /* Derived variants below */
       pOldDlpInternal->iTemporalResolution      = pNewDlpInternal->iTemporalResolution;
       pOldDlpInternal->iDecompositionStages     = pNewDlpInternal->iDecompositionStages;
-
       memcpy (pOldDlpInternal->uiCodingIdx2TemporalId, pNewDlpInternal->uiCodingIdx2TemporalId,
               sizeof (pOldDlpInternal->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage
       ++ iIndexD;
--- a/codec/encoder/core/src/ref_list_mgr_svc.cpp
+++ b/codec/encoder/core/src/ref_list_mgr_svc.cpp
@@ -512,12 +512,22 @@
 }
 
 int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest) {
-  SLTRRecoverRequest* pRequest = pLTRRecoverRequest;
-  SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
-  int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
-  SSpatialLayerInternal* pParamInternal    = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
-  if (pCtx->pSvcParam->bEnableLongTermReference) {
-    if (pRequest->uiFeedbackType == LTR_RECOVERY_REQUEST &&  pRequest->uiIDRPicId == pCtx->uiIdrPicId) {
+  //if disable LTR, force IDR
+  if (!pCtx->pSvcParam->bEnableLongTermReference) {
+    for (int32_t iDid = 0; iDid < pCtx->pSvcParam->iSpatialLayerNum; iDid++) {
+      SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iDid];
+      pParamInternal->bEncCurFrmAsIdrFlag = true;
+    }
+  } else {
+    SLTRRecoverRequest* pRequest = pLTRRecoverRequest;
+    int32_t iLayerId = pLTRRecoverRequest->iLayerId;
+    if ((iLayerId < 0) || (iLayerId >= pCtx->pSvcParam->iSpatialLayerNum))
+      return false;
+
+    SLTRState* pLtr = &pCtx->pLtr[iLayerId];
+    int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
+    SSpatialLayerInternal* pParamInternal    = &pCtx->pSvcParam->sDependencyLayers[iLayerId];
+    if (pRequest->uiFeedbackType == LTR_RECOVERY_REQUEST &&  pRequest->uiIDRPicId == pParamInternal->uiIdrPicId) {
       if (pRequest->iLastCorrectFrameNum == -1) {
         pParamInternal->bEncCurFrmAsIdrFlag = true;
         return true;
@@ -543,16 +553,20 @@
                "Receive LTR recovery pRequest,feedback_type = %d ,uiIdrPicId = %d , current_frame_num = %d , last correct frame num = %d"
                , pRequest->uiFeedbackType, pRequest->uiIDRPicId, pRequest->iCurrentFrameNum, pRequest->iLastCorrectFrameNum);
     }
-  } else if (!pCtx->pSvcParam->bEnableLongTermReference) {
-    pParamInternal->bEncCurFrmAsIdrFlag = true;
   }
+
   return true;
 }
 void FilterLTRMarkingFeedback (sWelsEncCtx* pCtx, SLTRMarkingFeedback* pLTRMarkingFeedback) {
-  SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
+  int32_t iLayerId = pLTRMarkingFeedback->iLayerId;
+  if ((iLayerId < 0) || (iLayerId >= pCtx->pSvcParam->iSpatialLayerNum)) {
+    return;
+  }
+  SLTRState* pLtr = &pCtx->pLtr[iLayerId];
   assert (pLTRMarkingFeedback);
   if (pCtx->pSvcParam->bEnableLongTermReference) {
-    if (pLTRMarkingFeedback->uiIDRPicId == pCtx->uiIdrPicId
+    SSpatialLayerInternal* pParamInternal    = &pCtx->pSvcParam->sDependencyLayers[iLayerId];
+    if (pLTRMarkingFeedback->uiIDRPicId == pParamInternal->uiIdrPicId
         && (pLTRMarkingFeedback->uiFeedbackType == LTR_MARKING_SUCCESS
             || pLTRMarkingFeedback->uiFeedbackType == LTR_MARKING_FAILED)) { // avoid error pData
       pLtr->uiLtrMarkState = pLTRMarkingFeedback->uiFeedbackType;
@@ -560,13 +574,13 @@
       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
                "Receive valid LTR marking feedback, feedback_type = %d , uiIdrPicId = %d , LTR_frame_num = %d , cur_idr_pic_id = %d",
                pLTRMarkingFeedback->uiFeedbackType, pLTRMarkingFeedback->uiIDRPicId, pLTRMarkingFeedback->iLTRFrameNum ,
-               pCtx->uiIdrPicId);
+               pParamInternal->uiIdrPicId);
 
     } else {
       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
                "Receive LTR marking feedback, feedback_type = %d , uiIdrPicId = %d , LTR_frame_num = %d , cur_idr_pic_id = %d",
                pLTRMarkingFeedback->uiFeedbackType, pLTRMarkingFeedback->uiIDRPicId, pLTRMarkingFeedback->iLTRFrameNum ,
-               pCtx->uiIdrPicId);
+               pParamInternal->uiIdrPicId);
     }
   }
 }
--- a/codec/encoder/core/src/svc_encode_slice.cpp
+++ b/codec/encoder/core/src/svc_encode_slice.cpp
@@ -97,8 +97,7 @@
   pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->sLayerInfo.pSliceInLayer, pSlice->uiSliceIdx);
 
   pCurSliceHeader->iFrameNum      = pParamInternal->iFrameNum;
-  pCurSliceHeader->uiIdrPicId     = pEncCtx->uiIdrPicId;
-
+  pCurSliceHeader->uiIdrPicId     = pParamInternal->uiIdrPicId;
   pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc;      // 0
 
   if (P_SLICE == pEncCtx->eSliceType) {
--- a/test/api/decode_api_test.cpp
+++ b/test/api/decode_api_test.cpp
@@ -190,6 +190,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.bPrefixNalAddingCtrl = false;
@@ -259,6 +261,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.bPrefixNalAddingCtrl = true;
@@ -314,6 +318,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (2, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.iTemporalLayerNum = (rand() % 4) + 1;
@@ -370,6 +376,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.iSpatialLayerNum = 1;
@@ -434,6 +442,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.iSpatialLayerNum = 1;
--- a/test/api/decoder_ec_test.cpp
+++ b/test/api/decoder_ec_test.cpp
@@ -14,6 +14,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   param_.bEnableLongTermReference = true;
@@ -80,6 +82,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   encoder_->Uninitialize();
@@ -660,6 +664,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = kSVCSwitch[0];
   p.width = p.width << 2;
   p.height = p.height << 2;
@@ -723,6 +729,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = kSVCSwitch[0];
   int iTarDid = 0;
   int iLastDid = 0;
--- a/test/api/ltr_test.cpp
+++ b/test/api/ltr_test.cpp
@@ -45,6 +45,8 @@
 TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) {
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   encoder_->Uninitialize();
@@ -105,6 +107,8 @@
   SLTRMarkingFeedback m_LTR_Marking_Feedback;
   SLTRRecoverRequest m_LTR_Recover_Request;
   m_LTR_Recover_Request.uiIDRPicId = 0;
+  m_LTR_Recover_Request.iLayerId = 0;
+  m_LTR_Marking_Feedback.iLayerId = 0;
   EncodeDecodeFileParamBase p = GetParam();
   prepareParamDefault (1, p.slicenum,  p.width, p.height, p.frameRate, &param_);
   encoder_->Uninitialize();