openh264/test/decoder/DecUT_DeblockCommon.cpp
Martin Storsjö 59fefbe7c7 Use an inline function instead of a macro for clipping which contains rand()
When using a macro, the macro parameters get evaluated
multiple times, which means that the rand() value compared
actually isn't the same that is used as return value.

This makes sure that clipping works as intended for the
random tests.
2014-12-16 11:13:22 +02:00

953 lines
36 KiB
C++

#include <gtest/gtest.h>
#include "../../codec/decoder/core/inc/deblocking.h"
#include "../../codec/common/inc/deblocking_common.h"
using namespace WelsDec;
/* extern pure C functions */
extern void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta,
int8_t* pTc);
extern void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta);
extern void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
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) \
if (iNum==0) { \
iAlpha = 255; \
iBeta = 18; \
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] = WelsClip3( pBase[i-1] -16 + rand()%32, 0, 255 ); \
} \
} else if (iNum==1) { \
iAlpha = 4; \
iBeta = 2; \
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] = WelsClip3( pBase[i-1] -4 + rand()%8, 0, 255 ); \
} \
} else { \
iAlpha = rand() % 256; \
iBeta = rand() % 19; \
for (int i=0; i<4; i++) { \
iTc[i] = rand() % 26; \
} \
for (int i = 0; i < iWidth*iWidth; i++) { \
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) {
// void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
// bS<4, Section 8.7.2.3
int32_t p[3];
int32_t q[3];
int32_t iTc;
int32_t iDelta;
int32_t iIndexTc;
for (int iLine = 0; iLine < 16; iLine++) {
iIndexTc = iLine >> 2;
iTc = pTc[iIndexTc];
for (int m = 0; m < 3; m++) {
p[m] = pPix[iStrideX * -1 * (m + 1)];
q[m] = pPix[iStrideX * m];
}// for
// filterSampleFlag, 8-460
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] = WELS_CLIP3 (p[1] + WELS_CLIP3 (((p[2] + ((p[0] + q[0] + 1) >> 1) - (p[1] << 1)) >> 1),
-1 * pTc[iIndexTc], pTc[iIndexTc]), 0, 255);
iTc++;
}
// 8-472
if (abs (q[2] - q[0]) < iBeta) {
pPix[iStrideX * 1] = WELS_CLIP3 (q[1] + WELS_CLIP3 (((q[2] + ((p[0] + q[0] + 1) >> 1) - (q[1] << 1)) >> 1),
-1 * pTc[iIndexTc], pTc[iIndexTc]), 0, 255);
iTc++;
}
// 8-467,468,469
iDelta = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPix[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
pPix[0] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
}
// Next line
pPix += iStrideY;
}
}
void anchor_DeblockingLumaIntra (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta) {
// void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
// bS==4, Section 8.7.2.4
int32_t p[4], q[4];
for (int iLine = 0; iLine < 16; iLine++) {
for (int m = 0; m < 4; m++) {
p[m] = pPix[iStrideX * -1 * (m + 1)];
q[m] = pPix[iStrideX * m];
}
// filterSampleFlag, 8-460
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
// 8-476
if (abs (p[2] - p[0]) < iBeta && abs (p[0] - q[0]) < ((iAlpha >> 2) + 2)) {
// 8-477,478, 479
pPix[iStrideX * -1] = (p[2] + 2 * p[1] + 2 * p[0] + 2 * q[0] + q[1] + 4) >> 3;
pPix[iStrideX * -2] = (p[2] + p[1] + p[0] + q[0] + 2) >> 2;
pPix[iStrideX * -3] = (2 * p[3] + 3 * p[2] + p[1] + p[0] + q[0] + 4) >> 3;
} else {
// 8-480
pPix[iStrideX * -1] = (2 * p[1] + p[0] + q[1] + 2) >> 2;
}
// 8-483
if (abs (q[2] - q[0]) < iBeta && abs (p[0] - q[0]) < ((iAlpha >> 2) + 2)) {
// 8-484,485,486
pPix[ 0 ] = (p[1] + 2 * p[0] + 2 * q[0] + 2 * q[1] + q[2] + 4) >> 3;
pPix[1 * iStrideX ] = (p[0] + q[0] + q[1] + q[2] + 2) >> 2;
pPix[2 * iStrideX ] = (2 * q[3] + 3 * q[2] + q[1] + q[0] + p[0] + 4) >> 3;
} else {
// 8-487
pPix[0 * iStrideX ] = (2 * q[1] + q[0] + p[1] + 2) >> 2;
}
}
// Next line
pPix += iStrideY;
}
}
void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY,
int32_t iAlpha, int32_t iBeta, int8_t* pTc) {
// void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
// Section 8.7.2.3
int32_t p[2], q[2];
int32_t iIndexTc;
int32_t iDelta;
int32_t iTc;
for (int iLine = 0; iLine < 8; iLine++) {
iIndexTc = iLine >> 1;
iTc = pTc[iIndexTc];
/* for Cb */
for (int m = 0; m < 2; m++) {
p[m] = pPixCb[iStrideX * -1 * (m + 1)];
q[m] = pPixCb[iStrideX * m];
}
// 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 = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPixCb[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
pPixCb[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
}
pPixCb += iStrideY;
/* for Cr */
for (int m = 0; m < 2; m++) {
p[m] = pPixCr[iStrideX * -1 * (m + 1)];
q[m] = pPixCr[iStrideX * m];
}
// 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 = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
pPixCr[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
pPixCr[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
}
pPixCr += iStrideY;
}
}
void anchor_DeblockingChromaIntra (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
int32_t iBeta) {
//void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
// Section 8.7.2.4
int32_t p[2], q[2];
for (int iLine = 0; iLine < 8; iLine++) {
/* for Cb */
for (int m = 0; m < 2; m++) {
p[m] = pPixCb[iStrideX * -1 * (m + 1)];
q[m] = pPixCb[iStrideX * m];
}
// 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] = WELS_CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
pPixCb[iStrideX * 0 ] = WELS_CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
}
pPixCb += iStrideY;
/* for Cr */
for (int m = 0; m < 2; m++) {
p[m] = pPixCr[iStrideX * -1 * (m + 1)];
q[m] = pPixCr[iStrideX * m];
}
// 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] = WELS_CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
pPixCr[iStrideX * 0 ] = WELS_CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
}
pPixCr += iStrideY;
}
}
/* Unit test functions body */
TEST (DeblockingCommon, DeblockLumaLt4_c) {
// void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
#define TEST_CYCLE 1000
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixBase, 16 * 16, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixRef, 16 * 16, 16);
int32_t iAlpha, iBeta;
ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
/* Horizontal */
GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
anchor_DeblockingLumaNormal (&iPixBase[8 * 1], 1, 16, iAlpha, iBeta, iTc);
DeblockLumaLt4_c (&iPixRef[8 * 1], 1, 16, iAlpha, iBeta, iTc);
for (int i = 0; i < 16 * 16; i++) {
ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Horizontal Error, (Pos, Base, Ref)-(" << i << "," <<
(uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
}
/* Vertical */
GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
anchor_DeblockingLumaNormal (&iPixBase[8 * 16], 16, 1, iAlpha, iBeta, iTc);
DeblockLumaLt4_c (&iPixRef[8 * 16], 16, 1, iAlpha, iBeta, iTc);
for (int i = 0; i < 16 * 16; i++) {
ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Vertical Error, (Pos, Base, Ref)-(" << i << "," <<
(uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
}
}
}
TEST (DeblockingCommon, DeblockLumaEq4_c) {
//void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
#define TEST_CYCLE 1000
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixBase, 16 * 16, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixRef, 16 * 16, 16);
int32_t iAlpha, iBeta;
/* NOT used here */
ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
/* Horizontal */
GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
anchor_DeblockingLumaIntra (&iPixBase[8 * 1], 1, 16, iAlpha, iBeta);
DeblockLumaEq4_c (&iPixRef[8 * 1], 1, 16, iAlpha, iBeta);
for (int i = 0; i < 16 * 16; i++) {
ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Horizontal Error, (Pos, Base, Ref)-(" << i << "," <<
(uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
}
/* Vertical */
GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
anchor_DeblockingLumaIntra (&iPixBase[8 * 16], 16, 1, iAlpha, iBeta);
DeblockLumaEq4_c (&iPixRef[8 * 16], 16, 1, iAlpha, iBeta);
for (int i = 0; i < 16 * 16; i++) {
ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Vertical Error, (Pos, Base, Ref)-(" << i << "," <<
(uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
}
}
}
TEST (DeblockingCommon, DeblockChromaLt4_c) {
// void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
#define TEST_CYCLE 1000
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbBase, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrBase, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbRef, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrRef, 8 * 8, 16);
int32_t iAlpha, iBeta;
ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
/* Horizontal */
GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
anchor_DeblockingChromaNormal (&iPixCbBase[4 * 1], &iPixCrBase[4 * 1], 1, 8, iAlpha, iBeta, iTc);
DeblockChromaLt4_c (&iPixCbRef[4 * 1], &iPixCrRef[4 * 1], 1, 8, iAlpha, iBeta, iTc);
for (int i = 0; i < 8 * 8; i++) {
ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
|| iPixCrBase[i] != iPixCrRef[i]) << "Horizontal Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
(uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
(uint32_t)iPixCrRef[i] << ")";
}
/* Vertical */
GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
anchor_DeblockingChromaNormal (&iPixCbBase[4 * 8], &iPixCrBase[4 * 8], 8, 1, iAlpha, iBeta, iTc);
DeblockChromaLt4_c (&iPixCbRef[4 * 8], &iPixCrRef[4 * 8], 8, 1, iAlpha, iBeta, iTc);
for (int i = 0; i < 8 * 8; i++) {
ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
|| iPixCrBase[i] != iPixCrRef[i]) << "Vertical Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
(uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
(uint32_t)iPixCrRef[i] << ")";
}
}
}
TEST (DeblockingCommon, DeblockChromaEq4_c) {
// void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
#define TEST_CYCLE 1000
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbBase, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrBase, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbRef, 8 * 8, 16);
ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrRef, 8 * 8, 16);
int32_t iAlpha, iBeta;
/* NOT used here*/
ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
/* Horizontal */
GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
anchor_DeblockingChromaIntra (&iPixCbBase[4 * 1], &iPixCrBase[4 * 1], 1, 8, iAlpha, iBeta);
DeblockChromaEq4_c (&iPixCbRef[4 * 1], &iPixCrRef[4 * 1], 1, 8, iAlpha, iBeta);
for (int i = 0; i < 8 * 8; i++) {
ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
|| iPixCrBase[i] != iPixCrRef[i]) << "Horizontal Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
(uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
(uint32_t)iPixCrRef[i] << ")";
}
/* Vertical */
GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
anchor_DeblockingChromaIntra (&iPixCbBase[4 * 8], &iPixCrBase[4 * 8], 8, 1, iAlpha, iBeta);
DeblockChromaEq4_c (&iPixCbRef[4 * 8], &iPixCrRef[4 * 8], 8, 1, iAlpha, iBeta);
for (int i = 0; i < 8 * 8; i++) {
ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
|| iPixCrBase[i] != iPixCrRef[i]) << "Vertical Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
(uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
(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 = 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)
}