QP的详解:https://blog.csdn.net/liangjiubujiu/article/details/
代码部分:https://blog.csdn.net/HEVC_CJL/article/details/
PU的帧内预测部分(MPM):https://www.cnblogs.com/DwyaneTalk/p/5711342.html
率失真优化方法部分:新一代高效视频编码H.265/HEVC:原理、标准与实现——万帅 杨付正 编著——电子工业出版社
一、QP的详解
Quantizer Parameter(量化参数),反映了空间细节压缩情况。值越小,量化越精细,图像质量越高,产生的码流也越长。如QP小,大部分的细节都会被保留;QP增大,一些细节丢失,码率降低,但图像失真加强和质量下降。
量化参数QP是量化步长Qstep的序号。对于亮度(Luma)编码而言,量化步长Qstep共有52个值,QP取值0—51,对于色度(Chroma)编码,Q的取值0—39。
QP取最小值0 时,表示量化最精细;相反,QP取最大值51时,表示量化是最粗糙的。QP和Qstep具有线性相关性,Qstep随着QP的增加而增加,每当QP值增加6,Qstep便增加一倍。

讯享网


(QP应该有52个值,我也不太懂这里为啥原博只有50个,不过可以根据关系推算)
二、MPM确定策略:
对于luma CU:有35个可选的帧内预测方向(Plannar(0)、DC(1)和方向预测(2~34)),对于mininum size的luma CB,可以平均划分成4个方形的subblocks,对于每个subblock进行独立的帧内预测,有独立的intra prediction mode。也就是说对于帧内预测的CU,可以进行2Nx2N和NxN两种PU划分模式,且NxN模式只有对mininum size CB可以使用。
一个帧内luma PU块,预测模式确定之后,需要对预测模式进行编码。HEVC中在进行帧内预测模式编码时,先为每个intra PU确定3个最可能模式(MPM),假设为S={M1,M2,M3}。然后通过判断luma PU的帧内预测模式是否在S中,如果在S中,则需要2bit编码预测模式在S中的索引,否则需要5bit编码预测模式在另外32种模式中的索引。
对于luma PU,确定最可能3个预测模式是根据当前PU左边和上边的预测模式,假设左边和上边的预测模式分别是A和B,如果左边或上边PU不是帧内预测模式或是PCM模式,则A或B为DC;另外,如果上边PU块不在当前CTU内,那么B也为DC。确定好A和B之后:
当A=B时,如果A,B都大于2,即A和B都不是Planar或DC,那么:
M1=A;
M2=2+((A-2-1+32)%32)
M3=2+((A-2+1)%32)
当A=B时,如果A,B至少有一个小于2,即A或B是Planar或DC,那么:
M1=Planar,M2=DC,M3=26(竖直方向预测)
当A!=B时,M1=A,M2=B,对于M3按照下面规则决定:
如果A和B都不是Planar,那么M3=Planar;
如果A和B都不是DC,那么M3=DC;
否则,说明{A,B}={Planar,DC},那么M3=26。
当candModeList(即为上述的S)建立好了之后,可以利用该列表对当前的PU模式信息进行编码,具体如下:
(1)若当前PU的最优模式(记为Mode C,下同)在candModeList中出现,则只需要编码ModeC在candModeList中出现的位置即可;
(2)若ModeC未在candModeList中出现,则按照以下步骤编码ModeC
1)将candModeList中的候选模式按照从小到大重新排列;
2)遍历重新排列后的三个候选模式,分别于ModeC进行比较,若
ModeC>=candModeList[i]
ModeC自减一,遍历结束后对ModeC的最终值进行编码。

三、RD(Rate Distortion)率失真的优化方法
CTU是H.265/HEVC的基本编码单元,每一个CTU可以被划分为不同的编码单元CU,每个CU可以使用不同的PU模式和TU模式,每个PU又可以选择不同的预测模式。因此,可以把CTU编码参数的优化过程分成:CTU层主要选择不同的CU划分模式,CU层主要选择不同的PU模式和TU模式,PU层主要选择不同的预测模式。由于主要编码参数属于CTU及其以下层,只关注CTU及其以下层编码单元编码参数的优化过程。
1、CTU优化方法
H.265/HEVC参考模型HM采用拉格朗日优化方法为每个CTU确定除量化参数外的编码参数,主要包括CU划分模式、CU的PU模式和TU模式、PU的预测参数等。一个CTU包含大量的编码参数组合,采用分级的方式对不同层的编码参数进行确定,主要步骤如下:
(1)遍历所有的CU划分模式进行编码,按照(11-11)确定最优CU划分模式。

(2)对其中的每个CU,遍历所有的PU模式和TU模式组合,按照(11-12)确定最优的PU和TU模式。

