• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "wels_common_basis.h"
2 #include "utils/BufferedData.h"
3 #include "BaseEncoderTest.h"
4 #include "svc_encode_slice.h"
5 #include "encoder.h"
6 #include "macros.h"
7 #include "EncUT_SliceBufferReallocate.h"
8 
9 namespace WelsEnc {
10 extern void FreeDqLayer (SDqLayer*& pDq, CMemoryAlign* pMa);
11 extern void FreeMemorySvc (sWelsEncCtx** ppCtx);
12 extern int32_t AcquireLayersNals (sWelsEncCtx** ppCtx,
13                                   SWelsSvcCodingParam* pParam,
14                                   int32_t* pCountLayers,
15                                   int32_t* pCountNals);
16 extern int32_t ExtendLayerBuffer (sWelsEncCtx* pCtx,
17                                   const int32_t kiMaxSliceNumOld,
18                                   const int32_t kiMaxSliceNumNew);
19 }
20 
RandAvailableThread(sWelsEncCtx * pCtx,const int32_t kiMinBufferNum)21 int32_t RandAvailableThread (sWelsEncCtx* pCtx, const int32_t kiMinBufferNum) {
22   int32_t aiThrdList[MAX_THREADS_NUM] = { -1 };
23   int32_t iCodedSlcNum = 0;
24   int32_t iMaxSlcNumInThrd = 0;
25   int32_t iAvailableThrdNum = 0;
26   int32_t iRandThrdIdx = -1;
27 
28   if (NULL == pCtx || NULL == pCtx->pCurDqLayer || pCtx->iActiveThreadsNum <= 0) {
29     return -1;
30   }
31 
32   for (int32_t iThrdIdx = 0; iThrdIdx < pCtx->iActiveThreadsNum; iThrdIdx++) {
33     iCodedSlcNum = pCtx->pCurDqLayer->sSliceBufferInfo[iThrdIdx].iCodedSliceNum;
34     iMaxSlcNumInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iThrdIdx].iMaxSliceNum;
35 
36     if ((iCodedSlcNum + kiMinBufferNum) <= iMaxSlcNumInThrd) {
37       aiThrdList[iAvailableThrdNum] = iThrdIdx;
38       iAvailableThrdNum++;
39     }
40   }
41 
42   if (0 == iAvailableThrdNum) {
43     return -1;
44   }
45   iRandThrdIdx = rand() % iAvailableThrdNum;
46 
47   return aiThrdList[iRandThrdIdx];
48 }
49 
AllocateLayerBuffer(sWelsEncCtx * pCtx,const int32_t iLayerIdx)50 int32_t AllocateLayerBuffer (sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
51   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
52   SDqLayer* pDqLayer = (SDqLayer*)pCtx->pMemAlign->WelsMallocz (sizeof (SDqLayer), "pDqLayer");
53   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pDqLayer))
54 
55   pDqLayer->iMbWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
56   pDqLayer->iMbHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
57   pDqLayer->iMaxSliceNum = GetInitialSliceNum (&pLayerCfg->sSliceArgument);
58 
59   int32_t iRet = InitSliceInLayer (pCtx, pDqLayer, iLayerIdx, pCtx->pMemAlign);
60   if (ENC_RETURN_SUCCESS != iRet) {
61     FreeDqLayer (pDqLayer, pCtx->pMemAlign);
62     return ENC_RETURN_MEMALLOCERR;
63   }
64 
65   pCtx->ppDqLayerList[iLayerIdx] = pDqLayer;
66   return ENC_RETURN_SUCCESS;
67 }
68 
SetPartitonMBNum(SDqLayer * pCurDqLayer,SSpatialLayerConfig * pLayerCfg,int32_t iPartNum)69 void SetPartitonMBNum (SDqLayer* pCurDqLayer, SSpatialLayerConfig* pLayerCfg, int32_t iPartNum) {
70   int32_t iMBWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
71   int32_t iMBHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
72   int32_t iMbNumInFrame = iMBWidth * iMBHeight;
73   int32_t iMBPerPart = iMbNumInFrame / iPartNum;
74 
75   if (0 == iMBPerPart) {
76     iPartNum = 1;
77     iMBPerPart = iMbNumInFrame;
78   }
79 
80   for (int32_t iPartIdx = 0; iPartIdx < (iPartNum - 1); iPartIdx++) {
81     pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] = iMBPerPart * iPartIdx;
82     pCurDqLayer->EndMbIdxOfPartition[iPartIdx] = pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] + iMBPerPart - 1;
83   }
84 
85   pCurDqLayer->FirstMbIdxOfPartition[iPartNum - 1] = iMBPerPart * (iPartNum - 1);
86   pCurDqLayer->EndMbIdxOfPartition[iPartNum - 1] = iMbNumInFrame - 1;
87 
88   for (int32_t iPartIdx = iPartNum; iPartIdx < MAX_THREADS_NUM; iPartIdx++) {
89     pCurDqLayer->FirstMbIdxOfPartition[iPartIdx] = 0;
90     pCurDqLayer->EndMbIdxOfPartition[iPartIdx] = 0;
91   }
92 }
93 
InitParamForSizeLimitSlcMode(sWelsEncCtx * pCtx,const int32_t iLayerIdx)94 int32_t InitParamForSizeLimitSlcMode (sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
95   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
96   SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
97   int32_t iSliceBufferSize = 0;
98   int32_t iLayerBsSize = WELS_ROUND (((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR)
99                          + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
100   pSliceArgument->uiSliceSizeConstraint = 600;
101   pCtx->pSvcParam->uiMaxNalSize = 1500;
102 
103   int32_t iMaxSliceNumEstimation = WELS_MIN (AVERSLICENUM_CONSTRAINT,
104                                    (iLayerBsSize / pSliceArgument->uiSliceSizeConstraint) + 1);
105   pCtx->iMaxSliceCount = WELS_MAX (pCtx->iMaxSliceCount, iMaxSliceNumEstimation);
106   iSliceBufferSize = (WELS_MAX ((int32_t)pSliceArgument->uiSliceSizeConstraint,
107                                 iLayerBsSize / iMaxSliceNumEstimation) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
108   pCtx->iSliceBufferSize[iLayerIdx] = iSliceBufferSize;
109 
110   int32_t iRet = AllocateLayerBuffer (pCtx, iLayerIdx);
111   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != iRet))
112 
113   SetPartitonMBNum (pCtx->ppDqLayerList[iLayerIdx], pLayerCfg, pCtx->iActiveThreadsNum);
114   return ENC_RETURN_SUCCESS;
115 }
116 
InitParamForRasterSlcMode(sWelsEncCtx * pCtx,const int32_t iLayerIdx)117 void InitParamForRasterSlcMode (sWelsEncCtx* pCtx, const int32_t iLayerIdx) {
118   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
119   SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
120   int32_t iMBWidth = (pLayerCfg->iVideoWidth + 15) >> 4;
121   int32_t iMBHeight = (pLayerCfg->iVideoHeight + 15) >> 4;
122   int32_t iMbNumInFrame = iMBWidth * iMBHeight;
123   int32_t iSliceMBNum = 0;
124 
125   pSliceArgument->uiSliceMbNum[0] = rand() % 2;
126   if (0 == pSliceArgument->uiSliceMbNum[0] && iMBHeight > MAX_SLICES_NUM) {
127     pSliceArgument->uiSliceNum = MAX_SLICES_NUM;
128     pSliceArgument->uiSliceMbNum[0] = 1;
129   }
130 
131   if (0 != pSliceArgument->uiSliceMbNum[0]) {
132     iSliceMBNum = iMbNumInFrame / pSliceArgument->uiSliceNum;
133     for (int32_t iSlcIdx = 0; iSlcIdx < (int32_t)pSliceArgument->uiSliceNum - 1; iSlcIdx++) {
134       pSliceArgument->uiSliceMbNum[iSlcIdx] = iSliceMBNum;
135     }
136     iSliceMBNum = iMbNumInFrame / pSliceArgument->uiSliceNum;
137     pSliceArgument->uiSliceMbNum[pSliceArgument->uiSliceNum - 1] = iMbNumInFrame - iSliceMBNum *
138         (pSliceArgument->uiSliceNum - 1);
139   }
140 }
141 
SetParamForReallocateTest(sWelsEncCtx * pCtx,int32_t iLayerIdx,int32_t iThreadIndex,int32_t iPartitionNum)142 void SetParamForReallocateTest (sWelsEncCtx* pCtx, int32_t iLayerIdx,
143                                 int32_t iThreadIndex, int32_t iPartitionNum) {
144   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
145   int32_t iPartitionID = rand() % iPartitionNum;
146   int32_t iMBNumInPatition = 0;
147   int32_t iCodedSlcNum = pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum - 1;
148   int32_t iLastCodeSlcIdx = iPartitionID + iCodedSlcNum * iPartitionNum;
149   SSlice* pLastCodedSlc = &pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer[iCodedSlcNum - 1];
150   pLastCodedSlc->iSliceIdx = iLastCodeSlcIdx;
151 
152   SetPartitonMBNum (pCtx->ppDqLayerList[iLayerIdx], pLayerCfg, iPartitionNum);
153 
154   iMBNumInPatition = pCtx->pCurDqLayer->EndMbIdxOfPartition[iPartitionID] -
155                      pCtx->pCurDqLayer->FirstMbIdxOfPartition[iPartitionID] + 1;
156   pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iCodedSliceNum = iCodedSlcNum;
157   pCtx->pCurDqLayer->LastCodedMbIdxOfPartition[iPartitionID] = rand() % iMBNumInPatition + 1;
158 
159 }
160 
InitParamForTestCase(int32_t iLayerIdx)161 int CSliceBufferReallocatTest::InitParamForTestCase (int32_t iLayerIdx) {
162   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParam()))
163   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitFrameBsBuffer()))
164   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitLayerSliceBuffer (iLayerIdx)))
165 
166   //param validation
167   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR,
168                          (cmResultSuccess != m_pEncoder->InitializeExt ((SEncParamExt*)m_EncContext.pSvcParam)))
169   return ENC_RETURN_SUCCESS;
170 }
171 
InitParamForSizeLimitSlcModeCase(int32_t iLayerIdx)172 int CSliceBufferReallocatTest::InitParamForSizeLimitSlcModeCase (int32_t iLayerIdx) {
173   SSliceArgument* pSliceArgument = &m_EncContext.pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
174 
175   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParam()))
176   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitFrameBsBuffer()))
177   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitLayerSliceBuffer (iLayerIdx)))
178 
179   if (SM_SIZELIMITED_SLICE != pSliceArgument->uiSliceMode && NULL != m_EncContext.ppDqLayerList[iLayerIdx]) {
180     UnInitLayerSliceBuffer (iLayerIdx);
181     pSliceArgument->uiSliceMode = SM_SIZELIMITED_SLICE;
182     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParamForSizeLimitSlcMode (&m_EncContext,
183                            iLayerIdx)))
184     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == m_EncContext.ppDqLayerList[iLayerIdx]))
185   }
186 
187   //param validation
188   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR,
189                          (cmResultSuccess != m_pEncoder->InitializeExt ((SEncParamExt*)m_EncContext.pSvcParam)))
190   return ENC_RETURN_SUCCESS;
191 }
192 
UnInitParamForTestCase(int32_t iLayerIdx)193 void CSliceBufferReallocatTest::UnInitParamForTestCase (int32_t iLayerIdx) {
194   int32_t iRet = m_pEncoder->Uninitialize();
195   ASSERT_TRUE (cmResultSuccess == iRet);
196 
197   UnInitFrameBsBuffer();
198   UnInitLayerSliceBuffer (iLayerIdx);
199   UnInitParam();
200 }
201 
InitParam()202 int CSliceBufferReallocatTest::InitParam() {
203   sWelsEncCtx* pCtx = &m_EncContext;
204   SWelsFuncPtrList sEncFunctionList;
205   pCtx->pFuncList = &sEncFunctionList;
206 
207   //always multi thread cases
208   pCtx->pSvcParam->iMultipleThreadIdc = (rand() % MAX_THREADS_NUM) + 1;
209   pCtx->pSvcParam->iMultipleThreadIdc = (pCtx->pSvcParam->iMultipleThreadIdc <= 1) ? 2 :
210                                         pCtx->pSvcParam->iMultipleThreadIdc;
211   pCtx->iActiveThreadsNum = pCtx->pSvcParam->iMultipleThreadIdc;
212   pCtx->pSvcParam->iSpatialLayerNum = 1;
213   pCtx->pSvcParam->bSimulcastAVC = rand() % 2 == 1;
214 
215   pCtx->pSvcParam->iPicHeight = (((rand() % MAX_WIDTH) >> 4) << 4) + 16;
216   pCtx->pSvcParam->iPicWidth  = (((rand() % MAX_HEIGH) >> 4) << 4) + 16;
217   pCtx->iGlobalQp = WelsClip3 (rand() % MAX_QP, MIN_QP, MAX_QP);
218   pCtx->pSvcParam->iRCMode = RC_OFF_MODE;
219   pCtx->pSvcParam->iTargetBitrate = WelsClip3 (rand() % MAX_BIT_RATE, MIN_BIT_RATE, MAX_BIT_RATE);
220   int32_t iParamStraIdx = rand() % 5;
221   pCtx->pSvcParam->eSpsPpsIdStrategy = (EParameterSetStrategy) (iParamStraIdx == 4 ? 0x06 : iParamStraIdx);
222 
223   pCtx->pFuncList = (SWelsFuncPtrList*)pCtx->pMemAlign->WelsMallocz (sizeof (SWelsFuncPtrList), "SWelsFuncPtrList");
224   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFuncList))
225 
226   pCtx->pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy (
227         pCtx->pSvcParam->eSpsPpsIdStrategy,
228         pCtx->pSvcParam->bSimulcastAVC, pCtx->pSvcParam->iSpatialLayerNum);
229   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFuncList->pParametersetStrategy))
230 
231   pCtx->ppDqLayerList = (SDqLayer**)pCtx->pMemAlign->WelsMallocz (pCtx->pSvcParam->iSpatialLayerNum * sizeof (SDqLayer*),
232                         "ppDqLayerList");
233   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->ppDqLayerList))
234   return ENC_RETURN_SUCCESS;
235 }
236 
UnInitParam()237 void CSliceBufferReallocatTest::UnInitParam() {
238   sWelsEncCtx* pCtx = &m_EncContext;
239   if (NULL != pCtx->pFuncList->pParametersetStrategy) {
240     delete pCtx->pFuncList->pParametersetStrategy;
241     pCtx->pFuncList->pParametersetStrategy = NULL;
242   }
243 
244   if (NULL != pCtx->pFuncList) {
245     pCtx->pMemAlign->WelsFree (pCtx->pFuncList, "pCtx->pFuncList");
246     pCtx->pFuncList = NULL;
247   }
248 
249   if (NULL != pCtx->ppDqLayerList) {
250     pCtx->pMemAlign->WelsFree (pCtx->ppDqLayerList, "pCtx->ppDqLayerList");
251     pCtx->ppDqLayerList = NULL;
252   }
253 }
254 
InitFrameBsBuffer()255 int CSliceBufferReallocatTest::InitFrameBsBuffer() {
256   const int32_t iLayerIdx = 0;
257   sWelsEncCtx* pCtx = &m_EncContext;
258   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
259   const int32_t kiSpsSize = pCtx->pFuncList->pParametersetStrategy->GetNeededSpsNum() * SPS_BUFFER_SIZE;
260   const int32_t kiPpsSize = pCtx->pFuncList->pParametersetStrategy->GetNeededPpsNum() * PPS_BUFFER_SIZE;
261 
262   int32_t iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
263   int32_t iLayerBsSize = WELS_ROUND (((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR) +
264                          MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
265   int32_t iVclLayersBsSizeCount = WELS_ALIGN (iLayerBsSize, 4);
266   int32_t iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount;
267   int32_t iCountNals = 0;
268 
269   int32_t iRet = AcquireLayersNals (&pCtx, pCtx->pSvcParam, &pCtx->pSvcParam->iSpatialLayerNum, &iCountNals);
270   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (0 != iRet))
271 
272   // Output
273   pCtx->pOut = (SWelsEncoderOutput*)pCtx->pMemAlign->WelsMallocz (sizeof (SWelsEncoderOutput), "SWelsEncoderOutput");
274   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut))
275   pCtx->pOut->pBsBuffer = (uint8_t*)pCtx->pMemAlign->WelsMallocz (iCountBsLen, "pOut->pBsBuffer");
276   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut->pBsBuffer))
277   pCtx->pOut->uiSize = iCountBsLen;
278   pCtx->pOut->sNalList = (SWelsNalRaw*)pCtx->pMemAlign->WelsMallocz (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
279   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut->sNalList))
280   pCtx->pOut->pNalLen = (int32_t*)pCtx->pMemAlign->WelsMallocz (iCountNals * sizeof (int32_t), "pOut->pNalLen");
281   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pOut->pNalLen))
282   pCtx->pOut->iCountNals = iCountNals;
283   pCtx->pOut->iNalIndex = 0;
284   pCtx->pOut->iLayerBsIndex = 0;
285   pCtx->pFrameBs = (uint8_t*)pCtx->pMemAlign->WelsMalloc (iCountBsLen, "pFrameBs");
286   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->pFrameBs))
287   pCtx->iFrameBsSize = iCountBsLen;
288   pCtx->iPosBsBuffer = 0;
289   return ENC_RETURN_SUCCESS;
290 }
291 
UnInitFrameBsBuffer()292 void CSliceBufferReallocatTest::UnInitFrameBsBuffer() {
293   sWelsEncCtx* pCtx = &m_EncContext;
294 
295   if (NULL != pCtx->pOut->pBsBuffer) {
296     pCtx->pMemAlign->WelsFree (pCtx->pOut->pBsBuffer, "pCtx->pOut->pBsBuffer");
297     pCtx->pOut->pBsBuffer = NULL;
298   }
299 
300   if (NULL != pCtx->pOut->sNalList) {
301     pCtx->pMemAlign->WelsFree (pCtx->pOut->sNalList, "pCtx->pOut->sNalList");
302     pCtx->pOut->sNalList = NULL;
303   }
304 
305   if (NULL != pCtx->pOut->pNalLen) {
306     pCtx->pMemAlign->WelsFree (pCtx->pOut->pNalLen, "pCtx->pOut->pNalLen");
307     pCtx->pOut->pNalLen = NULL;
308   }
309 
310   if (NULL != pCtx->pOut) {
311     pCtx->pMemAlign->WelsFree (pCtx->pOut, "pCtx->pOut");
312     pCtx->pOut = NULL;
313   }
314 
315   if (NULL != pCtx->pFrameBs) {
316     pCtx->pMemAlign->WelsFree (pCtx->pFrameBs, "pCtx->pFrameBs");
317     pCtx->pFrameBs = NULL;
318   }
319 }
320 
InitLayerSliceBuffer(const int32_t iLayerIdx)321 int CSliceBufferReallocatTest::InitLayerSliceBuffer (const int32_t iLayerIdx) {
322   sWelsEncCtx* pCtx = &m_EncContext;
323   SSpatialLayerConfig* pLayerCfg = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx];
324   SSliceArgument* pSliceArgument = &pLayerCfg->sSliceArgument;
325   int32_t iLayerBsSize = 0;
326   int32_t iSliceBufferSize = 0;
327   int32_t iMaxFrameRate = 0;
328 
329   pLayerCfg->iVideoWidth  = pCtx->pSvcParam->iPicWidth >> (pCtx->pSvcParam->iSpatialLayerNum - 1 - iLayerIdx);
330   pLayerCfg->iVideoHeight = pCtx->pSvcParam->iPicHeight >> (pCtx->pSvcParam->iSpatialLayerNum - 1 - iLayerIdx);
331 
332   iMaxFrameRate         = MAX_SAMPLES_PER_SECOND / (pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight);
333   pLayerCfg->fFrameRate = WelsClip3 (pLayerCfg->fFrameRate, (float)MIN_FRAME_RATE, (float)MAX_FRAME_RATE);
334   pLayerCfg->fFrameRate = (pLayerCfg->fFrameRate > (float)iMaxFrameRate) ? (float)iMaxFrameRate : pLayerCfg->fFrameRate;
335 
336   pLayerCfg->iSpatialBitrate = pCtx->pSvcParam->iTargetBitrate / pCtx->pSvcParam->iSpatialLayerNum;
337 
338   //Slice argument
339   pSliceArgument->uiSliceMode = (SliceModeEnum) (rand() % 4);
340   pSliceArgument->uiSliceNum = rand() % MAX_SLICES_NUM + 1;
341 
342   if (pSliceArgument->uiSliceMode == SM_SIZELIMITED_SLICE) {
343     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != InitParamForSizeLimitSlcMode (pCtx, iLayerIdx)))
344   } else {
345     if (pSliceArgument->uiSliceMode == SM_RASTER_SLICE) {
346       InitParamForRasterSlcMode (pCtx, iLayerIdx);
347     }
348 
349     iLayerBsSize = WELS_ROUND (((3 * pLayerCfg->iVideoWidth * pLayerCfg->iVideoHeight) >> 1) * COMPRESS_RATIO_THR)
350                    + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
351     pCtx->iMaxSliceCount = WELS_MAX (pCtx->iMaxSliceCount, (int)pSliceArgument->uiSliceNum);
352     iSliceBufferSize = ((iLayerBsSize / pSliceArgument->uiSliceNum) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
353 
354     pCtx->iSliceBufferSize[iLayerIdx] = iSliceBufferSize;
355     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (ENC_RETURN_SUCCESS != AllocateLayerBuffer (pCtx, iLayerIdx)))
356   }
357 
358   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pCtx->ppDqLayerList[iLayerIdx]))
359 
360   pCtx->uiDependencyId = iLayerIdx;
361   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
362   return ENC_RETURN_SUCCESS;
363 }
364 
UnInitLayerSliceBuffer(const int32_t iLayerIdx)365 void CSliceBufferReallocatTest::UnInitLayerSliceBuffer (const int32_t iLayerIdx) {
366   sWelsEncCtx* pCtx = &m_EncContext;
367   if (NULL != pCtx->ppDqLayerList[iLayerIdx]) {
368     FreeDqLayer (pCtx->ppDqLayerList[iLayerIdx], pCtx->pMemAlign);
369     pCtx->ppDqLayerList[iLayerIdx] = NULL;
370   }
371 }
372 
SimulateEncodedOneSlice(const int32_t kiSlcIdx,const int32_t kiThreadIdx)373 void CSliceBufferReallocatTest::SimulateEncodedOneSlice (const int32_t kiSlcIdx, const int32_t kiThreadIdx) {
374   if (m_EncContext.pCurDqLayer->bThreadSlcBufferFlag) {
375     int32_t iCodedSlcNumInThrd = m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].iCodedSliceNum;
376 
377     ASSERT_TRUE (NULL != m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer);
378     ASSERT_TRUE (NULL != &m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer[iCodedSlcNumInThrd]);
379 
380     m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].pSliceBuffer[iCodedSlcNumInThrd].iSliceIdx = kiSlcIdx;
381     m_EncContext.pCurDqLayer->sSliceBufferInfo[kiThreadIdx].iCodedSliceNum ++;
382   } else {
383     m_EncContext.pCurDqLayer->sSliceBufferInfo[0].pSliceBuffer[kiSlcIdx].iSliceIdx = kiSlcIdx;
384   }
385 }
386 
SimulateSliceInOnePartition(const int32_t kiPartNum,const int32_t kiPartIdx,const int32_t kiSlcNumInPart)387 void CSliceBufferReallocatTest::SimulateSliceInOnePartition (const int32_t kiPartNum,
388     const int32_t kiPartIdx,
389     const int32_t kiSlcNumInPart) {
390   int32_t iSlcIdxInPart = 0;
391 
392   //slice within same partition will encoded by same thread in current design
393   int32_t iPartitionThrdIdx = RandAvailableThread (&m_EncContext, kiSlcNumInPart);
394   ASSERT_TRUE (-1 != iPartitionThrdIdx);
395 
396   for (int32_t iSlcIdx = 0; iSlcIdx < kiSlcNumInPart; iSlcIdx++) {
397     iSlcIdxInPart = kiPartIdx + kiPartNum * iSlcIdx;
398 
399     SimulateEncodedOneSlice (iSlcIdxInPart, iPartitionThrdIdx);
400 
401     m_EncContext.pCurDqLayer->NumSliceCodedOfPartition[kiPartIdx] ++;
402     m_EncContext.pCurDqLayer->sSliceEncCtx.iSliceNumInFrame ++;
403   }
404 }
405 
SimulateSliceInOneLayer()406 void CSliceBufferReallocatTest::SimulateSliceInOneLayer() {
407   int32_t iLayerIdx = 0;
408   SSpatialLayerConfig* pLayerCfg = &m_EncContext.pSvcParam->sSpatialLayers[iLayerIdx];
409   int32_t iTotalSliceBuffer = m_EncContext.pCurDqLayer->iMaxSliceNum;
410   int32_t iSimulateSliceNum = rand() % iTotalSliceBuffer + 1;
411 
412   if (SM_SIZELIMITED_SLICE == pLayerCfg->sSliceArgument.uiSliceMode) {
413     int32_t iPartNum         = m_EncContext.iActiveThreadsNum;
414     int32_t iSlicNumPerPart  = iSimulateSliceNum / iPartNum;
415     int32_t iMaxSlcNumInThrd = m_EncContext.pCurDqLayer->sSliceBufferInfo[0].iMaxSliceNum;
416     int32_t iLastPartSlcNum = 0;
417 
418     iSlicNumPerPart = WelsClip3 (iSlicNumPerPart, 1, iMaxSlcNumInThrd);
419     iLastPartSlcNum = iSimulateSliceNum - iSlicNumPerPart * (iPartNum - 1);
420     iLastPartSlcNum = WelsClip3 (iLastPartSlcNum, 1, iMaxSlcNumInThrd);
421 
422     for (int32_t iPartIdx = 0; iPartIdx < iPartNum; iPartIdx ++) {
423       int32_t iSlcNumInPart = (iPartIdx < (iPartNum - 1)) ? iSlicNumPerPart : iLastPartSlcNum;
424       SimulateSliceInOnePartition (iPartNum, iPartIdx, iSlcNumInPart);
425     }
426   } else {
427     for (int32_t iSlcIdx = 0; iSlcIdx < iSimulateSliceNum; iSlcIdx ++) {
428       int32_t iSlcThrdIdx = RandAvailableThread (&m_EncContext, 1);
429       ASSERT_TRUE (-1 != iSlcThrdIdx);
430 
431       SimulateEncodedOneSlice (iSlcIdx, iSlcThrdIdx);
432       m_EncContext.pCurDqLayer->sSliceEncCtx.iSliceNumInFrame++;
433     }
434   }
435 }
436 
TEST_F(CSliceBufferReallocatTest,Reallocate_in_one_partition)437 TEST_F (CSliceBufferReallocatTest, Reallocate_in_one_partition) {
438   sWelsEncCtx* pCtx = &m_EncContext;
439   int32_t iLayerIdx = 0;
440   int32_t iRet      = 0;
441 
442   iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
443   ASSERT_TRUE (cmResultSuccess == iRet);
444   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
445   iRet = InitAllSlicesInThread (pCtx);
446   ASSERT_TRUE (cmResultSuccess == iRet);
447 
448   //case: reallocate during encoding one partition
449   //      include cases which part num less than thread num
450   //example: 3 threads but 2 partitions
451   //          thrd_0: partition_0
452   //          thrd_1: partition_1
453   //          thrd_2: idle
454   int32_t iThreadIndex  = rand() % pCtx->iActiveThreadsNum;
455   int32_t iPartitionNum = rand() % pCtx->iActiveThreadsNum + 1; //include cases which part num less than thread num
456   int32_t iSlcBufferNum = pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum;
457 
458   SetParamForReallocateTest (pCtx, iLayerIdx, iThreadIndex, iPartitionNum);
459   iRet = ReallocateSliceInThread (pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex);
460   EXPECT_TRUE (cmResultSuccess == iRet);
461   EXPECT_TRUE (NULL != pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer);
462   EXPECT_TRUE (iSlcBufferNum < pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum);
463 
464   UnInitParamForTestCase (iLayerIdx);
465 }
466 
TEST_F(CSliceBufferReallocatTest,Reallocate_in_one_thread)467 TEST_F (CSliceBufferReallocatTest, Reallocate_in_one_thread) {
468   sWelsEncCtx* pCtx = &m_EncContext;
469   int32_t iLayerIdx = 0;
470   int32_t iRet = 0;
471 
472   iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
473   ASSERT_TRUE (cmResultSuccess == iRet);
474   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
475   iRet = InitAllSlicesInThread (pCtx);
476   ASSERT_TRUE (cmResultSuccess == iRet);
477 
478   //case: all partitions encoded by one thread
479   //example: 3 threads 3 partions
480   //         thrd_0:  partion_0 -->partition_1 -->partition_2
481   //         thrd_1:  idle
482   //         thrd_2:  idle
483   int32_t iThreadIndex  =  rand() % pCtx->iActiveThreadsNum;
484   int32_t iPartitionNum = pCtx->iActiveThreadsNum;
485   int32_t iSlcBufferNum = 0;
486 
487   SetParamForReallocateTest (pCtx, iLayerIdx, iThreadIndex, iPartitionNum);
488 
489   for (int32_t iPartIdx = 0; iPartIdx < iPartitionNum; iPartIdx++) {
490     iSlcBufferNum = pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum;
491 
492     iRet = ReallocateSliceInThread (pCtx, pCtx->pCurDqLayer, iLayerIdx, iThreadIndex);
493     EXPECT_TRUE (cmResultSuccess == iRet);
494     EXPECT_TRUE (NULL != pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].pSliceBuffer);
495     EXPECT_TRUE (iSlcBufferNum < pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIndex].iMaxSliceNum);
496   }
497 
498   UnInitParamForTestCase (iLayerIdx);
499 }
500 
TEST_F(CSliceBufferReallocatTest,ExtendLayerBufferTest)501 TEST_F (CSliceBufferReallocatTest, ExtendLayerBufferTest) {
502   sWelsEncCtx* pCtx = &m_EncContext;
503   SSlice* pSlcListInThrd = NULL;
504   int32_t iLayerIdx = 0;
505   int32_t iRet = 0;
506   int32_t iMaxSliceNumNew = 0;
507   int32_t iSlcBuffNumInThrd = 0;
508 
509   iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
510   ASSERT_TRUE (cmResultSuccess == iRet);
511   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
512   iRet = InitAllSlicesInThread (pCtx);
513   ASSERT_TRUE (cmResultSuccess == iRet);
514 
515   //before extend, simulate reallocate slice buffer in one thread
516   int32_t iReallocateThrdIdx = rand() % pCtx->iActiveThreadsNum;
517   iSlcBuffNumInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum;
518   pSlcListInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer;
519 
520   iRet = ReallocateSliceList (pCtx, &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument,
521                               pSlcListInThrd, iSlcBuffNumInThrd, iSlcBuffNumInThrd * 2);
522   ASSERT_TRUE (cmResultSuccess == iRet);
523   ASSERT_TRUE (NULL != pSlcListInThrd);
524   pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer = pSlcListInThrd;
525   pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum   = iSlcBuffNumInThrd * 2;
526 
527   for (int32_t iThreadIdx = 0; iThreadIdx < pCtx->iActiveThreadsNum; iThreadIdx++) {
528     iMaxSliceNumNew += pCtx->pCurDqLayer->sSliceBufferInfo[iThreadIdx].iMaxSliceNum;
529   }
530 
531   iRet = ExtendLayerBuffer (pCtx, pCtx->pCurDqLayer->iMaxSliceNum, iMaxSliceNumNew);
532   EXPECT_TRUE (cmResultSuccess == iRet);
533   EXPECT_TRUE (NULL != pCtx->pCurDqLayer->ppSliceInLayer);
534   EXPECT_TRUE (NULL != pCtx->pCurDqLayer->pFirstMbIdxOfSlice);
535   EXPECT_TRUE (NULL != pCtx->pCurDqLayer->pCountMbNumInSlice);
536 
537   UnInitParamForTestCase (iLayerIdx);
538 }
539 
TEST_F(CSliceBufferReallocatTest,FrameBsReallocateTest)540 TEST_F (CSliceBufferReallocatTest, FrameBsReallocateTest) {
541   sWelsEncCtx* pCtx = &m_EncContext;
542   int32_t iLayerIdx = 0;
543   int32_t iRet = 0;
544   SFrameBSInfo FrameBsInfo;
545   SLayerBSInfo* pLayerBsInfo = NULL;
546   int32_t iCurLayerIdx = rand() % MAX_LAYER_NUM_OF_FRAME;
547 
548   memset (&FrameBsInfo, 0, sizeof (SFrameBSInfo));
549   InitParamForTestCase (iLayerIdx);
550 
551   //init for FrameBs and LayerBs
552   pCtx->iPosBsBuffer = rand() % pCtx->iFrameBsSize + 1;
553   pLayerBsInfo = &FrameBsInfo.sLayerInfo[iCurLayerIdx];
554   pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
555   pCtx->bNeedPrefixNalFlag = rand() % 2 == 1;
556 
557   int32_t iCodedNalCount = pCtx->pOut->iCountNals;
558   iRet = FrameBsRealloc (pCtx, &FrameBsInfo, pLayerBsInfo, iCodedNalCount);
559 
560   EXPECT_TRUE (cmResultSuccess == iRet);
561   EXPECT_TRUE (iCodedNalCount < pCtx->pOut->iCountNals);
562   EXPECT_TRUE (NULL != pCtx->pOut->sNalList);
563   EXPECT_TRUE (NULL != pCtx->pOut->pNalLen);
564 
565   UnInitParamForTestCase (iLayerIdx);
566 }
567 
TEST_F(CSliceBufferReallocatTest,ReorderTest)568 TEST_F (CSliceBufferReallocatTest, ReorderTest) {
569   int32_t iLayerIdx = 0;
570   int32_t iRet = 0;
571   sWelsEncCtx* pCtx = &m_EncContext;
572   SSliceArgument* pSliceArgument = &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument;
573 
574   iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
575   ASSERT_TRUE (cmResultSuccess == iRet);
576   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
577   iRet = InitAllSlicesInThread (pCtx);
578   ASSERT_TRUE (cmResultSuccess == iRet);
579 
580   SimulateSliceInOneLayer();
581 
582   iRet = ReOrderSliceInLayer (pCtx, pSliceArgument->uiSliceMode, pCtx->iActiveThreadsNum);
583   EXPECT_TRUE (cmResultSuccess == iRet);
584 
585   int32_t iCodedSlcNum = pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame;
586   int32_t iMaxSlicNum = pCtx->pCurDqLayer->iMaxSliceNum;
587   EXPECT_TRUE (iCodedSlcNum <= iMaxSlicNum);
588   EXPECT_TRUE (NULL != pCtx->pCurDqLayer);
589   EXPECT_TRUE (NULL != pCtx->pCurDqLayer->ppSliceInLayer);
590   for (int32_t iSlcIdx = 0; iSlcIdx < iCodedSlcNum; iSlcIdx++) {
591     EXPECT_TRUE (NULL != &pCtx->pCurDqLayer->ppSliceInLayer[iSlcIdx]);
592     EXPECT_TRUE (iSlcIdx == pCtx->pCurDqLayer->ppSliceInLayer[iSlcIdx]->iSliceIdx);
593   }
594 
595   UnInitParamForTestCase (iLayerIdx);
596 }
597 
TEST_F(CSliceBufferReallocatTest,LayerInfoUpdateTest)598 TEST_F (CSliceBufferReallocatTest, LayerInfoUpdateTest) {
599   sWelsEncCtx* pCtx = &m_EncContext;
600   int32_t iLayerIdx = 0;
601   int32_t iRet = 0;
602   SFrameBSInfo FrameBsInfo;
603   SLayerBSInfo* pLayerBsInfo = NULL;
604 
605   iRet = InitParamForSizeLimitSlcModeCase (iLayerIdx);
606   ASSERT_TRUE (cmResultSuccess == iRet);
607   pCtx->pCurDqLayer = pCtx->ppDqLayerList[iLayerIdx];
608   iRet = InitAllSlicesInThread (pCtx);
609   ASSERT_TRUE (cmResultSuccess == iRet);
610 
611   SimulateSliceInOneLayer();
612 
613   //simulate reallocate slice buffer in one thread
614   int32_t iReallocateThrdIdx = rand() % pCtx->iActiveThreadsNum;
615   int32_t iSlcBuffNumInThrd  = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum;
616   int32_t iCodedSlcNumInThrd = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iCodedSliceNum;
617   SSlice* pSlcListInThrd     = pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer;
618   SliceModeEnum eSlcMode     = pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument.uiSliceMode;
619   int32_t iSlcIdxInThrd      = 0;
620   int32_t iPartitionNum      = (SM_SIZELIMITED_SLICE == eSlcMode) ? pCtx->iActiveThreadsNum : 1;
621   int32_t iPartitionIdx      = 0;
622   iPartitionIdx = (iCodedSlcNumInThrd <= 0) ? 0 :
623                   pSlcListInThrd[iCodedSlcNumInThrd - 1].iSliceIdx % pCtx->iActiveThreadsNum;
624 
625   iRet = ReallocateSliceList (pCtx, &pCtx->pSvcParam->sSpatialLayers[iLayerIdx].sSliceArgument,
626                               pSlcListInThrd, iSlcBuffNumInThrd, iSlcBuffNumInThrd * 2);
627   ASSERT_TRUE (cmResultSuccess == iRet);
628   ASSERT_TRUE (NULL != pSlcListInThrd);
629   pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].pSliceBuffer = pSlcListInThrd;
630   pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iMaxSliceNum = iSlcBuffNumInThrd * 2;
631 
632   //update reallocate slice idx/NalNum info
633   for (int32_t iSlcIdx = iCodedSlcNumInThrd; iSlcIdx < iSlcBuffNumInThrd * 2; iSlcIdx++) {
634     if (SM_SIZELIMITED_SLICE == eSlcMode) {
635       iSlcIdxInThrd = iPartitionIdx + pCtx->pCurDqLayer->NumSliceCodedOfPartition[iPartitionIdx] * iPartitionNum;
636       pCtx->pCurDqLayer->NumSliceCodedOfPartition[iPartitionIdx] ++;
637     } else {
638       iSlcIdxInThrd = pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame;
639     }
640     ASSERT_TRUE (NULL != &pSlcListInThrd[iSlcIdx]);
641     pSlcListInThrd[iSlcIdx].iSliceIdx = iSlcIdxInThrd;
642     pSlcListInThrd[iSlcIdx].sSliceBs.iNalIndex = rand() % 2 + 1;
643     pSlcListInThrd[iSlcIdx].sSliceBs.uiBsPos = rand() % pSlcListInThrd[iSlcIdx].sSliceBs.uiSize + 1;
644     pCtx->pCurDqLayer->sSliceEncCtx.iSliceNumInFrame ++;
645     pCtx->pCurDqLayer->sSliceBufferInfo[iReallocateThrdIdx].iCodedSliceNum++;
646   }
647 
648   //simulate for layer bs
649   int32_t iCurLayerIdx = rand() % MAX_LAYER_NUM_OF_FRAME;
650   memset (&FrameBsInfo, 0, sizeof (SFrameBSInfo));
651 
652   pCtx->iPosBsBuffer = rand() % pCtx->iFrameBsSize + 1;
653   pLayerBsInfo = &FrameBsInfo.sLayerInfo[iCurLayerIdx];
654   pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
655   pCtx->bNeedPrefixNalFlag = rand() % 2 == 1;
656 
657   iRet = SliceLayerInfoUpdate (pCtx, &FrameBsInfo, pLayerBsInfo, eSlcMode);
658   EXPECT_TRUE (cmResultSuccess == iRet);
659 
660   UnInitParamForTestCase (iLayerIdx);
661 }
662