PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/test/decoder/DecUT_ErrorConcealment.cpp

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