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);
}
}
}HEVC学习(十六) —— SAO函数解析之四
最新推荐文章于 2026-08-20 15:09:48 发布
本文深入探讨了HEVC(高效视频编码)中SAO(样本自适应偏移)函数的具体实现,包括SAOParam结构的处理、失真度估算、最佳滤波类型选择和左/上邻块的融合策略。通过对不同滤波类型和带宽类别的RD成本计算,确定了最优的SAO参数,从而提高编码效率。
 —— SAO函数解析之四&spm=1001.2101.3001.5002&articleId=8288601&d=1&t=3&u=58c1a7e9256a4fd98af2db13f39b9c91)
1782

被折叠的 条评论
为什么被折叠?



