1 #include <gtest/gtest.h>
2
3 #include "wels_common_basis.h"
4 #include "memory_align.h"
5 #include "error_concealment.h"
6 #include "ls_defines.h"
7 #include "cpu.h"
8
9 using namespace WelsDec;
10
11 #define MAX_MB_WIDTH 260
12 #define MAX_MB_HEIGHT 130
13
14 typedef struct TagECInputCtx {
15 int32_t iMbWidth;
16 int32_t iMbHeight;
17 uint32_t iLinesize[3];
18 bool* pMbCorrectlyDecodedFlag; //actual memory
19 PWelsDecoderContext pCtx;
20 SDqLayer sDqLayer;
21 SPicture sAncPic; //Anc picture for comparison
22 SPicture sSrcPic; //Src picture as common input picture data
23 SPicture sWelsPic; //Wels picture to be compared
24 SWelsLastDecPicInfo sLastDecPicInfo;
25 } SECInputCtx, *PECInputCtx;
26
FreeInputData(PECInputCtx pECCtx)27 void FreeInputData (PECInputCtx pECCtx) {
28 if (pECCtx != NULL) {
29 if (pECCtx->pCtx != NULL) {
30 WELS_SAFE_FREE (pECCtx->pCtx->pParam, "pECCtx->pCtx->pParam");
31 WELS_SAFE_FREE (pECCtx->pCtx->pSps, "pECCtx->pCtx->pSps");
32 WELS_SAFE_FREE (pECCtx->pCtx, "pECCtx->pCtx");
33 }
34
35 WELS_SAFE_FREE (pECCtx->pMbCorrectlyDecodedFlag, "pECCtx->pMbCorrectlyDecodedFlag");
36 WELS_SAFE_FREE (pECCtx->sSrcPic.pData[0], "pECCtx->sSrcPic.pData");
37 WELS_SAFE_FREE (pECCtx->sAncPic.pData[0], "pECCtx->sAncPic.pData");
38 WELS_SAFE_FREE (pECCtx->sWelsPic.pData[0], "pECCtx->sWelsPic.pData");
39
40 WELS_SAFE_FREE (pECCtx, "pECCtx");
41 }
42 }
43
InitAndAllocInputData(PECInputCtx & pECCtx)44 int32_t InitAndAllocInputData (PECInputCtx& pECCtx) {
45 FreeInputData (pECCtx);
46
47 pECCtx = (PECInputCtx) WelsMallocz (sizeof (SECInputCtx), "pECCtx");
48 if (pECCtx == NULL)
49 return 1;
50 memset (pECCtx, 0, sizeof (SECInputCtx));
51
52 pECCtx->iMbWidth = rand() % (MAX_MB_WIDTH - 1) + 1; //give a constrained max width
53 pECCtx->iMbHeight = rand() % (MAX_MB_HEIGHT - 1) + 1; //give a constrained max height
54 pECCtx->iLinesize[0] = pECCtx->iMbWidth << 4;
55 pECCtx->iLinesize[1] = pECCtx->iLinesize[2] = pECCtx->iLinesize[0] >> 1;
56
57 const uint32_t kiLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
58
59 //allocate picture data
60 pECCtx->sWelsPic.pData[0] = (uint8_t*) WelsMallocz (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sWelsPic.pData");
61 if (pECCtx->sWelsPic.pData[0] == NULL)
62 return 1;
63 pECCtx->sWelsPic.pData[1] = pECCtx->sWelsPic.pData[0] + kiLumaSize;
64 pECCtx->sWelsPic.pData[2] = pECCtx->sWelsPic.pData[1] + (kiLumaSize >> 2);
65
66 pECCtx->sAncPic.pData[0] = (uint8_t*) WelsMallocz (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sAncPic.pData");
67 if (pECCtx->sAncPic.pData[0] == NULL)
68 return 1;
69 pECCtx->sAncPic.pData[1] = pECCtx->sAncPic.pData[0] + kiLumaSize;
70 pECCtx->sAncPic.pData[2] = pECCtx->sAncPic.pData[1] + (kiLumaSize >> 2);
71
72 pECCtx->sSrcPic.pData[0] = (uint8_t*) WelsMallocz (kiLumaSize * 3 / 2 * sizeof (uint8_t), "pECCtx->sSrcPic.pData");
73 if (pECCtx->sSrcPic.pData[0] == NULL)
74 return 1;
75 pECCtx->sSrcPic.pData[1] = pECCtx->sSrcPic.pData[0] + kiLumaSize;
76 pECCtx->sSrcPic.pData[2] = pECCtx->sSrcPic.pData[1] + (kiLumaSize >> 2);
77
78 pECCtx->sWelsPic.iLinesize[0] = pECCtx->sAncPic.iLinesize[0] = pECCtx->sSrcPic.iLinesize[0] = pECCtx->iLinesize[0];
79 pECCtx->sWelsPic.iLinesize[1] = pECCtx->sAncPic.iLinesize[1] = pECCtx->sSrcPic.iLinesize[1] = pECCtx->iLinesize[1];
80 pECCtx->sWelsPic.iLinesize[2] = pECCtx->sAncPic.iLinesize[2] = pECCtx->sSrcPic.iLinesize[2] = pECCtx->iLinesize[2];
81
82 pECCtx->pMbCorrectlyDecodedFlag = (bool*) WelsMallocz (pECCtx->iMbWidth * pECCtx->iMbHeight * sizeof (bool),
83 "pECCtx->pMbCorrectlyDecodedFlag");
84 if (pECCtx->pMbCorrectlyDecodedFlag == NULL)
85 return 1;
86
87 pECCtx->pCtx = (PWelsDecoderContext) WelsMallocz (sizeof (SWelsDecoderContext), "pECCtx->pCtx");
88 if (pECCtx->pCtx == NULL)
89 return 1;
90
91 pECCtx->pCtx->pDec = &pECCtx->sWelsPic;
92 pECCtx->pCtx->pCurDqLayer = &pECCtx->sDqLayer;
93 pECCtx->pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
94 pECCtx->pCtx->pLastDecPicInfo = &pECCtx->sLastDecPicInfo;
95 pECCtx->pCtx->pSps = (PSps) WelsMallocz (sizeof (SSps), "pECCtx->pCtx->pSps");
96 if (pECCtx->pCtx->pSps == NULL)
97 return 1;
98 pECCtx->pCtx->pSps->iMbWidth = pECCtx->iMbWidth;
99 pECCtx->pCtx->pSps->iMbHeight = pECCtx->iMbHeight;
100 pECCtx->pCtx->pParam = (PDecodingParam) WelsMallocz (sizeof (SDecodingParam), "pECCtx->pCtx->pParam");
101 if (pECCtx->pCtx->pParam == NULL)
102 return 1;
103
104 return 0;
105 }
106
InitECCopyData(PECInputCtx pECCtx)107 void InitECCopyData (PECInputCtx pECCtx) {
108 const int32_t kiMbNum = pECCtx->iMbWidth * pECCtx->iMbHeight;
109 int i;
110 //init pMbCorrectlyDecodedFlag
111 for (i = 0; i < kiMbNum; ++i) {
112 pECCtx->pMbCorrectlyDecodedFlag[i] = !! (rand() & 1);
113 }
114 //init Data
115 const int32_t iPixNum = kiMbNum * 256 * 3 / 2;
116 for (i = 0; i < iPixNum; ++i) {
117 pECCtx->sSrcPic.pData[0][i] = rand() & 0xff;
118 }
119 int32_t iCpuCores = 1;
120 pECCtx->pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
121 InitErrorCon (pECCtx->pCtx);
122 }
123
DoAncErrorConSliceCopy(PECInputCtx pECCtx)124 void DoAncErrorConSliceCopy (PECInputCtx pECCtx) {
125 int32_t iMbWidth = (int32_t) pECCtx->iMbWidth;
126 int32_t iMbHeight = (int32_t) pECCtx->iMbHeight;
127 PPicture pDstPic = &pECCtx->sAncPic;
128 PPicture pSrcPic = pECCtx->pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb;
129 if ((pECCtx->pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY)
130 && (pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
131 pSrcPic = NULL;
132
133 //uint8_t *pDstData[3], *pSrcData[3];
134 bool* pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
135
136 //Do slice copy late
137 int32_t iMbXyIndex, i;
138 uint8_t* pSrcData, *pDstData;
139 uint32_t iSrcStride = pECCtx->iLinesize[0];
140 uint32_t iDstStride = pECCtx->iLinesize[0];
141 for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
142 for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
143 iMbXyIndex = iMbY * iMbWidth + iMbX;
144 if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
145 if (pSrcPic != NULL) {
146 //Y component
147 pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
148 pSrcData = pSrcPic->pData[0] + iMbY * 16 * iSrcStride + iMbX * 16;
149 for (i = 0; i < 16; ++i) {
150 memcpy (pDstData, pSrcData, 16);
151 pDstData += iDstStride;
152 pSrcData += iSrcStride;
153 }
154 //U component
155 pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
156 pSrcData = pSrcPic->pData[1] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
157 for (i = 0; i < 8; ++i) {
158 memcpy (pDstData, pSrcData, 8);
159 pDstData += iDstStride / 2;
160 pSrcData += iSrcStride / 2;
161 }
162 //V component
163 pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
164 pSrcData = pSrcPic->pData[2] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
165 for (i = 0; i < 8; ++i) {
166 memcpy (pDstData, pSrcData, 8);
167 pDstData += iDstStride / 2;
168 pSrcData += iSrcStride / 2;
169 }
170 } else { //pSrcPic == NULL
171 //Y component
172 pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
173 for (i = 0; i < 16; ++i) {
174 memset (pDstData, 128, 16);
175 pDstData += iDstStride;
176 }
177 //U component
178 pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
179 for (i = 0; i < 8; ++i) {
180 memset (pDstData, 128, 8);
181 pDstData += iDstStride / 2;
182 }
183 //V component
184 pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
185 for (i = 0; i < 8; ++i) {
186 memset (pDstData, 128, 8);
187 pDstData += iDstStride / 2;
188 }
189 } //
190 } //!pMbCorrectlyDecodedFlag[iMbXyIndex]
191 } //iMbX
192 } //iMbY
193 }
194
195
196
ComparePictureDataI420(uint8_t * pSrcData,uint8_t * pDstData,const uint32_t kiStride,const int32_t kiHeight)197 bool ComparePictureDataI420 (uint8_t* pSrcData, uint8_t* pDstData, const uint32_t kiStride, const int32_t kiHeight) {
198 bool bSame = true;
199 uint8_t* pAncData; // = pECCtx->sAncPic.pData[0];
200 uint8_t* pCompData;
201 int32_t iStride;
202 int32_t iCurHeight;
203 int32_t iHeight = kiHeight;
204
205 //Y component
206 iStride = kiStride;
207 pAncData = pSrcData;
208 pCompData = pDstData;
209 for (iCurHeight = 0; bSame && (iCurHeight < kiHeight); ++iCurHeight) {
210 bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
211 pAncData += iStride;
212 pCompData += iStride;
213 }
214 //chroma component
215 iHeight >>= 1;
216 iStride >>= 1;
217 //U component
218 for (iCurHeight = 0; bSame && (iCurHeight < kiHeight / 2); ++iCurHeight) {
219 bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
220 pAncData += iStride;
221 pCompData += iStride;
222 }
223 //V component
224 for (iCurHeight = 0; bSame && (iCurHeight < kiHeight / 2); ++iCurHeight) {
225 bSame = (memcmp (pAncData, pCompData, iStride * sizeof (uint8_t)) == 0);
226 pAncData += iStride;
227 pCompData += iStride;
228 }
229
230 return bSame;
231 }
232
233 //TEST cases followed
TEST(ErrorConTest,DoErrorConFrameCopy)234 TEST (ErrorConTest, DoErrorConFrameCopy) {
235 bool bOK = true;
236 PECInputCtx pECCtx = NULL;
237 if (InitAndAllocInputData (pECCtx)) {
238 FreeInputData (pECCtx);
239 return;
240 }
241
242 for (int iEC = 0; iEC < 2; ++ iEC) { //ERROR_CON_FRAME_COPY, ERROR_CON_FRAME_COPY_CROSS_IDR
243 pECCtx->pCtx->pParam->eEcActiveIdc = iEC > 0 ? ERROR_CON_FRAME_COPY_CROSS_IDR : ERROR_CON_FRAME_COPY;
244 InitECCopyData (pECCtx);
245 int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
246
247 for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
248 pECCtx->pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
249 for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
250 pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
251 //Do reference code method
252 DoErrorConFrameCopy (pECCtx->pCtx);
253 //Do anchor method
254 if (iRef && ! ((pECCtx->pCtx->pParam->eEcActiveIdc == ERROR_CON_FRAME_COPY)
255 && (pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag)))
256 memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
257 else
258 memset (pECCtx->sAncPic.pData[0], 128, iLumaSize * 3 / 2); //should be the same as known EC method, here all 128
259 //Compare results
260 bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
261 pECCtx->iMbHeight * 16);
262 EXPECT_EQ (bOK, true);
263 } //non IDR, IDR
264 } // no ref, with ref
265 } //FRAME_COPY methods
266
267 FreeInputData (pECCtx);
268 }
269
270 //TEST cases followed
TEST(ErrorConTest,DoErrorConSliceCopy)271 TEST (ErrorConTest, DoErrorConSliceCopy) {
272 bool bOK = true;
273 PECInputCtx pECCtx = NULL;
274 if (InitAndAllocInputData (pECCtx)) {
275 FreeInputData (pECCtx);
276 return;
277 }
278
279 for (int iEC = 0; iEC < 2; ++ iEC) { //ERROR_CON_SLICE_COPY, ERROR_CON_SLICE_COPY_CROSS_IDR
280 pECCtx->pCtx->pParam->eEcActiveIdc = iEC > 0 ? ERROR_CON_SLICE_COPY_CROSS_IDR : ERROR_CON_SLICE_COPY;
281 InitECCopyData (pECCtx);
282 for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
283 pECCtx->pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
284 for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
285 pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
286 //Do reference code method
287 DoErrorConSliceCopy (pECCtx->pCtx);
288 //Do anchor method
289 DoAncErrorConSliceCopy (pECCtx);
290 //Compare results
291 bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
292 pECCtx->iMbHeight * 16);
293 EXPECT_EQ (bOK, true);
294 } //non IDR, IDR
295 } // no ref, with ref
296 } //FRAME_COPY methods
297
298 FreeInputData (pECCtx);
299 }
300