ref: f3df32f3c9c3c2d2549c9337f646770357cd4cb6
dir: /test/encoder/EncUT_SliceBufferReallocate.cpp/
#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->sSliceBufferInfo[iThrdIdx].iCodedSliceNum; iMaxSlcNumInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[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->sSliceBufferInfo[iThreadIndex].iMaxSliceNum - 1; int32_t iLastCodeSlcIdx = iPartitionID + iCodedSlcNum * iPartitionNum; SSlice* pLastCodedSlc = &pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer[iCodedSlcNum - 1]; pLastCodedSlc->iSliceIdx = iLastCodeSlcIdx; SetPartitonMBNum(pCtx->ppDqLayerList[iLayerIdx], pLayerCfg, iPartitionNum); iMBNumInPatition = pCtx->pCurDqLayer->EndMbIdxOfPartition[iPartitionID] - pCtx->pCurDqLayer->FirstMbIdxOfPartition[iPartitionID] + 1; pCtx->pCurDqLayer->sSliceBufferInfo[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; //always multi thread cases pCtx->pSvcParam->iMultipleThreadIdc = (rand() % MAX_THREADS_NUM) + 1; pCtx->pSvcParam->iMultipleThreadIdc = (pCtx->pSvcParam->iMultipleThreadIdc <= 1 )? 2 : pCtx->pSvcParam->iMultipleThreadIdc; pCtx->iActiveThreadsNum = pCtx->pSvcParam->iMultipleThreadIdc; pCtx->pSvcParam->iSpatialLayerNum = 1; pCtx->pSvcParam->bSimulcastAVC = rand() % 2 == 1; 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; 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) { if(m_EncContext.pCurDqLayer->bThreadSlcBufferFlag) { int32_t iCodedSlcNumInThrd = m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].iCodedSliceNum; EXPECT_TRUE(NULL != m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer); EXPECT_TRUE(NULL != &m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer[iCodedSlcNumInThrd]); m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer[iCodedSlcNumInThrd].iSliceIdx = kiSlcIdx; m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].iCodedSliceNum ++; } else { m_EncContext.pCurDqLayer->sSliceBufferInfo[0].pSliceBuffer[kiSlcIdx].iSliceIdx = kiSlcIdx; } } 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->sSliceBufferInfo[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; //include cases which part num less than thread num int32_t iSlcBufferNum = pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum; ParamSetForReallocateTest(pCtx, iLayerIdx, iThreadIndex, iPartitionNum); iRet = ReallocateSliceInThread(pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex); EXPECT_TRUE(cmResultSuccess == iRet); EXPECT_TRUE(NULL != pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer); EXPECT_TRUE(iSlcBufferNum < pCtx->pCurDqLayer->sSliceBufferInfo[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->sSliceBufferInfo[iThreadIndex].iMaxSliceNum; iRet = ReallocateSliceInThread(pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex); EXPECT_TRUE(cmResultSuccess == iRet); EXPECT_TRUE(NULL != pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer); EXPECT_TRUE(iSlcBufferNum < pCtx->pCurDqLayer->sSliceBufferInfo[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; InitParamForSizeLimitSlcModeCase(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->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum; pSlcListInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer; iRet = ReallocateSliceList(pCtx, &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument, pSlcListInThrd, iSlcBuffNumInThrd, iSlcBuffNumInThrd * 2); EXPECT_TRUE(cmResultSuccess == iRet); EXPECT_TRUE(NULL != pSlcListInThrd); pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer = pSlcListInThrd; pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum = iSlcBuffNumInThrd * 2; for (int32_t iThreadIdx = 0; iThreadIdx < pCtx->iActiveThreadsNum; iThreadIdx++) { iMaxSliceNumNew += pCtx->pCurDqLayer->sSliceBufferInfo[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 == 1; 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; InitParamForSizeLimitSlcModeCase(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; InitParamForSizeLimitSlcModeCase(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->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum; int32_t iCodedSlcNumInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iCodedSliceNum; SSlice* pSlcListInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer; 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->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer = pSlcListInThrd; pCtx->pCurDqLayer->sSliceBufferInfo[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->sSliceBufferInfo[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 == 1; iRet = SliceLayerInfoUpdate(pCtx, &FrameBsInfo, pLayerBsInfo, eSlcMode); EXPECT_TRUE(cmResultSuccess == iRet); UnInitParamForTestCase(iLayerIdx); }