diff -c -p -r HEVC_HM11.0/source/Lib/TLibCommon/TComSlice.cpp HEVC_Patched_990/source/Lib/TLibCommon/TComSlice.cpp *** HEVC_HM11.0/source/Lib/TLibCommon/TComSlice.cpp 2013-06-07 15:36:28.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibCommon/TComSlice.cpp 2013-08-09 09:53:44.000000000 +0100 *************** TComSlice::TComSlice() *** 70,79 **** , m_pcPic ( NULL ) , m_colFromL0Flag ( 1 ) , m_colRefIdx ( 0 ) ! #if SAO_CHROMA_LAMBDA ! , m_dLambdaLuma( 0.0 ) ! , m_dLambdaChroma( 0.0 ) ! #else , m_dLambda ( 0.0 ) #endif , m_uiTLayer ( 0 ) --- 70,76 ---- , m_pcPic ( NULL ) , m_colFromL0Flag ( 1 ) , m_colRefIdx ( 0 ) ! #if !SAO_CHROMA_LAMBDA , m_dLambda ( 0.0 ) #endif , m_uiTLayer ( 0 ) *************** TComSlice::TComSlice() *** 103,109 **** m_aiNumRefIdx[0] = m_aiNumRefIdx[1] = 0; initEqualRef(); ! for ( Int idx = 0; idx < MAX_NUM_REF; idx++ ) { m_list1IdxToList0Idx[idx] = -1; --- 100,109 ---- m_aiNumRefIdx[0] = m_aiNumRefIdx[1] = 0; initEqualRef(); ! for (UInt component = 0; component < 3; component++) ! { ! m_lambdas[component] = 0.0; ! } for ( Int idx = 0; idx < MAX_NUM_REF; idx++ ) { m_list1IdxToList0Idx[idx] = -1; *************** Void TComSlice::copySliceInfo(TComSlice *** 692,699 **** m_colFromL0Flag = pSrc->m_colFromL0Flag; m_colRefIdx = pSrc->m_colRefIdx; #if SAO_CHROMA_LAMBDA ! m_dLambdaLuma = pSrc->m_dLambdaLuma; ! m_dLambdaChroma = pSrc->m_dLambdaChroma; #else m_dLambda = pSrc->m_dLambda; #endif --- 692,698 ---- m_colFromL0Flag = pSrc->m_colFromL0Flag; m_colRefIdx = pSrc->m_colRefIdx; #if SAO_CHROMA_LAMBDA ! setLambdas(pSrc->getLambdas()); #else m_dLambda = pSrc->m_dLambda; #endif diff -c -p -r HEVC_HM11.0/source/Lib/TLibCommon/TComSlice.h HEVC_Patched_990/source/Lib/TLibCommon/TComSlice.h *** HEVC_HM11.0/source/Lib/TLibCommon/TComSlice.h 2013-06-07 15:36:28.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibCommon/TComSlice.h 2013-08-09 09:53:44.000000000 +0100 *************** private: *** 1165,1172 **** #if SAO_CHROMA_LAMBDA ! Double m_dLambdaLuma; ! Double m_dLambdaChroma; #else Double m_dLambda; #endif --- 1165,1171 ---- #if SAO_CHROMA_LAMBDA ! Double m_lambdas[3]; #else Double m_dLambda; #endif *************** public: *** 1316,1324 **** Bool isInterP () { return m_eSliceType == P_SLICE; } #if SAO_CHROMA_LAMBDA ! Void setLambda( Double d, Double e ) { m_dLambdaLuma = d; m_dLambdaChroma = e;} ! Double getLambdaLuma() { return m_dLambdaLuma; } ! Double getLambdaChroma() { return m_dLambdaChroma; } #else Void setLambda( Double d ) { m_dLambda = d; } Double getLambda() { return m_dLambda; } --- 1315,1322 ---- Bool isInterP () { return m_eSliceType == P_SLICE; } #if SAO_CHROMA_LAMBDA ! Void setLambdas ( const Double lambdas[3] ) { for (UInt component = 0; component < 3; component++) m_lambdas[component] = lambdas[component]; } ! const Double* getLambdas() const { return m_lambdas; } #else Void setLambda( Double d ) { m_dLambda = d; } Double getLambda() { return m_dLambda; } diff -c -p -r HEVC_HM11.0/source/Lib/TLibCommon/TComTrQuant.h HEVC_Patched_990/source/Lib/TLibCommon/TComTrQuant.h *** HEVC_HM11.0/source/Lib/TLibCommon/TComTrQuant.h 2013-01-25 10:29:33.000000000 +0000 --- HEVC_Patched_990/source/Lib/TLibCommon/TComTrQuant.h 2013-08-09 09:53:44.000000000 +0100 *************** public: *** 149,156 **** Void setQPforQuant( Int qpy, TextType eTxtType, Int qpBdOffset, Int chromaQPOffset); #if RDOQ_CHROMA_LAMBDA ! Void setLambda(Double dLambdaLuma, Double dLambdaChroma) { m_dLambdaLuma = dLambdaLuma; m_dLambdaChroma = dLambdaChroma; } ! Void selectLambda(TextType eTType) { m_dLambda = (eTType == TEXT_LUMA) ? m_dLambdaLuma : m_dLambdaChroma; } #else Void setLambda(Double dLambda) { m_dLambda = dLambda;} #endif --- 149,156 ---- Void setQPforQuant( Int qpy, TextType eTxtType, Int qpBdOffset, Int chromaQPOffset); #if RDOQ_CHROMA_LAMBDA ! Void setLambdas ( const Double lambdas[3] ) { for (UInt component = 0; component < 3; component++) m_lambdas[component] = lambdas[component]; } ! Void selectLambda(TextType eTType) { m_dLambda = (eTType == TEXT_LUMA) ? m_lambdas[0] : ((eTType == TEXT_CHROMA_U) ? m_lambdas[1] : m_lambdas[2]); } #else Void setLambda(Double dLambda) { m_dLambda = dLambda;} #endif *************** protected: *** 206,213 **** QpParam m_cQP; #if RDOQ_CHROMA_LAMBDA ! Double m_dLambdaLuma; ! Double m_dLambdaChroma; #endif Double m_dLambda; UInt m_uiRDOQOffset; --- 206,212 ---- QpParam m_cQP; #if RDOQ_CHROMA_LAMBDA ! Double m_lambdas[3]; #endif Double m_dLambda; UInt m_uiRDOQOffset; diff -c -p -r HEVC_HM11.0/source/Lib/TLibEncoder/TEncGOP.cpp HEVC_Patched_990/source/Lib/TLibEncoder/TEncGOP.cpp *** HEVC_HM11.0/source/Lib/TLibEncoder/TEncGOP.cpp 2013-06-07 15:36:28.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibEncoder/TEncGOP.cpp 2013-08-09 09:53:44.000000000 +0100 *************** Void TEncGOP::compressGOP( Int iPOCLast, *** 1503,1511 **** #if SAO_CHROMA_LAMBDA #if SAO_ENCODING_CHOICE ! m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambdaLuma(), pcPic->getSlice(0)->getLambdaChroma(), pcPic->getSlice(0)->getDepth()); #else ! m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambdaLuma(), pcPic->getSlice(0)->getLambdaChroma()); #endif #else m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambda()); --- 1503,1511 ---- #if SAO_CHROMA_LAMBDA #if SAO_ENCODING_CHOICE ! m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambdas(), pcPic->getSlice(0)->getDepth()); #else ! m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambdas()); #endif #else m_pcSAO->SAOProcess(&cSaoParam, pcPic->getSlice(0)->getLambda()); diff -c -p -r HEVC_HM11.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp HEVC_Patched_990/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp *** HEVC_HM11.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp 2013-06-07 15:36:28.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp 2013-08-09 09:53:44.000000000 +0100 *************** Void TEncSampleAdaptiveOffset::resetStat *** 1667,1675 **** * \param dLambdaChroma */ #if SAO_ENCODING_CHOICE ! Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma, Int depth) #else ! Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma) #endif #else /** Sample adaptive offset process --- 1667,1675 ---- * \param dLambdaChroma */ #if SAO_ENCODING_CHOICE ! Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, const Double dLambdas[3], Int depth) #else ! Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, const Double dLambdas[3]) #endif #else /** Sample adaptive offset process *************** Void TEncSampleAdaptiveOffset::SAOProces *** 1696,1704 **** if ( m_saoLcuBasedOptimization) { #if SAO_ENCODING_CHOICE ! rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth); #else ! rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma); #endif } else --- 1696,1704 ---- if ( m_saoLcuBasedOptimization) { #if SAO_ENCODING_CHOICE ! rdoSaoUnitAll(pcSaoParam, dLambdas, depth); #else ! rdoSaoUnitAll(pcSaoParam, dLambdas); #endif } else *************** Void TEncSampleAdaptiveOffset::SAOProces *** 1706,1712 **** pcSaoParam->bSaoFlag[0] = 1; pcSaoParam->bSaoFlag[1] = 0; dCostFinal = 0; ! Double lambdaRdo = dLambdaLuma; resetStats(); getSaoStats(pcSaoParam->psSaoPart[0], 0); runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0); --- 1706,1712 ---- pcSaoParam->bSaoFlag[0] = 1; pcSaoParam->bSaoFlag[1] = 0; dCostFinal = 0; ! Double lambdaRdo = dLambdas[0]; resetStats(); getSaoStats(pcSaoParam->psSaoPart[0], 0); runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0); *************** Void TEncSampleAdaptiveOffset::assignSao *** 1851,1859 **** * \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 { --- 1851,1859 ---- * \param lambdaChroma */ #if SAO_ENCODING_CHOICE ! Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, const Double dLambdas[3], Int depth) #else ! Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, const Double dLambdas[3]) #endif { *************** Void TEncSampleAdaptiveOffset::rdoSaoUni *** 1978,1985 **** } } ! saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, lambda, &mergeSaoParam[0][0], &compDistortion[0]); ! 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 --- 1978,1985 ---- } } ! saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, dLambdas[0], &mergeSaoParam[0][0], &compDistortion[0]); ! sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, dLambdas, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]); if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] ) { // Cost of new SAO_params *************** Void TEncSampleAdaptiveOffset::saoCompon *** 2330,2343 **** } } } ! Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion) { Int typeIdx; Int64 estDist[2]; Int classIdx; Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC-8); ! Int64 bestDist = 0; SaoLcuParam* saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])}; SaoLcuParam* saoLcuParamNeighbor[2] = {NULL, NULL}; --- 2330,2343 ---- } } } ! Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, const Double lambdas[3], SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion) { Int typeIdx; Int64 estDist[2]; Int classIdx; Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC-8); ! Double bestDistOverLambda = 0; SaoLcuParam* saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])}; SaoLcuParam* saoLcuParamNeighbor[2] = {NULL, NULL}; *************** Void TEncSampleAdaptiveOffset::sao2Chrom *** 2363,2379 **** Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; SaoLcuParam saoLcuParamRdo[2]; - Double estRate = 0; resetSaoUnit(&saoLcuParamRdo[0]); resetSaoUnit(&saoLcuParamRdo[1]); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcRDGoOnSbacCoder->resetBits(); m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1); m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2); - costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] ); copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] ); --- 2363,2381 ---- Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; SaoLcuParam saoLcuParamRdo[2]; resetSaoUnit(&saoLcuParamRdo[0]); resetSaoUnit(&saoLcuParamRdo[1]); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcRDGoOnSbacCoder->resetBits(); + m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1); + const UInt bitsWritten = m_pcEntropyCoder->getNumberOfWrittenBits(); + costPartBest = bitsWritten * lambdas[1]; m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2); + costPartBest += (m_pcEntropyCoder->getNumberOfWrittenBits() - bitsWritten) * lambdas[2]; copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] ); copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] ); *************** Void TEncSampleAdaptiveOffset::sao2Chrom *** 2386,2392 **** { Double currentRDCost = 0.0; bestRDCostTableBo = MAX_DOUBLE; ! estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++) { currentRDCost = 0.0; --- 2388,2394 ---- { Double currentRDCost = 0.0; bestRDCostTableBo = MAX_DOUBLE; ! estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambdas[compIdx + 1], currentDistortionTableBo, currentRdCostTableBo); for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++) { currentRDCost = 0.0; *************** Void TEncSampleAdaptiveOffset::sao2Chrom *** 2413,2424 **** } else { ! estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); ! estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcRDGoOnSbacCoder->resetBits(); for(Int compIdx = 0; compIdx < 2; compIdx++) { --- 2415,2428 ---- } else { ! estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambdas[1], currentDistortionTableBo, currentRdCostTableBo); ! estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambdas[2], currentDistortionTableBo, currentRdCostTableBo); } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcRDGoOnSbacCoder->resetBits(); + m_dCost[1][typeIdx] = 0; + UInt lastWrittenBits=0; for(Int compIdx = 0; compIdx < 2; compIdx++) { *************** Void TEncSampleAdaptiveOffset::sao2Chrom *** 2434,2453 **** } m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1); } ! estRate = m_pcEntropyCoder->getNumberOfWrittenBits(); ! m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1]) + lambda * (Double) estRate); ! if(m_dCost[1][typeIdx] < costPartBest) { costPartBest = m_dCost[1][typeIdx]; ! copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] ); ! copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] ); ! bestDist = (estDist[0]+estDist[1]); } } ! distortion[0] += ((Double)bestDist/lambda); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1); m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2); --- 2438,2461 ---- } m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1); + const UInt newWrittenBits = m_pcEntropyCoder->getNumberOfWrittenBits(); + m_dCost[1][typeIdx] += (Double)((Double)(estDist[compIdx]) + (lambdas[compIdx + 1] * (Double)(newWrittenBits - lastWrittenBits))); + lastWrittenBits = newWrittenBits; } ! if(m_dCost[1][typeIdx] < costPartBest) { costPartBest = m_dCost[1][typeIdx]; ! bestDistOverLambda = 0; ! for(Int compIdx = 0; compIdx < 2; compIdx++) ! { ! copySaoUnit(saoLcuParam[compIdx], &saoLcuParamRdo[compIdx] ); ! bestDistOverLambda += (estDist[compIdx] / lambdas[compIdx + 1]); ! } } } ! distortion[0] += bestDistOverLambda; m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1); m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2); *************** Void TEncSampleAdaptiveOffset::sao2Chrom *** 2490,2496 **** copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] ); saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag = idxNeighbor; saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor; ! distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda); } } } --- 2498,2504 ---- copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] ); saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag = idxNeighbor; saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor; ! distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambdas[compIdx + 1]); } } } diff -c -p -r HEVC_HM11.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h HEVC_Patched_990/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h *** HEVC_HM11.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h 2013-04-23 15:08:58.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h 2013-08-09 09:53:44.000000000 +0100 *************** public: *** 96,104 **** Void resetStats(); #if SAO_CHROMA_LAMBDA #if SAO_ENCODING_CHOICE ! Void SAOProcess(SAOParam *pcSaoParam, Double dLambda, Double dLambdaChroma, Int depth); #else ! Void SAOProcess(SAOParam *pcSaoParam, Double dLambda, Double dLambdaChroma); #endif #else Void SAOProcess(SAOParam *pcSaoParam, Double dLambda); --- 96,104 ---- Void resetStats(); #if SAO_CHROMA_LAMBDA #if SAO_ENCODING_CHOICE ! Void SAOProcess(SAOParam *pcSaoParam, const Double dLambdas[3], Int depth); #else ! Void SAOProcess(SAOParam *pcSaoParam, const Double dLambdas[3]); #endif #else Void SAOProcess(SAOParam *pcSaoParam, Double dLambda); *************** public: *** 118,129 **** Void assignSaoUnitSyntax(SaoLcuParam* saoLcuParam, SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr); Void checkMerge(SaoLcuParam * lcuParamCurr,SaoLcuParam * lcuParamCheck, Int dir); #if SAO_ENCODING_CHOICE ! Void rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth); #else ! Void rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma); #endif Void saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *distortion); ! Void sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion); inline Int64 estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift); inline Int64 estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo, Int offsetTh ); inline Int64 estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo); --- 118,129 ---- Void assignSaoUnitSyntax(SaoLcuParam* saoLcuParam, SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr); Void checkMerge(SaoLcuParam * lcuParamCurr,SaoLcuParam * lcuParamCheck, Int dir); #if SAO_ENCODING_CHOICE ! Void rdoSaoUnitAll(SAOParam *saoParam, const Double dLambdas[3], Int depth); #else ! Void rdoSaoUnitAll(SAOParam *saoParam, const Double dLambdas[3]); #endif Void saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *distortion); ! Void sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, const Double lambdas[3], SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion); inline Int64 estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift); inline Int64 estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo, Int offsetTh ); inline Int64 estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo); diff -c -p -r HEVC_HM11.0/source/Lib/TLibEncoder/TEncSearch.cpp HEVC_Patched_990/source/Lib/TLibEncoder/TEncSearch.cpp *** HEVC_HM11.0/source/Lib/TLibEncoder/TEncSearch.cpp 2013-08-08 16:44:24.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibEncoder/TEncSearch.cpp 2013-08-09 09:53:44.000000000 +0100 *************** TEncSearch::xIntraCodingChromaBlk( TComD *** 1301,1307 **** m_pcTrQuant->setQPforQuant ( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda (TEXT_CHROMA); #endif m_pcTrQuant->transformNxN ( pcCU, piResi, uiStride, pcCoeff, #if ADAPTIVE_QP_SELECTION --- 1301,1307 ---- m_pcTrQuant->setQPforQuant ( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda (uiChromaId > 0 ? TEXT_CHROMA_V : TEXT_CHROMA_U); #endif m_pcTrQuant->transformNxN ( pcCU, piResi, uiStride, pcCoeff, #if ADAPTIVE_QP_SELECTION *************** Void TEncSearch::xEstimateResidualQT( TC *** 4770,4776 **** m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda(TEXT_CHROMA); #endif m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, --- 4770,4776 ---- m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda(TEXT_CHROMA_U); #endif m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, *************** Void TEncSearch::xEstimateResidualQT( TC *** 4779,4784 **** --- 4779,4788 ---- #endif trWidthC, trHeightC, uiAbsSumU, TEXT_CHROMA_U, uiAbsPartIdx ); + #if RDOQ_CHROMA_LAMBDA + m_pcTrQuant->selectLambda(TEXT_CHROMA_V); + #endif + curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); m_pcTrQuant->transformNxN( pcCU, pcResi->getCrAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrV, *************** Void TEncSearch::xEstimateResidualQT( TC *** 5179,5185 **** m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda(TEXT_CHROMA); #endif m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, --- 5183,5189 ---- m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA ! m_pcTrQuant->selectLambda(TEXT_CHROMA_U); #endif m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, *************** Void TEncSearch::xEstimateResidualQT( TC *** 5187,5192 **** --- 5191,5201 ---- pcArlCoeffCurrU, #endif trWidthC, trHeightC, uiAbsSumTransformSkipU, TEXT_CHROMA_U, uiAbsPartIdx, true ); + + #if RDOQ_CHROMA_LAMBDA + m_pcTrQuant->selectLambda(TEXT_CHROMA_V); + #endif + curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); m_pcTrQuant->transformNxN( pcCU, pcResi->getCrAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrV, diff -c -p -r HEVC_HM11.0/source/Lib/TLibEncoder/TEncSlice.cpp HEVC_Patched_990/source/Lib/TLibEncoder/TEncSlice.cpp *** HEVC_HM11.0/source/Lib/TLibEncoder/TEncSlice.cpp 2013-06-07 15:36:28.000000000 +0100 --- HEVC_Patched_990/source/Lib/TLibEncoder/TEncSlice.cpp 2013-08-09 09:53:44.000000000 +0100 *************** Void TEncSlice::initEncSlice( TComPic* p *** 335,365 **** #if WEIGHTED_CHROMA_DISTORTION // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. ! Double weight = 1.0; Int qpc; Int chromaQPOffset; chromaQPOffset = rpcSlice->getPPS()->getChromaCbQpOffset() + rpcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight); chromaQPOffset = rpcSlice->getPPS()->getChromaCrQpOffset() + rpcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight); #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant->setLambda( dLambda, dLambda / weight ); #else m_pcTrQuant->setLambda( dLambda ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! rpcSlice ->setLambda( dLambda, dLambda / weight ); #else rpcSlice ->setLambda( dLambda ); #endif --- 335,367 ---- #if WEIGHTED_CHROMA_DISTORTION // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. ! Double weight[2] = {1.0, 1.0}; Int qpc; Int chromaQPOffset; chromaQPOffset = rpcSlice->getPPS()->getChromaCbQpOffset() + rpcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[0] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight[0]); chromaQPOffset = rpcSlice->getPPS()->getChromaCrQpOffset() + rpcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[1] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight[1]); ! ! const Double lambdaArray[3] = {dLambda, (dLambda / weight[0]), (dLambda / weight[1])}; #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant->setLambdas( lambdaArray ); #else m_pcTrQuant->setLambda( dLambda ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! rpcSlice ->setLambdas( lambdaArray ); #else rpcSlice ->setLambda( dLambda ); #endif *************** Void TEncSlice::resetQP( TComPic* pic, I *** 460,490 **** #if WEIGHTED_CHROMA_DISTORTION // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. ! Double weight; Int qpc; Int chromaQPOffset; chromaQPOffset = slice->getPPS()->getChromaCbQpOffset() + slice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, sliceQP + chromaQPOffset); ! weight = pow( 2.0, (sliceQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight); chromaQPOffset = slice->getPPS()->getChromaCrQpOffset() + slice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, sliceQP + chromaQPOffset); ! weight = pow( 2.0, (sliceQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight); #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant->setLambda( lambda, lambda / weight ); #else m_pcTrQuant->setLambda( lambda ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! slice ->setLambda( lambda, lambda / weight ); #else slice ->setLambda( lambda ); #endif --- 462,494 ---- #if WEIGHTED_CHROMA_DISTORTION // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. ! Double weight[2] = {1.0, 1.0}; Int qpc; Int chromaQPOffset; chromaQPOffset = slice->getPPS()->getChromaCbQpOffset() + slice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, sliceQP + chromaQPOffset); ! weight[0] = pow( 2.0, (sliceQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight[0]); chromaQPOffset = slice->getPPS()->getChromaCrQpOffset() + slice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, sliceQP + chromaQPOffset); ! weight[1] = pow( 2.0, (sliceQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight[1]); ! ! const Double lambdaArray[3] = {lambda, (lambda / weight[0]), (lambda / weight[1])}; #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant->setLambdas( lambdaArray ); #else m_pcTrQuant->setLambda( lambda ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! slice ->setLambdas( lambdaArray ); #else slice ->setLambda( lambda ); #endif *************** Void TEncSlice::precompressSlice( TComPi *** 675,704 **** // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. Int iQP = m_piRdPicQp [uiQpIdx]; ! Double weight = 1.0; Int qpc; Int chromaQPOffset; chromaQPOffset = pcSlice->getPPS()->getChromaCbQpOffset() + pcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight); chromaQPOffset = pcSlice->getPPS()->getChromaCrQpOffset() + pcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight); #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant ->setLambda( m_pdRdPicLambda[uiQpIdx], m_pdRdPicLambda[uiQpIdx] / weight ); #else m_pcTrQuant ->setLambda ( m_pdRdPicLambda[uiQpIdx] ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdx], m_pdRdPicLambda[uiQpIdx] / weight ); #else pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdx] ); #endif --- 679,710 ---- // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. Int iQP = m_piRdPicQp [uiQpIdx]; ! Double weight[2] = {1.0, 1.0}; Int qpc; Int chromaQPOffset; chromaQPOffset = pcSlice->getPPS()->getChromaCbQpOffset() + pcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[0] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight[0]); chromaQPOffset = pcSlice->getPPS()->getChromaCrQpOffset() + pcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[1] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight[1]); ! ! const Double lambdaArray[3] = {m_pdRdPicLambda[uiQpIdx], (m_pdRdPicLambda[uiQpIdx] / weight[0]), (m_pdRdPicLambda[uiQpIdx] / weight[1])}; #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant ->setLambdas ( lambdaArray ); #else m_pcTrQuant ->setLambda ( m_pdRdPicLambda[uiQpIdx] ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! pcSlice ->setLambdas ( lambdaArray ); #else pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdx] ); #endif *************** Void TEncSlice::precompressSlice( TComPi *** 731,760 **** #if WEIGHTED_CHROMA_DISTORTION // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. Int iQP = m_piRdPicQp [uiQpIdxBest]; ! Double weight = 1.0; Int qpc; Int chromaQPOffset; chromaQPOffset = pcSlice->getPPS()->getChromaCbQpOffset() + pcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight); chromaQPOffset = pcSlice->getPPS()->getChromaCrQpOffset() + pcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight); #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant ->setLambda( m_pdRdPicLambda[uiQpIdxBest], m_pdRdPicLambda[uiQpIdxBest] / weight ); #else m_pcTrQuant ->setLambda ( m_pdRdPicLambda[uiQpIdxBest] ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdxBest], m_pdRdPicLambda[uiQpIdxBest] / weight ); #else pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdxBest] ); #endif --- 737,768 ---- #if WEIGHTED_CHROMA_DISTORTION // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. Int iQP = m_piRdPicQp [uiQpIdxBest]; ! Double weight[2] = {1.0, 1.0}; Int qpc; Int chromaQPOffset; chromaQPOffset = pcSlice->getPPS()->getChromaCbQpOffset() + pcSlice->getSliceQpDeltaCb(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[0] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCbDistortionWeight(weight[0]); chromaQPOffset = pcSlice->getPPS()->getChromaCrQpOffset() + pcSlice->getSliceQpDeltaCr(); qpc = Clip3( 0, 57, iQP + chromaQPOffset); ! weight[1] = pow( 2.0, (iQP-g_aucChromaScale[qpc])/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset ! m_pcRdCost->setCrDistortionWeight(weight[1]); ! ! const Double lambdaArray[3] = {m_pdRdPicLambda[uiQpIdxBest], (m_pdRdPicLambda[uiQpIdxBest] / weight[0]), (m_pdRdPicLambda[uiQpIdxBest] / weight[1])}; #endif #if RDOQ_CHROMA_LAMBDA // for RDOQ ! m_pcTrQuant ->setLambdas ( lambdaArray ); #else m_pcTrQuant ->setLambda ( m_pdRdPicLambda[uiQpIdxBest] ); #endif #if SAO_CHROMA_LAMBDA // For SAO ! pcSlice ->setLambdas ( lambdaArray ); #else pcSlice ->setLambda ( m_pdRdPicLambda[uiQpIdxBest] ); #endif *************** Void TEncSlice::compressSlice( TComPic*& *** 1090,1096 **** #if RDOQ_CHROMA_LAMBDA // set lambda for RDOQ Double weight=m_pcRdCost->getChromaWeight(); ! m_pcTrQuant->setLambda( estLambda, estLambda / weight ); #else m_pcTrQuant->setLambda( estLambda ); #endif --- 1098,1105 ---- #if RDOQ_CHROMA_LAMBDA // set lambda for RDOQ Double weight=m_pcRdCost->getChromaWeight(); ! const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) }; ! m_pcTrQuant->setLambdas( lambdaArray ); #else m_pcTrQuant->setLambda( estLambda ); #endif