作者: 66
1. 理论部分–快速率失真计算方法:
在后面的代码中使用了,这里说明一下对后面的理解很方便的事情:
速率失真(j )=像素误差) d )语法编码成本(R ),r是编码所需的比特,是系数。
其中,像素误差有MSE (最小均方误差)、MAD (最小平均绝对误差)等. 这里使用的MSE是原始像素和重构像素的差分平方和。
假设原始像素为org,重构像素为rec,偏移值为offset,则:
补偿前:
补偿后:
校正前后误差:
上式中的n是像素数,所以速率失真的差如下。
可知计算差分j比计算j少约n次,所以要选择最佳的就比较差分j即可。
2.补充:
在昨天剩下的两个函数saoCOmponentParamDist中,计算EO、BO模式后的merge和mergeup取相邻块的SAO模式来计算率失真,即函数saoCOmponentParamDist为eed
图一、正文涉及的编码结构(红色标记部分) ) ) ) ) ) ) )。
在saoCOmponentParamDist中计算合并速率失真的代码:
//mergeleftormergeupfor (intidxneighbor=0; idxNeighbor2; idx neighbor (saolcuparamneighbor=null; if (allowmergeleftaddrleft=0idx neighbor==0(//! 左邻块为{ saolcuparamneighbor=(Sao param-saolcuparam [ ycbcr ] [ addr left ] ); //! 左侧相邻块的SAO参数(else if (allowmergeupaddrup=0idx neighbor==1) /! 上邻块为{ saolcuparamneighbor=(Sao param-saolcuparam [ ycbcr ] [ addr up ] ); //! 上邻块的SAO参数(if ) saolcuparamneighbor!=null}{estdist=0; typeidx=saolcuparamneighbor-typeidx; //取相邻块的SAO模式if (typeidx=0) intmergebandposition=) typeidx==Sao_bo )? saolcuparamneighbor-subtype idx :0; Int merge_iOffset; for(classidx=0; classIdx m_iNumClass[typeIdx]; classidx } { merge _ I offset=saolcuparamneighbor-offset [ classidx ]; est dist=estsaodist (m _ icount [ ycbcr ] [ typeidx ] [ classidxmergebandposition1],merge_iOffset,m_iofsetorg ) } } else { estDist=0; } copysaounit (compsaoparam [ idx neighbor ],saoLcuParamNeighbor; compsaoparam [ idx neighbor ].mergeupflag=idx neighbor; compsaoparam [ idx neighbor ].mergeleftflag=! idxNeighbor; comp distortion [ idx neighbor1]=((双) estDist/lambda ); }}其中调用计算率失真的函数estSaoDist,函数定义如下:
inline int 64 tencsampleadaptiveoffset :3360 estsaodist (int 64 count,Int64 offset,Int64 of
fsetOrg, Int shift){ return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);}
这个函数用的是SAO率失真的快速计算方法,其中return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);对应于公式
具体解析看前理论部分。
前面说过,merge模式参与率失真的比较在rdoSaoUnitAll函数后半部分,下面贴后半部分代码:
//计算亮度和色度模式下的参数融合率失真 if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] ) { // Cost of new SAO_params初始化参数 m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]); m_pcRDGoOnSbacCoder->resetBits(); if (allowMergeLeft) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); } if (allowMergeUp) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); } for ( compIdx=0;compIdx<3;compIdx++) { if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1])) { m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx); //cost of merge } } rate = m_pcEntropyCoder->getNumberOfWrittenBits(); bestCost = compDistortion[0] + (Double)rate; m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); //计算参数融合模式下的率失真 for(Int mergeUp=0; mergeUp<2; ++mergeUp) { if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) ) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]); m_pcRDGoOnSbacCoder->resetBits(); if (allowMergeLeft) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); } if ( allowMergeUp && (mergeUp==1) ) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); } rate = m_pcEntropyCoder->getNumberOfWrittenBits();//码率 mergeCost = compDistortion[mergeUp+1] + (Double)rate;//率失真 if (mergeCost < bestCost)//更新最佳滤波模式 { bestCost = mergeCost; m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); for ( compIdx=0;compIdx<3;compIdx++) { mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp; mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp; if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1])) { copySao快三导师带计划赚钱app if (allowMergeLeft) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); } if ( allowMergeUp && (mergeUp==1) ) { m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); } rate = m_pcEntropyCoder->getNumberOfWrittenBits();//码率 mergeCost = compDistortion[mergeUp+1] + (Double)rate;//率失真 if (mergeCost < bestCost)//更新最佳滤波模式 { bestCost = mergeCost; m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); for ( compIdx=0;compIdx<3;compIdx++) { mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp; mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp; if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1])) { copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] ); } } } } }#if SAO_ENCODING_CHOICE#if SAO_ENCODING_CHOICE_CHROMAif( saoParam->saoLcuParam[0][addr].typeIdx == -1)//Y分量不存在SAO参数{ numNoSao[0]++;}if( saoParam->saoLcuParam[1][addr].typeIdx == -1)//CbCr分量不存在SAO参数{ numNoSao[1]+=2;}#else for ( compIdx=0;compIdx<3;compIdx++) { if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1) { numNoSao++; } }#endif#endif m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]); }//!< if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] ) }//!< for (idxX = 0; idxX< frameWidthInCU; idxX++) }//!< for (idxY = 0; idxY< frameHeightInCU; idxY++)#if SAO_ENCODING_CHOICE#if SAO_ENCODING_CHOICE_CHROMA if( !saoParam->bSaoFlag[0]) { m_depthSaoRate[0][depth] = 1.0; } else { m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU); } if( !saoParam->bSaoFlag[1]) { m_depthSaoRate[1][depth] = 1.0; } else { m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2); }#else if( depth == 0) { // update SAO Rate m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3); }#endif#endif } (转载请注明出处)