/* 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-2011, 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 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" Void TEncEntropy::setEntropyCoder ( TEncEntropyIf* e, TComSlice* pcSlice ) { m_pcEntropyCoderIf = e; m_pcEntropyCoderIf->setSlice ( pcSlice ); } Void TEncEntropy::encodeSliceHeader ( TComSlice* pcSlice ) { m_pcEntropyCoderIf->codeSliceHeader( pcSlice ); return; } Void TEncEntropy::encodeTerminatingBit ( UInt uiIsLast ) { m_pcEntropyCoderIf->codeTerminatingBit( uiIsLast ); return; } Void TEncEntropy::encodeSliceFinish() { m_pcEntropyCoderIf->codeSliceFinish(); } void TEncEntropy::encodeSEI(const SEI& sei) { m_pcEntropyCoderIf->codeSEI(sei); return; } Void TEncEntropy::encodePPS( TComPPS* pcPPS ) { m_pcEntropyCoderIf->codePPS( pcPPS ); return; } Void TEncEntropy::encodeSPS( TComSPS* pcSPS ) { m_pcEntropyCoderIf->codeSPS( pcSPS ); return; } Void TEncEntropy::encodeSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if ( pcCU->getSlice()->isIntra() ) { return; } if( bRD ) uiAbsPartIdx = 0; m_pcEntropyCoderIf->codeSkipFlag( pcCU, uiAbsPartIdx ); } #include "../TLibCommon/TypeDef.h" #include "../TLibCommon/TComAdaptiveLoopFilter.h" Void TEncEntropy::codeFiltCountBit(ALFParam* pAlfParam, Int64* ruiRate) { resetEntropy(); resetBits(); codeFilt(pAlfParam); *ruiRate = getNumberOfWrittenBits(); resetEntropy(); resetBits(); } Void TEncEntropy::codeAuxCountBit(ALFParam* pAlfParam, Int64* ruiRate) { resetEntropy(); resetBits(); codeAux(pAlfParam); *ruiRate = getNumberOfWrittenBits(); resetEntropy(); resetBits(); } Void TEncEntropy::codeAux(ALFParam* pAlfParam) { #if ENABLE_FORCECOEFF0 if (pAlfParam->filtNo>=0) m_pcEntropyCoderIf->codeAlfFlag(1); else m_pcEntropyCoderIf->codeAlfFlag(0); #endif Int FiltTab[3] = {9, 7, 5}; Int Tab = FiltTab[pAlfParam->realfiltNo]; // m_pcEntropyCoderIf->codeAlfUvlc(pAlfParam->realfiltNo); #if MQT_BA_RA m_pcEntropyCoderIf->codeAlfFlag(pAlfParam->alf_pcr_region_flag); #endif m_pcEntropyCoderIf->codeAlfUvlc((Tab-5)/2); if (pAlfParam->filtNo>=0) { if(pAlfParam->realfiltNo >= 0) { // filters_per_fr m_pcEntropyCoderIf->codeAlfUvlc(pAlfParam->noFilters); if(pAlfParam->noFilters == 1) { m_pcEntropyCoderIf->codeAlfUvlc(pAlfParam->startSecondFilter); } else if (pAlfParam->noFilters == 2) { for (int i=1; icodeAlfFlag (pAlfParam->filterPattern[i]); } } } } Int TEncEntropy::lengthGolomb(int coeffVal, int k) { int m = 2 << (k - 1); int q = coeffVal / m; if(coeffVal != 0) return(q + 2 + k); else return(q + 1 + k); } Int TEncEntropy::codeFilterCoeff(ALFParam* ALFp) { int filters_per_group = ALFp->filters_per_group_diff; int sqrFiltLength = ALFp->num_coeff; int filtNo = ALFp->realfiltNo; int flTab[]={9/2, 7/2, 5/2}; int fl = flTab[filtNo]; int i, k, kMin, kStart, minBits, ind, scanPos, maxScanVal, coeffVal, len = 0, *pDepthInt=NULL, kMinTab[MAX_SQR_FILT_LENGTH], bitsCoeffScan[MAX_SCAN_VAL][MAX_EXP_GOLOMB], minKStart, minBitsKStart, bitsKStart; pDepthInt = pDepthIntTab[fl-2]; maxScanVal = 0; for(i = 0; i < sqrFiltLength; i++) maxScanVal = max(maxScanVal, pDepthInt[i]); // vlc for all memset(bitsCoeffScan, 0, MAX_SCAN_VAL * MAX_EXP_GOLOMB * sizeof(int)); for(ind=0; indcoeffmulti[ind][i]); for (k=1; k<15; k++) { bitsCoeffScan[scanPos][k]+=lengthGolomb(coeffVal, k); } } } minBitsKStart = 0; minKStart = -1; for(k = 1; k < 8; k++) { bitsKStart = 0; kStart = k; for(scanPos = 0; scanPos < maxScanVal; scanPos++) { kMin = kStart; minBits = bitsCoeffScan[scanPos][kMin]; if(bitsCoeffScan[scanPos][kStart+1] < minBits) { kMin = kStart + 1; minBits = bitsCoeffScan[scanPos][kMin]; } kStart = kMin; bitsKStart += minBits; } if((bitsKStart < minBitsKStart) || (k == 1)) { minBitsKStart = bitsKStart; minKStart = k; } } kStart = minKStart; for(scanPos = 0; scanPos < maxScanVal; scanPos++) { kMin = kStart; minBits = bitsCoeffScan[scanPos][kMin]; if(bitsCoeffScan[scanPos][kStart+1] < minBits) { kMin = kStart + 1; minBits = bitsCoeffScan[scanPos][kMin]; } kMinTab[scanPos] = kMin; kStart = kMin; } // Coding parameters ALFp->minKStart = minKStart; ALFp->maxScanVal = maxScanVal; for(scanPos = 0; scanPos < maxScanVal; scanPos++) { ALFp->kMinTab[scanPos] = kMinTab[scanPos]; } len += writeFilterCodingParams(minKStart, maxScanVal, kMinTab); // Filter coefficients len += writeFilterCoeffs(sqrFiltLength, filters_per_group, pDepthInt, ALFp->coeffmulti, kMinTab); return len; } Int TEncEntropy::writeFilterCodingParams(int minKStart, int maxScanVal, int kMinTab[]) { int scanPos; int golombIndexBit; int kMin; // Golomb parameters m_pcEntropyCoderIf->codeAlfUvlc(minKStart - 1); kMin = minKStart; for(scanPos = 0; scanPos < maxScanVal; scanPos++) { golombIndexBit = (kMinTab[scanPos] != kMin)? 1: 0; assert(kMinTab[scanPos] <= kMin + 1); m_pcEntropyCoderIf->codeAlfFlag(golombIndexBit); kMin = kMinTab[scanPos]; } return 0; } Int TEncEntropy::writeFilterCoeffs(int sqrFiltLength, int filters_per_group, int pDepthInt[], int **FilterCoeff, int kMinTab[]) { int ind, scanPos, i; for(ind = 0; ind < filters_per_group; ++ind) { for(i = 0; i < sqrFiltLength; i++) { scanPos = pDepthInt[i] - 1; golombEncode(FilterCoeff[ind][i], kMinTab[scanPos]); } } return 0; } Int TEncEntropy::golombEncode(int coeff, int k) { int q, i, m; int symbol = abs(coeff); m = (int)pow(2.0, k); q = symbol / m; for (i = 0; i < q; i++) m_pcEntropyCoderIf->codeAlfFlag(1); m_pcEntropyCoderIf->codeAlfFlag(0); // write one zero for(i = 0; i < k; i++) { m_pcEntropyCoderIf->codeAlfFlag(symbol & 0x01); symbol >>= 1; } if(coeff != 0) { int sign = (coeff > 0)? 1: 0; m_pcEntropyCoderIf->codeAlfFlag(sign); } return 0; } Void TEncEntropy::codeFilt(ALFParam* pAlfParam) { if(pAlfParam->filters_per_group > 1) { #if ENABLE_FORCECOEFF0 m_pcEntropyCoderIf->codeAlfFlag (pAlfParam->forceCoeff0); if (pAlfParam->forceCoeff0) { for (int i=0; ifilters_per_group; i++) m_pcEntropyCoderIf->codeAlfFlag (pAlfParam->codedVarBins[i]); } #endif m_pcEntropyCoderIf->codeAlfFlag (pAlfParam->predMethod); } codeFilterCoeff (pAlfParam); } Void print(ALFParam* pAlfParam) { Int i=0; Int ind=0; Int FiltLengthTab[] = {22, 14, 8}; //0:9tap Int FiltLength = FiltLengthTab[pAlfParam->realfiltNo]; printf("set of params\n"); printf("realfiltNo:%d\n", pAlfParam->realfiltNo); printf("filtNo:%d\n", pAlfParam->filtNo); printf("filterPattern:"); for (i=0; ifilterPattern[i]); printf("\n"); printf("startSecondFilter:%d\n", pAlfParam->startSecondFilter); printf("noFilters:%d\n", pAlfParam->noFilters); printf("varIndTab:"); for (i=0; ivarIndTab[i]); printf("\n"); printf("filters_per_group_diff:%d\n", pAlfParam->filters_per_group_diff); printf("filters_per_group:%d\n", pAlfParam->filters_per_group); printf("codedVarBins:"); for (i=0; icodedVarBins[i]); printf("\n"); printf("forceCoeff0:%d\n", pAlfParam->forceCoeff0); printf("predMethod:%d\n", pAlfParam->predMethod); for (ind=0; indfilters_per_group_diff; ind++) { printf("coeffmulti(%d):", ind); for (i=0; icoeffmulti[ind][i]); printf("\n"); } printf("minKStart:%d\n", pAlfParam->minKStart); printf("maxScanVal:%d\n", pAlfParam->maxScanVal); printf("kMinTab:"); for(Int scanPos = 0; scanPos < pAlfParam->maxScanVal; scanPos++) { printf("%d ", pAlfParam->kMinTab[scanPos]); } printf("\n"); printf("chroma_idc:%d\n", pAlfParam->chroma_idc); printf("tap_chroma:%d\n", pAlfParam->tap_chroma); printf("chroma_coeff:"); for(Int scanPos = 0; scanPos < pAlfParam->num_coeff_chroma; scanPos++) { printf("%d ", pAlfParam->coeff_chroma[scanPos]); } printf("\n"); } /** encode merge flag * \param pcCU * \param uiAbsPartIdx * \param uiPUIdx * \returns Void */ Void TEncEntropy::encodeMergeFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPUIdx ) { UInt uiNumCand = 0; for(UInt uiIter = 0; uiIter < MRG_MAX_NUM_CANDS; uiIter++ ) { if( pcCU->getNeighbourCandIdx( uiIter, uiAbsPartIdx ) == uiIter + 1 ) { uiNumCand++; break; } } if ( uiNumCand ) { // at least one merge candidate exists m_pcEntropyCoderIf->codeMergeFlag( pcCU, uiAbsPartIdx ); } else { assert( !pcCU->getMergeFlag( uiAbsPartIdx ) ); } } #if HHI_MRG_SKIP /** encode merge index * \param pcCU * \param uiAbsPartIdx * \param uiPUIdx * \param bRD * \returns Void */ Void TEncEntropy::encodeMergeIndex( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPUIdx, Bool bRD ) #else Void TEncEntropy::encodeMergeIndex( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPUIdx ) #endif { #if HHI_MRG_SKIP if( bRD ) { uiAbsPartIdx = 0; assert( pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ); } #endif UInt uiNumCand = 0; for(UInt uiIter = 0; uiIter < MRG_MAX_NUM_CANDS; uiIter++ ) { if( pcCU->getNeighbourCandIdx( uiIter, uiAbsPartIdx ) == uiIter + 1 ) { uiNumCand++; } } #if HHI_MPI if( pcCU->getSlice()->getSPS()->getUseMVI() && pcCU->getSlice()->getSliceType() != I_SLICE && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N ) uiNumCand++; #endif if ( uiNumCand > 1 ) { m_pcEntropyCoderIf->codeMergeIndex( pcCU, uiAbsPartIdx ); } } #if HHI_INTER_VIEW_RESIDUAL_PRED Void TEncEntropy::encodeResPredFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPUIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } // check whether flag is coded ROTVS( pcCU->getSlice()->getSPS()->isDepth () ); ROFVS( pcCU->getSlice()->getSPS()->getViewId () ); ROFVS( pcCU->getSlice()->getSPS()->getMultiviewResPredMode() ); ROTVS( pcCU->isIntra ( uiAbsPartIdx ) ); ROFVS( pcCU->getResPredAvail ( uiAbsPartIdx ) ); // encode flag m_pcEntropyCoderIf->codeResPredFlag( pcCU, uiAbsPartIdx ); } #endif Void TEncEntropy::encodeAlfParam(ALFParam* pAlfParam) { m_pcEntropyCoderIf->codeAlfFlag(pAlfParam->alf_flag); if (!pAlfParam->alf_flag) return; Int pos; codeAux(pAlfParam); codeFilt(pAlfParam); // filter parameters for chroma m_pcEntropyCoderIf->codeAlfUvlc(pAlfParam->chroma_idc); if(pAlfParam->chroma_idc) { m_pcEntropyCoderIf->codeAlfUvlc((pAlfParam->tap_chroma-5)/2); // filter coefficients for chroma for(pos=0; posnum_coeff_chroma; pos++) { m_pcEntropyCoderIf->codeAlfSvlc(pAlfParam->coeff_chroma[pos]); } } // region control parameters for luma m_pcEntropyCoderIf->codeAlfFlag(pAlfParam->cu_control_flag); if (pAlfParam->cu_control_flag) { assert( (pAlfParam->cu_control_flag && m_pcEntropyCoderIf->getAlfCtrl()) || (!pAlfParam->cu_control_flag && !m_pcEntropyCoderIf->getAlfCtrl())); m_pcEntropyCoderIf->codeAlfCtrlDepth(); } } Void TEncEntropy::encodeAlfCtrlFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) uiAbsPartIdx = 0; m_pcEntropyCoderIf->codeAlfCtrlFlag( pcCU, uiAbsPartIdx ); } #if TSB_ALF_HEADER Void TEncEntropy::encodeAlfCtrlParam( ALFParam* pAlfParam ) { m_pcEntropyCoderIf->codeAlfFlagNum( pAlfParam->num_alf_cu_flag, pAlfParam->num_cus_in_frame ); for(UInt i=0; inum_alf_cu_flag; i++) { m_pcEntropyCoderIf->codeAlfCtrlFlag( pAlfParam->alf_cu_flag[i] ); } } #endif /** 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 ); } Void TEncEntropy::xEncodeTransformSubdiv( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiInnerQuadIdx, UInt& uiYCbfFront3, UInt& uiUCbfFront3, UInt& uiVCbfFront3 ) { const UInt uiSubdiv = pcCU->getTransformIdx( uiAbsPartIdx ) + pcCU->getDepth( uiAbsPartIdx ) > uiDepth; const UInt uiLog2TrafoSize = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth()]+2 - uiDepth; #if CAVLC_RQT_CBP if(pcCU->getSlice()->getSymbolMode() == 0) { m_pcEntropyCoderIf->codeCbfTrdiv( pcCU, uiAbsPartIdx, uiDepth ); } else {//CABAC #endif if( pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTRA && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_NxN && uiDepth == pcCU->getDepth(uiAbsPartIdx) ) { 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) ); #if HHI_RQT_FORCE_SPLIT_ACC2_PU UInt uiCtx = uiDepth; const UInt uiTrMode = uiDepth - pcCU->getDepth( uiAbsPartIdx ); #if HHI_RQT_FORCE_SPLIT_NxN const Bool bNxNOK = pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_NxN && uiTrMode > 0; #else const Bool bNxNOK = pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_NxN; #endif #if HHI_RQT_FORCE_SPLIT_RECT const Bool bSymmetricOK = pcCU->getPartitionSize( uiAbsPartIdx ) >= SIZE_2NxN && pcCU->getPartitionSize( uiAbsPartIdx ) < SIZE_NxN && uiTrMode > 0; #else const Bool bSymmetricOK = pcCU->getPartitionSize( uiAbsPartIdx ) >= SIZE_2NxN && pcCU->getPartitionSize( uiAbsPartIdx ) < SIZE_NxN; #endif const Bool bNeedSubdivFlag = pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N || pcCU->getPredictionMode( uiAbsPartIdx ) == MODE_INTRA || bNxNOK || bSymmetricOK; if( bNeedSubdivFlag ) { m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSubdiv, uiCtx ); } #else m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSubdiv, uiDepth ); #endif } #if CAVLC_RQT_CBP } #endif if(pcCU->getSlice()->getSymbolMode() == 0) { if( uiSubdiv ) { ++uiDepth; const UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (uiDepth << 1); UInt uiDummyCbfY = 0; UInt uiDummyCbfU = 0; UInt uiDummyCbfV = 0; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 0, uiDummyCbfY, uiDummyCbfU, uiDummyCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 1, uiDummyCbfY, uiDummyCbfU, uiDummyCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 2, uiDummyCbfY, uiDummyCbfU, uiDummyCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 3, uiDummyCbfY, uiDummyCbfU, uiDummyCbfV ); } } else { if( pcCU->getPredictionMode(uiAbsPartIdx) != MODE_INTRA && uiLog2TrafoSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { const UInt uiTrDepthCurr = uiDepth - pcCU->getDepth( uiAbsPartIdx ); const Bool bFirstCbfOfCU = uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() || uiTrDepthCurr == 0; if( bFirstCbfOfCU || uiLog2TrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr - 1 ) ) { if ( uiInnerQuadIdx == 3 && uiUCbfFront3 == 0 && uiLog2TrafoSize < pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { uiUCbfFront3++; } else { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr ); uiUCbfFront3 += pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr ); } } if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr - 1 ) ) { if ( uiInnerQuadIdx == 3 && uiVCbfFront3 == 0 && uiLog2TrafoSize < pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { uiVCbfFront3++; } else { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr ); uiVCbfFront3 += pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr ); } } } else if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { 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 ) ); uiUCbfFront3 += pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrDepthCurr ); uiVCbfFront3 += pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrDepthCurr ); } } if( uiSubdiv ) { ++uiDepth; const UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (uiDepth << 1); UInt uiCurrentCbfY = 0; UInt uiCurrentCbfU = 0; UInt uiCurrentCbfV = 0; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 0, uiCurrentCbfY, uiCurrentCbfU, uiCurrentCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 1, uiCurrentCbfY, uiCurrentCbfU, uiCurrentCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 2, uiCurrentCbfY, uiCurrentCbfU, uiCurrentCbfV ); uiAbsPartIdx += uiQPartNum; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 3, uiCurrentCbfY, uiCurrentCbfU, uiCurrentCbfV ); uiYCbfFront3 += uiCurrentCbfY; uiUCbfFront3 += uiCurrentCbfU; uiVCbfFront3 += uiCurrentCbfV; } else { { DTRACE_CABAC_V( 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" ); } UInt uiLumaTrMode, uiChromaTrMode; pcCU->convertTransIdx( uiAbsPartIdx, pcCU->getTransformIdx( uiAbsPartIdx ), uiLumaTrMode, uiChromaTrMode ); 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 { if ( pcCU->getPredictionMode( uiAbsPartIdx ) != MODE_INTRA && uiInnerQuadIdx == 3 && uiYCbfFront3 == 0 && uiUCbfFront3 == 0 && uiVCbfFront3 == 0 && uiLog2TrafoSize < pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() && pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, uiLumaTrMode ) ) { uiYCbfFront3++; } else { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, uiLumaTrMode ); uiYCbfFront3 += pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, uiLumaTrMode ); } } if( pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTRA ) { Bool bCodeChroma = true; if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { UInt uiQPDiv = pcCU->getPic()->getNumPartInCU() >> ( ( uiDepth - 1 ) << 1 ); bCodeChroma = ( ( uiAbsPartIdx % uiQPDiv ) == 0 ); } if( bCodeChroma ) { m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiChromaTrMode ); m_pcEntropyCoderIf->codeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiChromaTrMode ); } } } } } // transform index Void TEncEntropy::encodeTransformIdx( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD ) { assert( !bRD ); // parameter bRD can be removed if( bRD ) uiAbsPartIdx = 0; DTRACE_CABAC_V( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tdecodeTransformIdx()\tCUDepth=" ) DTRACE_CABAC_V( uiDepth ) DTRACE_CABAC_T( "\n" ) UInt temp = 0; UInt temp1 = 0; UInt temp2 = 0; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 0, temp, temp1, temp2 ); } // Intra direction for Luma Void TEncEntropy::encodeIntraDirModeLuma ( TComDataCU* pcCU, UInt uiAbsPartIdx ) { m_pcEntropyCoderIf->codeIntraDirLumaAng( pcCU, uiAbsPartIdx ); } // 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; PartSize eSize = pcCU->getPartitionSize( uiAbsPartIdx ); if( pcCU->isIntra( uiAbsPartIdx ) ) // If it is Intra mode, encode intra prediction mode. { if( eSize == SIZE_NxN ) // if it is NxN size, encode 4 intra directions. { UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; // if it is NxN size, this size might be the smallest partition size. encodeIntraDirModeLuma( pcCU, uiAbsPartIdx ); encodeIntraDirModeLuma( pcCU, uiAbsPartIdx + uiPartOffset ); encodeIntraDirModeLuma( pcCU, uiAbsPartIdx + uiPartOffset*2 ); encodeIntraDirModeLuma( pcCU, uiAbsPartIdx + uiPartOffset*3 ); encodeIntraDirModeChroma( pcCU, uiAbsPartIdx, bRD ); } else // if it is not NxN size, encode 1 intra directions { encodeIntraDirModeLuma ( pcCU, uiAbsPartIdx ); encodeIntraDirModeChroma( pcCU, uiAbsPartIdx, bRD ); } } else // if it is Inter mode, encode motion vector and reference index { if ( pcCU->getSlice()->getSPS()->getUseMRG() ) { encodePUWise( pcCU, uiAbsPartIdx, bRD ); } else { #if MS_LCEC_LOOKUP_TABLE_EXCEPTION if ( pcCU->getSlice()->getSymbolMode() == 0 ) { if ( pcCU->isSuroundingRefIdxException( uiAbsPartIdx ) ) { pcCU->getSlice()->setRefIdxCombineCoding( false ); } else { pcCU->getSlice()->setRefIdxCombineCoding( true ); } } #endif encodeInterDir( pcCU, uiAbsPartIdx, bRD ); { if ( pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_0 ) > 0 ) // if ( ref. frame list0 has at least 1 entry ) { encodeRefFrmIdx ( pcCU, uiAbsPartIdx, REF_PIC_LIST_0, bRD ); encodeMvd ( pcCU, uiAbsPartIdx, REF_PIC_LIST_0, bRD ); encodeMVPIdx ( pcCU, uiAbsPartIdx, REF_PIC_LIST_0 ); } if ( pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_1 ) > 0 ) // if ( ref. frame list1 has at least 1 entry ) { encodeRefFrmIdx ( pcCU, uiAbsPartIdx, REF_PIC_LIST_1, bRD ); encodeMvd ( pcCU, uiAbsPartIdx, REF_PIC_LIST_1, bRD ); encodeMVPIdx ( pcCU, uiAbsPartIdx, REF_PIC_LIST_1 ); } } } } } /** encode inter direction * \param pcCU * \param uiAbsPartIdx * \param bRD * \returns Void */ Void TEncEntropy::encodeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { assert( !pcCU->isIntra( uiAbsPartIdx ) ); assert( pcCU->getSlice()->isInterB()); if( bRD ) uiAbsPartIdx = 0; if ( !pcCU->getSlice()->isInterB() ) { return; } UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; switch ( pcCU->getPartitionSize( uiAbsPartIdx ) ) { case SIZE_2Nx2N: { m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); break; } case SIZE_2NxN: { m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); uiAbsPartIdx += uiPartOffset << 1; m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); break; } case SIZE_Nx2N: { m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); uiAbsPartIdx += uiPartOffset; m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); break; } case SIZE_NxN: { for ( Int iPartIdx = 0; iPartIdx < 4; iPartIdx++ ) { m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); uiAbsPartIdx += uiPartOffset; } break; } default: break; } return; } /** encode motion information for every PU block * \param pcCU * \param uiAbsPartIdx * \param bRD * \returns Void * This function is called only if merge is enabled. */ 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 ) { #if PART_MRG if (pcCU->getWidth( uiAbsPartIdx ) <= 8 || uiNumPU != 2 || uiPartIdx != 0) #endif encodeMergeFlag( pcCU, uiSubPartIdx, uiPartIdx ); if ( pcCU->getMergeFlag( uiSubPartIdx ) ) { encodeMergeIndex( pcCU, uiSubPartIdx, uiPartIdx ); } else { #if MS_LCEC_LOOKUP_TABLE_EXCEPTION if ( pcCU->getSlice()->getSymbolMode() == 0 ) { if ( pcCU->isSuroundingRefIdxException( uiAbsPartIdx ) ) { pcCU->getSlice()->setRefIdxCombineCoding( false ); } else { pcCU->getSlice()->setRefIdxCombineCoding( true ); } } #endif 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 DCM_COMB_LIST if(pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_C)>0 && pcCU->getInterDir( uiAbsPartIdx ) != 3) { if ((eRefList== REF_PIC_LIST_1) || ( pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) == 1 ) ) { return; } if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else { #endif if ( ( pcCU->getSlice()->getNumRefIdx( eRefList ) == 1 ) ) { return; } if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } #if DCM_COMB_LIST } #endif 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 )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } return; } Void TEncEntropy::encodeMVPIdx( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList, Bool bRD ) { if( bRD ) uiAbsPartIdx = 0; UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; switch ( pcCU->getPartitionSize( uiAbsPartIdx ) ) { case SIZE_2Nx2N: { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_2NxN: { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset << 1; if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_Nx2N: { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_NxN: { for ( Int iPartIdx = 0; iPartIdx < 4; iPartIdx++ ) { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) && (pcCU->getMVPNum(eRefList, uiAbsPartIdx)> 1) && (pcCU->getAMVPMode(uiAbsPartIdx) == AM_EXPL) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; } break; } default: break; } return; } Void TEncEntropy::encodeViewIdx(Int iViewIdx ) { m_pcEntropyCoderIf->codeViewIdx(iViewIdx); } /** encode reference frame index * \param pcCU * \param uiAbsPartIdx * \param eRefList * \param bRD * \returns Void */ Void TEncEntropy::encodeRefFrmIdx( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList, Bool bRD ) { assert( !pcCU->isIntra( uiAbsPartIdx ) ); if( bRD ) uiAbsPartIdx = 0; #if DCM_COMB_LIST if(pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_C) > 0) { UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; switch ( pcCU->getPartitionSize( uiAbsPartIdx ) ) { case SIZE_2Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } break; } case SIZE_2NxN: { if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } uiAbsPartIdx += uiPartOffset << 1; if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } break; } case SIZE_Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } uiAbsPartIdx += uiPartOffset; if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } break; } case SIZE_NxN: { for ( Int iPartIdx = 0; iPartIdx < 4; iPartIdx++ ) { if ( pcCU->getInterDir( uiAbsPartIdx ) != 3 && eRefList== REF_PIC_LIST_0 && pcCU->getSlice()->getNumRefIdx( REF_PIC_LIST_C ) > 1) { if ( pcCU->getSlice()->getNumRefIdx ( REF_PIC_LIST_C ) > 1 ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, RefPicList(pcCU->getInterDir( uiAbsPartIdx )-1) ); } } else if (pcCU->getInterDir( uiAbsPartIdx ) == 3 && pcCU->getSlice()->getNumRefIdx( eRefList ) > 1) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } } uiAbsPartIdx += uiPartOffset; } break; } default: break; } } else { #endif if ( pcCU->getSlice()->getNumRefIdx( eRefList ) == 1 ) { return; } UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; switch ( pcCU->getPartitionSize( uiAbsPartIdx ) ) { case SIZE_2Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_2NxN: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset << 1; if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_NxN: { for ( Int iPartIdx = 0; iPartIdx < 4; iPartIdx++ ) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; } break; } default: break; } #if DCM_COMB_LIST } #endif return; } /** encode motion vector difference * \param pcCU * \param uiAbsPartIdx * \param eRefList * \param bRD * \returns Void */ Void TEncEntropy::encodeMvd( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList, Bool bRD ) { assert( !pcCU->isIntra( uiAbsPartIdx ) ); if( bRD ) uiAbsPartIdx = 0; UInt uiPartOffset = ( pcCU->getPic()->getNumPartInCU() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; switch ( pcCU->getPartitionSize( uiAbsPartIdx ) ) { case SIZE_2Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_2NxN: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset << 1; if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_Nx2N: { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } break; } case SIZE_NxN: { for ( Int iPartIdx = 0; iPartIdx < 4; iPartIdx++ ) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } uiAbsPartIdx += uiPartOffset; } break; } default: break; } 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 ); } // dQP Void TEncEntropy::encodeQP( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) uiAbsPartIdx = 0; if ( pcCU->getSlice()->getSPS()->getUseDQP() ) { m_pcEntropyCoderIf->codeDeltaQP( pcCU, uiAbsPartIdx ); } } // texture Void TEncEntropy::xEncodeCoeff( TComDataCU* pcCU, TCoeff* pcCoeff, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight, UInt uiTrIdx, UInt uiCurrTrIdx, TextType eType, Bool bRD ) { if ( pcCU->getCbf( uiAbsPartIdx, eType, uiTrIdx ) ) { #if SNY_DQP // dQP: only for LCU once if ( pcCU->getSlice()->getSPS()->getUseDQP() ) { if ( pcCU->getdQPFlag())// non-skip { encodeQP( pcCU, 0 ); pcCU->setdQPFlag(false); } } #endif//SNY_DQP UInt uiLumaTrMode, uiChromaTrMode; pcCU->convertTransIdx( uiAbsPartIdx, pcCU->getTransformIdx( uiAbsPartIdx ), uiLumaTrMode, uiChromaTrMode ); const UInt uiStopTrMode = eType == TEXT_LUMA ? uiLumaTrMode : uiChromaTrMode; assert(1); // as long as quadtrees are not used for residual transform if( uiTrIdx == uiStopTrMode ) { assert( !bRD ); // parameter bRD can be removed UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiDepth ] + 2; if( eType != TEXT_LUMA && uiLog2TrSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { UInt uiQPDiv = pcCU->getPic()->getNumPartInCU() >> ( ( uiDepth - 1 ) << 1 ); if( ( uiAbsPartIdx % uiQPDiv ) != 0 ) { return; } uiWidth <<= 1; uiHeight <<= 1; } m_pcEntropyCoderIf->codeCoeffNxN( pcCU, pcCoeff, uiAbsPartIdx, uiWidth, uiHeight, uiDepth, eType, bRD ); } else { { DTRACE_CABAC_V( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tgoing down\tdepth=" ); DTRACE_CABAC_V( uiDepth ); DTRACE_CABAC_T( "\ttridx=" ); DTRACE_CABAC_V( uiTrIdx ); DTRACE_CABAC_T( "\n" ); } if( uiCurrTrIdx <= uiTrIdx ) assert(1); UInt uiSize; uiWidth >>= 1; uiHeight >>= 1; uiSize = uiWidth*uiHeight; uiDepth++; uiTrIdx++; UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (uiDepth << 1); UInt uiIdx = uiAbsPartIdx; #if !CAVLC_RQT_CBP if(pcCU->getSlice()->getSymbolMode() == 0) { UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiDepth ] + 2; if( eType == TEXT_LUMA || uiLog2TrSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) m_pcEntropyCoderIf->codeBlockCbf(pcCU, uiIdx, eType, uiTrIdx, uiQPartNum); xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); } else { #endif xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); pcCoeff += uiSize; uiIdx += uiQPartNum; xEncodeCoeff( pcCU, pcCoeff, uiIdx, uiDepth, uiWidth, uiHeight, uiTrIdx, uiCurrTrIdx, eType, bRD ); #if !CAVLC_RQT_CBP } #endif { DTRACE_CABAC_V( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tgoing up\n" ); } } } } Void TEncEntropy::encodeCoeff( TComDataCU* pcCU, TCoeff* pCoeff, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight, UInt uiMaxTrMode, UInt uiTrMode, TextType eType, Bool bRD ) { xEncodeCoeff( pcCU, pCoeff, uiAbsPartIdx, uiDepth, uiWidth, uiHeight, uiTrMode, uiMaxTrMode, eType, bRD ); } /** encode coefficients * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param uiWidth * \param uiHeight * \returns Void */ Void TEncEntropy::encodeCoeff( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight ) { UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight(); UInt uiLumaOffset = uiMinCoeffSize*uiAbsPartIdx; UInt uiChromaOffset = uiLumaOffset>>2; UInt uiLumaTrMode, uiChromaTrMode; pcCU->convertTransIdx( uiAbsPartIdx, pcCU->getTransformIdx(uiAbsPartIdx), uiLumaTrMode, uiChromaTrMode ); if( pcCU->isIntra(uiAbsPartIdx) ) { DTRACE_CABAC_V( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tdecodeTransformIdx()\tCUDepth=" ) DTRACE_CABAC_V( uiDepth ) DTRACE_CABAC_T( "\n" ) UInt temp = 0; UInt temp1 = 0; UInt temp2 = 0; xEncodeTransformSubdiv( pcCU, uiAbsPartIdx, uiDepth, 0, temp, temp1, temp2 ); #if !CAVLC_RQT_CBP if (pcCU->getSlice()->getSymbolMode() == 0) { m_pcEntropyCoderIf->codeCbf( pcCU, uiAbsPartIdx, TEXT_ALL, 0 ); if(pcCU->getCbf(uiAbsPartIdx, TEXT_LUMA, 0)==0 && pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_U, 0)==0 && pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_V, 0)==0) return; } #endif } else { if (pcCU->getSlice()->getSymbolMode()==0) { #if !CAVLC_RQT_CBP m_pcEntropyCoderIf->codeCbf( pcCU, uiAbsPartIdx, TEXT_ALL, 0 ); if(pcCU->getCbf(uiAbsPartIdx, TEXT_LUMA, 0)==0 && pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_U, 0)==0 && pcCU->getCbf(uiAbsPartIdx, TEXT_CHROMA_V, 0)==0) return; #endif } else { #if HHI_MRG_SKIP #if HHI_MPI if( !(pcCU->getMergeFlag( uiAbsPartIdx ) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N && ( pcCU->getTextureModeDepth( uiAbsPartIdx ) == -1 || uiDepth == pcCU->getTextureModeDepth( uiAbsPartIdx ) ) ) ) #else if( !(pcCU->getMergeFlag( uiAbsPartIdx ) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ) ) #endif { m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); } #else m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); #endif if ( !pcCU->getQtRootCbf( uiAbsPartIdx ) ) { pcCU->setTrIdxSubParts( 0 , uiAbsPartIdx, uiDepth ); return; } } encodeTransformIdx( pcCU, uiAbsPartIdx, pcCU->getDepth(uiAbsPartIdx) ); } xEncodeCoeff( pcCU, pcCU->getCoeffY() + uiLumaOffset, uiAbsPartIdx, uiDepth, uiWidth, uiHeight, 0, uiLumaTrMode, TEXT_LUMA ); xEncodeCoeff( pcCU, pcCU->getCoeffCb() + uiChromaOffset, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight>>1, 0, uiChromaTrMode, TEXT_CHROMA_U ); xEncodeCoeff( pcCU, pcCU->getCoeffCr() + uiChromaOffset, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight>>1, 0, uiChromaTrMode, TEXT_CHROMA_V ); } Void TEncEntropy::encodeCoeffNxN( TComDataCU* pcCU, TCoeff* pcCoeff, UInt uiAbsPartIdx, UInt uiTrWidth, UInt uiTrHeight, UInt uiDepth, TextType eType, Bool bRD ) { // 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, bRD ); } Void TEncEntropy::estimateBit (estBitsSbacStruct* pcEstBitsSbac, UInt uiWidth, TextType eTType) { UInt uiCTXIdx; switch(uiWidth) { case 2: uiCTXIdx = 6; break; case 4: uiCTXIdx = 5; break; case 8: uiCTXIdx = 4; break; case 16: uiCTXIdx = 3; break; case 32: uiCTXIdx = 2; break; case 64: uiCTXIdx = 1; break; default: uiCTXIdx = 0; break; } eTType = eTType == TEXT_LUMA ? TEXT_LUMA : TEXT_CHROMA; m_pcEntropyCoderIf->estBit ( pcEstBitsSbac, uiCTXIdx, eTType ); } #if MTK_SAO /** encode QAO One Part * \param pQaoParam, iPartIdx */ Void TEncEntropy::encodeQAOOnePart(SAOParam* pQaoParam, Int iPartIdx ) { SAOQTPart* pAlfPart = &(pQaoParam->psSaoPart[iPartIdx]); UInt uiSymbol; if(!pAlfPart->bSplit) { if (pAlfPart->bEnableFlag) uiSymbol = pAlfPart->iBestType + 1; else uiSymbol = 0; m_pcEntropyCoderIf->codeAoUvlc(uiSymbol); if (pAlfPart->bEnableFlag) { for(Int i=0; i< pAlfPart->iLength; i++) { m_pcEntropyCoderIf->codeAoSvlc(pAlfPart->iOffset[i]); } } return; } //split if (pAlfPart->PartLevel < pQaoParam->iMaxSplitLevel) { for (Int i=0;iDownPartsIdx[i]); } } } /** encode QuadTree Split Flag * \param pQaoParam, iPartIdx */ Void TEncEntropy::encodeQuadTreeSplitFlag(SAOParam* pSaoParam, Int iPartIdx) { SAOQTPart* pSaoPart = &(pSaoParam->psSaoPart[iPartIdx]); if(pSaoPart->PartLevel < pSaoParam->iMaxSplitLevel) { //send one flag m_pcEntropyCoderIf->codeAoFlag( (pSaoPart->bSplit)?(1):(0) ); if(pSaoPart->bSplit) { for (Int i=0;iDownPartsIdx[i]); } } } } /** encode Sao Param * \param pQaoParam */ Void TEncEntropy::encodeSaoParam(SAOParam* pSaoParam) { m_pcEntropyCoderIf->codeAoFlag(pSaoParam->bSaoFlag); if (pSaoParam->bSaoFlag) { encodeQuadTreeSplitFlag(pSaoParam, 0); encodeQAOOnePart(pSaoParam, 0); } } #endif