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

Last change on this file since 1335 was 1332, checked in by seregin, 9 years ago

port rev 4410

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