HEVC代码学习11:xCompressCU函数
来源:互联网 发布:mysql添加唯一约束 编辑:程序博客网 时间:2024/05/18 00:12
今天接着之前进行了全局最小CU分块,来看进行CU分块的xCompressCU函数。
xCompressCU大致可以分为3个部分:
1.速率控制
2.帧间模式划分
3.帧内模式划分
通过自身迭代,实现CU、PU的划分。
我主要看的是帧间部分,帧内和QP只是粗略的看了下。下面来看xCompressCU中帧间模式的划分。
其中除skip模式中更新Merge模式代价使用xCheckRDCostMerge2Nx2N,其他的每个模式都会调用xCheckRDCostInter来计算代价并比较确定最优模式。
// ====================================================================================================================// Protected member functions// ====================================================================================================================/** Compress a CU block recursively with enabling sub-CTU-level delta QP * - for loop of QP value to compress the current CU with all possible QP*///迭代压缩CU块,初始输入为最大尺寸CU,直到达到最大深度结束#if AMP_ENC_SPEEDUPVoid TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth DEBUG_STRING_FN_DECLARE(sDebug_), PartSize eParentPartSize )#elseVoid TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth )#endif{ TComPic* pcPic = rpcBestCU->getPic(); DEBUG_STRING_NEW(sDebug) const TComPPS &pps=*(rpcTempCU->getSlice()->getPPS()); const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); // These are only used if getFastDeltaQp() is true const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMaxCUHeight()>>sps.getLog2DiffMaxMinCodingBlockSize(), sps.getMaxCUHeight(), 32u); // get Original YUV data from picture 获取原始YUV数据 m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu() ); // variable for Cbf fast mode PU decision Bool doNotBlockPu = true; Bool earlyDetectionSkipMode = false; //获取当前最优CU的范围 const UInt uiLPelX = rpcBestCU->getCUPelX(); const UInt uiRPelX = uiLPelX + rpcBestCU->getWidth(0) - 1; const UInt uiTPelY = rpcBestCU->getCUPelY(); const UInt uiBPelY = uiTPelY + rpcBestCU->getHeight(0) - 1; const UInt uiWidth = rpcBestCU->getWidth(0); Int iBaseQP = xComputeQP( rpcBestCU, uiDepth ); //计算QP Int iMinQP; Int iMaxQP; Bool isAddLowestQP = false; const UInt numberValidComponents = rpcBestCU->getPic()->getNumberValidComponents(); /*******************************************************分配QP*********************************************************/ //分配最大和最小QP if( uiDepth <= pps.getMaxCuDQPDepth() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP+idQP ); } else { iMinQP = rpcTempCU->getQP(0); iMaxQP = rpcTempCU->getQP(0); } if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } // transquant-bypass (TQB) processing loop variable initialisation --- TQP处理初始化 const Int lowestQP = iMinQP; // For TQB, use this QP which is the lowest non TQB QP tested (rather than QP'=0) - that way delta QPs are smaller, and TQB can be tested at all CU levels. if ( (pps.getTransquantBypassEnableFlag()) ) { isAddLowestQP = true; // mark that the first iteration is to cost TQB mode. iMinQP = iMinQP - 1; // increase loop variable range by 1, to allow testing of TQB mode along with other QPs if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; } } TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx()); const Bool bBoundary = !( uiRPelX < sps.getPicWidthInLumaSamples() && uiBPelY < sps.getPicHeightInLumaSamples() ); if ( !bBoundary ) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } m_cuChromaQpOffsetIdxPlus1 = 0; if (pcSlice->getUseChromaQpAdj()) { /* Pre-estimation of chroma QP based on input block activity may be performed * here, using for example m_ppcOrigYuv[uiDepth] */ /* To exercise the current code, the index used for adjustment is based on * block position */ Int lgMinCuSize = sps.getLog2MinCodingBlockSize() + std::max<Int>(0, sps.getLog2DiffMaxMinCodingBlockSize()-Int(pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth())); m_cuChromaQpOffsetIdxPlus1 = ((uiLPelX >> lgMinCuSize) + (uiTPelY >> lgMinCuSize)) % (pps.getPpsRangeExtension().getChromaQpOffsetListLen() + 1); } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); //当前CU初始化 /*******************************************************帧间模式选择************************************************************************/ // do inter modes, SKIP and 2Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) //非I帧 { // 2Nx2N if(m_pcEncCfg->getUseEarlySkipDetection()) //使用earlyDetectionSkipMode { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); //计算2Nx2N的代价并比较 rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );//by Competition for inter_2Nx2N } // SKIP 更新为Merge模式的代价 xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU DEBUG_STRING_PASS_INTO(sDebug), &earlyDetectionSkipMode );//by Merge for inter_2Nx2N rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(!m_pcEncCfg->getUseEarlySkipDetection()) //不使用earlyDetectionSkipMode { // 2Nx2N, NxN xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); //计算2Nx2N的代价并比较 rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode()) //使用快速模式 { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } if (bIsLosslessMode) // Restore loop variable if lossless mode was searched. { iQP = iMinQP; } } if(!earlyDetectionSkipMode) //非earlyDetectionSkipMode { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); // If lossless, then iQP is irrelevant for subsequent modules. if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); //帧间模式选择NxN,2NxN,Nx2N // do inter modes, NxN, 2NxN, and Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) //非I帧 { // 2Nx2N, NxN if(!( (rpcBestCU->getWidth(0)==8) && (rpcBestCU->getHeight(0)==8) )) //块尺寸不能为8x8 { if( uiDepth == sps.getLog2DiffMaxMinCodingBlockSize() && doNotBlockPu) { //计算NxN模式代价并比较 xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_NxN DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if(doNotBlockPu) { //计算Nx2N代价并比较 xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { //计算2NxN代价并比较 xCheckRDCostInter ( rpcBestCU, rpcTempCU, SIZE_2NxN DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxN) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } //尝试非对称尺寸 //! Try AMP (SIZE_2NxnU, SIZE_2NxnD, SIZE_nLx2N, SIZE_nRx2N) if(sps.getUseAMP() && uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) {#if AMP_ENC_SPEEDUP Bool bTestAMP_Hor = false, bTestAMP_Ver = false;#if AMP_MRG Bool bTestMergeAMP_Hor = false, bTestMergeAMP_Ver = false; deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver, bTestMergeAMP_Hor, bTestMergeAMP_Ver);#else deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver);#endif //! Do horizontal AMP if ( bTestAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } }#if AMP_MRG else if ( bTestMergeAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } }#endif //! Do horizontal AMP if ( bTestAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } }#if AMP_MRG else if ( bTestMergeAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } }#endif#else xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_SIZE_nRx2NnLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );#endif } } /***************************************************************帧内模式选择********************************************************/ // do normal intra modes // speedup for inter frames Double intraCost = 0.0; if((rpcBestCU->getSlice()->getSliceType() == I_SLICE) || ((!m_pcEncCfg->getDisableIntraPUsInInterSlices()) && ( (rpcBestCU->getCbf( 0, COMPONENT_Y ) != 0) || ((rpcBestCU->getCbf( 0, COMPONENT_Cb ) != 0) && (numberValidComponents > COMPONENT_Cb)) || ((rpcBestCU->getCbf( 0, COMPONENT_Cr ) != 0) && (numberValidComponents > COMPONENT_Cr)) // avoid very complex intra if it is unlikely ))) { xCheckRDCostIntra( rpcBestCU, rpcTempCU, intraCost, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if( uiDepth == sps.getLog2DiffMaxMinCodingBlockSize() ) { if( rpcTempCU->getWidth(0) > ( 1 << sps.getQuadtreeTULog2MinSize() ) ) { Double tmpIntraCost; xCheckRDCostIntra( rpcBestCU, rpcTempCU, tmpIntraCost, SIZE_NxN DEBUG_STRING_PASS_INTO(sDebug) ); intraCost = std::min(intraCost, tmpIntraCost); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } } // test PCM if(sps.getUsePCM() && rpcTempCU->getWidth(0) <= (1<<sps.getPCMLog2MaxSize()) && rpcTempCU->getWidth(0) >= (1<<sps.getPCMLog2MinSize()) ) { UInt uiRawBits = getTotalBits(rpcBestCU->getWidth(0), rpcBestCU->getHeight(0), rpcBestCU->getPic()->getChromaFormat(), sps.getBitDepths().recon); UInt uiBestBits = rpcBestCU->getTotalBits(); if((uiBestBits > uiRawBits) || (rpcBestCU->getTotalCost() > m_pcRdCost->calcRdCost(uiRawBits, 0))) { xCheckIntraPCM (rpcBestCU, rpcTempCU); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if (bIsLosslessMode) // Restore loop variable if lossless mode was searched. { iQP = iMinQP; } } } if( rpcBestCU->getTotalCost()!=MAX_DOUBLE ) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]); m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcBestCU, 0, uiDepth, true ); rpcBestCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcBestCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcBestCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcBestCU->getTotalBits(), rpcBestCU->getTotalDistortion() ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]); } } // copy original YUV samples to PCM buffer if( rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isLosslessCoded(0) && (rpcBestCU->getIPCMFlag(0) == false)) { xFillPCMBuffer(rpcBestCU, m_ppcOrigYuv[uiDepth]); } if( uiDepth == pps.getMaxCuDQPDepth() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP+idQP ); } else if( uiDepth < pps.getMaxCuDQPDepth() ) { iMinQP = iBaseQP; iMaxQP = iBaseQP; } else { const Int iStartQP = rpcTempCU->getQP(0); iMinQP = iStartQP; iMaxQP = iStartQP; } if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; // If all TUs are forced into using transquant bypass, do not loop here. } const Bool bSubBranch = bBoundary || !( m_pcEncCfg->getUseEarlyCU() && rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isSkipped(0) ); if( bSubBranch && uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() && (!getFastDeltaQp() || uiWidth > fastDeltaQPCuMaxSize || bBoundary)) { // further split for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = false; // False at this level. Next level down may set it to true. rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); UChar uhNextDepth = uiDepth+1; TComDataCU* pcSubBestPartCU = m_ppcBestCU[uhNextDepth]; TComDataCU* pcSubTempPartCU = m_ppcTempCU[uhNextDepth]; DEBUG_STRING_NEW(sTempDebug) for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ ) { pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. if( ( pcSubBestPartCU->getCUPelX() < sps.getPicWidthInLumaSamples() ) && ( pcSubBestPartCU->getCUPelY() < sps.getPicHeightInLumaSamples() ) ) { if ( 0 == uiPartUnitIdx) //initialize RD with previous depth buffer { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } else { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); }#if AMP_ENC_SPEEDUP DEBUG_STRING_NEW(sChild) if ( !(rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isInter(0)) ) { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth DEBUG_STRING_PASS_INTO(sChild), NUMBER_OF_PART_SIZES ); } else { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth DEBUG_STRING_PASS_INTO(sChild), rpcBestCU->getPartitionSize(0) ); } DEBUG_STRING_APPEND(sTempDebug, sChild)#else xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth );#endif rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); // Keep best part data to current temporary data. xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth ); } else { pcSubBestPartCU->copyToPic( uhNextDepth ); rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); } } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); if( !bBoundary ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcTempCU, 0, uiDepth, true ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); } rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP()) { Bool hasResidual = false; for( UInt uiBlkIdx = 0; uiBlkIdx < rpcTempCU->getTotalNumPart(); uiBlkIdx ++) { if( ( rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Y) || (rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Cb) && (numberValidComponents > COMPONENT_Cb)) || (rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Cr) && (numberValidComponents > COMPONENT_Cr)) ) ) { hasResidual = true; break; } } if ( hasResidual ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQP( rpcTempCU, 0, false ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // dQP bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); Bool foundNonZeroCbf = false; rpcTempCU->setQPSubCUs( rpcTempCU->getRefQP( 0 ), 0, uiDepth, foundNonZeroCbf ); assert( foundNonZeroCbf ); } else { rpcTempCU->setQPSubParts( rpcTempCU->getRefQP( 0 ), 0, uiDepth ); // set QP to default QP } } m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); // If the configuration being tested exceeds the maximum number of bytes for a slice / slice-segment, then // a proper RD evaluation cannot be performed. Therefore, termination of the // slice/slice-segment must be made prior to this CTU. // This can be achieved by forcing the decision to be that of the rpcTempCU. // The exception is each slice / slice-segment must have at least one CTU. if (rpcBestCU->getTotalCost()!=MAX_DOUBLE) { const Bool isEndOfSlice = pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES && ((pcSlice->getSliceBits()+rpcBestCU->getTotalBits())>pcSlice->getSliceArgument()<<3) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()); const Bool isEndOfSliceSegment = pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && ((pcSlice->getSliceSegmentBits()+rpcBestCU->getTotalBits()) > pcSlice->getSliceSegmentArgument()<<3) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()); // Do not need to check slice condition for slice-segment since a slice-segment is a subset of a slice. if(isEndOfSlice||isEndOfSliceSegment) { rpcBestCU->getTotalCost()=MAX_DOUBLE; } } //比较分块和更大一级块的代价 xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTempDebug) DEBUG_STRING_PASS_INTO(false) ); // RD compare current larger prediction // with sub partitioned prediction. } } DEBUG_STRING_APPEND(sDebug_, sDebug); rpcBestCU->copyToPic(uiDepth); // Copy Best data to Picture for next partition prediction. xCopyYuv2Pic( rpcBestCU->getPic(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu(), uiDepth, uiDepth ); // Copy Yuv data to picture Yuv if (bBoundary) { return; } // Assert if Best prediction mode is NONE // Selected mode's RD-cost must be not MAX_DOUBLE. assert( rpcBestCU->getPartitionSize ( 0 ) != NUMBER_OF_PART_SIZES ); assert( rpcBestCU->getPredictionMode( 0 ) != NUMBER_OF_PREDICTION_MODES ); assert( rpcBestCU->getTotalCost ( ) != MAX_DOUBLE );}
阅读全文
1 0
- HEVC代码学习11:xCompressCU函数
- HEVC中xcompressCU函数
- HEVC-xCompressCU
- HEVC-xCompressCU
- HEVC-xCompressCU
- HEVC代码追踪(七):xCompressCu
- HEVC 中主要LCU分析函数xCompressCU说明
- HEVC 中主要LCU分析函数xCompressCU说明
- HEVC代码学习2:TAppEncTop::encode函数
- HEVC代码学习3:TEncTop::encode函数
- HEVC代码学习7:xPatternSearchFracDIF函数
- HEVC代码学习8:xMotionEstimation函数
- HEVC代码学习9:getInterMergeCandidates函数
- HEVC代码学习12:xCheckRDCostInter函数
- HEVC代码学习13:predInterSearch函数
- HEVC代码学习14:motionCompensation函数
- HEVC代码学习15:AMVP相关函数
- HEVC代码学习20:xPatternSearchFast函数
- 高斯消元(浮点数)
- Xcode 8 错误 dyld: Library not loaded: @rpath/libswiftCore.dylib 解决办法
- 在android上启动分屏的方法
- 面向对象的三个基本特征和五大设计原则
- Markdown 语法还是不熟悉,CSDN 自带的说明,发出来看看效果
- HEVC代码学习11:xCompressCU函数
- 论文笔记——UNSUPERVISED REPRESENTATION LEARNING WITH DEEP CONVOLUTIONAL GENERATIVE ADVERSARIAL NETWORKS
- 贴片功率电感的作用
- 指针直接赋值和strcpy的区别
- 游(qbxt)
- Android——实现简单沉浸式状态栏
- 使用httpie下载图片
- ajax结合接口 分页插件
- Android-APK反编译和回编译