/* 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-2015, 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 TComPattern.cpp \brief neighbouring pixel access classes */ #include "TComPic.h" #include "TComPattern.h" #include "TComDataCU.h" #include "TComTU.h" #include "Debug.h" #include "TComPrediction.h" //! \ingroup TLibCommon //! \{ // Forward declarations /// padding of unavailable reference samples for intra prediction Void fillReferenceSamples( const Int bitDepth, #if O0043_BEST_EFFORT_DECODING const Int bitDepthDelta, #endif const Pel* piRoiOrigin, Pel* piIntraTemp, const Bool* bNeighborFlags, const Int iNumIntraNeighbor, const Int unitWidth, const Int unitHeight, const Int iAboveUnits, const Int iLeftUnits, const UInt uiWidth, const UInt uiHeight, const Int iPicStride ); /// constrained intra prediction Bool isAboveLeftAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT ); Int isAboveAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags ); Int isLeftAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags ); Int isAboveRightAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags ); Int isBelowLeftAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags ); // ==================================================================================================================== // Public member functions (TComPatternParam) // ==================================================================================================================== /** \param piTexture pixel data \param iRoiWidth pattern width \param iRoiHeight pattern height \param iStride buffer stride \param bitDepth bit depth */ Void TComPatternParam::setPatternParamPel ( Pel* piTexture, Int iRoiWidth, Int iRoiHeight, Int iStride, Int bitDepth ) { m_piROIOrigin = piTexture; m_iROIWidth = iRoiWidth; m_iROIHeight = iRoiHeight; m_iPatternStride = iStride; m_bitDepth = bitDepth; } // ==================================================================================================================== // Public member functions (TComPattern) // ==================================================================================================================== Void TComPattern::initPattern (Pel* piY, Int iRoiWidth, Int iRoiHeight, Int iStride, Int bitDepthLuma) { m_cPatternY. setPatternParamPel( piY, iRoiWidth, iRoiHeight, iStride, bitDepthLuma); } // TODO: move this function to TComPrediction.cpp. Void TComPrediction::initIntraPatternChType( TComTU &rTu, Bool& bAbove, Bool& bLeft, const ComponentID compID, const Bool bFilterRefSamples DEBUG_STRING_FN_DECLARE(sDebug)) { const ChannelType chType = toChannelType(compID); TComDataCU *pcCU=rTu.getCU(); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiZorderIdxInPart=rTu.GetAbsPartIdxTU(); const UInt uiTuWidth = rTu.getRect(compID).width; const UInt uiTuHeight = rTu.getRect(compID).height; const UInt uiTuWidth2 = uiTuWidth << 1; const UInt uiTuHeight2 = uiTuHeight << 1; const Int iBaseUnitSize = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); const Int iUnitWidth = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleX(compID); const Int iUnitHeight = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleY(compID); const Int iTUWidthInUnits = uiTuWidth / iUnitWidth; const Int iTUHeightInUnits = uiTuHeight / iUnitHeight; const Int iAboveUnits = iTUWidthInUnits << 1; const Int iLeftUnits = iTUHeightInUnits << 1; #if SVC_EXTENSION const Int bitDepthForChannel = pcCU->getSlice()->getBitDepth(chType); #else const Int bitDepthForChannel = sps.getBitDepth(chType); #endif assert(iTUHeightInUnits > 0 && iTUWidthInUnits > 0); const Int iPartIdxStride = pcCU->getPic()->getNumPartInCtuWidth(); const UInt uiPartIdxLT = pcCU->getZorderIdxInCtu() + uiZorderIdxInPart; const UInt uiPartIdxRT = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + iTUWidthInUnits - 1 ]; const UInt uiPartIdxLB = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + ((iTUHeightInUnits - 1) * iPartIdxStride)]; Int iPicStride = pcCU->getPic()->getStride(compID); Bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; Int iNumIntraNeighbor = 0; bNeighborFlags[iLeftUnits] = isAboveLeftAvailable( pcCU, uiPartIdxLT ); iNumIntraNeighbor += bNeighborFlags[iLeftUnits] ? 1 : 0; iNumIntraNeighbor += isAboveAvailable ( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1) ); iNumIntraNeighbor += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1 + iTUWidthInUnits ) ); iNumIntraNeighbor += isLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1) ); iNumIntraNeighbor += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1 - iTUHeightInUnits) ); bAbove = true; bLeft = true; const UInt uiROIWidth = uiTuWidth2+1; const UInt uiROIHeight = uiTuHeight2+1; assert(uiROIWidth*uiROIHeight <= m_iYuvExtSize); #if DEBUG_STRING std::stringstream ss(stringstream::out); #endif { Pel *piIntraTemp = m_piYuvExt[compID][PRED_BUF_UNFILTERED]; Pel *piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiZorderIdxInPart); #if O0043_BEST_EFFORT_DECODING const Int bitDepthForChannelInStream = sps.getStreamBitDepth(chType); fillReferenceSamples (bitDepthForChannelInStream, bitDepthForChannelInStream - bitDepthForChannel, #else fillReferenceSamples (bitDepthForChannel, #endif piRoiOrigin, piIntraTemp, bNeighborFlags, iNumIntraNeighbor, iUnitWidth, iUnitHeight, iAboveUnits, iLeftUnits, uiROIWidth, uiROIHeight, iPicStride); #if DEBUG_STRING if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA)) { ss << "###: generating Ref Samples for channel " << compID << " and " << rTu.getRect(compID).width << " x " << rTu.getRect(compID).height << "\n"; for (UInt y=0; y> shift; } piSrcPtr -= stride * (uiTuHeight2 - 1); } else { for(UInt i=1; i> 2; } } //------------------------------------------------ //top-left if (useStrongIntraSmoothing) { *piDestPtr = piSrcPtr[0]; } else { *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[1] + 2 ) >> 2; } piDestPtr += 1; piSrcPtr += 1; //------------------------------------------------ //top row (left-to-right) if (useStrongIntraSmoothing) { const Int shift = g_aucConvertToBit[uiTuWidth] + 3; //log2(uiTuWidth2) for(UInt i=1; i> shift; } piSrcPtr += uiTuWidth2 - 1; } else { for(UInt i=1; i> 2; } } //------------------------------------------------ *piDestPtr=*piSrcPtr; // far right is not filtered #if DEBUG_STRING if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA)) { ss << "###: filtered result for channel " << compID <<"\n"; for (UInt y=0; y(iNext, iLeftUnits); // fill left column while (iCurrJnit < iNextOrTop) { for (i=0; i= iLeftUnits) ? unitWidth : unitHeight; const Pel refSample = *(piIntraLineCur-1); for (i=0; i= iLeftUnits) ? unitWidth : unitHeight; iCurrJnit++; } } // Copy processed samples piIntraLineTemp = piIntraLine + uiHeight + unitWidth - 2; // top left, top and top right samples for (i=0; i=4 && uiTuChHeight>=4 && uiTuChWidth<128 && uiTuChHeight<128); if (uiDirMode == DC_IDX) { bFilter=false; //no smoothing for DC or LM chroma } else { Int diff = min(abs((Int) uiDirMode - HOR_IDX), abs((Int)uiDirMode - VER_IDX)); UInt sizeIndex=g_aucConvertToBit[uiTuChWidth]; assert(sizeIndex < MAX_INTRA_FILTER_DEPTHS); bFilter = diff > m_aucIntraFilter[toChannelType(compID)][sizeIndex]; } } return bFilter; } Bool isAboveLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT ) { Bool bAboveLeftFlag; UInt uiPartAboveLeft; TComDataCU* pcCUAboveLeft = pcCU->getPUAboveLeft( uiPartAboveLeft, uiPartIdxLT ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { bAboveLeftFlag = ( pcCUAboveLeft && pcCUAboveLeft->isIntra( uiPartAboveLeft ) ); } else { bAboveLeftFlag = (pcCUAboveLeft ? true : false); } return bAboveLeftFlag; } Int isAboveAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags ) { const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT]; const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxRT]+1; const UInt uiIdxStep = 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep ) { UInt uiPartAbove; TComDataCU* pcCUAbove = pcCU->getPUAbove( uiPartAbove, g_auiRasterToZscan[uiRasterPart] ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUAbove && pcCUAbove->isIntra( uiPartAbove ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if (pcCUAbove) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags++; } return iNumIntra; } Int isLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags ) { const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT]; const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxLB]+1; const UInt uiIdxStep = pcCU->getPic()->getNumPartInCtuWidth(); Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep ) { UInt uiPartLeft; TComDataCU* pcCULeft = pcCU->getPULeft( uiPartLeft, g_auiRasterToZscan[uiRasterPart] ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCULeft && pcCULeft->isIntra( uiPartLeft ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCULeft ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags--; // opposite direction } return iNumIntra; } Int isAboveRightAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags ) { const UInt uiNumUnitsInPU = g_auiZscanToRaster[uiPartIdxRT] - g_auiZscanToRaster[uiPartIdxLT] + 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ ) { UInt uiPartAboveRight; TComDataCU* pcCUAboveRight = pcCU->getPUAboveRight( uiPartAboveRight, uiPartIdxRT, uiOffset ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUAboveRight && pcCUAboveRight->isIntra( uiPartAboveRight ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCUAboveRight ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags++; } return iNumIntra; } Int isBelowLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags ) { const UInt uiNumUnitsInPU = (g_auiZscanToRaster[uiPartIdxLB] - g_auiZscanToRaster[uiPartIdxLT]) / pcCU->getPic()->getNumPartInCtuWidth() + 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ ) { UInt uiPartBelowLeft; TComDataCU* pcCUBelowLeft = pcCU->getPUBelowLeft( uiPartBelowLeft, uiPartIdxLB, uiOffset ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUBelowLeft && pcCUBelowLeft->isIntra( uiPartBelowLeft ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCUBelowLeft ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags--; // opposite direction } return iNumIntra; } //! \}