Do error concealment using slice MV copy method
| 177 | |
| 178 | //Do error concealment using slice MV copy method |
| 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)); |
no test coverage detected