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); } } }