shithub: openh264

Download patch

ref: 969c415daa17f2552f2ac4b7f5abea61851d8894
parent: fd2ccb9bd8b77f33a4b87a4d34670d7857c4d76e
parent: 4c3852c880d02df36b8ad6616ac51e8fa62e7a67
author: sijchen <sijchen@cisco.com>
date: Wed Apr 19 06:00:05 EDT 2017

Merge pull request #2714 from shihuade/MultiThread_V11.0_UT

Slice buffer reallocate design::PR07:add ut cases for new slice buffer reallocate design

--- a/codec/encoder/core/inc/svc_enc_slice_segment.h
+++ b/codec/encoder/core/inc/svc_enc_slice_segment.h
@@ -191,7 +191,7 @@
  *  Get slice count for multiple slice segment
  *
  */
-int32_t GetInitialSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArgument);
+int32_t GetInitialSliceNum (SSliceArgument* pSliceArgument);
 int32_t GetCurrentSliceNum (const SDqLayer* pCurDq);
 SSlice* GetSliceByIndex(sWelsEncCtx* pCtx, const int32_t kiSliceIdc);
 
--- a/codec/encoder/core/inc/svc_encode_slice.h
+++ b/codec/encoder/core/inc/svc_encode_slice.h
@@ -108,7 +108,6 @@
 void InitSliceRefInfoWithBase (SSlice* pSlice, SSlice* pBaseSlice, const uint8_t kuiRefCount);
 
 int32_t InitSliceList (sWelsEncCtx* pCtx,
-                       SDqLayer* pDqLayer,
                        SSlice*& pSliceList,
                        const int32_t kiMaxSliceNum,
                        const int32_t kiDlayerIndex,
@@ -147,6 +146,10 @@
                         SFrameBSInfo* pFrameBsInfo,
                         SLayerBSInfo* pLayerBsInfo,
                         const int32_t kiMaxSliceNumOld);
