在之前的 HEVC代码学习37:帧内预测代码整体学习 中已经提到,estIntraPredLumaQT是亮度帧内预测的入口函数,下面将对该函数进行详细学习。

estIntraPredLumaQT中完成了亮度分量的帧内预测,其主要流程如下:
一、初始化各种参数。
二、为了减少率失真优化次数,HEVC中默认使用帧内快速搜索算法,将分粗选和细选两个阶段进行。如果不使用快速搜索,将对所有帧内预测模式进行率失真优化。
1.粗选阶段:遍历35种帧内预测模式使用predIntraAng计算预测值,计算比较哈达玛失真,调用xUpdateCandList构建全率失真优化候选列表。全率失真优化候选列表长度numModesForFullRD由块宽度决定。注意在粗选阶段全部使用哈达玛变换计算失真,提高速度。
2.细选阶段:调用getIntraDirPredictor构建MPM列表,加入全率失真优化候选列表中。遍历全率失真优化候选列表,调用xRecurIntraCodingLumaQT进行变换量化重构,计算率失真代价,注意在这里该函数倒数第二个参数是bCheckFirst=true,表示会按照四叉树的方式继续向下划分。比较率失真代价,找到最优模式。
三、对获得的最优模式再次调用xRecurIntraCodingLumaQT,此时倒数第二个参数设置为false,检测同一模式下,bCheckFirst为true和false的情况下,选出最优模式为最终的亮度帧内预测模式。
四、收尾工作,记录信息:设置重建块、Cbf、上下文模型、总失真等。

其中调用了重要函数:predIntraAng(计算帧内预测模式的预测值)、getIntraDirPredictor(利用临近PU构建MPM列表)、xRecurIntraCodingLumaQT(进行帧内亮度分量的变换量化重构,计算率失真代价)。

代码分析:

