Modify the random value range which only for debug

Modify the CLIP3 macros to match the CLIP3(value, min, max)
Add partly UT cases into it which related to function call
Modify the typo for WELS_NEON
Add partly UT cases into it which related to Bs calculation
Update Windows VS project
This commit is contained in:
Haibo Zhu 2014-09-16 23:23:31 -07:00
parent 04c2a7ac5c
commit b7c54242a9
2 changed files with 607 additions and 21 deletions

View File

@ -470,6 +470,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\decoder\DecUT_DeblockCommon.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\DecUT_DecExt.cpp"
>

View File

@ -3,7 +3,7 @@
#include "../../codec/decoder/core/inc/deblocking.h"
#include "../../codec/common/inc/deblocking_common.h"
#define CLIP3(VALUE, MIN, MAX) ((VALUE) < (MIN) ? (MIN) : ((VALUE) > (MAX) ? (MAX) : (VALUE)))
#define CLIP3(MIN, MAX, VALUE) ((VALUE) < (MIN) ? (MIN) : ((VALUE) > (MAX) ? (MAX) : (VALUE)))
using namespace WelsDec;
@ -15,6 +15,10 @@ extern void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrid
int32_t iBeta, int8_t* pTc);
extern void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
int32_t iBeta);
namespace WelsDec {
extern void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag);
extern void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag);
}
/* Macros body */
#define GENERATE_DATA_DEBLOCKING(pBase, pRef, iWidth) \
@ -24,7 +28,7 @@ if (iNum==0) { \
iTc[0] = iTc[1] = iTc[2] = iTc[3] = 25; \
pBase[0] = pRef[0] = 128; \
for (int i = 1; i < iWidth*iWidth; i++) { \
pBase[i] = pRef[i] = CLIP3( pBase[i-1] -16 + rand()%32, 0, 255); \
pBase[i] = pRef[i] = CLIP3( 0, 255, pBase[i-1] -16 + rand()%32 ); \
} \
} else if (iNum==1) { \
iAlpha = 4; \
@ -32,7 +36,7 @@ if (iNum==0) { \
iTc[0] = iTc[1] = iTc[2] = iTc[3] = 9; \
pBase[0] = pRef[0] = 128; \
for (int i = 1; i < iWidth*iWidth; i++) { \
pBase[i] = pRef[i] = CLIP3( pBase[i-1] -4 + rand()%8, 0, 255); \
pBase[i] = pRef[i] = CLIP3( 0, 255, pBase[i-1] -4 + rand()%8); \
} \
} else { \
iAlpha = rand() % 256; \
@ -41,10 +45,50 @@ if (iNum==0) { \
iTc[i] = rand() % 26; \
} \
for (int i = 0; i < iWidth*iWidth; i++) { \
pBase[i] = pRef[i] = rand() % 200; \
pBase[i] = pRef[i] = rand() % 256; \
} \
}
/* NULL functions, for null call */
void UT_DeblockingFuncInterface (PDqLayer pCurDqLayer, PDeblockingFilter filter, int32_t boundry_flag) {
return;
}
/* Set deblocking functions to NULL */
void UT_DeblockingFuncLumaLT4Func (uint8_t* iSampleY, int32_t iStride, int32_t iAlpha, int32_t iBeta, int8_t* iTc) {
if (iAlpha > 0 || iBeta > 0) {
iSampleY[0]++;
}
return;
}
void UT_DeblockingFuncLumaEQ4Func (uint8_t* iSampleY, int32_t iStride, int32_t iAlpha, int32_t iBeta) {
if (iAlpha > 0 || iBeta > 0) {
iSampleY[0]++;
}
return;
}
void UT_DeblockingFuncChromaLT4Func (uint8_t* iSampleCb, uint8_t* iSampleCr, int32_t iStride, int32_t iAlpha,
int32_t iBeta, int8_t* iTc) {
if (iAlpha > 0 || iBeta > 0) {
iSampleCb[0]++;
iSampleCr[0]++;
}
return;
}
void UT_DeblockingFuncChromaEQ4Func (uint8_t* iSampleCb, uint8_t* iSampleCr, int32_t iStride, int32_t iAlpha,
int32_t iBeta) {
if (iAlpha > 0 || iBeta > 0) {
iSampleCb[0]++;
iSampleCr[0]++;
}
return;
}
/* Public function for local test */
/* Anchor functions body, some directly from the current code */
void anchor_DeblockingLumaNormal (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta,
int8_t* pTc) {
@ -69,20 +113,20 @@ void anchor_DeblockingLumaNormal (uint8_t* pPix, int32_t iStrideX, int32_t iStri
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-470
if (abs (p[2] - p[0]) < iBeta) {
pPix[iStrideX * -2] = CLIP3 (p[1] + CLIP3 (((p[2] + ((p[0] + q[0] + 1) >> 1) - (p[1] << 1)) >> 1), -1 * pTc[iIndexTc],
pTc[iIndexTc]), 0, 255);
pPix[iStrideX * -2] = CLIP3 (0, 255, p[1] + CLIP3 (-1 * pTc[iIndexTc], pTc[iIndexTc],
((p[2] + ((p[0] + q[0] + 1) >> 1) - (p[1] << 1)) >> 1)));
iTc++;
}
// 8-472
if (abs (q[2] - q[0]) < iBeta) {
pPix[iStrideX * 1] = CLIP3 (q[1] + CLIP3 (((q[2] + ((p[0] + q[0] + 1) >> 1) - (q[1] << 1)) >> 1), -1 * pTc[iIndexTc],
pTc[iIndexTc]), 0, 255);
pPix[iStrideX * 1] = CLIP3 (0, 255, q[1] + CLIP3 (-1 * pTc[iIndexTc], pTc[iIndexTc],
((q[2] + ((p[0] + q[0] + 1) >> 1) - (q[1] << 1)) >> 1)));
iTc++;
}
// 8-467,468,469
iDelta = CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPix[iStrideX * -1] = CLIP3 ((p[0] + iDelta), 0, 255);
pPix[0] = CLIP3 ((q[0] - iDelta), 0, 255);
iDelta = CLIP3 (-1 * iTc, iTc, ((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3));
pPix[iStrideX * -1] = CLIP3 (0, 255, (p[0] + iDelta));
pPix[0] = CLIP3 (0, 255, (q[0] - iDelta));
}
// Next line
@ -152,9 +196,9 @@ void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iS
// filterSampleFlag, 8-460
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-467, 468, 469
iDelta = CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPixCb[iStrideX * -1] = CLIP3 ((p[0] + iDelta), 0, 255);
pPixCb[iStrideX * 0 ] = CLIP3 ((q[0] - iDelta), 0, 255);
iDelta = CLIP3 (-1 * iTc, iTc, ((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3));
pPixCb[iStrideX * -1] = CLIP3 (0, 255, (p[0] + iDelta));
pPixCb[iStrideX * 0 ] = CLIP3 (0, 255, (q[0] - iDelta));
}
pPixCb += iStrideY;
@ -167,9 +211,9 @@ void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iS
// filterSampleFlag, 8-460
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-467, 468, 469
iDelta = CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPixCr[iStrideX * -1] = CLIP3 ((p[0] + iDelta), 0, 255);
pPixCr[iStrideX * 0 ] = CLIP3 ((q[0] - iDelta), 0, 255);
iDelta = CLIP3 (-1 * iTc, iTc, ((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3));
pPixCr[iStrideX * -1] = CLIP3 (0, 255, (p[0] + iDelta));
pPixCr[iStrideX * 0 ] = CLIP3 (0, 255, (q[0] - iDelta));
}
pPixCr += iStrideY;
}
@ -191,8 +235,8 @@ void anchor_DeblockingChromaIntra (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iSt
// filterSampleFlag, 8-460
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-480, 487
pPixCb[iStrideX * -1] = CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
pPixCb[iStrideX * 0 ] = CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
pPixCb[iStrideX * -1] = CLIP3 (0, 255, (2 * p[1] + p[0] + q[1] + 2) >> 2);
pPixCb[iStrideX * 0 ] = CLIP3 (0, 255, (2 * q[1] + q[0] + p[1] + 2) >> 2);
}
pPixCb += iStrideY;
@ -205,8 +249,8 @@ void anchor_DeblockingChromaIntra (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iSt
// filterSampleFlag, 8-460
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-480, 487
pPixCr[iStrideX * -1] = CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
pPixCr[iStrideX * 0 ] = CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
pPixCr[iStrideX * -1] = CLIP3 (0, 255, (2 * p[1] + p[0] + q[1] + 2) >> 2);
pPixCr[iStrideX * 0 ] = CLIP3 (0, 255, (2 * q[1] + q[0] + p[1] + 2) >> 2);
}
pPixCr += iStrideY;
}
@ -369,4 +413,542 @@ TEST (DeblockingCommon, DeblockChromaEq4_c) {
(uint32_t)iPixCrRef[i] << ")";
}
}
}
/////////// Logic call functions
TEST (DecoderDeblocking, DeblockingAvailableNoInterlayer) {
// DeblockingAvailableNoInterlayer (PDqLayer pCurDqLayer, int32_t iFilterIdc)
SDqLayer sLayer;
int32_t iFilterIdc;
int32_t iSliceIdc[9];
sLayer.pSliceIdc = iSliceIdc;
/* iFilterIdc only support 0 and 2, which is related with the encode configuration */
/* Using 3x3 grids to simulate the different situations */
#define UT_DBAvailable_idc_0(iX, iY, iExpect) \
iFilterIdc = 0; \
sLayer.iMbX = iX; \
sLayer.iMbY = iY; \
sLayer.iMbXyIndex = sLayer.iMbX + sLayer.iMbY*3; \
sLayer.iMbWidth = 3; \
EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect);
#define UT_DBAvailable_idc_2_same_slice(iX, iY, iExpect) \
iFilterIdc = 2; \
sLayer.iMbX = iX; \
sLayer.iMbY = iY; \
sLayer.iMbXyIndex = sLayer.iMbX + sLayer.iMbY*3; \
sLayer.iMbWidth = 3; \
iSliceIdc[0] = rand()%10; \
for (int i=1; i<9; i++) { \
iSliceIdc[i] = iSliceIdc[0]; \
} \
EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect)<<"Same Slice";
#define UT_DBAvailable_idc_2_diff_slice(iX, iY, iExpect) \
iFilterIdc = 2; \
sLayer.iMbX = iX; \
sLayer.iMbY = iY; \
sLayer.iMbXyIndex = sLayer.iMbX + sLayer.iMbY*3; \
sLayer.iMbWidth = 3; \
for (int i=0; i<9; i++) { \
iSliceIdc[i] = i; \
} \
EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect)<<"Different Slice";
// (1) idc==0
UT_DBAvailable_idc_0 (0, 0, 0x00)
UT_DBAvailable_idc_0 (0, 1, 0x02)
UT_DBAvailable_idc_0 (0, 2, 0x02)
UT_DBAvailable_idc_0 (1, 0, 0x01)
UT_DBAvailable_idc_0 (1, 1, 0x03)
UT_DBAvailable_idc_0 (1, 2, 0x03)
UT_DBAvailable_idc_0 (2, 0, 0x01)
UT_DBAvailable_idc_0 (2, 1, 0x03)
UT_DBAvailable_idc_0 (2, 2, 0x03)
// (2) idc==2, same slice
UT_DBAvailable_idc_2_same_slice (0, 0, 0x00)
UT_DBAvailable_idc_2_same_slice (0, 1, 0x02)
UT_DBAvailable_idc_2_same_slice (0, 2, 0x02)
UT_DBAvailable_idc_2_same_slice (1, 0, 0x01)
UT_DBAvailable_idc_2_same_slice (1, 1, 0x03)
UT_DBAvailable_idc_2_same_slice (1, 2, 0x03)
UT_DBAvailable_idc_2_same_slice (2, 0, 0x01)
UT_DBAvailable_idc_2_same_slice (2, 1, 0x03)
UT_DBAvailable_idc_2_same_slice (2, 2, 0x03)
// (3) idc==3, diff slice
UT_DBAvailable_idc_2_diff_slice (0, 0, 0x00)
UT_DBAvailable_idc_2_diff_slice (0, 1, 0x00)
UT_DBAvailable_idc_2_diff_slice (0, 2, 0x00)
UT_DBAvailable_idc_2_diff_slice (1, 0, 0x00)
UT_DBAvailable_idc_2_diff_slice (1, 1, 0x00)
UT_DBAvailable_idc_2_diff_slice (1, 2, 0x00)
UT_DBAvailable_idc_2_diff_slice (2, 0, 0x00)
UT_DBAvailable_idc_2_diff_slice (2, 1, 0x00)
UT_DBAvailable_idc_2_diff_slice (2, 2, 0x00)
}
TEST (DecoderDeblocking, DeblockingInit) {
// void DeblockingInit (PDeblockingFunc pDeblockingFunc, int32_t iCpu)
SDeblockingFunc sDBFunc;
memset (&sDBFunc, 0, sizeof (SDeblockingFunc));
#define DB_FUNC_CPUFLAG(idx) \
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 = 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 + 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 = 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 = 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 ((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 = 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) == (2 << (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) == (2 << (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) == (1 << (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) == (1 << (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) == (1 << (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) == (1 << (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) == (1 << (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) == (1 << (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) == (1 << (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)
}