shithub: openh264

Download patch

ref: 82cc0535ae2735804fdbeae75c4a98c13d2808f7
parent: f9f2bbf805ebb82d0cc46dd79aade2dfb264f046
author: Sijia Chen <sijchen@cisco.com>
date: Wed Sep 30 13:26:50 EDT 2015

Add fix for simulcast if frame rate in the middle spatial layer is smaller

--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -3114,11 +3114,8 @@
  * \brief   swap pDq layers between current pDq layer and reference pDq layer
  */
 
-static inline void WelsSwapDqLayers (sWelsEncCtx* pCtx) {
+static inline void WelsSwapDqLayers (sWelsEncCtx* pCtx, const int32_t kiNextDqIdx) {
   // swap and assign reference
-  const int32_t kiDid           = pCtx->uiDependencyId;
-  const int32_t kiNextDqIdx     = 1 + kiDid;
-
   SDqLayer* pTmpLayer           = pCtx->ppDqLayerList[kiNextDqIdx];
   SDqLayer* pRefLayer           = pCtx->pCurDqLayer;
   pCtx->pCurDqLayer             = pTmpLayer;
@@ -4384,7 +4381,8 @@
     ++ iSpatialIdx;
 
     if (iCurDid + 1 < pSvcParam->iSpatialLayerNum) {
-      WelsSwapDqLayers (pCtx);
+      //for next layer, note that iSpatialIdx has been ++ so it is pointer to next layer
+      WelsSwapDqLayers (pCtx, (pSpatialIndexMap + iSpatialIdx)->iDid);
     }
 
     if (pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, iDidIdx) != 0) {
@@ -4400,7 +4398,7 @@
         && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == videoFrameTypeIDR)) {
       pCtx->bRefOfCurTidIsLtr[iDidIdx][iCurTid] = true;
     }
-  }
+  }//end of (iSpatialIdx/iSpatialNum)
 
   if (ENC_RETURN_CORRECTED == pCtx->iEncoderError) {
     pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, (pSpatialIndexMap + iSpatialIdx)->iDid);
@@ -4448,8 +4446,9 @@
            iLayerNum,
            pFbi->iSubSeqId, iFrameSize);
   for (int32_t i = 0; i < iLayerNum; i++)
-    WelsLog (pLogCtx, WELS_LOG_DEBUG, "WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount = %d", i,
-             pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount);
+    WelsLog (pLogCtx, WELS_LOG_DEBUG,
+             "WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount = %d, first Nal Length=%d", i,
+             pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount, pFbi->sLayerInfo[i].pNalLengthInByte[0]);
   WelsEmms();
 
   pFbi->eFrameType = eFrameType;
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -3596,7 +3596,7 @@
 
 
 TEST_F (EncodeDecodeTestAPI, SimulcastAVCDiffFps) {
-//#define DEBUG_FILE_SAVE3
+//#define DEBUG_FILE_SAVE_SimulcastAVCDiffFps
   int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
   int iWidth       = WelsClip3 ((((rand() % MAX_WIDTH) >> 1)  + 1) << 1, 1 << iSpatialLayerNum, MAX_WIDTH);
   int iHeight      = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1)  + 1) << 1, 1 << iSpatialLayerNum, MAX_HEIGHT);
@@ -3608,11 +3608,8 @@
 
   //set flag of bSimulcastAVC
   param_.bSimulcastAVC = true;
-  param_.iTemporalLayerNum = 3;
+  param_.iTemporalLayerNum = (rand() % 2) ? 3 : 4;
 
-  int rv = encoder_->InitializeExt (&param_);
-  ASSERT_TRUE (rv == cmResultSuccess);
-
   unsigned char*  pBsBuf[MAX_SPATIAL_LAYER_NUM];
   int aLen[MAX_SPATIAL_LAYER_NUM] = {0};
   ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
@@ -3648,10 +3645,10 @@
     ASSERT_EQ (0, rv);
   }
 
-#define PATTERN_NUM (16)
+#define PATTERN_NUM (18)
   const int32_t iTemporalPattern[PATTERN_NUM][MAX_SPATIAL_LAYER_NUM] = { {2, 1, 1, 1}, {2, 2, 2, 1}, {4, 1, 1, 1}, {4, 2, 1, 1},
-    {1, 2, 1, 1}, {1, 1, 2, 1}, {1, 4, 1, 1}, {2, 4, 2, 1}, {1, 4, 2, 1},
-    {1, 2, 2, 1}, {1, 2, 4, 1},
+    {1, 2, 1, 1}, {1, 1, 2, 1}, {1, 4, 1, 1}, {2, 4, 2, 1}, {1, 4, 2, 1}, {1, 4, 4, 1},
+    {1, 2, 2, 1}, {2, 1, 2, 1}, {1, 2, 4, 1},
     {1, 1, 1, 2}, {1, 2, 2, 2}, {1, 2, 2, 4}, {1, 2, 4, 2}, {1, 4, 4, 4},
   };
   for (int iPatternIdx = 0; iPatternIdx < PATTERN_NUM; iPatternIdx++) {
@@ -3659,7 +3656,11 @@
       param_.sSpatialLayers[i].fFrameRate = (fFrameRate / iTemporalPattern[iPatternIdx][i]);
     }
 
+    int rv = encoder_->InitializeExt (&param_);
+    ASSERT_TRUE (rv == cmResultSuccess);
+
     iEncFrameNum = 10;
+    int iInsertIdr = rand() % iEncFrameNum;
     for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
       int iResult;
       int iLayerLen = 0;
@@ -3668,7 +3669,11 @@
       InitialEncDec (param_.iPicWidth, param_.iPicHeight);
       EncodeOneFrame (0);
 
-      // init
+      if (iInsertIdr == iFrame) {
+        encoder_->ForceIntraFrame (true);
+      }
+
+      // init aLen for the current frame
       for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
         aLen[iIdx] = 0;
       }
@@ -3700,7 +3705,7 @@
           EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx;
 
           iResult = decoder[iIdx]->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_);
-          EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx;
+          EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx << iPatternIdx;
           EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
         }
       }
@@ -3716,12 +3721,10 @@
     }
   }
 #ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
-  for (int i = 0; i <)MAX_SPATIAL_LAYER_NUM;
-  i++) {
+  for (int i = 0; i < MAX_SPATIAL_LAYER_NUM; i++) {
     fclose (fEnc[i]);
   }
 #endif
 }
-