openh264/test/decoder/DecUT_PredMv.cpp
2015-03-20 12:44:00 +08:00

671 lines
22 KiB
C++

#include <gtest/gtest.h>
#include "wels_common_basis.h"
#include "memory_align.h"
#include "mv_pred.h"
#include "ls_defines.h"
using namespace WelsDec;
//Anchor functions
#define REF_NOT_AVAIL -2
#define REF_NOT_IN_LIST -1 //intra
//cache element equal to 30
const uint8_t g_kuiAnchorCache30ScanIdx[16] = { //mv or ref_index cache scan index, 4*4 block as basic unit
7, 8, 13, 14,
9, 10, 15, 16,
19, 20, 25, 26,
21, 22, 27, 28
};
typedef struct TagAnchorMvPred {
int16_t iMvArray[2][30][2];
int8_t iRefIdxArray[2][30];
int32_t iPartIdx;
int32_t iPartWidth;
int32_t iRef;
int16_t iMvp[2];
} SAnchorMvPred;
void 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]) {
const uint8_t kuiLeftIdx = g_kuiAnchorCache30ScanIdx[iPartIdx] - 1;
const uint8_t kuiTopIdx = g_kuiAnchorCache30ScanIdx[iPartIdx] - 6;
const uint8_t kuiRightTopIdx = kuiTopIdx + iPartWidth;
const uint8_t kuiLeftTopIdx = kuiTopIdx - 1;
const int8_t kiLeftRef = iRefIndex[0][kuiLeftIdx];
const int8_t kiTopRef = iRefIndex[0][kuiTopIdx];
const int8_t kiRightTopRef = iRefIndex[0][kuiRightTopIdx];
const int8_t kiLeftTopRef = iRefIndex[0][kuiLeftTopIdx];
int8_t iDiagonalRef = kiRightTopRef;
int8_t iMatchRef = 0;
int16_t iAMV[2], iBMV[2], iCMV[2];
* (int32_t*)iAMV = INTD32 (iMotionVector[0][kuiLeftIdx]);
* (int32_t*)iBMV = INTD32 (iMotionVector[0][kuiTopIdx]);
* (int32_t*)iCMV = INTD32 (iMotionVector[0][kuiRightTopIdx]);
if (REF_NOT_AVAIL == iDiagonalRef) {
iDiagonalRef = kiLeftTopRef;
* (int32_t*)iCMV = INTD32 (iMotionVector[0][kuiLeftTopIdx]);
}
iMatchRef = (iRef == kiLeftRef) + (iRef == kiTopRef) + (iRef == iDiagonalRef);
if ((REF_NOT_AVAIL == kiTopRef) && (REF_NOT_AVAIL == iDiagonalRef) && (kiLeftRef >= REF_NOT_IN_LIST)) {
ST32 (iMVP, LD32 (iAMV));
return;
}
if (1 == iMatchRef) {
if (iRef == kiLeftRef) {
ST32 (iMVP, LD32 (iAMV));
} else if (iRef == kiTopRef) {
ST32 (iMVP, LD32 (iBMV));
} else {
ST32 (iMVP, LD32 (iCMV));
}
} else {
iMVP[0] = WelsMedian (iAMV[0], iBMV[0], iCMV[0]);
iMVP[1] = WelsMedian (iAMV[1], iBMV[1], iCMV[1]);
}
}
void 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]) {
if (0 == iPartIdx) {
const int8_t kiLeftRef = iRefIndex[0][6];
if (iRef == kiLeftRef) {
ST32 (iMVP, LD32 (&iMotionVector[0][6][0]));
return;
}
} else { // 4 == iPartIdx
int8_t iDiagonalRef = iRefIndex[0][5]; //top-right
int8_t index = 5;
if (REF_NOT_AVAIL == iDiagonalRef) {
iDiagonalRef = iRefIndex[0][2]; //top-left for 8*8 block(index 1)
index = 2;
}
if (iRef == iDiagonalRef) {
ST32 (iMVP, LD32 (&iMotionVector[0][index][0]));
return;
}
}
AnchorPredMv (iMotionVector, iRefIndex, iPartIdx, 2, iRef, iMVP);
}
void 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]) {
if (0 == iPartIdx) {
const int8_t kiTopRef = iRefIndex[0][1];
if (iRef == kiTopRef) {
ST32 (iMVP, LD32 (&iMotionVector[0][1][0]));
return;
}
} else { // 8 == iPartIdx
const int8_t kiLeftRef = iRefIndex[0][18];
if (iRef == kiLeftRef) {
ST32 (iMVP, LD32 (&iMotionVector[0][18][0]));
return;
}
}
AnchorPredMv (iMotionVector, iRefIndex, iPartIdx, 4, iRef, iMVP);
}
//Ref functions in WelsDec
//Input structure for test
typedef struct TagWelsMvPred {
int16_t iMvArray[2][30][2];
int8_t iRefIdxArray[2][30];
int32_t iPartIdx;
int32_t iPartWidth;
int32_t iRef;
int16_t iMvp[2];
} SWelsMvPred;
//mok input data
void AssignMvInputData (SAnchorMvPred* pAncMvPred) {
int32_t i, j, k;
//fill MV data and refIdx
for (i = 0; i < 2; ++i) {
for (j = 0; j < 30; ++j) {
for (k = 0; k < 2; ++k) {
pAncMvPred->iMvArray[i][j][k] = (rand() - RAND_MAX / 2);
}
pAncMvPred->iRefIdxArray[i][j] = (rand() % 18) - 2; //-2 ~ 15. 8x8 may have different values, but it matters nothing
}
}
}
void CopyMvInputData (SWelsMvPred* pDstMvPred, SAnchorMvPred* pSrcMvPred) {
int32_t i, j, k;
//fill MV data and refIdx
for (i = 0; i < 2; ++i) {
for (j = 0; j < 30; ++j) {
for (k = 0; k < 2; ++k) {
pDstMvPred->iMvArray[i][j][k] = pSrcMvPred->iMvArray[i][j][k];
}
pDstMvPred->iRefIdxArray[i][j] = pSrcMvPred->iRefIdxArray[i][j];
}
}
}
#define INIT_MV_DATA \
AssignMvInputData (&sAncMvPred); \
CopyMvInputData (&sWelsMvPred, &sAncMvPred);
#define TEST_MV_PRED \
AnchorPredMv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iBlockWidth, iRef, sAncMvPred.iMvp); \
PredMv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, iIndex, iBlockWidth, iRef, sWelsMvPred.iMvp); \
bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1])); \
EXPECT_EQ (bOK, true);
//TEST cases followed
TEST (PredMvTest, PredMv) {
SWelsMvPred sWelsMvPred;
SAnchorMvPred sAncMvPred;
int32_t i, iRef, iBlockWidth, iIndex;
const int32_t kiRandTime = 100;
bool bOK = true;
//test specific input: 16x16
iIndex = 0;
iBlockWidth = 4;
i = 0;
while (i++ < kiRandTime) {
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
TEST_MV_PRED;
}
//test specific input: 16x8
iBlockWidth = 4;
i = 0;
while (i++ < kiRandTime) {
iIndex = (rand() & 1) << 3; //0,8
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
TEST_MV_PRED;
}
//test specific input: 8x16
iBlockWidth = 2;
i = 0;
while (i++ < kiRandTime) {
iIndex = (rand() & 1) << 2; //0,4
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
TEST_MV_PRED;
}
//test specific input: 8x8
iBlockWidth = 2;
i = 0;
while (i++ < kiRandTime) {
iIndex = (rand() & 3) << 2; //0,4,8,12
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
TEST_MV_PRED;
}
//test specific input: 4x4
iBlockWidth = 1;
i = 0;
while (i++ < kiRandTime) {
iIndex = rand() & 0x0f; //0~15
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
TEST_MV_PRED;
}
} //TEST PredMv
TEST (PredMvTest, PredInter16x8Mv) {
SWelsMvPred sWelsMvPred;
SAnchorMvPred sAncMvPred;
int32_t i, iRef, iIndex;
const int32_t kiRandTime = 100;
bool bOK = true;
i = 0;
while (i++ < kiRandTime) {
iIndex = (rand() & 1) << 3; //0, 8
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
AnchorPredInter16x8Mv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iRef, sAncMvPred.iMvp);
PredInter16x8Mv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, iIndex, iRef, sWelsMvPred.iMvp);
bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1]));
EXPECT_EQ (bOK, true);
}
} //TEST PredInter16x8Mv
TEST (PredMvTest, PredInter8x16Mv) {
SWelsMvPred sWelsMvPred;
SAnchorMvPred sAncMvPred;
int32_t i, iRef, iIndex;
const int32_t kiRandTime = 100;
bool bOK = true;
i = 0;
while (i++ < kiRandTime) {
iIndex = (rand() & 1) << 2; //0, 4
iRef = (rand() % 18) - 2; //-2~15
INIT_MV_DATA;
AnchorPredInter8x16Mv (sAncMvPred.iMvArray, sAncMvPred.iRefIdxArray, iIndex, iRef, sAncMvPred.iMvp);
PredInter8x16Mv (sWelsMvPred.iMvArray, sWelsMvPred.iRefIdxArray, iIndex, iRef, sWelsMvPred.iMvp);
bOK = ((sAncMvPred.iMvp[0] == sWelsMvPred.iMvp[0]) && (sAncMvPred.iMvp[1] == sWelsMvPred.iMvp[1]));
EXPECT_EQ (bOK, true);
}
} //TEST PredInter16x8Mv
void AnchorPredPSkipMvFromNeighbor (PDqLayer pCurLayer, int16_t iMvp[2]) {
bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail;
int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc;
int32_t iLeftTopType, iRightTopType, iTopType, iLeftType;
int32_t iCurX, iCurY, iCurXy, iLeftXy, iTopXy, iLeftTopXy, iRightTopXy = 0;
int8_t iLeftRef;
int8_t iTopRef;
int8_t iRightTopRef;
int8_t iLeftTopRef;
int8_t iDiagonalRef;
int8_t iMatchRef;
int16_t iMvA[2], iMvB[2], iMvC[2], iMvD[2];
iCurXy = pCurLayer->iMbXyIndex;
iCurX = pCurLayer->iMbX;
iCurY = pCurLayer->iMbY;
iCurSliceIdc = pCurLayer->pSliceIdc[iCurXy];
if (iCurX != 0) {
iLeftXy = iCurXy - 1;
iLeftSliceIdc = pCurLayer->pSliceIdc[iLeftXy];
bLeftAvail = (iLeftSliceIdc == iCurSliceIdc);
} else {
bLeftAvail = 0;
bLeftTopAvail = 0;
}
if (iCurY != 0) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
iTopSliceIdc = pCurLayer->pSliceIdc[iTopXy];
bTopAvail = (iTopSliceIdc == iCurSliceIdc);
if (iCurX != 0) {
iLeftTopXy = iTopXy - 1;
iLeftTopSliceIdc = pCurLayer->pSliceIdc[iLeftTopXy];
bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc);
} else {
bLeftTopAvail = 0;
}
if (iCurX != (pCurLayer->iMbWidth - 1)) {
iRightTopXy = iTopXy + 1;
iRightTopSliceIdc = pCurLayer->pSliceIdc[iRightTopXy];
bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc);
} else {
bRightTopAvail = 0;
}
} else {
bTopAvail = 0;
bLeftTopAvail = 0;
bRightTopAvail = 0;
}
iLeftType = ((iCurX != 0 && bLeftAvail) ? pCurLayer->pMbType[iLeftXy] : 0);
iTopType = ((iCurY != 0 && bTopAvail) ? pCurLayer->pMbType[iTopXy] : 0);
iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail)
? pCurLayer->pMbType[iLeftTopXy] : 0);
iRightTopType = ((iCurX != pCurLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail)
? pCurLayer->pMbType[iRightTopXy] : 0);
/*get neb mv&iRefIdxArray*/
/*left*/
if (bLeftAvail && IS_INTER (iLeftType)) {
ST32 (iMvA, LD32 (pCurLayer->pMv[0][iLeftXy][3]));
iLeftRef = pCurLayer->pRefIndex[0][iLeftXy][3];
} else {
ST32 (iMvA, 0);
if (0 == bLeftAvail) { //not available
iLeftRef = REF_NOT_AVAIL;
} else { //available but is intra mb type
iLeftRef = REF_NOT_IN_LIST;
}
}
if (REF_NOT_AVAIL == iLeftRef ||
(0 == iLeftRef && 0 == * (int32_t*)iMvA)) {
ST32 (iMvp, 0);
return;
}
/*top*/
if (bTopAvail && IS_INTER (iTopType)) {
ST32 (iMvB, LD32 (pCurLayer->pMv[0][iTopXy][12]));
iTopRef = pCurLayer->pRefIndex[0][iTopXy][12];
} else {
ST32 (iMvB, 0);
if (0 == bTopAvail) { //not available
iTopRef = REF_NOT_AVAIL;
} else { //available but is intra mb type
iTopRef = REF_NOT_IN_LIST;
}
}
if (REF_NOT_AVAIL == iTopRef ||
(0 == iTopRef && 0 == * (int32_t*)iMvB)) {
ST32 (iMvp, 0);
return;
}
/*right_top*/
if (bRightTopAvail && IS_INTER (iRightTopType)) {
ST32 (iMvC, LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
iRightTopRef = pCurLayer->pRefIndex[0][iRightTopXy][12];
} else {
ST32 (iMvC, 0);
if (0 == bRightTopAvail) { //not available
iRightTopRef = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRightTopRef = REF_NOT_IN_LIST;
}
}
/*left_top*/
if (bLeftTopAvail && IS_INTER (iLeftTopType)) {
ST32 (iMvD, LD32 (pCurLayer->pMv[0][iLeftTopXy][15]));
iLeftTopRef = pCurLayer->pRefIndex[0][iLeftTopXy][15];
} else {
ST32 (iMvD, 0);
if (0 == bLeftTopAvail) { //not available
iLeftTopRef = REF_NOT_AVAIL;
} else { //available but is intra mb type
iLeftTopRef = REF_NOT_IN_LIST;
}
}
iDiagonalRef = iRightTopRef;
if (REF_NOT_AVAIL == iDiagonalRef) {
iDiagonalRef = iLeftTopRef;
* (int32_t*)iMvC = * (int32_t*)iMvD;
}
if (REF_NOT_AVAIL == iTopRef && REF_NOT_AVAIL == iDiagonalRef && iLeftRef >= REF_NOT_IN_LIST) {
ST32 (iMvp, LD32 (iMvA));
return;
}
iMatchRef = (0 == iLeftRef) + (0 == iTopRef) + (0 == iDiagonalRef);
if (1 == iMatchRef) {
if (0 == iLeftRef) {
ST32 (iMvp, LD32 (iMvA));
} else if (0 == iTopRef) {
ST32 (iMvp, LD32 (iMvB));
} else {
ST32 (iMvp, LD32 (iMvC));
}
} else {
iMvp[0] = WelsMedian (iMvA[0], iMvB[0], iMvC[0]);
iMvp[1] = WelsMedian (iMvA[1], iMvB[1], iMvC[1]);
}
}
int32_t AllocLayerData (PDqLayer pDqLayer) {
pDqLayer->pSliceIdc = (int32_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (int32_t),
"pDqLayer->pSliceIdc");
if (pDqLayer->pSliceIdc == NULL)
return 1;
pDqLayer->pMbType = (int16_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (int16_t),
"pDqLayer->pMbType");
if (pDqLayer->pMbType == NULL)
return 1;
pDqLayer->pMv[0] = (int16_t (*)[MB_BLOCK4x4_NUM][MV_A]) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (
int16_t) * MV_A * MB_BLOCK4x4_NUM, "pDqLayer->pMv");
if (pDqLayer->pMv[0] == NULL)
return 1;
pDqLayer->pRefIndex[0] = (int8_t (*)[MB_BLOCK4x4_NUM]) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (
int8_t) * MB_BLOCK4x4_NUM, "pDqLayer->pRefIndex");
if (pDqLayer->pRefIndex[0] == NULL)
return 1;
return 0;
}
int32_t FreeLayerData (PDqLayer pDqLayer) {
if (pDqLayer->pSliceIdc != NULL) {
WelsFree (pDqLayer->pSliceIdc, "pDqLayer->pSliceIdc");
pDqLayer->pSliceIdc = NULL;
}
if (pDqLayer->pMbType != NULL) {
WelsFree (pDqLayer->pMbType, "pDqLayer->pMbType");
pDqLayer->pMbType = NULL;
}
if (pDqLayer->pMv[0] != NULL) {
WelsFree (pDqLayer->pMv[0], "pDqlayer->pMv[0]");
pDqLayer->pMv[0] = NULL;
}
if (pDqLayer->pRefIndex[0] != NULL) {
WelsFree (pDqLayer->pRefIndex[0], "pDqlayer->pRefIndex[0]");
pDqLayer->pRefIndex[0] = NULL;
}
return 0;
}
void InitRandomLayerSliceIdc (PDqLayer pDqLayer) {
int32_t i = 0;
int32_t iTotalMbNum = pDqLayer->iMbWidth * pDqLayer->iMbHeight;
int32_t iMbFirstSliceEnd = rand() % (iTotalMbNum - 1); //assure 2 slices
for (i = 0; i <= iMbFirstSliceEnd; ++i) {
pDqLayer->pSliceIdc[i] = 0; //to keep simple value here
}
for (; i < iTotalMbNum; ++i) {
pDqLayer->pSliceIdc[i] = 1; //to keep simple value here
}
}
void InitRandomLayerMbType (PDqLayer pDqLayer) {
for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
pDqLayer->pMbType[i] = 1 << (rand() % 11); //2^(1 ~ 10)
}
}
void InitRandomLayerMvData (PDqLayer pDqLayer) {
for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
for (int32_t j = 0; j < MB_BLOCK4x4_NUM; ++j) {
for (int32_t k = 0; k < MV_A; ++k) {
pDqLayer->pMv[0][i][j][k] = (rand() - RAND_MAX / 2);
}
}
}
}
void InitRandomLayerRefIdxData (PDqLayer pDqLayer) {
for (int32_t i = 0; i < pDqLayer->iMbWidth * pDqLayer->iMbHeight; ++i) {
for (int32_t j = 0; j < MB_BLOCK4x4_NUM; ++j) {
pDqLayer->pRefIndex[0][i][j] = (rand() % 18 - 2); //-2 ~ 15
}
}
}
void InitRandomLayerData (PDqLayer pDqLayer) {
InitRandomLayerSliceIdc (pDqLayer);
InitRandomLayerMbType (pDqLayer);
InitRandomLayerMvData (pDqLayer);
InitRandomLayerRefIdxData (pDqLayer);
}
#define TEST_SKIP_MV_PRED \
PredPSkipMvFromNeighbor (&sDqLayer, iWelsMvp); \
bOK = ((iWelsMvp[0] == iAncMvp[0]) && (iWelsMvp[1] == iAncMvp[1])); \
EXPECT_EQ (bOK, true);
TEST (PredMvTest, PredSkipMvFromNeighbor) {
const int32_t kiRandTime = 100;
bool bOK = true;
SDqLayer sDqLayer;
int16_t iAncMvp[2], iWelsMvp[2];
int i;
memset (&sDqLayer, 0, sizeof (SDqLayer));
//Assume the input data as 352x288 size
//allocate the data
sDqLayer.iMbWidth = 11;
sDqLayer.iMbHeight = 9;
if (AllocLayerData (&sDqLayer)) { //memory allocate failed
FreeLayerData (&sDqLayer);
return;
}
InitRandomLayerData (&sDqLayer); //init MV data, as it would not affect the following logic test
#define CURR_MB_IDX (sDqLayer.iMbXyIndex)
#define LEFT_MB_IDX (sDqLayer.iMbXyIndex - 1)
#define LEFT_MB_BLK 3
#define TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth)
#define TOP_MB_BLK 12
#define LEFT_TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth - 1)
#define LEFT_TOP_MB_BLK 15
#define RIGHT_TOP_MB_IDX (sDqLayer.iMbXyIndex - sDqLayer.iMbWidth + 1)
#define RIGHT_TOP_MB_BLK 12
int32_t iTotalMbNum = sDqLayer.iMbHeight * sDqLayer.iMbWidth;
//CASE 1: test MB [0,0], expect mvp = (0,0)
sDqLayer.iMbX = 0;
sDqLayer.iMbY = 0;
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 2: test MB [ANY, 0], expect mvp = (0,0)
sDqLayer.iMbX = rand() % sDqLayer.iMbWidth;
sDqLayer.iMbY = 0;
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 3: test MB [0, ANY], expect mvp = (0,0)
sDqLayer.iMbX = 0;
sDqLayer.iMbY = rand() % sDqLayer.iMbHeight;
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 4.1: test MB [RIGHT_SIDE, ANY]
sDqLayer.iMbX = sDqLayer.iMbWidth - 1;
sDqLayer.iMbY = rand() % (sDqLayer.iMbHeight - 1) + 1; //not equal to 0
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
//CASE 4.1.1: same slice_idc, assume = 0
memset (sDqLayer.pSliceIdc, 0, iTotalMbNum * sizeof (int32_t));
//CASE 4.1.1.1: ALL P modes
for (i = 0; i < iTotalMbNum; ++i) {
sDqLayer.pMbType[i] = MB_TYPE_16x16;
}
//CASE 4.1.1.1.1: ref_idx = 0, left MV = 0, top MV != 0, expect mvp = (0,0)
memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t));
InitRandomLayerMvData (&sDqLayer); //reset Mv data
sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1] = 0; //left_mv = 0
sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][0] = sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][1] = 1; //top_mv != 0
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 4.1.1.1.2: ref_idx = 0, left MV != 0, top MV = 0, expect mvp = (0,0)
memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t));
InitRandomLayerMvData (&sDqLayer); //reset Mv data
sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1] = 1; //left_mv != 0
sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][0] = sDqLayer.pMv[0][ TOP_MB_IDX][ TOP_MB_BLK][1] = 0; //top_mv = 0
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 4.1.1.1.3: ref_idx top = 0, others = 1, expect mvp = top mv
InitRandomLayerMvData (&sDqLayer); //reset Mv data
sDqLayer.pRefIndex[0][ TOP_MB_IDX][ TOP_MB_BLK] = 0; //top ref_idx = 0
sDqLayer.pRefIndex[0][LEFT_MB_IDX][LEFT_MB_BLK] = 1; //left ref_idx = 1
sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 1; //left_top ref_idx = 1
iAncMvp[0] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][0];
iAncMvp[1] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][1];
TEST_SKIP_MV_PRED;
//CASE 4.1.1.1.4: ref_idx left = 0, others = 1, expect mvp = left mv
sDqLayer.pRefIndex[0][ TOP_MB_IDX][ TOP_MB_BLK] = 1; //top ref_idx = 1
sDqLayer.pRefIndex[0][LEFT_MB_IDX][LEFT_MB_BLK] = 0; //left ref_idx = 0
sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 1; //left_top ref_idx = 1
iAncMvp[0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0];
iAncMvp[1] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1];
TEST_SKIP_MV_PRED;
//CASE 4.1.1.2: All I
for (i = 0; i < iTotalMbNum; ++i) {
sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
}
//CASE 4.1.1.2.1: left P, expect mvp = left mv
sDqLayer.pMbType[LEFT_MB_IDX] = MB_TYPE_16x16; //left P
iAncMvp[0] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][0];
iAncMvp[1] = sDqLayer.pMv[0][LEFT_MB_IDX][LEFT_MB_BLK][1];
TEST_SKIP_MV_PRED;
//CASE 4.1.1.3: only top P, top ref_idx = 0, expect mvp = top mv
for (i = 0; i < iTotalMbNum; ++i) { // All I MB
sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
}
memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
sDqLayer.pMbType[TOP_MB_IDX] = MB_TYPE_16x16; //top P
sDqLayer.pRefIndex[0][TOP_MB_IDX][TOP_MB_BLK] = 0; //top ref_idx = 0
iAncMvp[0] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][0];
iAncMvp[1] = sDqLayer.pMv[0][TOP_MB_IDX][TOP_MB_BLK][1];
TEST_SKIP_MV_PRED;
//CASE 4.1.1.4: only left_top P, left_top ref_idx = 0, expect mvp = 0
sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
for (i = 0; i < iTotalMbNum; ++i) { // All I MB
sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
}
memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
sDqLayer.pMbType[LEFT_TOP_MB_IDX] = MB_TYPE_16x16; //top P
sDqLayer.pRefIndex[0][LEFT_TOP_MB_IDX][LEFT_TOP_MB_BLK] = 0; //top ref_idx = 0
iAncMvp[0] = iAncMvp[1] = 0; //expect anchor result to 0
TEST_SKIP_MV_PRED;
//CASE 4.1.1.5: only right_top P, right_top ref_idx = 0, expect mvp = right_top mv
sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
for (i = 0; i < iTotalMbNum; ++i) { // All I MB
sDqLayer.pMbType[i] = MB_TYPE_INTRA16x16;
}
memset (sDqLayer.pRefIndex[0], 1, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
sDqLayer.pMbType[RIGHT_TOP_MB_IDX] = MB_TYPE_16x16; //top P
sDqLayer.pRefIndex[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK] = 0; //top ref_idx = 0
iAncMvp[0] = sDqLayer.pMv[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK][0];
iAncMvp[1] = sDqLayer.pMv[0][RIGHT_TOP_MB_IDX][RIGHT_TOP_MB_BLK][1];
TEST_SKIP_MV_PRED;
//CASE 4.1.2: different neighbor slice idc for all P and ref_idx = 0, expect mvp = 0
for (i = 0; i < iTotalMbNum; ++i) { // All P MB
sDqLayer.pMbType[i] = MB_TYPE_16x16;
}
memset (sDqLayer.pRefIndex[0], 0, iTotalMbNum * MB_BLOCK4x4_NUM * sizeof (int8_t)); // All ref_idx = 1
sDqLayer.iMbX = (rand() % (sDqLayer.iMbWidth - 2)) + 1; //1 ~ (mb_width - 2)
sDqLayer.iMbY = (rand() % (sDqLayer.iMbHeight - 2)) + 1; //1 ~ (mb_height - 2)
sDqLayer.iMbXyIndex = sDqLayer.iMbY * sDqLayer.iMbWidth + sDqLayer.iMbX;
sDqLayer.pSliceIdc[CURR_MB_IDX] = 5;
sDqLayer.pSliceIdc[LEFT_MB_IDX] = 0;
sDqLayer.pSliceIdc[TOP_MB_IDX] = 1;
sDqLayer.pSliceIdc[LEFT_TOP_MB_IDX] = 2;
sDqLayer.pSliceIdc[RIGHT_TOP_MB_IDX] = 3;
iAncMvp[0] = iAncMvp[1] = 0;
TEST_SKIP_MV_PRED;
//add new specific tests here
//normal tests
i = 0;
while (i++ < kiRandTime) {
InitRandomLayerData (&sDqLayer); //init MV data, as it would not affect the following logic test
AnchorPredPSkipMvFromNeighbor (&sDqLayer, iAncMvp);
TEST_SKIP_MV_PRED;
}
FreeLayerData (&sDqLayer);
}