ref: 4a6259cf74617e15a4e0f0b3fdd8a749ed17499e
parent: f00d3ac15fa848c9116dcf282e33b3ac1b9c685d
author: huili2 <huili2@cisco.com>
date: Wed Apr 23 15:55:38 EDT 2014
add slice/frame copy UT for EC
--- /dev/null
+++ b/test/decoder/DecUT_ErrorConcealment.cpp
@@ -1,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);
+}
--- a/test/decoder/targets.mk
+++ b/test/decoder/targets.mk
@@ -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\