ref: 063709c92e8bafe467d384f564afbdc6b66eb39a
dir: /codec/decoder/core/src/rec_mb.cpp/
/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * \file rec_mb.c * * \brief implementation for all macroblock decoding process after mb syntax parsing and residual decoding with cavlc. * * \date 3/18/2009 Created * ************************************************************************************* */ #include <memory.h> #include "macros.h" #include "rec_mb.h" #include "parse_mb_syn_cavlc.h" #include "get_intra_predictor.h" #include "decode_mb_aux.h" #include "decode_slice.h" namespace WelsDec { void_t WelsFillRecNeededMbInfo(PWelsDecoderContext pCtx, bool_t bOutput, PDqLayer pCurLayer) { PPicture pCurPic = pCtx->pDec; int32_t iLumaStride = pCurPic->iLinesize[0]; int32_t iChromaStride = pCurPic->iLinesize[1]; int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; pCurLayer->iLumaStride= iLumaStride; pCurLayer->iChromaStride= iChromaStride; if(bOutput) { pCurLayer->pPred[0] = pCurPic->pData[0] + ((iMbY * iLumaStride + iMbX)<<4); pCurLayer->pPred[1] = pCurPic->pData[1] + ((iMbY * iChromaStride + iMbX)<<3); pCurLayer->pPred[2] = pCurPic->pData[2] + ((iMbY * iChromaStride + iMbX)<<3); } } int32_t RecI4x4Mb(int32_t iMBXY, PWelsDecoderContext pCtx, int16_t *pScoeffLevel, PDqLayer pDqLayer) { RecI4x4Luma(iMBXY, pCtx, pScoeffLevel, pDqLayer); RecI4x4Chroma( iMBXY, pCtx, pScoeffLevel, pDqLayer); return ERR_NONE; } int32_t RecI4x4Luma(int32_t iMBXY, PWelsDecoderContext pCtx, int16_t *pScoeffLevel, PDqLayer pDqLayer) { /*****get local variable from outer variable********/ /*prediction info*/ uint8_t *pPred = pDqLayer->pPred[0]; int32_t iLumaStride = pDqLayer->iLumaStride; int32_t *pBlockOffset = pCtx->iDecBlockOffsetArray; PGetIntraPredFunc *pGetI4x4LumaPredFunc = pCtx->pGetI4x4LumaPredFunc; int8_t *pIntra4x4PredMode = pDqLayer->pIntra4x4FinalMode[iMBXY]; int16_t *pRS = pScoeffLevel; /*itransform info*/ PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc; /*************local variable********************/ uint8_t i = 0; /*************real process*********************/ for(i=0; i<16; i++) { uint8_t *pPredI4x4 = pPred + pBlockOffset[i]; uint8_t uiMode= pIntra4x4PredMode[g_kuiScan4[i]]; pGetI4x4LumaPredFunc[uiMode](pPredI4x4, iLumaStride); if ( pDqLayer->pNzc[iMBXY][g_kuiMbNonZeroCountIdx[i]] ) { int16_t *pRSI4x4 = &pRS[i<<4]; pIdctResAddPredFunc(pPredI4x4, iLumaStride, pRSI4x4); } } return ERR_NONE; } int32_t RecI4x4Chroma(int32_t iMBXY, PWelsDecoderContext pCtx, int16_t *pScoeffLevel, PDqLayer pDqLayer) { int32_t iChromaStride = pCtx->pCurDqLayer->iCsStride[1]; int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY]; PGetIntraPredFunc *pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc; uint8_t *pPred = pDqLayer->pPred[1]; pGetIChromaPredFunc[iChromaPredMode](pPred, iChromaStride); pPred = pDqLayer->pPred[2]; pGetIChromaPredFunc[iChromaPredMode](pPred, iChromaStride); RecChroma(iMBXY, pCtx, pScoeffLevel, pDqLayer); return ERR_NONE; } int32_t RecI16x16Mb(int32_t iMBXY, PWelsDecoderContext pCtx, int16_t *pScoeffLevel, PDqLayer pDqLayer) { /*decoder use, encoder no use*/ int8_t iI16x16PredMode = pDqLayer->pIntraPredMode[iMBXY][7]; int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY]; PGetIntraPredFunc *pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc; PGetIntraPredFunc *pGetI16x16LumaPredFunc = pCtx->pGetI16x16LumaPredFunc; int32_t iUVStride = pCtx->pCurDqLayer->iCsStride[1]; /*common use by decoder&encoder*/ int32_t iYStride = pDqLayer->iLumaStride; int32_t *pBlockOffset = pCtx->iDecBlockOffsetArray; int16_t *pRS = pScoeffLevel; uint8_t *pPred = pDqLayer->pPred[0]; PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc; uint8_t i = 0; /*decode i16x16 y*/ pGetI16x16LumaPredFunc[iI16x16PredMode](pPred, iYStride); /*1 mb is divided 16 4x4_block to idct*/ for(i=0; i<16; i++) { int16_t *pRSI4x4 = pRS + (i<<4); uint8_t *pPredI4x4 = pPred + pBlockOffset[i]; if ( pDqLayer->pNzc[iMBXY][g_kuiMbNonZeroCountIdx[i]] || pRSI4x4[0] ) { pIdctResAddPredFunc(pPredI4x4, iYStride, pRSI4x4); } } /*decode intra mb cb&cr*/ pPred = pDqLayer->pPred[1]; pGetIChromaPredFunc[iChromaPredMode](pPred, iUVStride); pPred = pDqLayer->pPred[2]; pGetIChromaPredFunc[iChromaPredMode](pPred, iUVStride); RecChroma(iMBXY, pCtx, pScoeffLevel,pDqLayer); return ERR_NONE; } typedef struct TagMCRefMember { uint8_t* pDstY; uint8_t* pDstU; uint8_t* pDstV; uint8_t* pSrcY; uint8_t* pSrcU; uint8_t* pSrcV; int32_t iSrcLineLuma; int32_t iSrcLineChroma; int32_t iDstLineLuma; int32_t iDstLineChroma; int32_t iPicWidth; int32_t iPicHeight; }sMCRefMember; //according to current 8*8 block ref_index to gain reference picture static inline void_t GetRefPic(sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx, int8_t* pRefIdxList, int32_t iIndex) { PPicture pRefPic; int8_t iRefIdx = pRefIdxList[iIndex]; pRefPic = pCtx->sRefPic.pRefList[LIST_0][iRefIdx]; pMCRefMem->iSrcLineLuma = pRefPic->iLinesize[0]; pMCRefMem->iSrcLineChroma = pRefPic->iLinesize[1]; pMCRefMem->pSrcY = pRefPic->pData[0]; pMCRefMem->pSrcU = pRefPic->pData[1]; pMCRefMem->pSrcV = pRefPic->pData[2]; } #ifndef MC_FLOW_SIMPLE_JUDGE #define MC_FLOW_SIMPLE_JUDGE 1 #endif //MC_FLOW_SIMPLE_JUDGE static inline void_t BaseMC(sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc, int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) { int32_t iExpandWidth = PADDING_LENGTH; int32_t iExpandHeight = PADDING_LENGTH; int16_t iMVX = iMVs[0] >> 2; int16_t iMVY = iMVs[1] >> 2; int32_t iMVOffsetLuma = iMVX + iMVY * pMCRefMem->iSrcLineLuma; int32_t iMVOffsetChroma = (iMVX>>1) + (iMVY>>1) * pMCRefMem->iSrcLineChroma; int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel int32_t iFullMVy = (iYOffset << 2) + iMVs[1]; int32_t iIntMVx = iFullMVx >> 2;//integer pixel int32_t iIntMVy = iFullMVy >> 2; int32_t iSrcPixOffsetLuma = iXOffset + iYOffset * pMCRefMem->iSrcLineLuma; int32_t iSrcPixOffsetChroma = (iXOffset>>1) + (iYOffset>>1) * pMCRefMem->iSrcLineChroma; int32_t iBlkWidthChroma = iBlkWidth >> 1; int32_t iBlkHeightChroma = iBlkHeight >> 1; int32_t iPicWidthChroma = pMCRefMem->iPicWidth >> 1; int32_t iPicHeightChroma = pMCRefMem->iPicHeight >> 1; //the offset only for luma padding if MV violation as there was 5-tap (-2, -1, 0, 1, 2) filter for luma (horizon and vertical) int32_t iPadOffset = 2 + (pMCRefMem->iSrcLineLuma << 1); //(-2, -2) pixel location as the starting point uint8_t* pSrcY = pMCRefMem->pSrcY + iSrcPixOffsetLuma; uint8_t* pSrcU = pMCRefMem->pSrcU + iSrcPixOffsetChroma; uint8_t* pSrcV = pMCRefMem->pSrcV + iSrcPixOffsetChroma; uint8_t* pDstY = pMCRefMem->pDstY; uint8_t* pDstU = pMCRefMem->pDstU; uint8_t* pDstV = pMCRefMem->pDstV; bool_t bExpand = false; FORCE_STACK_ALIGN_1D( uint8_t, uiExpandBuf, (PADDING_LENGTH+6)*(PADDING_LENGTH+6), 16 ); if (iFullMVx & 0x07) { iExpandWidth -= 3; } if (iFullMVy & 0x07) { iExpandHeight -= 3; } #ifdef MC_FLOW_SIMPLE_JUDGE if (iIntMVx < -iExpandWidth || iIntMVy < -iExpandHeight || iIntMVx + iBlkWidth > pMCRefMem->iPicWidth - 1 + iExpandWidth || iIntMVy + iBlkHeight > pMCRefMem->iPicHeight - 1 + iExpandHeight) #else if (iIntMVx < -iExpandWidth || iIntMVy < -iExpandHeight || iIntMVx + PADDING_LENGTH > pMCRefMem->iPicWidth + iExpandWidth || iIntMVy + PADDING_LENGTH > pMCRefMem->iPicHeight + iExpandHeight) #endif { FillBufForMc(uiExpandBuf, 21, pSrcY, pMCRefMem->iSrcLineLuma, iMVOffsetLuma-iPadOffset, iBlkWidth+5, iBlkHeight+5, iIntMVx-2, iIntMVy-2, pMCRefMem->iPicWidth, pMCRefMem->iPicHeight); pMCFunc->pMcLumaFunc(uiExpandBuf+44, 21, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth, iBlkHeight);//44=2+2*21 bExpand = true; } else { pSrcY += iMVOffsetLuma; pMCFunc->pMcLumaFunc(pSrcY, pMCRefMem->iSrcLineLuma, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth, iBlkHeight); } if (bExpand) { FillBufForMc(uiExpandBuf, 21, pSrcU, pMCRefMem->iSrcLineChroma, iMVOffsetChroma, iBlkWidthChroma+1, iBlkHeightChroma+1, iFullMVx>>3, iFullMVy>>3, iPicWidthChroma, iPicHeightChroma); pMCFunc->pMcChromaFunc(uiExpandBuf, 21, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma, iBlkHeightChroma); FillBufForMc(uiExpandBuf, 21, pSrcV, pMCRefMem->iSrcLineChroma, iMVOffsetChroma, iBlkWidthChroma+1, iBlkHeightChroma+1, iFullMVx>>3, iFullMVy>>3, iPicWidthChroma, iPicHeightChroma); pMCFunc->pMcChromaFunc(uiExpandBuf, 21, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma, iBlkHeightChroma); } else { pSrcU += iMVOffsetChroma; pSrcV += iMVOffsetChroma; pMCFunc->pMcChromaFunc(pSrcU, pMCRefMem->iSrcLineChroma, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma, iBlkHeightChroma); pMCFunc->pMcChromaFunc(pSrcV, pMCRefMem->iSrcLineChroma, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy, iBlkWidthChroma, iBlkHeightChroma); } } void_t GetInterPred(uint8_t *pPredY, uint8_t *pPredCb, uint8_t *pPredCr, PWelsDecoderContext pCtx) { sMCRefMember pMCRefMem; PDqLayer pCurDqLayer = pCtx->pCurDqLayer; SMcFunc* pMCFunc = &pCtx->sMcFunc; int32_t iMBXY = pCurDqLayer->iMbXyIndex; int16_t iMVs[2] = {0}; int32_t iMBType = pCurDqLayer->pMbType[iMBXY]; int32_t iMBOffsetX = pCurDqLayer->iMbX << 4; int32_t iMBOffsetY = pCurDqLayer->iMbY << 4; int32_t iDstLineLuma = pCtx->pDec->iLinesize[0]; int32_t iDstLineChroma = pCtx->pDec->iLinesize[1]; int32_t iBlk8X, iBlk8Y, iBlk4X, iBlk4Y, i, j, iIIdx, iJIdx; pMCRefMem.iPicWidth = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbWidth<<4); pMCRefMem.iPicHeight = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbHeight<<4); pMCRefMem.pDstY = pPredY; pMCRefMem.pDstU = pPredCb; pMCRefMem.pDstV = pPredCr; pMCRefMem.iDstLineLuma = iDstLineLuma; pMCRefMem.iDstLineChroma = iDstLineChroma; switch(iMBType) { case MB_TYPE_SKIP: case MB_TYPE_16x16: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1]; GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0 ); BaseMC(&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs); break; case MB_TYPE_16x8: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1]; GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0 ); BaseMC(&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 8, iMVs); iMVs[0] = pCurDqLayer->pMv[0][iMBXY][8][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][8][1]; GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 8 ); pMCRefMem.pDstY = pPredY + (iDstLineLuma << 3); pMCRefMem.pDstU = pPredCb + (iDstLineChroma << 2); pMCRefMem.pDstV = pPredCr + (iDstLineChroma << 2); BaseMC(&pMCRefMem, iMBOffsetX, iMBOffsetY+8, pMCFunc, 16, 8, iMVs); break; case MB_TYPE_8x16: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1]; GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0 ); BaseMC(&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 8, 16, iMVs); iMVs[0] = pCurDqLayer->pMv[0][iMBXY][2][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][2][1]; GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 2 ); pMCRefMem.pDstY = pPredY + 8; pMCRefMem.pDstU = pPredCb + 4; pMCRefMem.pDstV = pPredCr + 4; BaseMC(&pMCRefMem, iMBOffsetX+8, iMBOffsetY, pMCFunc, 8, 16, iMVs); break; case MB_TYPE_8x8: case MB_TYPE_8x8_REF0: { uint32_t iSubMBType; int32_t iXOffset, iYOffset; uint8_t *pDstY, *pDstU, *pDstV; for (i = 0; i < 4; i++) { iSubMBType = pCurDqLayer->pSubMbType[iMBXY][i]; iBlk8X = (i&1) << 3; iBlk8Y = (i>>1) << 3; iXOffset = iMBOffsetX + iBlk8X; iYOffset = iMBOffsetY + iBlk8Y; iIIdx = ((i>>1)<<3) +((i&1)<<1); GetRefPic( &pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], iIIdx ); pDstY = pPredY + iBlk8X + iBlk8Y * iDstLineLuma; pDstU = pPredCb + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma; pDstV = pPredCr + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma; pMCRefMem.pDstY = pDstY; pMCRefMem.pDstU = pDstU; pMCRefMem.pDstV = pDstV; switch(iSubMBType) { case SUB_MB_TYPE_8x8: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1]; BaseMC( &pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs ); break; case SUB_MB_TYPE_8x4: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1]; BaseMC(&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs); iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx+4][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx+4][1]; pMCRefMem.pDstY += (iDstLineLuma << 2); pMCRefMem.pDstU += (iDstLineChroma << 1); pMCRefMem.pDstV += (iDstLineChroma << 1); BaseMC(&pMCRefMem, iXOffset, iYOffset+4, pMCFunc, 8, 4, iMVs); break; case SUB_MB_TYPE_4x8: iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1]; BaseMC(&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs); iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx+1][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx+1][1]; pMCRefMem.pDstY += 4; pMCRefMem.pDstU += 2; pMCRefMem.pDstV += 2; BaseMC(&pMCRefMem, iXOffset+4, iYOffset, pMCFunc, 4, 8, iMVs); break; case SUB_MB_TYPE_4x4: { for (j = 0; j < 4; j++) { int32_t iUVLineStride; iJIdx = ((j>>1)<<2) + (j&1); iBlk4X = (j&1) << 2; iBlk4Y = (j>>1) << 2; iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma; pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma; pMCRefMem.pDstU = pDstU + iUVLineStride; pMCRefMem.pDstV = pDstV + iUVLineStride; iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx+iJIdx][0]; iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx+iJIdx][1]; BaseMC(&pMCRefMem, iXOffset+iBlk4X, iYOffset+iBlk4Y, pMCFunc, 4, 4, iMVs); } } break; default: break; } } } break; default: break; } } int32_t RecChroma(int32_t iMBXY, PWelsDecoderContext pCtx, int16_t *pScoeffLevel, PDqLayer pDqLayer) { int32_t iChromaStride = pCtx->pCurDqLayer->iCsStride[1]; PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc; uint8_t i=0, j=0; uint8_t uiCbpC = pDqLayer->pCbp[iMBXY] >> 4; if ( 1 == uiCbpC || 2 == uiCbpC ) { WelsChromaDcIdct( pScoeffLevel + 256 ); // 256 = 16*16 WelsChromaDcIdct( pScoeffLevel + 320 ); // 256 = 16*16 for(i=0; i<2; i++) { int16_t *pRS = pScoeffLevel + 256 + (i << 6); uint8_t *pPred = pDqLayer->pPred[i+1]; int32_t *pBlockOffset = i==0 ? &pCtx->iDecBlockOffsetArray[16] : &pCtx->iDecBlockOffsetArray[20]; /*1 chroma is divided 4 4x4_block to idct*/ for(j=0; j<4; j++) { int16_t *pRSI4x4 = &pRS[j<<4]; uint8_t *pPredI4x4 = pPred + pBlockOffset[j]; if ( pDqLayer->pNzc[iMBXY][g_kuiMbNonZeroCountIdx[16+(i<<2)+j]] || pRSI4x4[0] ) { pIdctResAddPredFunc(pPredI4x4, iChromaStride, pRSI4x4); } } } } return ERR_NONE; } void_t FillBufForMc(uint8_t *pBuf, int32_t iBufStride, uint8_t *pSrc, int32_t iSrcStride, int32_t iSrcOffset, int32_t iBlockWidth, int32_t iBlockHeight, int32_t iSrcX, int32_t iSrcY, int32_t iPicWidth, int32_t iPicHeight) { int32_t iY; int32_t iStartY, iStartX, iEndY, iEndX; int32_t iOffsetAdj = 0; int32_t iAddrSrc, iAddrBuf; int32_t iNum, iNum1; uint8_t *pBufSrc, *pBufDst; uint8_t *pBufSrc1, *pBufDst1; if( iSrcY >= iPicHeight ) { iOffsetAdj += ( iPicHeight - 1 - iSrcY ) * iSrcStride; iSrcY = iPicHeight - 1; } else if( iSrcY <= -iBlockHeight ) { iOffsetAdj += ( 1 - iBlockHeight - iSrcY ) * iSrcStride; iSrcY = 1 - iBlockHeight; } if( iSrcX >= iPicWidth ) { iOffsetAdj += ( iPicWidth - 1 - iSrcX ); iSrcX = iPicWidth - 1; } else if( iSrcX <= -iBlockWidth ) { iOffsetAdj += ( 1 - iBlockWidth - iSrcX ); iSrcX = 1 - iBlockWidth; } iOffsetAdj += iSrcOffset; #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) > (b) ? (b) : (a)) iStartY = MAX(0, -iSrcY); iStartX = MAX(0, -iSrcX); iEndY = MIN(iBlockHeight, iPicHeight - iSrcY); iEndX = MIN(iBlockWidth, iPicWidth - iSrcX); // copy existing part iAddrSrc = iStartX + iStartY * iSrcStride; iAddrBuf = iStartX + iStartY * iBufStride; iNum = iEndX - iStartX; for( iY = iStartY; iY < iEndY; iY++ ) { memcpy( pBuf + iAddrBuf, pSrc + iOffsetAdj + iAddrSrc, iNum ); iAddrSrc += iSrcStride; iAddrBuf += iBufStride; } //top pBufSrc = pBuf + iStartX + iStartY * iBufStride; pBufDst = pBuf + iStartX; iNum = iEndX - iStartX; for( iY = 0; iY < iStartY; iY++ ) { memcpy( pBufDst, pBufSrc, iNum ); pBufDst += iBufStride; } //bottom pBufSrc = pBuf + iStartX + ( iEndY - 1 ) * iBufStride; pBufDst = pBuf + iStartX + iEndY * iBufStride; iNum = iEndX - iStartX; for( iY = iEndY; iY < iBlockHeight; iY++ ) { memcpy( pBufDst, pBufSrc, iNum ); pBufDst += iBufStride; } pBufSrc = pBuf + iStartX; pBufDst = pBuf; iNum = iStartX; pBufSrc1 = pBuf + iEndX - 1; pBufDst1 = pBuf + iEndX; iNum1 = iBlockWidth - iEndX; for( iY=0; iY<iBlockHeight; iY++ ) { //left memset( pBufDst, pBufSrc[0], iNum ); pBufDst += iBufStride; pBufSrc += iBufStride; //right memset( pBufDst1, pBufSrc1[0], iNum1 ); pBufDst1 += iBufStride; pBufSrc1 += iBufStride; } } } // namespace WelsDec