/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2012, ITU/ISO/IEC * 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. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * 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 TComPrediction.cpp \brief prediction class */ #include #include "TComPrediction.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constructor / destructor / initialize // ==================================================================================================================== TComPrediction::TComPrediction() : m_pLumaRecBuffer(0) , m_iLumaRecStride(0) { m_piYuvExt = NULL; } TComPrediction::~TComPrediction() { delete[] m_piYuvExt; m_acYuvPred[0].destroy(); m_acYuvPred[1].destroy(); m_cYuvPredTemp.destroy(); if( m_pLumaRecBuffer ) { delete [] m_pLumaRecBuffer; } Int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { m_filteredBlock[i][j].destroy(); } m_filteredBlockTmp[i].destroy(); } } Void TComPrediction::initTempBuff() { if( m_piYuvExt == NULL ) { Int extWidth = g_uiMaxCUWidth + 16; Int extHeight = g_uiMaxCUHeight + 1; Int i, j; for (i = 0; i < 4; i++) { m_filteredBlockTmp[i].create(extWidth, extHeight + 7); for (j = 0; j < 4; j++) { m_filteredBlock[i][j].create(extWidth, extHeight); } } m_iYuvExtHeight = ((g_uiMaxCUHeight + 2) << 4); m_iYuvExtStride = ((g_uiMaxCUWidth + 8) << 4); m_piYuvExt = new Int[ m_iYuvExtStride * m_iYuvExtHeight ]; // new structure m_acYuvPred[0] .create( g_uiMaxCUWidth, g_uiMaxCUHeight ); m_acYuvPred[1] .create( g_uiMaxCUWidth, g_uiMaxCUHeight ); m_cYuvPredTemp.create( g_uiMaxCUWidth, g_uiMaxCUHeight ); } if (m_iLumaRecStride != (g_uiMaxCUWidth>>1) + 1) { m_iLumaRecStride = (g_uiMaxCUWidth>>1) + 1; if (!m_pLumaRecBuffer) { m_pLumaRecBuffer = new Pel[ m_iLumaRecStride * m_iLumaRecStride ]; } } Int shift = g_uiBitDepth + g_uiBitIncrement + 4; for( Int i = 32; i < 64; i++ ) { m_uiaShift[i-32] = ( ( 1 << shift ) + i/2 ) / i; } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== // Function for calculating DC value of the reference samples used in Intra prediction Pel TComPrediction::predIntraGetPredValDC( Int* pSrc, Int iSrcStride, UInt iWidth, UInt iHeight, Bool bAbove, Bool bLeft ) { Int iInd, iSum = 0; Pel pDcVal; if (bAbove) { for (iInd = 0;iInd < iWidth;iInd++) { iSum += pSrc[iInd-iSrcStride]; } } if (bLeft) { for (iInd = 0;iInd < iHeight;iInd++) { iSum += pSrc[iInd*iSrcStride-1]; } } if (bAbove && bLeft) { pDcVal = (iSum + iWidth) / (iWidth + iHeight); } else if (bAbove) { pDcVal = (iSum + iWidth/2) / iWidth; } else if (bLeft) { pDcVal = (iSum + iHeight/2) / iHeight; } else { pDcVal = pSrc[-1]; // Default DC value already calculated and placed in the prediction array if no neighbors are available } return pDcVal; } // Function for deriving the angular Intra predictions /** Function for deriving the simplified angular intra predictions. * \param pSrc pointer to reconstructed sample array * \param srcStride the stride of the reconstructed sample array * \param rpDst reference to pointer for the prediction sample array * \param dstStride the stride of the prediction sample array * \param width the width of the block * \param height the height of the block * \param dirMode the intra prediction mode index * \param blkAboveAvailable boolean indication if the block above is available * \param blkLeftAvailable boolean indication if the block to the left is available * * This function derives the prediction samples for the angular mode based on the prediction direction indicated by * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and * the reference row above the block in the case of vertical prediction or displacement of the rightmost column * of the block and reference column left from the block in the case of the horizontal prediction. The displacement * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples, * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken * from the extended main reference. */ Void TComPrediction::xPredIntraAng( Int* pSrc, Int srcStride, Pel*& rpDst, Int dstStride, UInt width, UInt height, UInt dirMode, Bool blkAboveAvailable, Bool blkLeftAvailable, Bool bFilter ) { Int k,l; Int blkSize = width; Pel* pDst = rpDst; // Map the mode index to main prediction direction and angle assert( dirMode > 0 ); //no planar Bool modeDC = dirMode < 2; Bool modeHor = !modeDC && (dirMode < 18); Bool modeVer = !modeDC && !modeHor; Int intraPredAngle = modeVer ? (Int)dirMode - VER_IDX : modeHor ? -((Int)dirMode - HOR_IDX) : 0; Int absAng = abs(intraPredAngle); Int signAng = intraPredAngle < 0 ? -1 : 1; // Set bitshifts and scale the angle parameter to block size Int angTable[9] = {0, 2, 5, 9, 13, 17, 21, 26, 32}; Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle Int invAngle = invAngTable[absAng]; absAng = angTable[absAng]; intraPredAngle = signAng * absAng; // Do the DC prediction if (modeDC) { Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height, blkAboveAvailable, blkLeftAvailable); for (k=0;kblkSize*intraPredAngle>>5; k--) { invAngleSum += invAngle; refMain[k] = refSide[invAngleSum>>8]; } } else { for (k=0;k<2*blkSize+1;k++) { refAbove[k] = pSrc[k-srcStride-1]; } for (k=0;k<2*blkSize+1;k++) { refLeft[k] = pSrc[(k-1)*srcStride-1]; } refMain = modeVer ? refAbove : refLeft; refSide = modeVer ? refLeft : refAbove; } if (intraPredAngle == 0) { for (k=0;k> 1) ); } } } else { Int deltaPos=0; Int deltaInt; Int deltaFract; Int refMainIndex; for (k=0;k> 5; deltaFract = deltaPos & (32 - 1); if (deltaFract) { // Do linear filtering for (l=0;l> 5 ); } } else { // Just copy the integer samples for (l=0;l= 0 ); // 4x 4 assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128 assert( iWidth == iHeight ); ptrSrc = pcTComPattern->getPredictorPtr( uiDirMode, g_aucConvertToBit[ iWidth ] + 2, m_piYuvExt ); // get starting pixel in block Int sw = 2 * iWidth + 1; // Create the prediction if ( uiDirMode == PLANAR_IDX ) { xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight ); } else { xPredIntraAng( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode, bAbove, bLeft, true ); if( (uiDirMode == DC_IDX ) && bAbove && bLeft ) { xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight); } } } // Angular chroma Void TComPrediction::predIntraChromaAng( TComPattern* pcTComPattern, Int* piSrc, UInt uiDirMode, Pel* piPred, UInt uiStride, Int iWidth, Int iHeight, TComDataCU* pcCU, Bool bAbove, Bool bLeft ) { Pel *pDst = piPred; Int *ptrSrc = piSrc; // get starting pixel in block Int sw = 2 * iWidth + 1; if ( uiDirMode == PLANAR_IDX ) { xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight ); } else { // Create the prediction xPredIntraAng( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode, bAbove, bLeft, false ); } } /** Function for checking identical motion. * \param TComDataCU* pcCU * \param UInt PartAddr */ Bool TComPrediction::xCheckIdenticalMotion ( TComDataCU* pcCU, UInt PartAddr ) { if( pcCU->getSlice()->isInterB() && !pcCU->getSlice()->getPPS()->getWPBiPred() ) { if( pcCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx(PartAddr) >= 0 && pcCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx(PartAddr) >= 0) { Int RefPOCL0 = pcCU->getSlice()->getRefPic(REF_PIC_LIST_0, pcCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx(PartAddr))->getPOC(); Int RefPOCL1 = pcCU->getSlice()->getRefPic(REF_PIC_LIST_1, pcCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx(PartAddr))->getPOC(); if(RefPOCL0 == RefPOCL1 && pcCU->getCUMvField(REF_PIC_LIST_0)->getMv(PartAddr) == pcCU->getCUMvField(REF_PIC_LIST_1)->getMv(PartAddr)) { return true; } } } return false; } #if INTRA_BL && !NO_RESIDUAL_FLAG_FOR_BLPRED Void TComPrediction::getBaseBlk( TComDataCU* pcCU, TComYuv* pcYuvPred, Int iPartAddr, Int iWidth, Int iHeight ) { pcCU->getBaseLumaBlk( iWidth, iHeight, iPartAddr, pcYuvPred->getLumaAddr( iPartAddr ), pcYuvPred->getStride() ); pcCU->getBaseChromaBlk( iWidth >> 1, iHeight >> 1, iPartAddr, pcYuvPred->getCbAddr( iPartAddr ), pcYuvPred->getCStride(), 0 ); pcCU->getBaseChromaBlk( iWidth >> 1, iHeight >> 1, iPartAddr, pcYuvPred->getCrAddr( iPartAddr ), pcYuvPred->getCStride(), 1 ); } #endif Void TComPrediction::motionCompensation ( TComDataCU* pcCU, TComYuv* pcYuvPred, RefPicList eRefPicList, Int iPartIdx ) { Int iWidth; Int iHeight; UInt uiPartAddr; if ( iPartIdx >= 0 ) { pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight ); if ( eRefPicList != REF_PIC_LIST_X ) { if( pcCU->getSlice()->getPPS()->getUseWP()) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx, true ); } else { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx ); } if ( pcCU->getSlice()->getPPS()->getUseWP() ) { xWeightedPredictionUni( pcCU, pcYuvPred, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx ); } } else { if ( xCheckIdenticalMotion( pcCU, uiPartAddr ) ) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred, iPartIdx ); } else { xPredInterBi (pcCU, uiPartAddr, iWidth, iHeight, pcYuvPred, iPartIdx ); } } return; } for ( iPartIdx = 0; iPartIdx < pcCU->getNumPartInter(); iPartIdx++ ) { pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight ); if ( eRefPicList != REF_PIC_LIST_X ) { if( pcCU->getSlice()->getPPS()->getUseWP()) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx, true ); } else { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx ); } if ( pcCU->getSlice()->getPPS()->getUseWP() ) { xWeightedPredictionUni( pcCU, pcYuvPred, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, iPartIdx ); } } else { if ( xCheckIdenticalMotion( pcCU, uiPartAddr ) ) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred, iPartIdx ); } else { xPredInterBi (pcCU, uiPartAddr, iWidth, iHeight, pcYuvPred, iPartIdx ); } } } return; } Void TComPrediction::xPredInterUni ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, RefPicList eRefPicList, TComYuv*& rpcYuvPred, Int iPartIdx, Bool bi ) { Int iRefIdx = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr ); assert (iRefIdx >= 0); TComMv cMv = pcCU->getCUMvField( eRefPicList )->getMv( uiPartAddr ); pcCU->clipMv(cMv); xPredInterLumaBlk ( pcCU, pcCU->getSlice()->getRefPic( eRefPicList, iRefIdx )->getPicYuvRec(), uiPartAddr, &cMv, iWidth, iHeight, rpcYuvPred, bi ); xPredInterChromaBlk( pcCU, pcCU->getSlice()->getRefPic( eRefPicList, iRefIdx )->getPicYuvRec(), uiPartAddr, &cMv, iWidth, iHeight, rpcYuvPred, bi ); } Void TComPrediction::xPredInterBi ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, TComYuv*& rpcYuvPred, Int iPartIdx ) { TComYuv* pcMbYuv; Int iRefIdx[2] = {-1, -1}; for ( Int iRefList = 0; iRefList < 2; iRefList++ ) { RefPicList eRefPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); iRefIdx[iRefList] = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr ); if ( iRefIdx[iRefList] < 0 ) { continue; } assert( iRefIdx[iRefList] < pcCU->getSlice()->getNumRefIdx(eRefPicList) ); pcMbYuv = &m_acYuvPred[iRefList]; if( pcCU->getCUMvField( REF_PIC_LIST_0 )->getRefIdx( uiPartAddr ) >= 0 && pcCU->getCUMvField( REF_PIC_LIST_1 )->getRefIdx( uiPartAddr ) >= 0 ) { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv, iPartIdx, true ); } else { if ( ( pcCU->getSlice()->getPPS()->getUseWP() && pcCU->getSlice()->getSliceType() == P_SLICE ) || ( pcCU->getSlice()->getPPS()->getWPBiPred() && pcCU->getSlice()->getSliceType() == B_SLICE ) ) { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv, iPartIdx, true ); } else { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv, iPartIdx ); } } } if ( pcCU->getSlice()->getPPS()->getWPBiPred() && pcCU->getSlice()->getSliceType() == B_SLICE ) { xWeightedPredictionBi( pcCU, &m_acYuvPred[0], &m_acYuvPred[1], iRefIdx[0], iRefIdx[1], uiPartAddr, iWidth, iHeight, rpcYuvPred ); } else if ( pcCU->getSlice()->getPPS()->getUseWP() && pcCU->getSlice()->getSliceType() == P_SLICE ) { xWeightedPredictionUni( pcCU, &m_acYuvPred[0], uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, rpcYuvPred, iPartIdx ); } else { xWeightedAverage( pcCU, &m_acYuvPred[0], &m_acYuvPred[1], iRefIdx[0], iRefIdx[1], uiPartAddr, iWidth, iHeight, rpcYuvPred ); } } /** * \brief Generate motion-compensated luma block * * \param cu Pointer to current CU * \param refPic Pointer to reference picture * \param partAddr Address of block within CU * \param mv Motion vector * \param width Width of block * \param height Height of block * \param dstPic Pointer to destination picture * \param bi Flag indicating whether bipred is used */ Void TComPrediction::xPredInterLumaBlk( TComDataCU *cu, TComPicYuv *refPic, UInt partAddr, TComMv *mv, Int width, Int height, TComYuv *&dstPic, Bool bi ) { Int refStride = refPic->getStride(); Int refOffset = ( mv->getHor() >> 2 ) + ( mv->getVer() >> 2 ) * refStride; Pel *ref = refPic->getLumaAddr( cu->getAddr(), cu->getZorderIdxInCU() + partAddr ) + refOffset; Int dstStride = dstPic->getStride(); Pel *dst = dstPic->getLumaAddr( partAddr ); Int xFrac = mv->getHor() & 0x3; Int yFrac = mv->getVer() & 0x3; if ( yFrac == 0 ) { m_if.filterHorLuma( ref, refStride, dst, dstStride, width, height, xFrac, !bi ); } else if ( xFrac == 0 ) { m_if.filterVerLuma( ref, refStride, dst, dstStride, width, height, yFrac, true, !bi ); } else { Int tmpStride = m_filteredBlockTmp[0].getStride(); Short *tmp = m_filteredBlockTmp[0].getLumaAddr(); Int filterSize = NTAPS_LUMA; Int halfFilterSize = ( filterSize >> 1 ); m_if.filterHorLuma(ref - (halfFilterSize-1)*refStride, refStride, tmp, tmpStride, width, height+filterSize-1, xFrac, false ); m_if.filterVerLuma(tmp + (halfFilterSize-1)*tmpStride, tmpStride, dst, dstStride, width, height, yFrac, false, !bi); } } /** * \brief Generate motion-compensated chroma block * * \param cu Pointer to current CU * \param refPic Pointer to reference picture * \param partAddr Address of block within CU * \param mv Motion vector * \param width Width of block * \param height Height of block * \param dstPic Pointer to destination picture * \param bi Flag indicating whether bipred is used */ Void TComPrediction::xPredInterChromaBlk( TComDataCU *cu, TComPicYuv *refPic, UInt partAddr, TComMv *mv, Int width, Int height, TComYuv *&dstPic, Bool bi ) { Int refStride = refPic->getCStride(); Int dstStride = dstPic->getCStride(); Int refOffset = (mv->getHor() >> 3) + (mv->getVer() >> 3) * refStride; Pel* refCb = refPic->getCbAddr( cu->getAddr(), cu->getZorderIdxInCU() + partAddr ) + refOffset; Pel* refCr = refPic->getCrAddr( cu->getAddr(), cu->getZorderIdxInCU() + partAddr ) + refOffset; Pel* dstCb = dstPic->getCbAddr( partAddr ); Pel* dstCr = dstPic->getCrAddr( partAddr ); Int xFrac = mv->getHor() & 0x7; Int yFrac = mv->getVer() & 0x7; UInt cxWidth = width >> 1; UInt cxHeight = height >> 1; Int extStride = m_filteredBlockTmp[0].getStride(); Short* extY = m_filteredBlockTmp[0].getLumaAddr(); Int filterSize = NTAPS_CHROMA; Int halfFilterSize = (filterSize>>1); if ( yFrac == 0 ) { m_if.filterHorChroma(refCb, refStride, dstCb, dstStride, cxWidth, cxHeight, xFrac, !bi); m_if.filterHorChroma(refCr, refStride, dstCr, dstStride, cxWidth, cxHeight, xFrac, !bi); } else if ( xFrac == 0 ) { m_if.filterVerChroma(refCb, refStride, dstCb, dstStride, cxWidth, cxHeight, yFrac, true, !bi); m_if.filterVerChroma(refCr, refStride, dstCr, dstStride, cxWidth, cxHeight, yFrac, true, !bi); } else { m_if.filterHorChroma(refCb - (halfFilterSize-1)*refStride, refStride, extY, extStride, cxWidth, cxHeight+filterSize-1, xFrac, false); m_if.filterVerChroma(extY + (halfFilterSize-1)*extStride, extStride, dstCb, dstStride, cxWidth, cxHeight , yFrac, false, !bi); m_if.filterHorChroma(refCr - (halfFilterSize-1)*refStride, refStride, extY, extStride, cxWidth, cxHeight+filterSize-1, xFrac, false); m_if.filterVerChroma(extY + (halfFilterSize-1)*extStride, extStride, dstCr, dstStride, cxWidth, cxHeight , yFrac, false, !bi); } } Void TComPrediction::xWeightedAverage( TComDataCU* pcCU, TComYuv* pcYuvSrc0, TComYuv* pcYuvSrc1, Int iRefIdx0, Int iRefIdx1, UInt uiPartIdx, Int iWidth, Int iHeight, TComYuv*& rpcYuvDst ) { if( iRefIdx0 >= 0 && iRefIdx1 >= 0 ) { rpcYuvDst->addAvg( pcYuvSrc0, pcYuvSrc1, uiPartIdx, iWidth, iHeight ); } else if ( iRefIdx0 >= 0 && iRefIdx1 < 0 ) { pcYuvSrc0->copyPartToPartYuv( rpcYuvDst, uiPartIdx, iWidth, iHeight ); } else if ( iRefIdx0 < 0 && iRefIdx1 >= 0 ) { pcYuvSrc1->copyPartToPartYuv( rpcYuvDst, uiPartIdx, iWidth, iHeight ); } } // AMVP Void TComPrediction::getMvPredAMVP( TComDataCU* pcCU, UInt uiPartIdx, UInt uiPartAddr, RefPicList eRefPicList, Int iRefIdx, TComMv& rcMvPred ) { AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); #if !SPS_AMVP_CLEANUP if( pcCU->getAMVPMode(uiPartAddr) == AM_NONE || (pcAMVPInfo->iN <= 1 && pcCU->getAMVPMode(uiPartAddr) == AM_EXPL) ) #else if( pcAMVPInfo->iN <= 1 ) #endif { rcMvPred = pcAMVPInfo->m_acMvCand[0]; pcCU->setMVPIdxSubParts( 0, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); return; } assert(pcCU->getMVPIdx(eRefPicList,uiPartAddr) >= 0); rcMvPred = pcAMVPInfo->m_acMvCand[pcCU->getMVPIdx(eRefPicList,uiPartAddr)]; return; } /** Function for deriving planar intra prediction. * \param pSrc pointer to reconstructed sample array * \param srcStride the stride of the reconstructed sample array * \param rpDst reference to pointer for the prediction sample array * \param dstStride the stride of the prediction sample array * \param width the width of the block * \param height the height of the block * * This function derives the prediction samples for planar mode (intra coding). */ Void TComPrediction::xPredIntraPlanar( Int* pSrc, Int srcStride, Pel* rpDst, Int dstStride, UInt width, UInt height ) { assert(width == height); Int k, l, bottomLeft, topRight; Int horPred; Int leftColumn[MAX_CU_SIZE], topRow[MAX_CU_SIZE], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE]; UInt blkSize = width; UInt offset2D = width; UInt shift1D = g_aucConvertToBit[ width ] + 2; UInt shift2D = shift1D + 1; // Get left and above reference column and row for(k=0;k> shift2D ); } } } #if !REMOVE_LMCHROMA /** Function for deriving chroma LM intra prediction. * \param pcPattern pointer to neighbouring pixel access pattern * \param piSrc pointer to reconstructed chroma sample array * \param pPred pointer for the prediction sample array * \param uiPredStride the stride of the prediction sample array * \param uiCWidth the width of the chroma block * \param uiCHeight the height of the chroma block * \param uiChromaId boolean indication of chroma component * * This function derives the prediction samples for chroma LM mode (chroma intra coding) */ Void TComPrediction::predLMIntraChroma( TComPattern* pcPattern, Int* piSrc, Pel* pPred, UInt uiPredStride, UInt uiCWidth, UInt uiCHeight, UInt uiChromaId ) { UInt uiWidth = 2 * uiCWidth; xGetLLSPrediction( pcPattern, piSrc+uiWidth+2, uiWidth+1, pPred, uiPredStride, uiCWidth, uiCHeight, 1 ); } /** Function for deriving downsampled luma sample of current chroma block and its above, left causal pixel * \param pcPattern pointer to neighbouring pixel access pattern * \param uiCWidth the width of the chroma block * \param uiCHeight the height of the chroma block * * This function derives downsampled luma sample of current chroma block and its above, left causal pixel */ Void TComPrediction::getLumaRecPixels( TComPattern* pcPattern, UInt uiCWidth, UInt uiCHeight ) { UInt uiWidth = 2 * uiCWidth; UInt uiHeight = 2 * uiCHeight; Pel* pRecSrc = pcPattern->getROIY(); Pel* pDst0 = m_pLumaRecBuffer + m_iLumaRecStride + 1; Int iRecSrcStride = pcPattern->getPatternLStride(); Int iRecSrcStride2 = iRecSrcStride << 1; Int iDstStride = m_iLumaRecStride; Int iSrcStride = ( max( uiWidth, uiHeight ) << 1 ) + 1; Int* ptrSrc = pcPattern->getAdiOrgBuf( uiWidth, uiHeight, m_piYuvExt ); // initial pointers Pel* pDst = pDst0 - 1 - iDstStride; Int* piSrc = ptrSrc; // top left corner downsampled from ADI buffer // don't need this point // top row downsampled from ADI buffer pDst++; piSrc ++; for (Int i = 0; i < uiCWidth; i++) { pDst[i] = ((piSrc[2*i] * 2 ) + piSrc[2*i - 1] + piSrc[2*i + 1] + 2) >> 2; } // left column downsampled from ADI buffer pDst = pDst0 - 1; piSrc = ptrSrc + iSrcStride; for (Int j = 0; j < uiCHeight; j++) { pDst[0] = ( piSrc[0] + piSrc[iSrcStride] ) >> 1; piSrc += iSrcStride << 1; pDst += iDstStride; } // inner part from reconstructed picture buffer for( Int j = 0; j < uiCHeight; j++ ) { for (Int i = 0; i < uiCWidth; i++) { pDst0[i] = (pRecSrc[2*i] + pRecSrc[2*i + iRecSrcStride]) >> 1; } pDst0 += iDstStride; pRecSrc += iRecSrcStride2; } } /** Function for deriving the positon of first non-zero binary bit of a value * \param x input value * * This function derives the positon of first non-zero binary bit of a value */ Int GetFloorLog2( UInt x ) { int bits = -1; while( x > 0 ) { bits ++; x >>= 1; } return bits; } /** Function for deriving LM intra prediction. * \param pcPattern pointer to neighbouring pixel access pattern * \param pSrc0 pointer to reconstructed chroma sample array * \param iSrcStride the stride of reconstructed chroma sample array * \param pDst0 reference to pointer for the prediction sample array * \param iDstStride the stride of the prediction sample array * \param uiWidth the width of the chroma block * \param uiHeight the height of the chroma block * \param uiExt0 line number of neiggboirng pixels for calculating LM model parameter, default value is 1 * * This function derives the prediction samples for chroma LM mode (chroma intra coding) */ Void TComPrediction::xGetLLSPrediction( TComPattern* pcPattern, Int* pSrc0, Int iSrcStride, Pel* pDst0, Int iDstStride, UInt uiWidth, UInt uiHeight, UInt uiExt0 ) { Pel *pDst, *pLuma; Int *pSrc; Int iLumaStride = m_iLumaRecStride; Pel* pLuma0 = m_pLumaRecBuffer + uiExt0 * iLumaStride + uiExt0; Int i, j, iCountShift = 0; UInt uiInternalBitDepth = g_uiBitDepth + g_uiBitIncrement; UInt uiExt = uiExt0; // LLS parameters estimation --> Int x = 0, y = 0, xx = 0, xy = 0; pSrc = pSrc0 - iSrcStride; pLuma = pLuma0 - iLumaStride; for( j = 0; j < uiWidth; j++ ) { x += pLuma[j]; y += pSrc[j]; xx += pLuma[j] * pLuma[j]; xy += pLuma[j] * pSrc[j]; } pSrc = pSrc0 - uiExt; pLuma = pLuma0 - uiExt; for( i = 0; i < uiHeight; i++ ) { x += pLuma[0]; y += pSrc[0]; xx += pLuma[0] * pLuma[0]; xy += pLuma[0] * pSrc[0]; pSrc += iSrcStride; pLuma += iLumaStride; } iCountShift = g_aucConvertToBit[ uiWidth ] + 3; Int iTempShift = uiInternalBitDepth + iCountShift - 15; if(iTempShift > 0) { x = ( x + ( 1 << ( iTempShift - 1 ) ) ) >> iTempShift; y = ( y + ( 1 << ( iTempShift - 1 ) ) ) >> iTempShift; xx = ( xx + ( 1 << ( iTempShift - 1 ) ) ) >> iTempShift; xy = ( xy + ( 1 << ( iTempShift - 1 ) ) ) >> iTempShift; iCountShift -= iTempShift; } Int avgLuma = x >> iCountShift; Int avgSrc = y >> iCountShift; Int RErrLuma = x & ( ( 1 << iCountShift ) - 1 ); Int RErrSrc = y & ( ( 1 << iCountShift ) - 1 ); Int a, b, iShift = 13; Int iB = 7; iShift -= iB; if( iCountShift == 0 ) { a = 0; b = 1 << (uiInternalBitDepth - 1); iShift = 0; } else { Int a1 = xy - ( avgLuma*avgSrc << iCountShift ) - avgLuma*RErrSrc - avgSrc*RErrLuma; Int a2 = xx - ( avgLuma*avgLuma << iCountShift ) - 2*avgLuma*RErrLuma; const Int iShiftA1 = uiInternalBitDepth - 2; const Int iShiftA2 = 5; const Int iAccuracyShift = uiInternalBitDepth + 4; Int iScaleShiftA2 = 0; Int iScaleShiftA1 = 0; Int a1s = a1; Int a2s = a2; iScaleShiftA1 = a1 == 0 ? 0 : GetFloorLog2( abs( a1 ) ) - iShiftA1; iScaleShiftA2 = a2 == 0 ? 0 : GetFloorLog2( abs( a2 ) ) - iShiftA2; if( iScaleShiftA1 < 0 ) { iScaleShiftA1 = 0; } if( iScaleShiftA2 < 0 ) { iScaleShiftA2 = 0; } Int iScaleShiftA = iScaleShiftA2 + iAccuracyShift - iShift - iScaleShiftA1; a2s = a2 >> iScaleShiftA2; a1s = a1 >> iScaleShiftA1; if (a2s >= 32) { UInt a2t = m_uiaShift[ a2s - 32 ] ; a2t = Clip( a2t ); a = a1s * a2t; } else { a = 0; } if( iScaleShiftA < 0 ) { a = a << -iScaleShiftA; } else { a = a >> iScaleShiftA; } a = Clip3(-( 1 << (15-iB) ), ( 1 << (15-iB )) - 1, a); a = a << iB; Short n = 0; if (a != 0) { n = GetFloorLog2(abs( a ) + ( (a < 0 ? -1 : 1) - 1)/2 ) - 5; } iShift =(iShift+iB)-n; a = a>>n; b = avgSrc - ( ( a * avgLuma ) >> iShift ); } // <-- end of LLS parameters estimation // get prediction --> uiExt = uiExt0; pLuma = pLuma0; pDst = pDst0; for( i = 0; i < uiHeight; i++ ) { for( j = 0; j < uiWidth; j++ ) { pDst[j] = Clip( ( ( a * pLuma[j] ) >> iShift ) + b ); } pDst += iDstStride; pLuma += iLumaStride; } // <-- end of get prediction } #endif /** Function for filtering intra DC predictor. * \param pSrc pointer to reconstructed sample array * \param iSrcStride the stride of the reconstructed sample array * \param rpDst reference to pointer for the prediction sample array * \param iDstStride the stride of the prediction sample array * \param iWidth the width of the block * \param iHeight the height of the block * * This function performs filtering left and top edges of the prediction samples for DC mode (intra coding). */ Void TComPrediction::xDCPredFiltering( Int* pSrc, Int iSrcStride, Pel*& rpDst, Int iDstStride, Int iWidth, Int iHeight ) { Pel* pDst = rpDst; Int x, y, iDstStride2, iSrcStride2; // boundary pixels processing pDst[0] = (Pel)((pSrc[-iSrcStride] + pSrc[-1] + 2 * pDst[0] + 2) >> 2); for ( x = 1; x < iWidth; x++ ) { pDst[x] = (Pel)((pSrc[x - iSrcStride] + 3 * pDst[x] + 2) >> 2); } for ( y = 1, iDstStride2 = iDstStride, iSrcStride2 = iSrcStride-1; y < iHeight; y++, iDstStride2+=iDstStride, iSrcStride2+=iSrcStride ) { pDst[iDstStride2] = (Pel)((pSrc[iSrcStride2] + 3 * pDst[iDstStride2] + 2) >> 2); } return; } #if SVC_UPSAMPLING Void TComPrediction::upsampleBasePic( TComPicYuv* pcUsPic, TComPicYuv* pcBasePic, TComPicYuv* pcTempPic) { m_cUsf.upsampleBasePic( pcUsPic, pcBasePic, pcTempPic); } #endif //! \}