这篇博客写得不错,觉得对我对大家刚开始学习时会有帮助,于是转载之。原文地址:http://blog.csdn.net/hevc_cjl/article/details/8288601
- Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
- {
- Int typeIdx;
- Int64 estDist;
- Int classIdx;
- Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8); //!< 0 for 8bit-depth
- Int64 bestDist;
- SaoLcuParam* saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
- SaoLcuParam* saoLcuParamNeighbor = NULL;
- resetSaoUnit(saoLcuParam);
- resetSaoUnit(&compSaoParam[0]); //!< 左邻块的SAO参数
- resetSaoUnit(&compSaoParam[1]); //!< 上邻块的SAO参数
- Double dCostPartBest = MAX_DOUBLE;
- Double bestRDCostTableBo = MAX_DOUBLE;
- Int bestClassTableBo = 0;
- Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];
- Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];
- SaoLcuParam saoLcuParamRdo;
- Double estRate = 0;
- resetSaoUnit(&saoLcuParamRdo);
- m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
- m_pcRDGoOnSbacCoder->resetBits();
- m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
- dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ;
- copySaoUnit(saoLcuParam, &saoLcuParamRdo );
- bestDist = 0;
- for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) //!< 遍历所有的滤波类型
- {
- estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);//!< 得到当前滤波类型的失真值
- if( typeIdx == SAO_BO )
- {
- // Estimate Best Position
- Double currentRDCost = 0.0;
- for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
- {
- currentRDCost = 0.0;
- for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) //!< 依次以4个band为单位进行RDcost计算
- {
- currentRDCost += currentRdCostTableBo[uj];
- }
- if( currentRDCost < bestRDCostTableBo) //!< 更新最佳值
- {
- bestRDCostTableBo = currentRDCost;
- bestClassTableBo = i;
- }
- }
- // Re code all Offsets
- // Code Center
- estDist = 0;
- for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
- {
- estDist += currentDistortionTableBo[classIdx];
- }
- } //!< if( typeIdx == SAO_BO )
- resetSaoUnit(&saoLcuParamRdo);
- saoLcuParamRdo.length = m_iNumClass[typeIdx];
- saoLcuParamRdo.typeIdx = typeIdx;
- saoLcuParamRdo.mergeLeftFlag = 0;
- saoLcuParamRdo.mergeUpFlag = 0;
- saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
- for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
- {
- saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
- }
- m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
- m_pcRDGoOnSbacCoder->resetBits();
- m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
- estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
- m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
- if(m_dCost[yCbCr][typeIdx] < dCostPartBest) //!< 更新最佳值
- {
- dCostPartBest = m_dCost[yCbCr][typeIdx];
- copySaoUnit(saoLcuParam, &saoLcuParamRdo );
- bestDist = estDist;
- }
- } //!< for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
- compDistortion[0] += ((Double)bestDist/lambda);
- m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
- m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
- m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
- // merge left or merge up
- for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)
- {
- saoLcuParamNeighbor = NULL;
- if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) //!< 左邻块可用
- {
- saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]); //!< 取左邻块的SAO参数
- }
- else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) //!< 上邻块可用
- {
- saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]); //!< 取上邻块的SAO参数
- }
- if (saoLcuParamNeighbor!=NULL)
- {
- estDist = 0;
- typeIdx = saoLcuParamNeighbor->typeIdx;
- if (typeIdx>=0) //!< typeIdx为有效的
- {
- Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
- Int merge_iOffset;
- for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
- {
- merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
- estDist += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1], shift);
- }
- }
- else
- {
- estDist = 0;
- }
- copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
- compSaoParam[idxNeighbor].mergeUpFlag = idxNeighbor;
- compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
- compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
- }
- }
- }
Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
{
Int typeIdx;
Int64 estDist;
Int classIdx;
Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8); //!< 0 for 8bit-depth
Int64 bestDist;
SaoLcuParam* saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
SaoLcuParam* saoLcuParamNeighbor = NULL;
resetSaoUnit(saoLcuParam);
resetSaoUnit(&compSaoParam[0]); //!< 左邻块的SAO参数
resetSaoUnit(&compSaoParam[1]); //!< 上邻块的SAO参数
Double dCostPartBest = MAX_DOUBLE;
Double bestRDCostTableBo = MAX_DOUBLE;
Int bestClassTableBo = 0;
Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];
Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];
SaoLcuParam saoLcuParamRdo;
Double estRate = 0;
resetSaoUnit(&saoLcuParamRdo);
m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
m_pcRDGoOnSbacCoder->resetBits();
m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ;
copySaoUnit(saoLcuParam, &saoLcuParamRdo );
bestDist = 0;
for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) //!< 遍历所有的滤波类型
{
estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);//!< 得到当前滤波类型的失真值
if( typeIdx == SAO_BO )
{
// Estimate Best Position
Double currentRDCost = 0.0;
for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
{
currentRDCost = 0.0;
for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) //!< 依次以4个band为单位进行RDcost计算
{
currentRDCost += currentRdCostTableBo[uj];
}
if( currentRDCost < bestRDCostTableBo) //!< 更新最佳值
{
bestRDCostTableBo = currentRDCost;
bestClassTableBo = i;
}
}
// Re code all Offsets
// Code Center
estDist = 0;
for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
{
estDist += currentDistortionTableBo[classIdx];
}
} //!< if( typeIdx == SAO_BO )
resetSaoUnit(&saoLcuParamRdo);
saoLcuParamRdo.length = m_iNumClass[typeIdx];
saoLcuParamRdo.typeIdx = typeIdx;
saoLcuParamRdo.mergeLeftFlag = 0;
saoLcuParamRdo.mergeUpFlag = 0;
saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
{
saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
}
m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
m_pcRDGoOnSbacCoder->resetBits();
m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
if(m_dCost[yCbCr][typeIdx] < dCostPartBest) //!< 更新最佳值
{
dCostPartBest = m_dCost[yCbCr][typeIdx];
copySaoUnit(saoLcuParam, &saoLcuParamRdo );
bestDist = estDist;
}
} //!< for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
compDistortion[0] += ((Double)bestDist/lambda);
m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
// merge left or merge up
for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)
{
saoLcuParamNeighbor = NULL;
if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) //!< 左邻块可用
{
saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]); //!< 取左邻块的SAO参数
}
else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) //!< 上邻块可用
{
saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]); //!< 取上邻块的SAO参数
}
if (saoLcuParamNeighbor!=NULL)
{
estDist = 0;
typeIdx = saoLcuParamNeighbor->typeIdx;
if (typeIdx>=0) //!< typeIdx为有效的
{
Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
Int merge_iOffset;
for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
{
merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
estDist += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1], shift);
}
}
else
{
estDist = 0;
}
copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
compSaoParam[idxNeighbor].mergeUpFlag = idxNeighbor;
compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
}
}
}