这篇博客写得不错,觉得对我对大家刚开始学习时会有帮助,于是转载之。原文地址:http://blog.youkuaiyun.com/hevc_cjl/article/details/8288572
- /** rate distortion optimization of all SAO units
- * \param saoParam SAO parameters
- * \param lambda
- * \param lambdaChroma
- */
- #if SAO_ENCODING_CHOICE
- Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
- #else
- Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
- #endif
- {
- Int idxY;
- Int idxX;
- Int frameHeightInCU = saoParam->numCuInHeight;
- Int frameWidthInCU = saoParam->numCuInWidth;
- Int j, k;
- Int addr = 0;
- Int addrUp = -1;
- Int addrLeft = -1;
- Int compIdx = 0;
- SaoLcuParam mergeSaoParam[3][2];
- Double compDistortion[3];
- saoParam->bSaoFlag[0] = true;
- saoParam->bSaoFlag[1] = true;
- saoParam->oneUnitFlag[0] = false;
- saoParam->oneUnitFlag[1] = false;
- saoParam->oneUnitFlag[2] = false;
- #if SAO_ENCODING_CHOICE
- #if SAO_ENCODING_CHOICE_CHROMA
- Int numNoSao[2];
- numNoSao[0] = 0;// Luma
- numNoSao[1] = 0;// Chroma
- if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
- {
- saoParam->bSaoFlag[0] = false;
- }
- if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
- {
- saoParam->bSaoFlag[1] = false;
- }
- #else
- Int numNoSao = 0;
- if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
- {
- saoParam->bSaoFlag[0] = false;
- saoParam->bSaoFlag[1] = false;
- }
- #endif
- #endif
- //!< 以LCU为单位对图像中的每个LCU进行遍历
- for (idxY = 0; idxY< frameHeightInCU; idxY++)
- {
- for (idxX = 0; idxX< frameWidthInCU; idxX++)
- {
- addr = idxX + frameWidthInCU*idxY; //!< 当前LCU地址
- addrUp = addr < frameWidthInCU ? -1:idxX + frameWidthInCU*(idxY-1); //!< 当前LCU上邻块地址
- addrLeft = idxX == 0 ? -1:idxX-1 + frameWidthInCU*idxY; //!< 当前LCU左邻块地址
- Int allowMergeLeft = 1;
- Int allowMergeUp = 1;
- UInt rate;
- Double bestCost, mergeCost;
- if (idxX!=0) //!< 非第1列
- {
- // check tile id and slice id //! 检查当前LCU与其左邻块是否属于同一个tile以及是否属于同一个slice,不同的话该邻块不可用
- if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
- {
- allowMergeLeft = 0; //!< 左邻块不可用
- }
- }
- else
- {
- allowMergeLeft = 0; //!< 第1列的左邻块均不可用
- }
- if (idxY!=0) //!< 非第1行
- {//! 检查当前LCU与其上邻块是否属于同一个tile以及是否属于同一个slice,不同的话该邻块不可用
- if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
- {
- allowMergeUp = 0; //!< 上邻块不可用
- }
- }
- else
- {
- allowMergeUp = 0; //!< 第1行的上邻块均不可用
- }
- compDistortion[0] = 0; //!< Y distortion
- compDistortion[1] = 0; //!< Cb distortion
- compDistortion[2] = 0; //!< Cr distortion
- m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
- if (allowMergeLeft)
- {
- m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); //!< 编码句法元素sao_merge_left_flag
- }
- if (allowMergeUp)
- {
- m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); //!< 编码句法元素sao_merge_up_flag
- }
- m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
- // reset stats Y, Cb, Cr
- for ( compIdx=0;compIdx<3;compIdx++)
- {
- for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
- {
- for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
- {
- m_iOffset [compIdx][j][k] = 0;
- if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){ //!< true && false
- m_iCount [compIdx][j][k] = m_count_PreDblk [addr][compIdx][j][k];
- m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
- }
- else
- {
- m_iCount [compIdx][j][k] = 0;
- m_iOffsetOrg[compIdx][j][k] = 0;
- }
- }
- }
- saoParam->saoLcuParam[compIdx][addr].typeIdx = -1;
- saoParam->saoLcuParam[compIdx][addr].mergeUpFlag = 0;
- saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
- saoParam->saoLcuParam[compIdx][addr].subTypeIdx = 0;
- #if SAO_ENCODING_CHOICE
- if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
- #endif
- {//! 统计BO和EO各个模式下,对应classIdx下滤波前的重建像素值与原始像素值的差值的总和,以及对classIdx的计数
- calcSaoStatsCu(addr, compIdx, compIdx);
- }
- }
- //!< Y分量最佳滤波模式的选择
- saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, lambda, &mergeSaoParam[0][0], &compDistortion[0]);
- //!< CbCr分量最佳滤波模式的选择
- sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
- 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);
- }
- }
- rate = m_pcEntropyCoder->getNumberOfWrittenBits();
- bestCost = compDistortion[0] + (Double)rate;
- m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
- // Cost of Merge
- 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]))
- {
- copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );
- }
- }
- }
- }
- }
- #if SAO_ENCODING_CHOICE
- #if SAO_ENCODING_CHOICE_CHROMA
- if( 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 SAO_ENCODING_CHOICE_CHROMA_BF
- 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
- m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
- m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
- #endif
- #else
- if( depth == 0)
- {
- // update SAO Rate
- m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
- }
- #endif
- #endif
- }
/** rate distortion optimization of all SAO units
* \param saoParam SAO parameters
* \param lambda
* \param lambdaChroma
*/
#if SAO_ENCODING_CHOICE
Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
#else
Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
#endif
{
Int idxY;
Int idxX;
Int frameHeightInCU = saoParam->numCuInHeight;
Int frameWidthInCU = saoParam->numCuInWidth;
Int j, k;
Int addr = 0;
Int addrUp = -1;
Int addrLeft = -1;
Int compIdx = 0;
SaoLcuParam mergeSaoParam[3][2];
Double compDistortion[3];
saoParam->bSaoFlag[0] = true;
saoParam->bSaoFlag[1] = true;
saoParam->oneUnitFlag[0] = false;
saoParam->oneUnitFlag[1] = false;
saoParam->oneUnitFlag[2] = false;
#if SAO_ENCODING_CHOICE
#if SAO_ENCODING_CHOICE_CHROMA
Int numNoSao[2];
numNoSao[0] = 0;// Luma
numNoSao[1] = 0;// Chroma
if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
{
saoParam->bSaoFlag[0] = false;
}
if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
{
saoParam->bSaoFlag[1] = false;
}
#else
Int numNoSao = 0;
if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
{
saoParam->bSaoFlag[0] = false;
saoParam->bSaoFlag[1] = false;
}
#endif
#endif
//!< 以LCU为单位对图像中的每个LCU进行遍历
for (idxY = 0; idxY< frameHeightInCU; idxY++)
{
for (idxX = 0; idxX< frameWidthInCU; idxX++)
{
addr = idxX + frameWidthInCU*idxY; //!< 当前LCU地址
addrUp = addr < frameWidthInCU ? -1:idxX + frameWidthInCU*(idxY-1); //!< 当前LCU上邻块地址
addrLeft = idxX == 0 ? -1:idxX-1 + frameWidthInCU*idxY; //!< 当前LCU左邻块地址
Int allowMergeLeft = 1;
Int allowMergeUp = 1;
UInt rate;
Double bestCost, mergeCost;
if (idxX!=0) //!< 非第1列
{
// check tile id and slice id //! 检查当前LCU与其左邻块是否属于同一个tile以及是否属于同一个slice,不同的话该邻块不可用
if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
{
allowMergeLeft = 0; //!< 左邻块不可用
}
}
else
{
allowMergeLeft = 0; //!< 第1列的左邻块均不可用
}
if (idxY!=0) //!< 非第1行
{//! 检查当前LCU与其上邻块是否属于同一个tile以及是否属于同一个slice,不同的话该邻块不可用
if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
{
allowMergeUp = 0; //!< 上邻块不可用
}
}
else
{
allowMergeUp = 0; //!< 第1行的上邻块均不可用
}
compDistortion[0] = 0; //!< Y distortion
compDistortion[1] = 0; //!< Cb distortion
compDistortion[2] = 0; //!< Cr distortion
m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
if (allowMergeLeft)
{
m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); //!< 编码句法元素sao_merge_left_flag
}
if (allowMergeUp)
{
m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); //!< 编码句法元素sao_merge_up_flag
}
m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
// reset stats Y, Cb, Cr
for ( compIdx=0;compIdx<3;compIdx++)
{
for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
{
for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
{
m_iOffset [compIdx][j][k] = 0;
if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){ //!< true && false
m_iCount [compIdx][j][k] = m_count_PreDblk [addr][compIdx][j][k];
m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
}
else
{
m_iCount [compIdx][j][k] = 0;
m_iOffsetOrg[compIdx][j][k] = 0;
}
}
}
saoParam->saoLcuParam[compIdx][addr].typeIdx = -1;
saoParam->saoLcuParam[compIdx][addr].mergeUpFlag = 0;
saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
saoParam->saoLcuParam[compIdx][addr].subTypeIdx = 0;
#if SAO_ENCODING_CHOICE
if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
#endif
{//! 统计BO和EO各个模式下,对应classIdx下滤波前的重建像素值与原始像素值的差值的总和,以及对classIdx的计数
calcSaoStatsCu(addr, compIdx, compIdx);
}
}
//!< Y分量最佳滤波模式的选择
saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, lambda, &mergeSaoParam[0][0], &compDistortion[0]);
//!< CbCr分量最佳滤波模式的选择
sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
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);
}
}
rate = m_pcEntropyCoder->getNumberOfWrittenBits();
bestCost = compDistortion[0] + (Double)rate;
m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
// Cost of Merge
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]))
{
copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );
}
}
}
}
}
#if SAO_ENCODING_CHOICE
#if SAO_ENCODING_CHOICE_CHROMA
if( 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 SAO_ENCODING_CHOICE_CHROMA_BF
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
m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
#endif
#else
if( depth == 0)
{
// update SAO Rate
m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
}
#endif
#endif
}