+
+int32_t ReOrderSliceInLayer(sWelsEncCtx* pCtx,
+                            const SliceModeEnum kuiSliceMode,
+                            const int32_t kiThreadNum);
 
 int32_t SliceLayerInfoUpdate (sWelsEncCtx* pCtx,
                               SFrameBSInfo* pFrameBsInfo,
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -727,7 +727,7 @@
  * \pParam  iCountNals      pointer of count number of nals indeed
  * \return  0 - successful; otherwise failed
  */
-static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers,
+int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers,
     int32_t* pCountNals) {
   int32_t iCountNumLayers       = 0;
   int32_t iCountNumNals         = 0;
@@ -761,9 +761,7 @@
         return 1;
       }
     } else { /*if ( SM_SINGLE_SLICE != pDLayer->sSliceArgument.uiSliceMode )*/
-      const int32_t kiNumOfSlice = GetInitialSliceNum ((pDLayer->iVideoWidth + 0x0f) >> 4,
-                                   (pDLayer->iVideoHeight + 0x0f) >> 4,
-                                   &pDLayer->sSliceArgument);
+      const int32_t kiNumOfSlice = GetInitialSliceNum (&pDLayer->sSliceArgument);
 
       // NEED check iCountNals value in case multiple slices is used
       iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs
@@ -1069,7 +1067,7 @@
     pDqLayer->iMbHeight = kiMbH;
 
     int32_t iMaxSliceNum            = 1;
-    const int32_t kiSliceNum = GetInitialSliceNum (kiMbW, kiMbH, &pDlayer->sSliceArgument);
+    const int32_t kiSliceNum = GetInitialSliceNum (&pDlayer->sSliceArgument);
     if (iMaxSliceNum < kiSliceNum)
       iMaxSliceNum = kiSliceNum;
     pDqLayer->iMaxSliceNum = iMaxSliceNum;
--- a/codec/encoder/core/src/svc_enc_slice_segment.cpp
+++ b/codec/encoder/core/src/svc_enc_slice_segment.cpp
@@ -316,25 +316,25 @@
  *  Get slice count for multiple slice segment
  *
  */
-int32_t GetInitialSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArgument) {
+int32_t GetInitialSliceNum (SSliceArgument* pSliceArgument) {
   if (NULL == pSliceArgument)
     return -1;
 
   switch (pSliceArgument->uiSliceMode) {
-  case SM_SINGLE_SLICE:
-  case SM_FIXEDSLCNUM_SLICE:
-  case SM_RASTER_SLICE:
-    {
-    return pSliceArgument->uiSliceNum;
+    case SM_SINGLE_SLICE:
+    case SM_FIXEDSLCNUM_SLICE:
+    case SM_RASTER_SLICE:
+      {
+        return pSliceArgument->uiSliceNum;
+    }
+    case SM_SIZELIMITED_SLICE: {
+      return AVERSLICENUM_CONSTRAINT;//at the beginning of dynamic slicing, set the uiSliceNum to be 1
+    }
+    case SM_RESERVED:
+    default: {
+      return -1;
+    }
   }
-  case SM_SIZELIMITED_SLICE: {
-    return AVERSLICENUM_CONSTRAINT;//at the beginning of dynamic slicing, set the uiSliceNum to be 1
-  }
-  case SM_RESERVED:
-  default: {
-    return -1;
-  }
-  }
 
   return -1;
 }
@@ -404,7 +404,7 @@
     WelsSetMemMultiplebytes_c(pSliceSeg->pOverallMbMap, 0, kiCountMbNum, sizeof(uint16_t));
 
     //SM_SIZELIMITED_SLICE: init, set pSliceSeg->iSliceNumInFrame = 1;
-    pSliceSeg->iSliceNumInFrame = GetInitialSliceNum (kiMbWidth, kiMbHeight, pSliceArgument);
+    pSliceSeg->iSliceNumInFrame = GetInitialSliceNum (pSliceArgument);
     if (-1 == pSliceSeg->iSliceNumInFrame)
       return 1;
 
--- a/codec/encoder/core/src/svc_encode_slice.cpp
+++ b/codec/encoder/core/src/svc_encode_slice.cpp
@@ -929,13 +929,10 @@
 }
 
 int32_t InitSliceList (sWelsEncCtx* pCtx,
-                       SDqLayer* pDqLayer,
                        SSlice*& pSliceList,
                        const int32_t kiMaxSliceNum,
                        const int32_t kiDlayerIndex,
                        CMemoryAlign* pMa) {
-  const int32_t kiMBWidth         = pDqLayer->iMbWidth;
-  const int32_t kiMBHeight        = pDqLayer->iMbHeight;
   SSliceArgument* pSliceArgument  = & pCtx->pSvcParam->sSpatialLayers[kiDlayerIndex].sSliceArgument;
   int32_t iMaxSliceBufferSize     = (pCtx)->iSliceBufferSize[kiDlayerIndex];
   int32_t iSliceIdx               = 0;
@@ -945,8 +942,7 @@
   //even though multi-thread is on for other layers
   bool bIndependenceBsBuffer   = (pCtx->pSvcParam->iMultipleThreadIdc > 1 &&
                                   SM_SINGLE_SLICE != pSliceArgument->uiSliceMode) ? true : false;
-
-  if (iMaxSliceBufferSize <= 0 || kiMBWidth <= 0 || kiMBHeight <= 0) {
+  if (iMaxSliceBufferSize <= 0) {
     return ENC_RETURN_UNEXPECTED;
   }
 
@@ -1048,7 +1044,6 @@
       return ENC_RETURN_MEMALLOCERR;
     }
     iRet = InitSliceList (pCtx,
-                          pDqLayer,
                           pDqLayer->sSliceThreadInfo[iIdx].pSliceInThread,
                           iMaxSliceNum,
                           kiDlayerIndex,
--- a/test/build/win32/codec_ut/codec_unittest.vcproj
+++ b/test/build/win32/codec_ut/codec_unittest.vcproj
@@ -451,6 +451,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\encoder\EncUT_SliceBufferReallocate.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\encoder\EncUT_SVC_me.cpp"
 				>
 			</File>
--- /dev/null
+++ b/test/encoder/EncUT_SliceBufferReallocate.cpp
@@ -1,0 +1,649 @@
+#include "wels_common_basis.h"
+#include "utils/BufferedData.h"
+#include "BaseEncoderTest.h"
+#include "svc_encode_slice.h"
+#include "encoder.h"
+#include "macros.h"
+#include "EncUT_SliceBufferReallocate.h"
+
+namespace WelsEnc {
+extern void FreeDqLayer(SDqLayer*& pDq, CMemoryAlign* pMa);
+extern void FreeMemorySvc(sWelsEncCtx** ppCtx);
+extern int32_t AcquireLayersNals(sWelsEncCtx** ppCtx,
+                                 SWelsSvcCodingParam* pParam,
+                                 int32_t* pCountLayers,
+                                 int32_t* pCountNals);
+extern int32_t ExtendLayerBuffer(sWelsEncCtx* pCtx,
+                                 const int32_t kiMaxSliceNumOld,
+                                 const int32_t kiMaxSliceNumNew);
+}
+
+int32_t RandAvailableThread(sWelsEncCtx* pCtx, const int32_t kiMinBufferNum) {
+    int32_t aiThrdList[MAX_THREADS_NUM] = { -1 };
+    int32_t iCodedSlcNum = 0;
+    int32_t iMaxSlcNumInThrd = 0;
+    int32_t iAvailableThrdNum = 0;
+    int32_t iRandThrdIdx = -1;
+
+    if (NULL == pCtx || NULL == pCtx->pCurDqLayer || pCtx->iActiveThreadsNum <= 0) {
+        return -1;
+    }
+
+    for (int32_t iThrdIdx = 0; iThrdIdx < pCtx->iActiveThreadsNum; iThrdIdx++) {
+        iCodedSlcNum = pCtx->pCurDqLayer->sSliceThreadInfo[iThrdIdx].iCodedSliceNum;
+        iMaxSlcNumInThrd = pCtx->pCurDqLayer->sSliceThreadInfo[iThrdIdx].iMaxSliceNum;
+
+        if ((iCodedSlcNum + kiMinBufferNum) <= iMaxSlcNumInThrd) {
+            aiThrdList[iAvailableThrdNum] = iThrdIdx;
+            iAvailableThrdNum++;
+        }
+    }
+
+    if (0 == iAvailableThrdNum) {
+        return -1;
+    }
+    iRandThrdIdx = rand() % iAvailableThrdNum;
+
+    return aiThrdList[iRandThrdIdx];
+}
+
+int32_t AllocateLayerBuffer(sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    SDqLayer* pDqLayer = (SDqLayer*)pCtx->pMemAlign->WelsMallocz(sizeof(SDqLayer), "pDqLayer");
+    if (NULL == pDqLayer) {
+        return ENC_RETURN_MEMALLOCERR;
+    }
+
+    pDqLayer->iMbWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
+    pDqLayer->iMbHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
+    pDqLayer->iMaxSliceNum = GetInitialSliceNum(&pLayerCfg->sSliceArgument);
+
+    int32_t iRet = InitSliceInLayer(pCtx, pDqLayer, iLayerIdx, pCtx->pMemAlign);
+    if (ENC_RETURN_SUCCESS != iRet) {
+        FreeDqLayer(pDqLayer, pCtx->pMemAlign);
+        return ENC_RETURN_MEMALLOCERR;
+    }
+
+    pCtx->ppDqLayerList[iLayerIdx] = pDqLayer;
+    return ENC_RETURN_SUCCESS;
+}
+
+void SetPartitonMBNum(SDqLayer* pCurDqLayer, SSpatialLayerConfig* pLayerCfg, int32_t iPartNum) {
+    int32_t iMBWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
+    int32_t iMBHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
+    int32_t iMbNumInFrame = iMBWidth * iMBHeight;
+    int32_t iMBPerPart = iMbNumInFrame / iPartNum;
+
+    if (0 == iMBPerPart) {
+        iPartNum = 1;
+        iMBPerPart = iMbNumInFrame;
+    }
+
+    for (int32_t iPartIdx = 0; iPartIdx < (iPartNum - 1); iPartIdx++) {
+        pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] = iMBPerPart * iPartIdx;
+        pCurDqLayer->EndMbIdxOfPartition[iPartIdx] = pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] + iMBPerPart - 1;
+    }
+
+    pCurDqLayer->FirstMbIdxOfPartition[iPartNum - 1] = iMBPerPart * (iPartNum - 1);
+    pCurDqLayer->EndMbIdxOfPartition[iPartNum - 1] = iMbNumInFrame - 1;
+
+    for (int32_t iPartIdx = iPartNum; iPartIdx < MAX_THREADS_NUM; iPartIdx++) {
+        pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] = 0;
+        pCurDqLayer->EndMbIdxOfPartition[iPartIdx] = 0;
+    }
+}
+
+int32_t InitParamForSizeLimitSlcMode(sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
+    int32_t iSliceBufferSize = 0;
+    int32_t iLayerBsSize = WELS_ROUND(((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR)
+                           + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
+    pSliceArgument->uiSliceSizeConstraint = 600;
+    pCtx->pSvcParam->uiMaxNalSize = 1500;
+
+    int32_t iMaxSliceNumEstimation = WELS_MIN(AVERSLICENUM_CONSTRAINT,
+                                     (iLayerBsSize / pSliceArgument->uiSliceSizeConstraint) + 1);
+    pCtx->iMaxSliceCount = WELS_MAX(pCtx->iMaxSliceCount, iMaxSliceNumEstimation);
+    iSliceBufferSize = (WELS_MAX((int32_t)pSliceArgument->uiSliceSizeConstraint,
+                                 iLayerBsSize / iMaxSliceNumEstimation) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
+    pCtx->iSliceBufferSize[iLayerIdx] = iSliceBufferSize;
+
+    int32_t iRet = AllocateLayerBuffer(pCtx, iLayerIdx);
+    if (ENC_RETURN_SUCCESS != iRet) {
+        return ENC_RETURN_MEMALLOCERR;
+    }
+
+    SetPartitonMBNum(pCtx->ppDqLayerList[iLayerIdx], pLayerCfg, pCtx->iActiveThreadsNum);
+    return ENC_RETURN_SUCCESS;
+}
+
+void InitParamForRasterSlcMode(sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
+    int32_t iMBWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
+    int32_t iMBHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
+    int32_t iMbNumInFrame = iMBWidth * iMBHeight;
+    int32_t iSliceMBNum = 0;
+
+    pSliceArgument->uiSliceMbNum[0] = rand() % 2;
+    if (0 == pSliceArgument->uiSliceMbNum[0] && iMBHeight > MAX_SLICES_NUM) {
+        pSliceArgument->uiSliceNum = MAX_SLICES_NUM;
+        pSliceArgument->uiSliceMbNum[0] = 1;
+    }
+
+    if (0 != pSliceArgument->uiSliceMbNum[0]) {
+        iSliceMBNum = iMbNumInFrame / pSliceArgument->uiSliceNum;
+        for (int32_t iSlcIdx = 0; iSlcIdx < (int32_t)pSliceArgument->uiSliceNum - 1; iSlcIdx++) {
+            pSliceArgument->uiSliceMbNum[iSlcIdx] = iSliceMBNum;
+        }
+        iSliceMBNum = iMbNumInFrame / pSliceArgument->uiSliceNum;
+        pSliceArgument->uiSliceMbNum[pSliceArgument->uiSliceNum - 1] = iMbNumInFrame - iSliceMBNum * (pSliceArgument->uiSliceNum - 1);
+    }
+}
+
+void ParamSetForReallocateTest(sWelsEncCtx* pCtx, int32_t iLayerIdx,
+                               int32_t iThreadIndex, int32_t iPartitionNum) {
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    int32_t iPartitionID = rand() % iPartitionNum;
+    int32_t iMBNumInPatition = 0;
+    int32_t iCodedSlcNum = pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iMaxSliceNum - 1;
+    int32_t iLastCodeSlcIdx = iPartitionID + iCodedSlcNum * iPartitionNum;
+    SSlice* pLastCodedSlc = &pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].pSliceInThread[iCodedSlcNum - 1];
+    pLastCodedSlc->iSliceIdx = iLastCodeSlcIdx;
+
+    SetPartitonMBNum(pCtx->ppDqLayerList[iLayerIdx], pLayerCfg, iPartitionNum);
+
+    iMBNumInPatition = pCtx->pCurDqLayer->EndMbIdxOfPartition[iPartitionID] -
+                       pCtx->pCurDqLayer->FirstMbIdxOfPartition[iPartitionID] + 1;
+    pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iCodedSliceNum = iCodedSlcNum;
+    pCtx->pCurDqLayer->LastCodedMbIdxOfPartition[iPartitionID] = rand() % iMBNumInPatition + 1;
+
+}
+
+void CSliceBufferReallocatTest::InitParamForTestCase(int32_t iLayerIdx) {
+    InitParam();
+    InitLayerSliceBuffer(iLayerIdx);
+    InitFrameBsBuffer();
+
+    //param validation
+    int32_t iRet = m_pEncoder->InitializeExt((SEncParamExt*)m_EncContext.pSvcParam);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+}
+
+void CSliceBufferReallocatTest::InitParamForSizeLimitSlcModeCase(int32_t iLayerIdx) {
+    SSliceArgument* pSliceArgument = &m_EncContext.pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
+    int32_t iRet = 0;
+
+    InitParam();
+    InitLayerSliceBuffer(iLayerIdx);
+
+    if (SM_SIZELIMITED_SLICE != pSliceArgument->uiSliceMode && NULL != m_EncContext.ppDqLayerList[iLayerIdx]) {
+        UnInitLayerSliceBuffer(iLayerIdx);
+        pSliceArgument->uiSliceMode = SM_SIZELIMITED_SLICE;
+        iRet = InitParamForSizeLimitSlcMode(&m_EncContext, iLayerIdx);
+        EXPECT_TRUE(ENC_RETURN_SUCCESS == iRet);
+        EXPECT_TRUE(NULL != m_EncContext.ppDqLayerList[iLayerIdx]);
+    }
+    InitFrameBsBuffer();
+
+    //param validation
+    iRet = m_pEncoder->InitializeExt((SEncParamExt*)m_EncContext.pSvcParam);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+}
+
+void CSliceBufferReallocatTest::UnInitParamForTestCase(int32_t iLayerIdx) {
+    int32_t iRet = m_pEncoder->Uninitialize();
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    UnInitFrameBsBuffer();
+    UnInitLayerSliceBuffer(iLayerIdx);
+    UnInitParam();
+}
+
+void CSliceBufferReallocatTest::InitParam() {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    SWelsFuncPtrList sEncFunctionList;
+    pCtx->pFuncList = &sEncFunctionList;
+
+    pCtx->pSvcParam->iMultipleThreadIdc = (rand() % MAX_THREADS_NUM) + 1;
+    pCtx->iActiveThreadsNum = pCtx->pSvcParam->iMultipleThreadIdc;
+    pCtx->pSvcParam->iSpatialLayerNum = 1;
+    pCtx->pSvcParam->bSimulcastAVC = (bool)rand() % 2;
+
+    pCtx->pSvcParam->iPicHeight = (((rand() % MAX_WIDTH ) >> 4 ) << 4) + 16;
+    pCtx->pSvcParam->iPicWidth  = (((rand() % MAX_HEIGH ) >> 4) << 4) + 16;
+    pCtx->iGlobalQp = WelsClip3( rand() % MAX_QP, MIN_QP, MAX_QP);
+    pCtx->pSvcParam->iRCMode = RC_OFF_MODE;
+    pCtx->pSvcParam->iTargetBitrate = WelsClip3(rand() % MAX_BIT_RATE, MIN_BIT_RATE, MAX_BIT_RATE);
+    int32_t iParamStraIdx = rand() % 5;
+    pCtx->pSvcParam->eSpsPpsIdStrategy = (EParameterSetStrategy)(iParamStraIdx == 4 ? 0x06 : iParamStraIdx);
+
+    pCtx->pFuncList = (SWelsFuncPtrList*)pCtx->pMemAlign->WelsMallocz(sizeof(SWelsFuncPtrList), "SWelsFuncPtrList");
+    EXPECT_TRUE(NULL != pCtx->pFuncList);
+
+    pCtx->pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy(pCtx->pSvcParam->eSpsPpsIdStrategy,
+            pCtx->pSvcParam->bSimulcastAVC, pCtx->pSvcParam->iSpatialLayerNum);
+    EXPECT_TRUE(NULL != pCtx->pFuncList->pParametersetStrategy);
+
+    pCtx->ppDqLayerList = (SDqLayer**)pCtx->pMemAlign->WelsMallocz(pCtx->pSvcParam->iSpatialLayerNum * sizeof(SDqLayer*), "ppDqLayerList");
+    EXPECT_TRUE(NULL != pCtx->ppDqLayerList);
+}
+
+void CSliceBufferReallocatTest::UnInitParam() {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    if (NULL != pCtx->pFuncList->pParametersetStrategy) {
+        delete pCtx->pFuncList->pParametersetStrategy;
+        pCtx->pFuncList->pParametersetStrategy = NULL;
+    }
+
+    if (NULL != pCtx->pFuncList) {
+        pCtx->pMemAlign->WelsFree(pCtx->pFuncList, "pCtx->pFuncList");
+        pCtx->pFuncList = NULL;
+    }
+
+    if (NULL != pCtx->ppDqLayerList) {
+        pCtx->pMemAlign->WelsFree(pCtx->ppDqLayerList, "pCtx->ppDqLayerList");
+        pCtx->ppDqLayerList = NULL;
+    }
+}
+
+void CSliceBufferReallocatTest::InitFrameBsBuffer() {
+    const int32_t iLayerIdx = 0;
+    sWelsEncCtx* pCtx = &m_EncContext;
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    const int32_t kiSpsSize = pCtx->pFuncList->pParametersetStrategy->GetNeededSpsNum() * SPS_BUFFER_SIZE;
+    const int32_t kiPpsSize = pCtx->pFuncList->pParametersetStrategy->GetNeededPpsNum() * PPS_BUFFER_SIZE;
+
+    int32_t iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
+    int32_t iLayerBsSize = WELS_ROUND(((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
+    int32_t iVclLayersBsSizeCount = WELS_ALIGN(iLayerBsSize, 4);
+    int32_t iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount;
+    int32_t iCountNals = 0;
+
+    int32_t iRet = AcquireLayersNals(&pCtx, pCtx->pSvcParam, &pCtx->pSvcParam->iSpatialLayerNum, &iCountNals);
+    EXPECT_TRUE(0 == iRet);
+
+    // Output
+    pCtx->pOut = (SWelsEncoderOutput*)pCtx->pMemAlign->WelsMallocz(sizeof(SWelsEncoderOutput), "SWelsEncoderOutput");
+    EXPECT_TRUE(NULL != pCtx->pOut);
+    pCtx->pOut->pBsBuffer = (uint8_t*)pCtx->pMemAlign->WelsMallocz(iCountBsLen, "pOut->pBsBuffer");
+    EXPECT_TRUE(NULL != pCtx->pOut->pBsBuffer);
+    pCtx->pOut->uiSize = iCountBsLen;
+    pCtx->pOut->sNalList = (SWelsNalRaw*)pCtx->pMemAlign->WelsMallocz(iCountNals * sizeof(SWelsNalRaw), "pOut->sNalList");
+    EXPECT_TRUE(NULL != pCtx->pOut->sNalList);
+    pCtx->pOut->pNalLen = (int32_t*)pCtx->pMemAlign->WelsMallocz(iCountNals * sizeof(int32_t), "pOut->pNalLen");
+    EXPECT_TRUE(NULL != pCtx->pOut->pNalLen);
+    pCtx->pOut->iCountNals = iCountNals;
+    pCtx->pOut->iNalIndex = 0;
+    pCtx->pOut->iLayerBsIndex = 0;
+    pCtx->pFrameBs = (uint8_t*)pCtx->pMemAlign->WelsMalloc(iCountBsLen, "pFrameBs");
+    EXPECT_TRUE(NULL != pCtx->pOut);
+    pCtx->iFrameBsSize = iCountBsLen;
+    pCtx->iPosBsBuffer = 0;
+}
+
+void CSliceBufferReallocatTest::UnInitFrameBsBuffer() {
+    sWelsEncCtx* pCtx = &m_EncContext;
+
+    if (NULL != pCtx->pOut->pBsBuffer) {
+        pCtx->pMemAlign->WelsFree(pCtx->pOut->pBsBuffer, "pCtx->pOut->pBsBuffer");
+        pCtx->pOut->pBsBuffer = NULL;
+    }
+
+    if (NULL != pCtx->pOut->sNalList) {
+        pCtx->pMemAlign->WelsFree(pCtx->pOut->sNalList, "pCtx->pOut->sNalList");
+        pCtx->pOut->sNalList = NULL;
+    }
+
+    if (NULL != pCtx->pOut->pNalLen) {
+        pCtx->pMemAlign->WelsFree(pCtx->pOut->pNalLen, "pCtx->pOut->pNalLen");
+        pCtx->pOut->pNalLen = NULL;
+    }
+
+    if (NULL != pCtx->pOut) {
+        pCtx->pMemAlign->WelsFree(pCtx->pOut, "pCtx->pOut");
+        pCtx->pOut = NULL;
+    }
+
+    if (NULL != pCtx->pFrameBs) {
+        pCtx->pMemAlign->WelsFree(pCtx->pFrameBs, "pCtx->pFrameBs");
+        pCtx->pFrameBs = NULL;
+    }
+}
+
+void CSliceBufferReallocatTest::InitLayerSliceBuffer(const int32_t iLayerIdx) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
+    SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
+    int32_t iLayerBsSize = 0;
+    int32_t iSliceBufferSize = 0;
+    int32_t iRet = 0;
+    int32_t iMaxFrameRate = 0.0;
+
+    pLayerCfg->iVideoWidth  = pCtx->pSvcParam->iPicWidth >> (pCtx->pSvcParam->iSpatialLayerNum -1 - iLayerIdx);
+    pLayerCfg->iVideoHeight = pCtx->pSvcParam->iPicHeight >> (pCtx->pSvcParam->iSpatialLayerNum - 1 - iLayerIdx);
+
+    iMaxFrameRate         = MAX_SAMPLES_PER_SECOND / (pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight);
+    pLayerCfg->fFrameRate = WelsClip3(pLayerCfg->fFrameRate, (float)MIN_FRAME_RATE, (float)MAX_FRAME_RATE);
+    pLayerCfg->fFrameRate = (pLayerCfg->fFrameRate > (float)iMaxFrameRate) ? (float)iMaxFrameRate : pLayerCfg->fFrameRate;
+
+    pLayerCfg->iSpatialBitrate = pCtx->pSvcParam->iTargetBitrate / pCtx->pSvcParam->iSpatialLayerNum;
+
+    //Slice argument
+    pSliceArgument->uiSliceMode = (SliceModeEnum)(rand() % 4);
+    pSliceArgument->uiSliceNum = rand() % MAX_SLICES_NUM + 1;
+
+    if (pSliceArgument->uiSliceMode == SM_SIZELIMITED_SLICE) {
+        iRet = InitParamForSizeLimitSlcMode(pCtx, iLayerIdx);
+    } else {
+        if (pSliceArgument->uiSliceMode == SM_RASTER_SLICE) {
+            InitParamForRasterSlcMode(pCtx, iLayerIdx);
+        }
+
+        iLayerBsSize = WELS_ROUND(((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR)
+                       + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
+        pCtx->iMaxSliceCount = WELS_MAX(pCtx->iMaxSliceCount, (int)pSliceArgument->uiSliceNum);
+        iSliceBufferSize = ((iLayerBsSize / pSliceArgument->uiSliceNum) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
+
+        pCtx->iSliceBufferSize[iLayerIdx] = iSliceBufferSize;
+        iRet = AllocateLayerBuffer(pCtx, iLayerIdx);
+    }
+
+    EXPECT_TRUE(ENC_RETURN_SUCCESS == iRet);
+    EXPECT_TRUE(NULL != pCtx->ppDqLayerList[iLayerIdx]);
+
+    pCtx->uiDependencyId = iLayerIdx;
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+}
+
+void CSliceBufferReallocatTest::UnInitLayerSliceBuffer(const int32_t iLayerIdx) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    if (NULL != pCtx->ppDqLayerList[iLayerIdx]) {
+        FreeDqLayer(pCtx->ppDqLayerList[iLayerIdx], pCtx->pMemAlign);
+        pCtx->ppDqLayerList[iLayerIdx] = NULL;
+    }
+}
+
+void CSliceBufferReallocatTest::SimulateEncodedOneSlice(const int32_t kiSlcIdx, const int32_t kiThreadIdx) {
+    int32_t iCodedSlcNumInThrd = m_EncContext.pCurDqLayer->sSliceThreadInfo[kiThreadIdx].iCodedSliceNum;
+
+    EXPECT_TRUE(NULL != m_EncContext.pCurDqLayer->sSliceThreadInfo[kiThreadIdx].pSliceInThread);
+    EXPECT_TRUE(NULL != &m_EncContext.pCurDqLayer->sSliceThreadInfo[kiThreadIdx].pSliceInThread[iCodedSlcNumInThrd]);
+
+    m_EncContext.pCurDqLayer->sSliceThreadInfo[kiThreadIdx].pSliceInThread[iCodedSlcNumInThrd].iSliceIdx = kiSlcIdx;
+    m_EncContext.pCurDqLayer->sSliceThreadInfo[kiThreadIdx].iCodedSliceNum ++;
+}
+
+void CSliceBufferReallocatTest::SimulateSliceInOnePartition(const int32_t kiPartNum,
+        const int32_t kiPartIdx,
+        const int32_t kiSlcNumInPart) {
+    int32_t iSlcIdxInPart = 0;
+
+    //slice within same partition will encoded by same thread in current design
+    int32_t iPartitionThrdIdx = RandAvailableThread(&m_EncContext, kiSlcNumInPart);
+    EXPECT_TRUE(-1 != iPartitionThrdIdx);
+
+    for (int32_t iSlcIdx = 0; iSlcIdx < kiSlcNumInPart; iSlcIdx++) {
+        iSlcIdxInPart = kiPartIdx + kiPartNum * iSlcIdx;
+
+        SimulateEncodedOneSlice(iSlcIdxInPart, iPartitionThrdIdx);
+
+        m_EncContext.pCurDqLayer->NumSliceCodedOfPartition[kiPartIdx] ++;
+        m_EncContext.pCurDqLayer->sSliceEncCtx.iSliceNumInFrame ++;
+    }
+}
+
+void CSliceBufferReallocatTest::SimulateSliceInOneLayer() {
+    int32_t iLayerIdx = 0;
+    SSpatialLayerConfig* pLayerCfg = &m_EncContext.pSvcParam->sSpatialLayers[iLayerIdx];
+    int32_t iTotalSliceBuffer = m_EncContext.pCurDqLayer->iMaxSliceNum;
+    int32_t iSimulateSliceNum = rand() % iTotalSliceBuffer + 1;
+
+    if (SM_SIZELIMITED_SLICE == pLayerCfg->sSliceArgument.uiSliceMode) {
+        int32_t iPartNum         = m_EncContext.iActiveThreadsNum;
+        int32_t iSlicNumPerPart  = iSimulateSliceNum / iPartNum;
+        int32_t iMaxSlcNumInThrd = m_EncContext.pCurDqLayer->sSliceThreadInfo[0].iMaxSliceNum;
+        int32_t iLastPartSlcNum = 0;
+
+        iSlicNumPerPart = WelsClip3(iSlicNumPerPart, 1, iMaxSlcNumInThrd);
+        iLastPartSlcNum = iSimulateSliceNum - iSlicNumPerPart * (iPartNum - 1);
+        iLastPartSlcNum = WelsClip3(iLastPartSlcNum, 1, iMaxSlcNumInThrd);
+
+        for (int32_t iPartIdx = 0; iPartIdx < iPartNum; iPartIdx ++) {
+            int32_t iSlcNumInPart = (iPartIdx < (iPartNum - 1)) ? iSlicNumPerPart : iLastPartSlcNum;
+            SimulateSliceInOnePartition(iPartNum, iPartIdx, iSlcNumInPart);
+        }
+    } else {
+        for (int32_t iSlcIdx = 0; iSlcIdx < iSimulateSliceNum; iSlcIdx ++) {
+            int32_t iSlcThrdIdx = RandAvailableThread(&m_EncContext, 1);
+            EXPECT_TRUE(-1 != iSlcThrdIdx);
+
+            SimulateEncodedOneSlice(iSlcIdx, iSlcThrdIdx);
+            m_EncContext.pCurDqLayer->sSliceEncCtx.iSliceNumInFrame++;
+        }
+    }
+}
+
+TEST_F(CSliceBufferReallocatTest, Reallocate_in_one_partition) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    int32_t iLayerIdx = 0;
+    int32_t iRet      = 0;
+
+    InitParamForSizeLimitSlcModeCase(iLayerIdx);
+
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+    iRet = InitAllSlicesInThread(pCtx);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    //case: reallocate during encoding one partition
+    //      include cases which part num less than thread num
+    //example: 3 threads but 2 partitions
+    //          thrd_0: partition_0
+    //          thrd_1: partition_1
+    //          thrd_2: idle
+    int32_t iThreadIndex  = rand() % pCtx->iActiveThreadsNum;
+    int32_t iPartitionNum = rand() % pCtx->iActiveThreadsNum + 1;
+    int32_t iSlcBufferNum = pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iMaxSliceNum;
+
+    ParamSetForReallocateTest(pCtx, iLayerIdx, iThreadIndex, iPartitionNum);
+    iRet = ReallocateSliceInThread(pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].pSliceInThread);
+    EXPECT_TRUE(iSlcBufferNum < pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iMaxSliceNum);
+
+    UnInitParamForTestCase(iLayerIdx);
+}
+
+TEST_F(CSliceBufferReallocatTest, Reallocate_in_one_thread) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    int32_t iLayerIdx = 0;
+    int32_t iRet = 0;
+
+    InitParamForSizeLimitSlcModeCase(iLayerIdx);
+
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+    iRet = InitAllSlicesInThread(pCtx);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    //case: all partitions encoded by one thread
+    //example: 3 threads 3 partions
+    //         thrd_0:  partion_0 -->partition_1 -->partition_2
+    //         thrd_1:  idle
+    //         thrd_2:  idle
+    int32_t iThreadIndex  =  rand() % pCtx->iActiveThreadsNum;
+    int32_t iPartitionNum = pCtx->iActiveThreadsNum;
+    int32_t iSlcBufferNum = 0;
+
+    ParamSetForReallocateTest(pCtx, iLayerIdx, iThreadIndex, iPartitionNum);
+
+    for (int32_t iPartIdx = 0; iPartIdx < iPartitionNum; iPartIdx++) {
+        iSlcBufferNum = pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iMaxSliceNum;
+
+        iRet = ReallocateSliceInThread(pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex);
+        EXPECT_TRUE(cmResultSuccess == iRet);
+        EXPECT_TRUE(NULL != pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].pSliceInThread);
+        EXPECT_TRUE(iSlcBufferNum < pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIndex].iMaxSliceNum);
+    }
+
+    UnInitParamForTestCase(iLayerIdx);
+}
+
+TEST_F(CSliceBufferReallocatTest, ExtendLayerBufferTest) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    SSlice* pSlcListInThrd = NULL;
+    int32_t iLayerIdx = 0;
+    int32_t iRet = 0;
+    int32_t iMaxSliceNumNew = 0;
+    int32_t iSlcBuffNumInThrd = 0;
+
+    InitParamForTestCase(iLayerIdx);
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+    iRet = InitAllSlicesInThread(pCtx);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    //before extend, simulate reallocate slice buffer in one thread
+    int32_t iReallocateThrdIdx = rand() % pCtx->iActiveThreadsNum;
+    iSlcBuffNumInThrd = pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iMaxSliceNum;
+    pSlcListInThrd = pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].pSliceInThread;
+
+    iRet = ReallocateSliceList(pCtx, &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument,
+                               pSlcListInThrd, iSlcBuffNumInThrd, iSlcBuffNumInThrd * 2);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+    EXPECT_TRUE(NULL != pSlcListInThrd);
+    pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].pSliceInThread = pSlcListInThrd;
+    pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iMaxSliceNum   = iSlcBuffNumInThrd * 2;
+
+    for (int32_t iThreadIdx = 0; iThreadIdx < pCtx->iActiveThreadsNum; iThreadIdx++) {
+        iMaxSliceNumNew += pCtx->pCurDqLayer->sSliceThreadInfo[iThreadIdx].iMaxSliceNum;
+    }
+
+    iRet = ExtendLayerBuffer(pCtx, pCtx->pCurDqLayer->iMaxSliceNum, iMaxSliceNumNew);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer->ppSliceInLayer);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer->pFirstMbIdxOfSlice);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer->pCountMbNumInSlice);
+
+    UnInitParamForTestCase(iLayerIdx);
+}
+
+TEST_F(CSliceBufferReallocatTest, FrameBsReallocateTest) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    int32_t iLayerIdx = 0;
+    int32_t iRet = 0;
+    SFrameBSInfo FrameBsInfo;
+    SLayerBSInfo* pLayerBsInfo = NULL;
+    int32_t iCurLayerIdx = rand() % MAX_LAYER_NUM_OF_FRAME;
+
+    memset(&FrameBsInfo, 0, sizeof(SFrameBSInfo));
+    InitParamForTestCase(iLayerIdx);
+
+    //init for FrameBs and LayerBs
+    pCtx->iPosBsBuffer = rand() % pCtx->iFrameBsSize + 1;
+    pLayerBsInfo = &FrameBsInfo.sLayerInfo[iCurLayerIdx];
+    pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
+    pCtx->bNeedPrefixNalFlag = rand() % 2;
+
+    int32_t iCodedNalCount = pCtx->pOut->iCountNals;
+    iRet = FrameBsRealloc(pCtx, &FrameBsInfo, pLayerBsInfo, iCodedNalCount);
+
+    EXPECT_TRUE(cmResultSuccess == iRet);
+    EXPECT_TRUE(iCodedNalCount < pCtx->pOut->iCountNals);
+    EXPECT_TRUE(NULL != pCtx->pOut->sNalList);
+    EXPECT_TRUE(NULL != pCtx->pOut->pNalLen);
+
+    UnInitParamForTestCase(iLayerIdx);
+}
+
+TEST_F(CSliceBufferReallocatTest, ReorderTest) {
+    int32_t iLayerIdx = 0;
+    sWelsEncCtx* pCtx = &m_EncContext;
+    SSliceArgument* pSliceArgument = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
+
+    InitParamForTestCase(iLayerIdx);
+
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+    int32_t iRet = InitAllSlicesInThread(pCtx);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    SimulateSliceInOneLayer();
+
+    iRet = ReOrderSliceInLayer(pCtx, pSliceArgument->uiSliceMode, pCtx->iActiveThreadsNum);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    int32_t iCodedSlcNum = pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame;
+    int32_t iMaxSlicNum = pCtx->pCurDqLayer->iMaxSliceNum;
+    EXPECT_TRUE(iCodedSlcNum <= iMaxSlicNum);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer);
+    EXPECT_TRUE(NULL != pCtx->pCurDqLayer->ppSliceInLayer);
+    for (int32_t iSlcIdx = 0; iSlcIdx < iCodedSlcNum; iSlcIdx++) {
+        EXPECT_TRUE(NULL != &pCtx->pCurDqLayer->ppSliceInLayer[iSlcIdx]);
+        EXPECT_TRUE(iSlcIdx == pCtx->pCurDqLayer->ppSliceInLayer[iSlcIdx]->iSliceIdx);
+    }
+
+    UnInitParamForTestCase(iLayerIdx);
+}
+
+TEST_F(CSliceBufferReallocatTest, LayerInfoUpdateTest) {
+    sWelsEncCtx* pCtx = &m_EncContext;
+    int32_t iLayerIdx = 0;
+    int32_t iRet = 0;
+    SFrameBSInfo FrameBsInfo;
+    SLayerBSInfo* pLayerBsInfo = NULL;
+
+    InitParamForTestCase(iLayerIdx);
+    pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
+    iRet = InitAllSlicesInThread(pCtx);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    SimulateSliceInOneLayer();
+
+    //simulate reallocate slice buffer in one thread
+    int32_t iReallocateThrdIdx = rand() % pCtx->iActiveThreadsNum;
+    int32_t iSlcBuffNumInThrd  = pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iMaxSliceNum;
+    int32_t iCodedSlcNumInThrd = pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iCodedSliceNum;
+    SSlice* pSlcListInThrd     = pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].pSliceInThread;
+    SliceModeEnum eSlcMode     = pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument.uiSliceMode;
+    int32_t iSlcIdxInThrd      = 0;
+    int32_t iPartitionNum      = (SM_SIZELIMITED_SLICE == eSlcMode) ? pCtx->iActiveThreadsNum : 1;
+    int32_t iPartitionIdx      = 0;
+    iPartitionIdx = (iCodedSlcNumInThrd <= 0) ? 0 :
+                    pSlcListInThrd[iCodedSlcNumInThrd - 1].iSliceIdx % pCtx->iActiveThreadsNum;
+
+    iRet = ReallocateSliceList(pCtx, &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument,
+                               pSlcListInThrd, iSlcBuffNumInThrd, iSlcBuffNumInThrd * 2);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+    EXPECT_TRUE(NULL != pSlcListInThrd);
+    pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].pSliceInThread = pSlcListInThrd;
+    pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iMaxSliceNum = iSlcBuffNumInThrd * 2;
+
+    //update reallocate slice idx/NalNum info
+    for (int32_t iSlcIdx = iCodedSlcNumInThrd; iSlcIdx < iSlcBuffNumInThrd * 2; iSlcIdx++) {
+        if (SM_SIZELIMITED_SLICE == eSlcMode) {
+            iSlcIdxInThrd = iPartitionIdx + pCtx->pCurDqLayer->NumSliceCodedOfPartition[iPartitionIdx] * iPartitionNum;
+            pCtx->pCurDqLayer->NumSliceCodedOfPartition[iPartitionIdx] ++;
+        } else {
+            iSlcIdxInThrd = pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame;
+        }
+        EXPECT_TRUE(NULL != &pSlcListInThrd[iSlcIdx]);
+        pSlcListInThrd[iSlcIdx].iSliceIdx = iSlcIdxInThrd;
+        pSlcListInThrd[iSlcIdx].sSliceBs.iNalIndex = rand() % 2 + 1;
+        pSlcListInThrd[iSlcIdx].sSliceBs.uiBsPos = rand() % pSlcListInThrd[iSlcIdx].sSliceBs.uiSize + 1;
+        pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame ++;
+        pCtx->pCurDqLayer->sSliceThreadInfo[iReallocateThrdIdx].iCodedSliceNum++;
+    }
+
+    //simulate for layer bs
+    int32_t iCurLayerIdx = rand() % MAX_LAYER_NUM_OF_FRAME;
+    memset(&FrameBsInfo, 0, sizeof(SFrameBSInfo));
+
+    pCtx->iPosBsBuffer = rand() % pCtx->iFrameBsSize + 1;
+    pLayerBsInfo = &FrameBsInfo.sLayerInfo[iCurLayerIdx];
+    pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
+    pCtx->bNeedPrefixNalFlag = rand() % 2;
+
+    iRet = SliceLayerInfoUpdate(pCtx, &FrameBsInfo, pLayerBsInfo,	eSlcMode);
+    EXPECT_TRUE(cmResultSuccess == iRet);
+
+    UnInitParamForTestCase(iLayerIdx);
+}
--- /dev/null
+++ b/test/encoder/EncUT_SliceBufferReallocate.h
@@ -1,0 +1,70 @@
+#include <gtest/gtest.h>
+#include "utils/FileInputStream.h"
+#include "svc_encode_slice.h"
+
+//level 5.2, table A-6, Max frame rates setting
+#define MAX_WIDTH               (4096)
+#define MAX_HEIGH               (2304)
+#define MAX_SAMPLES_PER_SECOND  (530841600)
+
+#define MAX_QP                   (51)
+#define MIN_QP                   (0)
+
+class CSliceBufferReallocatTest : public ::testing::Test { //WithParamInterface<EncodeFileParam>{
+public:
+    virtual void SetUp() {
+        m_pEncoder   = NULL;
+        int32_t iRet = WelsCreateSVCEncoder(&m_pEncoder);
+        ASSERT_EQ(0, iRet);
+        EXPECT_TRUE(m_pEncoder != NULL);
+
+        int32_t iCacheLineSize = 16;
+        m_EncContext.pMemAlign = new CMemoryAlign(iCacheLineSize);
+        EXPECT_TRUE(NULL != m_EncContext.pMemAlign);
+
+        SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)m_EncContext.pMemAlign->WelsMalloc(sizeof(SWelsSvcCodingParam),
+                                            "SWelsSvcCodingParam");
+        EXPECT_TRUE(NULL != pCodingParam);
+        m_EncContext.pSvcParam = pCodingParam;
+
+        iRet = m_pEncoder->GetDefaultParams(m_EncContext.pSvcParam);
+        ASSERT_EQ(0, iRet);
+    }
+
+    virtual void TearDown() {
+        WelsDestroySVCEncoder(m_pEncoder);
+        m_pEncoder = NULL;
+        if (NULL != m_EncContext.pSvcParam) {
+            m_EncContext.pMemAlign->WelsFree(m_EncContext.pSvcParam, "SWelsSvcCodingParam");
+            m_EncContext.pSvcParam = NULL;
+        }
+
+        if (m_EncContext.pMemAlign != NULL)  {
+            delete m_EncContext.pMemAlign;
+            m_EncContext.pMemAlign = NULL;
+        }
+    }
+
+    void SimulateEncodedOneSlice(const int32_t kiSlcIdx, const int32_t kiThreadIdx);
+    void SimulateSliceInOnePartition(const int32_t kiPartNum,  const int32_t kiPartIdx, const int32_t kiSlcNumInPart);
+    void SimulateSliceInOneLayer();
+
+    void InitParamForTestCase(int32_t iLayerIdx);
+    void InitParamForSizeLimitSlcModeCase(int32_t iLayerIdx);
+    void UnInitParamForTestCase(int32_t iLayerIdx);
+
+    void InitParam();
+    void UnInitParam();
+
+    void InitFrameBsBuffer();
+    void UnInitFrameBsBuffer();
+
+    void InitLayerSliceBuffer(const int32_t iLayerIdx);
+    void UnInitLayerSliceBuffer(const int32_t iLayerIdx);
+
+    ISVCEncoder*  m_pEncoder;
+    sWelsEncCtx   m_EncContext;
+
+private:
+
+};
--- a/test/encoder/targets.mk
+++ b/test/encoder/targets.mk
@@ -18,6 +18,7 @@
 	$(ENCODER_UNITTEST_SRCDIR)/EncUT_Reconstruct.cpp\
 	$(ENCODER_UNITTEST_SRCDIR)/EncUT_Sample.cpp\
 	$(ENCODER_UNITTEST_SRCDIR)/EncUT_SVC_me.cpp\
+	$(ENCODER_UNITTEST_SRCDIR)/EncUT_SliceBufferReallocate.cpp\
 
 ENCODER_UNITTEST_OBJS += $(ENCODER_UNITTEST_CPP_SRCS:.cpp=.$(OBJ))