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

Last change on this file since 1263 was 1260, checked in by seregin, 9 years ago

port rev 4257

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