Changeset 532 in SHVCSoftware for branches/SHM-4.1-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
- Timestamp:
- 2 Jan 2014, 07:21:30 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/SHM-4.1-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
r494 r532 45 45 //! \{ 46 46 47 48 #if HM_CLEANUP_SAO 49 50 /** rounding with IBDI 51 * \param x 52 */ 53 inline Double xRoundIbdi2(Int bitDepth, Double x) 54 { 55 return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8)))); 56 } 57 58 inline Double xRoundIbdi(Int bitDepth, Double x) 59 { 60 return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ; 61 } 62 63 64 TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset() 65 { 66 m_pppcRDSbacCoder = NULL; 67 m_pcRDGoOnSbacCoder = NULL; 68 m_pppcBinCoderCABAC = NULL; 69 m_statData = NULL; 70 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 71 m_preDBFstatData = NULL; 72 #endif 73 } 74 75 TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset() 76 { 77 destroyEncData(); 78 } 79 80 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 81 Void TEncSampleAdaptiveOffset::createEncData(Bool isPreDBFSamplesUsed) 82 #else 83 Void TEncSampleAdaptiveOffset::createEncData() 84 #endif 85 { 86 87 //cabac coder for RDO 88 m_pppcRDSbacCoder = new TEncSbac* [NUM_SAO_CABACSTATE_LABELS]; 89 m_pppcBinCoderCABAC = new TEncBinCABACCounter* [NUM_SAO_CABACSTATE_LABELS]; 90 91 for(Int cs=0; cs < NUM_SAO_CABACSTATE_LABELS; cs++) 92 { 93 m_pppcRDSbacCoder[cs] = new TEncSbac; 94 m_pppcBinCoderCABAC[cs] = new TEncBinCABACCounter; 95 m_pppcRDSbacCoder [cs]->init( m_pppcBinCoderCABAC [cs] ); 96 } 97 98 99 //statistics 100 m_statData = new SAOStatData**[m_numCTUsPic]; 101 for(Int i=0; i< m_numCTUsPic; i++) 102 { 103 m_statData[i] = new SAOStatData*[NUM_SAO_COMPONENTS]; 104 for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++) 105 { 106 m_statData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES]; 107 } 108 } 109 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 110 if(isPreDBFSamplesUsed) 111 { 112 m_preDBFstatData = new SAOStatData**[m_numCTUsPic]; 113 for(Int i=0; i< m_numCTUsPic; i++) 114 { 115 m_preDBFstatData[i] = new SAOStatData*[NUM_SAO_COMPONENTS]; 116 for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++) 117 { 118 m_preDBFstatData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES]; 119 } 120 } 121 122 } 123 #endif 124 125 #if SAO_ENCODING_CHOICE 126 ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate)); 127 #endif 128 129 for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++) 130 { 131 m_skipLinesR[SAO_Y ][typeIdc]= 5; 132 m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3; 133 134 m_skipLinesB[SAO_Y ][typeIdc]= 4; 135 m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2; 136 137 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 138 if(isPreDBFSamplesUsed) 139 { 140 switch(typeIdc) 141 { 142 case SAO_TYPE_EO_0: 143 { 144 m_skipLinesR[SAO_Y ][typeIdc]= 5; 145 m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3; 146 147 m_skipLinesB[SAO_Y ][typeIdc]= 3; 148 m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1; 149 } 150 break; 151 case SAO_TYPE_EO_90: 152 { 153 m_skipLinesR[SAO_Y ][typeIdc]= 4; 154 m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2; 155 156 m_skipLinesB[SAO_Y ][typeIdc]= 4; 157 m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2; 158 } 159 break; 160 case SAO_TYPE_EO_135: 161 case SAO_TYPE_EO_45: 162 { 163 m_skipLinesR[SAO_Y ][typeIdc]= 5; 164 m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3; 165 166 m_skipLinesB[SAO_Y ][typeIdc]= 4; 167 m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2; 168 } 169 break; 170 case SAO_TYPE_BO: 171 { 172 m_skipLinesR[SAO_Y ][typeIdc]= 4; 173 m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2; 174 175 m_skipLinesB[SAO_Y ][typeIdc]= 3; 176 m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1; 177 } 178 break; 179 default: 180 { 181 printf("Not a supported type"); 182 assert(0); 183 exit(-1); 184 } 185 } 186 } 187 #endif 188 } 189 190 } 191 192 Void TEncSampleAdaptiveOffset::destroyEncData() 193 { 194 if(m_pppcRDSbacCoder != NULL) 195 { 196 for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ ) 197 { 198 delete m_pppcRDSbacCoder[cs]; 199 } 200 delete[] m_pppcRDSbacCoder; m_pppcRDSbacCoder = NULL; 201 } 202 203 if(m_pppcBinCoderCABAC != NULL) 204 { 205 for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ ) 206 { 207 delete m_pppcBinCoderCABAC[cs]; 208 } 209 delete[] m_pppcBinCoderCABAC; m_pppcBinCoderCABAC = NULL; 210 } 211 212 if(m_statData != NULL) 213 { 214 for(Int i=0; i< m_numCTUsPic; i++) 215 { 216 for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++) 217 { 218 delete[] m_statData[i][compIdx]; 219 } 220 delete[] m_statData[i]; 221 } 222 delete[] m_statData; m_statData = NULL; 223 } 224 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 225 if(m_preDBFstatData != NULL) 226 { 227 for(Int i=0; i< m_numCTUsPic; i++) 228 { 229 for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++) 230 { 231 delete[] m_preDBFstatData[i][compIdx]; 232 } 233 delete[] m_preDBFstatData[i]; 234 } 235 delete[] m_preDBFstatData; m_preDBFstatData = NULL; 236 } 237 238 #endif 239 } 240 241 Void TEncSampleAdaptiveOffset::initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice) 242 { 243 m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder; 244 m_pcRDGoOnSbacCoder->setSlice(pcSlice); 245 m_pcRDGoOnSbacCoder->resetEntropy(); 246 m_pcRDGoOnSbacCoder->resetBits(); 247 248 m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[SAO_CABACSTATE_PIC_INIT]); 249 } 250 251 252 253 Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas 254 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 255 , Bool isPreDBFSamplesUsed 256 #endif 257 ) 258 { 259 TComPicYuv* orgYuv= pPic->getPicYuvOrg(); 260 TComPicYuv* resYuv= pPic->getPicYuvRec(); 261 m_labmda[SAO_Y]= lambdas[0]; m_labmda[SAO_Cb]= lambdas[1]; m_labmda[SAO_Cr]= lambdas[2]; 262 TComPicYuv* srcYuv = m_tempPicYuv; 263 resYuv->copyToPic(srcYuv); 264 srcYuv->setBorderExtension(false); 265 srcYuv->extendPicBorder(); 266 267 //collect statistics 268 getStatistics(m_statData, orgYuv, srcYuv, pPic); 269 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 270 if(isPreDBFSamplesUsed) 271 { 272 addPreDBFStatistics(m_statData); 273 } 274 #endif 275 //slice on/off 276 decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth()); 277 278 //block on/off 279 SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters 280 decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam()); 281 delete[] reconParams; 282 283 } 284 285 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 286 Void TEncSampleAdaptiveOffset::getPreDBFStatistics(TComPic* pPic) 287 { 288 getStatistics(m_preDBFstatData, pPic->getPicYuvOrg(), pPic->getPicYuvRec(), pPic, true); 289 } 290 291 Void TEncSampleAdaptiveOffset::addPreDBFStatistics(SAOStatData*** blkStats) 292 { 293 for(Int n=0; n< m_numCTUsPic; n++) 294 { 295 for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++) 296 { 297 for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++) 298 { 299 blkStats[n][compIdx][typeIdc] += m_preDBFstatData[n][compIdx][typeIdc]; 300 } 301 } 302 } 303 } 304 305 #endif 306 307 Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic 308 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 309 , Bool isCalculatePreDeblockSamples 310 #endif 311 ) 312 { 313 Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail; 314 315 for(Int ctu= 0; ctu < m_numCTUsPic; ctu++) 316 { 317 Int yPos = (ctu / m_numCTUInWidth)*m_maxCUHeight; 318 Int xPos = (ctu % m_numCTUInWidth)*m_maxCUWidth; 319 Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight; 320 Int width = (xPos + m_maxCUWidth > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth; 321 322 pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail); 323 324 //NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities. 325 //For simplicity, here only picture boundaries are considered. 326 327 isRightAvail = (xPos + m_maxCUWidth < m_picWidth ); 328 isBelowAvail = (yPos + m_maxCUHeight < m_picHeight); 329 isBelowRightAvail = (isRightAvail && isBelowAvail); 330 isBelowLeftAvail = ((xPos > 0) && (isBelowAvail)); 331 isAboveRightAvail = ((yPos > 0) && (isRightAvail)); 332 333 for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++) 334 { 335 Bool isLuma = (compIdx == SAO_Y); 336 Int formatShift= isLuma?0:1; 337 338 Int srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride(); 339 Pel* srcBlk = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift); 340 341 Int orgStride = isLuma?orgYuv->getStride():orgYuv->getCStride(); 342 Pel* orgBlk = getPicBuf(orgYuv, compIdx)+ (yPos >> formatShift)*orgStride+ (xPos >> formatShift); 343 344 getBlkStats(compIdx, blkStats[ctu][compIdx] 345 , srcBlk, orgBlk, srcStride, orgStride, (width >> formatShift), (height >> formatShift) 346 , isLeftAvail, isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail, isBelowLeftAvail, isBelowRightAvail 347 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 348 , isCalculatePreDeblockSamples 349 #endif 350 ); 351 352 } 353 } 354 } 355 356 Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer) 357 { 358 //decide sliceEnabled[compIdx] 359 for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++) 360 { 361 // reset flags & counters 362 sliceEnabled[compIdx] = true; 363 364 #if SAO_ENCODING_CHOICE 365 #if SAO_ENCODING_CHOICE_CHROMA 366 // decide slice-level on/off based on previous results 367 if( (picTempLayer > 0) 368 && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==SAO_Y) ? SAO_ENCODING_RATE : SAO_ENCODING_RATE_CHROMA)) ) 369 { 370 sliceEnabled[compIdx] = false; 371 } 372 #else 373 // decide slice-level on/off based on previous results 374 if( (picTempLayer > 0) 375 && (m_saoDisabledRate[SAO_Y][0] > SAO_ENCODING_RATE) ) 376 { 377 sliceEnabled[compIdx] = false; 378 } 379 #endif 380 #endif 381 } 382 } 383 384 Int64 TEncSampleAdaptiveOffset::getDistortion(Int ctu, Int compIdx, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData) 385 { 386 Int64 dist=0; 387 Int inputBitDepth = (compIdx == SAO_Y) ? g_bitDepthY : g_bitDepthC ; 388 Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(inputBitDepth-8); 389 390 switch(typeIdc) 391 { 392 case SAO_TYPE_EO_0: 393 case SAO_TYPE_EO_90: 394 case SAO_TYPE_EO_135: 395 case SAO_TYPE_EO_45: 396 { 397 for (Int offsetIdx=0; offsetIdx<NUM_SAO_EO_CLASSES; offsetIdx++) 398 { 399 dist += estSaoDist( statData.count[offsetIdx], invQuantOffset[offsetIdx], statData.diff[offsetIdx], shift); 400 } 401 } 402 break; 403 case SAO_TYPE_BO: 404 { 405 for (Int offsetIdx=typeAuxInfo; offsetIdx<typeAuxInfo+4; offsetIdx++) 406 { 407 Int bandIdx = offsetIdx % NUM_SAO_BO_CLASSES ; 408 dist += estSaoDist( statData.count[bandIdx], invQuantOffset[bandIdx], statData.diff[bandIdx], shift); 409 } 410 } 411 break; 412 default: 413 { 414 printf("Not a supported type"); 415 assert(0); 416 exit(-1); 417 } 418 } 419 420 return dist; 421 } 422 423 inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift) 424 { 425 return (( count*offset*offset-diffSum*offset*2 ) >> shift); 426 } 427 428 429 inline Int TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh ) 430 { 431 Int iterOffset, tempOffset; 432 Int64 tempDist, tempRate; 433 Double tempCost, tempMinCost; 434 Int offsetOutput = 0; 435 iterOffset = offsetInput; 436 // 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. 437 tempMinCost = lambda; 438 while (iterOffset != 0) 439 { 440 // Calculate the bits required for signaling the offset 441 tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1); 442 if (abs((Int)iterOffset)==offsetTh) //inclusive 443 { 444 tempRate --; 445 } 446 // Do the dequantization before distortion calculation 447 tempOffset = iterOffset << bitIncrease; 448 tempDist = estSaoDist( count, tempOffset, diffSum, shift); 449 tempCost = ((Double)tempDist + lambda * (Double) tempRate); 450 if(tempCost < tempMinCost) 451 { 452 tempMinCost = tempCost; 453 offsetOutput = iterOffset; 454 bestDist = tempDist; 455 bestCost = tempCost; 456 } 457 iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1); 458 } 459 return offsetOutput; 460 } 461 462 463 Void TEncSampleAdaptiveOffset::deriveOffsets(Int ctu, Int compIdx, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo) 464 { 465 Int bitDepth = (compIdx== SAO_Y) ? g_bitDepthY : g_bitDepthC; 466 Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8); 467 Int offsetTh = g_saoMaxOffsetQVal[compIdx]; //inclusive 468 469 ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES); 470 471 //derive initial offsets 472 Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES); 473 for(Int classIdx=0; classIdx< numClasses; classIdx++) 474 { 475 if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN) ) 476 { 477 continue; //offset will be zero 478 } 479 480 if(statData.count[classIdx] == 0) 481 { 482 continue; //offset will be zero 483 } 484 485 quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8)) 486 / 487 (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx]) 488 ); 489 quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]); 490 } 491 492 // adjust offsets 493 switch(typeIdc) 494 { 495 case SAO_TYPE_EO_0: 496 case SAO_TYPE_EO_90: 497 case SAO_TYPE_EO_135: 498 case SAO_TYPE_EO_45: 499 { 500 Int64 classDist; 501 Double classCost; 502 for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++) 503 { 504 if(classIdx==SAO_CLASS_EO_FULL_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0; 505 if(classIdx==SAO_CLASS_EO_HALF_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0; 506 if(classIdx==SAO_CLASS_EO_HALF_PEAK && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0; 507 if(classIdx==SAO_CLASS_EO_FULL_PEAK && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0; 508 509 if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero 510 { 511 quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh ); 512 } 513 } 514 515 typeAuxInfo =0; 516 } 517 break; 518 case SAO_TYPE_BO: 519 { 520 Int64 distBOClasses[NUM_SAO_BO_CLASSES]; 521 Double costBOClasses[NUM_SAO_BO_CLASSES]; 522 ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES); 523 for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++) 524 { 525 costBOClasses[classIdx]= m_labmda[compIdx]; 526 if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero 527 { 528 quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], distBOClasses[classIdx], costBOClasses[classIdx], offsetTh ); 529 } 530 } 531 532 //decide the starting band index 533 Double minCost = MAX_DOUBLE, cost; 534 for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++) 535 { 536 cost = costBOClasses[band ]; 537 cost += costBOClasses[band+1]; 538 cost += costBOClasses[band+2]; 539 cost += costBOClasses[band+3]; 540 541 if(cost < minCost) 542 { 543 minCost = cost; 544 typeAuxInfo = band; 545 } 546 } 547 //clear those unused classes 548 Int clearQuantOffset[NUM_SAO_BO_CLASSES]; 549 ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES); 550 for(Int i=0; i< 4; i++) 551 { 552 Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES; 553 clearQuantOffset[band] = quantOffsets[band]; 554 } 555 ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES); 556 } 557 break; 558 default: 559 { 560 printf("Not a supported type"); 561 assert(0); 562 exit(-1); 563 } 564 565 } 566 567 568 } 569 570 571 Void TEncSampleAdaptiveOffset::deriveModeNewRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel) 572 { 573 Double minCost, cost; 574 Int rate, minRate; 575 Int64 dist[NUM_SAO_COMPONENTS], modeDist[NUM_SAO_COMPONENTS]; 576 SAOOffset testOffset[NUM_SAO_COMPONENTS]; 577 Int compIdx; 578 Int invQuantOffset[MAX_NUM_SAO_CLASSES]; 579 580 modeDist[SAO_Y]= modeDist[SAO_Cb] = modeDist[SAO_Cr] = 0; 581 582 //pre-encode merge flags 583 modeParam[SAO_Y ].modeIdc = SAO_MODE_OFF; 584 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); 585 m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true); 586 m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); 587 588 //------ luma --------// 589 compIdx = SAO_Y; 590 //"off" case as initial cost 591 modeParam[compIdx].modeIdc = SAO_MODE_OFF; 592 m_pcRDGoOnSbacCoder->resetBits(); 593 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx]); 594 minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 595 modeDist[compIdx] = 0; 596 minCost= m_labmda[compIdx]*((Double)minRate); 597 m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); 598 if(sliceEnabled[compIdx]) 599 { 600 for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++) 601 { 602 testOffset[compIdx].modeIdc = SAO_MODE_NEW; 603 testOffset[compIdx].typeIdc = typeIdc; 604 605 //derive coded offset 606 deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo); 607 608 //inversed quantized offsets 609 invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset); 610 611 //get distortion 612 dist[compIdx] = getDistortion(ctu, compIdx, testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]); 613 614 //get rate 615 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); 616 m_pcRDGoOnSbacCoder->resetBits(); 617 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx]); 618 rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 619 cost = (Double)dist[compIdx] + m_labmda[compIdx]*((Double)rate); 620 if(cost < minCost) 621 { 622 minCost = cost; 623 minRate = rate; 624 modeDist[compIdx] = dist[compIdx]; 625 modeParam[compIdx]= testOffset[compIdx]; 626 m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); 627 } 628 } 629 } 630 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); 631 m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); 632 633 //------ chroma --------// 634 assert(m_labmda[SAO_Cb] == m_labmda[SAO_Cr]); 635 Double chromaLambda = m_labmda[SAO_Cb]; 636 //"off" case as initial cost 637 m_pcRDGoOnSbacCoder->resetBits(); 638 modeParam[SAO_Cb].modeIdc = SAO_MODE_OFF; 639 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, modeParam[SAO_Cb], sliceEnabled[SAO_Cb]); 640 modeParam[SAO_Cr].modeIdc = SAO_MODE_OFF; 641 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, modeParam[SAO_Cr], sliceEnabled[SAO_Cr]); 642 minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 643 modeDist[SAO_Cb] = modeDist[SAO_Cr]= 0; 644 minCost= chromaLambda*((Double)minRate); 645 646 //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function 647 648 for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++) 649 { 650 for(compIdx= SAO_Cb; compIdx< NUM_SAO_COMPONENTS; compIdx++) 651 { 652 if(!sliceEnabled[compIdx]) 653 { 654 testOffset[compIdx].modeIdc = SAO_MODE_OFF; 655 dist[compIdx]= 0; 656 continue; 657 } 658 testOffset[compIdx].modeIdc = SAO_MODE_NEW; 659 testOffset[compIdx].typeIdc = typeIdc; 660 661 //derive offset & get distortion 662 deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo); 663 invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset); 664 dist[compIdx]= getDistortion(ctu, compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]); 665 } 666 667 //get rate 668 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); 669 m_pcRDGoOnSbacCoder->resetBits(); 670 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, testOffset[SAO_Cb], sliceEnabled[SAO_Cb]); 671 m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, testOffset[SAO_Cr], sliceEnabled[SAO_Cr]); 672 rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 673 674 cost = (Double)(dist[SAO_Cb]+ dist[SAO_Cr]) + chromaLambda*((Double)rate); 675 if(cost < minCost) 676 { 677 minCost = cost; 678 minRate = rate; 679 modeDist[SAO_Cb] = dist[SAO_Cb]; 680 modeDist[SAO_Cr] = dist[SAO_Cr]; 681 modeParam[SAO_Cb]= testOffset[SAO_Cb]; 682 modeParam[SAO_Cr]= testOffset[SAO_Cr]; 683 } 684 } 685 686 687 //----- re-gen rate & normalized cost----// 688 modeNormCost = (Double)modeDist[SAO_Y]/m_labmda[SAO_Y]; 689 modeNormCost += (Double)(modeDist[SAO_Cb]+ modeDist[SAO_Cr])/chromaLambda; 690 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); 691 m_pcRDGoOnSbacCoder->resetBits(); 692 m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false); 693 modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 694 695 } 696 697 Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel) 698 { 699 Int mergeListSize = (Int)mergeList.size(); 700 modeNormCost = MAX_DOUBLE; 701 702 Double cost; 703 SAOBlkParam testBlkParam; 704 705 for(Int mergeType=0; mergeType< mergeListSize; mergeType++) 706 { 707 if(mergeList[mergeType] == NULL) 708 { 709 continue; 710 } 711 712 testBlkParam = *(mergeList[mergeType]); 713 //normalized distortion 714 Double normDist=0; 715 for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++) 716 { 717 testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE; 718 testBlkParam[compIdx].typeIdc = mergeType; 719 720 SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx]; 721 722 if( mergedOffsetParam.modeIdc != SAO_MODE_OFF) 723 { 724 //offsets have been reconstructed. Don't call inversed quantization function. 725 normDist += (((Double)getDistortion(ctu, compIdx, mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctu][compIdx][mergedOffsetParam.typeIdc])) 726 /m_labmda[compIdx] 727 ); 728 } 729 730 } 731 732 //rate 733 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); 734 m_pcRDGoOnSbacCoder->resetBits(); 735 m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false); 736 Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); 737 738 cost = normDist+(Double)rate; 739 740 if(cost < modeNormCost) 741 { 742 modeNormCost = cost; 743 modeParam = testBlkParam; 744 m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); 745 } 746 } 747 748 m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); 749 750 751 } 752 753 Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams) 754 { 755 Bool isAllBlksDisabled = false; 756 if(!sliceEnabled[SAO_Y] && !sliceEnabled[SAO_Cb] && !sliceEnabled[SAO_Cr]) 757 { 758 isAllBlksDisabled = true; 759 } 760 761 m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]); 762 763 SAOBlkParam modeParam; 764 Double minCost, modeCost; 765 766 for(Int ctu=0; ctu< m_numCTUsPic; ctu++) 767 { 768 if(isAllBlksDisabled) 769 { 770 codedParams[ctu].reset(); 771 continue; 772 } 773 774 m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]); 775 776 //get merge list 777 std::vector<SAOBlkParam*> mergeList; 778 getMergeList(pic, ctu, reconParams, mergeList); 779 780 minCost = MAX_DOUBLE; 781 for(Int mode=0; mode < NUM_SAO_MODES; mode++) 782 { 783 switch(mode) 784 { 785 case SAO_MODE_OFF: 786 { 787 continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case. 788 } 789 break; 790 case SAO_MODE_NEW: 791 { 792 deriveModeNewRDO(ctu, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR); 793 794 } 795 break; 796 case SAO_MODE_MERGE: 797 { 798 deriveModeMergeRDO(ctu, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR); 799 } 800 break; 801 default: 802 { 803 printf("Not a supported SAO mode\n"); 804 assert(0); 805 exit(-1); 806 } 807 } 808 809 if(modeCost < minCost) 810 { 811 minCost = modeCost; 812 codedParams[ctu] = modeParam; 813 m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]); 814 815 } 816 } //mode 817 m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]); 818 819 //apply reconstructed offsets 820 reconParams[ctu] = codedParams[ctu]; 821 reconstructBlkSAOParam(reconParams[ctu], mergeList); 822 offsetCTU(ctu, srcYuv, resYuv, reconParams[ctu], pic); 823 } //ctu 824 825 #if SAO_ENCODING_CHOICE 826 Int picTempLayer = pic->getSlice(0)->getDepth(); 827 Int numLcusForSAOOff[NUM_SAO_COMPONENTS]; 828 numLcusForSAOOff[SAO_Y ] = numLcusForSAOOff[SAO_Cb]= numLcusForSAOOff[SAO_Cr]= 0; 829 830 for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++) 831 { 832 for(Int ctu=0; ctu< m_numCTUsPic; ctu++) 833 { 834 if( reconParams[ctu][compIdx].modeIdc == SAO_MODE_OFF) 835 { 836 numLcusForSAOOff[compIdx]++; 837 } 838 } 839 } 840 #if SAO_ENCODING_CHOICE_CHROMA 841 for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++) 842 { 843 m_saoDisabledRate[compIdx][picTempLayer] = (Double)numLcusForSAOOff[compIdx]/(Double)m_numCTUsPic; 844 } 845 #else 846 if (picTempLayer == 0) 847 { 848 m_saoDisabledRate[SAO_Y][0] = (Double)(numLcusForSAOOff[SAO_Y]+numLcusForSAOOff[SAO_Cb]+numLcusForSAOOff[SAO_Cr])/(Double)(m_numCTUsPic*3); 849 } 850 #endif 851 #endif 852 } 853 854 855 Void TEncSampleAdaptiveOffset::getBlkStats(Int compIdx, SAOStatData* statsDataTypes 856 , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height 857 , Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail 858 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 859 , Bool isCalculatePreDeblockSamples 860 #endif 861 ) 862 { 863 if(m_lineBufWidth != m_maxCUWidth) 864 { 865 m_lineBufWidth = m_maxCUWidth; 866 867 if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL; 868 m_signLineBuf1 = new Char[m_lineBufWidth+1]; 869 870 if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL; 871 m_signLineBuf2 = new Char[m_lineBufWidth+1]; 872 } 873 874 Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX; 875 Char signLeft, signRight, signDown; 876 Int64 *diff, *count; 877 Pel *srcLine, *orgLine; 878 Int* skipLinesR = m_skipLinesR[compIdx]; 879 Int* skipLinesB = m_skipLinesB[compIdx]; 880 881 for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++) 882 { 883 SAOStatData& statsData= statsDataTypes[typeIdx]; 884 statsData.reset(); 885 886 srcLine = srcBlk; 887 orgLine = orgBlk; 888 diff = statsData.diff; 889 count = statsData.count; 890 switch(typeIdx) 891 { 892 case SAO_TYPE_EO_0: 893 { 894 diff +=2; 895 count+=2; 896 endY = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height; 897 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 898 startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1) 899 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) 900 ; 901 #else 902 startX = isLeftAvail ? 0 : 1; 903 #endif 904 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 905 endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) 906 : (isRightAvail ? width : (width - 1)) 907 ; 908 #else 909 endX = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1); 910 #endif 911 for (y=0; y<endY; y++) 912 { 913 signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]]; 914 for (x=startX; x<endX; x++) 915 { 916 signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 917 edgeType = signRight + signLeft; 918 signLeft = -signRight; 919 920 diff [edgeType] += (orgLine[x] - srcLine[x]); 921 count[edgeType] ++; 922 } 923 srcLine += srcStride; 924 orgLine += orgStride; 925 } 926 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 927 if(isCalculatePreDeblockSamples) 928 { 929 if(isBelowAvail) 930 { 931 startX = isLeftAvail ? 0 : 1; 932 endX = isRightAvail ? width : (width -1); 933 934 for(y=0; y<skipLinesB[typeIdx]; y++) 935 { 936 signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]]; 937 for (x=startX; x<endX; x++) 938 { 939 signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 940 edgeType = signRight + signLeft; 941 signLeft = -signRight; 942 943 diff [edgeType] += (orgLine[x] - srcLine[x]); 944 count[edgeType] ++; 945 } 946 srcLine += srcStride; 947 orgLine += orgStride; 948 } 949 } 950 } 951 #endif 952 } 953 break; 954 case SAO_TYPE_EO_90: 955 { 956 diff +=2; 957 count+=2; 958 Char *signUpLine = m_signLineBuf1; 959 960 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 961 startX = (!isCalculatePreDeblockSamples) ? 0 962 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width) 963 ; 964 #endif 965 startY = isAboveAvail ? 0 : 1; 966 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 967 endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width) 968 : width 969 ; 970 #else 971 endX = isRightAvail ? (width - skipLinesR[typeIdx]) : width ; 972 #endif 973 endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1); 974 if (!isAboveAvail) 975 { 976 srcLine += srcStride; 977 orgLine += orgStride; 978 } 979 980 Pel* srcLineAbove = srcLine - srcStride; 981 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 982 for (x=startX; x<endX; x++) 983 #else 984 for (x=0; x< endX; x++) 985 #endif 986 { 987 signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]]; 988 } 989 990 Pel* srcLineBelow; 991 for (y=startY; y<endY; y++) 992 { 993 srcLineBelow = srcLine + srcStride; 994 995 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 996 for (x=startX; x<endX; x++) 997 #else 998 for (x=0; x<endX; x++) 999 #endif 1000 { 1001 signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 1002 edgeType = signDown + signUpLine[x]; 1003 signUpLine[x]= -signDown; 1004 1005 diff [edgeType] += (orgLine[x] - srcLine[x]); 1006 count[edgeType] ++; 1007 } 1008 srcLine += srcStride; 1009 orgLine += orgStride; 1010 } 1011 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1012 if(isCalculatePreDeblockSamples) 1013 { 1014 if(isBelowAvail) 1015 { 1016 startX = 0; 1017 endX = width; 1018 1019 for(y=0; y<skipLinesB[typeIdx]; y++) 1020 { 1021 srcLineBelow = srcLine + srcStride; 1022 srcLineAbove = srcLine - srcStride; 1023 1024 for (x=startX; x<endX; x++) 1025 { 1026 edgeType = m_sign[srcLine[x] - srcLineBelow[x]] + m_sign[srcLine[x] - srcLineAbove[x]]; 1027 diff [edgeType] += (orgLine[x] - srcLine[x]); 1028 count[edgeType] ++; 1029 } 1030 srcLine += srcStride; 1031 orgLine += orgStride; 1032 } 1033 } 1034 } 1035 #endif 1036 1037 } 1038 break; 1039 case SAO_TYPE_EO_135: 1040 { 1041 diff +=2; 1042 count+=2; 1043 Char *signUpLine, *signDownLine, *signTmpLine; 1044 1045 signUpLine = m_signLineBuf1; 1046 signDownLine= m_signLineBuf2; 1047 1048 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1049 startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1) 1050 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) 1051 ; 1052 #else 1053 startX = isLeftAvail ? 0 : 1 ; 1054 #endif 1055 1056 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1057 endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1)) 1058 : (isRightAvail ? width : (width - 1)) 1059 ; 1060 #else 1061 endX = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1); 1062 #endif 1063 endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1); 1064 1065 //prepare 2nd line's upper sign 1066 Pel* srcLineBelow = srcLine + srcStride; 1067 for (x=startX; x<endX+1; x++) 1068 { 1069 signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x-1]]; 1070 } 1071 1072 //1st line 1073 Pel* srcLineAbove = srcLine - srcStride; 1074 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1075 firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0 : 1) : startX; 1076 firstLineEndX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? endX : 1) : endX; 1077 #else 1078 firstLineStartX = isAboveLeftAvail ? 0 : 1; 1079 firstLineEndX = isAboveAvail ? endX : 1; 1080 #endif 1081 for(x=firstLineStartX; x<firstLineEndX; x++) 1082 { 1083 edgeType = m_sign[srcLine[x] - srcLineAbove[x-1]] - signUpLine[x+1]; 1084 diff [edgeType] += (orgLine[x] - srcLine[x]); 1085 count[edgeType] ++; 1086 } 1087 srcLine += srcStride; 1088 orgLine += orgStride; 1089 1090 1091 //middle lines 1092 for (y=1; y<endY; y++) 1093 { 1094 srcLineBelow = srcLine + srcStride; 1095 1096 for (x=startX; x<endX; x++) 1097 { 1098 signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x+1]] ; 1099 edgeType = signDown + signUpLine[x]; 1100 diff [edgeType] += (orgLine[x] - srcLine[x]); 1101 count[edgeType] ++; 1102 1103 signDownLine[x+1] = -signDown; 1104 } 1105 signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]]; 1106 1107 signTmpLine = signUpLine; 1108 signUpLine = signDownLine; 1109 signDownLine = signTmpLine; 1110 1111 srcLine += srcStride; 1112 orgLine += orgStride; 1113 } 1114 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1115 if(isCalculatePreDeblockSamples) 1116 { 1117 if(isBelowAvail) 1118 { 1119 startX = isLeftAvail ? 0 : 1 ; 1120 endX = isRightAvail ? width : (width -1); 1121 1122 for(y=0; y<skipLinesB[typeIdx]; y++) 1123 { 1124 srcLineBelow = srcLine + srcStride; 1125 srcLineAbove = srcLine - srcStride; 1126 1127 for (x=startX; x< endX; x++) 1128 { 1129 edgeType = m_sign[srcLine[x] - srcLineBelow[x+1]] + m_sign[srcLine[x] - srcLineAbove[x-1]]; 1130 diff [edgeType] += (orgLine[x] - srcLine[x]); 1131 count[edgeType] ++; 1132 } 1133 srcLine += srcStride; 1134 orgLine += orgStride; 1135 } 1136 } 1137 } 1138 #endif 1139 } 1140 break; 1141 case SAO_TYPE_EO_45: 1142 { 1143 diff +=2; 1144 count+=2; 1145 Char *signUpLine = m_signLineBuf1+1; 1146 1147 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1148 startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1) 1149 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) 1150 ; 1151 #else 1152 startX = isLeftAvail ? 0 : 1; 1153 #endif 1154 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1155 endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) 1156 : (isRightAvail ? width : (width - 1)) 1157 ; 1158 #else 1159 endX = isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1); 1160 #endif 1161 endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1); 1162 1163 //prepare 2nd line upper sign 1164 Pel* srcLineBelow = srcLine + srcStride; 1165 for (x=startX-1; x<endX; x++) 1166 { 1167 signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]]; 1168 } 1169 1170 1171 //first line 1172 Pel* srcLineAbove = srcLine - srcStride; 1173 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1174 firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX) 1175 : startX 1176 ; 1177 firstLineEndX = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX) 1178 : endX 1179 ; 1180 #else 1181 firstLineStartX = isAboveAvail ? startX : endX; 1182 firstLineEndX = (!isRightAvail && isAboveRightAvail) ? width : endX; 1183 #endif 1184 for(x=firstLineStartX; x<firstLineEndX; x++) 1185 { 1186 edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] - signUpLine[x-1]; 1187 diff [edgeType] += (orgLine[x] - srcLine[x]); 1188 count[edgeType] ++; 1189 } 1190 1191 srcLine += srcStride; 1192 orgLine += orgStride; 1193 1194 //middle lines 1195 for (y=1; y<endY; y++) 1196 { 1197 srcLineBelow = srcLine + srcStride; 1198 1199 for(x=startX; x<endX; x++) 1200 { 1201 signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ; 1202 edgeType = signDown + signUpLine[x]; 1203 1204 diff [edgeType] += (orgLine[x] - srcLine[x]); 1205 count[edgeType] ++; 1206 1207 signUpLine[x-1] = -signDown; 1208 } 1209 signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]]; 1210 srcLine += srcStride; 1211 orgLine += orgStride; 1212 } 1213 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1214 if(isCalculatePreDeblockSamples) 1215 { 1216 if(isBelowAvail) 1217 { 1218 startX = isLeftAvail ? 0 : 1 ; 1219 endX = isRightAvail ? width : (width -1); 1220 1221 for(y=0; y<skipLinesB[typeIdx]; y++) 1222 { 1223 srcLineBelow = srcLine + srcStride; 1224 srcLineAbove = srcLine - srcStride; 1225 1226 for (x=startX; x<endX; x++) 1227 { 1228 edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + m_sign[srcLine[x] - srcLineAbove[x+1]]; 1229 diff [edgeType] += (orgLine[x] - srcLine[x]); 1230 count[edgeType] ++; 1231 } 1232 srcLine += srcStride; 1233 orgLine += orgStride; 1234 } 1235 } 1236 } 1237 #endif 1238 } 1239 break; 1240 case SAO_TYPE_BO: 1241 { 1242 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1243 startX = (!isCalculatePreDeblockSamples)?0 1244 :( isRightAvail?(width- skipLinesR[typeIdx]):width) 1245 ; 1246 endX = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width ) 1247 :width 1248 ; 1249 #else 1250 endX = isRightAvail ? (width- skipLinesR[typeIdx]) : width; 1251 #endif 1252 endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height; 1253 Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2; 1254 for (y=0; y< endY; y++) 1255 { 1256 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1257 for (x=startX; x< endX; x++) 1258 #else 1259 for (x=0; x< endX; x++) 1260 #endif 1261 { 1262 1263 Int bandIdx= srcLine[x] >> shiftBits; 1264 diff [bandIdx] += (orgLine[x] - srcLine[x]); 1265 count[bandIdx] ++; 1266 } 1267 srcLine += srcStride; 1268 orgLine += orgStride; 1269 } 1270 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK 1271 if(isCalculatePreDeblockSamples) 1272 { 1273 if(isBelowAvail) 1274 { 1275 startX = 0; 1276 endX = width; 1277 1278 for(y= 0; y< skipLinesB[typeIdx]; y++) 1279 { 1280 for (x=startX; x< endX; x++) 1281 { 1282 Int bandIdx= srcLine[x] >> shiftBits; 1283 diff [bandIdx] += (orgLine[x] - srcLine[x]); 1284 count[bandIdx] ++; 1285 } 1286 srcLine += srcStride; 1287 orgLine += orgStride; 1288 1289 } 1290 1291 } 1292 } 1293 #endif 1294 } 1295 break; 1296 default: 1297 { 1298 printf("Not a supported SAO types\n"); 1299 assert(0); 1300 exit(-1); 1301 } 1302 } 1303 } 1304 } 1305 1306 #else 1307 1308 1309 47 1310 TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset() 48 1311 { … … 1661 2924 } 1662 2925 1663 #if SAO_CHROMA_LAMBDA1664 2926 /** Sample adaptive offset process 1665 2927 * \param pcSaoParam … … 1671 2933 #else 1672 2934 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma) 1673 #endif1674 #else1675 /** Sample adaptive offset process1676 * \param dLambda1677 */1678 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)1679 2935 #endif 1680 2936 { … … 2501 3757 } 2502 3758 3759 #endif 3760 2503 3761 //! \}
Note: See TracChangeset for help on using the changeset viewer.