671 lines
22 KiB
C++
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);
|
|
}
|