1 /*!
2 * \copy
3 * Copyright (c) 2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * error_concealment.cpp: Wels decoder error concealment implementation
32 */
33
34 #include "error_code.h"
35 #include "expand_pic.h"
36 #include "manage_dec_ref.h"
37 #include "copy_mb.h"
38 #include "error_concealment.h"
39 #include "cpu_core.h"
40
41 namespace WelsDec {
42 //Init
InitErrorCon(PWelsDecoderContext pCtx)43 void InitErrorCon (PWelsDecoderContext pCtx) {
44 if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY)
45 || (pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR)
46 || (pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR)
47 || (pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
48 || (pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE)) {
49 if ((pCtx->pParam->eEcActiveIdc != ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
50 && (pCtx->pParam->eEcActiveIdc != ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE)) {
51 pCtx->bFreezeOutput = false;
52 }
53 pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_c;
54 pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
55
56 #if defined(X86_ASM)
57 if (pCtx->uiCpuFlag & WELS_CPU_MMXEXT) {
58 pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_mmx; //aligned
59 }
60
61 if (pCtx->uiCpuFlag & WELS_CPU_SSE2) {
62 pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_sse2; //this is aligned copy;
63 }
64 #endif //X86_ASM
65
66 #if defined(HAVE_NEON)
67 if (pCtx->uiCpuFlag & WELS_CPU_NEON) {
68 pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_neon; //aligned
69 pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_neon; //aligned
70 }
71 #endif //HAVE_NEON
72
73 #if defined(HAVE_NEON_AARCH64)
74 if (pCtx->uiCpuFlag & WELS_CPU_NEON) {
75 pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_AArch64_neon; //aligned
76 pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_AArch64_neon; //aligned
77 }
78 #endif //HAVE_NEON_AARCH64
79
80 #if defined(HAVE_LSX)
81 if (pCtx->uiCpuFlag & WELS_CPU_LSX) {
82 pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_lsx; //aligned
83 pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_lsx; //aligned
84 }
85 #endif// HAVE_LSX
86 } //TODO add more methods here
87 return;
88 }
89
90 //Do error concealment using frame copy method
DoErrorConFrameCopy(PWelsDecoderContext pCtx)91 void DoErrorConFrameCopy (PWelsDecoderContext pCtx) {
92 PPicture pDstPic = pCtx->pDec;
93 PPicture pSrcPic = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb;
94 uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
95 int32_t iStrideY = pDstPic->iLinesize[0];
96 int32_t iStrideUV = pDstPic->iLinesize[1];
97 pCtx->pDec->iMbEcedNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
98 if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_FRAME_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
99 pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
100 if (pSrcPic == NULL) { //no ref pic, assign specific data to picture
101 memset (pDstPic->pData[0], 128, uiHeightInPixelY * iStrideY);
102 memset (pDstPic->pData[1], 128, (uiHeightInPixelY >> 1) * iStrideUV);
103 memset (pDstPic->pData[2], 128, (uiHeightInPixelY >> 1) * iStrideUV);
104 } else if (pSrcPic == pDstPic) {
105 WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "DoErrorConFrameCopy()::EC memcpy overlap.");
106 } else { //has ref pic here
107 memcpy (pDstPic->pData[0], pSrcPic->pData[0], uiHeightInPixelY * iStrideY);
108 memcpy (pDstPic->pData[1], pSrcPic->pData[1], (uiHeightInPixelY >> 1) * iStrideUV);
109 memcpy (pDstPic->pData[2], pSrcPic->pData[2], (uiHeightInPixelY >> 1) * iStrideUV);
110 }
111 }
112
113
114 //Do error concealment using slice copy method
DoErrorConSliceCopy(PWelsDecoderContext pCtx)115 void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
116 int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
117 int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
118 PPicture pDstPic = pCtx->pDec;
119 PPicture pSrcPic = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb;
120 if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
121 pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
122
123 //uint8_t *pDstData[3], *pSrcData[3];
124 bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
125 //Do slice copy late
126 int32_t iMbXyIndex;
127 uint8_t* pSrcData, *pDstData;
128 uint32_t iSrcStride; // = pSrcPic->iLinesize[0];
129 uint32_t iDstStride = pDstPic->iLinesize[0];
130 if (pSrcPic == pDstPic) {
131 WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "DoErrorConSliceCopy()::EC memcpy overlap.");
132 return;
133 }
134 for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
135 for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
136 iMbXyIndex = iMbY * iMbWidth + iMbX;
137 if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
138 pCtx->pDec->iMbEcedNum++;
139 if (pSrcPic != NULL) {
140 iSrcStride = pSrcPic->iLinesize[0];
141 //Y component
142 pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
143 pSrcData = pSrcPic->pData[0] + iMbY * 16 * iSrcStride + iMbX * 16;
144 pCtx->sCopyFunc.pCopyLumaFunc (pDstData, iDstStride, pSrcData, iSrcStride);
145 //U component
146 pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
147 pSrcData = pSrcPic->pData[1] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
148 pCtx->sCopyFunc.pCopyChromaFunc (pDstData, iDstStride / 2, pSrcData, iSrcStride / 2);
149 //V component
150 pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
151 pSrcData = pSrcPic->pData[2] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
152 pCtx->sCopyFunc.pCopyChromaFunc (pDstData, iDstStride / 2, pSrcData, iSrcStride / 2);
153 } else { //pSrcPic == NULL
154 //Y component
155 pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
156 for (int32_t i = 0; i < 16; ++i) {
157 memset (pDstData, 128, 16);
158 pDstData += iDstStride;
159 }
160 //U component
161 pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
162 for (int32_t i = 0; i < 8; ++i) {
163 memset (pDstData, 128, 8);
164 pDstData += iDstStride / 2;
165 }
166 //V component
167 pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
168 for (int32_t i = 0; i < 8; ++i) {
169 memset (pDstData, 128, 8);
170 pDstData += iDstStride / 2;
171 }
172 } //
173 } //!pMbCorrectlyDecodedFlag[iMbXyIndex]
174 } //iMbX
175 } //iMbY
176 }
177
178 //Do error concealment using slice MV copy method
DoMbECMvCopy(PWelsDecoderContext pCtx,PPicture pDec,PPicture pRef,int32_t iMbXy,int32_t iMbX,int32_t iMbY,sMCRefMember * pMCRefMem)179 void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32_t iMbXy, int32_t iMbX, int32_t iMbY,
180 sMCRefMember* pMCRefMem) {
181 if (pDec == pRef) {
182 return; // for protection, shall never go into this logic, error info printed outside.
183 }
184 int16_t iMVs[2];
185 int32_t iMbXInPix = iMbX << 4;
186 int32_t iMbYInPix = iMbY << 4;
187 int32_t iScale0;
188 int32_t iScale1;
189 uint8_t* pDst[3];
190 int32_t iCurrPoc = pDec->iFramePoc;
191 pDst[0] = pDec->pData[0] + iMbXInPix + iMbYInPix * pMCRefMem->iDstLineLuma;
192 pDst[1] = pDec->pData[1] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
193 pDst[2] = pDec->pData[2] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
194 if (pDec->bIdrFlag == true || pCtx->pECRefPic[0] == NULL) {
195 uint8_t* pSrcData;
196 //Y component
197 pSrcData = pMCRefMem->pSrcY + iMbY * 16 * pMCRefMem->iSrcLineLuma + iMbX * 16;
198 pCtx->sCopyFunc.pCopyLumaFunc (pDst[0], pMCRefMem->iDstLineLuma, pSrcData, pMCRefMem->iSrcLineLuma);
199 //U component
200 pSrcData = pMCRefMem->pSrcU + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
201 pCtx->sCopyFunc.pCopyChromaFunc (pDst[1], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
202 //V component
203 pSrcData = pMCRefMem->pSrcV + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
204 pCtx->sCopyFunc.pCopyChromaFunc (pDst[2], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
205 return;
206 }
207
208 if (pCtx->pECRefPic[0]) {
209 if (pCtx->pECRefPic[0] == pRef) {
210 iMVs[0] = pCtx->iECMVs[0][0];
211 iMVs[1] = pCtx->iECMVs[0][1];
212 } else {
213 iScale0 = pCtx->pECRefPic[0]->iFramePoc - iCurrPoc;
214 iScale1 = pRef->iFramePoc - iCurrPoc;
215 iMVs[0] = iScale0 == 0 ? 0 : pCtx->iECMVs[0][0] * iScale1 / iScale0;
216 iMVs[1] = iScale0 == 0 ? 0 : pCtx->iECMVs[0][1] * iScale1 / iScale0;
217 }
218 pMCRefMem->pDstY = pDst[0];
219 pMCRefMem->pDstU = pDst[1];
220 pMCRefMem->pDstV = pDst[2];
221 int32_t iFullMVx = (iMbXInPix << 2) + iMVs[0]; //quarter pixel
222 int32_t iFullMVy = (iMbYInPix << 2) + iMVs[1];
223 // only use to be output pixels to EC;
224 int32_t iPicWidthLeftLimit = 0;
225 int32_t iPicHeightTopLimit = 0;
226 int32_t iPicWidthRightLimit = pMCRefMem->iPicWidth;
227 int32_t iPicHeightBottomLimit = pMCRefMem->iPicHeight;
228 if (pCtx->pSps->bFrameCroppingFlag) {
229 iPicWidthLeftLimit = 0 + pCtx->sFrameCrop.iLeftOffset * 2;
230 iPicWidthRightLimit = (pMCRefMem->iPicWidth - pCtx->sFrameCrop.iRightOffset * 2);
231 iPicHeightTopLimit = 0 + pCtx->sFrameCrop.iTopOffset * 2;
232 iPicHeightBottomLimit = (pMCRefMem->iPicHeight - pCtx->sFrameCrop.iTopOffset * 2);
233 }
234 // further make sure no need to expand picture
235 int32_t iMinLeftOffset = (iPicWidthLeftLimit + 2) * (1 << 2);
236 int32_t iMaxRightOffset = ((iPicWidthRightLimit - 18) * (1 << 2));
237 int32_t iMinTopOffset = (iPicHeightTopLimit + 2) * (1 << 2);
238 int32_t iMaxBottomOffset = ((iPicHeightBottomLimit - 18) * (1 << 2));
239 if (iFullMVx < iMinLeftOffset) {
240 iFullMVx = (iFullMVx >> 2) * (1 << 2);
241 iFullMVx = WELS_MAX (iPicWidthLeftLimit, iFullMVx);
242 } else if (iFullMVx > iMaxRightOffset) {
243 iFullMVx = (iFullMVx >> 2) * (1 << 2);
244 iFullMVx = WELS_MIN (((iPicWidthRightLimit - 16) * (1 << 2)), iFullMVx);
245 }
246 if (iFullMVy < iMinTopOffset) {
247 iFullMVy = (iFullMVy >> 2) * (1 << 2);
248 iFullMVy = WELS_MAX (iPicHeightTopLimit, iFullMVy);
249 } else if (iFullMVy > iMaxBottomOffset) {
250 iFullMVy = (iFullMVy >> 2) * (1 << 2);
251 iFullMVy = WELS_MIN (((iPicHeightBottomLimit - 16) * (1 << 2)), iFullMVy);
252 }
253 iMVs[0] = iFullMVx - (iMbXInPix << 2);
254 iMVs[1] = iFullMVy - (iMbYInPix << 2);
255 BaseMC (pCtx, pMCRefMem, -1, -1, iMbXInPix, iMbYInPix, &pCtx->sMcFunc, 16, 16, iMVs);
256 }
257 return;
258 }
259
GetAvilInfoFromCorrectMb(PWelsDecoderContext pCtx)260 void GetAvilInfoFromCorrectMb (PWelsDecoderContext pCtx) {
261 int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
262 int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
263 bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
264 PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
265 int32_t iInterMbCorrectNum[16];
266 int32_t iMbXyIndex;
267
268 int8_t iRefIdx;
269 memset (pCtx->iECMVs, 0, sizeof (int32_t) * 32);
270 memset (pCtx->pECRefPic, 0, sizeof (PPicture) * 16);
271 memset (iInterMbCorrectNum, 0, sizeof (int32_t) * 16);
272
273 for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
274 for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
275 iMbXyIndex = iMbY * iMbWidth + iMbX;
276 if (pMbCorrectlyDecodedFlag[iMbXyIndex] && IS_INTER (pCurDqLayer->pDec->pMbType[iMbXyIndex])) {
277 uint32_t iMBType = pCurDqLayer->pDec->pMbType[iMbXyIndex];
278 switch (iMBType) {
279 case MB_TYPE_SKIP:
280 case MB_TYPE_16x16:
281 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][0];
282 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][0];
283 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][1];
284 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
285 iInterMbCorrectNum[iRefIdx]++;
286 break;
287 case MB_TYPE_16x8:
288 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][0];
289 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][0];
290 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][1];
291 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
292 iInterMbCorrectNum[iRefIdx]++;
293
294 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][8];
295 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][8][0];
296 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][8][1];
297 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
298 iInterMbCorrectNum[iRefIdx]++;
299 break;
300 case MB_TYPE_8x16:
301 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][0];
302 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][0];
303 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][0][1];
304 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
305 iInterMbCorrectNum[iRefIdx]++;
306
307 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][2];
308 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][2][0];
309 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][2][1];
310 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
311 iInterMbCorrectNum[iRefIdx]++;
312 break;
313 case MB_TYPE_8x8:
314 case MB_TYPE_8x8_REF0: {
315 uint32_t iSubMBType;
316 int32_t i, j, iIIdx, iJIdx;
317
318 for (i = 0; i < 4; i++) {
319 iSubMBType = pCurDqLayer->pSubMbType[iMbXyIndex][i];
320 iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
321 iRefIdx = pCurDqLayer->pDec->pRefIndex[0][iMbXyIndex][iIIdx];
322 pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
323 switch (iSubMBType) {
324 case SUB_MB_TYPE_8x8:
325 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][0];
326 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][1];
327 iInterMbCorrectNum[iRefIdx]++;
328
329 break;
330 case SUB_MB_TYPE_8x4:
331 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][0];
332 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][1];
333
334
335 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + 4][0];
336 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + 4][1];
337 iInterMbCorrectNum[iRefIdx] += 2;
338
339 break;
340 case SUB_MB_TYPE_4x8:
341 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][0];
342 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx][1];
343
344
345 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + 1][0];
346 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + 1][1];
347 iInterMbCorrectNum[iRefIdx] += 2;
348 break;
349 case SUB_MB_TYPE_4x4: {
350 for (j = 0; j < 4; j++) {
351 iJIdx = ((j >> 1) << 2) + (j & 1);
352 pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + iJIdx][0];
353 pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pDec->pMv[0][iMbXyIndex][iIIdx + iJIdx][1];
354 }
355 iInterMbCorrectNum[iRefIdx] += 4;
356 }
357 break;
358 default:
359 break;
360 }
361 }
362 }
363 break;
364 default:
365 break;
366 }
367 } //pMbCorrectlyDecodedFlag[iMbXyIndex]
368 } //iMbX
369 } //iMbY
370 for (int32_t i = 0; i < 16; i++) {
371 if (iInterMbCorrectNum[i]) {
372 pCtx->iECMVs[i][0] = pCtx->iECMVs[i][0] / iInterMbCorrectNum[i];
373 pCtx->iECMVs[i][1] = pCtx->iECMVs[i][1] / iInterMbCorrectNum[i];
374 }
375 }
376 }
377
DoErrorConSliceMVCopy(PWelsDecoderContext pCtx)378 void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx) {
379 int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
380 int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
381 PPicture pDstPic = pCtx->pDec;
382 PPicture pSrcPic = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb;
383
384 bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
385 int32_t iMbXyIndex;
386 uint8_t* pDstData;
387 uint32_t iDstStride = pDstPic->iLinesize[0];
388 sMCRefMember sMCRefMem;
389 if (pSrcPic != NULL) {
390 sMCRefMem.iSrcLineLuma = pSrcPic->iLinesize[0];
391 sMCRefMem.iSrcLineChroma = pSrcPic->iLinesize[1];
392 sMCRefMem.pSrcY = pSrcPic->pData[0];
393 sMCRefMem.pSrcU = pSrcPic->pData[1];
394 sMCRefMem.pSrcV = pSrcPic->pData[2];
395 sMCRefMem.iDstLineLuma = pDstPic->iLinesize[0];
396 sMCRefMem.iDstLineChroma = pDstPic->iLinesize[1];
397 sMCRefMem.iPicWidth = pDstPic->iWidthInPixel;
398 sMCRefMem.iPicHeight = pDstPic->iHeightInPixel;
399 if (pDstPic == pSrcPic) {
400 // output error info, EC will be ignored in DoMbECMvCopy
401 WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "DoErrorConSliceMVCopy()::EC memcpy overlap.");
402 return;
403 }
404 }
405
406 for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
407 for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
408 iMbXyIndex = iMbY * iMbWidth + iMbX;
409 if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
410 pCtx->pDec->iMbEcedNum++;
411 if (pSrcPic != NULL) {
412 DoMbECMvCopy (pCtx, pDstPic, pSrcPic, iMbXyIndex, iMbX, iMbY, &sMCRefMem);
413 } else { //pSrcPic == NULL
414 //Y component
415 pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
416 for (int32_t i = 0; i < 16; ++i) {
417 memset (pDstData, 128, 16);
418 pDstData += iDstStride;
419 }
420 //U component
421 pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
422 for (int32_t i = 0; i < 8; ++i) {
423 memset (pDstData, 128, 8);
424 pDstData += iDstStride / 2;
425 }
426 //V component
427 pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
428 for (int32_t i = 0; i < 8; ++i) {
429 memset (pDstData, 128, 8);
430 pDstData += iDstStride / 2;
431 }
432 } //
433
434 } //!pMbCorrectlyDecodedFlag[iMbXyIndex]
435 } //iMbX
436 } //iMbY
437 }
438
439 //Mark erroneous frame as Ref Pic into DPB
MarkECFrameAsRef(PWelsDecoderContext pCtx)440 int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) {
441 int32_t iRet = WelsMarkAsRef (pCtx);
442 // Under EC mode, the ERR_INFO_DUPLICATE_FRAME_NUM does not need to be process
443 if (iRet != ERR_NONE) {
444 return iRet;
445 }
446 ExpandReferencingPicture (pCtx->pDec->pData, pCtx->pDec->iWidthInPixel, pCtx->pDec->iHeightInPixel,
447 pCtx->pDec->iLinesize,
448 pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
449
450 return ERR_NONE;
451 }
452
NeedErrorCon(PWelsDecoderContext pCtx)453 bool NeedErrorCon (PWelsDecoderContext pCtx) {
454 bool bNeedEC = false;
455 int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
456 for (int32_t i = 0; i < iMbNum; ++i) {
457 if (!pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag[i]) {
458 bNeedEC = true;
459 break;
460 }
461 }
462 return bNeedEC;
463 }
464
465 // ImplementErrorConceal
466 // Do actual error concealment
ImplementErrorCon(PWelsDecoderContext pCtx)467 void ImplementErrorCon (PWelsDecoderContext pCtx) {
468 if (ERROR_CON_DISABLE == pCtx->pParam->eEcActiveIdc) {
469 pCtx->iErrorCode |= dsBitstreamError;
470 return;
471 } else if ((ERROR_CON_FRAME_COPY == pCtx->pParam->eEcActiveIdc)
472 || (ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)) {
473 DoErrorConFrameCopy (pCtx);
474 } else if ((ERROR_CON_SLICE_COPY == pCtx->pParam->eEcActiveIdc)
475 || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
476 || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)) {
477 DoErrorConSliceCopy (pCtx);
478 } else if ((ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
479 || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)) {
480 GetAvilInfoFromCorrectMb (pCtx);
481 DoErrorConSliceMVCopy (pCtx);
482 } //TODO add other EC methods here in the future
483 pCtx->iErrorCode |= dsDataErrorConcealed;
484 pCtx->pDec->bIsComplete = false; // Set complete flag to false after do EC.
485 }
486
487 } // namespace WelsDec
488