Merge pull request #742 from huili2/ec_ut_copy
add slice/frame copy UT for EC
This commit is contained in:
commit
d905d6bdfd
291
test/decoder/DecUT_ErrorConcealment.cpp
Normal file
291
test/decoder/DecUT_ErrorConcealment.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
#include<gtest/gtest.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "wels_common_basis.h"
|
||||
#include "mem_align.h"
|
||||
#include "error_concealment.h"
|
||||
#include "ls_defines.h"
|
||||
#include "cpu.h"
|
||||
|
||||
using namespace WelsDec;
|
||||
|
||||
#define MAX_MB_WIDTH 260
|
||||
#define MAX_MB_HEIGHT 130
|
||||
|
||||
typedef struct TagECInputCtx {
|
||||
int32_t iMbWidth;
|
||||
int32_t iMbHeight;
|
||||
uint32_t iLinesize[3];
|
||||
bool* pMbCorrectlyDecodedFlag; //actual memory
|
||||
PWelsDecoderContext pCtx;
|
||||
SDqLayer sDqLayer;
|
||||
SPicture sAncPic; //Anc picture for comparison
|
||||
SPicture sSrcPic; //Src picture as common input picture data
|
||||
SPicture sWelsPic; //Wels picture to be compared
|
||||
} SECInputCtx, *PECInputCtx;
|
||||
|
||||
void FreeInputData (PECInputCtx pECCtx) {
|
||||
if (pECCtx != NULL) {
|
||||
if (pECCtx->pCtx != NULL) {
|
||||
WELS_SAFE_FREE (pECCtx->pCtx->pSps, "pECCtx->pCtx->pSps");
|
||||
WELS_SAFE_FREE (pECCtx->pCtx, "pECCtx->pCtx");
|
||||
}
|
||||
|
||||
WELS_SAFE_FREE (pECCtx->pMbCorrectlyDecodedFlag, "pECCtx->pMbCorrectlyDecodedFlag");
|
||||
WELS_SAFE_FREE (pECCtx->sSrcPic.pData[0], "pECCtx->sSrcPic.pData");
|
||||
WELS_SAFE_FREE (pECCtx->sAncPic.pData[0], "pECCtx->sAncPic.pData");
|
||||
WELS_SAFE_FREE (pECCtx->sWelsPic.pData[0], "pECCtx->sWelsPic.pData");
|
||||
|
||||
WELS_SAFE_FREE (pECCtx, "pECCtx");
|
||||
}
|
||||
}
|
||||
|
||||
int32_t InitAndAllocInputData (PECInputCtx& pECCtx) {
|
||||
FreeInputData (pECCtx);
|
||||
|
||||
pECCtx = (PECInputCtx) WelsMalloc (sizeof (SECInputCtx), "pECCtx");
|
||||
if (pECCtx == NULL)
|
||||
return 1;
|
||||
memset (pECCtx, 0, sizeof (SECInputCtx));
|
||||
|
||||
srand ((uint32_t)time (NULL));
|
||||
pECCtx->iMbWidth = rand() % MAX_MB_WIDTH; //give a constrained max width
|
||||
pECCtx->iMbHeight = rand() % MAX_MB_HEIGHT; //give a constrained max height
|
||||
pECCtx->iLinesize[0] = pECCtx->iMbWidth << 4;
|
||||
pECCtx->iLinesize[1] = pECCtx->iLinesize[2] = pECCtx->iLinesize[0] >> 1;
|
||||
|
||||
const uint32_t kiLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
|
||||
|
||||
//allocate picture data
|
||||
pECCtx->sWelsPic.pData[0] = (uint8_t*) WelsMalloc (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sWelsPic.pData");
|
||||
if (pECCtx->sWelsPic.pData[0] == NULL)
|
||||
return 1;
|
||||
pECCtx->sWelsPic.pData[1] = pECCtx->sWelsPic.pData[0] + kiLumaSize;
|
||||
pECCtx->sWelsPic.pData[2] = pECCtx->sWelsPic.pData[1] + (kiLumaSize >> 2);
|
||||
|
||||
pECCtx->sAncPic.pData[0] = (uint8_t*) WelsMalloc (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sAncPic.pData");
|
||||
if (pECCtx->sAncPic.pData[0] == NULL)
|
||||
return 1;
|
||||
pECCtx->sAncPic.pData[1] = pECCtx->sAncPic.pData[0] + kiLumaSize;
|
||||
pECCtx->sAncPic.pData[2] = pECCtx->sAncPic.pData[1] + (kiLumaSize >> 2);
|
||||
|
||||
pECCtx->sSrcPic.pData[0] = (uint8_t*) WelsMalloc (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sSrcPic.pData");
|
||||
if (pECCtx->sAncPic.pData[0] == NULL)
|
||||
return 1;
|
||||
pECCtx->sSrcPic.pData[1] = pECCtx->sSrcPic.pData[0] + kiLumaSize;
|
||||
pECCtx->sSrcPic.pData[2] = pECCtx->sSrcPic.pData[1] + (kiLumaSize >> 2);
|
||||
|
||||
pECCtx->sWelsPic.iLinesize[0] = pECCtx->sAncPic.iLinesize[0] = pECCtx->sSrcPic.iLinesize[0] = pECCtx->iLinesize[0];
|
||||
pECCtx->sWelsPic.iLinesize[1] = pECCtx->sAncPic.iLinesize[1] = pECCtx->sSrcPic.iLinesize[1] = pECCtx->iLinesize[1];
|
||||
pECCtx->sWelsPic.iLinesize[2] = pECCtx->sAncPic.iLinesize[2] = pECCtx->sSrcPic.iLinesize[2] = pECCtx->iLinesize[2];
|
||||
|
||||
pECCtx->pMbCorrectlyDecodedFlag = (bool*) WelsMalloc (pECCtx->iMbWidth * pECCtx->iMbHeight * sizeof (bool),
|
||||
"pECCtx->pMbCorrectlyDecodedFlag");
|
||||
if (pECCtx->pMbCorrectlyDecodedFlag == NULL)
|
||||
return 1;
|
||||
|
||||
pECCtx->pCtx = (PWelsDecoderContext) WelsMalloc (sizeof (SWelsDecoderContext), "pECCtx->pCtx");
|
||||
if (pECCtx->pCtx == NULL)
|
||||
return 1;
|
||||
|
||||
pECCtx->pCtx->pDec = &pECCtx->sWelsPic;
|
||||
pECCtx->pCtx->pCurDqLayer = &pECCtx->sDqLayer;
|
||||
pECCtx->pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
|
||||
|
||||
pECCtx->pCtx->pSps = (PSps) WelsMalloc (sizeof (SSps), "pECCtx->pCtx->pSps");
|
||||
if (pECCtx->pCtx->pSps == NULL)
|
||||
return 1;
|
||||
pECCtx->pCtx->pSps->iMbWidth = pECCtx->iMbWidth;
|
||||
pECCtx->pCtx->pSps->iMbHeight = pECCtx->iMbHeight;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitECCopyData (PECInputCtx pECCtx) {
|
||||
srand ((uint32_t)time (NULL));
|
||||
const int32_t kiMbNum = pECCtx->iMbWidth * pECCtx->iMbHeight;
|
||||
int i;
|
||||
//init pMbCorrectlyDecodedFlag
|
||||
for (i = 0; i < kiMbNum; ++i) {
|
||||
pECCtx->pMbCorrectlyDecodedFlag[i] = !! (rand() & 1);
|
||||
}
|
||||
//init Data
|
||||
const int32_t iPixNum = kiMbNum * 256 * 3 / 2;
|
||||
for (i = 0; i < iPixNum; ++i) {
|
||||
pECCtx->sSrcPic.pData[0][i] = rand() & 0xff;
|
||||
}
|
||||
int32_t iCpuCores = 1;
|
||||
pECCtx->pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
|
||||
InitErrorCon (pECCtx->pCtx);
|
||||
}
|
||||
|
||||
void DoAncErrorConSliceCopy (PECInputCtx pECCtx) {
|
||||
int32_t iMbWidth = (int32_t) pECCtx->iMbWidth;
|
||||
int32_t iMbHeight = (int32_t) pECCtx->iMbHeight;
|
||||
PPicture pDstPic = &pECCtx->sAncPic;
|
||||
PPicture pSrcPic = pECCtx->pCtx->pPreviousDecodedPictureInDpb;
|
||||
|
||||
//uint8_t *pDstData[3], *pSrcData[3];
|
||||
bool* pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
|
||||
|
||||
//Do slice copy late
|
||||
int32_t iMbXyIndex, i;
|
||||
uint8_t* pSrcData, *pDstData;
|
||||
uint32_t iSrcStride = pECCtx->iLinesize[0];
|
||||
uint32_t iDstStride = pECCtx->iLinesize[0];
|
||||
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
|
||||
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
|
||||
iMbXyIndex = iMbY * iMbWidth + iMbX;
|
||||
if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
|
||||
if (pSrcPic != NULL) {
|
||||
//Y component
|
||||
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
|
||||
pSrcData = pSrcPic->pData[0] + iMbY * 16 * iSrcStride + iMbX * 16;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
memcpy (pDstData, pSrcData, 16);
|
||||
pDstData += iDstStride;
|
||||
pSrcData += iSrcStride;
|
||||
}
|
||||
//U component
|
||||
pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
pSrcData = pSrcPic->pData[1] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
memcpy (pDstData, pSrcData, 8);
|
||||
pDstData += iDstStride;
|
||||
pSrcData += iSrcStride;
|
||||
}
|
||||
//V component
|
||||
pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
pSrcData = pSrcPic->pData[2] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
memcpy (pDstData, pSrcData, 8);
|
||||
pDstData += iDstStride;
|
||||
pSrcData += iSrcStride;
|
||||
}
|
||||
} else { //pSrcPic == NULL
|
||||
//Y component
|
||||
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
|
||||
for (int32_t i = 0; i < 16; ++i) {
|
||||
memset (pDstData, 0, 16);
|
||||
pDstData += iDstStride;
|
||||
}
|
||||
//U component
|
||||
pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
for (int32_t i = 0; i < 8; ++i) {
|
||||
memset (pDstData, 0, 8);
|
||||
pDstData += iDstStride / 2;
|
||||
}
|
||||
//V component
|
||||
pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
for (int32_t i = 0; i < 8; ++i) {
|
||||
memset (pDstData, 0, 8);
|
||||
pDstData += iDstStride / 2;
|
||||
}
|
||||
} //
|
||||
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
|
||||
} //iMbX
|
||||
} //iMbY
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ComparePictureDataI420 (uint8_t* pSrcData, uint8_t* pDstData, const uint32_t kiStride, const int32_t kiHeight) {
|
||||
bool bSame = true;
|
||||
uint8_t* pAncData; // = pECCtx->sAncPic.pData[0];
|
||||
uint8_t* pCompData;
|
||||
int32_t iStride;
|
||||
int32_t iCurHeight;
|
||||
int32_t iHeight = kiHeight;
|
||||
|
||||
//Y component
|
||||
iStride = kiStride;
|
||||
pAncData = pSrcData;
|
||||
pCompData = pDstData;
|
||||
for (iCurHeight = 0; bSame && (iCurHeight < kiHeight); ++iCurHeight) {
|
||||
bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
|
||||
pAncData += iStride;
|
||||
pCompData += iStride;
|
||||
}
|
||||
//chroma component
|
||||
iHeight >>= 1;
|
||||
iStride >>= 1;
|
||||
//U component
|
||||
for (iCurHeight = 0; bSame && (iCurHeight < kiHeight / 2); ++iCurHeight) {
|
||||
bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
|
||||
pAncData += iStride;
|
||||
pCompData += iStride;
|
||||
}
|
||||
//V component
|
||||
for (iCurHeight = 0; bSame && (iCurHeight < kiHeight / 2); ++iCurHeight) {
|
||||
bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
|
||||
pAncData += iStride;
|
||||
pCompData += iStride;
|
||||
}
|
||||
|
||||
return bSame;
|
||||
}
|
||||
|
||||
//TEST cases followed
|
||||
TEST (ErrorConTest, DoErrorConFrameCopy) {
|
||||
bool bOK = true;
|
||||
PECInputCtx pECCtx = NULL;
|
||||
if (InitAndAllocInputData (pECCtx)) {
|
||||
FreeInputData (pECCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
pECCtx->pCtx->iErrorConMethod = ERROR_CON_FRAME_COPY;
|
||||
InitECCopyData (pECCtx);
|
||||
//case 1: no reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||
DoErrorConFrameCopy (pECCtx->pCtx);
|
||||
|
||||
int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
|
||||
memset (pECCtx->sAncPic.pData[0], 0, iLumaSize * 3 / 2); //should be the same as known EC method, here all 0
|
||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
||||
pECCtx->iMbHeight * 16);
|
||||
EXPECT_EQ (bOK, true);
|
||||
|
||||
//case 2: with reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sSrcPic;
|
||||
DoErrorConFrameCopy (pECCtx->pCtx);
|
||||
|
||||
memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
|
||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
||||
pECCtx->iMbHeight * 16);
|
||||
EXPECT_EQ (bOK, true);
|
||||
|
||||
FreeInputData (pECCtx);
|
||||
}
|
||||
|
||||
//TEST cases followed
|
||||
TEST (ErrorConTest, DoErrorConSliceCopy) {
|
||||
bool bOK = true;
|
||||
PECInputCtx pECCtx = NULL;
|
||||
if (InitAndAllocInputData (pECCtx)) {
|
||||
FreeInputData (pECCtx);
|
||||
return;
|
||||
}
|
||||
pECCtx->pCtx->iErrorConMethod = ERROR_CON_SLICE_COPY;
|
||||
InitECCopyData (pECCtx);
|
||||
//case 1: no reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||
DoAncErrorConSliceCopy (pECCtx);
|
||||
DoErrorConSliceCopy (pECCtx->pCtx);
|
||||
|
||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
||||
pECCtx->iMbHeight * 16);
|
||||
EXPECT_EQ (bOK, true);
|
||||
|
||||
//case 2: with reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sAncPic;
|
||||
DoAncErrorConSliceCopy (pECCtx);
|
||||
DoErrorConSliceCopy (pECCtx->pCtx);
|
||||
|
||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
||||
pECCtx->iMbHeight * 16);
|
||||
EXPECT_EQ (bOK, true);
|
||||
|
||||
FreeInputData (pECCtx);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
DECODER_UNITTEST_SRCDIR=test/decoder
|
||||
DECODER_UNITTEST_CPP_SRCS=\
|
||||
$(DECODER_UNITTEST_SRCDIR)/DecUT_ErrorConcealment.cpp\
|
||||
$(DECODER_UNITTEST_SRCDIR)/DecUT_ExpandPicture.cpp\
|
||||
$(DECODER_UNITTEST_SRCDIR)/DecUT_IdctResAddPred.cpp\
|
||||
$(DECODER_UNITTEST_SRCDIR)/DecUT_IntraPrediction.cpp\
|
||||
|
Loading…
Reference in New Issue
Block a user