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

Last change on this file since 1550 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
Line 
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-2016, 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
34/**
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
47
48//! rounding with IBDI
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
60TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
61{
62  m_pppcRDSbacCoder = NULL;
63  m_pcRDGoOnSbacCoder = NULL;
64  m_pppcBinCoderCABAC = NULL;
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];
79#if FAST_BIT_EST
80  m_pppcBinCoderCABAC = new TEncBinCABACCounter* [NUM_SAO_CABACSTATE_LABELS];
81#else
82  m_pppcBinCoderCABAC = new TEncBinCABAC* [NUM_SAO_CABACSTATE_LABELS];
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
89    m_pppcBinCoderCABAC[cs] = new TEncBinCABACCounter;
90#else
91    m_pppcBinCoderCABAC[cs] = new TEncBinCABAC;
92#endif
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  {
101    m_statData[i] = new SAOStatData*[MAX_NUM_COMPONENT];
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  {
109    m_preDBFstatData = new SAOStatData**[m_numCTUsPic];
110    for(Int i=0; i< m_numCTUsPic; i++)
111    {
112      m_preDBFstatData[i] = new SAOStatData*[MAX_NUM_COMPONENT];
113      for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++)
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));
122#if OPTIONAL_RESET_SAO_ENCODING_AFTER_IRAP
123  m_lastIRAPPoc = MAX_INT;
124#endif
125
126  for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
127  {
128    m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
129    m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
130
131    m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
132    m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
133
134    if(isPreDBFSamplesUsed)
135    {
136      switch(typeIdc)
137      {
138      case SAO_TYPE_EO_0:
139        {
140          m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
141          m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
142
143          m_skipLinesB[COMPONENT_Y ][typeIdc]= 3;
144          m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1;
145        }
146        break;
147      case SAO_TYPE_EO_90:
148        {
149          m_skipLinesR[COMPONENT_Y ][typeIdc]= 4;
150          m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2;
151
152          m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
153          m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
154        }
155        break;
156      case SAO_TYPE_EO_135:
157      case SAO_TYPE_EO_45:
158        {
159          m_skipLinesR[COMPONENT_Y ][typeIdc]= 5;
160          m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3;
161
162          m_skipLinesB[COMPONENT_Y ][typeIdc]= 4;
163          m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2;
164        }
165        break;
166      case SAO_TYPE_BO:
167        {
168          m_skipLinesR[COMPONENT_Y ][typeIdc]= 4;
169          m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2;
170
171          m_skipLinesB[COMPONENT_Y ][typeIdc]= 3;
172          m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1;
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    {
211      for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++)
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    {
223      for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++)
224      {
225        delete[] m_preDBFstatData[i][compIdx];
226      }
227      delete[] m_preDBFstatData[i];
228    }
229    delete[] m_preDBFstatData; m_preDBFstatData = NULL;
230  }
231}
232
233Void TEncSampleAdaptiveOffset::initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice)
234{
235  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
236  m_pcRDGoOnSbacCoder->resetEntropy(pcSlice);
237  m_pcRDGoOnSbacCoder->resetBits();
238
239  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[SAO_CABACSTATE_PIC_INIT]);
240}
241
242
243
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
247Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma, Bool isPreDBFSamplesUsed )
248#endif
249{
250  TComPicYuv* orgYuv= pPic->getPicYuvOrg();
251  TComPicYuv* resYuv= pPic->getPicYuvRec();
252  memcpy(m_lambda, lambdas, sizeof(m_lambda));
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  }
264
265  //slice on/off
266#if OPTIONAL_RESET_SAO_ENCODING_AFTER_IRAP
267  decidePicParams(sliceEnabled, pPic, saoEncodingRate, saoEncodingRateChroma, bResetStateAfterIRAP);
268#else
269  decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth(), saoEncodingRate, saoEncodingRateChroma);
270#endif
271
272  //block on/off
273  SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters
274  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam(), bTestSAODisableAtPictureLevel, saoEncodingRate, saoEncodingRateChroma);
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  {
287    for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++)
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
297Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic, Bool isCalculatePreDeblockSamples)
298{
299  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
300
301  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
302
303  for(Int ctuRsAddr= 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++)
304  {
305    Int yPos   = (ctuRsAddr / m_numCTUInWidth)*m_maxCUHeight;
306    Int xPos   = (ctuRsAddr % m_numCTUInWidth)*m_maxCUWidth;
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
310    pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctuRsAddr, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
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
321    for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
322    {
323      const ComponentID component = ComponentID(compIdx);
324
325      const UInt componentScaleX = getComponentScaleX(component, pPic->getChromaFormat());
326      const UInt componentScaleY = getComponentScaleY(component, pPic->getChromaFormat());
327
328      Int  srcStride  = srcYuv->getStride(component);
329      Pel* srcBlk     = srcYuv->getAddr(component) + ((yPos >> componentScaleY) * srcStride) + (xPos >> componentScaleX);
330
331      Int  orgStride  = orgYuv->getStride(component);
332      Pel* orgBlk     = orgYuv->getAddr(component) + ((yPos >> componentScaleY) * orgStride) + (xPos >> componentScaleX);
333
334      getBlkStats(component, pPic->getPicSym()->getSPS().getBitDepth(toChannelType(component)), blkStats[ctuRsAddr][component]
335                , srcBlk, orgBlk, srcStride, orgStride, (width  >> componentScaleX), (height >> componentScaleY)
336                , isLeftAvail,  isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail
337                , isCalculatePreDeblockSamples
338                );
339
340    }
341  }
342}
343
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
347Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer, const Double saoEncodingRate, const Double saoEncodingRateChroma)
348#endif
349{
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
369  //decide sliceEnabled[compIdx]
370  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
371  for (Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++)
372  {
373    sliceEnabled[compIdx] = false;
374  }
375
376  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
377  {
378    // reset flags & counters
379    sliceEnabled[compIdx] = true;
380
381    if (saoEncodingRate>0.0)
382    {
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      }
401    }
402  }
403}
404
405Int64 TEncSampleAdaptiveOffset::getDistortion(const Int channelBitDepth, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData)
406{
407  Int64 dist        = 0;
408  Int shift         = 2 * DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth - 8);
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);
420        }
421      }
422      break;
423    case SAO_TYPE_BO:
424      {
425        for (Int offsetIdx=typeAuxInfo; offsetIdx<typeAuxInfo+4; offsetIdx++)
426        {
427          Int bandIdx = offsetIdx % NUM_SAO_BO_CLASSES ;
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
449inline Int TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh )
450{
451  Int iterOffset, tempOffset;
452  Int64 tempDist, tempRate;
453  Double tempCost, tempMinCost;
454  Int offsetOutput = 0;
455  iterOffset = offsetInput;
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;
458  while (iterOffset != 0)
459  {
460    // Calculate the bits required for signaling the offset
461    tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
462    if (abs((Int)iterOffset)==offsetTh) //inclusive
463    {
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
482Void TEncSampleAdaptiveOffset::deriveOffsets(ComponentID compIdx, const Int channelBitDepth, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo)
483{
484  Int bitDepth = channelBitDepth;
485  Int shift    = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8);
486  Int offsetTh = TComSampleAdaptiveOffset::getMaxOffsetQVal(channelBitDepth);  //inclusive
487
488  ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
489
490  //derive initial offsets
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  {
494    if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN)  )
495    {
496      continue; //offset will be zero
497    }
498
499    if(statData.count[classIdx] == 0)
500    {
501      continue; //offset will be zero
502    }
503
504    quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8))
505                                                                  /
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;
521        for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++)
522        {
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          }
539
540          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
541          {
542            quantOffsets[classIdx] = estIterOffset( typeIdc, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh );
543          }
544        }
545
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++)
555        {
556          costBOClasses[classIdx]= m_lambda[compIdx];
557          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
558          {
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 );
560          }
561        }
562
563        //decide the starting band index
564        Double minCost = MAX_DOUBLE, cost;
565        for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++)
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);
581        for(Int i=0; i< 4; i++)
582        {
583          Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES;
584          clearQuantOffset[band] = quantOffsets[band];
585        }
586        ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES);
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
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)
602{
603  Double minCost, cost;
604  UInt previousWrittenBits;
605  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
606
607  Int64 dist[MAX_NUM_COMPONENT], modeDist[MAX_NUM_COMPONENT];
608  SAOOffset testOffset[MAX_NUM_COMPONENT];
609  Int invQuantOffset[MAX_NUM_SAO_CLASSES];
610  for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++)
611  {
612    modeDist[comp] = 0;
613  }
614
615  //pre-encode merge flags
616  modeParam[COMPONENT_Y].modeIdc = SAO_MODE_OFF;
617  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
618  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true);
619  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
620
621    //------ luma --------//
622  {
623    const ComponentID compIdx = COMPONENT_Y;
624    //"off" case as initial cost
625    modeParam[compIdx].modeIdc = SAO_MODE_OFF;
626    m_pcRDGoOnSbacCoder->resetBits();
627    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]);
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])
632    {
633      for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
634      {
635        testOffset[compIdx].modeIdc = SAO_MODE_NEW;
636        testOffset[compIdx].typeIdc = typeIdc;
637
638        //derive coded offset
639        deriveOffsets(compIdx, bitDepths.recon[CHANNEL_TYPE_LUMA], typeIdc, blkStats[ctuRsAddr][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
640
641        //inversed quantized offsets
642        invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
643
644        //get distortion
645        dist[compIdx] = getDistortion(bitDepths.recon[CHANNEL_TYPE_LUMA], testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][compIdx][typeIdc]);
646
647        //get rate
648        m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
649        m_pcRDGoOnSbacCoder->resetBits();
650        m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]);
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        }
660      }
661    }
662    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
663    m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
664  }
665
666  //------ chroma --------//
667//"off" case as initial cost
668  cost = 0;
669  previousWrittenBits = 0;
670  m_pcRDGoOnSbacCoder->resetBits();
671  for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
672  {
673    const ComponentID component = ComponentID(componentIndex);
674
675    modeParam[component].modeIdc = SAO_MODE_OFF;
676    modeDist [component]         = 0;
677    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, modeParam[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]);
678   
679    const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
680    cost += m_lambda[component] * (currentWrittenBits - previousWrittenBits);
681    previousWrittenBits = currentWrittenBits;
682  }
683
684  minCost = cost;
685
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  {
690    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
691    m_pcRDGoOnSbacCoder->resetBits();
692    previousWrittenBits = 0;
693    cost = 0;
694
695    for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
696    {
697      const ComponentID component = ComponentID(componentIndex);
698      if(!sliceEnabled[component])
699      {
700        testOffset[component].modeIdc = SAO_MODE_OFF;
701        dist[component]= 0;
702        continue;
703      }
704      testOffset[component].modeIdc = SAO_MODE_NEW;
705      testOffset[component].typeIdc = typeIdc;
706
707      //derive offset & get distortion
708      deriveOffsets(component, bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, blkStats[ctuRsAddr][component][typeIdc], testOffset[component].offset, testOffset[component].typeAuxInfo);
709      invertQuantOffsets(component, typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, testOffset[component].offset);
710      dist[component] = getDistortion(bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][component][typeIdc]);
711
712      m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, testOffset[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]);
713
714      const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
715      cost += dist[component] + (m_lambda[component] * (currentWrittenBits - previousWrittenBits));
716      previousWrittenBits = currentWrittenBits;
717    }
718
719    if(cost < minCost)
720    {
721      minCost = cost;
722      for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++)
723      {
724        modeDist[componentIndex]  = dist[componentIndex];
725        modeParam[componentIndex] = testOffset[componentIndex];
726      }
727    }
728
729  } // SAO_TYPE loop
730
731  //----- re-gen rate & normalized cost----//
732  modeNormCost = 0;
733  for(UInt componentIndex = COMPONENT_Y; componentIndex < numberOfComponents; componentIndex++)
734  {
735    modeNormCost += (Double)modeDist[componentIndex] / m_lambda[componentIndex];
736  }
737
738  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
739  m_pcRDGoOnSbacCoder->resetBits();
740  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
741  modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
742}
743
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)
745{
746  modeNormCost = MAX_DOUBLE;
747
748  Double cost;
749  SAOBlkParam testBlkParam;
750  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
751
752  for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++)
753  {
754    if(mergeList[mergeType] == NULL)
755    {
756      continue;
757    }
758
759    testBlkParam = *(mergeList[mergeType]);
760    //normalized distortion
761    Double normDist=0;
762    for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
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.
772        normDist += (((Double)getDistortion(bitDepths.recon[toChannelType(ComponentID(compIdx))], mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctuRsAddr][compIdx][mergedOffsetParam.typeIdc]))
773                       /m_lambda[compIdx]
774                    );
775      }
776
777    }
778
779    //rate
780    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
781    m_pcRDGoOnSbacCoder->resetBits();
782    m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
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
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)
801{
802  Bool allBlksDisabled = true;
803  const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC);
804  for(Int compId = COMPONENT_Y; compId < numberOfComponents; compId++)
805  {
806    if (sliceEnabled[compId])
807    {
808      allBlksDisabled = false;
809    }
810  }
811
812  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]);
813
814  SAOBlkParam modeParam;
815  Double minCost, modeCost;
816
817
818  Double totalCost = 0; // Used if bTestSAODisableAtPictureLevel==true
819
820  for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
821  {
822    if(allBlksDisabled)
823    {
824      codedParams[ctuRsAddr].reset();
825      continue;
826    }
827
828    m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]);
829
830    //get merge list
831    SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES] = { NULL };
832    getMergeList(pic, ctuRsAddr, reconParams, mergeList);
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        {
846          deriveModeNewRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
847
848        }
849        break;
850      case SAO_MODE_MERGE:
851        {
852          deriveModeMergeRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
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;
866        codedParams[ctuRsAddr] = modeParam;
867        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
868      }
869    } //mode
870
871    totalCost += minCost;
872
873    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
874
875    //apply reconstructed offsets
876    reconParams[ctuRsAddr] = codedParams[ctuRsAddr];
877    reconstructBlkSAOParam(reconParams[ctuRsAddr], mergeList);
878    offsetCTU(ctuRsAddr, srcYuv, resYuv, reconParams[ctuRsAddr], pic);
879  } //ctuRsAddr
880
881  if (!allBlksDisabled && (totalCost >= 0) && bTestSAODisableAtPictureLevel) //SAO has not beneficial in this case - disable it
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
896  if (saoEncodingRate > 0.0)
897  {
898    Int picTempLayer = pic->getSlice(0)->getDepth();
899    Int numCtusForSAOOff[MAX_NUM_COMPONENT];
900
901    for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
902    {
903      numCtusForSAOOff[compIdx] = 0;
904      for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
905      {
906        if( reconParams[ctuRsAddr][compIdx].modeIdc == SAO_MODE_OFF)
907        {
908          numCtusForSAOOff[compIdx]++;
909        }
910      }
911    }
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    }
923  }
924}
925
926
927Void TEncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData* statsDataTypes
928                        , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height
929                        , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail
930                        , Bool isCalculatePreDeblockSamples
931                        )
932{
933  if(m_lineBufWidth != m_maxCUWidth)
934  {
935    m_lineBufWidth = m_maxCUWidth;
936
937    if (m_signLineBuf1)
938    {
939      delete[] m_signLineBuf1;
940      m_signLineBuf1 = NULL;
941    }
942    m_signLineBuf1 = new SChar[m_lineBufWidth+1];
943
944    if (m_signLineBuf2)
945    {
946      delete[] m_signLineBuf2;
947      m_signLineBuf2 = NULL;
948    }
949    m_signLineBuf2 = new SChar[m_lineBufWidth+1];
950  }
951
952  Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;
953  SChar signLeft, signRight, signDown;
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        {
983          signLeft = (SChar)sgn(srcLine[startX] - srcLine[startX-1]);
984          for (x=startX; x<endX; x++)
985          {
986            signRight =  (SChar)sgn(srcLine[x] - srcLine[x+1]);
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            {
1005              signLeft = (SChar)sgn(srcLine[startX] - srcLine[startX-1]);
1006              for (x=startX; x<endX; x++)
1007              {
1008                signRight =  (SChar)sgn(srcLine[x] - srcLine[x+1]);
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;
1026        SChar *signUpLine = m_signLineBuf1;
1027
1028        startX = (!isCalculatePreDeblockSamples) ? 0
1029                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
1030                                                 ;
1031        startY = isAboveAvail ? 0 : 1;
1032        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
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;
1043        for (x=startX; x<endX; x++)
1044        {
1045          signUpLine[x] = (SChar)sgn(srcLine[x] - srcLineAbove[x]);
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          {
1055            signDown  = (SChar)sgn(srcLine[x] - srcLineBelow[x]);
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              {
1079                edgeType = sgn(srcLine[x] - srcLineBelow[x]) + sgn(srcLine[x] - srcLineAbove[x]);
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;
1095        SChar *signUpLine, *signDownLine, *signTmpLine;
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        {
1113          signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x-1]);
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        {
1122          edgeType = sgn(srcLine[x] - srcLineAbove[x-1]) - signUpLine[x+1];
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          {
1137            signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x+1]);
1138            edgeType = signDown + signUpLine[x];
1139            diff [edgeType] += (orgLine[x] - srcLine[x]);
1140            count[edgeType] ++;
1141
1142            signDownLine[x+1] = -signDown;
1143          }
1144          signDownLine[startX] = (SChar)sgn(srcLineBelow[startX] - srcLine[startX-1]);
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              {
1167                edgeType = sgn(srcLine[x] - srcLineBelow[x+1]) + sgn(srcLine[x] - srcLineAbove[x-1]);
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;
1182        SChar *signUpLine = m_signLineBuf1+1;
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        {
1196          signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x+1]);
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        {
1210          edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) - signUpLine[x-1];
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          {
1225            signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x-1]);
1226            edgeType = signDown + signUpLine[x];
1227
1228            diff [edgeType] += (orgLine[x] - srcLine[x]);
1229            count[edgeType] ++;
1230
1231            signUpLine[x-1] = -signDown;
1232          }
1233          signUpLine[endX-1] = (SChar)sgn(srcLineBelow[endX-1] - srcLine[endX]);
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              {
1251                edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + sgn(srcLine[x] - srcLineAbove[x+1]);
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;
1271        Int shiftBits = channelBitDepth - NUM_SAO_BO_CLASSES_LOG2;
1272        for (y=0; y< endY; y++)
1273        {
1274          for (x=startX; x< endX; x++)
1275          {
1276
1277            Int bandIdx= srcLine[x] >> shiftBits;
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              {
1295                Int bandIdx= srcLine[x] >> shiftBits;
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
1318
1319//! \}
Note: See TracBrowser for help on using the repository browser.