#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 30const 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 testtypedef 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 datavoid 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, LIST_0, 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, LIST_0, 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, LIST_0, 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 = 0, iLeftTopXy = 0, 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 = (uint32_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (uint32_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 } }} Lines 1–500 of 670. Load more
#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, LIST_0, 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, LIST_0, 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, LIST_0, 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 = 0, iLeftTopXy = 0, 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 = (uint32_t*) WelsMallocz (pDqLayer->iMbWidth * pDqLayer->iMbHeight * sizeof (uint32_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 } } }