ref: a65e761385e798f35fdc9f33c93b470f6a490a0d
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");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pDqLayer))
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);
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != iRet))
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 SetParamForReallocateTest (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;
}
int CSliceBufferReallocatTest::InitParamForTestCase (int32_t iLayerIdx) {
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParam()))
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitFrameBsBuffer()))
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitLayerSliceBuffer (iLayerIdx)))
//param validation
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR,
(cmResultSuccess != m_pEncoder->InitializeExt ((SEncParamExt*)m_EncContext.pSvcParam)))
return ENC_RETURN_SUCCESS;
}
int CSliceBufferReallocatTest::InitParamForSizeLimitSlcModeCase (int32_t iLayerIdx) {
SSliceArgument* pSliceArgument = &m_EncContext.pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParam()))
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitFrameBsBuffer()))
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitLayerSliceBuffer (iLayerIdx)))
if (SM_SIZELIMITED_SLICE != pSliceArgument->uiSliceMode && NULL != m_EncContext.ppDqLayerList[iLayerIdx]) {
UnInitLayerSliceBuffer (iLayerIdx);
pSliceArgument->uiSliceMode = SM_SIZELIMITED_SLICE;
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParamForSizeLimitSlcMode (&m_EncContext,
iLayerIdx)))
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == m_EncContext.ppDqLayerList[iLayerIdx]))
}
//param validation
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR,
(cmResultSuccess != m_pEncoder->InitializeExt ((SEncParamExt*)m_EncContext.pSvcParam)))
return ENC_RETURN_SUCCESS;
}
void CSliceBufferReallocatTest::UnInitParamForTestCase (int32_t iLayerIdx) {
int32_t iRet = m_pEncoder->Uninitialize();
ASSERT_TRUE (cmResultSuccess == iRet);
UnInitFrameBsBuffer();
UnInitLayerSliceBuffer (iLayerIdx);
UnInitParam();
}
int 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");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFuncList))
pCtx->pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy (
pCtx->pSvcParam->eSpsPpsIdStrategy,
pCtx->pSvcParam->bSimulcastAVC, pCtx->pSvcParam->iSpatialLayerNum);
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFuncList->pParametersetStrategy))
pCtx->ppDqLayerList = (SDqLayer**)pCtx->pMemAlign->WelsMallocz (pCtx->pSvcParam->iSpatialLayerNum * sizeof (SDqLayer*),
"ppDqLayerList");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->ppDqLayerList))
return ENC_RETURN_SUCCESS;
}
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;
}
}
int 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);
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (0 != iRet))
// Output
pCtx->pOut = (SWelsEncoderOutput*)pCtx->pMemAlign->WelsMallocz (sizeof (SWelsEncoderOutput), "SWelsEncoderOutput");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut))
pCtx->pOut->pBsBuffer = (uint8_t*)pCtx->pMemAlign->WelsMallocz (iCountBsLen, "pOut->pBsBuffer");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut->pBsBuffer))
pCtx->pOut->uiSize = iCountBsLen;
pCtx->pOut->sNalList = (SWelsNalRaw*)pCtx->pMemAlign->WelsMallocz (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut->sNalList))
pCtx->pOut->pNalLen = (int32_t*)pCtx->pMemAlign->WelsMallocz (iCountNals * sizeof (int32_t), "pOut->pNalLen");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (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");
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFrameBs))
pCtx->iFrameBsSize = iCountBsLen;
pCtx->iPosBsBuffer = 0;
return ENC_RETURN_SUCCESS;
}
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;
}
}
int 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 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) {
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != 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;
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != AllocateLayerBuffer (pCtx, iLayerIdx)))
}
WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->ppDqLayerList[iLayerIdx]))
pCtx->uiDependencyId = iLayerIdx;
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
return ENC_RETURN_SUCCESS;
}
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;
ASSERT_TRUE (NULL != m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer);
ASSERT_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);
ASSERT_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);
ASSERT_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;
iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
ASSERT_TRUE (cmResultSuccess == iRet);
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
iRet = InitAllSlicesInThread (pCtx);
ASSERT_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;
SetParamForReallocateTest (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;
iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
ASSERT_TRUE (cmResultSuccess == iRet);
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
iRet = InitAllSlicesInThread (pCtx);
ASSERT_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;
SetParamForReallocateTest (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;
iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
ASSERT_TRUE (cmResultSuccess == iRet);
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
iRet = InitAllSlicesInThread (pCtx);
ASSERT_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);
ASSERT_TRUE (cmResultSuccess == iRet);
ASSERT_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;
int32_t iRet = 0;
sWelsEncCtx* pCtx = &m_EncContext;
SSliceArgument* pSliceArgument = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
ASSERT_TRUE (cmResultSuccess == iRet);
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
iRet = InitAllSlicesInThread (pCtx);
ASSERT_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;
iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
ASSERT_TRUE (cmResultSuccess == iRet);
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
iRet = InitAllSlicesInThread (pCtx);
ASSERT_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);
ASSERT_TRUE (cmResultSuccess == iRet);
ASSERT_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;
}
ASSERT_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);
}