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