//亮度分量预测
VoidTEncSearch::estIntraPredLumaQT(TComDataCU* pcCU,TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,TComYuv*    pcRecoYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE]
DEBUG_STRING_FN_DECLARE(sDebug))
{const UInt         uiDepth               = pcCU->getDepth(0);       //划分深度const UInt         uiInitTrDepth         = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1;     //当CU为2Nx2N时,初始变换深度为0;否则为1。const UInt         uiNumPU               = 1<<(2*uiInitTrDepth);        //PU分块数const UInt         uiQNumParts           = pcCU->getTotalNumPart() >> 2;        const UInt         uiWidthBit            = pcCU->getIntraSizeIdx(0);const ChromaFormat chFmt                 = pcCU->getPic()->getChromaFormat();       //颜色格式const UInt         numberValidComponents = getNumberValidComponents(chFmt);const TComSPS     &sps                   = *(pcCU->getSlice()->getSPS());           //SPSconst TComPPS     &pps                   = *(pcCU->getSlice()->getPPS());           //PPSDistortion   uiOverallDistY        = 0;UInt         CandNum;           //候选数Double       CandCostList[ FAST_UDI_MAX_RDMODE_NUM ];       //候选代价列表Pel          resiLumaPU[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];        //亮度残差Bool    bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++){bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise}bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());// Lambda calculation at equivalent Qp of 4 is recommended because at that Qp, the quantisation divisor is 1.
#if FULL_NBITconst Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?sqrt(0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12) / 3.0))): m_pcRdCost->getSqrtLambda();
#else//计算Lambdaconst Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?sqrt(0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12 - 6 * (sps.getBitDepth(CHANNEL_TYPE_LUMA) - 8)) / 3.0))): m_pcRdCost->getSqrtLambda();
#endif//===== set QP and clear Cbf =====//设置QP,清除Cbfif ( pps.getUseDQP() == true){pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );}else{pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );}//===== loop over partitions =====//迭代分块TComTURecurse tuRecurseCU(pcCU, 0);TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT);do      //遍历一个CU的所有PU{const UInt uiPartOffset=tuRecurseWithPU.GetAbsPartIdxTU();      //当前PU的偏移//  for( UInt uiPU = 0, uiPartOffset=0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts )//{//===== init pattern for luma prediction =====DEBUG_STRING_NEW(sTemp2)//===== determine set of modes to be tested (using prediction signal only) =====Int numModesAvailable     = 35; //total number of Intra modes       可用模式总数UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];     //根据块宽度设定全率失真优化的模式数Int numModesForFullRD = m_pcEncCfg->getFastUDIUseMPMEnabled()?g_aucIntraModeNumFast_UseMPM[ uiWidthBit ] : g_aucIntraModeNumFast_NotUseMPM[ uiWidthBit ];// this should always be trueassert (tuRecurseWithPU.ProcessComponentSection(COMPONENT_Y));initIntraPatternChType( tuRecurseWithPU, COMPONENT_Y, true DEBUG_STRING_PASS_INTO(sTemp2) );        //初始化/**************************************************快速搜索粗选阶段**************************************************/Bool doFastSearch = (numModesForFullRD != numModesAvailable);       //默认开启快速搜索if (doFastSearch)           //快速搜索  {assert(numModesForFullRD < numModesAvailable);for( Int i=0; i < numModesForFullRD; i++ )      //对numModesForFullRD个候选设置代价为最大{CandCostList[ i ] = MAX_DOUBLE;}CandNum = 0;const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y);       //获取Y分量PUconst UInt uiAbsPartIdx=tuRecurseWithPU.GetAbsPartIdxTU();          //PU地址Pel* piOrg         = pcOrgYuv ->getAddr( COMPONENT_Y, uiAbsPartIdx );       //原始图像Pel* piPred        = pcPredYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );       //预测图像UInt uiStride      = pcPredYuv->getStride( COMPONENT_Y );           //跨度DistParam distParam;        //失真参数const Bool bUseHadamard=pcCU->getCUTransquantBypass(0) == 0;        //是否使用哈达玛变换m_pcRdCost->setDistParam(distParam, sps.getBitDepth(CHANNEL_TYPE_LUMA), piOrg, uiStride, piPred, uiStride, puRect.width, puRect.height, bUseHadamard);      //使用哈达玛变换初始化失真distParam.bApplyWeight = false;for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ )      //遍历35种帧内预测模式{UInt       uiMode = modeIdx;        //当前模式Distortion uiSad  = 0;      //失真//参考采样滤波const Bool bUseFilter=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, uiMode, puRect.width, puRect.height, chFmt, sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag());//计算相应模式的预测值predIntraAng( COMPONENT_Y, uiMode, piOrg, uiStride, piPred, uiStride, tuRecurseWithPU, bUseFilter, TComPrediction::UseDPCMForFirstPassIntraEstimation(tuRecurseWithPU, uiMode) );// use hadamard transform hereuiSad+=distParam.DistFunc(&distParam);      //计算哈达玛失真UInt   iModeBits = 0;           //bit数// NB xModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.iModeBits+=xModeBitsIntra( pcCU, uiMode, uiPartOffset, uiDepth, CHANNEL_TYPE_LUMA );        //计算bit数Double cost      = (Double)uiSad + (Double)iModeBits * sqrtLambdaForFirstPass;      //使用哈达玛失真计算率失真代价#if DEBUG_INTRA_SEARCH_COSTSstd::cout << "1st pass mode " << uiMode << " SAD = " << uiSad << ", mode bits = " << iModeBits << ", cost = " << cost << "\n";
#endif//比较代价更新候选列表CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );}/**************************************************快速搜索细选阶段**************************************************/if (m_pcEncCfg->getFastUDIUseMPMEnabled())          {Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1};        //初始化MPM列表,长度为3Int iMode = -1;//利用临近PU构建MPMpcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode );//当有可用MPM时,numCand就等于MPM对应的模式,否则为NUM_MOST_PROBABLE_MODESconst Int numCand = ( iMode >= 0 ) ? iMode : Int(NUM_MOST_PROBABLE_MODES);//把MPM加入全率失真优化列表中for( Int j=0; j < numCand; j++){Bool mostProbableModeIncluded = false;Int mostProbableMode = uiPreds[j];for( Int i=0; i < numModesForFullRD; i++){mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);}if (!mostProbableModeIncluded){uiRdModeList[numModesForFullRD++] = mostProbableMode;}}}}else        //不启用快速搜索,将所有模式都加入全率失真优化列表中{for( Int i=0; i < numModesForFullRD; i++){uiRdModeList[i] = i;}}//===== check modes (using r-d costs) =====
#if HHI_RQT_INTRA_SPEEDUP_MODUInt   uiSecondBestMode  = MAX_UINT;Double dSecondBestPUCost = MAX_DOUBLE;
#endifDEBUG_STRING_NEW(sPU)UInt       uiBestPUMode  = 0;       //最优模式Distortion uiBestPUDistY = 0;           //最优失真Double     dBestPUCost   = MAX_DOUBLE;      //最优代价#if ENVIRONMENT_VARIABLE_DEBUG_AND_TESTUInt max=numModesForFullRD;if (DebugOptionList::ForceLumaMode.isSet()){max=0;  // we are forcing a direction, so don't bother with mode check}for ( UInt uiMode = 0; uiMode < max; uiMode++)
#else//遍历全率失真优化列表for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ )
#endif{// set luma prediction modeUInt uiOrgMode = uiRdModeList[uiMode];      //原始模式//设置子块的帧内预测模式pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );DEBUG_STRING_NEW(sMode)// set context models//设置上下文模型m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );// determine residual for partitionDistortion uiPUDistY = 0;       //初始化当前失真Double     dPUCost   = 0.0; //初始化当前代价
#if HHI_RQT_INTRA_SPEEDUP//重构帧内亮度分量,计算率失真代价//注意倒数第二个参数bCheckFirst是true,表示会继续按照四叉树的方式向下划分xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, true, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );
#elsexRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );
#endif#if DEBUG_INTRA_SEARCH_COSTSstd::cout << "2nd pass [luma,chroma] mode [" << Int(pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiPartOffset)) << "," << Int(pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiPartOffset)) << "] cost = " << dPUCost << "\n";
#endif// check r-d cost//如果当前代价小于最优代价,将当前模式置为最优模式if( dPUCost < dBestPUCost ){DEBUG_STRING_SWAP(sPU, sMode)
#if HHI_RQT_INTRA_SPEEDUP_MODuiSecondBestMode  = uiBestPUMode;dSecondBestPUCost = dBestPUCost;
#endifuiBestPUMode  = uiOrgMode;uiBestPUDistY = uiPUDistY;dBestPUCost   = dPUCost;xSetIntraResultLumaQT( pcRecoYuv, tuRecurseWithPU );if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()){const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0;const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE );}}}UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID  ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_puhQTTempTransformSkipFlag[compID],  pcCU->getTransformSkip(compID)  + uiPartOffset, uiQPartNum * sizeof( UChar ) );}}
#if HHI_RQT_INTRA_SPEEDUP_MODelse if( dPUCost < dSecondBestPUCost ){uiSecondBestMode  = uiOrgMode;dSecondBestPUCost = dPUCost;}
#endif} // Mode loop#if HHI_RQT_INTRA_SPEEDUP
#if HHI_RQT_INTRA_SPEEDUP_MODfor( UInt ui =0; ui < 2; ++ui )
#endif{
#if HHI_RQT_INTRA_SPEEDUP_MODUInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;if( uiOrgMode == MAX_UINT ){break;}
#else/****************************************************已获得最优模式,使用最优模式进行预测变换量化重构等,计算最终的率失真代价*********************************************************///取最优模式UInt uiOrgMode = uiBestPUMode;
#endif#if ENVIRONMENT_VARIABLE_DEBUG_AND_TESTif (DebugOptionList::ForceLumaMode.isSet()){uiOrgMode = DebugOptionList::ForceLumaMode.getInt();}
#endif//设置子块的帧内预测模式pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );DEBUG_STRING_NEW(sModeTree)//加载上下文模型// set context modelsm_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );// determine residual for partitionDistortion uiPUDistY = 0;Double     dPUCost   = 0.0;//重构亮度分量//注意倒数第二个参数bCheckFirst是false,表示当前PU不再进行划分,即只处理当前深度的PU  xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, false, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sModeTree));// check r-d cost//检测同一模式下,bCheckFirst为true和false的情况下,选最优  if( dPUCost < dBestPUCost ){DEBUG_STRING_SWAP(sPU, sModeTree)uiBestPUMode  = uiOrgMode;uiBestPUDistY = uiPUDistY;dBestPUCost   = dPUCost;xSetIntraResultLumaQT( pcRecoYuv, tuRecurseWithPU );if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()){const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0;const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE );}}}const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID  ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_puhQTTempTransformSkipFlag[compID],  pcCU->getTransformSkip(compID)  + uiPartOffset, uiQPartNum * sizeof( UChar ) );}}} // Mode loop
#endifDEBUG_STRING_APPEND(sDebug, sPU)//--- update overall distortion ---uiOverallDistY += uiBestPUDistY;//--- update transform index and cbf ---const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( pcCU->getCbf( compID  ) + uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) );::memcpy( pcCU->getTransformSkip( compID  ) + uiPartOffset, m_puhQTTempTransformSkipFlag[compID ], uiQPartNum * sizeof( UChar ) );}//--- set reconstruction for next intra prediction blocks ---//设置重建块if( !tuRecurseWithPU.IsLastSection() ){const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y);const UInt  uiCompWidth   = puRect.width;const UInt  uiCompHeight  = puRect.height;const UInt  uiZOrder      = pcCU->getZorderIdxInCtu() + uiPartOffset;Pel*  piDes         = pcCU->getPic()->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), uiZOrder );const UInt  uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride( COMPONENT_Y);const Pel*  piSrc         = pcRecoYuv->getAddr( COMPONENT_Y, uiPartOffset );const UInt  uiSrcStride   = pcRecoYuv->getStride( COMPONENT_Y);for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ){for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ){piDes[ uiX ] = piSrc[ uiX ];}}}//=== update PU data ====pcCU->setIntraDirSubParts     ( CHANNEL_TYPE_LUMA, uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );} while (tuRecurseWithPU.nextSection(tuRecurseCU));//设置Cbfif( uiNumPU > 1 ){ // set Cbf for all blocksUInt uiCombCbfY = 0;UInt uiCombCbfU = 0;UInt uiCombCbfV = 0;UInt uiPartIdx  = 0;for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ){uiCombCbfY |= pcCU->getCbf( uiPartIdx, COMPONENT_Y,  1 );uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 );uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 );}for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ){pcCU->getCbf( COMPONENT_Y  )[ uiOffs ] |= uiCombCbfY;pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU;pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV;}}//===== reset context models =====//重置上下文模型m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);//===== set distortion (rate and r-d costs are determined later) =====//设置总失真pcCU->getTotalDistortion() = uiOverallDistY;
}

