HEVC Test Model (HM)  HM-16.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TEncSampleAdaptiveOffset.cpp
Go to the documentation of this file.
1 /* The copyright in this software is being made available under the BSD
2  * License, included below. This software may be subject to other third party
3  * and contributor rights, including patent rights, and no such rights are
4  * granted under this license.
5  *
6  * Copyright (c) 2010-2017, ITU/ISO/IEC
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18  * be used to endorse or promote products derived from this software without
19  * specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
39 #include <string.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <math.h>
43 
46 
47 
49 inline Double xRoundIbdi2(Int bitDepth, Double x)
50 {
51  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))));
52 }
53 
54 inline Double xRoundIbdi(Int bitDepth, Double x)
55 {
56  return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
57 }
58 
59 
61 {
65  m_statData = NULL;
67 }
68 
70 {
72 }
73 
75 {
76 
77  //cabac coder for RDO
79 #if FAST_BIT_EST
81 #else
83 #endif
84 
85  for(Int cs=0; cs < NUM_SAO_CABACSTATE_LABELS; cs++)
86  {
87  m_pppcRDSbacCoder[cs] = new TEncSbac;
88 #if FAST_BIT_EST
90 #else
92 #endif
94  }
95 
96 
97  //statistics
99  for(Int i=0; i< m_numCTUsPic; i++)
100  {
102  for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++)
103  {
104  m_statData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES];
105  }
106  }
107  if(isPreDBFSamplesUsed)
108  {
110  for(Int i=0; i< m_numCTUsPic; i++)
111  {
113  for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++)
114  {
116  }
117  }
118 
119  }
120 
121  ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate));
123 
124  for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
125  {
126  m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
127  m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
128 
129  m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
130  m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
131 
132  if(isPreDBFSamplesUsed)
133  {
134  switch(typeIdc)
135  {
136  case SAO_TYPE_EO_0:
137  {
138  m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
139  m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
140 
141  m_skipLinesB[COMPONENT_Y ][typeIdc]= 3;
142  m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1;
143  }
144  break;
145  case SAO_TYPE_EO_90:
146  {
147  m_skipLinesR[COMPONENT_Y ][typeIdc]= 4;
148  m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2;
149 
150  m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
151  m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
152  }
153  break;
154  case SAO_TYPE_EO_135:
155  case SAO_TYPE_EO_45:
156  {
157  m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
158  m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
159 
160  m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
161  m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
162  }
163  break;
164  case SAO_TYPE_BO:
165  {
166  m_skipLinesR[COMPONENT_Y ][typeIdc]= 4;
167  m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2;
168 
169  m_skipLinesB[COMPONENT_Y ][typeIdc]= 3;
170  m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1;
171  }
172  break;
173  default:
174  {
175  printf("Not a supported type");
176  assert(0);
177  exit(-1);
178  }
179  }
180  }
181  }
182 
183 }
184 
186 {
187  if(m_pppcRDSbacCoder != NULL)
188  {
189  for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
190  {
191  delete m_pppcRDSbacCoder[cs];
192  }
194  }
195 
197  {
198  for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
199  {
200  delete m_pppcBinCoderCABAC[cs];
201  }
203  }
204 
205  if(m_statData != NULL)
206  {
207  for(Int i=0; i< m_numCTUsPic; i++)
208  {
209  for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++)
210  {
211  delete[] m_statData[i][compIdx];
212  }
213  delete[] m_statData[i];
214  }
215  delete[] m_statData; m_statData = NULL;
216  }
217  if(m_preDBFstatData != NULL)
218  {
219  for(Int i=0; i< m_numCTUsPic; i++)
220  {
221  for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++)
222  {
223  delete[] m_preDBFstatData[i][compIdx];
224  }
225  delete[] m_preDBFstatData[i];
226  }
228  }
229 }
230 
232 {
233  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
236 
238 }
239 
240 
241 
242 Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool isPreDBFSamplesUsed, const Bool bResetStateAfterIRAP )
243 {
244  TComPicYuv* orgYuv= pPic->getPicYuvOrg();
245  TComPicYuv* resYuv= pPic->getPicYuvRec();
246  memcpy(m_lambda, lambdas, sizeof(m_lambda));
247  TComPicYuv* srcYuv = m_tempPicYuv;
248  resYuv->copyToPic(srcYuv);
249  srcYuv->setBorderExtension(false);
250  srcYuv->extendPicBorder();
251 
252  //collect statistics
253  getStatistics(m_statData, orgYuv, srcYuv, pPic);
254  if(isPreDBFSamplesUsed)
255  {
257  }
258 
259  //slice on/off
260  decidePicParams(sliceEnabled, pPic, saoEncodingRate, saoEncodingRateChroma, bResetStateAfterIRAP);
261 
262  //block on/off
263  SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters
264  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam(), bTestSAODisableAtPictureLevel, saoEncodingRate, saoEncodingRateChroma);
265  delete[] reconParams;
266 }
267 
269 {
270  getStatistics(m_preDBFstatData, pPic->getPicYuvOrg(), pPic->getPicYuvRec(), pPic, true);
271 }
272 
274 {
275  for(Int n=0; n< m_numCTUsPic; n++)
276  {
277  for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++)
278  {
279  for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
280  {
281  blkStats[n][compIdx][typeIdc] += m_preDBFstatData[n][compIdx][typeIdc];
282  }
283  }
284  }
285 }
286 
287 Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic, Bool isCalculatePreDeblockSamples)
288 {
289  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
290 
291  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
292 
293  for(Int ctuRsAddr= 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++)
294  {
295  Int yPos = (ctuRsAddr / m_numCTUInWidth)*m_maxCUHeight;
296  Int xPos = (ctuRsAddr % m_numCTUInWidth)*m_maxCUWidth;
297  Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
298  Int width = (xPos + m_maxCUWidth > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
299 
300  pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctuRsAddr, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
301 
302  //NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities.
303  //For simplicity, here only picture boundaries are considered.
304 
305  isRightAvail = (xPos + m_maxCUWidth < m_picWidth );
306  isBelowAvail = (yPos + m_maxCUHeight < m_picHeight);
307  isBelowRightAvail = (isRightAvail && isBelowAvail);
308  isBelowLeftAvail = ((xPos > 0) && (isBelowAvail));
309  isAboveRightAvail = ((yPos > 0) && (isRightAvail));
310 
311  for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
312  {
313  const ComponentID component = ComponentID(compIdx);
314 
315  const UInt componentScaleX = getComponentScaleX(component, pPic->getChromaFormat());
316  const UInt componentScaleY = getComponentScaleY(component, pPic->getChromaFormat());
317 
318  Int srcStride = srcYuv->getStride(component);
319  Pel* srcBlk = srcYuv->getAddr(component) + ((yPos >> componentScaleY) * srcStride) + (xPos >> componentScaleX);
320 
321  Int orgStride = orgYuv->getStride(component);
322  Pel* orgBlk = orgYuv->getAddr(component) + ((yPos >> componentScaleY) * orgStride) + (xPos >> componentScaleX);
323 
324  getBlkStats(component, pPic->getPicSym()->getSPS().getBitDepth(toChannelType(component)), blkStats[ctuRsAddr][component]
325  , srcBlk, orgBlk, srcStride, orgStride, (width >> componentScaleX), (height >> componentScaleY)
326  , isLeftAvail, isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail
327  , isCalculatePreDeblockSamples
328  );
329 
330  }
331  }
332 }
333 
334 Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, const TComPic* pic, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool bResetStateAfterIRAP)
335 {
336  if (pic->getSlice(0)->isIRAP())
337  {
338  m_lastIRAPPoc = pic->getSlice(0)->getPOC();
339  }
340  if (bResetStateAfterIRAP && pic->getSlice(0)->getPOC() > m_lastIRAPPoc)
341  { // reset
342  for (Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++)
343  {
344  for (Int tempLayer = 1; tempLayer < MAX_TLAYER; tempLayer++)
345  {
346  m_saoDisabledRate[compIdx][tempLayer] = 0.0;
347  }
348  }
350  }
351  const Int picTempLayer = pic->getSlice(0)->getDepth();
352 
353  //decide sliceEnabled[compIdx]
354  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
355  for (Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++)
356  {
357  sliceEnabled[compIdx] = false;
358  }
359 
360  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
361  {
362  // reset flags & counters
363  sliceEnabled[compIdx] = true;
364 
365  if (saoEncodingRate>0.0)
366  {
367  if (saoEncodingRateChroma>0.0)
368  {
369  // decide slice-level on/off based on previous results
370  if( (picTempLayer > 0)
371  && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==COMPONENT_Y) ? saoEncodingRate : saoEncodingRateChroma)) )
372  {
373  sliceEnabled[compIdx] = false;
374  }
375  }
376  else
377  {
378  // decide slice-level on/off based on previous results
379  if( (picTempLayer > 0)
380  && (m_saoDisabledRate[COMPONENT_Y][0] > saoEncodingRate) )
381  {
382  sliceEnabled[compIdx] = false;
383  }
384  }
385  }
386  }
387 }
388 
389 Int64 TEncSampleAdaptiveOffset::getDistortion(const Int channelBitDepth, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData)
390 {
391  Int64 dist = 0;
392  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth - 8);
393 
394  switch(typeIdc)
395  {
396  case SAO_TYPE_EO_0:
397  case SAO_TYPE_EO_90:
398  case SAO_TYPE_EO_135:
399  case SAO_TYPE_EO_45:
400  {
401  for (Int offsetIdx=0; offsetIdx<NUM_SAO_EO_CLASSES; offsetIdx++)
402  {
403  dist += estSaoDist( statData.count[offsetIdx], invQuantOffset[offsetIdx], statData.diff[offsetIdx], shift);
404  }
405  }
406  break;
407  case SAO_TYPE_BO:
408  {
409  for (Int offsetIdx=typeAuxInfo; offsetIdx<typeAuxInfo+4; offsetIdx++)
410  {
411  Int bandIdx = offsetIdx % NUM_SAO_BO_CLASSES ;
412  dist += estSaoDist( statData.count[bandIdx], invQuantOffset[bandIdx], statData.diff[bandIdx], shift);
413  }
414  }
415  break;
416  default:
417  {
418  printf("Not a supported type");
419  assert(0);
420  exit(-1);
421  }
422  }
423 
424  return dist;
425 }
426 
427 inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift)
428 {
429  return (( count*offset*offset-diffSum*offset*2 ) >> shift);
430 }
431 
432 
433 inline Int TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh )
434 {
435  Int iterOffset, tempOffset;
436  Int64 tempDist, tempRate;
437  Double tempCost, tempMinCost;
438  Int offsetOutput = 0;
439  iterOffset = offsetInput;
440  // 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.
441  tempMinCost = lambda;
442  while (iterOffset != 0)
443  {
444  // Calculate the bits required for signaling the offset
445  tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
446  if (abs((Int)iterOffset)==offsetTh) //inclusive
447  {
448  tempRate --;
449  }
450  // Do the dequantization before distortion calculation
451  tempOffset = iterOffset << bitIncrease;
452  tempDist = estSaoDist( count, tempOffset, diffSum, shift);
453  tempCost = ((Double)tempDist + lambda * (Double) tempRate);
454  if(tempCost < tempMinCost)
455  {
456  tempMinCost = tempCost;
457  offsetOutput = iterOffset;
458  bestDist = tempDist;
459  bestCost = tempCost;
460  }
461  iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
462  }
463  return offsetOutput;
464 }
465 
466 Void TEncSampleAdaptiveOffset::deriveOffsets(ComponentID compIdx, const Int channelBitDepth, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo)
467 {
468  Int bitDepth = channelBitDepth;
469  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8);
470  Int offsetTh = TComSampleAdaptiveOffset::getMaxOffsetQVal(channelBitDepth); //inclusive
471 
472  ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
473 
474  //derive initial offsets
475  Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES);
476  for(Int classIdx=0; classIdx< numClasses; classIdx++)
477  {
478  if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN) )
479  {
480  continue; //offset will be zero
481  }
482 
483  if(statData.count[classIdx] == 0)
484  {
485  continue; //offset will be zero
486  }
487 
488  quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8))
489  /
490  (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx])
491  );
492  quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]);
493  }
494 
495  // adjust offsets
496  switch(typeIdc)
497  {
498  case SAO_TYPE_EO_0:
499  case SAO_TYPE_EO_90:
500  case SAO_TYPE_EO_135:
501  case SAO_TYPE_EO_45:
502  {
503  Int64 classDist;
504  Double classCost;
505  for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++)
506  {
507  if(classIdx==SAO_CLASS_EO_FULL_VALLEY && quantOffsets[classIdx] < 0)
508  {
509  quantOffsets[classIdx] =0;
510  }
511  if(classIdx==SAO_CLASS_EO_HALF_VALLEY && quantOffsets[classIdx] < 0)
512  {
513  quantOffsets[classIdx] =0;
514  }
515  if(classIdx==SAO_CLASS_EO_HALF_PEAK && quantOffsets[classIdx] > 0)
516  {
517  quantOffsets[classIdx] =0;
518  }
519  if(classIdx==SAO_CLASS_EO_FULL_PEAK && quantOffsets[classIdx] > 0)
520  {
521  quantOffsets[classIdx] =0;
522  }
523 
524  if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
525  {
526  quantOffsets[classIdx] = estIterOffset( typeIdc, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh );
527  }
528  }
529 
530  typeAuxInfo =0;
531  }
532  break;
533  case SAO_TYPE_BO:
534  {
535  Int64 distBOClasses[NUM_SAO_BO_CLASSES];
536  Double costBOClasses[NUM_SAO_BO_CLASSES];
537  ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES);
538  for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++)
539  {
540  costBOClasses[classIdx]= m_lambda[compIdx];
541  if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
542  {
543  quantOffsets[classIdx] = estIterOffset( typeIdc, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], distBOClasses[classIdx], costBOClasses[classIdx], offsetTh );
544  }
545  }
546 
547  //decide the starting band index
548  Double minCost = MAX_DOUBLE, cost;
549  for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++)
550  {
551  cost = costBOClasses[band ];
552  cost += costBOClasses[band+1];
553  cost += costBOClasses[band+2];
554  cost += costBOClasses[band+3];
555 
556  if(cost < minCost)
557  {
558  minCost = cost;
559  typeAuxInfo = band;
560  }
561  }
562  //clear those unused classes
563  Int clearQuantOffset[NUM_SAO_BO_CLASSES];
564  ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES);
565  for(Int i=0; i< 4; i++)
566  {
567  Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES;
568  clearQuantOffset[band] = quantOffsets[band];
569  }
570  ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES);
571  }
572  break;
573  default:
574  {
575  printf("Not a supported type");
576  assert(0);
577  exit(-1);
578  }
579 
580  }
581 
582 
583 }
584 
585 Void TEncSampleAdaptiveOffset::deriveModeNewRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
586 {
587  Double minCost, cost;
588  UInt previousWrittenBits;
589  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
590 
591  Int64 dist[MAX_NUM_COMPONENT], modeDist[MAX_NUM_COMPONENT];
592  SAOOffset testOffset[MAX_NUM_COMPONENT];
593  Int invQuantOffset[MAX_NUM_SAO_CLASSES];
594  for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++)
595  {
596  modeDist[comp] = 0;
597  }
598 
599  //pre-encode merge flags
600  modeParam[COMPONENT_Y].modeIdc = SAO_MODE_OFF;
601  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
602  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true);
604 
605  //------ luma --------//
606  {
607  const ComponentID compIdx = COMPONENT_Y;
608  //"off" case as initial cost
609  modeParam[compIdx].modeIdc = SAO_MODE_OFF;
611  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]);
612  modeDist[compIdx] = 0;
615  if(sliceEnabled[compIdx])
616  {
617  for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
618  {
619  testOffset[compIdx].modeIdc = SAO_MODE_NEW;
620  testOffset[compIdx].typeIdc = typeIdc;
621 
622  //derive coded offset
623  deriveOffsets(compIdx, bitDepths.recon[CHANNEL_TYPE_LUMA], typeIdc, blkStats[ctuRsAddr][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
624 
625  //inversed quantized offsets
626  invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
627 
628  //get distortion
629  dist[compIdx] = getDistortion(bitDepths.recon[CHANNEL_TYPE_LUMA], testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][compIdx][typeIdc]);
630 
631  //get rate
632  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
634  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]);
636  cost = (Double)dist[compIdx] + m_lambda[compIdx]*((Double)rate);
637  if(cost < minCost)
638  {
639  minCost = cost;
640  modeDist[compIdx] = dist[compIdx];
641  modeParam[compIdx]= testOffset[compIdx];
642  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
643  }
644  }
645  }
646  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
647  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
648  }
649 
650  //------ chroma --------//
651 //"off" case as initial cost
652  cost = 0;
653  previousWrittenBits = 0;
655  for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
656  {
657  const ComponentID component = ComponentID(componentIndex);
658 
659  modeParam[component].modeIdc = SAO_MODE_OFF;
660  modeDist [component] = 0;
661  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, modeParam[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]);
662 
663  const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
664  cost += m_lambda[component] * (currentWrittenBits - previousWrittenBits);
665  previousWrittenBits = currentWrittenBits;
666  }
667 
668  minCost = cost;
669 
670  //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function
671 
672  for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
673  {
674  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
676  previousWrittenBits = 0;
677  cost = 0;
678 
679  for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
680  {
681  const ComponentID component = ComponentID(componentIndex);
682  if(!sliceEnabled[component])
683  {
684  testOffset[component].modeIdc = SAO_MODE_OFF;
685  dist[component]= 0;
686  continue;
687  }
688  testOffset[component].modeIdc = SAO_MODE_NEW;
689  testOffset[component].typeIdc = typeIdc;
690 
691  //derive offset & get distortion
692  deriveOffsets(component, bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, blkStats[ctuRsAddr][component][typeIdc], testOffset[component].offset, testOffset[component].typeAuxInfo);
693  invertQuantOffsets(component, typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, testOffset[component].offset);
694  dist[component] = getDistortion(bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][component][typeIdc]);
695 
696  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, testOffset[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]);
697 
698  const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
699  cost += dist[component] + (m_lambda[component] * (currentWrittenBits - previousWrittenBits));
700  previousWrittenBits = currentWrittenBits;
701  }
702 
703  if(cost < minCost)
704  {
705  minCost = cost;
706  for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
707  {
708  modeDist[componentIndex] = dist[componentIndex];
709  modeParam[componentIndex] = testOffset[componentIndex];
710  }
711  }
712 
713  } // SAO_TYPE loop
714 
715  //----- re-gen rate & normalized cost----//
716  modeNormCost = 0;
717  for(UInt componentIndex = COMPONENT_Y; componentIndex < numberOfComponents; componentIndex++)
718  {
719  modeNormCost += (Double)modeDist[componentIndex] / m_lambda[componentIndex];
720  }
721 
722  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
724  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
726 }
727 
728 Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
729 {
730  modeNormCost = MAX_DOUBLE;
731 
732  Double cost;
733  SAOBlkParam testBlkParam;
734  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
735 
736  for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++)
737  {
738  if(mergeList[mergeType] == NULL)
739  {
740  continue;
741  }
742 
743  testBlkParam = *(mergeList[mergeType]);
744  //normalized distortion
745  Double normDist=0;
746  for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
747  {
748  testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE;
749  testBlkParam[compIdx].typeIdc = mergeType;
750 
751  SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx];
752 
753  if( mergedOffsetParam.modeIdc != SAO_MODE_OFF)
754  {
755  //offsets have been reconstructed. Don't call inversed quantization function.
756  normDist += (((Double)getDistortion(bitDepths.recon[toChannelType(ComponentID(compIdx))], mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctuRsAddr][compIdx][mergedOffsetParam.typeIdc]))
757  /m_lambda[compIdx]
758  );
759  }
760 
761  }
762 
763  //rate
764  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
766  m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
768 
769  cost = normDist+(Double)rate;
770 
771  if(cost < modeNormCost)
772  {
773  modeNormCost = cost;
774  modeParam = testBlkParam;
776  }
777  }
778 
780 }
781 
783  SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel,
784  const Double saoEncodingRate, const Double saoEncodingRateChroma)
785 {
786  Bool allBlksDisabled = true;
787  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
788  for(Int compId = COMPONENT_Y; compId < numberOfComponents; compId++)
789  {
790  if (sliceEnabled[compId])
791  {
792  allBlksDisabled = false;
793  }
794  }
795 
797 
798  SAOBlkParam modeParam;
799  Double minCost, modeCost;
800 
801 
802  Double totalCost = 0; // Used if bTestSAODisableAtPictureLevel==true
803 
804  for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
805  {
806  if(allBlksDisabled)
807  {
808  codedParams[ctuRsAddr].reset();
809  continue;
810  }
811 
813 
814  //get merge list
815  SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES] = { NULL };
816  getMergeList(pic, ctuRsAddr, reconParams, mergeList);
817 
818  minCost = MAX_DOUBLE;
819  for(Int mode=0; mode < NUM_SAO_MODES; mode++)
820  {
821  switch(mode)
822  {
823  case SAO_MODE_OFF:
824  {
825  continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case.
826  }
827  break;
828  case SAO_MODE_NEW:
829  {
830  deriveModeNewRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
831 
832  }
833  break;
834  case SAO_MODE_MERGE:
835  {
836  deriveModeMergeRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
837  }
838  break;
839  default:
840  {
841  printf("Not a supported SAO mode\n");
842  assert(0);
843  exit(-1);
844  }
845  }
846 
847  if(modeCost < minCost)
848  {
849  minCost = modeCost;
850  codedParams[ctuRsAddr] = modeParam;
852  }
853  } //mode
854 
855  totalCost += minCost;
856 
858 
859  //apply reconstructed offsets
860  reconParams[ctuRsAddr] = codedParams[ctuRsAddr];
861  reconstructBlkSAOParam(reconParams[ctuRsAddr], mergeList);
862  offsetCTU(ctuRsAddr, srcYuv, resYuv, reconParams[ctuRsAddr], pic);
863  } //ctuRsAddr
864 
865  if (!allBlksDisabled && (totalCost >= 0) && bTestSAODisableAtPictureLevel) //SAO has not beneficial in this case - disable it
866  {
867  for(Int ctuRsAddr = 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++)
868  {
869  codedParams[ctuRsAddr].reset();
870  }
871 
872  for (UInt componentIndex = 0; componentIndex < MAX_NUM_COMPONENT; componentIndex++)
873  {
874  sliceEnabled[componentIndex] = false;
875  }
876 
877  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]);
878  }
879 
880  if (saoEncodingRate > 0.0)
881  {
882  Int picTempLayer = pic->getSlice(0)->getDepth();
883  Int numCtusForSAOOff[MAX_NUM_COMPONENT];
884 
885  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
886  {
887  numCtusForSAOOff[compIdx] = 0;
888  for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
889  {
890  if( reconParams[ctuRsAddr][compIdx].modeIdc == SAO_MODE_OFF)
891  {
892  numCtusForSAOOff[compIdx]++;
893  }
894  }
895  }
896  if (saoEncodingRateChroma > 0.0)
897  {
898  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
899  {
900  m_saoDisabledRate[compIdx][picTempLayer] = (Double)numCtusForSAOOff[compIdx]/(Double)m_numCTUsPic;
901  }
902  }
903  else if (picTempLayer == 0)
904  {
905  m_saoDisabledRate[COMPONENT_Y][0] = (Double)(numCtusForSAOOff[COMPONENT_Y]+numCtusForSAOOff[COMPONENT_Cb]+numCtusForSAOOff[COMPONENT_Cr])/(Double)(m_numCTUsPic*3);
906  }
907  }
908 }
909 
910 
911 Void TEncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData* statsDataTypes
912  , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height
913  , Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail
914  , Bool isCalculatePreDeblockSamples
915  )
916 {
918  {
920 
921  if (m_signLineBuf1)
922  {
923  delete[] m_signLineBuf1;
925  }
927 
928  if (m_signLineBuf2)
929  {
930  delete[] m_signLineBuf2;
932  }
934  }
935 
936  Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;
937  SChar signLeft, signRight, signDown;
938  Int64 *diff, *count;
939  Pel *srcLine, *orgLine;
940  Int* skipLinesR = m_skipLinesR[compIdx];
941  Int* skipLinesB = m_skipLinesB[compIdx];
942 
943  for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++)
944  {
945  SAOStatData& statsData= statsDataTypes[typeIdx];
946  statsData.reset();
947 
948  srcLine = srcBlk;
949  orgLine = orgBlk;
950  diff = statsData.diff;
951  count = statsData.count;
952  switch(typeIdx)
953  {
954  case SAO_TYPE_EO_0:
955  {
956  diff +=2;
957  count+=2;
958  endY = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height;
959  startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1)
960  : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
961  ;
962  endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
963  : (isRightAvail ? width : (width - 1))
964  ;
965  for (y=0; y<endY; y++)
966  {
967  signLeft = (SChar)sgn(srcLine[startX] - srcLine[startX-1]);
968  for (x=startX; x<endX; x++)
969  {
970  signRight = (SChar)sgn(srcLine[x] - srcLine[x+1]);
971  edgeType = signRight + signLeft;
972  signLeft = -signRight;
973 
974  diff [edgeType] += (orgLine[x] - srcLine[x]);
975  count[edgeType] ++;
976  }
977  srcLine += srcStride;
978  orgLine += orgStride;
979  }
980  if(isCalculatePreDeblockSamples)
981  {
982  if(isBelowAvail)
983  {
984  startX = isLeftAvail ? 0 : 1;
985  endX = isRightAvail ? width : (width -1);
986 
987  for(y=0; y<skipLinesB[typeIdx]; y++)
988  {
989  signLeft = (SChar)sgn(srcLine[startX] - srcLine[startX-1]);
990  for (x=startX; x<endX; x++)
991  {
992  signRight = (SChar)sgn(srcLine[x] - srcLine[x+1]);
993  edgeType = signRight + signLeft;
994  signLeft = -signRight;
995 
996  diff [edgeType] += (orgLine[x] - srcLine[x]);
997  count[edgeType] ++;
998  }
999  srcLine += srcStride;
1000  orgLine += orgStride;
1001  }
1002  }
1003  }
1004  }
1005  break;
1006  case SAO_TYPE_EO_90:
1007  {
1008  diff +=2;
1009  count+=2;
1010  SChar *signUpLine = m_signLineBuf1;
1011 
1012  startX = (!isCalculatePreDeblockSamples) ? 0
1013  : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
1014  ;
1015  startY = isAboveAvail ? 0 : 1;
1016  endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
1017  : width
1018  ;
1019  endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1020  if (!isAboveAvail)
1021  {
1022  srcLine += srcStride;
1023  orgLine += orgStride;
1024  }
1025 
1026  Pel* srcLineAbove = srcLine - srcStride;
1027  for (x=startX; x<endX; x++)
1028  {
1029  signUpLine[x] = (SChar)sgn(srcLine[x] - srcLineAbove[x]);
1030  }
1031 
1032  Pel* srcLineBelow;
1033  for (y=startY; y<endY; y++)
1034  {
1035  srcLineBelow = srcLine + srcStride;
1036 
1037  for (x=startX; x<endX; x++)
1038  {
1039  signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x]);
1040  edgeType = signDown + signUpLine[x];
1041  signUpLine[x]= -signDown;
1042 
1043  diff [edgeType] += (orgLine[x] - srcLine[x]);
1044  count[edgeType] ++;
1045  }
1046  srcLine += srcStride;
1047  orgLine += orgStride;
1048  }
1049  if(isCalculatePreDeblockSamples)
1050  {
1051  if(isBelowAvail)
1052  {
1053  startX = 0;
1054  endX = width;
1055 
1056  for(y=0; y<skipLinesB[typeIdx]; y++)
1057  {
1058  srcLineBelow = srcLine + srcStride;
1059  srcLineAbove = srcLine - srcStride;
1060 
1061  for (x=startX; x<endX; x++)
1062  {
1063  edgeType = sgn(srcLine[x] - srcLineBelow[x]) + sgn(srcLine[x] - srcLineAbove[x]);
1064  diff [edgeType] += (orgLine[x] - srcLine[x]);
1065  count[edgeType] ++;
1066  }
1067  srcLine += srcStride;
1068  orgLine += orgStride;
1069  }
1070  }
1071  }
1072 
1073  }
1074  break;
1075  case SAO_TYPE_EO_135:
1076  {
1077  diff +=2;
1078  count+=2;
1079  SChar *signUpLine, *signDownLine, *signTmpLine;
1080 
1081  signUpLine = m_signLineBuf1;
1082  signDownLine= m_signLineBuf2;
1083 
1084  startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1)
1085  : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1086  ;
1087 
1088  endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1))
1089  : (isRightAvail ? width : (width - 1))
1090  ;
1091  endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1092 
1093  //prepare 2nd line's upper sign
1094  Pel* srcLineBelow = srcLine + srcStride;
1095  for (x=startX; x<endX+1; x++)
1096  {
1097  signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x-1]);
1098  }
1099 
1100  //1st line
1101  Pel* srcLineAbove = srcLine - srcStride;
1102  firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0 : 1) : startX;
1103  firstLineEndX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? endX : 1) : endX;
1104  for(x=firstLineStartX; x<firstLineEndX; x++)
1105  {
1106  edgeType = sgn(srcLine[x] - srcLineAbove[x-1]) - signUpLine[x+1];
1107  diff [edgeType] += (orgLine[x] - srcLine[x]);
1108  count[edgeType] ++;
1109  }
1110  srcLine += srcStride;
1111  orgLine += orgStride;
1112 
1113 
1114  //middle lines
1115  for (y=1; y<endY; y++)
1116  {
1117  srcLineBelow = srcLine + srcStride;
1118 
1119  for (x=startX; x<endX; x++)
1120  {
1121  signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x+1]);
1122  edgeType = signDown + signUpLine[x];
1123  diff [edgeType] += (orgLine[x] - srcLine[x]);
1124  count[edgeType] ++;
1125 
1126  signDownLine[x+1] = -signDown;
1127  }
1128  signDownLine[startX] = (SChar)sgn(srcLineBelow[startX] - srcLine[startX-1]);
1129 
1130  signTmpLine = signUpLine;
1131  signUpLine = signDownLine;
1132  signDownLine = signTmpLine;
1133 
1134  srcLine += srcStride;
1135  orgLine += orgStride;
1136  }
1137  if(isCalculatePreDeblockSamples)
1138  {
1139  if(isBelowAvail)
1140  {
1141  startX = isLeftAvail ? 0 : 1 ;
1142  endX = isRightAvail ? width : (width -1);
1143 
1144  for(y=0; y<skipLinesB[typeIdx]; y++)
1145  {
1146  srcLineBelow = srcLine + srcStride;
1147  srcLineAbove = srcLine - srcStride;
1148 
1149  for (x=startX; x< endX; x++)
1150  {
1151  edgeType = sgn(srcLine[x] - srcLineBelow[x+1]) + sgn(srcLine[x] - srcLineAbove[x-1]);
1152  diff [edgeType] += (orgLine[x] - srcLine[x]);
1153  count[edgeType] ++;
1154  }
1155  srcLine += srcStride;
1156  orgLine += orgStride;
1157  }
1158  }
1159  }
1160  }
1161  break;
1162  case SAO_TYPE_EO_45:
1163  {
1164  diff +=2;
1165  count+=2;
1166  SChar *signUpLine = m_signLineBuf1+1;
1167 
1168  startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1)
1169  : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1170  ;
1171  endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1172  : (isRightAvail ? width : (width - 1))
1173  ;
1174  endY = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1175 
1176  //prepare 2nd line upper sign
1177  Pel* srcLineBelow = srcLine + srcStride;
1178  for (x=startX-1; x<endX; x++)
1179  {
1180  signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x+1]);
1181  }
1182 
1183 
1184  //first line
1185  Pel* srcLineAbove = srcLine - srcStride;
1186  firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX)
1187  : startX
1188  ;
1189  firstLineEndX = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX)
1190  : endX
1191  ;
1192  for(x=firstLineStartX; x<firstLineEndX; x++)
1193  {
1194  edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) - signUpLine[x-1];
1195  diff [edgeType] += (orgLine[x] - srcLine[x]);
1196  count[edgeType] ++;
1197  }
1198 
1199  srcLine += srcStride;
1200  orgLine += orgStride;
1201 
1202  //middle lines
1203  for (y=1; y<endY; y++)
1204  {
1205  srcLineBelow = srcLine + srcStride;
1206 
1207  for(x=startX; x<endX; x++)
1208  {
1209  signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x-1]);
1210  edgeType = signDown + signUpLine[x];
1211 
1212  diff [edgeType] += (orgLine[x] - srcLine[x]);
1213  count[edgeType] ++;
1214 
1215  signUpLine[x-1] = -signDown;
1216  }
1217  signUpLine[endX-1] = (SChar)sgn(srcLineBelow[endX-1] - srcLine[endX]);
1218  srcLine += srcStride;
1219  orgLine += orgStride;
1220  }
1221  if(isCalculatePreDeblockSamples)
1222  {
1223  if(isBelowAvail)
1224  {
1225  startX = isLeftAvail ? 0 : 1 ;
1226  endX = isRightAvail ? width : (width -1);
1227 
1228  for(y=0; y<skipLinesB[typeIdx]; y++)
1229  {
1230  srcLineBelow = srcLine + srcStride;
1231  srcLineAbove = srcLine - srcStride;
1232 
1233  for (x=startX; x<endX; x++)
1234  {
1235  edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + sgn(srcLine[x] - srcLineAbove[x+1]);
1236  diff [edgeType] += (orgLine[x] - srcLine[x]);
1237  count[edgeType] ++;
1238  }
1239  srcLine += srcStride;
1240  orgLine += orgStride;
1241  }
1242  }
1243  }
1244  }
1245  break;
1246  case SAO_TYPE_BO:
1247  {
1248  startX = (!isCalculatePreDeblockSamples)?0
1249  :( isRightAvail?(width- skipLinesR[typeIdx]):width)
1250  ;
1251  endX = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width )
1252  :width
1253  ;
1254  endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height;
1255  Int shiftBits = channelBitDepth - NUM_SAO_BO_CLASSES_LOG2;
1256  for (y=0; y< endY; y++)
1257  {
1258  for (x=startX; x< endX; x++)
1259  {
1260 
1261  Int bandIdx= srcLine[x] >> shiftBits;
1262  diff [bandIdx] += (orgLine[x] - srcLine[x]);
1263  count[bandIdx] ++;
1264  }
1265  srcLine += srcStride;
1266  orgLine += orgStride;
1267  }
1268  if(isCalculatePreDeblockSamples)
1269  {
1270  if(isBelowAvail)
1271  {
1272  startX = 0;
1273  endX = width;
1274 
1275  for(y= 0; y< skipLinesB[typeIdx]; y++)
1276  {
1277  for (x=startX; x< endX; x++)
1278  {
1279  Int bandIdx= srcLine[x] >> shiftBits;
1280  diff [bandIdx] += (orgLine[x] - srcLine[x]);
1281  count[bandIdx] ++;
1282  }
1283  srcLine += srcStride;
1284  orgLine += orgStride;
1285 
1286  }
1287 
1288  }
1289  }
1290  }
1291  break;
1292  default:
1293  {
1294  printf("Not a supported SAO types\n");
1295  assert(0);
1296  exit(-1);
1297  }
1298  }
1299  }
1300 }
1301 
1302 
#define NUM_SAO_BO_CLASSES_LOG2
Definition: TypeDef.h:574
Void init(TEncBinIf *p)
Definition: TEncSbac.h:72
Double xRoundIbdi(Int bitDepth, Double x)
Int64 estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift)
Void addPreDBFStatistics(SAOStatData ***blkStats)
Void deriveOffsets(ComponentID compIdx, const Int channelBitDepth, Int typeIdc, SAOStatData &statData, Int *quantOffsets, Int &typeAuxInfo)
Int estIterOffset(Int typeIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64 &bestDist, Double &bestCost, Int offsetTh)
#define MAX_NUM_SAO_CLASSES
Definition: TypeDef.h:757
Double xRoundIbdi2(Int bitDepth, Double x)
rounding with IBDI
Void extendPicBorder()
Definition: TComPicYuv.cpp:229
picture YUV buffer class
Definition: TComPicYuv.h:55
Int typeAuxInfo
Definition: TypeDef.h:763
picture class (symbol + YUV buffers)
Definition: TComPic.h:56
void Void
Definition: TypeDef.h:203
Int getStride(const ComponentID id) const
Definition: TComPicYuv.h:121
#define NULL
Definition: CommonDef.h:107
Int typeIdc
Definition: TypeDef.h:762
estimation part of sample adaptive offset class (header)
TComSlice * getSlice(Int i)
Definition: TComPic.h:113
static UInt getComponentScaleY(const ComponentID id, const ChromaFormat fmt)
Int offset[32]
Definition: TypeDef.h:764
Int64 getDistortion(const Int channelBitDepth, Int typeIdc, Int typeAuxInfo, Int *offsetVal, SAOStatData &statData)
unsigned int UInt
Definition: TypeDef.h:212
static UInt getComponentScaleX(const ComponentID id, const ChromaFormat fmt)
Short Pel
pixel type
Definition: TypeDef.h:249
Int sgn(T val)
Int getMergeList(TComPic *pic, Int ctuRsAddr, SAOBlkParam *blkParams, SAOBlkParam *mergeList[NUM_SAO_MERGE_TYPES])
Void invertQuantOffsets(ComponentID compIdx, Int typeIdc, Int typeAuxInfo, Int *dstOffsets, Int *srcOffsets)
Void initRDOCabacCoder(TEncSbac *pcRDGoOnSbacCoder, TComSlice *pcSlice)
Int recon[MAX_NUM_CHANNEL_TYPE]
the bit depth as indicated in the SPS
Definition: TypeDef.h:793
Void reconstructBlkSAOParam(SAOBlkParam &recParam, SAOBlkParam *mergeList[NUM_SAO_MERGE_TYPES])
Void SAOProcess(TComPic *pPic, Bool *sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool isPreDBFSamplesUsed, const Bool bResetStateAfterIRAP)
TComPicYuv * getPicYuvRec()
Definition: TComPic.h:120
Void offsetCTU(Int ctuRsAddr, TComPicYuv *srcYuv, TComPicYuv *resYuv, SAOBlkParam &saoblkParam, TComPic *pPic)
UInt m_offsetStepLog2[MAX_NUM_COMPONENT]
Void codeSAOBlkParam(SAOBlkParam &saoBlkParam, const BitDepths &bitDepths, Bool *sliceEnabled, Bool leftMergeAvail, Bool aboveMergeAvail, Bool onlyEstMergeInfo=false)
Definition: TEncSbac.cpp:1683
#define NUM_SAO_BO_CLASSES
Definition: TypeDef.h:575
Double m_lambda[MAX_NUM_COMPONENT]
signed char SChar
Definition: TypeDef.h:207
bool Bool
Definition: TypeDef.h:204
long long Int64
Definition: TypeDef.h:232
Void deriveModeMergeRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam *mergeList[NUM_SAO_MERGE_TYPES], Bool *sliceEnabled, SAOStatData ***blkStats, SAOBlkParam &modeParam, Double &modeNormCost, TEncSbac **cabacCoderRDO, Int inCabacLabel)
Double m_saoDisabledRate[MAX_NUM_COMPONENT][MAX_TLAYER]
Void codeSAOOffsetParam(ComponentID compIdx, SAOOffset &ctbParam, Bool sliceEnabled, const Int channelBitDepth)
Definition: TEncSbac.cpp:1605
TEncBinCABACCounter ** m_pppcBinCoderCABAC
Void copyToPic(TComPicYuv *pcPicYuvDst) const
Definition: TComPicYuv.cpp:198
static const Int MAX_INT
max. value of signed 32-bit integer
Definition: CommonDef.h:115
Void load(const TEncSbac *pSrc)
Definition: TEncSbac.cpp:396
static ChannelType toChannelType(const ComponentID id)
T Clip3(const T minVal, const T maxVal, const T a)
general min/max clip
Definition: CommonDef.h:252
TComPicYuv * getPicYuvOrg()
Definition: TComPic.h:119
Int getBitDepth(ChannelType type) const
Definition: TComSlice.h:894
SAOMode modeIdc
Definition: TypeDef.h:761
TComPicSym * getPicSym()
Definition: TComPic.h:111
Void getStatistics(SAOStatData ***blkStats, TComPicYuv *orgYuv, TComPicYuv *srcYuv, TComPic *pPic, Bool isCalculatePreDeblockSamples=false)
const BitDepths & getBitDepths() const
Definition: TComSlice.h:900
Void deriveModeNewRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam *mergeList[NUM_SAO_MERGE_TYPES], Bool *sliceEnabled, SAOStatData ***blkStats, SAOBlkParam &modeParam, Double &modeNormCost, TEncSbac **cabacCoderRDO, Int inCabacLabel)
UInt getNumberOfWrittenBits()
Definition: TEncSbac.h:85
Int getDepth() const
Definition: TComSlice.h:1376
ChromaFormat getChromaFormat() const
Definition: TComPic.h:139
Int getPOC() const
Definition: TComSlice.h:1354
Void decideBlkParams(TComPic *pic, Bool *sliceEnabled, SAOStatData ***blkStats, TComPicYuv *srcYuv, TComPicYuv *resYuv, SAOBlkParam *reconParams, SAOBlkParam *codedParams, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma)
const TComSPS & getSPS() const
Definition: TComPicSym.h:163
static const Int MAX_TLAYER
Explicit temporal layer QP offset - max number of temporal layer.
Definition: CommonDef.h:134
static Int getMaxOffsetQVal(const Int channelBitDepth)
Void resetEntropy(const TComSlice *pSlice)
Definition: TEncSbac.cpp:105
static const Double MAX_DOUBLE
max. value of Double-type value
Definition: CommonDef.h:116
Pel * getAddr(const ComponentID ch)
Definition: TComPicYuv.h:139
Void deriveLoopFilterBoundaryAvailibility(Int ctuRsAddr, Bool &isLeftAvail, Bool &isRightAvail, Bool &isAboveAvail, Bool &isBelowAvail, Bool &isAboveLeftAvail, Bool &isAboveRightAvail, Bool &isBelowLeftAvail, Bool &isBelowRightAvail)
Definition: TComPicSym.cpp:482
Void getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData *statsDataTypes, Pel *srcBlk, Pel *orgBlk, Int srcStride, Int orgStride, Int width, Int height, Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isCalculatePreDeblockSamples)
Void resetBits()
Definition: TEncSbac.h:84
#define DISTORTION_PRECISION_ADJUSTMENT(x)
Definition: TypeDef.h:164
Void store(TEncSbac *pDest) const
Definition: TEncSbac.cpp:415
Int m_skipLinesR[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES]
int Int
Definition: TypeDef.h:211
ComponentID
Definition: TypeDef.h:308
Void decidePicParams(Bool *sliceEnabled, const TComPic *pic, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool bResetStateAfterIRAP)
Int m_skipLinesB[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES]
SBAC encoder class.
Definition: TEncSbac.h:66
double Double
Definition: TypeDef.h:213
Void setBorderExtension(Bool b)
Definition: TComPicYuv.h:170
static UInt getNumberValidComponents(const ChromaFormat fmt)
Void createEncData(Bool isPreDBFSamplesUsed)
slice header class
Definition: TComSlice.h:1225
Bool isIRAP() const
Definition: TComSlice.h:1394
SAOBlkParam * getSAOBlkParam()
Definition: TComPicSym.h:186