EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Ver == &DeblockLumaLt4V_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Ver == &DeblockLumaEq4V_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Hor == &DeblockLumaLt4H_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Hor == &DeblockLumaEq4H_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Ver == &DeblockChromaLt4V_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Ver == &DeblockChromaEq4V_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Hor == &DeblockChromaLt4H_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Hor == &DeblockChromaEq4H_##idx); #ifndef X86_ASM // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c)#endif #ifdef X86_ASM // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // SSE3 DeblockingInit (&sDBFunc, 0x00000200); DB_FUNC_CPUFLAG (ssse3)#endif #ifdef HAVE_NEON // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // NEON DeblockingInit (&sDBFunc, 0x000004); DB_FUNC_CPUFLAG (neon)#endif #ifdef HAVE_NEON_AARCH64 // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // NEON_AARCH64 DeblockingInit (&sDBFunc, 0x000004); DB_FUNC_CPUFLAG (AArch64_neon)#endif} TEST (DecoderDeblocking, WelsDeblockingFilterSlice) { // void WelsDeblockingFilterSlice (PWelsDecoderContext pCtx, PDeblockingFilterMbFunc pDeblockMb) /* NOT support FMO now */ SWelsDecoderContext sCtx; SDqLayer sDqLayer; SSps sSPS; SPps sPPS; SPicture sDec; PDeblockingFilterMbFunc pDeblockMb = &UT_DeblockingFuncInterface; /* NOT do actual deblocking process, set related parameters to null */ sCtx.pDec = &sDec; sCtx.pDec->iLinesize[0] = sCtx.pDec->iLinesize[1] = sCtx.pDec->iLinesize[2] = 0; sCtx.pDec->pData[0] = sCtx.pDec->pData[1] = sCtx.pDec->pData[2] = NULL; /* As no FMO in encoder now, the multi slicegroups has not been set */ sCtx.pFmo = NULL; sCtx.pCurDqLayer = &sDqLayer; /* As void return, using iMbXyIndex to reflect whether the all MBs have been passed. */ sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 0; // whether disable Deblocking Filter Idc sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceAlphaC0Offset = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceBetaOffset = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps = &sSPS; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps = &sPPS; /* Only test one slicegroup, not reflect the FMO func */ sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps->uiNumSliceGroups = 1; // (1) Normal case, the iTotalMbInCurSlice == pSps->uiTotalMbCount sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; // at least one MB sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice) << sDqLayer.iMbXyIndex << " " << sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; // (2) Normal case, multi slices, iTotalMbInCurSlice <= pSps->uiTotalMbCount sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice + rand() % 256; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice); // (3) Special case, iTotalMbInCurSlice >= pSps->uiTotalMbCount, JUST FOR TEST sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount + rand() % 256; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((uint32_t) (sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount); // (4) Special case, uiDisableDeblockingFilterIdc==1, disable deblocking sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 1; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE (sDqLayer.iMbXyIndex == 0) << sDqLayer.iMbXyIndex << " " << sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; } TEST (DecoderDeblocking, FilteringEdgeChromaHV) { // void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) SDqLayer sDqLayer; SDeblockingFilter sFilter; int32_t iBoundryFlag = 0x01; int32_t iQP; memset (&sDqLayer, 0, sizeof (SDqLayer)); memset (&sFilter, 0, sizeof (SDeblockingFilter)); SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func; int8_t iChromaQP[9]; sDqLayer.pChromaQp = iChromaQP; uint8_t iCb[9] = {0}; uint8_t iCr[9] = {0}; sFilter.pCsData[1] = iCb; sFilter.pCsData[2] = iCr; sFilter.iCsStride[0] = sFilter.iCsStride[1] = 2; sDqLayer.iMbX = 0; sDqLayer.iMbY = 0; //Only for test easy sDqLayer.iMbXyIndex = 1; // this function has NO iMbXyIndex validation #define UT_DB_CHROMA_TEST(iFlag, iQP, iV0, iV1, iV2) \ iBoundryFlag = iFlag; \ memset(iChromaQP, iQP, sizeof(int8_t)*9); \ memset(iCb, 0, sizeof(uint8_t)*9); \ memset(iCr, 0, sizeof(uint8_t)*9); \ FilteringEdgeChromaHV(&sDqLayer, &sFilter, iBoundryFlag); \ EXPECT_TRUE(iCb[0]==iV0 && iCr[0]==iV0); \ EXPECT_TRUE(iCb[2<<1]==iV1 && iCr[2<<1]==iV1); \ EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iV2); // QP<=15, iAlpha == iBeta == 0, TOP & LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x03, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x03, iQP, 2, 1, 1) // QP<=15, iAlpha == iBeta == 0, TOP | LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x01, iQP, 0, 0, 0) iQP = rand() % 16; UT_DB_CHROMA_TEST (0x02, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x01, iQP, 1, 1, 1) iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x02, iQP, 1, 1, 1) // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x00, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x00, iQP, 0, 1, 1)} TEST (DecoderDeblocking, FilteringEdgeLumaHV) { // void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) SDqLayer sDqLayer; SDeblockingFilter sFilter; int32_t iBoundryFlag = 0x03; int32_t iQP; memset (&sDqLayer, 0, sizeof (SDqLayer)); memset (&sFilter, 0, sizeof (SDeblockingFilter)); SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func; int8_t iLumaQP[50]; sDqLayer.pLumaQp = iLumaQP; uint8_t iY[50] = {0}; sFilter.pCsData[0] = iY; sFilter.iCsStride[0] = sFilter.iCsStride[1] = 4; sDqLayer.iMbX = 0; sDqLayer.iMbY = 0; //Only for test easy sDqLayer.iMbXyIndex = 1; // this function has NO iMbXyIndex validation #define UT_DB_LUMA_TEST(iFlag, iQP, iV0, iV1, iV2) \ iBoundryFlag = iFlag; \ memset(iLumaQP, iQP, sizeof(int8_t)*50); \ memset(iY, 0, sizeof(uint8_t)*50); \ FilteringEdgeLumaHV(&sDqLayer, &sFilter, iBoundryFlag); \ EXPECT_TRUE(iY[0]==iV0); \ EXPECT_TRUE(iY[1<<2]==iV1 && iY[2<<2]==iV1 && iY[3<<2]==iV1); \ EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iV2); // QP<=15, iAlpha == iBeta == 0, TOP & LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x03, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x03, iQP, 2, 1, 1) // QP<=15, iAlpha == iBeta == 0, TOP | LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x01, iQP, 0, 0, 0) iQP = rand() % 16; UT_DB_LUMA_TEST (0x02, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x01, iQP, 1, 1, 1) iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x02, iQP, 1, 1, 1) // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x00, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x00, iQP, 0, 1, 1)} /////////// Bs calculation functionsTEST (DecoderDeblocking, DeblockingBsMarginalMBAvcbase) { // uint32_t DeblockingBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) /* Calculate the Bs equal to 2 or 1 */ SDqLayer sDqLayer; // Only define 2 MBs here int8_t iNoZeroCount[24 * 2]; // (*pNzc)[24] int8_t iLayerRefIndex[2][16 * 2]; // (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM]; int16_t iLayerMv[2][16 * 2][2]; //(*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A]; sDqLayer.pNzc = (int8_t (*)[24])iNoZeroCount; sDqLayer.pRefIndex[0] = (int8_t (*)[16])&iLayerRefIndex[0]; sDqLayer.pRefIndex[1] = (int8_t (*)[16])&iLayerRefIndex[1]; sDqLayer.pMv[0] = (int16_t (*) [16][2])&iLayerMv[0]; sDqLayer.pMv[1] = (int16_t (*) [16][2])&iLayerMv[1]; #define UT_DB_CLEAN_STATUS \ memset(iNoZeroCount, 0, sizeof(int8_t)*24*2); \ memset(iLayerRefIndex, 0, sizeof(int8_t)*2*16*2); \ memset(iLayerMv, 0, sizeof(int16_t)*2*16*2*2); int32_t iCurrBlock, iNeighborBlock; /* Cycle for each block and its neighboring block */ for (int iEdge = 0; iEdge < 2; iEdge++) { // Vertical and Horizontal for (int iPos = 0; iPos < 4; iPos++) { // Four different blocks on the edge iCurrBlock = (iEdge == 0 ? 4 * iPos : iPos); iNeighborBlock = (iEdge == 0 ? (3 + iPos * 4) : (12 + iPos)); // (1) iEdge == 0, current block NoZeroCount != 0 UT_DB_CLEAN_STATUS iNoZeroCount[0 * 24 + iCurrBlock] = 1; // Current MB_block position EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (2u << (iPos * 8))) << iEdge << " " << iPos << " NoZeroCount!=0"; // (2) iEdge == 0, neighbor block NoZeroCount != 0 UT_DB_CLEAN_STATUS iNoZeroCount[1 * 24 + iNeighborBlock ] = 1; // Neighbor MB_block position EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (2u << (iPos * 8))) << iEdge << " " << iPos << " NoZeroCount!=0"; // (3) iEdge == 0, reference idx diff UT_DB_CLEAN_STATUS iLayerRefIndex[0][0 * 16 + iCurrBlock] = 0; iLayerRefIndex[0][1 * 16 + iNeighborBlock] = 1; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " Ref idx diff"; // (4) iEdge == 0, abs(mv diff) < 4 UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][0] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][1] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; // (5) iEdge == 0, abs(mv diff) > 4 UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][0] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][1] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = -2048; iLayerMv[0][1 * 16 + iNeighborBlock][0] = 2047; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == maximum"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = -2048; iLayerMv[0][1 * 16 + iNeighborBlock][1] = 2047; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == maximum"; } }} TEST (Deblocking, WelsDeblockingMb) { // void WelsDeblockingMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) /* Deblock one MB, calculate the Bs inside the function, only consider the intra / intra block */ SDqLayer sDqLayer; SDeblockingFilter sFilter; SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func; sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 1; sDqLayer.iMbWidth = 1; uint8_t iY[50] = {0}; sFilter.pCsData[0] = iY; sFilter.iCsStride[0] = 4; uint8_t iCb[9] = {0}; uint8_t iCr[9] = {0}; sFilter.pCsData[1] = iCb; sFilter.pCsData[2] = iCr; sFilter.iCsStride[1] = 2; int8_t iLumaQP[50] = {0}; int8_t iChromaQP[9] = {0}; sDqLayer.pLumaQp = iLumaQP; sDqLayer.pChromaQp = iChromaQP; int8_t iMbType[2]; sDqLayer.pMbType = iMbType; sDqLayer.pMbType[0] = 0x01; sDqLayer.pMbType[1] = 0x01; sFilter.iSliceAlphaC0Offset = 0; sFilter.iSliceBetaOffset = 0; int32_t iQP; #define UT_DB_MACROBLOCK_TEST( iBoundFlag, iQP, iLumaV0, iLumaV1, iLumaV2, iChromaV0, iChromaV1, iChromaV2 ) \ memset(sDqLayer.pLumaQp, iQP, sizeof(int8_t)*50); \ memset(sDqLayer.pChromaQp, iQP, sizeof(int8_t)*9); \ memset(sFilter.pCsData[0], 0, sizeof(int8_t)*50); \ memset(sFilter.pCsData[1], 0, sizeof(int8_t)*9); \ memset(sFilter.pCsData[2], 0, sizeof(int8_t)*9); \ WelsDeblockingMb(&sDqLayer, &sFilter, iBoundFlag ); \ EXPECT_TRUE(iY[0]==iLumaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iY[1<<2]==iLumaV1 && iY[2<<2]==iLumaV1 && iY[3<<2]==iLumaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iLumaV2)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[0]==iChromaV0 && iCr[0]==iChromaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[2<<1]==iChromaV1 && iCr[2<<1]==iChromaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iChromaV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iChromaV2)<<iQP<<" "<<sDqLayer.pMbType[1]; // QP>16, LEFT & TOP, Intra mode 0x01 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x01; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // QP>16, LEFT & TOP, Intra mode 0x02 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x02; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // MbType==0x03, Intra8x8 has not been supported now. // QP>16, LEFT & TOP, Intra mode 0x04 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x04; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // QP>16, LEFT & TOP, neighbor is Intra iQP = 16 + rand() % 35; sDqLayer.pMbType[0] = 0x02; sDqLayer.pMbType[1] = 0x0f; // Internal SKIP, Bs==0 UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 0, 0, 2, 0, 0) // QP<15, no output iQP = rand() % 16; sDqLayer.pMbType[1] = 0x04; UT_DB_MACROBLOCK_TEST (0x03, iQP, 0, 0, 0, 0, 0, 0)}Lines 501–954 of 954. Previous lines
EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Ver == &DeblockLumaLt4V_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Ver == &DeblockLumaEq4V_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Hor == &DeblockLumaLt4H_##idx); \ EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Hor == &DeblockLumaEq4H_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Ver == &DeblockChromaLt4V_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Ver == &DeblockChromaEq4V_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Hor == &DeblockChromaLt4H_##idx); \ EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Hor == &DeblockChromaEq4H_##idx); #ifndef X86_ASM // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) #endif #ifdef X86_ASM // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // SSE3 DeblockingInit (&sDBFunc, 0x00000200); DB_FUNC_CPUFLAG (ssse3) #endif #ifdef HAVE_NEON // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // NEON DeblockingInit (&sDBFunc, 0x000004); DB_FUNC_CPUFLAG (neon) #endif #ifdef HAVE_NEON_AARCH64 // pure C DeblockingInit (&sDBFunc, 0x00000000); DB_FUNC_CPUFLAG (c) // NEON_AARCH64 DeblockingInit (&sDBFunc, 0x000004); DB_FUNC_CPUFLAG (AArch64_neon) #endif } TEST (DecoderDeblocking, WelsDeblockingFilterSlice) { // void WelsDeblockingFilterSlice (PWelsDecoderContext pCtx, PDeblockingFilterMbFunc pDeblockMb) /* NOT support FMO now */ SWelsDecoderContext sCtx; SDqLayer sDqLayer; SSps sSPS; SPps sPPS; SPicture sDec; PDeblockingFilterMbFunc pDeblockMb = &UT_DeblockingFuncInterface; /* NOT do actual deblocking process, set related parameters to null */ sCtx.pDec = &sDec; sCtx.pDec->iLinesize[0] = sCtx.pDec->iLinesize[1] = sCtx.pDec->iLinesize[2] = 0; sCtx.pDec->pData[0] = sCtx.pDec->pData[1] = sCtx.pDec->pData[2] = NULL; /* As no FMO in encoder now, the multi slicegroups has not been set */ sCtx.pFmo = NULL; sCtx.pCurDqLayer = &sDqLayer; /* As void return, using iMbXyIndex to reflect whether the all MBs have been passed. */ sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 0; // whether disable Deblocking Filter Idc sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceAlphaC0Offset = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceBetaOffset = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps = &sSPS; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps = &sPPS; /* Only test one slicegroup, not reflect the FMO func */ sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps->uiNumSliceGroups = 1; // (1) Normal case, the iTotalMbInCurSlice == pSps->uiTotalMbCount sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; // at least one MB sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice) << sDqLayer.iMbXyIndex << " " << sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; // (2) Normal case, multi slices, iTotalMbInCurSlice <= pSps->uiTotalMbCount sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice + rand() % 256; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice); // (3) Special case, iTotalMbInCurSlice >= pSps->uiTotalMbCount, JUST FOR TEST sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount + rand() % 256; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE ((uint32_t) (sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount); // (4) Special case, uiDisableDeblockingFilterIdc==1, disable deblocking sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 0; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 1; sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; sDqLayer.iMbWidth = 1 + rand() % 128; WelsDeblockingFilterSlice (&sCtx, pDeblockMb); EXPECT_TRUE (sDqLayer.iMbXyIndex == 0) << sDqLayer.iMbXyIndex << " " << sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; } TEST (DecoderDeblocking, FilteringEdgeChromaHV) { // void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) SDqLayer sDqLayer; SDeblockingFilter sFilter; int32_t iBoundryFlag = 0x01; int32_t iQP; memset (&sDqLayer, 0, sizeof (SDqLayer)); memset (&sFilter, 0, sizeof (SDeblockingFilter)); SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func; int8_t iChromaQP[9]; sDqLayer.pChromaQp = iChromaQP; uint8_t iCb[9] = {0}; uint8_t iCr[9] = {0}; sFilter.pCsData[1] = iCb; sFilter.pCsData[2] = iCr; sFilter.iCsStride[0] = sFilter.iCsStride[1] = 2; sDqLayer.iMbX = 0; sDqLayer.iMbY = 0; //Only for test easy sDqLayer.iMbXyIndex = 1; // this function has NO iMbXyIndex validation #define UT_DB_CHROMA_TEST(iFlag, iQP, iV0, iV1, iV2) \ iBoundryFlag = iFlag; \ memset(iChromaQP, iQP, sizeof(int8_t)*9); \ memset(iCb, 0, sizeof(uint8_t)*9); \ memset(iCr, 0, sizeof(uint8_t)*9); \ FilteringEdgeChromaHV(&sDqLayer, &sFilter, iBoundryFlag); \ EXPECT_TRUE(iCb[0]==iV0 && iCr[0]==iV0); \ EXPECT_TRUE(iCb[2<<1]==iV1 && iCr[2<<1]==iV1); \ EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iV2); // QP<=15, iAlpha == iBeta == 0, TOP & LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x03, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x03, iQP, 2, 1, 1) // QP<=15, iAlpha == iBeta == 0, TOP | LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x01, iQP, 0, 0, 0) iQP = rand() % 16; UT_DB_CHROMA_TEST (0x02, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x01, iQP, 1, 1, 1) iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x02, iQP, 1, 1, 1) // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT iQP = rand() % 16; UT_DB_CHROMA_TEST (0x00, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT iQP = 16 + rand() % 35; UT_DB_CHROMA_TEST (0x00, iQP, 0, 1, 1) } TEST (DecoderDeblocking, FilteringEdgeLumaHV) { // void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) SDqLayer sDqLayer; SDeblockingFilter sFilter; int32_t iBoundryFlag = 0x03; int32_t iQP; memset (&sDqLayer, 0, sizeof (SDqLayer)); memset (&sFilter, 0, sizeof (SDeblockingFilter)); SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func; int8_t iLumaQP[50]; sDqLayer.pLumaQp = iLumaQP; uint8_t iY[50] = {0}; sFilter.pCsData[0] = iY; sFilter.iCsStride[0] = sFilter.iCsStride[1] = 4; sDqLayer.iMbX = 0; sDqLayer.iMbY = 0; //Only for test easy sDqLayer.iMbXyIndex = 1; // this function has NO iMbXyIndex validation #define UT_DB_LUMA_TEST(iFlag, iQP, iV0, iV1, iV2) \ iBoundryFlag = iFlag; \ memset(iLumaQP, iQP, sizeof(int8_t)*50); \ memset(iY, 0, sizeof(uint8_t)*50); \ FilteringEdgeLumaHV(&sDqLayer, &sFilter, iBoundryFlag); \ EXPECT_TRUE(iY[0]==iV0); \ EXPECT_TRUE(iY[1<<2]==iV1 && iY[2<<2]==iV1 && iY[3<<2]==iV1); \ EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iV2); // QP<=15, iAlpha == iBeta == 0, TOP & LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x03, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x03, iQP, 2, 1, 1) // QP<=15, iAlpha == iBeta == 0, TOP | LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x01, iQP, 0, 0, 0) iQP = rand() % 16; UT_DB_LUMA_TEST (0x02, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x01, iQP, 1, 1, 1) iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x02, iQP, 1, 1, 1) // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT iQP = rand() % 16; UT_DB_LUMA_TEST (0x00, iQP, 0, 0, 0) // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT iQP = 16 + rand() % 35; UT_DB_LUMA_TEST (0x00, iQP, 0, 1, 1) } /////////// Bs calculation functions TEST (DecoderDeblocking, DeblockingBsMarginalMBAvcbase) { // uint32_t DeblockingBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) /* Calculate the Bs equal to 2 or 1 */ SDqLayer sDqLayer; // Only define 2 MBs here int8_t iNoZeroCount[24 * 2]; // (*pNzc)[24] int8_t iLayerRefIndex[2][16 * 2]; // (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM]; int16_t iLayerMv[2][16 * 2][2]; //(*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A]; sDqLayer.pNzc = (int8_t (*)[24])iNoZeroCount; sDqLayer.pRefIndex[0] = (int8_t (*)[16])&iLayerRefIndex[0]; sDqLayer.pRefIndex[1] = (int8_t (*)[16])&iLayerRefIndex[1]; sDqLayer.pMv[0] = (int16_t (*) [16][2])&iLayerMv[0]; sDqLayer.pMv[1] = (int16_t (*) [16][2])&iLayerMv[1]; #define UT_DB_CLEAN_STATUS \ memset(iNoZeroCount, 0, sizeof(int8_t)*24*2); \ memset(iLayerRefIndex, 0, sizeof(int8_t)*2*16*2); \ memset(iLayerMv, 0, sizeof(int16_t)*2*16*2*2); int32_t iCurrBlock, iNeighborBlock; /* Cycle for each block and its neighboring block */ for (int iEdge = 0; iEdge < 2; iEdge++) { // Vertical and Horizontal for (int iPos = 0; iPos < 4; iPos++) { // Four different blocks on the edge iCurrBlock = (iEdge == 0 ? 4 * iPos : iPos); iNeighborBlock = (iEdge == 0 ? (3 + iPos * 4) : (12 + iPos)); // (1) iEdge == 0, current block NoZeroCount != 0 UT_DB_CLEAN_STATUS iNoZeroCount[0 * 24 + iCurrBlock] = 1; // Current MB_block position EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (2u << (iPos * 8))) << iEdge << " " << iPos << " NoZeroCount!=0"; // (2) iEdge == 0, neighbor block NoZeroCount != 0 UT_DB_CLEAN_STATUS iNoZeroCount[1 * 24 + iNeighborBlock ] = 1; // Neighbor MB_block position EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (2u << (iPos * 8))) << iEdge << " " << iPos << " NoZeroCount!=0"; // (3) iEdge == 0, reference idx diff UT_DB_CLEAN_STATUS iLayerRefIndex[0][0 * 16 + iCurrBlock] = 0; iLayerRefIndex[0][1 * 16 + iNeighborBlock] = 1; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " Ref idx diff"; // (4) iEdge == 0, abs(mv diff) < 4 UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][0] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][1] = rand() % 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == 0) << iEdge << " " << iPos << " diff_mv < 4"; // (5) iEdge == 0, abs(mv diff) > 4 UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][0] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][1 * 16 + iNeighborBlock][1] = 4; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == 4"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][0] = -2048; iLayerMv[0][1 * 16 + iNeighborBlock][0] = 2047; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == maximum"; UT_DB_CLEAN_STATUS iLayerMv[0][0 * 16 + iCurrBlock][1] = -2048; iLayerMv[0][1 * 16 + iNeighborBlock][1] = 2047; EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sDqLayer, iEdge, 1, 0) == (1u << (iPos * 8))) << iEdge << " " << iPos << " diff_mv == maximum"; } } } TEST (Deblocking, WelsDeblockingMb) { // void WelsDeblockingMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) /* Deblock one MB, calculate the Bs inside the function, only consider the intra / intra block */ SDqLayer sDqLayer; SDeblockingFilter sFilter; SDeblockingFunc sDBFunc; sFilter.pLoopf = &sDBFunc; sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func; sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func; sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func; sDqLayer.iMbX = sDqLayer.iMbY = 0; sDqLayer.iMbXyIndex = 1; sDqLayer.iMbWidth = 1; uint8_t iY[50] = {0}; sFilter.pCsData[0] = iY; sFilter.iCsStride[0] = 4; uint8_t iCb[9] = {0}; uint8_t iCr[9] = {0}; sFilter.pCsData[1] = iCb; sFilter.pCsData[2] = iCr; sFilter.iCsStride[1] = 2; int8_t iLumaQP[50] = {0}; int8_t iChromaQP[9] = {0}; sDqLayer.pLumaQp = iLumaQP; sDqLayer.pChromaQp = iChromaQP; int8_t iMbType[2]; sDqLayer.pMbType = iMbType; sDqLayer.pMbType[0] = 0x01; sDqLayer.pMbType[1] = 0x01; sFilter.iSliceAlphaC0Offset = 0; sFilter.iSliceBetaOffset = 0; int32_t iQP; #define UT_DB_MACROBLOCK_TEST( iBoundFlag, iQP, iLumaV0, iLumaV1, iLumaV2, iChromaV0, iChromaV1, iChromaV2 ) \ memset(sDqLayer.pLumaQp, iQP, sizeof(int8_t)*50); \ memset(sDqLayer.pChromaQp, iQP, sizeof(int8_t)*9); \ memset(sFilter.pCsData[0], 0, sizeof(int8_t)*50); \ memset(sFilter.pCsData[1], 0, sizeof(int8_t)*9); \ memset(sFilter.pCsData[2], 0, sizeof(int8_t)*9); \ WelsDeblockingMb(&sDqLayer, &sFilter, iBoundFlag ); \ EXPECT_TRUE(iY[0]==iLumaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iY[1<<2]==iLumaV1 && iY[2<<2]==iLumaV1 && iY[3<<2]==iLumaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iLumaV2)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[0]==iChromaV0 && iCr[0]==iChromaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[2<<1]==iChromaV1 && iCr[2<<1]==iChromaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \ EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iChromaV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iChromaV2)<<iQP<<" "<<sDqLayer.pMbType[1]; // QP>16, LEFT & TOP, Intra mode 0x01 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x01; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // QP>16, LEFT & TOP, Intra mode 0x02 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x02; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // MbType==0x03, Intra8x8 has not been supported now. // QP>16, LEFT & TOP, Intra mode 0x04 iQP = 16 + rand() % 35; sDqLayer.pMbType[1] = 0x04; UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1) // QP>16, LEFT & TOP, neighbor is Intra iQP = 16 + rand() % 35; sDqLayer.pMbType[0] = 0x02; sDqLayer.pMbType[1] = 0x0f; // Internal SKIP, Bs==0 UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 0, 0, 2, 0, 0) // QP<15, no output iQP = rand() % 16; sDqLayer.pMbType[1] = 0x04; UT_DB_MACROBLOCK_TEST (0x03, iQP, 0, 0, 0, 0, 0, 0) }