source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1590

Last change on this file since 1590 was 1549, checked in by seregin, 9 years ago

port rev 4732, update copyright notice to include 2016

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