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