HEVC代码学习42:estIntraPredLumaQT函数相关推荐

  1. H.266代码学习:estIntraPredLumaQT函数

    之前 HEVC代码学习42:estIntraPredLumaQT函数 对HM中的estIntraPredLumaQT函数进行了学习,下面将对JEM中的该函数进行学习. estIntraPredLuma ...

  2. HEVC代码学习39:decodeCtu和xDecodeCU函数

    在之前 HEVC代码学习38:decompressSlice函数 学习中提到,解码slice会遍历所有CTU,调用decodeCtu和decompressCtu解码每一个CTU.下面就来学习一下dec ...

  3. HEVC代码学习——帧间预测:预测MV获取(xEstimateMvPredAMVP、fillMVPCand)

    HEVC帧间预测在AMVP模式下是依靠xEstimateMvPredAMVP函数获取预测MV(MVP)的. 这部分内容的学习还可以参考这两篇博客: HEVC代码学习15:AMVP相关函数 HM编码器代 ...

  4. HEVC代码学习:帧间预测——MVP过程中MV的获取、传递及存储

    作为一个视频编码小白,最近开始着手啃HEVC帧间预测的代码,想用博客记录一下自己的学习过程,也想与大家分享.交流一下. HEVC代码的学习主要是参考两位大神岳麓吹雪.NB_vol_1的博客以及HM参考 ...

  5. H.266代码学习:xEncodeCU函数

    之前在HEVC代码学习35:xEncodeCU函数中介绍过xEncodeCU函数,今天来看JEM中的xEncodeCU,其中难点在于QTBT编码结构. HM中使用compressCtu对每个CTU进行 ...

  6. H.266代码学习:xIntraCodingTUBlock函数

    今天来继续学习帧内编码的重要函数xIntraCodingTUBlock,上次 H.266代码学习:xRecurIntraCodingLumaQT函数 学习中提到,xIntraCodingTUBlock ...

  7. HEVC代码学习6:filterHor和filterVer函数

    帧间预测分为运动估计ME和运动补偿MV,其中用到了MV的亚像素搜索,需要使用filterHor和filterVer进行插值. 这里使用的是HM16,在之前版本中分为filterHorLuma.filt ...

  8. HEVC代码学习13:predInterSearch函数

    在上一章的xCheckRDCostInter学习中,我们知道了,进行帧间搜索的入口实际是predInterSearch,今天我们就来对他进行学习. 推荐看大神博客 http://blog.csdn.n ...

  9. HEVC代码学习27:calcRdCost函数

    之前在率失真代价TComRdCost类中提到,计算率失真代价的函数为:calcRdCost,下面就来学习一下. calcRdCost工作流程如下: 1.根据输入的失真类型eDFunc来设置λ. 2.根 ...

