Changeset 608 in 3DVCSoftware for trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
 Timestamp:
 1 Sep 2013, 22:47:26 (11 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
r443 r608 4 4 * granted under this license. 5 5 * 6 * Copyright (c) 2010201 2, ITU/ISO/IEC6 * Copyright (c) 20102013, ITU/ISO/IEC 7 7 * All rights reserved. 8 8 * … … 32 32 */ 33 33 34 /** \file TEncSampleAdaptiveOffset.cpp 34 /** 35 \file TEncSampleAdaptiveOffset.cpp 35 36 \brief estimation part of sample adaptive offset class 36 37 */ … … 43 44 //! \ingroup TLibEncoder 44 45 //! \{ 45 #if LGE_SAO_MIGRATION_D0091 46 46 47 TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset() 47 48 { 48 m_pcEntropyCoder= NULL;49 50 51 m_pppcBinCoderCABAC = NULL;52 m_iCount = NULL;53 m_iOffset = NULL;54 m_iOffsetOrg = NULL;55 m_iRate = NULL;56 m_iDist = NULL;57 m_dCost = NULL;58 m_dCostPartBest = NULL;59 m_iDistOrg = NULL;60 m_iTypePartBest = NULL;49 m_pcEntropyCoder = NULL; 50 m_pppcRDSbacCoder = NULL; 51 m_pcRDGoOnSbacCoder = NULL; 52 m_pppcBinCoderCABAC = NULL; 53 m_iCount = NULL; 54 m_iOffset = NULL; 55 m_iOffsetOrg = NULL; 56 m_iRate = NULL; 57 m_iDist = NULL; 58 m_dCost = NULL; 59 m_dCostPartBest = NULL; 60 m_iDistOrg = NULL; 61 m_iTypePartBest = NULL; 61 62 #if SAO_ENCODING_CHOICE_CHROMA 62 63 64 65 66 67 68 69 63 m_depthSaoRate[0][0] = 0; 64 m_depthSaoRate[0][1] = 0; 65 m_depthSaoRate[0][2] = 0; 66 m_depthSaoRate[0][3] = 0; 67 m_depthSaoRate[1][0] = 0; 68 m_depthSaoRate[1][1] = 0; 69 m_depthSaoRate[1][2] = 0; 70 m_depthSaoRate[1][3] = 0; 70 71 #endif 71 72 } 72 73 73 TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset() 74 74 { … … 84 84 // ==================================================================================================================== 85 85 86 inline Double xRoundIbdi2(Double x) 87 { 88 #if FULL_NBIT 89 Int bitDepthMinus8 = g_uiBitDepth  8; 90 return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepthMinus81)))/(1<<bitDepthMinus8)) : ((Int)(((Int)(x)(1<<(bitDepthMinus81)))/(1<<bitDepthMinus8))); 91 #else 92 return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)(1<<(g_uiBitIncrement1)))/(1<<g_uiBitIncrement))); 93 #endif 86 inline Double xRoundIbdi2(Int bitDepth, Double x) 87 { 88 return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth81)))/(1<<(bitDepth8))) : ((Int)(((Int)(x)(1<<(bitDepth81)))/(1<<(bitDepth8)))); 94 89 } 95 90 … … 97 92 * \param x 98 93 */ 99 inline Double xRoundIbdi(Double x) 100 { 101 #if FULL_NBIT 102 return (g_uiBitDepth > 8 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)0.5)))) ; 103 #else 104 return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)0.5)))) ; 105 #endif 106 } 94 inline Double xRoundIbdi(Int bitDepth, Double x) 95 { 96 return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)0.5)))) ; 97 } 98 99 107 100 108 101 /** process SAO for one partition … … 111 104 Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda, Int yCbCr) 112 105 { 113 Int iTypeIdx; 114 Int iNumTotalType = MAX_NUM_SAO_TYPE; 115 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]); 116 117 Int64 iEstDist; 118 Int iClassIdx; 119 Int uiShift = g_uiBitIncrement << 1; 120 UInt uiDepth = pOnePart>PartLevel; 121 122 m_iDistOrg [iPartIdx] = 0; 123 124 Double bestRDCostTableBo = MAX_DOUBLE; 125 Int bestClassTableBo = 0; 126 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS]; 127 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; 128 129 Int addr; 130 Int allowMergeLeft; 131 Int allowMergeUp; 132 Int frameWidthInCU = m_pcPic>getFrameWidthInCU(); 133 SaoLcuParam saoLcuParamRdo; 134 135 for (iTypeIdx=1; iTypeIdx<iNumTotalType; iTypeIdx++) 136 { 106 Int iTypeIdx; 107 Int iNumTotalType = MAX_NUM_SAO_TYPE; 108 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]); 109 110 Int64 iEstDist; 111 Int iClassIdx; 112 Int uiShift = 2 * DISTORTION_PRECISION_ADJUSTMENT((yCbCr == 0 ? g_bitDepthY : g_bitDepthC)8); 113 UInt uiDepth = pOnePart>PartLevel; 114 115 m_iDistOrg [iPartIdx] = 0; 116 117 Double bestRDCostTableBo = MAX_DOUBLE; 118 Int bestClassTableBo = 0; 119 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS]; 120 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; 121 122 Int addr; 123 Int allowMergeLeft; 124 Int allowMergeUp; 125 Int frameWidthInCU = m_pcPic>getFrameWidthInCU(); 126 SaoLcuParam saoLcuParamRdo; 127 128 for (iTypeIdx=1; iTypeIdx<iNumTotalType; iTypeIdx++) 129 { 130 if( m_bUseSBACRD ) 131 { 132 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); 133 m_pcRDGoOnSbacCoder>resetBits(); 134 } 135 else 136 { 137 m_pcEntropyCoder>resetEntropy(); 138 m_pcEntropyCoder>resetBits(); 139 } 140 141 iEstDist = 0; 142 143 if (iTypeIdx == 1) 144 { 145 for (Int ry = pOnePart>StartCUY; ry<= pOnePart>EndCUY; ry++) 146 { 147 for (Int rx = pOnePart>StartCUX; rx <= pOnePart>EndCUX; rx++) 148 { 149 addr = ry * frameWidthInCU + rx; 150 151 // get bits for iTypeIdx = 1 152 allowMergeLeft = 1; 153 allowMergeUp = 1; 154 if (rx != 0) 155 { 156 // check tile id and slice id 157 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 158 { 159 allowMergeLeft = 0; 160 } 161 } 162 if (ry!=0) 163 { 164 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 165 { 166 allowMergeUp = 0; 167 } 168 } 169 170 // reset 171 resetSaoUnit(&saoLcuParamRdo); 172 173 // set merge flag 174 saoLcuParamRdo.mergeUpFlag = 1; 175 saoLcuParamRdo.mergeLeftFlag = 1; 176 177 if (ry == pOnePart>StartCUY) 178 { 179 saoLcuParamRdo.mergeUpFlag = 0; 180 } 181 182 if (rx == pOnePart>StartCUX) 183 { 184 saoLcuParamRdo.mergeLeftFlag = 0; 185 } 186 187 m_pcEntropyCoder>encodeSaoUnitInterleaving(yCbCr, 1, rx, ry, &saoLcuParamRdo, 1, 1, allowMergeLeft, allowMergeUp); 188 189 } 190 } 191 } 192 193 if (iTypeIdx>=0) 194 { 195 iEstDist = estSaoTypeDist(iPartIdx, iTypeIdx, uiShift, dLambda, currentDistortionTableBo, currentRdCostTableBo); 196 if( iTypeIdx == SAO_BO ) 197 { 198 // Estimate Best Position 199 Double currentRDCost = 0.0; 200 201 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++) 202 { 203 currentRDCost = 0.0; 204 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) 205 { 206 currentRDCost += currentRdCostTableBo[uj]; 207 } 208 209 if( currentRDCost < bestRDCostTableBo) 210 { 211 bestRDCostTableBo = currentRDCost; 212 bestClassTableBo = i; 213 } 214 } 215 216 // Re code all Offsets 217 // Code Center 218 for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++) 219 { 220 iEstDist += currentDistortionTableBo[iClassIdx]; 221 } 222 } 223 224 for (Int ry = pOnePart>StartCUY; ry<= pOnePart>EndCUY; ry++) 225 { 226 for (Int rx = pOnePart>StartCUX; rx <= pOnePart>EndCUX; rx++) 227 { 228 addr = ry * frameWidthInCU + rx; 229 230 // get bits for iTypeIdx = 1 231 allowMergeLeft = 1; 232 allowMergeUp = 1; 233 if (rx != 0) 234 { 235 // check tile id and slice id 236 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 237 { 238 allowMergeLeft = 0; 239 } 240 } 241 if (ry!=0) 242 { 243 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 244 { 245 allowMergeUp = 0; 246 } 247 } 248 249 // reset 250 resetSaoUnit(&saoLcuParamRdo); 251 252 // set merge flag 253 saoLcuParamRdo.mergeUpFlag = 1; 254 saoLcuParamRdo.mergeLeftFlag = 1; 255 256 if (ry == pOnePart>StartCUY) 257 { 258 saoLcuParamRdo.mergeUpFlag = 0; 259 } 260 261 if (rx == pOnePart>StartCUX) 262 { 263 saoLcuParamRdo.mergeLeftFlag = 0; 264 } 265 266 // set type and offsets 267 saoLcuParamRdo.typeIdx = iTypeIdx; 268 saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0; 269 saoLcuParamRdo.length = m_iNumClass[iTypeIdx]; 270 for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++) 271 { 272 saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1]; 273 } 274 275 m_pcEntropyCoder>encodeSaoUnitInterleaving(yCbCr, 1, rx, ry, &saoLcuParamRdo, 1, 1, allowMergeLeft, allowMergeUp); 276 277 } 278 } 279 280 m_iDist[iPartIdx][iTypeIdx] = iEstDist; 281 m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder>getNumberOfWrittenBits(); 282 283 m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]); 284 285 if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx]) 286 { 287 m_iDistOrg [iPartIdx] = 0; 288 m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx]; 289 m_iTypePartBest[iPartIdx] = iTypeIdx; 137 290 if( m_bUseSBACRD ) 138 { 139 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); 140 m_pcRDGoOnSbacCoder>resetBits(); 141 } 142 else 143 { 144 m_pcEntropyCoder>resetEntropy(); 145 m_pcEntropyCoder>resetBits(); 146 } 147 148 iEstDist = 0; 149 150 if (iTypeIdx == 1) 151 { 152 for (Int ry = pOnePart>StartCUY; ry<= pOnePart>EndCUY; ry++) 153 { 154 for (Int rx = pOnePart>StartCUX; rx <= pOnePart>EndCUX; rx++) 155 { 156 addr = ry * frameWidthInCU + rx; 157 // get bits for iTypeIdx = 1 158 allowMergeLeft = 1; 159 allowMergeUp = 1; 160 if (rx != 0) 161 { 162 // check tile id and slice id 163 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 164 { 165 allowMergeLeft = 0; 166 } 167 } 168 if (ry!=0) 169 { 170 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 171 { 172 allowMergeUp = 0; 173 } 174 } 175 176 // reset 177 resetSaoUnit(&saoLcuParamRdo); 178 179 // set merge flag 180 saoLcuParamRdo.mergeUpFlag = 1; 181 saoLcuParamRdo.mergeLeftFlag = 1; 182 183 if (ry == pOnePart>StartCUY) 184 { 185 saoLcuParamRdo.mergeUpFlag = 0; 186 } 187 188 if (rx == pOnePart>StartCUX) 189 { 190 saoLcuParamRdo.mergeLeftFlag = 0; 191 } 192 193 m_pcEntropyCoder>encodeSaoUnitInterleaving(yCbCr, 1, rx, ry, &saoLcuParamRdo, 1, 1, allowMergeLeft, allowMergeUp); 194 195 } 196 } 197 } 198 199 if (iTypeIdx>=0) 200 { 201 iEstDist = estSaoTypeDist(iPartIdx, iTypeIdx, uiShift, dLambda, currentDistortionTableBo, currentRdCostTableBo); 202 if( iTypeIdx == SAO_BO ) 203 { 204 // Estimate Best Position 205 Double currentRDCost = 0.0; 206 207 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++) 208 { 209 currentRDCost = 0.0; 210 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) 211 { 212 currentRDCost += currentRdCostTableBo[uj]; 213 } 214 215 if( currentRDCost < bestRDCostTableBo) 216 { 217 bestRDCostTableBo = currentRDCost; 218 bestClassTableBo = i; 219 } 220 } 221 222 // Re code all Offsets 223 // Code Center 224 for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++) 225 { 226 iEstDist += currentDistortionTableBo[iClassIdx]; 227 } 228 } 229 230 for (Int ry = pOnePart>StartCUY; ry<= pOnePart>EndCUY; ry++) 231 { 232 for (Int rx = pOnePart>StartCUX; rx <= pOnePart>EndCUX; rx++) 233 { 234 addr = ry * frameWidthInCU + rx; 235 236 // get bits for iTypeIdx = 1 237 allowMergeLeft = 1; 238 allowMergeUp = 1; 239 if (rx != 0) 240 { 241 // check tile id and slice id 242 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 243 { 244 allowMergeLeft = 0; 245 } 246 } 247 if (ry!=0) 248 { 249 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 250 { 251 allowMergeUp = 0; 252 } 253 } 254 255 // reset 256 resetSaoUnit(&saoLcuParamRdo); 257 258 // set merge flag 259 saoLcuParamRdo.mergeUpFlag = 1; 260 saoLcuParamRdo.mergeLeftFlag = 1; 261 262 if (ry == pOnePart>StartCUY) 263 { 264 saoLcuParamRdo.mergeUpFlag = 0; 265 } 266 267 if (rx == pOnePart>StartCUX) 268 { 269 saoLcuParamRdo.mergeLeftFlag = 0; 270 } 271 272 // set type and offsets 273 saoLcuParamRdo.typeIdx = iTypeIdx; 274 saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0; 275 saoLcuParamRdo.length = m_iNumClass[iTypeIdx]; 276 for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++) 277 { 278 saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1]; 279 } 280 281 m_pcEntropyCoder>encodeSaoUnitInterleaving(yCbCr, 1, rx, ry, &saoLcuParamRdo, 1, 1, allowMergeLeft, allowMergeUp); 282 283 } 284 } 285 286 m_iDist[iPartIdx][iTypeIdx] = iEstDist; 287 m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder>getNumberOfWrittenBits(); 288 289 m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]); 290 291 if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx]) 292 { 293 m_iDistOrg [iPartIdx] = 0; 294 m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx]; 295 m_iTypePartBest[iPartIdx] = iTypeIdx; 296 if( m_bUseSBACRD ) 297 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] ); 298 } 299 } 300 else 301 { 302 if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] ) 303 { 304 m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder>getNumberOfWrittenBits()*dLambda ; 305 m_iTypePartBest[iPartIdx] = 1; 306 if( m_bUseSBACRD ) 307 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] ); 308 } 309 } 310 } 311 312 pOnePart>bProcessed = true; 313 pOnePart>bSplit = false; 314 pOnePart>iMinDist = m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx]; 315 pOnePart>iMinRate = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0); 316 pOnePart>dMinCost = pOnePart>iMinDist + dLambda * pOnePart>iMinRate; 317 pOnePart>iBestType = m_iTypePartBest[iPartIdx]; 318 if (pOnePart>iBestType != 1) 319 { 320 // pOnePart>bEnableFlag = 1; 321 pOnePart>iLength = m_iNumClass[pOnePart>iBestType]; 322 Int minIndex = 0; 323 if( pOnePart>iBestType == SAO_BO ) 324 { 325 pOnePart>subTypeIdx = bestClassTableBo; 326 minIndex = pOnePart>subTypeIdx; 327 } 328 for (Int i=0; i< pOnePart>iLength ; i++) 329 { 330 pOnePart>iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart>iBestType][minIndex+i+1]; 331 } 332 291 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] ); 292 } 333 293 } 334 294 else 335 295 { 336 // pOnePart>bEnableFlag = 0; 337 pOnePart>iLength = 0; 338 } 296 if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] ) 297 { 298 m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder>getNumberOfWrittenBits()*dLambda ; 299 m_iTypePartBest[iPartIdx] = 1; 300 if( m_bUseSBACRD ) 301 { 302 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] ); 303 } 304 } 305 } 306 } 307 308 pOnePart>bProcessed = true; 309 pOnePart>bSplit = false; 310 pOnePart>iMinDist = m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx]; 311 pOnePart>iMinRate = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0); 312 pOnePart>dMinCost = pOnePart>iMinDist + dLambda * pOnePart>iMinRate; 313 pOnePart>iBestType = m_iTypePartBest[iPartIdx]; 314 if (pOnePart>iBestType != 1) 315 { 316 // pOnePart>bEnableFlag = 1; 317 pOnePart>iLength = m_iNumClass[pOnePart>iBestType]; 318 Int minIndex = 0; 319 if( pOnePart>iBestType == SAO_BO ) 320 { 321 pOnePart>subTypeIdx = bestClassTableBo; 322 minIndex = pOnePart>subTypeIdx; 323 } 324 for (Int i=0; i< pOnePart>iLength ; i++) 325 { 326 pOnePart>iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart>iBestType][minIndex+i+1]; 327 } 328 329 } 330 else 331 { 332 // pOnePart>bEnableFlag = 0; 333 pOnePart>iLength = 0; 334 } 339 335 } 340 336 … … 343 339 Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx) 344 340 { 345 346 347 348 349 350 351 352 353 354 355 356 341 SAOQTPart* pOnePart= &(psQTPart[iPartIdx]); 342 pOnePart>bSplit = false; 343 pOnePart>iLength = 0; 344 pOnePart>iBestType = 1; 345 346 if (pOnePart>PartLevel < m_uiMaxSplitLevel) 347 { 348 for (Int i=0; i<NUM_DOWN_PART; i++) 349 { 350 disablePartTree(psQTPart, pOnePart>DownPartsIdx[i]); 351 } 352 } 357 353 } 358 354 … … 362 358 Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda, Int yCbCr) 363 359 { 364 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]); 365 366 UInt uiDepth = pOnePart>PartLevel; 367 UInt uhNextDepth = uiDepth+1; 368 369 if (iPartIdx == 0) 370 { 371 dCostFinal = 0; 372 } 373 374 //SAO for this part 375 if(!pOnePart>bProcessed) 376 { 377 rdoSaoOnePart (psQTPart, iPartIdx, dLambda, yCbCr); 378 } 379 380 //SAO for sub 4 parts 381 if (pOnePart>PartLevel < iMaxLevel) 382 { 383 Double dCostNotSplit = dLambda + pOnePart>dMinCost; 384 Double dCostSplit = dLambda; 385 386 for (Int i=0; i< NUM_DOWN_PART ;i++) 387 { 388 if( m_bUseSBACRD ) 389 { 390 if ( 0 == i) //initialize RD with previous depth buffer 391 { 392 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); 393 } 394 else 395 { 396 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); 397 } 398 } 399 runQuadTreeDecision(psQTPart, pOnePart>DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda, yCbCr); 400 dCostSplit += dCostFinal; 401 if( m_bUseSBACRD ) 402 { 403 m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]); 404 } 405 } 406 407 if(dCostSplit < dCostNotSplit) 408 { 409 dCostFinal = dCostSplit; 410 pOnePart>bSplit = true; 411 pOnePart>iLength = 0; 412 pOnePart>iBestType = 1; 413 if( m_bUseSBACRD ) 414 { 415 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); 416 } 360 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]); 361 362 UInt uiDepth = pOnePart>PartLevel; 363 UInt uhNextDepth = uiDepth+1; 364 365 if (iPartIdx == 0) 366 { 367 dCostFinal = 0; 368 } 369 370 //SAO for this part 371 if(!pOnePart>bProcessed) 372 { 373 rdoSaoOnePart (psQTPart, iPartIdx, dLambda, yCbCr); 374 } 375 376 //SAO for sub 4 parts 377 if (pOnePart>PartLevel < iMaxLevel) 378 { 379 Double dCostNotSplit = dLambda + pOnePart>dMinCost; 380 Double dCostSplit = dLambda; 381 382 for (Int i=0; i< NUM_DOWN_PART ;i++) 383 { 384 if( m_bUseSBACRD ) 385 { 386 if ( 0 == i) //initialize RD with previous depth buffer 387 { 388 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); 417 389 } 418 390 else 419 391 { 420 dCostFinal = dCostNotSplit; 421 pOnePart>bSplit = false; 422 for (Int i=0; i<NUM_DOWN_PART; i++) 423 { 424 disablePartTree(psQTPart, pOnePart>DownPartsIdx[i]); 425 } 426 if( m_bUseSBACRD ) 427 { 428 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); 429 } 430 } 392 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); 393 } 394 } 395 runQuadTreeDecision(psQTPart, pOnePart>DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda, yCbCr); 396 dCostSplit += dCostFinal; 397 if( m_bUseSBACRD ) 398 { 399 m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]); 400 } 401 } 402 403 if(dCostSplit < dCostNotSplit) 404 { 405 dCostFinal = dCostSplit; 406 pOnePart>bSplit = true; 407 pOnePart>iLength = 0; 408 pOnePart>iBestType = 1; 409 if( m_bUseSBACRD ) 410 { 411 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); 412 } 431 413 } 432 414 else 433 415 { 434 dCostFinal = pOnePart>dMinCost; 435 } 416 dCostFinal = dCostNotSplit; 417 pOnePart>bSplit = false; 418 for (Int i=0; i<NUM_DOWN_PART; i++) 419 { 420 disablePartTree(psQTPart, pOnePart>DownPartsIdx[i]); 421 } 422 if( m_bUseSBACRD ) 423 { 424 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); 425 } 426 } 427 } 428 else 429 { 430 dCostFinal = pOnePart>dMinCost; 431 } 436 432 } 437 433 … … 446 442 if (m_iCount [i][j]) 447 443 { 448 delete [] m_iCount [i][j]; 444 delete [] m_iCount [i][j]; 449 445 } 450 446 if (m_iOffset[i][j]) … … 454 450 if (m_iOffsetOrg[i][j]) 455 451 { 456 delete [] m_iOffsetOrg[i][j]; 452 delete [] m_iOffsetOrg[i][j]; 457 453 } 458 454 } … … 463 459 if (m_iDist[i]) 464 460 { 465 delete [] m_iDist[i]; 461 delete [] m_iDist[i]; 466 462 } 467 463 if (m_dCost[i]) … … 471 467 if (m_iCount [i]) 472 468 { 473 delete [] m_iCount [i]; 469 delete [] m_iCount [i]; 474 470 } 475 471 if (m_iOffset[i]) … … 479 475 if (m_iOffsetOrg[i]) 480 476 { 481 delete [] m_iOffsetOrg[i]; 482 } 477 delete [] m_iOffsetOrg[i]; 478 } 479 483 480 } 484 481 if (m_iDistOrg) … … 528 525 if (m_count_PreDblk [i][j][k]) 529 526 { 530 delete [] m_count_PreDblk [i][j][k]; 527 delete [] m_count_PreDblk [i][j][k]; 531 528 } 532 529 if (m_offsetOrg_PreDblk[i][j][k]) … … 537 534 if (m_count_PreDblk [i][j]) 538 535 { 539 delete [] m_count_PreDblk [i][j]; 536 delete [] m_count_PreDblk [i][j]; 540 537 } 541 538 if (m_offsetOrg_PreDblk[i][j]) 542 539 { 543 delete [] m_offsetOrg_PreDblk[i][j]; 540 delete [] m_offsetOrg_PreDblk[i][j]; 544 541 } 545 542 } 546 543 if (m_count_PreDblk [i]) 547 544 { 548 delete [] m_count_PreDblk [i]; 545 delete [] m_count_PreDblk [i]; 549 546 } 550 547 if (m_offsetOrg_PreDblk[i]) 551 548 { 552 delete [] m_offsetOrg_PreDblk[i]; 549 delete [] m_offsetOrg_PreDblk[i]; 553 550 } 554 551 } … … 588 585 Void TEncSampleAdaptiveOffset::createEncBuffer() 589 586 { 590 m_iDistOrg = new Int64 [m_iNumTotalParts]; 591 m_dCostPartBest = new Double [m_iNumTotalParts]; 592 m_iTypePartBest = new Int [m_iNumTotalParts]; 587 m_iDistOrg = new Int64 [m_iNumTotalParts]; 588 m_dCostPartBest = new Double [m_iNumTotalParts]; 589 m_iTypePartBest = new Int [m_iNumTotalParts]; 593 590 594 591 m_iRate = new Int64* [m_iNumTotalParts]; … … 603 600 { 604 601 m_iRate[i] = new Int64 [MAX_NUM_SAO_TYPE]; 605 m_iDist[i] = new Int64 [MAX_NUM_SAO_TYPE]; 606 m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 607 608 m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 609 m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 610 m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 602 m_iDist[i] = new Int64 [MAX_NUM_SAO_TYPE]; 603 m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 604 605 m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 606 m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 607 m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 611 608 612 609 for (Int j=0;j<MAX_NUM_SAO_TYPE;j++) 613 610 { 614 m_iCount [i][j] = new Int64 [MAX_NUM_SAO_CLASS]; 615 m_iOffset[i][j] = new Int64 [MAX_NUM_SAO_CLASS]; 616 m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 611 m_iCount [i][j] = new Int64 [MAX_NUM_SAO_CLASS]; 612 m_iOffset[i][j] = new Int64 [MAX_NUM_SAO_CLASS]; 613 m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 617 614 } 618 615 } … … 627 624 for (Int j=0;j<3;j++) 628 625 { 629 m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 630 m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 626 m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 627 m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 631 628 632 629 for (Int k=0;k<MAX_NUM_SAO_TYPE;k++) 633 630 { 634 m_count_PreDblk [i][j][k] = new Int64 [MAX_NUM_SAO_CLASS]; 635 m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS]; 631 m_count_PreDblk [i][j][k] = new Int64 [MAX_NUM_SAO_CLASS]; 632 m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS]; 636 633 } 637 634 } … … 668 665 669 666 /** Start SAO encoder 670 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder 667 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder 671 668 */ 672 669 Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder) 673 670 { 674 m_bUseSBACRD = true;671 m_bUseSBACRD = true; 675 672 m_pcPic = pcPic; 676 673 m_pcEntropyCoder = pcEntropyCoder; … … 696 693 } 697 694 698 inline int xSign(int x)699 { 700 return ((x >> 31)  (( int)( (((unsigned int) x)) >> 31)));695 inline Int xSign(Int x) 696 { 697 return ((x >> 31)  ((Int)( (((UInt) x)) >> 31))); 701 698 } 702 699 … … 711 708 * \param pbBorderAvail availabilities of block border pixels 712 709 */ 713 Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail )710 Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr) 714 711 { 715 712 Int64 *stats, *count; … … 718 715 UInt edgeType; 719 716 Int x, y; 717 Pel *pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo; 720 718 721 719 // Band offset// … … 728 726 for (x=0; x< width; x++) 729 727 { 730 classIdx = m_lumaTableBo[pRec[x]];728 classIdx = pTableBo[pRec[x]]; 731 729 if (classIdx) 732 730 { 733 stats[classIdx] += (pOrg[x]  pRec[x]); 731 stats[classIdx] += (pOrg[x]  pRec[x]); 734 732 count[classIdx] ++; 735 733 } … … 744 742 pRec = pRecStart; 745 743 744 746 745 startX = (pbBorderAvail[SGU_L]) ? 0 : 1; 747 746 endX = (pbBorderAvail[SGU_R]) ? width : (width 1); … … 751 750 for (x=startX; x< endX; x++) 752 751 { 753 signRight = xSign(pRec[x]  pRec[x+1]); 752 signRight = xSign(pRec[x]  pRec[x+1]); 754 753 edgeType = signRight + signLeft + 2; 755 754 signLeft = signRight; … … 784 783 for (x=0; x< width; x++) 785 784 { 786 signDown = xSign(pRec[x]  pRec[x+stride]); 785 signDown = xSign(pRec[x]  pRec[x+stride]); 787 786 edgeType = signDown + m_iUpBuff1[x] + 2; 788 787 m_iUpBuff1[x] = signDown; … … 843 842 count[m_auiEoTable[edgeType]] ++; 844 843 845 m_iUpBufft[x+1] = signDown1; 844 m_iUpBufft[x+1] = signDown1; 846 845 } 847 846 m_iUpBufft[startX] = xSign(pRec[stride+startX]  pRec[startX1]); … … 989 988 posOffset = (yPos* stride) + xPos; 990 989 991 calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail); 992 } 993 } 990 calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail, iYCbCr); 991 } 992 } 993 994 994 } 995 995 … … 1006 1006 Pel* pRec; 1007 1007 Int iStride; 1008 Int iLcu Width= pTmpSPS>getMaxCUHeight();1009 Int iLcu Height= pTmpSPS>getMaxCUWidth();1008 Int iLcuHeight = pTmpSPS>getMaxCUHeight(); 1009 Int iLcuWidth = pTmpSPS>getMaxCUWidth(); 1010 1010 UInt uiLPelX = pTmpCu>getCUPelX(); 1011 1011 UInt uiTPelY = pTmpCu>getCUPelY(); … … 1021 1021 Int iEndX; 1022 1022 Int iEndY; 1023 Pel* pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo; 1023 1024 1024 1025 Int iIsChroma = (iYCbCr!=0)? 1:0; … … 1029 1030 } 1030 1031 1031 #if SAO_SKIP_RIGHT1032 1032 Int numSkipLineRight = iIsChroma? 3:5; 1033 1033 if (m_saoLcuBasedOptimization == 0) … … 1035 1035 numSkipLineRight = 0; 1036 1036 } 1037 #endif1038 1037 1039 1038 iPicWidthTmp = m_iPicWidth >> iIsChroma; … … 1065 1064 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr); 1066 1065 1067 #if SAO_SKIP_RIGHT1068 1066 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidthnumSkipLineRight; 1069 #endif1070 1071 1067 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeightnumSkipLine; 1072 1068 for (y=0; y<iEndY; y++) 1073 1069 { 1074 #if SAO_SKIP_RIGHT1075 1070 for (x=0; x<iEndX; x++) 1076 #else 1077 for (x=0; x<iLcuWidth; x++) 1078 #endif 1079 { 1080 iClassIdx = m_lumaTableBo[pRec[x]]; 1071 { 1072 iClassIdx = pTableBo[pRec[x]]; 1081 1073 if (iClassIdx) 1082 1074 { … … 1114 1106 1115 1107 iStartX = (uiLPelX == 0) ? 1 : 0; 1116 #if SAO_SKIP_RIGHT1117 1108 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidthnumSkipLineRight; 1118 #else1119 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;1120 #endif1121 1109 for (y=0; y<iLcuHeightnumSkipLine; y++) 1122 1110 { … … 1150 1138 1151 1139 iStartY = (uiTPelY == 0) ? 1 : 0; 1152 #if SAO_SKIP_RIGHT1153 1140 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidthnumSkipLineRight; 1154 #endif1155 1141 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight1 : iLcuHeightnumSkipLine; 1156 1142 if (uiTPelY == 0) … … 1166 1152 for (y=iStartY; y<iEndY; y++) 1167 1153 { 1168 #if SAO_SKIP_RIGHT1169 1154 for (x=0; x<iEndX; x++) 1170 #else1171 for (x=0; x<iLcuWidth; x++)1172 #endif1173 1155 { 1174 1156 iSignDown = xSign(pRec[x]  pRec[x+iStride]); … … 1197 1179 1198 1180 iStartX = (uiLPelX == 0) ? 1 : 0; 1199 #if SAO_SKIP_RIGHT1200 1181 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidthnumSkipLineRight; 1201 #else1202 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;1203 #endif1204 1182 1205 1183 iStartY = (uiTPelY == 0) ? 1 : 0; … … 1249 1227 1250 1228 iStartX = (uiLPelX == 0) ? 1 : 0; 1251 #if SAO_SKIP_RIGHT1252 1229 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidthnumSkipLineRight; 1253 #else1254 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;1255 #endif1256 1230 1257 1231 iStartY = (uiTPelY == 0) ? 1 : 0; … … 1297 1271 Pel* pRec; 1298 1272 Int stride; 1299 Int lcu Width= pTmpSPS>getMaxCUHeight();1300 Int lcu Height= pTmpSPS>getMaxCUWidth();1273 Int lcuHeight = pTmpSPS>getMaxCUHeight(); 1274 Int lcuWidth = pTmpSPS>getMaxCUWidth(); 1301 1275 UInt rPelX; 1302 1276 UInt bPelY; … … 1323 1297 UInt lPelX, tPelY; 1324 1298 TComDataCU *pTmpCu; 1299 Pel* pTableBo; 1325 1300 1326 1301 for (idxY = 0; idxY< frameHeightInCU; idxY++) … … 1328 1303 for (idxX = 0; idxX< frameWidthInCU; idxX++) 1329 1304 { 1330 lcu Width= pTmpSPS>getMaxCUHeight();1331 lcu Height= pTmpSPS>getMaxCUWidth();1305 lcuHeight = pTmpSPS>getMaxCUHeight(); 1306 lcuWidth = pTmpSPS>getMaxCUWidth(); 1332 1307 addr = idxX + frameWidthInCU*idxY; 1333 1308 pTmpCu = pcPic>getCU(addr); … … 1368 1343 1369 1344 stride = (yCbCr == 0)? pcPic>getStride(): pcPic>getCStride(); 1345 pTableBo = (yCbCr==0)?m_lumaTableBo:m_chromaTableBo; 1370 1346 1371 1347 //if(iSaoType == BO) … … 1390 1366 continue; 1391 1367 1392 classIdx = m_lumaTableBo[pRec[x]];1368 classIdx = pTableBo[pRec[x]]; 1393 1369 if (classIdx) 1394 1370 { … … 1703 1679 #endif 1704 1680 { 1705 m_eSliceType = m_pcPic>getSlice(0)>getSliceType(); 1706 m_iPicNalReferenceIdc = (m_pcPic>getSlice(0)>isReferenced() ? 1 :0); 1707 1708 #if SAO_CHROMA_LAMBDA 1709 m_dLambdaLuma = dLambdaLuma; 1710 m_dLambdaChroma = dLambdaChroma; 1681 if(m_bUseNIF) 1682 { 1683 m_pcPic>getPicYuvRec()>copyToPic(m_pcYuvTmp); 1684 } 1685 1686 m_uiSaoBitIncreaseY = max(g_bitDepthY  10, 0); 1687 m_uiSaoBitIncreaseC = max(g_bitDepthC  10, 0); 1688 m_iOffsetThY = 1 << min(g_bitDepthY  5, 5); 1689 m_iOffsetThC = 1 << min(g_bitDepthC  5, 5); 1690 resetSAOParam(pcSaoParam); 1691 if( !m_saoLcuBasedOptimization  !m_saoLcuBoundary ) 1692 { 1693 resetStats(); 1694 } 1695 Double dCostFinal = 0; 1696 if ( m_saoLcuBasedOptimization) 1697 { 1698 #if SAO_ENCODING_CHOICE 1699 rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth); 1711 1700 #else 1712 m_dLambdaLuma = dLambda; 1713 m_dLambdaChroma = dLambda; 1701 rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma); 1714 1702 #endif 1715 1716 if(m_bUseNIF)1717 {1718 m_pcPic>getPicYuvRec()>copyToPic(m_pcYuvTmp);1719 }1720 1721 #if FULL_NBIT1722 m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth8)  min((Int)(g_uiBitDepth + (g_uiBitDepth8)), 10);1723 #else1724 m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement  min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);1725 #endif1726 1727 #if FULL_NBIT1728 m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + (g_uiBitDepth8)5),5) );1729 #else1730 m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + g_uiBitIncrement5),5) );1731 #endif1732 1733 resetSAOParam(pcSaoParam);1734 if( !m_saoLcuBasedOptimization  !m_saoLcuBoundary )1735 {1736 resetStats();1737 }1738 Double dCostFinal = 0;1739 if ( m_saoLcuBasedOptimization)1740 {1741 #if SAO_ENCODING_CHOICE1742 rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth);1743 #else1744 rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);1745 #endif1746 }1747 else1748 {1749 pcSaoParam>bSaoFlag[0] = 1;1750 pcSaoParam>bSaoFlag[1] = 0;1751 dCostFinal = 0;1752 Double lambdaRdo = dLambdaLuma;1753 resetStats();1754 getSaoStats(pcSaoParam>psSaoPart[0], 0);1755 runQuadTreeDecision(pcSaoParam>psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0);1756 pcSaoParam>bSaoFlag[0] = dCostFinal < 0 ? 1:0;1757 if(pcSaoParam>bSaoFlag[0])1758 {1759 convertQT2SaoUnit(pcSaoParam, 0, 0);1760 assignSaoUnitSyntax(pcSaoParam>saoLcuParam[0], pcSaoParam>psSaoPart[0], pcSaoParam>oneUnitFlag[0], 0);1761 }1762 }1763 1764 if (pcSaoParam>bSaoFlag[0])1765 {1766 processSaoUnitAll( pcSaoParam>saoLcuParam[0], pcSaoParam>oneUnitFlag[0], 0);1767 }1768 if (pcSaoParam>bSaoFlag[1])1769 {1770 processSaoUnitAll( pcSaoParam>saoLcuParam[1], pcSaoParam>oneUnitFlag[1], 1);1771 processSaoUnitAll( pcSaoParam>saoLcuParam[2], pcSaoParam>oneUnitFlag[2], 2);1772 }1773 }1774 /** Check merge SAO unit1775 * \param saoUnitCurr current SAO unit1776 * \param saoUnitCheck SAO unit tobe check1777 * \param dir direction1778 */1779 Void TEncSampleAdaptiveOffset::checkMerge(SaoLcuParam * saoUnitCurr, SaoLcuParam * saoUnitCheck, Int dir)1780 {1781 Int i ;1782 Int countDiff = 0;1783 if (saoUnitCurr>partIdx != saoUnitCheck>partIdx)1784 {1785 if (saoUnitCurr>typeIdx !=1)1786 {1787 if (saoUnitCurr>typeIdx == saoUnitCheck>typeIdx)1788 {1789 for (i=0;i<saoUnitCurr>length;i++)1790 {1791 countDiff += (saoUnitCurr>offset[i] != saoUnitCheck>offset[i]);1792 }1793 countDiff += (saoUnitCurr>subTypeIdx != saoUnitCheck>subTypeIdx);1794 if (countDiff ==0)1795 {1796 saoUnitCurr>partIdx = saoUnitCheck>partIdx;1797 if (dir == 1)1798 {1799 saoUnitCurr>mergeUpFlag = 1;1800 saoUnitCurr>mergeLeftFlag = 0;1801 }1802 else1803 {1804 saoUnitCurr>mergeUpFlag = 0;1805 saoUnitCurr>mergeLeftFlag = 1;1806 }1807 }1808 }1809 }1810 else1811 {1812 if (saoUnitCurr>typeIdx == saoUnitCheck>typeIdx)1813 {1814 saoUnitCurr>partIdx = saoUnitCheck>partIdx;1815 if (dir == 1)1816 {1817 saoUnitCurr>mergeUpFlag = 1;1818 saoUnitCurr>mergeLeftFlag = 0;1819 }1820 else1821 {1822 saoUnitCurr>mergeUpFlag = 0;1823 saoUnitCurr>mergeLeftFlag = 1;1824 }1825 }1826 }1827 }1828 }1829 /** Assign SAO unit syntax from picturebased algorithm1830 * \param saoLcuParam SAO LCU parameters1831 * \param saoPart SAO part1832 * \param oneUnitFlag SAO one unit flag1833 * \param iYCbCr color component Index1834 */1835 Void TEncSampleAdaptiveOffset::assignSaoUnitSyntax(SaoLcuParam* saoLcuParam, SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr)1836 {1837 if (saoPart>bSplit == 0)1838 {1839 oneUnitFlag = 1;1840 }1841 else1842 {1843 Int i,j, addr, addrUp, addrLeft, idx, idxUp, idxLeft, idxCount;1844 1845 oneUnitFlag = 0;1846 1847 idxCount = 1;1848 saoLcuParam[0].mergeUpFlag = 0;1849 saoLcuParam[0].mergeLeftFlag = 0;1850 1851 for (j=0;j<m_iNumCuInHeight;j++)1852 {1853 for (i=0;i<m_iNumCuInWidth;i++)1854 {1855 addr = i + j*m_iNumCuInWidth;1856 addrLeft = (addr%m_iNumCuInWidth == 0) ? 1 : addr  1;1857 addrUp = (addr<m_iNumCuInWidth) ? 1 : addr  m_iNumCuInWidth;1858 idx = saoLcuParam[addr].partIdxTmp;1859 idxLeft = (addrLeft == 1) ? 1 : saoLcuParam[addrLeft].partIdxTmp;1860 idxUp = (addrUp == 1) ? 1 : saoLcuParam[addrUp].partIdxTmp;1861 1862 if(idx!=idxLeft && idx!=idxUp)1863 {1864 saoLcuParam[addr].mergeUpFlag = 0; idxCount++;1865 saoLcuParam[addr].mergeLeftFlag = 0;1866 saoLcuParam[addr].partIdx = idxCount;1867 }1868 else if (idx==idxLeft)1869 {1870 saoLcuParam[addr].mergeUpFlag = 1;1871 saoLcuParam[addr].mergeLeftFlag = 1;1872 saoLcuParam[addr].partIdx = saoLcuParam[addrLeft].partIdx;1873 }1874 else if (idx==idxUp)1875 {1876 saoLcuParam[addr].mergeUpFlag = 1;1877 saoLcuParam[addr].mergeLeftFlag = 0;1878 saoLcuParam[addr].partIdx = saoLcuParam[addrUp].partIdx;1879 }1880 if (addrUp != 1)1881 {1882 checkMerge(&saoLcuParam[addr], &saoLcuParam[addrUp], 1);1883 }1884 if (addrLeft != 1)1885 {1886 checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);1887 }1888 }1889 }1890 }1891 }1892 /** rate distortion optimization of all SAO units1893 * \param saoParam SAO parameters1894 * \param lambda1895 * \param lambdaChroma1896 */1897 #if SAO_ENCODING_CHOICE1898 Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)1899 #else1900 Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)1901 #endif1902 {1903 Int idxY;1904 Int idxX;1905 Int frameHeightInCU = saoParam>numCuInHeight;1906 Int frameWidthInCU = saoParam>numCuInWidth;1907 Int j, k;1908 Int addr = 0;1909 Int addrUp = 1;1910 Int addrLeft = 1;1911 Int compIdx = 0;1912 SaoLcuParam mergeSaoParam[3][2];1913 Double compDistortion[3];1914 1915 saoParam>bSaoFlag[0] = true;1916 saoParam>bSaoFlag[1] = true;1917 saoParam>oneUnitFlag[0] = false;1918 saoParam>oneUnitFlag[1] = false;1919 saoParam>oneUnitFlag[2] = false;1920 1921 #if SAO_ENCODING_CHOICE1922 #if SAO_ENCODING_CHOICE_CHROMA1923 Int numNoSao[2];1924 numNoSao[0] = 0;// Luma1925 numNoSao[1] = 0;// Chroma1926 if( depth > 0 && m_depthSaoRate[0][depth1] > SAO_ENCODING_RATE )1927 {1928 saoParam>bSaoFlag[0] = false;1929 }1930 1931 if( depth > 0 && m_depthSaoRate[1][depth1] > SAO_ENCODING_RATE_CHROMA )1932 {1933 saoParam>bSaoFlag[1] = false;1934 }1935 #else1936 Int numNoSao = 0;1937 1938 if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )1939 {1940 saoParam>bSaoFlag[0] = false;1941 saoParam>bSaoFlag[1] = false;1942 }1943 #endif1944 #endif1945 1946 for (idxY = 0; idxY< frameHeightInCU; idxY++)1947 {1948 for (idxX = 0; idxX< frameWidthInCU; idxX++)1949 {1950 addr = idxX + frameWidthInCU*idxY;1951 addrUp = addr < frameWidthInCU ? 1:idxX + frameWidthInCU*(idxY1);1952 addrLeft = idxX == 0 ? 1:idxX1 + frameWidthInCU*idxY;1953 Int allowMergeLeft = 1;1954 Int allowMergeUp = 1;1955 UInt rate;1956 Double bestCost, mergeCost;1957 1958 if (idxX!=0)1959 {1960 // check tile id and slice id1961 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx()))1962 {1963 allowMergeLeft = 0;1964 }1965 }1966 else1967 {1968 allowMergeLeft = 0;1969 }1970 if (idxY!=0)1971 {1972 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx()))1973 {1974 allowMergeUp = 0;1975 }1976 }1977 else1978 {1979 allowMergeUp = 0;1980 }1981 1982 compDistortion[0] = 0;1983 compDistortion[1] = 0;1984 compDistortion[2] = 0;1985 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);1986 1987 if (allowMergeLeft)1988 {1989 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0);1990 }1991 if (allowMergeUp)1992 {1993 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0);1994 }1995 1996 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );1997 1998 // reset stats Y, Cb, Cr1999 for ( compIdx=0;compIdx<3;compIdx++)2000 {2001 for ( j=0;j<MAX_NUM_SAO_TYPE;j++)2002 {2003 for ( k=0;k< MAX_NUM_SAO_CLASS;k++)2004 {2005 m_iOffset [compIdx][j][k] = 0;2006 if( m_saoLcuBasedOptimization && m_saoLcuBoundary )2007 {2008 m_iCount [compIdx][j][k] = m_count_PreDblk [addr][compIdx][j][k];2009 m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];2010 }2011 else2012 {2013 m_iCount [compIdx][j][k] = 0;2014 m_iOffsetOrg[compIdx][j][k] = 0;2015 }2016 }2017 }2018 saoParam>saoLcuParam[compIdx][addr].typeIdx = 1;2019 saoParam>saoLcuParam[compIdx][addr].mergeUpFlag = 0;2020 saoParam>saoLcuParam[compIdx][addr].mergeLeftFlag = 0;2021 saoParam>saoLcuParam[compIdx][addr].subTypeIdx = 0;2022 #if SAO_ENCODING_CHOICE2023 if( (compIdx ==0 && saoParam>bSaoFlag[0]) (compIdx >0 && saoParam>bSaoFlag[1]) )2024 #endif2025 {2026 calcSaoStatsCu(addr, compIdx, compIdx);2027 }2028 }2029 saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, lambda, &mergeSaoParam[0][0], &compDistortion[0]);2030 sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);2031 if( saoParam>bSaoFlag[0]  saoParam>bSaoFlag[1] )2032 {2033 // Cost of new SAO_params2034 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);2035 m_pcRDGoOnSbacCoder>resetBits();2036 if (allowMergeLeft)2037 {2038 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0);2039 }2040 if (allowMergeUp)2041 {2042 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0);2043 }2044 for ( compIdx=0;compIdx<3;compIdx++)2045 {2046 if( (compIdx ==0 && saoParam>bSaoFlag[0])  (compIdx >0 && saoParam>bSaoFlag[1]))2047 {2048 m_pcEntropyCoder>encodeSaoOffset(&saoParam>saoLcuParam[compIdx][addr], compIdx);2049 }2050 }2051 2052 rate = m_pcEntropyCoder>getNumberOfWrittenBits();2053 bestCost = compDistortion[0] + (Double)rate;2054 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2055 2056 // Cost of Merge2057 for(Int mergeUp=0; mergeUp<2; ++mergeUp)2058 {2059 if ( (allowMergeLeft && (mergeUp==0))  (allowMergeUp && (mergeUp==1)) )2060 {2061 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);2062 m_pcRDGoOnSbacCoder>resetBits();2063 if (allowMergeLeft)2064 {2065 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(1mergeUp);2066 }2067 if ( allowMergeUp && (mergeUp==1) )2068 {2069 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(1);2070 }2071 2072 rate = m_pcEntropyCoder>getNumberOfWrittenBits();2073 mergeCost = compDistortion[mergeUp+1] + (Double)rate;2074 if (mergeCost < bestCost)2075 {2076 bestCost = mergeCost;2077 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2078 for ( compIdx=0;compIdx<3;compIdx++)2079 {2080 mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1mergeUp;2081 mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;2082 if( (compIdx==0 && saoParam>bSaoFlag[0])  (compIdx>0 && saoParam>bSaoFlag[1]))2083 {2084 copySaoUnit(&saoParam>saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );2085 }2086 }2087 }2088 }2089 }2090 #if SAO_ENCODING_CHOICE2091 #if SAO_ENCODING_CHOICE_CHROMA2092 if( saoParam>saoLcuParam[0][addr].typeIdx == 1)2093 {2094 numNoSao[0]++;2095 }2096 if( saoParam>saoLcuParam[1][addr].typeIdx == 1)2097 {2098 numNoSao[1]+=2;2099 }2100 #else2101 for ( compIdx=0;compIdx<3;compIdx++)2102 {2103 if( depth == 0 && saoParam>saoLcuParam[compIdx][addr].typeIdx == 1)2104 {2105 numNoSao++;2106 }2107 }2108 #endif2109 #endif2110 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2111 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);2112 }2113 }2114 }2115 #if SAO_ENCODING_CHOICE2116 #if SAO_ENCODING_CHOICE_CHROMA2117 #if SAO_ENCODING_CHOICE_CHROMA_BF2118 if( !saoParam>bSaoFlag[0])2119 {2120 m_depthSaoRate[0][depth] = 1.0;2121 }2122 else2123 {2124 m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);2125 }2126 if( !saoParam>bSaoFlag[1])2127 {2128 m_depthSaoRate[1][depth] = 1.0;2129 }2130 else2131 {2132 m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);2133 }2134 #else2135 m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);2136 m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);2137 #endif2138 #else2139 if( depth == 0)2140 {2141 // update SAO Rate2142 m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);2143 }2144 #endif2145 #endif2146 }2147 /** rate distortion optimization of SAO unit2148 * \param saoParam SAO parameters2149 * \param addr address2150 * \param addrUp above address2151 * \param addrLeft left address2152 * \param yCbCr color component index2153 * \param lambda2154 */2155 inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)2156 {2157 Int64 estDist = 0;2158 Int classIdx;2159 for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ? m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)2160 {2161 if( typeIdx == SAO_BO)2162 {2163 currentDistortionTableBo[classIdx1] = 0;2164 currentRdCostTableBo[classIdx1] = lambda;2165 }2166 if(m_iCount [compIdx][typeIdx][classIdx])2167 {2168 #if FULL_NBIT2169 m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitDepth8) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));2170 #else2171 m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitIncrement) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));2172 #endif2173 m_iOffset[compIdx][typeIdx][classIdx] = Clip3(m_iOffsetTh+1, m_iOffsetTh1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);2174 if (typeIdx < 4)2175 {2176 if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )2177 {2178 m_iOffset[compIdx][typeIdx][classIdx] = 0;2179 }2180 if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)2181 {2182 m_iOffset[compIdx][typeIdx][classIdx] = 0;2183 }2184 }2185 m_iOffset[compIdx][typeIdx][classIdx] = estIterOffset( typeIdx, classIdx, lambda, m_iOffset[compIdx][typeIdx][classIdx], m_iCount [compIdx][typeIdx][classIdx], m_iOffsetOrg[compIdx][typeIdx][classIdx], shift, m_uiSaoBitIncrease, currentDistortionTableBo, currentRdCostTableBo );2186 }2187 else2188 {2189 m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;2190 m_iOffset[compIdx][typeIdx][classIdx] = 0;2191 }2192 if( typeIdx != SAO_BO )2193 {2194 estDist += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << m_uiSaoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);2195 }2196 }2197 return estDist;2198 }2199 2200 inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)2201 {2202 return (( count*offset*offsetoffsetOrg*offset*2 ) >> shift);2203 }2204 inline Int64 TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo )2205 {2206 //Clean up, best_q_offset.2207 Int64 iterOffset, tempOffset;2208 Int64 tempDist, tempRate;2209 Double tempCost, tempMinCost;2210 Int64 offsetOutput = 0;2211 iterOffset = offsetInput;2212 // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here.2213 tempMinCost = lambda;2214 while (iterOffset != 0)2215 {2216 // Calculate the bits required for signalling the offset2217 tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);2218 if (abs((Int)iterOffset)==m_iOffsetTh1)2219 {2220 tempRate ;2221 }2222 // Do the dequntization before distorion calculation2223 tempOffset = iterOffset << bitIncrease;2224 tempDist = estSaoDist( count, tempOffset, offsetOrg, shift);2225 tempCost = ((Double)tempDist + lambda * (Double) tempRate);2226 if(tempCost < tempMinCost)2227 {2228 tempMinCost = tempCost;2229 offsetOutput = iterOffset;2230 if(typeIdx == SAO_BO)2231 {2232 currentDistortionTableBo[classIdx1] = (Int) tempDist;2233 currentRdCostTableBo[classIdx1] = tempCost;2234 }2235 }2236 iterOffset = (iterOffset > 0) ? (iterOffset1):(iterOffset+1);2237 }2238 return offsetOutput;2239 }2240 2241 Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)2242 {2243 Int typeIdx;2244 Int64 estDist;2245 Int classIdx;2246 2247 Int shift = g_uiBitIncrement << 1;2248 2249 Int64 bestDist;2250 2251 SaoLcuParam* saoLcuParam = &(saoParam>saoLcuParam[yCbCr][addr]);2252 SaoLcuParam* saoLcuParamNeighbor = NULL;2253 2254 resetSaoUnit(saoLcuParam);2255 resetSaoUnit(&compSaoParam[0]);2256 resetSaoUnit(&compSaoParam[1]);2257 2258 Double dCostPartBest = MAX_DOUBLE;2259 2260 Double bestRDCostTableBo = MAX_DOUBLE;2261 Int bestClassTableBo = 0;2262 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];2263 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];2264 2265 SaoLcuParam saoLcuParamRdo;2266 Double estRate = 0;2267 2268 resetSaoUnit(&saoLcuParamRdo);2269 2270 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2271 m_pcRDGoOnSbacCoder>resetBits();2272 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo, yCbCr);2273 dCostPartBest = m_pcEntropyCoder>getNumberOfWrittenBits()*lambda ;2274 2275 copySaoUnit(saoLcuParam, &saoLcuParamRdo );2276 2277 bestDist = 0;2278 2279 for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)2280 {2281 estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);2282 if( typeIdx == SAO_BO )2283 {2284 // Estimate Best Position2285 Double currentRDCost = 0.0;2286 2287 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++)2288 {2289 currentRDCost = 0.0;2290 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)2291 {2292 currentRDCost += currentRdCostTableBo[uj];2293 }2294 2295 if( currentRDCost < bestRDCostTableBo)2296 {2297 bestRDCostTableBo = currentRDCost;2298 bestClassTableBo = i;2299 }2300 }2301 2302 // Re code all Offsets2303 // Code Center2304 estDist = 0;2305 for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)2306 {2307 estDist += currentDistortionTableBo[classIdx];2308 }2309 }2310 resetSaoUnit(&saoLcuParamRdo);2311 saoLcuParamRdo.length = m_iNumClass[typeIdx];2312 saoLcuParamRdo.typeIdx = typeIdx;2313 saoLcuParamRdo.mergeLeftFlag = 0;2314 saoLcuParamRdo.mergeUpFlag = 0;2315 saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;2316 for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)2317 {2318 saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];2319 }2320 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2321 m_pcRDGoOnSbacCoder>resetBits();2322 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo, yCbCr);2323 2324 estRate = m_pcEntropyCoder>getNumberOfWrittenBits();2325 m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);2326 2327 if(m_dCost[yCbCr][typeIdx] < dCostPartBest)2328 {2329 dCostPartBest = m_dCost[yCbCr][typeIdx];2330 copySaoUnit(saoLcuParam, &saoLcuParamRdo );2331 bestDist = estDist;2332 }2333 }2334 2335 compDistortion[0] += ((Double)bestDist/lambda);2336 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2337 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam, yCbCr);2338 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );2339 2340 // merge left or merge up2341 for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)2342 {2343 saoLcuParamNeighbor = NULL;2344 if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)2345 {2346 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrLeft]);2347 }2348 else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)2349 {2350 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrUp]);2351 }2352 if (saoLcuParamNeighbor!=NULL)2353 {2354 estDist = 0;2355 typeIdx = saoLcuParamNeighbor>typeIdx;2356 if (typeIdx>=0)2357 {2358 Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor>subTypeIdx:0;2359 Int merge_iOffset;2360 for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)2361 {2362 merge_iOffset = saoLcuParamNeighbor>offset[classIdx];2363 estDist += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1], shift);2364 }2365 }2366 else2367 {2368 estDist = 0;2369 }2370 2371 copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );2372 compSaoParam[idxNeighbor].mergeUpFlag = idxNeighbor;2373 compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;2374 2375 compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);2376 }2377 }2378 }2379 2380 Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)2381 {2382 Int typeIdx;2383 2384 Int64 estDist[2];2385 Int classIdx;2386 Int shift = g_uiBitIncrement << 1;2387 Int64 bestDist = 0;2388 2389 SaoLcuParam* saoLcuParam[2] = {&(saoParam>saoLcuParam[1][addr]), &(saoParam>saoLcuParam[2][addr])};2390 SaoLcuParam* saoLcuParamNeighbor[2] = {NULL, NULL};2391 SaoLcuParam* saoMergeParam[2][2];2392 saoMergeParam[0][0] = &crSaoParam[0];2393 saoMergeParam[0][1] = &crSaoParam[1];2394 saoMergeParam[1][0] = &cbSaoParam[0];2395 saoMergeParam[1][1] = &cbSaoParam[1];2396 2397 resetSaoUnit(saoLcuParam[0]);2398 resetSaoUnit(saoLcuParam[1]);2399 resetSaoUnit(saoMergeParam[0][0]);2400 resetSaoUnit(saoMergeParam[0][1]);2401 resetSaoUnit(saoMergeParam[1][0]);2402 resetSaoUnit(saoMergeParam[1][1]);2403 2404 Double costPartBest = MAX_DOUBLE;2405 2406 Double bestRDCostTableBo;2407 Int bestClassTableBo[2] = {0, 0};2408 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];2409 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];2410 2411 SaoLcuParam saoLcuParamRdo[2];2412 Double estRate = 0;2413 2414 resetSaoUnit(&saoLcuParamRdo[0]);2415 resetSaoUnit(&saoLcuParamRdo[1]);2416 2417 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2418 m_pcRDGoOnSbacCoder>resetBits();2419 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[0], 1);2420 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[1], 2);2421 2422 costPartBest = m_pcEntropyCoder>getNumberOfWrittenBits()*lambda ;2423 copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );2424 copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );2425 2426 for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)2427 {2428 if( typeIdx == SAO_BO )2429 {2430 // Estimate Best Position2431 for(Int compIdx = 0; compIdx < 2; compIdx++)2432 {2433 Double currentRDCost = 0.0;2434 bestRDCostTableBo = MAX_DOUBLE;2435 estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);2436 2437 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++)2438 {2439 currentRDCost = 0.0;2440 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)2441 {2442 currentRDCost += currentRdCostTableBo[uj];2443 }2444 2445 if( currentRDCost < bestRDCostTableBo)2446 {2447 bestRDCostTableBo = currentRDCost;2448 bestClassTableBo[compIdx] = i;2449 }2450 }2451 2452 // Re code all Offsets2453 // Code Center2454 estDist[compIdx] = 0;2455 for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)2456 {2457 estDist[compIdx] += currentDistortionTableBo[classIdx];2458 }2459 }2460 }2461 else2462 {2463 estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);2464 estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);2465 }2466 2467 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2468 m_pcRDGoOnSbacCoder>resetBits();2469 2470 for(Int compIdx = 0; compIdx < 2; compIdx++)2471 {2472 resetSaoUnit(&saoLcuParamRdo[compIdx]);2473 saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];2474 saoLcuParamRdo[compIdx].typeIdx = typeIdx;2475 saoLcuParamRdo[compIdx].mergeLeftFlag = 0;2476 saoLcuParamRdo[compIdx].mergeUpFlag = 0;2477 saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;2478 for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)2479 {2480 saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];2481 }2482 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);2483 }2484 estRate = m_pcEntropyCoder>getNumberOfWrittenBits();2485 m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1]) + lambda * (Double) estRate);2486 2487 if(m_dCost[1][typeIdx] < costPartBest)2488 {2489 costPartBest = m_dCost[1][typeIdx];2490 copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );2491 copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );2492 bestDist = (estDist[0]+estDist[1]);2493 }2494 }2495 2496 distortion[0] += ((Double)bestDist/lambda);2497 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);2498 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam[0], 1);2499 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam[1], 2);2500 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );2501 2502 // merge left or merge up2503 2504 for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)2505 {2506 for(Int compIdx = 0; compIdx < 2; compIdx++)2507 {2508 saoLcuParamNeighbor[compIdx] = NULL;2509 if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)2510 {2511 saoLcuParamNeighbor[compIdx] = &(saoParam>saoLcuParam[compIdx+1][addrLeft]);2512 }2513 else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)2514 {2515 saoLcuParamNeighbor[compIdx] = &(saoParam>saoLcuParam[compIdx+1][addrUp]);2516 }2517 if (saoLcuParamNeighbor[compIdx]!=NULL)2518 {2519 estDist[compIdx] = 0;2520 typeIdx = saoLcuParamNeighbor[compIdx]>typeIdx;2521 if (typeIdx>=0)2522 {2523 Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]>subTypeIdx:0;2524 Int merge_iOffset;2525 for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)2526 {2527 merge_iOffset = saoLcuParamNeighbor[compIdx]>offset[classIdx];2528 estDist[compIdx] += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1], shift);2529 }2530 }2531 else2532 {2533 estDist[compIdx] = 0;2534 }2535 2536 copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );2537 saoMergeParam[compIdx][idxNeighbor]>mergeUpFlag = idxNeighbor;2538 saoMergeParam[compIdx][idxNeighbor]>mergeLeftFlag = !idxNeighbor;2539 distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);2540 }2541 }2542 }2543 }2544 #else2545 TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()2546 {2547 m_pcEntropyCoder = NULL;2548 m_pppcRDSbacCoder = NULL;2549 m_pcRDGoOnSbacCoder = NULL;2550 m_pppcBinCoderCABAC = NULL;2551 m_iCount = NULL;2552 m_iOffset = NULL;2553 m_iOffsetOrg = NULL;2554 m_iRate = NULL;2555 m_iDist = NULL;2556 m_dCost = NULL;2557 m_dCostPartBest = NULL;2558 m_iDistOrg = NULL;2559 m_iTypePartBest = NULL;2560 }2561 TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()2562 {2563 2564 }2565 // ====================================================================================================================2566 // Constants2567 // ====================================================================================================================2568 2569 2570 // ====================================================================================================================2571 // Tables2572 // ====================================================================================================================2573 2574 inline Double xRoundIbdi2(Double x)2575 {2576 #if FULL_NBIT2577 Int bitDepthMinus8 = g_uiBitDepth  8;2578 return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepthMinus81)))/(1<<bitDepthMinus8)) : ((Int)(((Int)(x)(1<<(bitDepthMinus81)))/(1<<bitDepthMinus8)));2579 #else2580 return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)(1<<(g_uiBitIncrement1)))/(1<<g_uiBitIncrement)));2581 #endif2582 }2583 2584 /** rounding with IBDI2585 * \param x2586 */2587 inline Double xRoundIbdi(Double x)2588 {2589 #if FULL_NBIT2590 return (g_uiBitDepth > 8 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)0.5)))) ;2591 #else2592 return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)0.5)))) ;2593 #endif2594 }2595 2596 2597 2598 /** process SAO for one partition2599 * \param *psQTPart, iPartIdx, dLambda2600 */2601 Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda)2602 {2603 Int iTypeIdx;2604 Int iNumTotalType = MAX_NUM_SAO_TYPE;2605 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]);2606 2607 Int64 iEstDist;2608 Int64 iOffsetOrg;2609 Int64 iOffset;2610 Int64 iCount;2611 Int iClassIdx;2612 Int uiShift = g_uiBitIncrement << 1;2613 UInt uiDepth = pOnePart>PartLevel;2614 2615 m_iDistOrg [iPartIdx] = 0;2616 2617 Double bestRDCostTableBo = MAX_DOUBLE;2618 Int bestClassTableBo = 0;2619 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];2620 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];2621 2622 #if HHI_INTERVIEW_SKIP2623 Int iFrameWidthInCU = m_pcPic>getFrameWidthInCU();2624 Int LcuIdxX = psQTPart>StartCUX;2625 Int LcuIdxY = psQTPart>StartCUY;2626 Int iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;2627 TComDataCU *pcCU = m_pcPic>getCU(iAddr);2628 Bool bRenderable = pcCU>getRenderable(0) ;2629 2630 #endif2631 for (iTypeIdx=1; iTypeIdx<iNumTotalType; iTypeIdx++)2632 {2633 if( m_bUseSBACRD )2634 {2635 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);2636 m_pcRDGoOnSbacCoder>resetBits();2637 }2638 else2639 {2640 m_pcEntropyCoder>resetEntropy();2641 m_pcEntropyCoder>resetBits();2642 }2643 2644 iEstDist = 0;2645 2646 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoTypeIdx(iTypeIdx+1);2647 2648 if (iTypeIdx>=0)2649 {2650 2651 for(iClassIdx=1; iClassIdx < ( (iTypeIdx < SAO_BO) ? m_iNumClass[iTypeIdx]+1 : SAO_MAX_BO_CLASSES+1); iClassIdx++)2652 {2653 if( iTypeIdx == SAO_BO)2654 {2655 currentDistortionTableBo[iClassIdx1] = 0;2656 currentRdCostTableBo[iClassIdx1] = dLambda;2657 }2658 #if HHI_INTERVIEW_SKIP2659 if(m_iCount [iPartIdx][iTypeIdx][iClassIdx] && !bRenderable)2660 #else2661 if(m_iCount [iPartIdx][iTypeIdx][iClassIdx])2662 #endif2663 {2664 #if FULL_NBIT2665 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]<<g_uiBitDepth8) / (Double)(m_iCount [iPartIdx][iTypeIdx][iClassIdx]<<m_uiSaoBitIncrease));2666 #else2667 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]<<g_uiBitIncrement) / (Double)(m_iCount [iPartIdx][iTypeIdx][iClassIdx]<<m_uiSaoBitIncrease));2668 #endif2669 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = Clip3(m_iOffsetTh, m_iOffsetTh1, (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);2670 2671 if (iTypeIdx < 4)2672 {2673 if ( m_iOffset[iPartIdx][iTypeIdx][iClassIdx]<0 && iClassIdx<3 )2674 {2675 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;2676 }2677 if ( m_iOffset[iPartIdx][iTypeIdx][iClassIdx]>0 && iClassIdx>=3)2678 {2679 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;2680 }2681 }2682 {2683 //Clean up, best_q_offset.2684 Int64 iIterOffset, iTempOffset;2685 Int64 iTempDist, iTempRate;2686 Double dTempCost, dTempMinCost;2687 UInt uiLength, uiTemp;2688 2689 iIterOffset = m_iOffset[iPartIdx][iTypeIdx][iClassIdx];2690 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;2691 dTempMinCost = dLambda; // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here.2692 2693 while (iIterOffset != 0)2694 {2695 // Calculate the bits required for signalling the offset2696 uiLength = 1;2697 uiTemp = (UInt)((iIterOffset <= 0) ? ( (iIterOffset<<1) + 1 ) : (iIterOffset<<1));2698 while( 1 != uiTemp )2699 {2700 uiTemp >>= 1;2701 uiLength += 2;2702 }2703 iTempRate = (uiLength >> 1) + ((uiLength+1) >> 1);2704 2705 // Do the dequntization before distorion calculation2706 iTempOffset = iIterOffset << m_uiSaoBitIncrease;2707 iTempDist = (( m_iCount [iPartIdx][iTypeIdx][iClassIdx]*iTempOffset*iTempOffsetm_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]*iTempOffset*2 ) >> uiShift);2708 2709 dTempCost = ((Double)iTempDist + dLambda * (Double) iTempRate);2710 if(dTempCost < dTempMinCost)2711 {2712 dTempMinCost = dTempCost;2713 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = iIterOffset;2714 if(iTypeIdx == SAO_BO)2715 {2716 currentDistortionTableBo[iClassIdx1] = (Int) iTempDist;2717 currentRdCostTableBo[iClassIdx1] = dTempCost;2718 }2719 }2720 iIterOffset = (iIterOffset > 0) ? (iIterOffset1):(iIterOffset+1);2721 }2722 2723 }2724 }2725 else2726 {2727 m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] = 0;2728 m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;2729 }2730 if( iTypeIdx != SAO_BO )2731 {2732 iCount = m_iCount [iPartIdx][iTypeIdx][iClassIdx];2733 iOffset = m_iOffset[iPartIdx][iTypeIdx][iClassIdx] << m_uiSaoBitIncrease;2734 iOffsetOrg = m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx];2735 iEstDist += (( iCount*iOffset*iOffsetiOffsetOrg*iOffset*2 ) >> uiShift);2736 if (iTypeIdx < 4)2737 {2738 if (iClassIdx<3)2739 {2740 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);2741 }2742 else2743 {2744 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);2745 }2746 }2747 else2748 {2749 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoSvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);2750 }2751 }2752 }2753 2754 if( iTypeIdx == SAO_BO )2755 {2756 // Estimate Best Position2757 Double currentRDCost = 0.0;2758 2759 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++)2760 {2761 currentRDCost = 0.0;2762 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)2763 {2764 currentRDCost += currentRdCostTableBo[uj];2765 }2766 2767 if( currentRDCost < bestRDCostTableBo)2768 {2769 bestRDCostTableBo = currentRDCost;2770 bestClassTableBo = i;2771 }2772 }2773 2774 // Re code all Offsets2775 // Code Center2776 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUflc( (UInt) (bestClassTableBo) );2777 2778 for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++)2779 {2780 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoSvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+1]);2781 iEstDist += currentDistortionTableBo[iClassIdx];2782 }2783 }2784 2785 m_iDist[iPartIdx][iTypeIdx] = iEstDist;2786 m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder>getNumberOfWrittenBits();2787 2788 m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]);2789 2790 if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx])2791 {2792 m_iDistOrg [iPartIdx] = 0;2793 m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx];2794 m_iTypePartBest[iPartIdx] = iTypeIdx;2795 if( m_bUseSBACRD )2796 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] );2797 }2798 }2799 else2800 {2801 if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] )2802 {2803 m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder>getNumberOfWrittenBits()*dLambda ;2804 m_iTypePartBest[iPartIdx] = 1;2805 if( m_bUseSBACRD )2806 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[pOnePart>PartLevel][CI_TEMP_BEST] );2807 }2808 }2809 }2810 2811 pOnePart>bProcessed = true;2812 pOnePart>bSplit = false;2813 pOnePart>iMinDist = m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];2814 pOnePart>iMinRate = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);2815 pOnePart>dMinCost = pOnePart>iMinDist + dLambda * pOnePart>iMinRate;2816 pOnePart>iBestType = m_iTypePartBest[iPartIdx];2817 if (pOnePart>iBestType != 1)2818 {2819 // pOnePart>bEnableFlag = 1;2820 pOnePart>iLength = m_iNumClass[pOnePart>iBestType];2821 Int minIndex = 0;2822 if( pOnePart>iBestType == SAO_BO )2823 {2824 pOnePart>bandPosition = bestClassTableBo;2825 minIndex = pOnePart>bandPosition;2826 }2827 for (Int i=0; i< pOnePart>iLength ; i++)2828 {2829 pOnePart>iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart>iBestType][minIndex+i+1];2830 }2831 2832 }2833 else2834 {2835 // pOnePart>bEnableFlag = 0;2836 pOnePart>iLength = 0;2837 }2838 }2839 2840 /** Run partition tree disable2841 */2842 Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx)2843 {2844 SAOQTPart* pOnePart= &(psQTPart[iPartIdx]);2845 pOnePart>bSplit = false;2846 pOnePart>iLength = 0;2847 pOnePart>iBestType = 1;2848 2849 if (pOnePart>PartLevel < m_uiMaxSplitLevel)2850 {2851 for (Int i=0; i<NUM_DOWN_PART; i++)2852 {2853 disablePartTree(psQTPart, pOnePart>DownPartsIdx[i]);2854 }2855 }2856 }2857 2858 /** Run quadtree decision function2859 * \param iPartIdx, pcPicOrg, pcPicDec, pcPicRest, &dCostFinal2860 */2861 Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda)2862 {2863 SAOQTPart* pOnePart = &(psQTPart[iPartIdx]);2864 2865 UInt uiDepth = pOnePart>PartLevel;2866 UInt uhNextDepth = uiDepth+1;2867 2868 if (iPartIdx == 0)2869 {2870 dCostFinal = 0;2871 }2872 2873 //SAO for this part2874 if(!pOnePart>bProcessed)2875 {2876 rdoSaoOnePart (psQTPart, iPartIdx, dLambda);2877 }2878 2879 //SAO for sub 4 parts2880 if (pOnePart>PartLevel < iMaxLevel)2881 {2882 Double dCostNotSplit = dLambda + pOnePart>dMinCost;2883 Double dCostSplit = dLambda;2884 2885 for (Int i=0; i< NUM_DOWN_PART ;i++)2886 {2887 if( m_bUseSBACRD )2888 {2889 if ( 0 == i) //initialize RD with previous depth buffer2890 {2891 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);2892 }2893 else2894 {2895 m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);2896 }2897 }2898 runQuadTreeDecision(psQTPart, pOnePart>DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda);2899 dCostSplit += dCostFinal;2900 if( m_bUseSBACRD )2901 {2902 m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]);2903 }2904 }2905 2906 if(dCostSplit < dCostNotSplit)2907 {2908 dCostFinal = dCostSplit;2909 pOnePart>bSplit = true;2910 pOnePart>iLength = 0;2911 pOnePart>iBestType = 1;2912 if( m_bUseSBACRD )2913 {2914 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);2915 }2916 }2917 else2918 {2919 dCostFinal = dCostNotSplit;2920 pOnePart>bSplit = false;2921 for (Int i=0; i<NUM_DOWN_PART; i++)2922 {2923 disablePartTree(psQTPart, pOnePart>DownPartsIdx[i]);2924 }2925 if( m_bUseSBACRD )2926 {2927 m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]>load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);2928 }2929 }2930 }2931 else2932 {2933 dCostFinal = pOnePart>dMinCost;2934 }2935 }2936 2937 /** delete allocated memory of TEncSampleAdaptiveOffset class.2938 */2939 Void TEncSampleAdaptiveOffset::destroyEncBuffer()2940 {2941 for (Int i=0;i<m_iNumTotalParts;i++)2942 {2943 for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)2944 {2945 if (m_iCount [i][j])2946 {2947 delete [] m_iCount [i][j];2948 }2949 if (m_iOffset[i][j])2950 {2951 delete [] m_iOffset[i][j];2952 }2953 if (m_iOffsetOrg[i][j])2954 {2955 delete [] m_iOffsetOrg[i][j];2956 }2957 }2958 if (m_iRate[i])2959 {2960 delete [] m_iRate[i];2961 }2962 if (m_iDist[i])2963 {2964 delete [] m_iDist[i];2965 }2966 if (m_dCost[i])2967 {2968 delete [] m_dCost[i];2969 }2970 if (m_iCount [i])2971 {2972 delete [] m_iCount [i];2973 }2974 if (m_iOffset[i])2975 {2976 delete [] m_iOffset[i];2977 }2978 if (m_iOffsetOrg[i])2979 {2980 delete [] m_iOffsetOrg[i];2981 }2982 2983 }2984 if (m_iDistOrg)2985 {2986 delete [] m_iDistOrg ; m_iDistOrg = NULL;2987 }2988 if (m_dCostPartBest)2989 {2990 delete [] m_dCostPartBest ; m_dCostPartBest = NULL;2991 }2992 if (m_iTypePartBest)2993 {2994 delete [] m_iTypePartBest ; m_iTypePartBest = NULL;2995 }2996 if (m_iRate)2997 {2998 delete [] m_iRate ; m_iRate = NULL;2999 }3000 if (m_iDist)3001 {3002 delete [] m_iDist ; m_iDist = NULL;3003 }3004 if (m_dCost)3005 {3006 delete [] m_dCost ; m_dCost = NULL;3007 }3008 if (m_iCount)3009 {3010 delete [] m_iCount ; m_iCount = NULL;3011 }3012 if (m_iOffset)3013 {3014 delete [] m_iOffset ; m_iOffset = NULL;3015 }3016 if (m_iOffsetOrg)3017 {3018 delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;3019 }3020 3021 Int iMaxDepth = 4;3022 Int iDepth;3023 for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )3024 {3025 for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )3026 {3027 delete m_pppcRDSbacCoder[iDepth][iCIIdx];3028 delete m_pppcBinCoderCABAC[iDepth][iCIIdx];3029 }3030 }3031 3032 for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )3033 {3034 delete [] m_pppcRDSbacCoder[iDepth];3035 delete [] m_pppcBinCoderCABAC[iDepth];3036 }3037 3038 delete [] m_pppcRDSbacCoder;3039 delete [] m_pppcBinCoderCABAC;3040 }3041 3042 /** create Encoder Buffer for SAO3043 * \param3044 */3045 Void TEncSampleAdaptiveOffset::createEncBuffer()3046 {3047 m_iDistOrg = new Int64 [m_iNumTotalParts];3048 m_dCostPartBest = new Double [m_iNumTotalParts];3049 m_iTypePartBest = new Int [m_iNumTotalParts];3050 3051 m_iRate = new Int64* [m_iNumTotalParts];3052 m_iDist = new Int64* [m_iNumTotalParts];3053 m_dCost = new Double*[m_iNumTotalParts];3054 3055 m_iCount = new Int64 **[m_iNumTotalParts];3056 m_iOffset = new Int64 **[m_iNumTotalParts];3057 m_iOffsetOrg = new Int64 **[m_iNumTotalParts];3058 3059 for (Int i=0;i<m_iNumTotalParts;i++)3060 {3061 m_iRate[i] = new Int64 [MAX_NUM_SAO_TYPE];3062 m_iDist[i] = new Int64 [MAX_NUM_SAO_TYPE];3063 m_dCost[i] = new Double [MAX_NUM_SAO_TYPE];3064 3065 m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE];3066 m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE];3067 m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE];3068 3069 for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)3070 {3071 m_iCount [i][j] = new Int64 [MAX_NUM_SAO_CLASS];3072 m_iOffset[i][j] = new Int64 [MAX_NUM_SAO_CLASS];3073 m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS];3074 }3075 }3076 3077 Int iMaxDepth = 4;3078 m_pppcRDSbacCoder = new TEncSbac** [iMaxDepth+1];3079 #if FAST_BIT_EST3080 m_pppcBinCoderCABAC = new TEncBinCABACCounter** [iMaxDepth+1];3081 #else3082 m_pppcBinCoderCABAC = new TEncBinCABAC** [iMaxDepth+1];3083 #endif3084 3085 for ( Int iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )3086 {3087 m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM];3088 #if FAST_BIT_EST3089 m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM];3090 #else3091 m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM];3092 #endif3093 for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )3094 {3095 m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac;3096 #if FAST_BIT_EST3097 m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter;3098 #else3099 m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC;3100 #endif3101 m_pppcRDSbacCoder [iDepth][iCIIdx]>init( m_pppcBinCoderCABAC [iDepth][iCIIdx] );3102 }3103 }3104 }3105 3106 /** Start SAO encoder3107 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder3108 */3109 Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)3110 {3111 if( pcRDGoOnSbacCoder )3112 m_bUseSBACRD = true;3113 else3114 m_bUseSBACRD = false;3115 3116 m_pcPic = pcPic;3117 m_pcEntropyCoder = pcEntropyCoder;3118 3119 m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;3120 m_pcEntropyCoder>resetEntropy();3121 m_pcEntropyCoder>resetBits();3122 3123 if( m_bUseSBACRD )3124 {3125 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);3126 m_pppcRDSbacCoder[0][CI_CURR_BEST]>load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);3127 }3128 }3129 3130 /** End SAO encoder3131 */3132 Void TEncSampleAdaptiveOffset::endSaoEnc()3133 {3134 m_pcPic = NULL;3135 m_pcEntropyCoder = NULL;3136 }3137 3138 inline int xSign(int x)3139 {3140 return ((x >> 31)  ((int)( (((unsigned int) x)) >> 31)));3141 }3142 3143 /** Calculate SAO statistics for noncrossslice or noncrosstile processing3144 * \param pRecStart tobefiltered block buffer pointer3145 * \param pOrgStart original block buffer pointer3146 * \param stride picture buffer stride3147 * \param ppStat statistics buffer3148 * \param ppCount counter buffer3149 * \param width block width3150 * \param height block height3151 * \param pbBorderAvail availabilities of block border pixels3152 */3153 Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail)3154 {3155 Int64 *stats, *count;3156 Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;3157 Pel *pOrg, *pRec;3158 UInt edgeType;3159 Int x, y;3160 3161 // Band offset//3162 stats = ppStats[SAO_BO];3163 count = ppCount[SAO_BO];3164 pOrg = pOrgStart;3165 pRec = pRecStart;3166 for (y=0; y< height; y++)3167 {3168 for (x=0; x< width; x++)3169 {3170 classIdx = m_lumaTableBo[pRec[x]];3171 if (classIdx)3172 {3173 stats[classIdx] += (pOrg[x]  pRec[x]);3174 count[classIdx] ++;3175 }3176 }3177 pOrg += stride;3178 pRec += stride;3179 }3180 // Edge offset 0//3181 stats = ppStats[SAO_EO_0];3182 count = ppCount[SAO_EO_0];3183 pOrg = pOrgStart;3184 pRec = pRecStart;3185 3186 3187 startX = (pbBorderAvail[SGU_L]) ? 0 : 1;3188 endX = (pbBorderAvail[SGU_R]) ? width : (width 1);3189 for (y=0; y< height; y++)3190 {3191 signLeft = xSign(pRec[startX]  pRec[startX1]);3192 for (x=startX; x< endX; x++)3193 {3194 signRight = xSign(pRec[x]  pRec[x+1]);3195 edgeType = signRight + signLeft + 2;3196 signLeft = signRight;3197 3198 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3199 count[m_auiEoTable[edgeType]] ++;3200 }3201 pRec += stride;3202 pOrg += stride;3203 }3204 3205 // Edge offset 1//3206 stats = ppStats[SAO_EO_1];3207 count = ppCount[SAO_EO_1];3208 pOrg = pOrgStart;3209 pRec = pRecStart;3210 3211 startY = (pbBorderAvail[SGU_T]) ? 0 : 1;3212 endY = (pbBorderAvail[SGU_B]) ? height : height1;3213 if (!pbBorderAvail[SGU_T])3214 {3215 pRec += stride;3216 pOrg += stride;3217 }3218 3219 for (x=0; x< width; x++)3220 {3221 m_iUpBuff1[x] = xSign(pRec[x]  pRec[xstride]);3222 }3223 for (y=startY; y<endY; y++)3224 {3225 for (x=0; x< width; x++)3226 {3227 signDown = xSign(pRec[x]  pRec[x+stride]);3228 edgeType = signDown + m_iUpBuff1[x] + 2;3229 m_iUpBuff1[x] = signDown;3230 3231 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3232 count[m_auiEoTable[edgeType]] ++;3233 }3234 pOrg += stride;3235 pRec += stride;3236 }3237 // Edge offset 2//3238 stats = ppStats[SAO_EO_2];3239 count = ppCount[SAO_EO_2];3240 pOrg = pOrgStart;3241 pRec = pRecStart;3242 3243 posShift= stride + 1;3244 3245 startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;3246 endX = (pbBorderAvail[SGU_R]) ? width : (width1);3247 3248 //prepare 2nd line upper sign3249 pRec += stride;3250 for (x=startX; x< endX+1; x++)3251 {3252 m_iUpBuff1[x] = xSign(pRec[x]  pRec[x posShift]);3253 }3254 3255 //1st line3256 pRec = stride;3257 if(pbBorderAvail[SGU_TL])3258 {3259 x= 0;3260 edgeType = xSign(pRec[x]  pRec[x posShift])  m_iUpBuff1[x+1] + 2;3261 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3262 count[m_auiEoTable[edgeType]] ++;3263 }3264 if(pbBorderAvail[SGU_T])3265 {3266 for(x= 1; x< endX; x++)3267 {3268 edgeType = xSign(pRec[x]  pRec[x posShift])  m_iUpBuff1[x+1] + 2;3269 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3270 count[m_auiEoTable[edgeType]] ++;3271 }3272 }3273 pRec += stride;3274 pOrg += stride;3275 3276 //middle lines3277 for (y= 1; y< height1; y++)3278 {3279 for (x=startX; x<endX; x++)3280 {3281 signDown1 = xSign(pRec[x]  pRec[x+ posShift]) ;3282 edgeType = signDown1 + m_iUpBuff1[x] + 2;3283 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3284 count[m_auiEoTable[edgeType]] ++;3285 3286 m_iUpBufft[x+1] = signDown1;3287 }3288 m_iUpBufft[startX] = xSign(pRec[stride+startX]  pRec[startX1]);3289 3290 ipSwap = m_iUpBuff1;3291 m_iUpBuff1 = m_iUpBufft;3292 m_iUpBufft = ipSwap;3293 3294 pRec += stride;3295 pOrg += stride;3296 }3297 3298 //last line3299 if(pbBorderAvail[SGU_B])3300 {3301 for(x= startX; x< width1; x++)3302 {3303 edgeType = xSign(pRec[x]  pRec[x+ posShift]) + m_iUpBuff1[x] + 2;3304 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3305 count[m_auiEoTable[edgeType]] ++;3306 }3307 }3308 if(pbBorderAvail[SGU_BR])3309 {3310 x= width 1;3311 edgeType = xSign(pRec[x]  pRec[x+ posShift]) + m_iUpBuff1[x] + 2;3312 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3313 count[m_auiEoTable[edgeType]] ++;3314 }3315 3316 // Edge offset 3//3317 3318 stats = ppStats[SAO_EO_3];3319 count = ppCount[SAO_EO_3];3320 pOrg = pOrgStart;3321 pRec = pRecStart;3322 3323 posShift = stride  1;3324 startX = (pbBorderAvail[SGU_L]) ? 0 : 1;3325 endX = (pbBorderAvail[SGU_R]) ? width : (width 1);3326 3327 //prepare 2nd line upper sign3328 pRec += stride;3329 for (x=startX1; x< endX; x++)3330 {3331 m_iUpBuff1[x] = xSign(pRec[x]  pRec[x posShift]);3332 }3333 3334 3335 //first line3336 pRec = stride;3337 if(pbBorderAvail[SGU_T])3338 {3339 for(x= startX; x< width 1; x++)3340 {3341 edgeType = xSign(pRec[x]  pRec[x posShift]) m_iUpBuff1[x1] + 2;3342 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3343 count[m_auiEoTable[edgeType]] ++;3344 }3345 }3346 if(pbBorderAvail[SGU_TR])3347 {3348 x= width1;3349 edgeType = xSign(pRec[x]  pRec[x posShift]) m_iUpBuff1[x1] + 2;3350 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3351 count[m_auiEoTable[edgeType]] ++;3352 }3353 pRec += stride;3354 pOrg += stride;3355 3356 //middle lines3357 for (y= 1; y< height1; y++)3358 {3359 for(x= startX; x< endX; x++)3360 {3361 signDown1 = xSign(pRec[x]  pRec[x+ posShift]) ;3362 edgeType = signDown1 + m_iUpBuff1[x] + 2;3363 3364 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3365 count[m_auiEoTable[edgeType]] ++;3366 m_iUpBuff1[x1] = signDown1;3367 3368 }3369 m_iUpBuff1[endX1] = xSign(pRec[endX1 + stride]  pRec[endX]);3370 3371 pRec += stride;3372 pOrg += stride;3373 }3374 3375 //last line3376 if(pbBorderAvail[SGU_BL])3377 {3378 x= 0;3379 edgeType = xSign(pRec[x]  pRec[x+ posShift]) + m_iUpBuff1[x] + 2;3380 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3381 count[m_auiEoTable[edgeType]] ++;3382 3383 }3384 if(pbBorderAvail[SGU_B])3385 {3386 for(x= 1; x< endX; x++)3387 {3388 edgeType = xSign(pRec[x]  pRec[x+ posShift]) + m_iUpBuff1[x] + 2;3389 stats[m_auiEoTable[edgeType]] += (pOrg[x]  pRec[x]);3390 count[m_auiEoTable[edgeType]] ++;3391 }3392 }3393 }3394 3395 /** Calculate SAO statistics for current LCU3396 * \param iAddr, iPartIdx, iYCbCr3397 */3398 Void TEncSampleAdaptiveOffset::calcSaoStatsCu(Int iAddr, Int iPartIdx, Int iYCbCr)3399 {3400 if(!m_bUseNIF)3401 {3402 calcSaoStatsCuOrg( iAddr, iPartIdx, iYCbCr);3403 }3404 else3405 {3406 Int64** ppStats = m_iOffsetOrg[iPartIdx];3407 Int64** ppCount = m_iCount [iPartIdx];3408 3409 //parameters3410 Int isChroma = (iYCbCr != 0)? 1:0;3411 Int stride = (iYCbCr != 0)?(m_pcPic>getCStride()):(m_pcPic>getStride());3412 Pel* pPicOrg = getPicYuvAddr (m_pcPic>getPicYuvOrg(), iYCbCr);3413 Pel* pPicRec = getPicYuvAddr(m_pcYuvTmp, iYCbCr);3414 3415 std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic>getCU(iAddr)>getNDBFilterBlocks());3416 3417 //variables3418 UInt xPos, yPos, width, height;3419 Bool* pbBorderAvail;3420 UInt posOffset;3421 3422 for(Int i=0; i< vFilterBlocks.size(); i++)3423 {3424 xPos = vFilterBlocks[i].posX >> isChroma;3425 yPos = vFilterBlocks[i].posY >> isChroma;3426 width = vFilterBlocks[i].width >> isChroma;3427 height = vFilterBlocks[i].height >> isChroma;3428 pbBorderAvail = vFilterBlocks[i].isBorderAvailable;3429 3430 posOffset = (yPos* stride) + xPos;3431 3432 #if HHI_INTERVIEW_SKIP3433 if( !m_pcPic>getCU(iAddr)>getRenderable(0 ))3434 {3435 calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);3436 }3437 #else3438 calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);3439 #endif3440 }3441 }3442 3443 }3444 3445 /** Calculate SAO statistics for current LCU without noncrossing slice3446 * \param iAddr, iPartIdx, iYCbCr3447 */3448 Void TEncSampleAdaptiveOffset::calcSaoStatsCuOrg(Int iAddr, Int iPartIdx, Int iYCbCr)3449 {3450 Int x,y;3451 TComDataCU *pTmpCu = m_pcPic>getCU(iAddr);3452 TComSPS *pTmpSPS = m_pcPic>getSlice(0)>getSPS();3453 3454 Pel* pOrg;3455 Pel* pRec;3456 Int iStride;3457 Int iLcuWidth = pTmpSPS>getMaxCUHeight();3458 Int iLcuHeight = pTmpSPS>getMaxCUWidth();3459 UInt uiLPelX = pTmpCu>getCUPelX();3460 UInt uiTPelY = pTmpCu>getCUPelY();3461 UInt uiRPelX;3462 UInt uiBPelY;3463 Int64* iStats;3464 Int64* iCount;3465 Int iClassIdx;3466 Int iPicWidthTmp;3467 Int iPicHeightTmp;3468 Int iStartX;3469 Int iStartY;3470 Int iEndX;3471 Int iEndY;3472 3473 Int iIsChroma = (iYCbCr!=0)? 1:0;3474 Int numSkipLine = iIsChroma? 2:4;3475 if (m_saoInterleavingFlag == 0)3476 {3477 numSkipLine = 0;3478 }3479 3480 iPicWidthTmp = m_iPicWidth >> iIsChroma;3481 iPicHeightTmp = m_iPicHeight >> iIsChroma;3482 iLcuWidth = iLcuWidth >> iIsChroma;3483 iLcuHeight = iLcuHeight >> iIsChroma;3484 uiLPelX = uiLPelX >> iIsChroma;3485 uiTPelY = uiTPelY >> iIsChroma;3486 uiRPelX = uiLPelX + iLcuWidth ;3487 uiBPelY = uiTPelY + iLcuHeight ;3488 uiRPelX = uiRPelX > iPicWidthTmp ? iPicWidthTmp : uiRPelX;3489 uiBPelY = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;3490 iLcuWidth = uiRPelX  uiLPelX;3491 iLcuHeight = uiBPelY  uiTPelY;3492 3493 iStride = (iYCbCr == 0)? m_pcPic>getStride(): m_pcPic>getCStride();3494 3495 //if(iSaoType == BO_0  iSaoType == BO_1)3496 #if HHI_INTERVIEW_SKIP3497 if( !m_pcPic>getCU(iAddr)>getRenderable(0) )3498 #endif3499 {3500 iStats = m_iOffsetOrg[iPartIdx][SAO_BO];3501 iCount = m_iCount [iPartIdx][SAO_BO];3502 3503 pOrg = getPicYuvAddr(m_pcPic>getPicYuvOrg(), iYCbCr, iAddr);3504 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr);3505 3506 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeightnumSkipLine;3507 for (y=0; y<iEndY; y++)3508 {3509 for (x=0; x<iLcuWidth; x++)3510 {3511 iClassIdx = m_lumaTableBo[pRec[x]];3512 if (iClassIdx)3513 {3514 iStats[iClassIdx] += (pOrg[x]  pRec[x]);3515 iCount[iClassIdx] ++;3516 }3517 }3518 pOrg += iStride;3519 pRec += iStride;3520 }3521 3522 }3523 Int iSignLeft;3524 Int iSignRight;3525 Int iSignDown;3526 Int iSignDown1;3527 Int iSignDown2;3528 3529 UInt uiEdgeType;3530 3531 //if (iSaoType == EO_0  iSaoType == EO_1  iSaoType == EO_2  iSaoType == EO_3)3532 #if HHI_INTERVIEW_SKIP3533 if( !m_pcPic>getCU(iAddr)>getRenderable(0) )3534 #endif3535 {3536 //if (iSaoType == EO_0)3537 {3538 iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];3539 iCount = m_iCount [iPartIdx][SAO_EO_0];3540 3541 pOrg = getPicYuvAddr(m_pcPic>getPicYuvOrg(), iYCbCr, iAddr);3542 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr);3543 3544 iStartX = (uiLPelX == 0) ? 1 : 0;3545 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;3546 for (y=0; y<iLcuHeightnumSkipLine; y++)3547 {3548 iSignLeft = xSign(pRec[iStartX]  pRec[iStartX1]);3549 for (x=iStartX; x< iEndX; x++)3550 {3551 iSignRight = xSign(pRec[x]  pRec[x+1]);3552 uiEdgeType = iSignRight + iSignLeft + 2;3553 iSignLeft = iSignRight;3554 3555 iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x]  pRec[x]);3556 iCount[m_auiEoTable[uiEdgeType]] ++;3557 }3558 pOrg += iStride;3559 pRec += iStride;3560 }3561 }3562 3563 //if (iSaoType == EO_1)3564 {3565 iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];3566 iCount = m_iCount [iPartIdx][SAO_EO_1];3567 3568 pOrg = getPicYuvAddr(m_pcPic>getPicYuvOrg(), iYCbCr, iAddr);3569 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr);3570 3571 iStartY = (uiTPelY == 0) ? 1 : 0;3572 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight1 : iLcuHeightnumSkipLine;3573 if (uiTPelY == 0)3574 {3575 pOrg += iStride;3576 pRec += iStride;3577 }3578 3579 for (x=0; x< iLcuWidth; x++)3580 {3581 m_iUpBuff1[x] = xSign(pRec[x]  pRec[xiStride]);3582 }3583 for (y=iStartY; y<iEndY; y++)3584 {3585 for (x=0; x<iLcuWidth; x++)3586 {3587 iSignDown = xSign(pRec[x]  pRec[x+iStride]);3588 uiEdgeType = iSignDown + m_iUpBuff1[x] + 2;3589 m_iUpBuff1[x] = iSignDown;3590 3591 iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x]  pRec[x]);3592 iCount[m_auiEoTable[uiEdgeType]] ++;3593 }3594 pOrg += iStride;3595 pRec += iStride;3596 }3597 }3598 //if (iSaoType == EO_2)3599 {3600 iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];3601 iCount = m_iCount [iPartIdx][SAO_EO_2];3602 3603 pOrg = getPicYuvAddr(m_pcPic>getPicYuvOrg(), iYCbCr, iAddr);3604 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr);3605 3606 iStartX = (uiLPelX == 0) ? 1 : 0;3607 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;3608 3609 iStartY = (uiTPelY == 0) ? 1 : 0;3610 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight1 : iLcuHeightnumSkipLine;3611 if (uiTPelY == 0)3612 {3613 pOrg += iStride;3614 pRec += iStride;3615 }3616 3617 for (x=iStartX; x<iEndX; x++)3618 {3619 m_iUpBuff1[x] = xSign(pRec[x]  pRec[xiStride1]);3620 }3621 for (y=iStartY; y<iEndY; y++)3622 {3623 iSignDown2 = xSign(pRec[iStride+iStartX]  pRec[iStartX1]);3624 for (x=iStartX; x<iEndX; x++)3625 {3626 iSignDown1 = xSign(pRec[x]  pRec[x+iStride+1]) ;3627 uiEdgeType = iSignDown1 + m_iUpBuff1[x] + 2;3628 m_iUpBufft[x+1] = iSignDown1;3629 iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x]  pRec[x]);3630 iCount[m_auiEoTable[uiEdgeType]] ++;3631 }3632 m_iUpBufft[iStartX] = iSignDown2;3633 ipSwap = m_iUpBuff1;3634 m_iUpBuff1 = m_iUpBufft;3635 m_iUpBufft = ipSwap;3636 3637 pRec += iStride;3638 pOrg += iStride;3639 }3640 }3641 //if (iSaoType == EO_3 )3642 {3643 iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];3644 iCount = m_iCount [iPartIdx][SAO_EO_3];3645 3646 pOrg = getPicYuvAddr(m_pcPic>getPicYuvOrg(), iYCbCr, iAddr);3647 pRec = getPicYuvAddr(m_pcPic>getPicYuvRec(), iYCbCr, iAddr);3648 3649 iStartX = (uiLPelX == 0) ? 1 : 0;3650 iEndX = (uiRPelX == iPicWidthTmp) ? iLcuWidth1 : iLcuWidth;3651 3652 iStartY = (uiTPelY == 0) ? 1 : 0;3653 iEndY = (uiBPelY == iPicHeightTmp) ? iLcuHeight1 : iLcuHeightnumSkipLine;3654 if (iStartY == 1)3655 {3656 pOrg += iStride;3657 pRec += iStride;3658 }3659 3660 for (x=iStartX1; x<iEndX; x++)3661 {3662 m_iUpBuff1[x] = xSign(pRec[x]  pRec[xiStride+1]);3663 }3664 3665 for (y=iStartY; y<iEndY; y++)3666 {3667 for (x=iStartX; x<iEndX; x++)3668 {3669 iSignDown1 = xSign(pRec[x]  pRec[x+iStride1]) ;3670 uiEdgeType = iSignDown1 + m_iUpBuff1[x] + 2;3671 m_iUpBuff1[x1] = iSignDown1;3672 iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x]  pRec[x]);3673 iCount[m_auiEoTable[uiEdgeType]] ++;3674 }3675 m_iUpBuff1[iEndX1] = xSign(pRec[iEndX1 + iStride]  pRec[iEndX]);3676 3677 pRec += iStride;3678 pOrg += iStride;3679 }3680 }3681 }3682 }3683 3684 /** get SAO statistics3685 * \param *psQTPart, iYCbCr3686 */3687 Void TEncSampleAdaptiveOffset::getSaoStats(SAOQTPart *psQTPart, Int iYCbCr)3688 {3689 Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;3690 Int i;3691 Int iNumTotalType = MAX_NUM_SAO_TYPE;3692 Int LcuIdxX;3693 Int LcuIdxY;3694 Int iAddr;3695 Int iFrameWidthInCU = m_pcPic>getFrameWidthInCU();3696 Int iDownPartIdx;3697 Int iPartStart;3698 Int iPartEnd;3699 SAOQTPart* pOnePart;3700 3701 if (m_uiMaxSplitLevel == 0)3702 {3703 iPartIdx = 0;3704 pOnePart = &(psQTPart[iPartIdx]);3705 for (LcuIdxY = pOnePart>StartCUY; LcuIdxY<= pOnePart>EndCUY; LcuIdxY++)3706 {3707 for (LcuIdxX = pOnePart>StartCUX; LcuIdxX<= pOnePart>EndCUX; LcuIdxX++)3708 {3709 iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;3710 calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);3711 }3712 }3713 }3714 else3715 {3716 for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)3717 {3718 pOnePart = &(psQTPart[iPartIdx]);3719 for (LcuIdxY = pOnePart>StartCUY; LcuIdxY<= pOnePart>EndCUY; LcuIdxY++)3720 {3721 for (LcuIdxX = pOnePart>StartCUX; LcuIdxX<= pOnePart>EndCUX; LcuIdxX++)3722 {3723 iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;3724 calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);3725 }3726 }3727 }3728 for (iLevelIdx = m_uiMaxSplitLevel1; iLevelIdx>=0; iLevelIdx )3729 {3730 iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx1] : 0;3731 iPartEnd = m_aiNumCulPartsLevel[iLevelIdx];3732 3733 for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)3734 {3735 pOnePart = &(psQTPart[iPartIdx]);3736 for (i=0; i< NUM_DOWN_PART; i++)3737 {3738 iDownPartIdx = pOnePart>DownPartsIdx[i];3739 for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)3740 {3741 for (iClassIdx=0; iClassIdx< (iTypeIdx < SAO_BO ? m_iNumClass[iTypeIdx] : SAO_MAX_BO_CLASSES) +1; iClassIdx++)3742 {3743 m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];3744 m_iCount [iPartIdx][iTypeIdx][iClassIdx] += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];3745 }3746 }3747 }3748 }3749 }3750 }3751 }3752 3753 /** reset offset statistics3754 * \param3755 */3756 Void TEncSampleAdaptiveOffset::resetStats()3757 {3758 for (Int i=0;i<m_iNumTotalParts;i++)3759 {3760 m_dCostPartBest[i] = MAX_DOUBLE;3761 m_iTypePartBest[i] = 1;3762 m_iDistOrg[i] = 0;3763 for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)3764 {3765 m_iDist[i][j] = 0;3766 m_iRate[i][j] = 0;3767 m_dCost[i][j] = 0;3768 for (Int k=0;k<MAX_NUM_SAO_CLASS;k++)3769 {3770 m_iCount [i][j][k] = 0;3771 m_iOffset[i][j][k] = 0;3772 m_iOffsetOrg[i][j][k] = 0;3773 }3774 }3775 }3776 }3777 3778 #if SAO_CHROMA_LAMBDA3779 /** Sample adaptive offset process3780 * \param pcSaoParam3781 * \param dLambdaLuma3782 * \param dLambdaChroma3783 */3784 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)3785 #else3786 /** Sample adaptive offset process3787 * \param dLambda3788 */3789 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)3790 #endif3791 {3792 3793 m_eSliceType = m_pcPic>getSlice(0)>getSliceType();3794 m_iPicNalReferenceIdc = (m_pcPic>getSlice(0)>isReferenced() ? 1 :0);3795 3796 #if SAO_CHROMA_LAMBDA3797 m_dLambdaLuma = dLambdaLuma;3798 m_dLambdaChroma = dLambdaChroma;3799 #else3800 m_dLambdaLuma = dLambda;3801 m_dLambdaChroma = dLambda;3802 #endif3803 3804 if(m_bUseNIF)3805 {3806 m_pcPic>getPicYuvRec()>copyToPic(m_pcYuvTmp);3807 }3808 3809 #if FULL_NBIT3810 m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth8)  min((Int)(g_uiBitDepth + (g_uiBitDepth8)), 10);3811 #else3812 m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement  min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);3813 #endif3814 3815 const Int iOffsetBitRange8Bit = 4;3816 Int iOffsetBitDepth = g_uiBitDepth + g_uiBitIncrement  m_uiSaoBitIncrease;3817 Int iOffsetBitRange = iOffsetBitRange8Bit + (iOffsetBitDepth  8);3818 m_iOffsetTh = 1 << (iOffsetBitRange  1);3819 resetSAOParam(pcSaoParam);3820 resetStats();3821 3822 Int iY = 0;3823 Double dCostFinal = 0;3824 3825 3826 if ( m_saoInterleavingFlag)3827 {3828 rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);3829 1703 } 3830 1704 else … … 3832 1706 pcSaoParam>bSaoFlag[0] = 1; 3833 1707 pcSaoParam>bSaoFlag[1] = 0; 3834 pcSaoParam>bSaoFlag[2] = 0; 3835 for (Int compIdx=0;compIdx<3;compIdx++) 3836 { 3837 if (pcSaoParam>bSaoFlag[iY]) 3838 { 3839 dCostFinal = 0; 3840 Double lambdaRdo = (compIdx==0 ? dLambdaLuma: dLambdaChroma); 3841 resetStats(); 3842 getSaoStats(pcSaoParam>psSaoPart[compIdx], compIdx); 3843 runQuadTreeDecision(pcSaoParam>psSaoPart[compIdx], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo); 3844 pcSaoParam>bSaoFlag[compIdx] = dCostFinal < 0 ? 1:0; 3845 if(pcSaoParam>bSaoFlag[compIdx]) 3846 { 3847 convertQT2SaoUnit(pcSaoParam, 0, compIdx); 3848 assignSaoUnitSyntax(pcSaoParam>saoLcuParam[compIdx], pcSaoParam>psSaoPart[compIdx], pcSaoParam>oneUnitFlag[compIdx], compIdx); 3849 } 3850 } 3851 } 3852 } 3853 for (Int compIdx=0;compIdx<3;compIdx++) 3854 { 3855 if (pcSaoParam>bSaoFlag[compIdx]) 3856 { 3857 processSaoUnitAll( pcSaoParam>saoLcuParam[compIdx], pcSaoParam>oneUnitFlag[compIdx], compIdx); 3858 } 1708 dCostFinal = 0; 1709 Double lambdaRdo = dLambdaLuma; 1710 resetStats(); 1711 getSaoStats(pcSaoParam>psSaoPart[0], 0); 1712 runQuadTreeDecision(pcSaoParam>psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0); 1713 pcSaoParam>bSaoFlag[0] = dCostFinal < 0 ? 1:0; 1714 if(pcSaoParam>bSaoFlag[0]) 1715 { 1716 convertQT2SaoUnit(pcSaoParam, 0, 0); 1717 assignSaoUnitSyntax(pcSaoParam>saoLcuParam[0], pcSaoParam>psSaoPart[0], pcSaoParam>oneUnitFlag[0], 0); 1718 } 1719 } 1720 if (pcSaoParam>bSaoFlag[0]) 1721 { 1722 processSaoUnitAll( pcSaoParam>saoLcuParam[0], pcSaoParam>oneUnitFlag[0], 0); 1723 } 1724 if (pcSaoParam>bSaoFlag[1]) 1725 { 1726 processSaoUnitAll( pcSaoParam>saoLcuParam[1], pcSaoParam>oneUnitFlag[1], 1); 1727 processSaoUnitAll( pcSaoParam>saoLcuParam[2], pcSaoParam>oneUnitFlag[2], 2); 3859 1728 } 3860 1729 } … … 3878 1747 countDiff += (saoUnitCurr>offset[i] != saoUnitCheck>offset[i]); 3879 1748 } 3880 countDiff += (saoUnitCurr> bandPosition != saoUnitCheck>bandPosition);1749 countDiff += (saoUnitCurr>subTypeIdx != saoUnitCheck>subTypeIdx); 3881 1750 if (countDiff ==0) 3882 1751 { … … 3929 1798 { 3930 1799 Int i,j, addr, addrUp, addrLeft, idx, idxUp, idxLeft, idxCount; 3931 Int run;3932 Int runPartBeginAddr=0;3933 Int runPart;3934 Int runPartPrevious;3935 1800 3936 1801 oneUnitFlag = 0; … … 3942 1807 for (j=0;j<m_iNumCuInHeight;j++) 3943 1808 { 3944 run = 0;3945 runPartPrevious = 1;3946 1809 for (i=0;i<m_iNumCuInWidth;i++) 3947 1810 { … … 3979 1842 checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0); 3980 1843 } 3981 runPart = saoLcuParam[addr].partIdx;3982 if (runPart == runPartPrevious)3983 {3984 run ++;3985 saoLcuParam[addr].run = 1;3986 saoLcuParam[runPartBeginAddr].run = run;3987 }3988 else3989 {3990 runPartBeginAddr = addr;3991 run = 0;3992 saoLcuParam[addr].run = run;3993 }3994 runPartPrevious = runPart;3995 }3996 }3997 3998 for (j=0;j<m_iNumCuInHeight;j++)3999 {4000 for (i=0;i<m_iNumCuInWidth;i++)4001 {4002 addr = i + j*m_iNumCuInWidth;4003 addrLeft = (addr%m_iNumCuInWidth == 0) ? 1 : addr  1;4004 addrUp = (addr<m_iNumCuInWidth) ? 1 : addr  m_iNumCuInWidth;4005 4006 if (saoLcuParam[addr].run == 1)4007 {4008 if (addrLeft != 1)4009 {4010 saoLcuParam[addr].run = saoLcuParam[addrLeft].run1;4011 }4012 }4013 if (addrUp>=0)4014 {4015 saoLcuParam[addr].runDiff = saoLcuParam[addr].run  saoLcuParam[addrUp].run;4016 }4017 else4018 {4019 saoLcuParam[addr].runDiff = saoLcuParam[addr].run ;4020 }4021 1844 } 4022 1845 } … … 4028 1851 * \param lambdaChroma 4029 1852 */ 1853 #if SAO_ENCODING_CHOICE 1854 Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth) 1855 #else 4030 1856 Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma) 1857 #endif 4031 1858 { 4032 1859 … … 4040 1867 Int addrLeft = 1; 4041 1868 Int compIdx = 0; 4042 Double lambdaComp; 1869 SaoLcuParam mergeSaoParam[3][2]; 1870 Double compDistortion[3]; 4043 1871 4044 1872 saoParam>bSaoFlag[0] = true; 4045 1873 saoParam>bSaoFlag[1] = true; 4046 saoParam>bSaoFlag[2] = true;4047 1874 saoParam>oneUnitFlag[0] = false; 4048 1875 saoParam>oneUnitFlag[1] = false; 4049 1876 saoParam>oneUnitFlag[2] = false; 4050 1877 1878 #if SAO_ENCODING_CHOICE 1879 #if SAO_ENCODING_CHOICE_CHROMA 1880 Int numNoSao[2]; 1881 numNoSao[0] = 0;// Luma 1882 numNoSao[1] = 0;// Chroma 1883 if( depth > 0 && m_depthSaoRate[0][depth1] > SAO_ENCODING_RATE ) 1884 { 1885 saoParam>bSaoFlag[0] = false; 1886 } 1887 if( depth > 0 && m_depthSaoRate[1][depth1] > SAO_ENCODING_RATE_CHROMA ) 1888 { 1889 saoParam>bSaoFlag[1] = false; 1890 } 1891 #else 1892 Int numNoSao = 0; 1893 1894 if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE ) 1895 { 1896 saoParam>bSaoFlag[0] = false; 1897 saoParam>bSaoFlag[1] = false; 1898 } 1899 #endif 1900 #endif 4051 1901 4052 1902 for (idxY = 0; idxY< frameHeightInCU; idxY++) … … 4057 1907 addrUp = addr < frameWidthInCU ? 1:idxX + frameWidthInCU*(idxY1); 4058 1908 addrLeft = idxX == 0 ? 1:idxX1 + frameWidthInCU*idxY; 1909 Int allowMergeLeft = 1; 1910 Int allowMergeUp = 1; 1911 UInt rate; 1912 Double bestCost, mergeCost; 1913 if (idxX!=0) 1914 { 1915 // check tile id and slice id 1916 if ( (m_pcPic>getPicSym()>getTileIdxMap(addr1) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addr1)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 1917 { 1918 allowMergeLeft = 0; 1919 } 1920 } 1921 else 1922 { 1923 allowMergeLeft = 0; 1924 } 1925 if (idxY!=0) 1926 { 1927 if ( (m_pcPic>getPicSym()>getTileIdxMap(addrm_iNumCuInWidth) != m_pcPic>getPicSym()>getTileIdxMap(addr))  (m_pcPic>getCU(addrm_iNumCuInWidth)>getSlice()>getSliceIdx() != m_pcPic>getCU(addr)>getSlice()>getSliceIdx())) 1928 { 1929 allowMergeUp = 0; 1930 } 1931 } 1932 else 1933 { 1934 allowMergeUp = 0; 1935 } 1936 1937 compDistortion[0] = 0; 1938 compDistortion[1] = 0; 1939 compDistortion[2] = 0; 1940 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]); 1941 if (allowMergeLeft) 1942 { 1943 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0); 1944 } 1945 if (allowMergeUp) 1946 { 1947 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0); 1948 } 1949 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] ); 4059 1950 // reset stats Y, Cb, Cr 4060 1951 for ( compIdx=0;compIdx<3;compIdx++) … … 4064 1955 for ( k=0;k< MAX_NUM_SAO_CLASS;k++) 4065 1956 { 4066 m_iCount [compIdx][j][k] = 0;4067 1957 m_iOffset [compIdx][j][k] = 0; 4068 m_iOffsetOrg[compIdx][j][k] = 0; 1958 if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){ 1959 m_iCount [compIdx][j][k] = m_count_PreDblk [addr][compIdx][j][k]; 1960 m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k]; 1961 } 1962 else 1963 { 1964 m_iCount [compIdx][j][k] = 0; 1965 m_iOffsetOrg[compIdx][j][k] = 0; 1966 } 4069 1967 } 4070 1968 } 4071 1969 saoParam>saoLcuParam[compIdx][addr].typeIdx = 1; 4072 1970 saoParam>saoLcuParam[compIdx][addr].mergeUpFlag = 0; 4073 saoParam>saoLcuParam[compIdx][addr].run = 0;4074 saoParam>saoLcuParam[compIdx][addr].runDiff = 0;4075 1971 saoParam>saoLcuParam[compIdx][addr].mergeLeftFlag = 0; 4076 saoParam>saoLcuParam[compIdx][addr].bandPosition = 0; 4077 lambdaComp = compIdx==0 ? lambda : lambdaChroma; 4078 calcSaoStatsCu(addr, compIdx, compIdx); 4079 rdoSaoUnit (saoParam, addr, addrUp, addrLeft, compIdx, lambdaComp); 4080 #if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_3 4081 if (compIdx!=0) 4082 { 4083 if ( saoParam>saoLcuParam[compIdx][0].typeIdx == 1 ) 1972 saoParam>saoLcuParam[compIdx][addr].subTypeIdx = 0; 1973 #if SAO_ENCODING_CHOICE 1974 if( (compIdx ==0 && saoParam>bSaoFlag[0]) (compIdx >0 && saoParam>bSaoFlag[1]) ) 1975 #endif 1976 { 1977 calcSaoStatsCu(addr, compIdx, compIdx); 1978 1979 } 1980 } 1981 saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0, lambda, &mergeSaoParam[0][0], &compDistortion[0]); 1982 sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]); 1983 if( saoParam>bSaoFlag[0]  saoParam>bSaoFlag[1] ) 1984 { 1985 // Cost of new SAO_params 1986 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]); 1987 m_pcRDGoOnSbacCoder>resetBits(); 1988 if (allowMergeLeft) 1989 { 1990 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0); 1991 } 1992 if (allowMergeUp) 1993 { 1994 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(0); 1995 } 1996 for ( compIdx=0;compIdx<3;compIdx++) 1997 { 1998 if( (compIdx ==0 && saoParam>bSaoFlag[0])  (compIdx >0 && saoParam>bSaoFlag[1])) 4084 1999 { 4085 saoParam>bSaoFlag[compIdx] = false;2000 m_pcEntropyCoder>encodeSaoOffset(&saoParam>saoLcuParam[compIdx][addr], compIdx); 4086 2001 } 4087 2002 } 2003 2004 rate = m_pcEntropyCoder>getNumberOfWrittenBits(); 2005 bestCost = compDistortion[0] + (Double)rate; 2006 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2007 2008 // Cost of Merge 2009 for(Int mergeUp=0; mergeUp<2; ++mergeUp) 2010 { 2011 if ( (allowMergeLeft && (mergeUp==0))  (allowMergeUp && (mergeUp==1)) ) 2012 { 2013 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_CURR_BEST]); 2014 m_pcRDGoOnSbacCoder>resetBits(); 2015 if (allowMergeLeft) 2016 { 2017 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(1mergeUp); 2018 } 2019 if ( allowMergeUp && (mergeUp==1) ) 2020 { 2021 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoMerge(1); 2022 } 2023 2024 rate = m_pcEntropyCoder>getNumberOfWrittenBits(); 2025 mergeCost = compDistortion[mergeUp+1] + (Double)rate; 2026 if (mergeCost < bestCost) 2027 { 2028 bestCost = mergeCost; 2029 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2030 for ( compIdx=0;compIdx<3;compIdx++) 2031 { 2032 mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1mergeUp; 2033 mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp; 2034 if( (compIdx==0 && saoParam>bSaoFlag[0])  (compIdx>0 && saoParam>bSaoFlag[1])) 2035 { 2036 copySaoUnit(&saoParam>saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] ); 2037 } 2038 } 2039 } 2040 } 2041 } 2042 #if SAO_ENCODING_CHOICE 2043 #if SAO_ENCODING_CHOICE_CHROMA 2044 if( saoParam>saoLcuParam[0][addr].typeIdx == 1) 2045 { 2046 numNoSao[0]++; 2047 } 2048 if( saoParam>saoLcuParam[1][addr].typeIdx == 1) 2049 { 2050 numNoSao[1]+=2; 2051 } 2052 #else 2053 for ( compIdx=0;compIdx<3;compIdx++) 2054 { 2055 if( depth == 0 && saoParam>saoLcuParam[compIdx][addr].typeIdx == 1) 2056 { 2057 numNoSao++; 2058 } 2059 } 4088 2060 #endif 4089 } 4090 } 4091 } 2061 #endif 2062 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2063 m_pcRDGoOnSbacCoder>store(m_pppcRDSbacCoder[0][CI_CURR_BEST]); 2064 } 2065 } 2066 } 2067 #if SAO_ENCODING_CHOICE 2068 #if SAO_ENCODING_CHOICE_CHROMA 2069 if( !saoParam>bSaoFlag[0]) 2070 { 2071 m_depthSaoRate[0][depth] = 1.0; 2072 } 2073 else 2074 { 2075 m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU); 2076 } 2077 if( !saoParam>bSaoFlag[1]) 2078 { 2079 m_depthSaoRate[1][depth] = 1.0; 2080 } 2081 else 2082 { 2083 m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2); 2084 } 2085 #else 2086 if( depth == 0) 2087 { 2088 // update SAO Rate 2089 m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3); 2090 } 2091 #endif 2092 #endif 4092 2093 4093 2094 } … … 4100 2101 * \param lambda 4101 2102 */ 4102 Void TEncSampleAdaptiveOffset::rdoSaoUnit(SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda) 2103 inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo) 2104 { 2105 Int64 estDist = 0; 2106 Int classIdx; 2107 Int bitDepth = (compIdx==0) ? g_bitDepthY : g_bitDepthC; 2108 Int saoBitIncrease = (compIdx==0) ? m_uiSaoBitIncreaseY : m_uiSaoBitIncreaseC; 2109 Int saoOffsetTh = (compIdx==0) ? m_iOffsetThY : m_iOffsetThC; 2110 2111 for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ? m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++) 2112 { 2113 if( typeIdx == SAO_BO) 2114 { 2115 currentDistortionTableBo[classIdx1] = 0; 2116 currentRdCostTableBo[classIdx1] = lambda; 2117 } 2118 if(m_iCount [compIdx][typeIdx][classIdx]) 2119 { 2120 m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi(bitDepth, (Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<(bitDepth8)) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<saoBitIncrease)); 2121 m_iOffset[compIdx][typeIdx][classIdx] = Clip3(saoOffsetTh+1, saoOffsetTh1, (Int)m_iOffset[compIdx][typeIdx][classIdx]); 2122 if (typeIdx < 4) 2123 { 2124 if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 ) 2125 { 2126 m_iOffset[compIdx][typeIdx][classIdx] = 0; 2127 } 2128 if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3) 2129 { 2130 m_iOffset[compIdx][typeIdx][classIdx] = 0; 2131 } 2132 } 2133 m_iOffset[compIdx][typeIdx][classIdx] = estIterOffset( typeIdx, classIdx, lambda, m_iOffset[compIdx][typeIdx][classIdx], m_iCount [compIdx][typeIdx][classIdx], m_iOffsetOrg[compIdx][typeIdx][classIdx], shift, saoBitIncrease, currentDistortionTableBo, currentRdCostTableBo, saoOffsetTh ); 2134 } 2135 else 2136 { 2137 m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0; 2138 m_iOffset[compIdx][typeIdx][classIdx] = 0; 2139 } 2140 if( typeIdx != SAO_BO ) 2141 { 2142 estDist += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << saoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift); 2143 } 2144 2145 } 2146 return estDist; 2147 } 2148 2149 inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift) 2150 { 2151 return (( count*offset*offsetoffsetOrg*offset*2 ) >> shift); 2152 } 2153 inline Int64 TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo, Int offsetTh ) 2154 { 2155 //Clean up, best_q_offset. 2156 Int64 iterOffset, tempOffset; 2157 Int64 tempDist, tempRate; 2158 Double tempCost, tempMinCost; 2159 Int64 offsetOutput = 0; 2160 iterOffset = offsetInput; 2161 // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here. 2162 tempMinCost = lambda; 2163 while (iterOffset != 0) 2164 { 2165 // Calculate the bits required for signalling the offset 2166 tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1); 2167 if (abs((Int)iterOffset)==offsetTh1) 2168 { 2169 tempRate ; 2170 } 2171 // Do the dequntization before distorion calculation 2172 tempOffset = iterOffset << bitIncrease; 2173 tempDist = estSaoDist( count, tempOffset, offsetOrg, shift); 2174 tempCost = ((Double)tempDist + lambda * (Double) tempRate); 2175 if(tempCost < tempMinCost) 2176 { 2177 tempMinCost = tempCost; 2178 offsetOutput = iterOffset; 2179 if(typeIdx == SAO_BO) 2180 { 2181 currentDistortionTableBo[classIdx1] = (Int) tempDist; 2182 currentRdCostTableBo[classIdx1] = tempCost; 2183 } 2184 } 2185 iterOffset = (iterOffset > 0) ? (iterOffset1):(iterOffset+1); 2186 } 2187 return offsetOutput; 2188 } 2189 2190 2191 Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion) 4103 2192 { 4104 2193 Int typeIdx; 4105 2194 4106 2195 Int64 estDist; 4107 Int64 offsetOrg;4108 Int64 offset;4109 Int64 count;4110 2196 Int classIdx; 4111 Int shift = g_uiBitIncrement << 1;4112 // Double dAreaWeight = 0;4113 Double complexityCost = 0; 4114 SaoLcuParam* saoLcuParam = NULL;2197 Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)8); 2198 Int64 bestDist; 2199 2200 SaoLcuParam* saoLcuParam = &(saoParam>saoLcuParam[yCbCr][addr]); 4115 2201 SaoLcuParam* saoLcuParamNeighbor = NULL; 4116 Int merge_iOffset [33]; 4117 Int64 merge_iDist; 4118 Int merge_iRate; 4119 Double merge_dCost; 4120 Int offsetTh = m_iOffsetTh; 4121 4122 saoLcuParam = &(saoParam>saoLcuParam[yCbCr][addr]); 4123 4124 saoLcuParam>mergeUpFlag = 0; 4125 saoLcuParam>mergeLeftFlag = 0; 4126 saoLcuParam>run = 0; 4127 saoLcuParam>runDiff= 0; 4128 4129 4130 m_iTypePartBest[yCbCr] = 1; 4131 m_dCostPartBest[yCbCr] = 0; 4132 m_iDistOrg[yCbCr] = 0; 2202 2203 resetSaoUnit(saoLcuParam); 2204 resetSaoUnit(&compSaoParam[0]); 2205 resetSaoUnit(&compSaoParam[1]); 2206 2207 2208 Double dCostPartBest = MAX_DOUBLE; 4133 2209 4134 2210 Double bestRDCostTableBo = MAX_DOUBLE; … … 4136 2212 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS]; 4137 2213 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; 4138 Int bestClassTableBoMerge = 0; 4139 4140 #if HHI_INTERVIEW_SKIP 4141 Bool bRenderable = m_pcPic>getCU(addr)>getRenderable(0) ; 4142 #endif 4143 for (typeIdx=1; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) 4144 { 4145 m_pcEntropyCoder>resetEntropy(); 4146 m_pcEntropyCoder>resetBits(); 4147 4148 if (m_saoInterleavingFlag) 4149 { 4150 #if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_1 4151 if(yCbCr>0 && typeIdx>3 ) 4152 { 4153 continue; 4154 } 4155 #endif 4156 #if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_2 4157 if (yCbCr>0 ) 4158 { 4159 offsetTh = 2<<g_uiBitIncrement; 2214 2215 2216 SaoLcuParam saoLcuParamRdo; 2217 Double estRate = 0; 2218 2219 resetSaoUnit(&saoLcuParamRdo); 2220 2221 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2222 m_pcRDGoOnSbacCoder>resetBits(); 2223 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo, yCbCr); 2224 2225 dCostPartBest = m_pcEntropyCoder>getNumberOfWrittenBits()*lambda ; 2226 copySaoUnit(saoLcuParam, &saoLcuParamRdo ); 2227 bestDist = 0; 2228 2229 2230 2231 for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) 2232 { 2233 estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); 2234 2235 if( typeIdx == SAO_BO ) 2236 { 2237 // Estimate Best Position 2238 Double currentRDCost = 0.0; 2239 2240 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++) 2241 { 2242 currentRDCost = 0.0; 2243 for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) 2244 { 2245 currentRDCost += currentRdCostTableBo[uj]; 2246 } 2247 2248 if( currentRDCost < bestRDCostTableBo) 2249 { 2250 bestRDCostTableBo = currentRDCost; 2251 bestClassTableBo = i; 2252 } 2253 } 2254 2255 // Re code all Offsets 2256 // Code Center 2257 estDist = 0; 2258 for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++) 2259 { 2260 estDist += currentDistortionTableBo[classIdx]; 2261 } 2262 } 2263 resetSaoUnit(&saoLcuParamRdo); 2264 saoLcuParamRdo.length = m_iNumClass[typeIdx]; 2265 saoLcuParamRdo.typeIdx = typeIdx; 2266 saoLcuParamRdo.mergeLeftFlag = 0; 2267 saoLcuParamRdo.mergeUpFlag = 0; 2268 saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0; 2269 for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++) 2270 { 2271 saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1]; 2272 } 2273 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2274 m_pcRDGoOnSbacCoder>resetBits(); 2275 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo, yCbCr); 2276 2277 estRate = m_pcEntropyCoder>getNumberOfWrittenBits(); 2278 m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate); 2279 2280 if(m_dCost[yCbCr][typeIdx] < dCostPartBest) 2281 { 2282 dCostPartBest = m_dCost[yCbCr][typeIdx]; 2283 copySaoUnit(saoLcuParam, &saoLcuParamRdo ); 2284 bestDist = estDist; 2285 } 2286 } 2287 compDistortion[0] += ((Double)bestDist/lambda); 2288 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2289 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam, yCbCr); 2290 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] ); 2291 2292 2293 // merge left or merge up 2294 2295 for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 2296 { 2297 saoLcuParamNeighbor = NULL; 2298 if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) 2299 { 2300 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrLeft]); 2301 } 2302 else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) 2303 { 2304 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrUp]); 2305 } 2306 if (saoLcuParamNeighbor!=NULL) 2307 { 2308 estDist = 0; 2309 typeIdx = saoLcuParamNeighbor>typeIdx; 2310 if (typeIdx>=0) 2311 { 2312 Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor>subTypeIdx:0; 2313 Int merge_iOffset; 2314 for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++) 2315 { 2316 merge_iOffset = saoLcuParamNeighbor>offset[classIdx]; 2317 estDist += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1], shift); 2318 } 4160 2319 } 4161 2320 else 4162 #endif 4163 { 4164 offsetTh = m_iOffsetTh; 4165 } 4166 } 4167 4168 estDist = 0; 4169 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoTypeIdx(typeIdx+1); 4170 if (typeIdx>=0) 4171 { 4172 4173 for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ? m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++) 4174 { 4175 if( typeIdx == SAO_BO) 4176 { 4177 currentDistortionTableBo[classIdx1] = 0; 4178 currentRdCostTableBo[classIdx1] = lambda; 4179 } 4180 #if HHI_INTERVIEW_SKIP 4181 if(m_iCount [yCbCr][typeIdx][classIdx] && !bRenderable) 4182 #else 4183 if(m_iCount [yCbCr][typeIdx][classIdx]) 4184 #endif 4185 { 4186 m_iOffset[yCbCr][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[yCbCr][typeIdx][classIdx]<<g_uiBitIncrement) / (Double)(m_iCount [yCbCr][typeIdx][classIdx]<<m_uiSaoBitIncrease)); 4187 m_iOffset[yCbCr][typeIdx][classIdx] = Clip3(offsetTh, offsetTh, (Int)m_iOffset[yCbCr][typeIdx][classIdx]); 4188 if (typeIdx < 4) 4189 { 4190 if ( m_iOffset[yCbCr][typeIdx][classIdx]<0 && classIdx<3 ) 4191 { 4192 m_iOffset[yCbCr][typeIdx][classIdx] = 0; 4193 } 4194 if ( m_iOffset[yCbCr][typeIdx][classIdx]>0 && classIdx>=3) 4195 { 4196 m_iOffset[yCbCr][typeIdx][classIdx] = 0; 4197 } 4198 } 4199 { 4200 //Clean up, best_q_offset. 4201 Int64 iIterOffset, iTempOffset; 4202 Int64 iTempDist, iTempRate; 4203 Double dTempCost, dTempMinCost; 4204 UInt uiLength, uiTemp; 4205 4206 iIterOffset = m_iOffset[yCbCr][typeIdx][classIdx]; 4207 m_iOffset[yCbCr][typeIdx][classIdx] = 0; 4208 dTempMinCost = lambda; // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here. 4209 4210 while (iIterOffset != 0) 4211 { 4212 // Calculate the bits required for signalling the offset 4213 uiLength = 1; 4214 uiTemp = (UInt)((iIterOffset <= 0) ? ( (iIterOffset<<1) + 1 ) : (iIterOffset<<1)); 4215 while( 1 != uiTemp ) 4216 { 4217 uiTemp >>= 1; 4218 uiLength += 2; 4219 } 4220 iTempRate = (uiLength >> 1) + ((uiLength+1) >> 1); 4221 4222 // Do the dequntization before distorion calculation 4223 iTempOffset = iIterOffset << m_uiSaoBitIncrease; 4224 iTempDist = (( m_iCount [yCbCr][typeIdx][classIdx]*iTempOffset*iTempOffsetm_iOffsetOrg[yCbCr][typeIdx][classIdx]*iTempOffset*2 ) >> shift); 4225 dTempCost = ((Double)iTempDist + lambda * (Double) iTempRate); 4226 if(dTempCost < dTempMinCost) 4227 { 4228 dTempMinCost = dTempCost; 4229 m_iOffset[yCbCr][typeIdx][classIdx] = iIterOffset; 4230 if(typeIdx == SAO_BO) 4231 { 4232 currentDistortionTableBo[classIdx1] = (Int) iTempDist; 4233 currentRdCostTableBo[classIdx1] = dTempCost; 4234 } 4235 } 4236 iIterOffset = (iIterOffset > 0) ? (iIterOffset1):(iIterOffset+1); 4237 } 4238 } 4239 4240 } 4241 else 4242 { 4243 m_iOffsetOrg[yCbCr][typeIdx][classIdx] = 0; 4244 m_iOffset[yCbCr][typeIdx][classIdx] = 0; 4245 } 4246 if( typeIdx != SAO_BO ) 4247 { 4248 count = m_iCount [yCbCr][typeIdx][classIdx]; 4249 offset = m_iOffset[yCbCr][typeIdx][classIdx] << m_uiSaoBitIncrease; 4250 offsetOrg = m_iOffsetOrg[yCbCr][typeIdx][classIdx]; 4251 #if HHI_INTERVIEW_SKIP 4252 if (!bRenderable) 4253 { 4254 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift); 4255 } 4256 #else 4257 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift); 4258 #endif 4259 if (typeIdx < 4) 4260 { 4261 if (classIdx<3) 4262 { 4263 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx]); 4264 } 4265 else 4266 { 4267 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx]); 4268 } 4269 } 4270 else 4271 { 4272 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoSvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx]); 4273 } 4274 } 4275 4276 } 4277 4278 if( typeIdx == SAO_BO ) 4279 { 4280 // Estimate Best Position 2321 { 2322 estDist = 0; 2323 } 2324 2325 copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor ); 2326 compSaoParam[idxNeighbor].mergeUpFlag = idxNeighbor; 2327 compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor; 2328 2329 compDistortion[idxNeighbor+1] += ((Double)estDist/lambda); 2330 } 2331 } 2332 } 2333 Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion) 2334 { 2335 Int typeIdx; 2336 2337 Int64 estDist[2]; 2338 Int classIdx; 2339 Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC8); 2340 Int64 bestDist = 0; 2341 2342 SaoLcuParam* saoLcuParam[2] = {&(saoParam>saoLcuParam[1][addr]), &(saoParam>saoLcuParam[2][addr])}; 2343 SaoLcuParam* saoLcuParamNeighbor[2] = {NULL, NULL}; 2344 SaoLcuParam* saoMergeParam[2][2]; 2345 saoMergeParam[0][0] = &crSaoParam[0]; 2346 saoMergeParam[0][1] = &crSaoParam[1]; 2347 saoMergeParam[1][0] = &cbSaoParam[0]; 2348 saoMergeParam[1][1] = &cbSaoParam[1]; 2349 2350 resetSaoUnit(saoLcuParam[0]); 2351 resetSaoUnit(saoLcuParam[1]); 2352 resetSaoUnit(saoMergeParam[0][0]); 2353 resetSaoUnit(saoMergeParam[0][1]); 2354 resetSaoUnit(saoMergeParam[1][0]); 2355 resetSaoUnit(saoMergeParam[1][1]); 2356 2357 2358 Double costPartBest = MAX_DOUBLE; 2359 2360 Double bestRDCostTableBo; 2361 Int bestClassTableBo[2] = {0, 0}; 2362 Int currentDistortionTableBo[MAX_NUM_SAO_CLASS]; 2363 Double currentRdCostTableBo[MAX_NUM_SAO_CLASS]; 2364 2365 SaoLcuParam saoLcuParamRdo[2]; 2366 Double estRate = 0; 2367 2368 resetSaoUnit(&saoLcuParamRdo[0]); 2369 resetSaoUnit(&saoLcuParamRdo[1]); 2370 2371 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2372 m_pcRDGoOnSbacCoder>resetBits(); 2373 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[0], 1); 2374 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[1], 2); 2375 2376 costPartBest = m_pcEntropyCoder>getNumberOfWrittenBits()*lambda ; 2377 copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] ); 2378 copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] ); 2379 2380 for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) 2381 { 2382 if( typeIdx == SAO_BO ) 2383 { 2384 // Estimate Best Position 2385 for(Int compIdx = 0; compIdx < 2; compIdx++) 2386 { 4281 2387 Double currentRDCost = 0.0; 4282 2388 bestRDCostTableBo = MAX_DOUBLE; 2389 estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); 4283 2390 for(Int i=0; i< SAO_MAX_BO_CLASSES SAO_BO_LEN +1; i++) 4284 2391 { … … 4292 2399 { 4293 2400 bestRDCostTableBo = currentRDCost; 4294 bestClassTableBo = i;2401 bestClassTableBo[compIdx] = i; 4295 2402 } 4296 2403 } … … 4298 2405 // Re code all Offsets 4299 2406 // Code Center 4300 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoUflc( (UInt) (bestClassTableBo) ); 4301 4302 for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++) 4303 { 4304 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoSvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx+1]); 4305 #if HHI_INTERVIEW_SKIP 4306 if (!bRenderable) 2407 estDist[compIdx] = 0; 2408 for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++) 2409 { 2410 estDist[compIdx] += currentDistortionTableBo[classIdx]; 2411 } 2412 } 2413 } 2414 else 2415 { 2416 estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); 2417 estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo); 2418 } 2419 2420 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2421 m_pcRDGoOnSbacCoder>resetBits(); 2422 2423 for(Int compIdx = 0; compIdx < 2; compIdx++) 2424 { 2425 resetSaoUnit(&saoLcuParamRdo[compIdx]); 2426 saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx]; 2427 saoLcuParamRdo[compIdx].typeIdx = typeIdx; 2428 saoLcuParamRdo[compIdx].mergeLeftFlag = 0; 2429 saoLcuParamRdo[compIdx].mergeUpFlag = 0; 2430 saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0; 2431 for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++) 2432 { 2433 saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1]; 2434 } 2435 2436 m_pcEntropyCoder>encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1); 2437 } 2438 estRate = m_pcEntropyCoder>getNumberOfWrittenBits(); 2439 m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1]) + lambda * (Double) estRate); 2440 2441 if(m_dCost[1][typeIdx] < costPartBest) 2442 { 2443 costPartBest = m_dCost[1][typeIdx]; 2444 copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] ); 2445 copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] ); 2446 bestDist = (estDist[0]+estDist[1]); 2447 } 2448 } 2449 2450 distortion[0] += ((Double)bestDist/lambda); 2451 m_pcRDGoOnSbacCoder>load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]); 2452 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam[0], 1); 2453 m_pcEntropyCoder>encodeSaoOffset(saoLcuParam[1], 2); 2454 m_pcRDGoOnSbacCoder>store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] ); 2455 2456 // merge left or merge up 2457 2458 for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 2459 { 2460 for(Int compIdx = 0; compIdx < 2; compIdx++) 2461 { 2462 saoLcuParamNeighbor[compIdx] = NULL; 2463 if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) 2464 { 2465 saoLcuParamNeighbor[compIdx] = &(saoParam>saoLcuParam[compIdx+1][addrLeft]); 2466 } 2467 else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) 2468 { 2469 saoLcuParamNeighbor[compIdx] = &(saoParam>saoLcuParam[compIdx+1][addrUp]); 2470 } 2471 if (saoLcuParamNeighbor[compIdx]!=NULL) 2472 { 2473 estDist[compIdx] = 0; 2474 typeIdx = saoLcuParamNeighbor[compIdx]>typeIdx; 2475 if (typeIdx>=0) 2476 { 2477 Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]>subTypeIdx:0; 2478 Int merge_iOffset; 2479 for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++) 4307 2480 { 4308 estDist += currentDistortionTableBo[classIdx]; 2481 merge_iOffset = saoLcuParamNeighbor[compIdx]>offset[classIdx]; 2482 estDist[compIdx] += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1], shift); 4309 2483 } 4310 #else4311 estDist += currentDistortionTableBo[classIdx];4312 #endif4313 }4314 }4315 4316 m_iDist[yCbCr][typeIdx] = estDist;4317 m_iRate[yCbCr][typeIdx] = m_pcEntropyCoder>getNumberOfWrittenBits();4318 4319 m_dCost[yCbCr][typeIdx] = (Double)((Double)m_iDist[yCbCr][typeIdx] + lambda * (Double) m_iRate[yCbCr][typeIdx]);4320 4321 if(m_dCost[yCbCr][typeIdx] < m_dCostPartBest[yCbCr])4322 {4323 m_iDistOrg [yCbCr] = (Int64)complexityCost;4324 m_dCostPartBest[yCbCr] = m_dCost[yCbCr][typeIdx];4325 m_iTypePartBest[yCbCr] = typeIdx;4326 }4327 }4328 else4329 {4330 if(m_iDistOrg[yCbCr] < m_dCostPartBest[yCbCr])4331 {4332 m_dCostPartBest[yCbCr] = (Double) m_iDistOrg[yCbCr] + m_pcEntropyCoder>getNumberOfWrittenBits()*lambda ;4333 m_iTypePartBest[yCbCr] = 1;4334 }4335 }4336 }4337 4338 // merge left or merge up4339 4340 for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)4341 {4342 saoLcuParamNeighbor = NULL;4343 if (addrLeft>=0 && idxNeighbor ==0)4344 {4345 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrLeft]);4346 }4347 else if (addrUp>=0 && idxNeighbor ==1)4348 {4349 saoLcuParamNeighbor = &(saoParam>saoLcuParam[yCbCr][addrUp]);4350 }4351 if (saoLcuParamNeighbor!=NULL)4352 {4353 if (saoLcuParamNeighbor>typeIdx>=0) //new4354 {4355 m_pcEntropyCoder>resetEntropy();4356 m_pcEntropyCoder>resetBits();4357 4358 estDist = 0;4359 typeIdx = saoLcuParamNeighbor>typeIdx;4360 m_pcEntropyCoder>m_pcEntropyCoderIf>codeSaoFlag(1);4361 if (saoLcuParamNeighbor>typeIdx == SAO_BO)4362 {4363 for(classIdx = saoLcuParamNeighbor>bandPosition+1; classIdx < saoLcuParamNeighbor>bandPosition+SAO_BO_LEN+1; classIdx++)4364 {4365 merge_iOffset[classIdx] = saoLcuParamNeighbor>offset[classIdx1saoLcuParamNeighbor>bandPosition];4366 4367 count = m_iCount [yCbCr][typeIdx][classIdx];4368 offset = merge_iOffset[classIdx];4369 offsetOrg = m_iOffsetOrg[yCbCr][typeIdx][classIdx];4370 #if HHI_INTERVIEW_SKIP4371 if (!bRenderable)4372 {4373 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift);4374 }4375 #else4376 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift);4377 #endif4378 }4379 2484 } 4380 2485 else 4381 2486 { 4382 for(classIdx=1; classIdx < m_iNumClass[typeIdx]+1; classIdx++) 4383 { 4384 merge_iOffset[classIdx] = saoLcuParamNeighbor>offset[classIdx1]; 4385 4386 count = m_iCount [yCbCr][typeIdx][classIdx]; 4387 offset = merge_iOffset[classIdx]; 4388 offsetOrg = m_iOffsetOrg[yCbCr][typeIdx][classIdx]; 4389 #if HHI_INTERVIEW_SKIP 4390 if (!bRenderable) 4391 { 4392 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift); 4393 } 4394 #else 4395 estDist += (( count*offset*offsetoffsetOrg*offset*2 ) >> shift); 4396 #endif 4397 } 4398 } 4399 merge_iDist = estDist; 4400 merge_iRate = m_pcEntropyCoder>getNumberOfWrittenBits(); 4401 merge_dCost = (Double)((Double)merge_iDist + m_dLambdaLuma * (Double) merge_iRate) ; 4402 4403 if(merge_dCost < m_dCostPartBest[yCbCr]) 4404 { 4405 m_iDistOrg [yCbCr] = (Int64)complexityCost; 4406 m_dCostPartBest[yCbCr] = merge_dCost; 4407 m_iTypePartBest[yCbCr] = typeIdx; 4408 if (typeIdx == SAO_BO) 4409 { 4410 bestClassTableBoMerge = saoLcuParamNeighbor>bandPosition; 4411 for(classIdx = saoLcuParamNeighbor>bandPosition+1; classIdx < saoLcuParamNeighbor>bandPosition+SAO_BO_LEN+1; classIdx++) 4412 { 4413 m_iOffset[yCbCr][typeIdx][classIdx] = merge_iOffset[classIdx]; 4414 } 4415 } 4416 else 4417 { 4418 for(classIdx=1; classIdx < m_iNumClass[typeIdx]+1; classIdx++) 4419 { 4420 m_iOffset[yCbCr][typeIdx][classIdx] = merge_iOffset[classIdx]; 4421 } 4422 } 4423 saoLcuParam>mergeUpFlag = idxNeighbor; 4424 saoLcuParam>mergeLeftFlag = !idxNeighbor; 4425 } 4426 } 4427 } 2487 estDist[compIdx] = 0; 2488 } 2489 2490 copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] ); 2491 saoMergeParam[compIdx][idxNeighbor]>mergeUpFlag = idxNeighbor; 2492 saoMergeParam[compIdx][idxNeighbor]>mergeLeftFlag = !idxNeighbor; 2493 distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda); 2494 } 2495 } 4428 2496 } 4429 4430 saoLcuParam>typeIdx = m_iTypePartBest[yCbCr]; 4431 if (saoLcuParam>typeIdx != 1) 4432 { 4433 saoLcuParam>length = m_iNumClass[saoLcuParam>typeIdx]; 4434 Int minIndex = 0; 4435 if( saoLcuParam>typeIdx == SAO_BO ) 4436 { 4437 if ((saoLcuParam>mergeUpFlag )(saoLcuParam>mergeLeftFlag)) 4438 { 4439 saoLcuParam>bandPosition = bestClassTableBoMerge; 4440 } 4441 else 4442 { 4443 saoLcuParam>bandPosition = bestClassTableBo; 4444 } 4445 minIndex = saoLcuParam>bandPosition; 4446 } 4447 for (Int i=0; i< saoLcuParam>length ; i++) 4448 { 4449 saoLcuParam>offset[i] = (Int) m_iOffset[yCbCr][saoLcuParam>typeIdx][minIndex+i+1]; 4450 } 4451 } 4452 else 4453 { 4454 saoLcuParam>length = 0; 4455 } 4456 4457 if (addrUp>=0) 4458 { 4459 if (saoLcuParam>typeIdx == 1 && saoParam>saoLcuParam[yCbCr][addrUp].typeIdx == 1) 4460 { 4461 saoLcuParam>mergeUpFlag = 1; 4462 saoLcuParam>mergeLeftFlag = 0; 4463 } 4464 } 4465 if (addrLeft>=0) 4466 { 4467 if (saoLcuParam>typeIdx == 1 && saoParam>saoLcuParam[yCbCr][addrLeft].typeIdx == 1) 4468 { 4469 saoLcuParam>mergeUpFlag = 0; 4470 saoLcuParam>mergeLeftFlag = 1; 4471 } 4472 } 4473 4474 } 4475 #endif 4476 2497 } 4477 2498 4478 2499 //! \}
Note: See TracChangeset for help on using the changeset viewer.