/* 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-2013, 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 TEncEntropy.cpp \brief entropy encoder class */ #include "TEncEntropy.h" #include "TLibCommon/TypeDef.h" #include "TLibCommon/TComSampleAdaptiveOffset.h" //! \ingroup TLibEncoder //! \{ Void TEncEntropy::setEntropyCoder ( TEncEntropyIf* e, TComSlice* pcSlice ) { m_pcEntropyCoderIf = e; m_pcEntropyCoderIf->setSlice ( pcSlice ); } Void TEncEntropy::encodeSliceHeader ( TComSlice* pcSlice ) { if (pcSlice->getSPS()->getUseSAO()) { SAOParam *saoParam = pcSlice->getPic()->getPicSym()->getSaoParam(); pcSlice->setSaoEnabledFlag (saoParam->bSaoFlag[0]); { pcSlice->setSaoEnabledFlagChroma (saoParam->bSaoFlag[1]); } } m_pcEntropyCoderIf->codeSliceHeader( pcSlice ); return; } Void TEncEntropy::encodeTilesWPPEntryPoint( TComSlice* pSlice ) { m_pcEntropyCoderIf->codeTilesWPPEntryPoint( pSlice ); } Void TEncEntropy::encodeTerminatingBit ( UInt uiIsLast ) { m_pcEntropyCoderIf->codeTerminatingBit( uiIsLast ); return; } Void TEncEntropy::encodeSliceFinish() { m_pcEntropyCoderIf->codeSliceFinish(); } Void TEncEntropy::encodePPS( TComPPS* pcPPS ) { m_pcEntropyCoderIf->codePPS( pcPPS ); return; } #if H_3D Void TEncEntropy::encodeSPS( TComSPS* pcSPS, Int viewIndex, Bool depthFlag ) { m_pcEntropyCoderIf->codeSPS( pcSPS, viewIndex, depthFlag ); return; } #else Void TEncEntropy::encodeSPS( TComSPS* pcSPS ) { m_pcEntropyCoderIf->codeSPS( pcSPS ); return; } #endif Void TEncEntropy::encodeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeCUTransquantBypassFlag( pcCU, uiAbsPartIdx ); } Void TEncEntropy::encodeVPS( TComVPS* pcVPS ) { m_pcEntropyCoderIf->codeVPS( pcVPS ); return; } Void TEncEntropy::encodeSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if ( pcCU->getSlice()->isIntra() ) { return; } if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeSkipFlag( pcCU, uiAbsPartIdx ); } /** encode merge flag * \param pcCU * \param uiAbsPartIdx * \returns Void */ Void TEncEntropy::encodeMergeFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) { // at least one merge candidate exists m_pcEntropyCoderIf->codeMergeFlag( pcCU, uiAbsPartIdx ); } /** encode merge index * \param pcCU * \param uiAbsPartIdx * \param uiPUIdx * \param bRD * \returns Void */ Void TEncEntropy::encodeMergeIndex( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; assert( pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ); } m_pcEntropyCoderIf->codeMergeIndex( pcCU, uiAbsPartIdx ); } /** encode prediction mode * \param pcCU * \param uiAbsPartIdx * \param bRD * \returns Void */ Void TEncEntropy::encodePredMode( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } if ( pcCU->getSlice()->isIntra() ) { return; } m_pcEntropyCoderIf->codePredMode( pcCU, uiAbsPartIdx ); } // Split mode Void TEncEntropy::encodeSplitFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeSplitFlag( pcCU, uiAbsPartIdx, uiDepth ); } /** encode partition size * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param bRD * \returns Void */ Void TEncEntropy::encodePartSize( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codePartSize( pcCU, uiAbsPartIdx, uiDepth ); } /** Encode I_PCM information. * \param pcCU pointer to CU * \param uiAbsPartIdx CU index * \param bRD flag indicating estimation or encoding * \returns Void */ Void TEncEntropy::encodeIPCMInfo( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if(!pcCU->getSlice()->getSPS()->getUsePCM() || pcCU->getWidth(uiAbsPartIdx) > (1<getSlice()->getSPS()->getPCMLog2MaxSize()) || pcCU->getWidth(uiAbsPartIdx) < (1<getSlice()->getSPS()->getPCMLog2MinSize())) { return; } #if H_3D_DIM_SDC if( pcCU->getSDCFlag(uiAbsPartIdx) ) { return; } #endif if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeIPCMInfo ( pcCU, uiAbsPartIdx ); } Void TEncEntropy::xEncodeTransform( TComDataCU* pcCU,UInt offsetLuma, UInt offsetChroma, UInt uiAbsPartIdx, UInt uiDepth, UInt width, UInt height, UInt uiTrIdx, Bool& bCodeDQP ) { const UInt uiSubdiv = pcCU->getTransformIdx( uiAbsPartIdx ) + pcCU->getDepth( uiAbsPartIdx ) > uiDepth; const UInt uiLog2TrafoSize = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth()]+2 - uiDepth; UInt cbfY = pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA , uiTrIdx ); UInt cbfU = pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrIdx ); UInt cbfV = pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrIdx ); if(uiTrIdx==0) { m_bakAbsPartIdxCU = uiAbsPartIdx; } if( uiLog2TrafoSize == 2 ) { UInt partNum = pcCU->getPic()->getNumPartInCU() >> ( ( uiDepth - 1 ) << 1 ); if( ( uiAbsPartIdx % partNum ) == 0 ) { m_uiBakAbsPartIdx = uiAbsPartIdx; m_uiBakChromaOffset = offsetChroma; } else if( ( uiAbsPartIdx % partNum ) == (partNum - 1) ) { cbfU = pcCU->getCbf( m_uiBakAbsPartIdx, TEXT_CHROMA_U, uiTrIdx ); cbfV = pcCU->getCbf( m_uiBakAbsPartIdx, TEXT_CHROMA_V, uiTrIdx ); } } if( pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTRA && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_NxN && uiDepth == pcCU->getDepth(uiAbsPartIdx) ) { assert( uiSubdiv ); } else if( pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTER && (pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N) && uiDepth == pcCU->getDepth(uiAbsPartIdx) && (pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) ) { if ( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( uiSubdiv ); } else { assert(!uiSubdiv ); } } else if( uiLog2TrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { assert( uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { assert( !uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( !uiSubdiv ); } else { assert( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSubdiv, 5 - uiLog2TrafoSize ); } const UInt uiTrDepthCurr = uiDepth - pcCU->getDepth( uiAbsPartIdx ); const Bool bFirstCbfOfCU = uiTrDepthCurr == 0; if( bFirstCbfOfCU || uiLog2TrafoSize > 2 ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr - 1 ) ) { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr ); } if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr - 1 ) ) { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr ); } } else if( uiLog2TrafoSize == 2 ) { assert( pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr ) == pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr - 1 ) ); assert( pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr ) == pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr - 1 ) ); } if( uiSubdiv ) { UInt size; width >>= 1; height >>= 1; size = width*height; uiTrIdx++; ++uiDepth; const UInt partNum = pcCU->getPic()->getNumPartInCU() >> (uiDepth << 1); xEncodeTransform( pcCU, offsetLuma, offsetChroma, uiAbsPartIdx, uiDepth, width, height, uiTrIdx, bCodeDQP ); uiAbsPartIdx += partNum; offsetLuma += size; offsetChroma += (size>>2); xEncodeTransform( pcCU, offsetLuma, offsetChroma, uiAbsPartIdx, uiDepth, width, height, uiTrIdx, bCodeDQP ); uiAbsPartIdx += partNum; offsetLuma += size; offsetChroma += (size>>2); xEncodeTransform( pcCU, offsetLuma, offsetChroma, uiAbsPartIdx, uiDepth, width, height, uiTrIdx, bCodeDQP ); uiAbsPartIdx += partNum; offsetLuma += size; offsetChroma += (size>>2); xEncodeTransform( pcCU, offsetLuma, offsetChroma, uiAbsPartIdx, uiDepth, width, height, uiTrIdx, bCodeDQP ); } else { { DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tTrIdx: abspart=" ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\tdepth=" ); DTRACE_CABAC_V( uiDepth ); DTRACE_CABAC_T( "\ttrdepth=" ); DTRACE_CABAC_V( pcCU->getTransformIdx( uiAbsPartIdx ) ); DTRACE_CABAC_T( "\n" ); } if( pcCU->getPredictionMode(uiAbsPartIdx) != MODE_INTRA && uiDepth == pcCU->getDepth( uiAbsPartIdx ) && !pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, 0 ) && !pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, 0 ) ) { assert( pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, 0 ) ); // printf( "saved one bin! " ); } else { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, pcCU->getTransformIdx( uiAbsPartIdx ) ); } if ( cbfY || cbfU || cbfV ) { // dQP: only for LCU once if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { if ( bCodeDQP ) { encodeQP( pcCU, m_bakAbsPartIdxCU ); bCodeDQP = false; } } } if( cbfY ) { Int trWidth = width; Int trHeight = height; m_pcEntropyCoderIf->codeCoeffNxN( pcCU, (pcCU->getCoeffY()+offsetLuma), uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_LUMA ); } if( uiLog2TrafoSize > 2 ) { Int trWidth = width >> 1; Int trHeight = height >> 1; if( cbfU ) { m_pcEntropyCoderIf->codeCoeffNxN( pcCU, (pcCU->getCoeffCb()+offsetChroma), uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_U ); } if( cbfV ) { m_pcEntropyCoderIf->codeCoeffNxN( pcCU, (pcCU->getCoeffCr()+offsetChroma), uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_V ); } } else { UInt partNum = pcCU->getPic()->getNumPartInCU() >> ( ( uiDepth - 1 ) << 1 ); if( ( uiAbsPartIdx % partNum ) == (partNum - 1) ) { Int trWidth = width; Int trHeight = height; if( cbfU ) { m_pcEntropyCoderIf->codeCoeffNxN( pcCU, (pcCU->getCoeffCb()+m_uiBakChromaOffset), m_uiBakAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_U ); } if( cbfV ) { m_pcEntropyCoderIf->codeCoeffNxN( pcCU, (pcCU->getCoeffCr()+m_uiBakChromaOffset), m_uiBakAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_V ); } } } } } // Intra direction for Luma Void TEncEntropy::encodeIntraDirModeLuma ( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiplePU ) { m_pcEntropyCoderIf->codeIntraDirLumaAng( pcCU, absPartIdx , isMultiplePU); } // Intra direction for Chroma Void TEncEntropy::encodeIntraDirModeChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeIntraDirChroma( pcCU, uiAbsPartIdx ); } Void TEncEntropy::encodePredInfo( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } if( pcCU->isIntra( uiAbsPartIdx ) ) // If it is Intra mode, encode intra prediction mode. { encodeIntraDirModeLuma ( pcCU, uiAbsPartIdx,true ); #if H_3D_DIM_SDC if(!pcCU->getSDCFlag(uiAbsPartIdx)) #endif encodeIntraDirModeChroma( pcCU, uiAbsPartIdx, bRD ); } else // if it is Inter mode, encode motion vector and reference index { encodePUWise( pcCU, uiAbsPartIdx, bRD ); } } /** encode motion information for every PU block * \param pcCU * \param uiAbsPartIdx * \param bRD * \returns Void */ Void TEncEntropy::encodePUWise( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if ( bRD ) { uiAbsPartIdx = 0; } PartSize ePartSize = pcCU->getPartitionSize( uiAbsPartIdx ); UInt uiNumPU = ( ePartSize == SIZE_2Nx2N ? 1 : ( ePartSize == SIZE_NxN ? 4 : 2 ) ); UInt uiDepth = pcCU->getDepth( uiAbsPartIdx ); UInt uiPUOffset = ( g_auiPUOffset[UInt( ePartSize )] << ( ( pcCU->getSlice()->getSPS()->getMaxCUDepth() - uiDepth ) << 1 ) ) >> 4; for ( UInt uiPartIdx = 0, uiSubPartIdx = uiAbsPartIdx; uiPartIdx < uiNumPU; uiPartIdx++, uiSubPartIdx += uiPUOffset ) { encodeMergeFlag( pcCU, uiSubPartIdx ); if ( pcCU->getMergeFlag( uiSubPartIdx ) ) { encodeMergeIndex( pcCU, uiSubPartIdx ); } else { encodeInterDirPU( pcCU, uiSubPartIdx ); for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { encodeRefFrmIdxPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); encodeMvdPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); encodeMVPIdxPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); } } } } return; } Void TEncEntropy::encodeInterDirPU( TComDataCU* pcCU, UInt uiAbsPartIdx ) { if ( !pcCU->getSlice()->isInterB() ) { return; } m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); return; } /** encode reference frame index for a PU block * \param pcCU * \param uiAbsPartIdx * \param eRefList * \returns Void */ Void TEncEntropy::encodeRefFrmIdxPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { assert( !pcCU->isIntra( uiAbsPartIdx ) ); { if ( ( pcCU->getSlice()->getNumRefIdx( eRefList ) == 1 ) ) { return; } if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } return; } /** encode motion vector difference for a PU block * \param pcCU * \param uiAbsPartIdx * \param eRefList * \returns Void */ Void TEncEntropy::encodeMvdPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { assert( !pcCU->isIntra( uiAbsPartIdx ) ); if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } return; } Void TEncEntropy::encodeMVPIdxPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } return; } Void TEncEntropy::encodeQtCbf( TComDataCU* pcCU, UInt uiAbsPartIdx, TextType eType, UInt uiTrDepth ) { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, eType, uiTrDepth ); } Void TEncEntropy::encodeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ) { m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSymbol, uiCtx ); } Void TEncEntropy::encodeQtRootCbf( TComDataCU* pcCU, UInt uiAbsPartIdx ) { m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); } Void TEncEntropy::encodeQtCbfZero( TComDataCU* pcCU, TextType eType, UInt uiTrDepth ) { m_pcEntropyCoderIf->codeQtCbfZero( pcCU, eType, uiTrDepth ); } Void TEncEntropy::encodeQtRootCbfZero( TComDataCU* pcCU ) { m_pcEntropyCoderIf->codeQtRootCbfZero( pcCU ); } // dQP Void TEncEntropy::encodeQP( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { m_pcEntropyCoderIf->codeDeltaQP( pcCU, uiAbsPartIdx ); } } // texture /** encode coefficients * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param uiWidth * \param uiHeight */ Void TEncEntropy::encodeCoeff( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight, Bool& bCodeDQP ) { UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight(); UInt uiLumaOffset = uiMinCoeffSize*uiAbsPartIdx; UInt uiChromaOffset = uiLumaOffset>>2; #if H_3D_DIM_SDC if( pcCU->getSDCFlag( uiAbsPartIdx ) ) { assert( pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ); assert( pcCU->getTransformIdx(uiAbsPartIdx) == 0 ); assert( pcCU->getCbf(uiAbsPartIdx, TEXT_LUMA) == 1 ); assert( pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_U) == 1 ); assert( pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_V) == 1 ); return; } #endif if( pcCU->isIntra(uiAbsPartIdx) ) { #if !H_MV DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tdecodeTransformIdx()\tCUDepth=" ) DTRACE_CABAC_V( uiDepth ) DTRACE_CABAC_T( "\n" ) #endif } else { if( !(pcCU->getMergeFlag( uiAbsPartIdx ) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ) ) { m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); } if ( !pcCU->getQtRootCbf( uiAbsPartIdx ) ) { return; } } xEncodeTransform( pcCU, uiLumaOffset, uiChromaOffset, uiAbsPartIdx, uiDepth, uiWidth, uiHeight, 0, bCodeDQP); } Void TEncEntropy::encodeCoeffNxN( TComDataCU* pcCU, TCoeff* pcCoeff, UInt uiAbsPartIdx, UInt uiTrWidth, UInt uiTrHeight, UInt uiDepth, TextType eType ) { // This is for Transform unit processing. This may be used at mode selection stage for Inter. m_pcEntropyCoderIf->codeCoeffNxN( pcCU, pcCoeff, uiAbsPartIdx, uiTrWidth, uiTrHeight, uiDepth, eType ); } Void TEncEntropy::estimateBit (estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, TextType eTType) { eTType = eTType == TEXT_LUMA ? TEXT_LUMA : TEXT_CHROMA; m_pcEntropyCoderIf->estBit ( pcEstBitsSbac, width, height, eTType ); } /** Encode SAO Offset * \param saoLcuParam SAO LCU paramters */ Void TEncEntropy::encodeSaoOffset(SaoLcuParam* saoLcuParam, UInt compIdx) { UInt uiSymbol; Int i; uiSymbol = saoLcuParam->typeIdx + 1; if (compIdx!=2) { m_pcEntropyCoderIf->codeSaoTypeIdx(uiSymbol); } if (uiSymbol) { if (saoLcuParam->typeIdx < 4 && compIdx != 2) { saoLcuParam->subTypeIdx = saoLcuParam->typeIdx; } Int bitDepth = compIdx ? g_bitDepthC : g_bitDepthY; Int offsetTh = 1 << min(bitDepth - 5,5); if( saoLcuParam->typeIdx == SAO_BO ) { for( i=0; i< saoLcuParam->length; i++) { UInt absOffset = ( (saoLcuParam->offset[i] < 0) ? -saoLcuParam->offset[i] : saoLcuParam->offset[i]); m_pcEntropyCoderIf->codeSaoMaxUvlc(absOffset, offsetTh-1); } for( i=0; i< saoLcuParam->length; i++) { if (saoLcuParam->offset[i] != 0) { UInt sign = (saoLcuParam->offset[i] < 0) ? 1 : 0 ; m_pcEntropyCoderIf->codeSAOSign(sign); } } uiSymbol = (UInt) (saoLcuParam->subTypeIdx); m_pcEntropyCoderIf->codeSaoUflc(5, uiSymbol); } else if( saoLcuParam->typeIdx < 4 ) { m_pcEntropyCoderIf->codeSaoMaxUvlc( saoLcuParam->offset[0], offsetTh-1); m_pcEntropyCoderIf->codeSaoMaxUvlc( saoLcuParam->offset[1], offsetTh-1); m_pcEntropyCoderIf->codeSaoMaxUvlc(-saoLcuParam->offset[2], offsetTh-1); m_pcEntropyCoderIf->codeSaoMaxUvlc(-saoLcuParam->offset[3], offsetTh-1); if (compIdx!=2) { uiSymbol = (UInt) (saoLcuParam->subTypeIdx); m_pcEntropyCoderIf->codeSaoUflc(2, uiSymbol); } } } } /** Encode SAO unit interleaving * \param rx * \param ry * \param pSaoParam * \param pcCU * \param iCUAddrInSlice * \param iCUAddrUpInSlice * \param bLFCrossSliceBoundaryFlag */ Void TEncEntropy::encodeSaoUnitInterleaving(Int compIdx, Bool saoFlag, Int rx, Int ry, SaoLcuParam* saoLcuParam, Int cuAddrInSlice, Int cuAddrUpInSlice, Int allowMergeLeft, Int allowMergeUp) { if (saoFlag) { if (rx>0 && cuAddrInSlice!=0 && allowMergeLeft) { m_pcEntropyCoderIf->codeSaoMerge(saoLcuParam->mergeLeftFlag); } else { saoLcuParam->mergeLeftFlag = 0; } if (saoLcuParam->mergeLeftFlag == 0) { if ( (ry > 0) && (cuAddrUpInSlice>=0) && allowMergeUp ) { m_pcEntropyCoderIf->codeSaoMerge(saoLcuParam->mergeUpFlag); } else { saoLcuParam->mergeUpFlag = 0; } if (!saoLcuParam->mergeUpFlag) { encodeSaoOffset(saoLcuParam, compIdx); } } } } Int TEncEntropy::countNonZeroCoeffs( TCoeff* pcCoef, UInt uiSize ) { Int count = 0; for ( Int i = 0; i < uiSize; i++ ) { count += pcCoef[i] != 0; } return count; } /** encode quantization matrix * \param scalingList quantization matrix information */ Void TEncEntropy::encodeScalingList( TComScalingList* scalingList ) { m_pcEntropyCoderIf->codeScalingList( scalingList ); } //! \}