最新文章

  1. 自定义DateField,带时分秒
  2. 小说形象特征包括哪些方面_中高考常考题:怎样鉴赏散文中的形象 ?
  3. jvmti_JVMTI标记如何影响GC暂停
  4. CodeForces - 786BLegacy——线段树建图+最短路
  5. Java 获取文件的上级目录
  6. PPT无法直接在页面上播放插入的MP4视频
  7. Android 音视频深入 十三 OpenSL ES 制作音乐播放器,能暂停和调整音量(附源码下载)...
  8. java 学习笔记之AtomicInteger类的使用
  9. 表格送货单自动编号vba_制作仓库入库单,自动登记商品数据,这段代码只需三步搞定...
  10. 在netbeans中使用tomcat服务器的web应用,在NetBeans中创建Apache—Tomcat-web服务器
  11. dom4j 解析xml Error on line 9717 of document 不允许有匹配 [xX][mM][lL] 的处理指令目标
  12. CABAC 基础二-算术编码
  13. 怎么杀php源文件的木马,PHP一句话木马及查杀
  14. 【个人学习文章收集】
  15. Android Q - 设置默认输入法
  16. 代码坏味道与重构之数据泥团和基本类型偏执
  17. 网页视频倍速播放代码
  18. 计算机毕业设计基于Android宠物领养救助系统app——计算机毕业设计
  19. 【交互设计】七步打造手机网站
  20. 程序员必需知道的MySQL:MySQL和SQL Server的区别

热门文章

  1. MySQL数据类型及字段属性
  2. EAS BOS 新建单据后新增字段
  3. 新邮政法规定:邮政企业对平常邮件损失不赔偿
  4. K8S - 安装教程 和 体验(kubeadm)
  5. 聆思CSK6视觉AI开发套件使用——AI手势识别+头肩识别+编译helloworld
  6. MIUI双开的权限bug
  7. Jmeter正则表达式提取器的使用
  8. 谷歌Pixel 4神奇在哪儿? AI黑科技带来四大改变!
  9. 北京丰台线下处理交通违章的地方在哪里
  10. 魔都上海财务自由需要多少万?