1 #include <gtest/gtest.h>
2
3 #include "wels_common_basis.h"
4 #include "memory_align.h"
5 #include "mv_pred.h"
6 #include "ls_defines.h"
7
8 using namespace WelsDec;
9
10 //Anchor functions
11 #define REF_NOT_AVAIL -2
12 #define REF_NOT_IN_LIST -1 //intra
13
14 //cache element equal to 30
15 const uint8_t g_kuiAnchorCache30ScanIdx[16] = { //mv or ref_index cache scan index, 4*4 block as basic unit
16 7, 8, 13, 14,
17 9, 10, 15, 16,
18 19, 20, 25, 26,
19 21, 22, 27, 28
20 };
21
22 typedef struct TagAnchorMvPred {
23 int16_t iMvArray[2][30][2];
24 int8_t iRefIdxArray[2][30];
25 int32_t iPartIdx;
26 int32_t iPartWidth;
27 int32_t iRef;
28 int16_t iMvp[2];
29 } SAnchorMvPred;
30
AnchorPredMv(int16_t iMotionVector[LIST_A][30][MV_A],int8_t iRefIndex[LIST_A][30],int32_t iPartIdx,int32_t iPartWidth,int8_t iRef,int16_t iMVP[2])31 void AnchorPredMv (int16_t iMotionVector[LIST_A][30][MV_A], int8_t iRefIndex[LIST_A][30],
32 int32_t iPartIdx, int32_t iPartWidth, int8_t iRef, int16_t iMVP[2]) {
33 const uint8_t kuiLeftIdx = g_kuiAnchorCache30ScanIdx[iPartIdx] - 1;
34 const uint8_t kuiTopIdx = g_kuiAnchorCache30ScanIdx[iPartIdx] - 6;
35 const uint8_t kuiRightTopIdx = kuiTopIdx + iPartWidth;
36 const uint8_t kuiLeftTopIdx = kuiTopIdx - 1;
37 const int8_t kiLeftRef = iRefIndex[0][kuiLeftIdx];
38 const int8_t kiTopRef = iRefIndex[0][kuiTopIdx];
39 const int8_t kiRightTopRef = iRefIndex[0][kuiRightTopIdx];
40 const int8_t kiLeftTopRef = iRefIndex[0][kuiLeftTopIdx];
41 int8_t iDiagonalRef = kiRightTopRef;
42 int8_t iMatchRef = 0;
43
44 int16_t iAMV[2], iBMV[2], iCMV[2];
45
46 * (int32_t*)iAMV = INTD32 (iMotionVector[0][kuiLeftIdx]);
47 * (int32_t*)iBMV = INTD32 (iMotionVector[0][kuiTopIdx]);
48 * (int32_t*)iCMV = INTD32 (iMotionVector[0][kuiRightTopIdx]);
49
50 if (REF_NOT_AVAIL == iDiagonalRef) {
51 iDiagonalRef = kiLeftTopRef;
52 * (int32_t*)iCMV = INTD32 (iMotionVector[0][kuiLeftTopIdx]);
53 }
54
55 iMatchRef = (iRef == kiLeftRef) + (iRef == kiTopRef) + (iRef == iDiagonalRef);
56
57 if ((REF_NOT_AVAIL == kiTopRef) && (REF_NOT_AVAIL == iDiagonalRef) && (kiLeftRef >= REF_NOT_IN_LIST)) {
58 ST32 (iMVP, LD32 (iAMV));
59 return;
60 }
61
62 if (1 == iMatchRef) {
63 if (iRef == kiLeftRef) {
64 ST32 (iMVP, LD32 (iAMV));
65 } else if (iRef == kiTopRef) {
66 ST32 (iMVP, LD32 (iBMV));
67 } else {
68 ST32 (iMVP, LD32 (iCMV));
69 }
70 } else {
71 iMVP[0] = WelsMedian (iAMV[0], iBMV[0], iCMV[0]);
72 iMVP[1] = WelsMedian (iAMV[1], iBMV[1], iCMV[1]);
73 }
74 }
75
AnchorPredInter8x16Mv(int16_t iMotionVector[LIST_A][30][MV_A],int8_t iRefIndex[LIST_A][30],int32_t iPartIdx,int8_t iRef,int16_t iMVP[2])76 void AnchorPredInter8x16Mv (int16_t iMotionVector[LIST_A][30][MV_A], int8_t iRefIndex[LIST_A][30],
77 int32_t iPartIdx, int8_t iRef, int16_t iMVP[2]) {
78 if (0 == iPartIdx) {
79 const int8_t kiLeftRef = iRefIndex[0][6];
80 if (iRef == kiLeftRef) {
81 ST32 (iMVP, LD32 (&iMotionVector[0][6][0]));
82 return;
83 }
84 } else { // 4 == iPartIdx
85 int8_t iDiagonalRef = iRefIndex[0][5]; //top-right
86 int8_t index = 5;
87 if (REF_NOT_AVAIL == iDiagonalRef) {
88 iDiagonalRef = iRefIndex[0][2]; //top-left for 8*8 block(index 1)
89 index = 2;
90 }
91 if (iRef == iDiagonalRef) {
92 ST32 (iMVP, LD32 (&iMotionVector[0][index][0]));
93 return;
94 }
95 }
96
97 AnchorPredMv (iMotionVector, iRefIndex, iPartIdx, 2, iRef, iMVP);
98 }
99
AnchorPredInter16x8Mv(int16_t iMotionVector[LIST_A][30][MV_A],int8_t iRefIndex[LIST_A][30],int32_t iPartIdx,int8_t iRef,int16_t iMVP[2])100 void AnchorPredInter16x8Mv (int16_t iMotionVector[LIST_A][30][MV_A], int8_t iRefIndex[LIST_A][30],
101 int32_t iPartIdx, int8_t iRef, int16_t iMVP[2]) {
102 if (0 == iPartIdx) {
103 const int8_t kiTopRef = iRefIndex[0][1];
104 if (iRef == kiTopRef) {
105 ST32 (iMVP, LD32 (&iMotionVector[0][1][0]));
106 return;
107 }
108 } else { // 8 == iPartIdx
109 const int8_t kiLeftRef = iRefIndex[0][18];
110 if (iRef == kiLeftRef) {
111 ST32 (iMVP, LD32 (&iMotionVector[0][18][0]));
112 return;
113 }
114 }
115
116 AnchorPredMv (iMotionVector, iRefIndex, iPartIdx, 4, iRef, iMVP);
117 }
118
119
120 //Ref functions in WelsDec
121 //Input structure for test
122 typedef struct TagWelsMvPred {
123 int16_t iMvArray[2][30][2];
124 int8_t iRefIdxArray[2][30];
125 int32_t iPartIdx;
126 int32_t iPartWidth;
127 int32_t iRef;
128 int16_t iMvp[2];
129 } SWelsMvPred;
130
131 //mok input data
AssignMvInputData(SAnchorMvPred * pAncMvPred)132 void AssignMvInputData (SAnchorMvPred* pAncMvPred) {
133 int32_t i, j, k;
134 //fill MV data and refIdx
135 for (i = 0; i < 2; ++i) {
136 for (j = 0; j < 30; ++j) {
137 for (k = 0; k < 2; ++k) {
138 pAncMvPred->iMvArray[i][j][k] = (rand() - RAND_MAX / 2);
139 }
140 pAncMvPred->iRefIdxArray[i][j] = (rand() % 18) - 2; //-2 ~ 15. 8x8 may have different values, but it matters nothing
141 }
142 }
143 }
144
CopyMvInputData(SWelsMvPred * pDstMvPred,SAnchorMvPred * pSrcMvPred)145 void CopyMvInputData (SWelsMvPred* pDstMvPred, SAnchorMvPred* pSrcMvPred) {
146 int32_t i, j, k;
147 //fill MV data and refIdx
148 for (i = 0; i < 2; ++i) {
149 for (j = 0; j < 30; ++j) {
150 for (k = 0; k < 2; ++k) {
151 pDstMvPred->iMvArray[i][j][k] = pSrcMvPred->iMvArray[i][j][k];
152 }
153 pDstMvPred->iRefIdxArray[i][j] = pSrcMvPred->iRefIdxArray[i][j];
154 }
155 }
156 }
157
158 #define INIT_MV_DATA \
159 AssignMvInputData (&sAncMvPred); \
160 CopyMvInputData (&sWelsMvPred, &sAncMvPred);
161
162 #define TEST_MV_PRED \
163 AnchorPredMv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iBlockWidth, iRef, sAncMvPred.iMvp); \
164 PredMv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, LIST_0, iIndex, iBlockWidth, iRef, sWelsMvPred.iMvp); \
165 bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1])); \
166 EXPECT_EQ (bOK, true);
167
168
169 //TEST cases followed
170
TEST(PredMvTest,PredMv)171 TEST (PredMvTest, PredMv) {
172 SWelsMvPred sWelsMvPred;
173 SAnchorMvPred sAncMvPred;
174 int32_t i, iRef, iBlockWidth, iIndex;
175 const int32_t kiRandTime = 100;
176 bool bOK = true;
177
178 //test specific input: 16x16
179 iIndex = 0;
180 iBlockWidth = 4;
181 i = 0;
182 while (i++ < kiRandTime) {
183 iRef = (rand() % 18) - 2; //-2~15
184 INIT_MV_DATA;
185 TEST_MV_PRED;
186 }
187 //test specific input: 16x8
188 iBlockWidth = 4;
189 i = 0;
190 while (i++ < kiRandTime) {
191 iIndex = (rand() & 1) << 3; //0,8
192 iRef = (rand() % 18) - 2; //-2~15
193 INIT_MV_DATA;
194 TEST_MV_PRED;
195 }
196 //test specific input: 8x16
197 iBlockWidth = 2;
198 i = 0;
199 while (i++ < kiRandTime) {
200 iIndex = (rand() & 1) << 2; //0,4
201 iRef = (rand() % 18) - 2; //-2~15
202 INIT_MV_DATA;
203 TEST_MV_PRED;
204 }
205 //test specific input: 8x8
206 iBlockWidth = 2;
207 i = 0;
208 while (i++ < kiRandTime) {
209 iIndex = (rand() & 3) << 2; //0,4,8,12
210 iRef = (rand() % 18) - 2; //-2~15
211 INIT_MV_DATA;
212 TEST_MV_PRED;
213 }
214 //test specific input: 4x4
215 iBlockWidth = 1;
216 i = 0;
217 while (i++ < kiRandTime) {
218 iIndex = rand() & 0x0f; //0~15
219 iRef = (rand() % 18) - 2; //-2~15
220 INIT_MV_DATA;
221 TEST_MV_PRED;
222 }
223 } //TEST PredMv
224
225
TEST(PredMvTest,PredInter16x8Mv)226 TEST (PredMvTest, PredInter16x8Mv) {
227 SWelsMvPred sWelsMvPred;
228 SAnchorMvPred sAncMvPred;
229 int32_t i, iRef, iIndex;
230 const int32_t kiRandTime = 100;
231 bool bOK = true;
232
233 i = 0;
234 while (i++ < kiRandTime) {
235 iIndex = (rand() & 1) << 3; //0, 8
236 iRef = (rand() % 18) - 2; //-2~15
237 INIT_MV_DATA;
238 AnchorPredInter16x8Mv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iRef, sAncMvPred.iMvp);
239 PredInter16x8Mv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, LIST_0, iIndex, iRef, sWelsMvPred.iMvp);
240 bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1]));
241 EXPECT_EQ (bOK, true);
242 }
243 } //TEST PredInter16x8Mv
244
TEST(PredMvTest,PredInter8x16Mv)245 TEST (PredMvTest, PredInter8x16Mv) {
246 SWelsMvPred sWelsMvPred;
247 SAnchorMvPred sAncMvPred;
248 int32_t i, iRef, iIndex;
249 const int32_t kiRandTime = 100;
250 bool bOK = true;
251
252 i = 0;
253 while (i++ < kiRandTime) {
254 iIndex = (rand() & 1) << 2; //0, 4
255 iRef = (rand() % 18) - 2; //-2~15
256 INIT_MV_DATA;
257 AnchorPredInter8x16Mv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iRef, sAncMvPred.iMvp);
258 PredInter8x16Mv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, LIST_0, iIndex, iRef, sWelsMvPred.iMvp);
259 bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1]));
260 EXPECT_EQ (bOK, true);
261 }
262 } //TEST PredInter16x8Mv
263
AnchorPredPSkipMvFromNeighbor(PDqLayer pCurLayer,int16_t iMvp[2])264 void AnchorPredPSkipMvFromNeighbor (PDqLayer pCurLayer, int16_t iMvp[2]) {
265 bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail;
266
267 int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc;
268 int32_t iLeftTopType, iRightTopType, iTopType, iLeftType;
269 int32_t iCurX, iCurY, iCurXy, iLeftXy, iTopXy = 0, iLeftTopXy = 0, iRightTopXy = 0;
270
271 int8_t iLeftRef;
272 int8_t iTopRef;
273 int8_t iRightTopRef;
274 int8_t iLeftTopRef;
275 int8_t iDiagonalRef;
276 int8_t iMatchRef;
277 int16_t iMvA[2], iMvB[2], iMvC[2], iMvD[2];
278
279 iCurXy = pCurLayer->iMbXyIndex;
280 iCurX = pCurLayer->iMbX;
281 iCurY = pCurLayer->iMbY;
282 iCurSliceIdc = pCurLayer->pSliceIdc[iCurXy];
283
284 if (iCurX != 0) {
285 iLeftXy = iCurXy - 1;
286 iLeftSliceIdc = pCurLayer->pSliceIdc[iLeftXy];
287 bLeftAvail = (iLeftSliceIdc == iCurSliceIdc);
288 } else {
289 bLeftAvail = 0;
290 bLeftTopAvail = 0;
291 }
292
293 if (iCurY != 0) {
294 iTopXy = iCurXy - pCurLayer->iMbWidth;
295 iTopSliceIdc = pCurLayer->pSliceIdc[iTopXy];
296 bTopAvail = (iTopSliceIdc == iCurSliceIdc);
297 if (iCurX != 0) {
298 iLeftTopXy = iTopXy - 1;
299 iLeftTopSliceIdc = pCurLayer->pSliceIdc[iLeftTopXy];
300 bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc);
301 } else {
302 bLeftTopAvail = 0;
303 }
304 if (iCurX != (pCurLayer->iMbWidth - 1)) {
305 iRightTopXy = iTopXy + 1;
306 iRightTopSliceIdc = pCurLayer->pSliceIdc[iRightTopXy];
307 bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc);
308 } else {
309 bRightTopAvail = 0;
310 }
311 } else {
312 bTopAvail = 0;
313 bLeftTopAvail = 0;
314 bRightTopAvail = 0;
315 }
316
317 iLeftType = ((iCurX != 0 && bLeftAvail) ? pCurLayer->pMbType[iLeftXy] : 0);
318 iTopType = ((iCurY != 0 && bTopAvail) ? pCurLayer->pMbType[iTopXy] : 0);
319 iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail)
320 ? pCurLayer->pMbType[iLeftTopXy] : 0);
321 iRightTopType = ((iCurX != pCurLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail)
322 ? pCurLayer->pMbType[iRightTopXy] : 0);
323
324 /*get neb mv&iRefIdxArray*/
325 /*left*/
326 if (bLeftAvail && IS_INTER (iLeftType)) {
327 ST32 (iMvA, LD32 (pCurLayer->pMv[0][iLeftXy][3]));
328 iLeftRef = pCurLayer->pRefIndex[0][iLeftXy][3];
329 } else {
330 ST32 (iMvA, 0);
331 if (0 == bLeftAvail) { //not available
332 iLeftRef = REF_NOT_AVAIL;
333 } else { //available but is intra mb type
334 iLeftRef = REF_NOT_IN_LIST;
335 }
336 }
337 if (REF_NOT_AVAIL == iLeftRef ||
338 (0 == iLeftRef && 0 == * (int32_t*)iMvA)) {
339 ST32 (iMvp, 0);
340 return;
341 }
342
343 /*top*/
344 if (bTopAvail && IS_INTER (iTopType)) {
345 ST32 (iMvB, LD32 (pCurLayer->pMv[0][iTopXy][12]));
346 iTopRef = pCurLayer->pRefIndex[0][iTopXy][12];
347 } else {
348 ST32 (iMvB, 0);
349 if (0 == bTopAvail) { //not available
350 iTopRef = REF_NOT_AVAIL;
351 } else { //available but is intra mb type
352 iTopRef = REF_NOT_IN_LIST;
353 }
354 }
355 if (REF_NOT_AVAIL == iTopRef ||
356 (0 == iTopRef && 0 == * (int32_t*)iMvB)) {
357 ST32 (iMvp, 0);
358 return;
359 }
360
361 /*right_top*/
362 if (bRightTopAvail && IS_INTER (iRightTopType)) {
363 ST32 (iMvC, LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
364 iRightTopRef = pCurLayer->pRefIndex[0][iRightTopXy][12];
365 } else {
366 ST32 (iMvC, 0);
367 if (0 == bRightTopAvail) { //not available
368 iRightTopRef = REF_NOT_AVAIL;
369 } else { //available but is intra mb type
370 iRightTopRef = REF_NOT_IN_LIST;
371 }
372 }
373
374 /*left_top*/
375 if (bLeftTopAvail && IS_INTER (iLeftTopType)) {
376 ST32 (iMvD, LD32 (pCurLayer->pMv[0][iLeftTopXy][15]));
377 iLeftTopRef = pCurLayer->pRefIndex[0][iLeftTopXy][15];
378 } else {
379 ST32 (iMvD, 0);
380 if (0 == bLeftTopAvail) { //not available
381 iLeftTopRef = REF_NOT_AVAIL;
382 } else { //available but is intra mb type
383 iLeftTopRef = REF_NOT_IN_LIST;
384 }
385 }
386
387 iDiagonalRef = iRightTopRef;
388 if (REF_NOT_AVAIL == iDiagonalRef) {
389 iDiagonalRef = iLeftTopRef;
390 * (int32_t*)iMvC = * (int32_t*)iMvD;
391 }
392
393 if (REF_NOT_AVAIL == iTopRef && REF_NOT_AVAIL == iDiagonalRef && iLeftRef >= REF_NOT_IN_LIST) {
394 ST32 (iMvp, LD32 (iMvA));
395 return;
396 }
397
398 iMatchRef = (0 == iLeftRef) + (0 == iTopRef) + (0 == iDiagonalRef);
399 if (1 == iMatchRef) {
400 if (0 == iLeftRef) {
401 ST32 (iMvp, LD32 (iMvA));
402 } else if (0 == iTopRef) {
403 ST32 (iMvp, LD32 (iMvB));
404 } else {
405 ST32 (iMvp, LD32 (iMvC));
406 }
407 } else {
408 iMvp[0] = WelsMedian (iMvA[0], iMvB[0], iMvC[0]);
409 iMvp[1] = WelsMedian (iMvA[1], iMvB[1], iMvC[1]);
410 }
411 }
412
413
414
AllocLayerData(PDqLayer pDqLayer)415 int32_t AllocLayerData (PDqLayer pDqLayer) {
416
417 pDqLayer->pSliceIdc = (int32_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (int32_t),
418 "pDqLayer->pSliceIdc");
419 if (pDqLayer->pSliceIdc == NULL)
420 return 1;
421
422 pDqLayer->pMbType = (uint32_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (uint32_t),
423 "pDqLayer->pMbType");
424 if (pDqLayer->pMbType == NULL)
425 return 1;
426
427 pDqLayer->pMv[0] = (int16_t (*)[MB_BLOCK4x4_NUM][MV_A]) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (
428 int16_t) * MV_A * MB_BLOCK4x4_NUM, "pDqLayer->pMv");
429 if (pDqLayer->pMv[0] == NULL)
430 return 1;
431
432 pDqLayer->pRefIndex[0] = (int8_t (*)[MB_BLOCK4x4_NUM]) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (
433 int8_t) * MB_BLOCK4x4_NUM, "pDqLayer->pRefIndex");
434 if (pDqLayer->pRefIndex[0] == NULL)
435 return 1;
436
437 return 0;
438 }
439
FreeLayerData(PDqLayer pDqLayer)440 int32_t FreeLayerData (PDqLayer pDqLayer) {
441
442 if (pDqLayer->pSliceIdc != NULL) {
443 WelsFree (pDqLayer->pSliceIdc, "pDqLayer->pSliceIdc");
444 pDqLayer->pSliceIdc = NULL;
445 }
446
447 if (pDqLayer->pMbType != NULL) {
448 WelsFree (pDqLayer->pMbType, "pDqLayer->pMbType");
449 pDqLayer->pMbType = NULL;
450 }
451
452 if (pDqLayer->pMv[0] != NULL) {
453 WelsFree (pDqLayer->pMv[0], "pDqlayer->pMv[0]");
454 pDqLayer->pMv[0] = NULL;
455 }
456
457 if (pDqLayer->pRefIndex[0] != NULL) {
458 WelsFree (pDqLayer->pRefIndex[0], "pDqlayer->pRefIndex[0]");
459 pDqLayer->pRefIndex[0] = NULL;
460 }
461
462 return 0;
463 }
464
InitRandomLayerSliceIdc(PDqLayer pDqLayer)465 void InitRandomLayerSliceIdc (PDqLayer pDqLayer) {
466 int32_t i = 0;
467 int32_t iTotalMbNum = pDqLayer->iMbWidth * pDqLayer->iMbHeight;
468 int32_t iMbFirstSliceEnd = rand() % (iTotalMbNum - 1); //assure 2 slices
469 for (i = 0; i <= iMbFirstSliceEnd; ++i) {
470 pDqLayer->pSliceIdc[i] = 0; //to keep simple value here
471 }
472 for (; i < iTotalMbNum; ++i) {
473 pDqLayer->pSliceIdc[i] = 1; //to keep simple value here
474 }
475 }
476
InitRandomLayerMbType(PDqLayer pDqLayer)477 void InitRandomLayerMbType (PDqLayer pDqLayer) {
478 for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
479 pDqLayer->pMbType[i] = 1 << (rand() % 11); //2^(1 ~ 10)
480 }
481 }
482
InitRandomLayerMvData(PDqLayer pDqLayer)483 void InitRandomLayerMvData (PDqLayer pDqLayer) {
484 for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
485 for (int32_t j = 0; j < MB_BLOCK4x4_NUM; ++j) {
486 for (int32_t k = 0; k < MV_A; ++k) {
487 pDqLayer->pMv[0][i][j][k] = (rand() - RAND_MAX / 2);
488 }
489 }
490 }
491 }
492
InitRandomLayerRefIdxData(PDqLayer pDqLayer)493 void InitRandomLayerRefIdxData (PDqLayer pDqLayer) {
494 for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
495 for (int32_t j = 0; j < MB_BLOCK4x4_NUM; ++j) {
496 pDqLayer->pRefIndex[0][i][j] = (rand() % 18 - 2); //-2 ~ 15
497 }
498 }
499 }
500
InitRandomLayerData(PDqLayer pDqLayer)501 void InitRandomLayerData (PDqLayer pDqLayer) {
502 InitRandomLayerSliceIdc (pDqLayer);
503 InitRandomLayerMbType (pDqLayer);
504 InitRandomLayerMvData (pDqLayer);
505 InitRandomLayerRefIdxData (pDqLayer);
506 }
507
508 #define TEST_SKIP_MV_PRED \
509 PredPSkipMvFromNeighbor (&sDqLayer, iWelsMvp); \
510 bOK = ((iWelsMvp[0] == iAncMvp[0]) && (iWelsMvp[1] == iAncMvp[1])); \
511 EXPECT_EQ (bOK, true);
512
TEST(PredMvTest,PredSkipMvFromNeighbor)513 TEST (PredMvTest, PredSkipMvFromNeighbor) {
514 const int32_t kiRandTime = 100;
515 bool bOK = true;
516 SDqLayer sDqLayer;
517 int16_t iAncMvp[2], iWelsMvp[2];
518 int i;
519
520 memset (&sDqLayer, 0, sizeof (SDqLayer));
521 //Assume the input data as 352x288 size
522 //allocate the data
523 sDqLayer.iMbWidth = 11;
524 sDqLayer.iMbHeight = 9;
525 if (AllocLayerData (&sDqLayer)) { //memory allocate failed
526 FreeLayerData (&sDqLayer);
527 return;
528 }
529 InitRandomLayerData (&sDqLayer); //init MV data, as it would not affect the following logic test
530
531 #define CURR_MB_IDX (sDqLayer.iMbXyIndex)
532 #define LEFT_MB_IDX (sDqLayer.iMbXyIndex - 1)
533 #define LEFT_MB_BLK 3
534 #define TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth)
535 #define TOP_MB_BLK 12
536 #define LEFT_TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth - 1)
537 #define LEFT_TOP_MB_BLK 15
538 #define RIGHT_TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth + 1)
539 #define RIGHT_TOP_MB_BLK 12
540
541 int32_t iTotalMbNum = sDqLayer.iMbHeight * sDqLayer.iMbWidth;
542 //CASE 1: test MB [0,0], expect mvp = (0,0)
543 sDqLayer.iMbX = 0;
544 sDqLayer.iMbY = 0;
545 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
546 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
547 TEST_SKIP_MV_PRED;
548 //CASE 2: test MB [ANY, 0], expect mvp = (0,0)
549 sDqLayer.iMbX = rand() % sDqLayer.iMbWidth;
550 sDqLayer.iMbY = 0;
551 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
552 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
553 TEST_SKIP_MV_PRED;
554 //CASE 3: test MB [0, ANY], expect mvp = (0,0)
555 sDqLayer.iMbX = 0;
556 sDqLayer.iMbY = rand() % sDqLayer.iMbHeight;
557 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
558 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
559 TEST_SKIP_MV_PRED;
560 //CASE 4.1: test MB [RIGHT_SIDE, ANY]
561 sDqLayer.iMbX = sDqLayer.iMbWidth - 1;
562 sDqLayer.iMbY = rand() % (sDqLayer.iMbHeight - 1) + 1; //not equal to 0
563 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
564 //CASE 4.1.1: same slice_idc, assume = 0
565 memset (sDqLayer.pSliceIdc, 0, iTotalMbNum * sizeof (int32_t));
566 //CASE 4.1.1.1: ALL P modes
567 for (i = 0; i < iTotalMbNum; ++i) {
568 sDqLayer.pMbType[i] = MB_TYPE_16x16;
569 }
570 //CASE 4.1.1.1.1: ref_idx = 0, left MV = 0, top MV != 0, expect mvp = (0,0)
571 memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t));
572 InitRandomLayerMvData (&sDqLayer); //reset Mv data
573 sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1] = 0; //left_mv = 0
574 sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][0] = sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][1] = 1; //top_mv != 0
575 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
576 TEST_SKIP_MV_PRED;
577 //CASE 4.1.1.1.2: ref_idx = 0, left MV != 0, top MV = 0, expect mvp = (0,0)
578 memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t));
579 InitRandomLayerMvData (&sDqLayer); //reset Mv data
580 sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1] = 1; //left_mv != 0
581 sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][0] = sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][1] = 0; //top_mv = 0
582 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
583 TEST_SKIP_MV_PRED;
584 //CASE 4.1.1.1.3: ref_idx top = 0, others = 1, expect mvp = top mv
585 InitRandomLayerMvData (&sDqLayer); //reset Mv data
586 sDqLayer.pRefIndex[0][ TOP_MB_IDX][ TOP_MB_BLK] = 0; //top ref_idx = 0
587 sDqLayer.pRefIndex[0][LEFT_MB_IDX][LEFT_MB_BLK] = 1; //left ref_idx = 1
588 sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 1; //left_top ref_idx = 1
589 iAncMvp[0] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][0];
590 iAncMvp[1] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][1];
591 TEST_SKIP_MV_PRED;
592 //CASE 4.1.1.1.4: ref_idx left = 0, others = 1, expect mvp = left mv
593 sDqLayer.pRefIndex[0][ TOP_MB_IDX][ TOP_MB_BLK] = 1; //top ref_idx = 1
594 sDqLayer.pRefIndex[0][LEFT_MB_IDX][LEFT_MB_BLK] = 0; //left ref_idx = 0
595 sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 1; //left_top ref_idx = 1
596 iAncMvp[0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0];
597 iAncMvp[1] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1];
598 TEST_SKIP_MV_PRED;
599 //CASE 4.1.1.2: All I
600 for (i = 0; i < iTotalMbNum; ++i) {
601 sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
602 }
603 //CASE 4.1.1.2.1: left P, expect mvp = left mv
604 sDqLayer.pMbType[LEFT_MB_IDX] = MB_TYPE_16x16; //left P
605 iAncMvp[0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0];
606 iAncMvp[1] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1];
607 TEST_SKIP_MV_PRED;
608 //CASE 4.1.1.3: only top P, top ref_idx = 0, expect mvp = top mv
609 for (i = 0; i < iTotalMbNum; ++i) { // All I MB
610 sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
611 }
612 memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
613 sDqLayer.pMbType[TOP_MB_IDX] = MB_TYPE_16x16; //top P
614 sDqLayer.pRefIndex[0][TOP_MB_IDX][TOP_MB_BLK] = 0; //top ref_idx = 0
615 iAncMvp[0] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][0];
616 iAncMvp[1] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][1];
617 TEST_SKIP_MV_PRED;
618 //CASE 4.1.1.4: only left_top P, left_top ref_idx = 0, expect mvp = 0
619 sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
620 sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
621 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
622 for (i = 0; i < iTotalMbNum; ++i) { // All I MB
623 sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
624 }
625 memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
626 sDqLayer.pMbType[LEFT_TOP_MB_IDX] = MB_TYPE_16x16; //top P
627 sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 0; //top ref_idx = 0
628 iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
629 TEST_SKIP_MV_PRED;
630 //CASE 4.1.1.5: only right_top P, right_top ref_idx = 0, expect mvp = right_top mv
631 sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
632 sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
633 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
634 for (i = 0; i < iTotalMbNum; ++i) { // All I MB
635 sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
636 }
637 memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
638 sDqLayer.pMbType[RIGHT_TOP_MB_IDX] = MB_TYPE_16x16; //top P
639 sDqLayer.pRefIndex[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK] = 0; //top ref_idx = 0
640 iAncMvp[0] = sDqLayer.pMv[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK][0];
641 iAncMvp[1] = sDqLayer.pMv[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK][1];
642 TEST_SKIP_MV_PRED;
643 //CASE 4.1.2: different neighbor slice idc for all P and ref_idx = 0, expect mvp = 0
644 for (i = 0; i < iTotalMbNum; ++i) { // All P MB
645 sDqLayer.pMbType[i] = MB_TYPE_16x16;
646 }
647 memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
648 sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
649 sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
650 sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
651 sDqLayer.pSliceIdc[CURR_MB_IDX] = 5;
652 sDqLayer.pSliceIdc[LEFT_MB_IDX] = 0;
653 sDqLayer.pSliceIdc[TOP_MB_IDX] = 1;
654 sDqLayer.pSliceIdc[LEFT_TOP_MB_IDX] = 2;
655 sDqLayer.pSliceIdc[RIGHT_TOP_MB_IDX] = 3;
656 iAncMvp[0] = iAncMvp[1] = 0;
657 TEST_SKIP_MV_PRED;
658
659 //add new specific tests here
660
661 //normal tests
662 i = 0;
663 while (i++ < kiRandTime) {
664 InitRandomLayerData (&sDqLayer); //init MV data, as it would not affect the following logic test
665 AnchorPredPSkipMvFromNeighbor (&sDqLayer, iAncMvp);
666 TEST_SKIP_MV_PRED;
667 }
668
669 FreeLayerData (&sDqLayer);
670 }
671