(3)对其中的每个PU,遍历所有的预测模式,按照(11-13)或(11-14)确定最优的预测模式。







2.快速模式判决策略


3.CTU编码参数优化流程
(实在是太多了,在HEVC那本书的第337页)
四、代码部分
Void TEncSearch::estIntraPredQT(TComDataCU* pcCU,//指向当前CU块 TComYuv* pcOrgYuv,//指向原始YUV样本序列 TComYuv* pcPredYuv,//指向预测YUV样本序列 TComYuv* pcResiYuv,//指向剩余YUV样本序列 TComYuv* pcRecoYuv,//指向重建YUV样本序列 UInt& ruiDistC, Bool bLumaOnly) { UInt uiDepth = pcCU->getDepth(0); //!< 当前CU的深度 UInt uiNumPU = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... ) UInt uiInitTrDepth = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth UInt uiWidth = pcCU->getWidth(0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2 UInt uiHeight = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2 UInt uiQNumParts = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标 UInt uiWidthBit = pcCU->getIntraSizeIdx(0); UInt uiOverallDistY = 0; UInt uiOverallDistC = 0; UInt CandNum;//记录一记录候选模式数量, Double CandCostList[FAST_UDI_MAX_RDMODE_NUM];//CandCostList计算每种候选模式代价的变量;FAST_UDI_MAX_RDMODE_NUM=在快速udi估计循环中进行RD比较的最大次数 //===== set QP and clear Cbf =====设置QP和清空Cbf(cbf是code-block-flag标志) if (pcCU->getSlice()->getPPS()->getUseDQP() == true) { pcCU->setQPSubParts(pcCU->getQP(0), 0, uiDepth); } else { pcCU->setQPSubParts(pcCU->getSlice()->getSliceQp(), 0, uiDepth); } //===== loop over partitions =====遍历分区 UInt uiPartOffset = 0; //!< 用于记录当前PU的Zorder坐标 for (UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts) //!< 对当前CU中的每个PU进行遍历 { //===== init pattern for luma prediction =====用于luma预测的init模式 Bool bAboveAvail = false; Bool bLeftAvail = false; pcCU->getPattern()->initPattern(pcCU, uiInitTrDepth, uiPartOffset); // set parameters from CU data for accessing neighbouring pixels从CU数据中设置参数来访问邻近的像素 // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波 pcCU->getPattern()->initAdiPattern(pcCU, uiPartOffset, uiInitTrDepth, m_piYuvExt, m_iYuvExtStride, m_iYuvExtHeight, bAboveAvail, bLeftAvail); //===== determine set of modes to be tested (using prediction signal only) =====确定要测试的模式集(仅使用预测信号) Int numModesAvailable = 35; //total number of Intra modes帧内预测模式的总数 Pel* piOrg = pcOrgYuv->getLumaAddr(uiPU, uiWidth); Pel* piPred = pcPredYuv->getLumaAddr(uiPU, uiWidth); UInt uiStride = pcPredYuv->getStride(); UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];//FAST_UDI_MAX_RDMODE_NUM=在快速udi估计循环中进行RD比较的最大次数 Int numModesForFullRD = g_aucIntraModeNumFast[uiWidthBit]; //!< MPM数目 //!< g_aucIntraModeNumFast[] = {3, 8, 8, 3, 3, 3, 3}; 2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128 Bool doFastSearch = (numModesForFullRD != numModesAvailable); //!< 此处doFastSearch恒为真,MPM为3,帧内模式为35 if (doFastSearch) { assert(numModesForFullRD < numModesAvailable); for (Int i = 0; i < numModesForFullRD; i++) { CandCostList[i] = MAX_DOUBLE;// ///< max. value of Double-type value } CandNum = 0; for (Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++) //!< 遍历35种帧内预测模式 { UInt uiMode = modeIdx; //! 调用亮度帧内预测函数 predIntraLumaAng(pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail); // use hadamard transform here在这里使用hadamard变换 UInt uiSad = m_pcRdCost->calcHAD(piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight); UInt iModeBits = xModeBitsIntra(pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth); Double cost = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda(); CandNum += xUpdateCandList(uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList); } #if FAST_UDI_USE_MPM // UDI---Unified Directional Intra统一定向帧内 Int uiPreds[3] = { -1, -1, -1 }; Int iMode = -1; //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2 Int numCand = pcCU->getIntraDirLumaPredictor(uiPartOffset, uiPreds, &iMode); //!< 获取亮度帧内预测模式的三个MPM:most probable mode if (iMode >= 0) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode { numCand = iMode; } for (Int j = 0; j < numCand; j++) { Bool mostProbableModeIncluded = false; Int mostProbableMode = uiPreds[j]; //!< 取出MPM for (Int i = 0; i < numModesForFullRD; i++) { mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); //!< 检查MPMs是否被uiRdModeList所包含 } if (!mostProbableModeIncluded) //!< 如果没被包含,则将该MPM包含到uiRdModeList里 { uiRdModeList[numModesForFullRD++] = mostProbableMode; } } #endif // FAST_UDI_USE_MPM } //!< if (doFastSearch) else { for (Int i = 0; i < numModesForFullRD; i++) { uiRdModeList[i] = i; } } //===== check modes (using r-d costs) =====RD(Rate Distortion)率失真、RD costs率失真代价 //! 帧内预测模式**值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出 //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做 //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到**预测模式(在HM9.0中会得到包括次优解在内的两个 //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对**(及次优)预测模式的所有分割模式遍历一遍, //! 得到最终的**结果 #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiSecondBestMode = MAX_UINT; Double dSecondBestPUCost = MAX_DOUBLE; #endif UInt uiBestPUMode = 0; //!< 存放**预测模式 UInt uiBestPUDistY = 0; //!< 存放**预测模式对应的亮度失真值 UInt uiBestPUDistC = 0; //!< 存放**预测模式对应的色度失真值 Double dBestPUCost = MAX_DOUBLE; //!< 存放**预测模式对应的总代价 for (UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++) //!< 遍历存储在uiRdModeList里的模式 { // set luma prediction mode设置luma预测模式 UInt uiOrgMode = uiRdModeList[uiMode]; pcCU->setLumaIntraDirSubParts(uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth); // set context models设置上下文模型 if (m_bUseSBACRD) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } // determine residual for partition确定分区的剩余值 UInt uiPUDistY = 0; //!< 存放当前预测模式对应的亮度失真值 UInt uiPUDistC = 0; //!< 存放当前预测模式对应的色度失真值 Double dPUCost = 0.0; //!< 存放当前预测模式对应的代价 #if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true,仅仅对当前深度的失真值进行计算 xRecurIntraCodingQT(pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost);//重点就在倒数第二个参数上,它控制着函数中bCheckSplit的值,如果该值为ture,则TU只进行当前深度的计算,如果该值为false,则TU进行所有深度的计算。 #else xRecurIntraCodingQT(pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost); #endif // check r-d cost检查RD代价 if (dPUCost < dBestPUCost) //!< 更新**预测模式相关参数,如果当前PU的预测模式的cost要比**模式的cost小,则做如下工作: { #if HHI_RQT_INTRA_SPEEDUP_MOD uiSecondBestMode = uiBestPUMode;//首先把**模式和**模式代价付给第二佳模式和第二佳模式代价 dSecondBestPUCost = dBestPUCost; #endif uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost;//将当前的模式的各个参数赋给**模式 xSetIntraResultQT(pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv); UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ((pcCU->getDepth(0) + uiInitTrDepth) << 1); ::memcpy(m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[0], pcCU->getCbf(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[1], pcCU->getCbf(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[2], pcCU->getCbf(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof(UChar)); } #if HHI_RQT_INTRA_SPEEDUP_MOD else if (dPUCost < dSecondBestPUCost)//如果当前PU的预测模式的cost要比第二佳模式的cost要小,则把当前模式的各个参数赋给第二佳模式 { uiSecondBestMode = uiOrgMode; dSecondBestPUCost = dPUCost; } #endif } // Mode loop #if HHI_RQT_INTRA_SPEEDUP // 1 tests one best mode with full rqt 测试一个**模式的所有rqt(我也不知道这个rqt是什么鬼。。。哭) #if HHI_RQT_INTRA_SPEEDUP_MOD// 0 tests two best mode with full rqt 测试两个**模式的所有rqt for (UInt ui = 0; ui < 2; ++ui) #endif { #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiOrgMode = ui ? uiSecondBestMode : uiBestPUMode; if (uiOrgMode == MAX_UINT) { break;//如果是两种**模式,取**模式赋给uiOrgMode } #else UInt uiOrgMode = uiBestPUMode; //!< 如果是一种**模式,设置uiOrgMode模式为**预测模式 #endif pcCU->setLumaIntraDirSubParts(uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth); // set context models 设置上下文模型 if (m_bUseSBACRD) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } // determine residual for partition 确定用来划分的残差 UInt uiPUDistY = 0; //!< 存放当前预测模式对应的亮度失真值 UInt uiPUDistC = 0; //!< 存放当前预测模式对应的色度失真值 Double dPUCost = 0.0; //!< 存放当前预测模式对应的代价 //! 注意这个函数倒数第二个参数,此时为false,对所有深度的失真值进行计算 xRecurIntraCodingQT(pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost); // check r-d cost检查r-d cost if (dPUCost < dBestPUCost)//如果模式的PU的代价小于**模式的PU代价,则用当前的模式代替**模式 { uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost; xSetIntraResultQT(pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv); UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ((pcCU->getDepth(0) + uiInitTrDepth) << 1); ::memcpy(m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[0], pcCU->getCbf(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[1], pcCU->getCbf(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempCbf[2], pcCU->getCbf(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof(UChar)); ::memcpy(m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof(UChar)); } } // Mode loop 遍历了所有的模式 #endif //--- update overall distortion ---更新所有的失真 uiOverallDistY += uiBestPUDistY; uiOverallDistC += uiBestPUDistC; //--- update transform index and cbf ---更新传输索引和cbf UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ((pcCU->getDepth(0) + uiInitTrDepth) << 1); ::memcpy(pcCU->getTransformIdx() + uiPartOffset, m_puhQTTempTrIdx, uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getCbf(TEXT_LUMA) + uiPartOffset, m_puhQTTempCbf[0], uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getCbf(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempCbf[1], uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getCbf(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempCbf[2], uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getTransformSkip(TEXT_LUMA) + uiPartOffset, m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof(UChar)); ::memcpy(pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof(UChar)); //--- set reconstruction for next intra prediction blocks ---设置下个帧内预测块的重建 if (uiPU != uiNumPU - 1) { Bool bSkipChroma = false; Bool bChromaSame = false; UInt uiLog2TrSize = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth() >> (pcCU->getDepth(0) + uiInitTrDepth)] + 2; if (!bLumaOnly && uiLog2TrSize == 2) { assert(uiInitTrDepth > 0); bSkipChroma = (uiPU != 0); bChromaSame = true; } UInt uiCompWidth = pcCU->getWidth(0) >> uiInitTrDepth; UInt uiCompHeight = pcCU->getHeight(0) >> uiInitTrDepth; UInt uiZOrder = pcCU->getZorderIdxInCU() + uiPartOffset; Pel* piDes = pcCU->getPic()->getPicYuvRec()->getLumaAddr(pcCU->getAddr(), uiZOrder); UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride(); Pel* piSrc = pcRecoYuv->getLumaAddr(uiPartOffset); UInt uiSrcStride = pcRecoYuv->getStride(); for (UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride) { for (UInt uiX = 0; uiX < uiCompWidth; uiX++) { piDes[uiX] = piSrc[uiX]; } } if (!bLumaOnly && !bSkipChroma) { if (!bChromaSame) { uiCompWidth >>= 1; uiCompHeight >>= 1; } piDes = pcCU->getPic()->getPicYuvRec()->getCbAddr(pcCU->getAddr(), uiZOrder); uiDesStride = pcCU->getPic()->getPicYuvRec()->getCStride(); piSrc = pcRecoYuv->getCbAddr(uiPartOffset); uiSrcStride = pcRecoYuv->getCStride(); for (UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride) { for (UInt uiX = 0; uiX < uiCompWidth; uiX++) { piDes[uiX] = piSrc[uiX]; } } piDes = pcCU->getPic()->getPicYuvRec()->getCrAddr(pcCU->getAddr(), uiZOrder); piSrc = pcRecoYuv->getCrAddr(uiPartOffset); 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 ====更新PU数据 pcCU->setLumaIntraDirSubParts(uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth); pcCU->copyToPic(uiDepth, uiPU, uiInitTrDepth); } // PU loop if (uiNumPU > 1) { // set Cbf for all blocks对于所有块设置cbf UInt uiCombCbfY = 0; UInt uiCombCbfU = 0; UInt uiCombCbfV = 0; UInt uiPartIdx = 0; for (UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts) { uiCombCbfY |= pcCU->getCbf(uiPartIdx, TEXT_LUMA, 1); uiCombCbfU |= pcCU->getCbf(uiPartIdx, TEXT_CHROMA_U, 1); uiCombCbfV |= pcCU->getCbf(uiPartIdx, TEXT_CHROMA_V, 1); } for (UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++) { pcCU->getCbf(TEXT_LUMA)[uiOffs] |= uiCombCbfY; pcCU->getCbf(TEXT_CHROMA_U)[uiOffs] |= uiCombCbfU; pcCU->getCbf(TEXT_CHROMA_V)[uiOffs] |= uiCombCbfV; } } //===== reset context models =====重新设置上下文模式 if (m_bUseSBACRD) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } //===== set distortion (rate and r-d costs are determined later) =====速率和r-d失真确定之后的失真设置 ruiDistC = uiOverallDistC; pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC; }
讯享网
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/120373.html