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

Last change on this file since 1557 was 532, checked in by seregin, 11 years ago

update to HM-12.1 base

  • Property svn:eol-style set to native
File size: 115.6 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-2013, 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#if HM_CLEANUP_SAO
49
50/** rounding with IBDI
51 * \param  x
52 */
53inline Double xRoundIbdi2(Int bitDepth, Double x)
54{
55  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))));
56}
57
58inline Double xRoundIbdi(Int bitDepth, Double x)
59{
60  return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
61}
62
63
64TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
65{
66  m_pppcRDSbacCoder = NULL;           
67  m_pcRDGoOnSbacCoder = NULL;
68  m_pppcBinCoderCABAC = NULL;   
69  m_statData = NULL;
70#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
71  m_preDBFstatData = NULL;
72#endif
73}
74
75TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
76{
77  destroyEncData();
78}
79
80#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
81Void TEncSampleAdaptiveOffset::createEncData(Bool isPreDBFSamplesUsed)
82#else
83Void TEncSampleAdaptiveOffset::createEncData()
84#endif
85{
86
87  //cabac coder for RDO
88  m_pppcRDSbacCoder = new TEncSbac* [NUM_SAO_CABACSTATE_LABELS];
89  m_pppcBinCoderCABAC = new TEncBinCABACCounter* [NUM_SAO_CABACSTATE_LABELS];
90
91  for(Int cs=0; cs < NUM_SAO_CABACSTATE_LABELS; cs++)
92  {
93    m_pppcRDSbacCoder[cs] = new TEncSbac;
94    m_pppcBinCoderCABAC[cs] = new TEncBinCABACCounter;
95    m_pppcRDSbacCoder   [cs]->init( m_pppcBinCoderCABAC [cs] );
96  }
97
98
99  //statistics
100  m_statData = new SAOStatData**[m_numCTUsPic];
101  for(Int i=0; i< m_numCTUsPic; i++)
102  {
103    m_statData[i] = new SAOStatData*[NUM_SAO_COMPONENTS];
104    for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
105    {
106      m_statData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES];
107    }
108  }
109#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
110  if(isPreDBFSamplesUsed)
111  {
112    m_preDBFstatData = new SAOStatData**[m_numCTUsPic];
113    for(Int i=0; i< m_numCTUsPic; i++)
114    {
115      m_preDBFstatData[i] = new SAOStatData*[NUM_SAO_COMPONENTS];
116      for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
117      {
118        m_preDBFstatData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES];
119      }
120    }
121
122  }
123#endif
124
125#if SAO_ENCODING_CHOICE
126  ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate));
127#endif
128
129  for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
130  {
131    m_skipLinesR[SAO_Y ][typeIdc]= 5;
132    m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
133
134    m_skipLinesB[SAO_Y ][typeIdc]= 4;
135    m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
136
137#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
138    if(isPreDBFSamplesUsed)
139    {
140      switch(typeIdc)
141      {
142      case SAO_TYPE_EO_0:
143        {
144          m_skipLinesR[SAO_Y ][typeIdc]= 5;
145          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
146
147          m_skipLinesB[SAO_Y ][typeIdc]= 3;
148          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1;
149        }
150        break;
151      case SAO_TYPE_EO_90:
152        {
153          m_skipLinesR[SAO_Y ][typeIdc]= 4;
154          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2;
155
156          m_skipLinesB[SAO_Y ][typeIdc]= 4;
157          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
158        }
159        break;
160      case SAO_TYPE_EO_135:
161      case SAO_TYPE_EO_45:
162        {
163          m_skipLinesR[SAO_Y ][typeIdc]= 5;
164          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
165
166          m_skipLinesB[SAO_Y ][typeIdc]= 4;
167          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
168        }
169        break;
170      case SAO_TYPE_BO:
171        {
172          m_skipLinesR[SAO_Y ][typeIdc]= 4;
173          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2;
174
175          m_skipLinesB[SAO_Y ][typeIdc]= 3;
176          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1;
177        }
178        break;
179      default:
180        {
181          printf("Not a supported type");
182          assert(0);
183          exit(-1);
184        }
185      }
186    }
187#endif   
188  }
189
190}
191
192Void TEncSampleAdaptiveOffset::destroyEncData()
193{
194  if(m_pppcRDSbacCoder != NULL)
195  {
196    for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
197    {
198      delete m_pppcRDSbacCoder[cs];
199    }
200    delete[] m_pppcRDSbacCoder; m_pppcRDSbacCoder = NULL;
201  }
202
203  if(m_pppcBinCoderCABAC != NULL)
204  {
205    for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
206    {
207      delete m_pppcBinCoderCABAC[cs];
208    }
209    delete[] m_pppcBinCoderCABAC; m_pppcBinCoderCABAC = NULL;
210  }
211
212  if(m_statData != NULL)
213  {
214    for(Int i=0; i< m_numCTUsPic; i++)
215    {
216      for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
217      {
218        delete[] m_statData[i][compIdx];
219      }
220      delete[] m_statData[i];
221    }
222    delete[] m_statData; m_statData = NULL;
223  }
224#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
225  if(m_preDBFstatData != NULL)
226  {
227    for(Int i=0; i< m_numCTUsPic; i++)
228    {
229      for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
230      {
231        delete[] m_preDBFstatData[i][compIdx];
232      }
233      delete[] m_preDBFstatData[i];
234    }
235    delete[] m_preDBFstatData; m_preDBFstatData = NULL;
236  }
237
238#endif
239}
240
241Void TEncSampleAdaptiveOffset::initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice) 
242{
243  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
244  m_pcRDGoOnSbacCoder->setSlice(pcSlice);
245  m_pcRDGoOnSbacCoder->resetEntropy();
246  m_pcRDGoOnSbacCoder->resetBits();
247
248  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[SAO_CABACSTATE_PIC_INIT]);
249}
250
251
252
253Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas
254#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
255                                         , Bool isPreDBFSamplesUsed
256#endif
257                                          )
258{
259  TComPicYuv* orgYuv= pPic->getPicYuvOrg();
260  TComPicYuv* resYuv= pPic->getPicYuvRec();
261  m_labmda[SAO_Y]= lambdas[0]; m_labmda[SAO_Cb]= lambdas[1]; m_labmda[SAO_Cr]= lambdas[2];
262  TComPicYuv* srcYuv = m_tempPicYuv;
263  resYuv->copyToPic(srcYuv);
264  srcYuv->setBorderExtension(false);
265  srcYuv->extendPicBorder();
266
267  //collect statistics
268  getStatistics(m_statData, orgYuv, srcYuv, pPic);
269#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
270  if(isPreDBFSamplesUsed)
271  {
272    addPreDBFStatistics(m_statData);
273  }
274#endif
275  //slice on/off
276  decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth()); 
277
278  //block on/off
279  SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters
280  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam());
281  delete[] reconParams;
282
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 < NUM_SAO_COMPONENTS; 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  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
316  {
317    Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
318    Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
319    Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
320    Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
321
322    pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
323
324    //NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities.
325    //For simplicity, here only picture boundaries are considered.
326
327    isRightAvail      = (xPos + m_maxCUWidth  < m_picWidth );
328    isBelowAvail      = (yPos + m_maxCUHeight < m_picHeight);
329    isBelowRightAvail = (isRightAvail && isBelowAvail);
330    isBelowLeftAvail  = ((xPos > 0) && (isBelowAvail));
331    isAboveRightAvail = ((yPos > 0) && (isRightAvail));
332
333    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
334    {
335      Bool isLuma     = (compIdx == SAO_Y);
336      Int  formatShift= isLuma?0:1;
337
338      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
339      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
340
341      Int  orgStride  = isLuma?orgYuv->getStride():orgYuv->getCStride();
342      Pel* orgBlk     = getPicBuf(orgYuv, compIdx)+ (yPos >> formatShift)*orgStride+ (xPos >> formatShift);
343
344      getBlkStats(compIdx, blkStats[ctu][compIdx] 
345                , srcBlk, orgBlk, srcStride, orgStride, (width  >> formatShift), (height >> formatShift)
346                , isLeftAvail,  isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail, isBelowLeftAvail, isBelowRightAvail
347#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
348                , isCalculatePreDeblockSamples
349#endif
350                );
351
352    }
353  }
354}
355
356Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer)
357{
358  //decide sliceEnabled[compIdx]
359  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
360  {
361    // reset flags & counters
362    sliceEnabled[compIdx] = true;
363
364#if SAO_ENCODING_CHOICE
365#if SAO_ENCODING_CHOICE_CHROMA
366    // decide slice-level on/off based on previous results
367    if( (picTempLayer > 0) 
368      && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==SAO_Y) ? SAO_ENCODING_RATE : SAO_ENCODING_RATE_CHROMA)) )
369    {
370      sliceEnabled[compIdx] = false;
371    }
372#else
373    // decide slice-level on/off based on previous results
374    if( (picTempLayer > 0) 
375      && (m_saoDisabledRate[SAO_Y][0] > SAO_ENCODING_RATE) )
376    {
377      sliceEnabled[compIdx] = false;
378    }
379#endif
380#endif
381  }
382}
383
384Int64 TEncSampleAdaptiveOffset::getDistortion(Int ctu, Int compIdx, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData)
385{
386  Int64 dist=0;
387  Int inputBitDepth    = (compIdx == SAO_Y) ? g_bitDepthY : g_bitDepthC ;
388  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(inputBitDepth-8);
389
390  switch(typeIdc)
391  {
392    case SAO_TYPE_EO_0:
393    case SAO_TYPE_EO_90:
394    case SAO_TYPE_EO_135:
395    case SAO_TYPE_EO_45:
396      {
397        for (Int offsetIdx=0; offsetIdx<NUM_SAO_EO_CLASSES; offsetIdx++)
398        {
399          dist += estSaoDist( statData.count[offsetIdx], invQuantOffset[offsetIdx], statData.diff[offsetIdx], shift);
400        }       
401      }
402      break;
403    case SAO_TYPE_BO:
404      {
405        for (Int offsetIdx=typeAuxInfo; offsetIdx<typeAuxInfo+4; offsetIdx++)
406        {
407          Int bandIdx = offsetIdx % NUM_SAO_BO_CLASSES ; 
408          dist += estSaoDist( statData.count[bandIdx], invQuantOffset[bandIdx], statData.diff[bandIdx], shift);
409        }
410      }
411      break;
412    default:
413      {
414        printf("Not a supported type");
415        assert(0);
416        exit(-1);
417      }
418  }
419
420  return dist;
421}
422
423inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift)
424{
425  return (( count*offset*offset-diffSum*offset*2 ) >> shift);
426}
427
428
429inline 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 )
430{
431  Int iterOffset, tempOffset;
432  Int64 tempDist, tempRate;
433  Double tempCost, tempMinCost;
434  Int offsetOutput = 0;
435  iterOffset = offsetInput;
436  // 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.
437  tempMinCost = lambda; 
438  while (iterOffset != 0)
439  {
440    // Calculate the bits required for signaling the offset
441    tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1); 
442    if (abs((Int)iterOffset)==offsetTh) //inclusive
443    { 
444      tempRate --;
445    }
446    // Do the dequantization before distortion calculation
447    tempOffset  = iterOffset << bitIncrease;
448    tempDist    = estSaoDist( count, tempOffset, diffSum, shift);
449    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
450    if(tempCost < tempMinCost)
451    {
452      tempMinCost = tempCost;
453      offsetOutput = iterOffset;
454      bestDist = tempDist;
455      bestCost = tempCost;
456    }
457    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
458  }
459  return offsetOutput;
460}
461
462
463Void TEncSampleAdaptiveOffset::deriveOffsets(Int ctu, Int compIdx, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo)
464{
465  Int bitDepth = (compIdx== SAO_Y) ? g_bitDepthY : g_bitDepthC;
466  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8);
467  Int offsetTh = g_saoMaxOffsetQVal[compIdx];  //inclusive
468
469  ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
470
471  //derive initial offsets
472  Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES);
473  for(Int classIdx=0; classIdx< numClasses; classIdx++)
474  {
475    if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN)  ) 
476    {
477      continue; //offset will be zero
478    }
479
480    if(statData.count[classIdx] == 0)
481    {
482      continue; //offset will be zero
483    }
484
485    quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8)) 
486                                                                  / 
487                                                          (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx])
488                                               );
489    quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]);
490  }
491
492  // adjust offsets
493  switch(typeIdc)
494  {
495    case SAO_TYPE_EO_0:
496    case SAO_TYPE_EO_90:
497    case SAO_TYPE_EO_135:
498    case SAO_TYPE_EO_45:
499      {
500        Int64 classDist;
501        Double classCost;
502        for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++) 
503        {         
504          if(classIdx==SAO_CLASS_EO_FULL_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
505          if(classIdx==SAO_CLASS_EO_HALF_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
506          if(classIdx==SAO_CLASS_EO_HALF_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
507          if(classIdx==SAO_CLASS_EO_FULL_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
508
509          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
510          {
511            quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh );
512          }
513        }
514     
515        typeAuxInfo =0;
516      }
517      break;
518    case SAO_TYPE_BO:
519      {
520        Int64  distBOClasses[NUM_SAO_BO_CLASSES];
521        Double costBOClasses[NUM_SAO_BO_CLASSES];
522        ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES);
523        for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++)
524        {         
525          costBOClasses[classIdx]= m_labmda[compIdx];
526          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
527          {
528            quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], distBOClasses[classIdx], costBOClasses[classIdx], offsetTh );
529          }
530        }
531
532        //decide the starting band index
533        Double minCost = MAX_DOUBLE, cost;
534        for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++) 
535        {
536          cost  = costBOClasses[band  ];
537          cost += costBOClasses[band+1];
538          cost += costBOClasses[band+2];
539          cost += costBOClasses[band+3];
540
541          if(cost < minCost)
542          {
543            minCost = cost;
544            typeAuxInfo = band;
545          }
546        }
547        //clear those unused classes
548        Int clearQuantOffset[NUM_SAO_BO_CLASSES];
549        ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES);
550        for(Int i=0; i< 4; i++) 
551        {
552          Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES;
553          clearQuantOffset[band] = quantOffsets[band];
554        }
555        ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES);       
556      }
557      break;
558    default:
559      {
560        printf("Not a supported type");
561        assert(0);
562        exit(-1);
563      }
564
565  }
566
567
568}
569
570
571Void TEncSampleAdaptiveOffset::deriveModeNewRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
572{
573  Double minCost, cost;
574  Int rate, minRate;
575  Int64 dist[NUM_SAO_COMPONENTS], modeDist[NUM_SAO_COMPONENTS];
576  SAOOffset testOffset[NUM_SAO_COMPONENTS];
577  Int compIdx;
578  Int invQuantOffset[MAX_NUM_SAO_CLASSES];
579
580  modeDist[SAO_Y]= modeDist[SAO_Cb] = modeDist[SAO_Cr] = 0;
581
582  //pre-encode merge flags
583  modeParam[SAO_Y ].modeIdc = SAO_MODE_OFF;
584  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
585  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true);
586  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
587
588  //------ luma --------//
589  compIdx = SAO_Y;
590  //"off" case as initial cost
591  modeParam[compIdx].modeIdc = SAO_MODE_OFF;
592  m_pcRDGoOnSbacCoder->resetBits();
593  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx]);
594  minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
595  modeDist[compIdx] = 0;
596  minCost= m_labmda[compIdx]*((Double)minRate);
597  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
598  if(sliceEnabled[compIdx])
599  {
600    for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
601    {
602      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
603      testOffset[compIdx].typeIdc = typeIdc;
604
605      //derive coded offset
606      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
607
608      //inversed quantized offsets
609      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
610
611      //get distortion
612      dist[compIdx] = getDistortion(ctu, compIdx, testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
613
614      //get rate
615      m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
616      m_pcRDGoOnSbacCoder->resetBits();
617      m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx]);
618      rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
619      cost = (Double)dist[compIdx] + m_labmda[compIdx]*((Double)rate);
620      if(cost < minCost)
621      {
622        minCost = cost;
623        minRate = rate;
624        modeDist[compIdx] = dist[compIdx];
625        modeParam[compIdx]= testOffset[compIdx];
626        m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
627      }
628    }
629  }
630  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
631  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
632
633  //------ chroma --------//
634  assert(m_labmda[SAO_Cb] == m_labmda[SAO_Cr]);
635  Double chromaLambda = m_labmda[SAO_Cb];
636  //"off" case as initial cost
637  m_pcRDGoOnSbacCoder->resetBits();
638  modeParam[SAO_Cb].modeIdc = SAO_MODE_OFF; 
639  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, modeParam[SAO_Cb], sliceEnabled[SAO_Cb]);
640  modeParam[SAO_Cr].modeIdc = SAO_MODE_OFF; 
641  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, modeParam[SAO_Cr], sliceEnabled[SAO_Cr]);
642  minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
643  modeDist[SAO_Cb] = modeDist[SAO_Cr]= 0;
644  minCost= chromaLambda*((Double)minRate); 
645
646  //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function
647
648  for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
649  {
650    for(compIdx= SAO_Cb; compIdx< NUM_SAO_COMPONENTS; compIdx++)
651    {
652      if(!sliceEnabled[compIdx])
653      {
654        testOffset[compIdx].modeIdc = SAO_MODE_OFF;
655        dist[compIdx]= 0;
656        continue;
657      }
658      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
659      testOffset[compIdx].typeIdc = typeIdc;
660
661      //derive offset & get distortion
662      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
663      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
664      dist[compIdx]= getDistortion(ctu, compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
665    }
666
667    //get rate
668    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
669    m_pcRDGoOnSbacCoder->resetBits();
670    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, testOffset[SAO_Cb], sliceEnabled[SAO_Cb]);
671    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, testOffset[SAO_Cr], sliceEnabled[SAO_Cr]);
672    rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
673
674    cost = (Double)(dist[SAO_Cb]+ dist[SAO_Cr]) + chromaLambda*((Double)rate);
675    if(cost < minCost)
676    {
677      minCost = cost;
678      minRate = rate;
679      modeDist[SAO_Cb] = dist[SAO_Cb];
680      modeDist[SAO_Cr] = dist[SAO_Cr];
681      modeParam[SAO_Cb]= testOffset[SAO_Cb];
682      modeParam[SAO_Cr]= testOffset[SAO_Cr];
683    }
684  }
685
686
687  //----- re-gen rate & normalized cost----//
688  modeNormCost  = (Double)modeDist[SAO_Y]/m_labmda[SAO_Y];
689  modeNormCost += (Double)(modeDist[SAO_Cb]+ modeDist[SAO_Cr])/chromaLambda; 
690  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
691  m_pcRDGoOnSbacCoder->resetBits();
692  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
693  modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
694
695}
696
697Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
698{
699  Int mergeListSize = (Int)mergeList.size();
700  modeNormCost = MAX_DOUBLE;
701
702  Double cost;
703  SAOBlkParam testBlkParam;
704
705  for(Int mergeType=0; mergeType< mergeListSize; mergeType++)
706  {
707    if(mergeList[mergeType] == NULL)
708    {
709      continue;
710    }
711
712    testBlkParam = *(mergeList[mergeType]);
713    //normalized distortion
714    Double normDist=0;
715    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
716    {
717      testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE;
718      testBlkParam[compIdx].typeIdc = mergeType;
719
720      SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx];
721
722      if( mergedOffsetParam.modeIdc != SAO_MODE_OFF)
723      {
724        //offsets have been reconstructed. Don't call inversed quantization function.
725        normDist += (((Double)getDistortion(ctu, compIdx, mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctu][compIdx][mergedOffsetParam.typeIdc]))
726                       /m_labmda[compIdx]
727                    );
728      }
729
730    }
731
732    //rate
733    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
734    m_pcRDGoOnSbacCoder->resetBits();
735    m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
736    Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
737
738    cost = normDist+(Double)rate;
739
740    if(cost < modeNormCost)
741    {
742      modeNormCost = cost;
743      modeParam    = testBlkParam;
744      m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
745    }
746  }
747
748  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
749
750
751}
752
753Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams)
754{
755  Bool isAllBlksDisabled = false;
756  if(!sliceEnabled[SAO_Y] && !sliceEnabled[SAO_Cb] && !sliceEnabled[SAO_Cr])
757  {
758    isAllBlksDisabled = true;
759  }
760
761  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]);
762
763  SAOBlkParam modeParam;
764  Double minCost, modeCost;
765
766  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
767  {
768    if(isAllBlksDisabled)
769    {
770      codedParams[ctu].reset();
771      continue;
772    }
773
774    m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]);
775
776    //get merge list
777    std::vector<SAOBlkParam*> mergeList;
778    getMergeList(pic, ctu, reconParams, mergeList);
779
780    minCost = MAX_DOUBLE;
781    for(Int mode=0; mode < NUM_SAO_MODES; mode++)
782    {
783      switch(mode)
784      {
785      case SAO_MODE_OFF:
786        {
787          continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case.
788        }
789        break;
790      case SAO_MODE_NEW:
791        {
792          deriveModeNewRDO(ctu, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
793
794        }
795        break;
796      case SAO_MODE_MERGE:
797        {
798          deriveModeMergeRDO(ctu, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
799        }
800        break;
801      default:
802        {
803          printf("Not a supported SAO mode\n");
804          assert(0);
805          exit(-1);
806        }
807      }
808
809      if(modeCost < minCost)
810      {
811        minCost = modeCost;
812        codedParams[ctu] = modeParam;
813        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
814
815      }
816    } //mode
817    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
818
819    //apply reconstructed offsets
820    reconParams[ctu] = codedParams[ctu];
821    reconstructBlkSAOParam(reconParams[ctu], mergeList);
822    offsetCTU(ctu, srcYuv, resYuv, reconParams[ctu], pic);
823  } //ctu
824
825#if SAO_ENCODING_CHOICE
826  Int picTempLayer = pic->getSlice(0)->getDepth();
827  Int numLcusForSAOOff[NUM_SAO_COMPONENTS];
828  numLcusForSAOOff[SAO_Y ] = numLcusForSAOOff[SAO_Cb]= numLcusForSAOOff[SAO_Cr]= 0;
829
830  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
831  {
832    for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
833    {
834      if( reconParams[ctu][compIdx].modeIdc == SAO_MODE_OFF)
835      {
836        numLcusForSAOOff[compIdx]++;
837      }
838    }
839  }
840#if SAO_ENCODING_CHOICE_CHROMA
841  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
842  {
843    m_saoDisabledRate[compIdx][picTempLayer] = (Double)numLcusForSAOOff[compIdx]/(Double)m_numCTUsPic;
844  }
845#else
846  if (picTempLayer == 0)
847  {
848    m_saoDisabledRate[SAO_Y][0] = (Double)(numLcusForSAOOff[SAO_Y]+numLcusForSAOOff[SAO_Cb]+numLcusForSAOOff[SAO_Cr])/(Double)(m_numCTUsPic*3);
849  }
850#endif                                             
851#endif
852}
853
854
855Void TEncSampleAdaptiveOffset::getBlkStats(Int compIdx, SAOStatData* statsDataTypes 
856                        , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height
857                        , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail
858#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
859                        , Bool isCalculatePreDeblockSamples
860#endif
861                        )
862{
863  if(m_lineBufWidth != m_maxCUWidth)
864  {
865    m_lineBufWidth = m_maxCUWidth;
866
867    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
868    m_signLineBuf1 = new Char[m_lineBufWidth+1]; 
869
870    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
871    m_signLineBuf2 = new Char[m_lineBufWidth+1];
872  }
873
874  Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;
875  Char signLeft, signRight, signDown;
876  Int64 *diff, *count;
877  Pel *srcLine, *orgLine;
878  Int* skipLinesR = m_skipLinesR[compIdx];
879  Int* skipLinesB = m_skipLinesB[compIdx];
880
881  for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++)
882  {
883    SAOStatData& statsData= statsDataTypes[typeIdx];
884    statsData.reset();
885
886    srcLine = srcBlk;
887    orgLine = orgBlk;
888    diff    = statsData.diff;
889    count   = statsData.count;
890    switch(typeIdx)
891    {
892    case SAO_TYPE_EO_0:
893      {
894        diff +=2;
895        count+=2;
896        endY   = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height;
897#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
898        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
899                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
900                                                 ;
901#else
902        startX = isLeftAvail ? 0 : 1;
903#endif
904#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
905        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
906                                                 : (isRightAvail ? width : (width - 1))
907                                                 ;
908#else
909        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
910#endif
911        for (y=0; y<endY; y++)
912        {
913          signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
914          for (x=startX; x<endX; x++)
915          {
916            signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
917            edgeType  =  signRight + signLeft;
918            signLeft  = -signRight;
919
920            diff [edgeType] += (orgLine[x] - srcLine[x]);
921            count[edgeType] ++;
922          }
923          srcLine  += srcStride;
924          orgLine  += orgStride;
925        }
926#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
927        if(isCalculatePreDeblockSamples)
928        {
929          if(isBelowAvail)
930          {
931            startX = isLeftAvail  ? 0 : 1;
932            endX   = isRightAvail ? width : (width -1);
933
934            for(y=0; y<skipLinesB[typeIdx]; y++)
935            {
936              signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
937              for (x=startX; x<endX; x++)
938              {
939                signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
940                edgeType  =  signRight + signLeft;
941                signLeft  = -signRight;
942
943                diff [edgeType] += (orgLine[x] - srcLine[x]);
944                count[edgeType] ++;
945              }
946              srcLine  += srcStride;
947              orgLine  += orgStride;
948            }
949          }
950        }
951#endif
952      }
953      break;
954    case SAO_TYPE_EO_90:
955      {
956        diff +=2;
957        count+=2;
958        Char *signUpLine = m_signLineBuf1;
959
960#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
961        startX = (!isCalculatePreDeblockSamples) ? 0
962                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
963                                                 ;
964#endif
965        startY = isAboveAvail ? 0 : 1;
966#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
967        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width) 
968                                                 : width
969                                                 ;
970#else
971        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : width ;
972#endif
973        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
974        if (!isAboveAvail)
975        {
976          srcLine += srcStride;
977          orgLine += orgStride;
978        }
979
980        Pel* srcLineAbove = srcLine - srcStride;
981#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
982        for (x=startX; x<endX; x++) 
983#else
984        for (x=0; x< endX; x++) 
985#endif
986        {
987          signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
988        }
989
990        Pel* srcLineBelow;
991        for (y=startY; y<endY; y++)
992        {
993          srcLineBelow = srcLine + srcStride;
994
995#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
996          for (x=startX; x<endX; x++)
997#else
998          for (x=0; x<endX; x++)
999#endif
1000          {
1001            signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
1002            edgeType  = signDown + signUpLine[x];
1003            signUpLine[x]= -signDown;
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 = 0;
1017            endX   = width;
1018
1019            for(y=0; y<skipLinesB[typeIdx]; y++)
1020            {
1021              srcLineBelow = srcLine + srcStride;
1022              srcLineAbove = srcLine - srcStride;
1023
1024              for (x=startX; x<endX; x++)
1025              {
1026                edgeType = m_sign[srcLine[x] - srcLineBelow[x]] + m_sign[srcLine[x] - srcLineAbove[x]];
1027                diff [edgeType] += (orgLine[x] - srcLine[x]);
1028                count[edgeType] ++;
1029              }
1030              srcLine  += srcStride;
1031              orgLine  += orgStride;
1032            }
1033          }
1034        }
1035#endif
1036
1037      }
1038      break;
1039    case SAO_TYPE_EO_135:
1040      {
1041        diff +=2;
1042        count+=2;
1043        Char *signUpLine, *signDownLine, *signTmpLine;
1044
1045        signUpLine  = m_signLineBuf1;
1046        signDownLine= m_signLineBuf2;
1047
1048#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1049        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1050                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1051                                                 ;
1052#else
1053        startX = isLeftAvail ? 0 : 1 ;
1054#endif
1055
1056#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1057        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1))
1058                                                 : (isRightAvail ? width : (width - 1))
1059                                                 ;
1060#else
1061        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
1062#endif
1063        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1064
1065        //prepare 2nd line's upper sign
1066        Pel* srcLineBelow = srcLine + srcStride;
1067        for (x=startX; x<endX+1; x++)
1068        {
1069          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x-1]];
1070        }
1071
1072        //1st line
1073        Pel* srcLineAbove = srcLine - srcStride;
1074#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1075        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0    : 1) : startX;
1076        firstLineEndX   = (!isCalculatePreDeblockSamples) ? (isAboveAvail     ? endX : 1) : endX;
1077#else
1078        firstLineStartX = isAboveLeftAvail ? 0    : 1;
1079        firstLineEndX   = isAboveAvail     ? endX : 1;
1080#endif
1081        for(x=firstLineStartX; x<firstLineEndX; x++)
1082        {
1083          edgeType = m_sign[srcLine[x] - srcLineAbove[x-1]] - signUpLine[x+1];
1084          diff [edgeType] += (orgLine[x] - srcLine[x]);
1085          count[edgeType] ++;
1086        }
1087        srcLine  += srcStride;
1088        orgLine  += orgStride;
1089
1090
1091        //middle lines
1092        for (y=1; y<endY; y++)
1093        {
1094          srcLineBelow = srcLine + srcStride;
1095
1096          for (x=startX; x<endX; x++)
1097          {
1098            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x+1]] ;
1099            edgeType = signDown + signUpLine[x];
1100            diff [edgeType] += (orgLine[x] - srcLine[x]);
1101            count[edgeType] ++;
1102
1103            signDownLine[x+1] = -signDown; 
1104          }
1105          signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
1106
1107          signTmpLine  = signUpLine;
1108          signUpLine   = signDownLine;
1109          signDownLine = signTmpLine;
1110
1111          srcLine += srcStride;
1112          orgLine += orgStride;
1113        }
1114#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1115        if(isCalculatePreDeblockSamples)
1116        {
1117          if(isBelowAvail)
1118          {
1119            startX = isLeftAvail  ? 0     : 1 ;
1120            endX   = isRightAvail ? width : (width -1);
1121
1122            for(y=0; y<skipLinesB[typeIdx]; y++)
1123            {
1124              srcLineBelow = srcLine + srcStride;
1125              srcLineAbove = srcLine - srcStride;
1126
1127              for (x=startX; x< endX; x++)
1128              {
1129                edgeType = m_sign[srcLine[x] - srcLineBelow[x+1]] + m_sign[srcLine[x] - srcLineAbove[x-1]];
1130                diff [edgeType] += (orgLine[x] - srcLine[x]);
1131                count[edgeType] ++;
1132              }
1133              srcLine  += srcStride;
1134              orgLine  += orgStride;
1135            }
1136          }
1137        }
1138#endif
1139      }
1140      break;
1141    case SAO_TYPE_EO_45:
1142      {
1143        diff +=2;
1144        count+=2;
1145        Char *signUpLine = m_signLineBuf1+1;
1146
1147#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1148        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1149                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1150                                                 ;
1151#else
1152        startX = isLeftAvail ? 0 : 1;
1153#endif
1154#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1155        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1156                                                 : (isRightAvail ? width : (width - 1))
1157                                                 ;
1158#else
1159        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1);
1160#endif
1161        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1162
1163        //prepare 2nd line upper sign
1164        Pel* srcLineBelow = srcLine + srcStride;
1165        for (x=startX-1; x<endX; x++)
1166        {
1167          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
1168        }
1169
1170
1171        //first line
1172        Pel* srcLineAbove = srcLine - srcStride;
1173#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1174        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX)
1175                                                          : startX
1176                                                          ;
1177        firstLineEndX   = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX)
1178                                                          : endX
1179                                                          ;
1180#else
1181        firstLineStartX = isAboveAvail ? startX : endX;
1182        firstLineEndX   = (!isRightAvail && isAboveRightAvail) ? width : endX;
1183#endif
1184        for(x=firstLineStartX; x<firstLineEndX; x++)
1185        {
1186          edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] - signUpLine[x-1];
1187          diff [edgeType] += (orgLine[x] - srcLine[x]);
1188          count[edgeType] ++;
1189        }
1190
1191        srcLine += srcStride;
1192        orgLine += orgStride;
1193
1194        //middle lines
1195        for (y=1; y<endY; y++)
1196        {
1197          srcLineBelow = srcLine + srcStride;
1198
1199          for(x=startX; x<endX; x++)
1200          {
1201            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
1202            edgeType = signDown + signUpLine[x];
1203
1204            diff [edgeType] += (orgLine[x] - srcLine[x]);
1205            count[edgeType] ++;
1206
1207            signUpLine[x-1] = -signDown; 
1208          }
1209          signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
1210          srcLine  += srcStride;
1211          orgLine  += orgStride;
1212        }
1213#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1214        if(isCalculatePreDeblockSamples)
1215        {
1216          if(isBelowAvail)
1217          {
1218            startX = isLeftAvail  ? 0     : 1 ;
1219            endX   = isRightAvail ? width : (width -1);
1220
1221            for(y=0; y<skipLinesB[typeIdx]; y++)
1222            {
1223              srcLineBelow = srcLine + srcStride;
1224              srcLineAbove = srcLine - srcStride;
1225
1226              for (x=startX; x<endX; x++)
1227              {
1228                edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + m_sign[srcLine[x] - srcLineAbove[x+1]];
1229                diff [edgeType] += (orgLine[x] - srcLine[x]);
1230                count[edgeType] ++;
1231              }
1232              srcLine  += srcStride;
1233              orgLine  += orgStride;
1234            }
1235          }
1236        }
1237#endif
1238      }
1239      break;
1240    case SAO_TYPE_BO:
1241      {
1242#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1243        startX = (!isCalculatePreDeblockSamples)?0
1244                                                :( isRightAvail?(width- skipLinesR[typeIdx]):width)
1245                                                ;
1246        endX   = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width )
1247                                                :width
1248                                                ;
1249#else
1250        endX = isRightAvail ? (width- skipLinesR[typeIdx]) : width;
1251#endif
1252        endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height;
1253        Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
1254        for (y=0; y< endY; y++)
1255        {
1256#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1257          for (x=startX; x< endX; x++)
1258#else
1259          for (x=0; x< endX; x++)
1260#endif
1261          {
1262
1263            Int bandIdx= srcLine[x] >> shiftBits; 
1264            diff [bandIdx] += (orgLine[x] - srcLine[x]);
1265            count[bandIdx] ++;
1266          }
1267          srcLine += srcStride;
1268          orgLine += orgStride;
1269        }
1270#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1271        if(isCalculatePreDeblockSamples)
1272        {
1273          if(isBelowAvail)
1274          {
1275            startX = 0;
1276            endX   = width;
1277
1278            for(y= 0; y< skipLinesB[typeIdx]; y++)
1279            {
1280              for (x=startX; x< endX; x++)
1281              {
1282                Int bandIdx= srcLine[x] >> shiftBits; 
1283                diff [bandIdx] += (orgLine[x] - srcLine[x]);
1284                count[bandIdx] ++;
1285              }
1286              srcLine  += srcStride;
1287              orgLine  += orgStride;
1288
1289            }
1290
1291          }
1292        }
1293#endif
1294      }
1295      break;
1296    default:
1297      {
1298        printf("Not a supported SAO types\n");
1299        assert(0);
1300        exit(-1);
1301      }
1302    }
1303  }
1304}
1305
1306#else
1307
1308
1309
1310TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
1311{
1312  m_pcEntropyCoder = NULL;
1313  m_pppcRDSbacCoder = NULL;
1314  m_pcRDGoOnSbacCoder = NULL;
1315  m_pppcBinCoderCABAC = NULL;           
1316  m_iCount = NULL;     
1317  m_iOffset = NULL;     
1318  m_iOffsetOrg = NULL; 
1319  m_iRate = NULL;       
1320  m_iDist = NULL;       
1321  m_dCost = NULL;       
1322  m_dCostPartBest = NULL; 
1323  m_iDistOrg = NULL;     
1324  m_iTypePartBest = NULL; 
1325#if SAO_ENCODING_CHOICE_CHROMA
1326  m_depthSaoRate[0][0] = 0;
1327  m_depthSaoRate[0][1] = 0;
1328  m_depthSaoRate[0][2] = 0;
1329  m_depthSaoRate[0][3] = 0;
1330  m_depthSaoRate[1][0] = 0;
1331  m_depthSaoRate[1][1] = 0;
1332  m_depthSaoRate[1][2] = 0;
1333  m_depthSaoRate[1][3] = 0;
1334#endif
1335}
1336TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
1337{
1338
1339}
1340// ====================================================================================================================
1341// Constants
1342// ====================================================================================================================
1343
1344
1345// ====================================================================================================================
1346// Tables
1347// ====================================================================================================================
1348
1349inline Double xRoundIbdi2(Int bitDepth, Double x)
1350{
1351  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))));
1352}
1353
1354/** rounding with IBDI
1355 * \param  x
1356 */
1357inline Double xRoundIbdi(Int bitDepth, Double x)
1358{
1359  return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
1360}
1361
1362
1363
1364/** process SAO for one partition
1365 * \param  *psQTPart, iPartIdx, dLambda
1366 */
1367Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda, Int yCbCr)
1368{
1369  Int iTypeIdx;
1370  Int iNumTotalType = MAX_NUM_SAO_TYPE;
1371  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
1372
1373  Int64 iEstDist;
1374  Int iClassIdx;
1375  Int uiShift = 2 * DISTORTION_PRECISION_ADJUSTMENT((yCbCr == 0 ? g_bitDepthY : g_bitDepthC)-8);
1376  UInt uiDepth = pOnePart->PartLevel;
1377
1378  m_iDistOrg [iPartIdx] =  0;
1379
1380  Double  bestRDCostTableBo = MAX_DOUBLE;
1381  Int     bestClassTableBo    = 0;
1382  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
1383  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
1384
1385  Int addr;
1386  Int allowMergeLeft;
1387  Int allowMergeUp;
1388  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
1389  SaoLcuParam  saoLcuParamRdo;
1390
1391  for (iTypeIdx=-1; iTypeIdx<iNumTotalType; iTypeIdx++)
1392  {
1393    if( m_bUseSBACRD )
1394    {
1395      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
1396      m_pcRDGoOnSbacCoder->resetBits();
1397    }
1398    else
1399    {
1400      m_pcEntropyCoder->resetEntropy();
1401      m_pcEntropyCoder->resetBits();
1402    }
1403
1404    iEstDist = 0;
1405
1406    if (iTypeIdx == -1)
1407    {     
1408      for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
1409      {
1410        for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
1411        {
1412          addr = ry * frameWidthInCU + rx;         
1413
1414          // get bits for iTypeIdx = -1
1415          allowMergeLeft = 1;
1416          allowMergeUp   = 1;
1417          if (rx != 0)
1418          { 
1419            // check tile id and slice id
1420            if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1421            {
1422              allowMergeLeft = 0;
1423            }
1424          }
1425          if (ry!=0)
1426          {
1427            if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1428            {
1429              allowMergeUp = 0;
1430            }
1431          }
1432
1433          // reset
1434          resetSaoUnit(&saoLcuParamRdo);
1435
1436          // set merge flag
1437          saoLcuParamRdo.mergeUpFlag   = 1;
1438          saoLcuParamRdo.mergeLeftFlag = 1;
1439
1440          if (ry == pOnePart->StartCUY) 
1441          {
1442            saoLcuParamRdo.mergeUpFlag = 0;
1443          } 
1444         
1445          if (rx == pOnePart->StartCUX) 
1446          {
1447            saoLcuParamRdo.mergeLeftFlag = 0;
1448          }
1449
1450          m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
1451
1452        }
1453      }
1454    }
1455
1456    if (iTypeIdx>=0)
1457    {
1458      iEstDist = estSaoTypeDist(iPartIdx, iTypeIdx, uiShift, dLambda, currentDistortionTableBo, currentRdCostTableBo);
1459      if( iTypeIdx == SAO_BO )
1460      {
1461        // Estimate Best Position
1462        Double currentRDCost = 0.0;
1463
1464        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
1465        {
1466          currentRDCost = 0.0;
1467          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
1468          {
1469            currentRDCost += currentRdCostTableBo[uj];
1470          }
1471
1472          if( currentRDCost < bestRDCostTableBo)
1473          {
1474            bestRDCostTableBo = currentRDCost;
1475            bestClassTableBo  = i;
1476          }
1477        }
1478
1479        // Re code all Offsets
1480        // Code Center
1481        for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++)
1482        {
1483          iEstDist += currentDistortionTableBo[iClassIdx];
1484        }
1485      }
1486
1487      for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
1488      {
1489        for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
1490        {
1491          addr = ry * frameWidthInCU + rx;         
1492
1493          // get bits for iTypeIdx = -1
1494          allowMergeLeft = 1;
1495          allowMergeUp   = 1;
1496          if (rx != 0)
1497          { 
1498            // check tile id and slice id
1499            if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1500            {
1501              allowMergeLeft = 0;
1502            }
1503          }
1504          if (ry!=0)
1505          {
1506            if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1507            {
1508              allowMergeUp = 0;
1509            }
1510          }
1511
1512          // reset
1513          resetSaoUnit(&saoLcuParamRdo);
1514         
1515          // set merge flag
1516          saoLcuParamRdo.mergeUpFlag   = 1;
1517          saoLcuParamRdo.mergeLeftFlag = 1;
1518
1519          if (ry == pOnePart->StartCUY) 
1520          {
1521            saoLcuParamRdo.mergeUpFlag = 0;
1522          } 
1523         
1524          if (rx == pOnePart->StartCUX) 
1525          {
1526            saoLcuParamRdo.mergeLeftFlag = 0;
1527          }
1528
1529          // set type and offsets
1530          saoLcuParamRdo.typeIdx = iTypeIdx;
1531          saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
1532          saoLcuParamRdo.length = m_iNumClass[iTypeIdx];
1533          for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++)
1534          {
1535            saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1];
1536          }
1537
1538          m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
1539
1540        }
1541      }
1542
1543      m_iDist[iPartIdx][iTypeIdx] = iEstDist;
1544      m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder->getNumberOfWrittenBits();
1545
1546      m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]);
1547
1548      if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx])
1549      {
1550        m_iDistOrg [iPartIdx] = 0;
1551        m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx];
1552        m_iTypePartBest[iPartIdx] = iTypeIdx;
1553        if( m_bUseSBACRD )
1554          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
1555      }
1556    }
1557    else
1558    {
1559      if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] )
1560      {
1561        m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder->getNumberOfWrittenBits()*dLambda ; 
1562        m_iTypePartBest[iPartIdx] = -1;
1563        if( m_bUseSBACRD )
1564        {
1565          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
1566        }
1567      }
1568    }
1569  }
1570
1571  pOnePart->bProcessed = true;
1572  pOnePart->bSplit     = false;
1573  pOnePart->iMinDist   =        m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];
1574  pOnePart->iMinRate   = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);
1575  pOnePart->dMinCost   = pOnePart->iMinDist + dLambda * pOnePart->iMinRate;
1576  pOnePart->iBestType  = m_iTypePartBest[iPartIdx];
1577  if (pOnePart->iBestType != -1)
1578  {
1579    //     pOnePart->bEnableFlag =  1;
1580    pOnePart->iLength = m_iNumClass[pOnePart->iBestType];
1581    Int minIndex = 0;
1582    if( pOnePart->iBestType == SAO_BO )
1583    {
1584      pOnePart->subTypeIdx = bestClassTableBo;
1585      minIndex = pOnePart->subTypeIdx;
1586    }
1587    for (Int i=0; i< pOnePart->iLength ; i++)
1588    {
1589      pOnePart->iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart->iBestType][minIndex+i+1];
1590    }
1591
1592  }
1593  else
1594  {
1595    //     pOnePart->bEnableFlag = 0;
1596    pOnePart->iLength     = 0;
1597  }
1598}
1599
1600/** Run partition tree disable
1601 */
1602Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx)
1603{
1604  SAOQTPart*  pOnePart= &(psQTPart[iPartIdx]);
1605  pOnePart->bSplit      = false;
1606  pOnePart->iLength     =  0;
1607  pOnePart->iBestType   = -1;
1608
1609  if (pOnePart->PartLevel < m_uiMaxSplitLevel)
1610  {
1611    for (Int i=0; i<NUM_DOWN_PART; i++)
1612    {
1613      disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
1614    }
1615  }
1616}
1617
1618/** Run quadtree decision function
1619 * \param  iPartIdx, pcPicOrg, pcPicDec, pcPicRest, &dCostFinal
1620 */
1621Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda, Int yCbCr)
1622{
1623  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
1624
1625  UInt uiDepth = pOnePart->PartLevel;
1626  UInt uhNextDepth = uiDepth+1;
1627
1628  if (iPartIdx == 0)
1629  {
1630    dCostFinal = 0;
1631  }
1632
1633  //SAO for this part
1634  if(!pOnePart->bProcessed)
1635  {
1636    rdoSaoOnePart (psQTPart, iPartIdx, dLambda, yCbCr);
1637  }
1638
1639  //SAO for sub 4 parts
1640  if (pOnePart->PartLevel < iMaxLevel)
1641  {
1642    Double      dCostNotSplit = dLambda + pOnePart->dMinCost;
1643    Double      dCostSplit    = dLambda;
1644
1645    for (Int i=0; i< NUM_DOWN_PART ;i++)
1646    {
1647      if( m_bUseSBACRD ) 
1648      {
1649        if ( 0 == i) //initialize RD with previous depth buffer
1650        {
1651          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
1652        }
1653        else
1654        {
1655          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
1656        }
1657      } 
1658      runQuadTreeDecision(psQTPart, pOnePart->DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda, yCbCr);
1659      dCostSplit += dCostFinal;
1660      if( m_bUseSBACRD )
1661      {
1662        m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]);
1663      }
1664    }
1665
1666    if(dCostSplit < dCostNotSplit)
1667    {
1668      dCostFinal = dCostSplit;
1669      pOnePart->bSplit      = true;
1670      pOnePart->iLength     =  0;
1671      pOnePart->iBestType   = -1;
1672      if( m_bUseSBACRD )
1673      {
1674        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
1675      }
1676    }
1677    else
1678    {
1679      dCostFinal = dCostNotSplit;
1680      pOnePart->bSplit = false;
1681      for (Int i=0; i<NUM_DOWN_PART; i++)
1682      {
1683        disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
1684      }
1685      if( m_bUseSBACRD )
1686      {
1687        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
1688      }
1689    }
1690  }
1691  else
1692  {
1693    dCostFinal = pOnePart->dMinCost;
1694  }
1695}
1696
1697/** delete allocated memory of TEncSampleAdaptiveOffset class.
1698 */
1699Void TEncSampleAdaptiveOffset::destroyEncBuffer()
1700{
1701  for (Int i=0;i<m_iNumTotalParts;i++)
1702  {
1703    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
1704    {
1705      if (m_iCount [i][j])
1706      {
1707        delete [] m_iCount [i][j]; 
1708      }
1709      if (m_iOffset[i][j])
1710      {
1711        delete [] m_iOffset[i][j]; 
1712      }
1713      if (m_iOffsetOrg[i][j])
1714      {
1715        delete [] m_iOffsetOrg[i][j]; 
1716      }
1717    }
1718    if (m_iRate[i])
1719    {
1720      delete [] m_iRate[i];
1721    }
1722    if (m_iDist[i])
1723    {
1724      delete [] m_iDist[i]; 
1725    }
1726    if (m_dCost[i])
1727    {
1728      delete [] m_dCost[i]; 
1729    }
1730    if (m_iCount [i])
1731    {
1732      delete [] m_iCount [i]; 
1733    }
1734    if (m_iOffset[i])
1735    {
1736      delete [] m_iOffset[i]; 
1737    }
1738    if (m_iOffsetOrg[i])
1739    {
1740      delete [] m_iOffsetOrg[i]; 
1741    }
1742
1743  }
1744  if (m_iDistOrg)
1745  {
1746    delete [] m_iDistOrg ; m_iDistOrg = NULL;
1747  }
1748  if (m_dCostPartBest)
1749  {
1750    delete [] m_dCostPartBest ; m_dCostPartBest = NULL;
1751  }
1752  if (m_iTypePartBest)
1753  {
1754    delete [] m_iTypePartBest ; m_iTypePartBest = NULL;
1755  }
1756  if (m_iRate)
1757  {
1758    delete [] m_iRate ; m_iRate = NULL;
1759  }
1760  if (m_iDist)
1761  {
1762    delete [] m_iDist ; m_iDist = NULL;
1763  }
1764  if (m_dCost)
1765  {
1766    delete [] m_dCost ; m_dCost = NULL;
1767  }
1768  if (m_iCount)
1769  {
1770    delete [] m_iCount  ; m_iCount = NULL;
1771  }
1772  if (m_iOffset)
1773  {
1774    delete [] m_iOffset ; m_iOffset = NULL;
1775  }
1776  if (m_iOffsetOrg)
1777  {
1778    delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;
1779  }
1780  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
1781
1782  for (Int i=0;i<numLcu;i++)
1783  {
1784    for (Int j=0;j<3;j++)
1785    {
1786      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
1787      {
1788        if (m_count_PreDblk [i][j][k])
1789        {
1790          delete [] m_count_PreDblk [i][j][k]; 
1791        }
1792        if (m_offsetOrg_PreDblk[i][j][k])
1793        {
1794          delete [] m_offsetOrg_PreDblk[i][j][k];
1795        }
1796      }
1797      if (m_count_PreDblk [i][j])
1798      {
1799        delete [] m_count_PreDblk [i][j]; 
1800      }
1801      if (m_offsetOrg_PreDblk[i][j])
1802      {
1803        delete [] m_offsetOrg_PreDblk[i][j]; 
1804      }
1805    }
1806    if (m_count_PreDblk [i])
1807    {
1808      delete [] m_count_PreDblk [i]; 
1809    }
1810    if (m_offsetOrg_PreDblk[i])
1811    {
1812      delete [] m_offsetOrg_PreDblk[i]; 
1813    }
1814  }
1815  if (m_count_PreDblk)
1816  {
1817    delete [] m_count_PreDblk  ; m_count_PreDblk = NULL;
1818  }
1819  if (m_offsetOrg_PreDblk)
1820  {
1821    delete [] m_offsetOrg_PreDblk ; m_offsetOrg_PreDblk = NULL;
1822  }
1823
1824  Int iMaxDepth = 4;
1825  Int iDepth;
1826  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
1827  {
1828    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
1829    {
1830      delete m_pppcRDSbacCoder[iDepth][iCIIdx];
1831      delete m_pppcBinCoderCABAC[iDepth][iCIIdx];
1832    }
1833  }
1834
1835  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
1836  {
1837    delete [] m_pppcRDSbacCoder[iDepth];
1838    delete [] m_pppcBinCoderCABAC[iDepth];
1839  }
1840
1841  delete [] m_pppcRDSbacCoder;
1842  delete [] m_pppcBinCoderCABAC;
1843}
1844
1845/** create Encoder Buffer for SAO
1846 * \param
1847 */
1848Void TEncSampleAdaptiveOffset::createEncBuffer()
1849{
1850  m_iDistOrg = new Int64 [m_iNumTotalParts]; 
1851  m_dCostPartBest = new Double [m_iNumTotalParts]; 
1852  m_iTypePartBest = new Int [m_iNumTotalParts]; 
1853
1854  m_iRate = new Int64* [m_iNumTotalParts];
1855  m_iDist = new Int64* [m_iNumTotalParts];
1856  m_dCost = new Double*[m_iNumTotalParts];
1857
1858  m_iCount  = new Int64 **[m_iNumTotalParts];
1859  m_iOffset = new Int64 **[m_iNumTotalParts];
1860  m_iOffsetOrg = new Int64 **[m_iNumTotalParts];
1861
1862  for (Int i=0;i<m_iNumTotalParts;i++)
1863  {
1864    m_iRate[i] = new Int64  [MAX_NUM_SAO_TYPE];
1865    m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE]; 
1866    m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 
1867
1868    m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
1869    m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
1870    m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
1871
1872    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
1873    {
1874      m_iCount [i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
1875      m_iOffset[i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
1876      m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 
1877    }
1878  }
1879  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
1880  m_count_PreDblk  = new Int64 ***[numLcu];
1881  m_offsetOrg_PreDblk = new Int64 ***[numLcu];
1882  for (Int i=0; i<numLcu; i++)
1883  {
1884    m_count_PreDblk[i]  = new Int64 **[3];
1885    m_offsetOrg_PreDblk[i] = new Int64 **[3];
1886
1887    for (Int j=0;j<3;j++)
1888    {
1889      m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
1890      m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
1891
1892      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
1893      {
1894        m_count_PreDblk [i][j][k]   = new Int64 [MAX_NUM_SAO_CLASS]; 
1895        m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS]; 
1896      }
1897    }
1898  }
1899
1900  Int iMaxDepth = 4;
1901  m_pppcRDSbacCoder = new TEncSbac** [iMaxDepth+1];
1902#if FAST_BIT_EST
1903  m_pppcBinCoderCABAC = new TEncBinCABACCounter** [iMaxDepth+1];
1904#else
1905  m_pppcBinCoderCABAC = new TEncBinCABAC** [iMaxDepth+1];
1906#endif
1907
1908  for ( Int iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
1909  {
1910    m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM];
1911#if FAST_BIT_EST
1912    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM];
1913#else
1914    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM];
1915#endif
1916    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
1917    {
1918      m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac;
1919#if FAST_BIT_EST
1920      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter;
1921#else
1922      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC;
1923#endif
1924      m_pppcRDSbacCoder   [iDepth][iCIIdx]->init( m_pppcBinCoderCABAC [iDepth][iCIIdx] );
1925    }
1926  }
1927}
1928
1929/** Start SAO encoder
1930 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
1931 */
1932Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
1933{
1934    m_bUseSBACRD = true;
1935  m_pcPic = pcPic;
1936  m_pcEntropyCoder = pcEntropyCoder;
1937
1938  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
1939  m_pcEntropyCoder->setEntropyCoder(m_pcRDGoOnSbacCoder, pcPic->getSlice(0));
1940  m_pcEntropyCoder->resetEntropy();
1941  m_pcEntropyCoder->resetBits();
1942
1943  if( m_bUseSBACRD )
1944  {
1945    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
1946    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
1947  }
1948}
1949
1950/** End SAO encoder
1951 */
1952Void TEncSampleAdaptiveOffset::endSaoEnc()
1953{
1954  m_pcPic = NULL;
1955  m_pcEntropyCoder = NULL;
1956}
1957
1958inline Int xSign(Int x)
1959{
1960  return ((x >> 31) | ((Int)( (((UInt) -x)) >> 31)));
1961}
1962
1963/** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
1964 * \param  pRecStart to-be-filtered block buffer pointer
1965 * \param  pOrgStart original block buffer pointer
1966 * \param  stride picture buffer stride
1967 * \param  ppStat statistics buffer
1968 * \param  ppCount counter buffer
1969 * \param  width block width
1970 * \param  height block height
1971 * \param  pbBorderAvail availabilities of block border pixels
1972 */
1973Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr)
1974{
1975  Int64 *stats, *count;
1976  Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
1977  Pel *pOrg, *pRec;
1978  UInt edgeType;
1979  Int x, y;
1980  Pel *pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo;
1981
1982  //--------- Band offset-----------//
1983  stats = ppStats[SAO_BO];
1984  count = ppCount[SAO_BO];
1985  pOrg   = pOrgStart;
1986  pRec   = pRecStart;
1987  for (y=0; y< height; y++)
1988  {
1989    for (x=0; x< width; x++)
1990    {
1991      classIdx = pTableBo[pRec[x]];
1992      if (classIdx)
1993      {
1994        stats[classIdx] += (pOrg[x] - pRec[x]); 
1995        count[classIdx] ++;
1996      }
1997    }
1998    pOrg += stride;
1999    pRec += stride;
2000  }
2001  //---------- Edge offset 0--------------//
2002  stats = ppStats[SAO_EO_0];
2003  count = ppCount[SAO_EO_0];
2004  pOrg   = pOrgStart;
2005  pRec   = pRecStart;
2006
2007
2008  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
2009  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
2010  for (y=0; y< height; y++)
2011  {
2012    signLeft = xSign(pRec[startX] - pRec[startX-1]);
2013    for (x=startX; x< endX; x++)
2014    {
2015      signRight =  xSign(pRec[x] - pRec[x+1]); 
2016      edgeType =  signRight + signLeft + 2;
2017      signLeft  = -signRight;
2018
2019      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2020      count[m_auiEoTable[edgeType]] ++;
2021    }
2022    pRec  += stride;
2023    pOrg += stride;
2024  }
2025
2026  //---------- Edge offset 1--------------//
2027  stats = ppStats[SAO_EO_1];
2028  count = ppCount[SAO_EO_1];
2029  pOrg   = pOrgStart;
2030  pRec   = pRecStart;
2031
2032  startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
2033  endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
2034  if (!pbBorderAvail[SGU_T])
2035  {
2036    pRec  += stride;
2037    pOrg  += stride;
2038  }
2039
2040  for (x=0; x< width; x++)
2041  {
2042    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
2043  }
2044  for (y=startY; y<endY; y++)
2045  {
2046    for (x=0; x< width; x++)
2047    {
2048      signDown     =  xSign(pRec[x] - pRec[x+stride]); 
2049      edgeType    =  signDown + m_iUpBuff1[x] + 2;
2050      m_iUpBuff1[x] = -signDown;
2051
2052      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2053      count[m_auiEoTable[edgeType]] ++;
2054    }
2055    pOrg += stride;
2056    pRec += stride;
2057  }
2058  //---------- Edge offset 2--------------//
2059  stats = ppStats[SAO_EO_2];
2060  count = ppCount[SAO_EO_2];
2061  pOrg   = pOrgStart;
2062  pRec   = pRecStart;
2063
2064  posShift= stride + 1;
2065
2066  startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
2067  endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
2068
2069  //prepare 2nd line upper sign
2070  pRec += stride;
2071  for (x=startX; x< endX+1; x++)
2072  {
2073    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
2074  }
2075
2076  //1st line
2077  pRec -= stride;
2078  if(pbBorderAvail[SGU_TL])
2079  {
2080    x= 0;
2081    edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
2082    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2083    count[m_auiEoTable[edgeType]] ++;
2084  }
2085  if(pbBorderAvail[SGU_T])
2086  {
2087    for(x= 1; x< endX; x++)
2088    {
2089      edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
2090      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2091      count[m_auiEoTable[edgeType]] ++;
2092    }
2093  }
2094  pRec   += stride;
2095  pOrg   += stride;
2096
2097  //middle lines
2098  for (y= 1; y< height-1; y++)
2099  {
2100    for (x=startX; x<endX; x++)
2101    {
2102      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
2103      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
2104      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2105      count[m_auiEoTable[edgeType]] ++;
2106
2107      m_iUpBufft[x+1] = -signDown1; 
2108    }
2109    m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]);
2110
2111    ipSwap     = m_iUpBuff1;
2112    m_iUpBuff1 = m_iUpBufft;
2113    m_iUpBufft = ipSwap;
2114
2115    pRec  += stride;
2116    pOrg  += stride;
2117  }
2118
2119  //last line
2120  if(pbBorderAvail[SGU_B])
2121  {
2122    for(x= startX; x< width-1; x++)
2123    {
2124      edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
2125      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2126      count[m_auiEoTable[edgeType]] ++;
2127    }
2128  }
2129  if(pbBorderAvail[SGU_BR])
2130  {
2131    x= width -1;
2132    edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
2133    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2134    count[m_auiEoTable[edgeType]] ++;
2135  }
2136
2137  //---------- Edge offset 3--------------//
2138
2139  stats = ppStats[SAO_EO_3];
2140  count = ppCount[SAO_EO_3];
2141  pOrg   = pOrgStart;
2142  pRec   = pRecStart;
2143
2144  posShift     = stride - 1;
2145  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
2146  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
2147
2148  //prepare 2nd line upper sign
2149  pRec += stride;
2150  for (x=startX-1; x< endX; x++)
2151  {
2152    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
2153  }
2154
2155
2156  //first line
2157  pRec -= stride;
2158  if(pbBorderAvail[SGU_T])
2159  {
2160    for(x= startX; x< width -1; x++)
2161    {
2162      edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
2163      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2164      count[m_auiEoTable[edgeType]] ++;
2165    }
2166  }
2167  if(pbBorderAvail[SGU_TR])
2168  {
2169    x= width-1;
2170    edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
2171    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2172    count[m_auiEoTable[edgeType]] ++;
2173  }
2174  pRec  += stride;
2175  pOrg  += stride;
2176
2177  //middle lines
2178  for (y= 1; y< height-1; y++)
2179  {
2180    for(x= startX; x< endX; x++)
2181    {
2182      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
2183      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
2184
2185      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2186      count[m_auiEoTable[edgeType]] ++;
2187      m_iUpBuff1[x-1] = -signDown1; 
2188
2189    }
2190    m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
2191
2192    pRec  += stride;
2193    pOrg  += stride;
2194  }
2195
2196  //last line
2197  if(pbBorderAvail[SGU_BL])
2198  {
2199    x= 0;
2200    edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
2201    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2202    count[m_auiEoTable[edgeType]] ++;
2203
2204  }
2205  if(pbBorderAvail[SGU_B])
2206  {
2207    for(x= 1; x< endX; x++)
2208    {
2209      edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
2210      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
2211      count[m_auiEoTable[edgeType]] ++;
2212    }
2213  }
2214}
2215
2216/** Calculate SAO statistics for current LCU
2217 * \param  iAddr,  iPartIdx,  iYCbCr
2218 */
2219Void TEncSampleAdaptiveOffset::calcSaoStatsCu(Int iAddr, Int iPartIdx, Int iYCbCr)
2220{
2221  if(!m_bUseNIF)
2222  {
2223    calcSaoStatsCuOrg( iAddr, iPartIdx, iYCbCr);
2224  }
2225  else
2226  {
2227    Int64** ppStats = m_iOffsetOrg[iPartIdx];
2228    Int64** ppCount = m_iCount    [iPartIdx];
2229
2230    //parameters
2231    Int  isChroma = (iYCbCr != 0)? 1:0;
2232    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
2233    Pel* pPicOrg = getPicYuvAddr (m_pcPic->getPicYuvOrg(), iYCbCr);
2234    Pel* pPicRec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
2235
2236    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
2237
2238    //variables
2239    UInt  xPos, yPos, width, height;
2240    Bool* pbBorderAvail;
2241    UInt  posOffset;
2242
2243    for(Int i=0; i< vFilterBlocks.size(); i++)
2244    {
2245      xPos        = vFilterBlocks[i].posX   >> isChroma;
2246      yPos        = vFilterBlocks[i].posY   >> isChroma;
2247      width       = vFilterBlocks[i].width  >> isChroma;
2248      height      = vFilterBlocks[i].height >> isChroma;
2249      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
2250
2251      posOffset = (yPos* stride) + xPos;
2252
2253      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail, iYCbCr);
2254    }
2255  }
2256
2257}
2258
2259/** Calculate SAO statistics for current LCU without non-crossing slice
2260 * \param  iAddr,  iPartIdx,  iYCbCr
2261 */
2262Void TEncSampleAdaptiveOffset::calcSaoStatsCuOrg(Int iAddr, Int iPartIdx, Int iYCbCr)
2263{
2264  Int x,y;
2265  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
2266  TComSPS *pTmpSPS =  m_pcPic->getSlice(0)->getSPS();
2267
2268  Pel* pOrg;
2269  Pel* pRec;
2270  Int iStride;
2271  Int iLcuHeight = pTmpSPS->getMaxCUHeight();
2272  Int iLcuWidth  = pTmpSPS->getMaxCUWidth();
2273  UInt uiLPelX   = pTmpCu->getCUPelX();
2274  UInt uiTPelY   = pTmpCu->getCUPelY();
2275  UInt uiRPelX;
2276  UInt uiBPelY;
2277  Int64* iStats;
2278  Int64* iCount;
2279  Int iClassIdx;
2280  Int iPicWidthTmp;
2281  Int iPicHeightTmp;
2282  Int iStartX;
2283  Int iStartY;
2284  Int iEndX;
2285  Int iEndY;
2286  Pel* pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo;
2287
2288  Int iIsChroma = (iYCbCr!=0)? 1:0;
2289  Int numSkipLine = iIsChroma? 2:4;
2290  if (m_saoLcuBasedOptimization == 0)
2291  {
2292    numSkipLine = 0;
2293  }
2294
2295  Int numSkipLineRight = iIsChroma? 3:5;
2296  if (m_saoLcuBasedOptimization == 0)
2297  {
2298    numSkipLineRight = 0;
2299  }
2300
2301  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
2302  iPicHeightTmp = m_iPicHeight >> iIsChroma;
2303  iLcuWidth     = iLcuWidth    >> iIsChroma;
2304  iLcuHeight    = iLcuHeight   >> iIsChroma;
2305  uiLPelX       = uiLPelX      >> iIsChroma;
2306  uiTPelY       = uiTPelY      >> iIsChroma;
2307  uiRPelX       = uiLPelX + iLcuWidth  ;
2308  uiBPelY       = uiTPelY + iLcuHeight ;
2309  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
2310  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
2311  iLcuWidth     = uiRPelX - uiLPelX;
2312  iLcuHeight    = uiBPelY - uiTPelY;
2313
2314  iStride    =  (iYCbCr == 0)? m_pcPic->getStride(): m_pcPic->getCStride();
2315
2316//if(iSaoType == BO_0 || iSaoType == BO_1)
2317  {
2318    if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2319    {
2320      numSkipLine = iIsChroma? 1:3;
2321      numSkipLineRight = iIsChroma? 2:4;
2322    }
2323    iStats = m_iOffsetOrg[iPartIdx][SAO_BO];
2324    iCount = m_iCount    [iPartIdx][SAO_BO];
2325
2326    pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
2327    pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
2328
2329    iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
2330    iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeight-numSkipLine;
2331    for (y=0; y<iEndY; y++)
2332    {
2333      for (x=0; x<iEndX; x++)
2334      {
2335        iClassIdx = pTableBo[pRec[x]];
2336        if (iClassIdx)
2337        {
2338          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
2339          iCount[iClassIdx] ++;
2340        }
2341      }
2342      pOrg += iStride;
2343      pRec += iStride;
2344    }
2345
2346  }
2347  Int iSignLeft;
2348  Int iSignRight;
2349  Int iSignDown;
2350  Int iSignDown1;
2351  Int iSignDown2;
2352
2353  UInt uiEdgeType;
2354
2355//if (iSaoType == EO_0  || iSaoType == EO_1 || iSaoType == EO_2 || iSaoType == EO_3)
2356  {
2357  //if (iSaoType == EO_0)
2358    {
2359      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2360      {
2361        numSkipLine = iIsChroma? 1:3;
2362        numSkipLineRight = iIsChroma? 3:5;
2363      }
2364      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];
2365      iCount = m_iCount    [iPartIdx][SAO_EO_0];
2366
2367      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
2368      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
2369
2370      iStartX = (uiLPelX == 0) ? 1 : 0;
2371      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
2372      for (y=0; y<iLcuHeight-numSkipLine; y++)
2373      {
2374        iSignLeft = xSign(pRec[iStartX] - pRec[iStartX-1]);
2375        for (x=iStartX; x< iEndX; x++)
2376        {
2377          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
2378          uiEdgeType =  iSignRight + iSignLeft + 2;
2379          iSignLeft  = -iSignRight;
2380
2381          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2382          iCount[m_auiEoTable[uiEdgeType]] ++;
2383        }
2384        pOrg += iStride;
2385        pRec += iStride;
2386      }
2387    }
2388
2389  //if (iSaoType == EO_1)
2390    {
2391      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2392      {
2393        numSkipLine = iIsChroma? 2:4;
2394        numSkipLineRight = iIsChroma? 2:4;
2395      }
2396      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];
2397      iCount = m_iCount    [iPartIdx][SAO_EO_1];
2398
2399      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
2400      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
2401
2402      iStartY = (uiTPelY == 0) ? 1 : 0;
2403      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
2404      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
2405      if (uiTPelY == 0)
2406      {
2407        pOrg += iStride;
2408        pRec += iStride;
2409      }
2410
2411      for (x=0; x< iLcuWidth; x++)
2412      {
2413        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
2414      }
2415      for (y=iStartY; y<iEndY; y++)
2416      {
2417        for (x=0; x<iEndX; x++)
2418        {
2419          iSignDown     =  xSign(pRec[x] - pRec[x+iStride]); 
2420          uiEdgeType    =  iSignDown + m_iUpBuff1[x] + 2;
2421          m_iUpBuff1[x] = -iSignDown;
2422
2423          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2424          iCount[m_auiEoTable[uiEdgeType]] ++;
2425        }
2426        pOrg += iStride;
2427        pRec += iStride;
2428      }
2429    }
2430  //if (iSaoType == EO_2)
2431    {
2432      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2433      {
2434        numSkipLine = iIsChroma? 2:4;
2435        numSkipLineRight = iIsChroma? 3:5;
2436      }
2437      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];
2438      iCount = m_iCount    [iPartIdx][SAO_EO_2];
2439
2440      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
2441      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
2442
2443      iStartX = (uiLPelX == 0) ? 1 : 0;
2444      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
2445
2446      iStartY = (uiTPelY == 0) ? 1 : 0;
2447      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
2448      if (uiTPelY == 0)
2449      {
2450        pOrg += iStride;
2451        pRec += iStride;
2452      }
2453
2454      for (x=iStartX; x<iEndX; x++)
2455      {
2456        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
2457      }
2458      for (y=iStartY; y<iEndY; y++)
2459      {
2460        iSignDown2 = xSign(pRec[iStride+iStartX] - pRec[iStartX-1]);
2461        for (x=iStartX; x<iEndX; x++)
2462        {
2463          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
2464          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
2465          m_iUpBufft[x+1] = -iSignDown1; 
2466          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2467          iCount[m_auiEoTable[uiEdgeType]] ++;
2468        }
2469        m_iUpBufft[iStartX] = iSignDown2;
2470        ipSwap     = m_iUpBuff1;
2471        m_iUpBuff1 = m_iUpBufft;
2472        m_iUpBufft = ipSwap;
2473
2474        pRec += iStride;
2475        pOrg += iStride;
2476      }
2477    } 
2478  //if (iSaoType == EO_3  )
2479    {
2480      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2481      {
2482        numSkipLine = iIsChroma? 2:4;
2483        numSkipLineRight = iIsChroma? 3:5;
2484      }
2485      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];
2486      iCount = m_iCount    [iPartIdx][SAO_EO_3];
2487
2488      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
2489      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
2490
2491      iStartX = (uiLPelX == 0) ? 1 : 0;
2492      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
2493
2494      iStartY = (uiTPelY == 0) ? 1 : 0;
2495      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
2496      if (iStartY == 1)
2497      {
2498        pOrg += iStride;
2499        pRec += iStride;
2500      }
2501
2502      for (x=iStartX-1; x<iEndX; x++)
2503      {
2504        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
2505      }
2506
2507      for (y=iStartY; y<iEndY; y++)
2508      {
2509        for (x=iStartX; x<iEndX; x++)
2510        {
2511          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
2512          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
2513          m_iUpBuff1[x-1] = -iSignDown1; 
2514          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2515          iCount[m_auiEoTable[uiEdgeType]] ++;
2516        }
2517        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
2518
2519        pRec += iStride;
2520        pOrg += iStride;
2521      } 
2522    } 
2523  }
2524}
2525
2526
2527Void TEncSampleAdaptiveOffset::calcSaoStatsCu_BeforeDblk( TComPic* pcPic )
2528{
2529  Int addr, yCbCr;
2530  Int x,y;
2531  TComSPS *pTmpSPS =  pcPic->getSlice(0)->getSPS();
2532
2533  Pel* pOrg;
2534  Pel* pRec;
2535  Int stride;
2536  Int lcuHeight = pTmpSPS->getMaxCUHeight();
2537  Int lcuWidth  = pTmpSPS->getMaxCUWidth();
2538  UInt rPelX;
2539  UInt bPelY;
2540  Int64* stats;
2541  Int64* count;
2542  Int classIdx;
2543  Int picWidthTmp = 0;
2544  Int picHeightTmp = 0;
2545  Int startX;
2546  Int startY;
2547  Int endX;
2548  Int endY;
2549  Int firstX, firstY;
2550
2551  Int idxY;
2552  Int idxX;
2553  Int frameHeightInCU = m_iNumCuInHeight;
2554  Int frameWidthInCU  = m_iNumCuInWidth;
2555  Int j, k;
2556
2557  Int isChroma;
2558  Int numSkipLine, numSkipLineRight;
2559
2560  UInt lPelX, tPelY;
2561  TComDataCU *pTmpCu;
2562  Pel* pTableBo;
2563
2564  for (idxY = 0; idxY< frameHeightInCU; idxY++)
2565  {
2566    for (idxX = 0; idxX< frameWidthInCU; idxX++)
2567    {
2568      lcuHeight = pTmpSPS->getMaxCUHeight();
2569      lcuWidth  = pTmpSPS->getMaxCUWidth();
2570      addr     = idxX  + frameWidthInCU*idxY;
2571      pTmpCu = pcPic->getCU(addr);
2572      lPelX   = pTmpCu->getCUPelX();
2573      tPelY   = pTmpCu->getCUPelY();
2574      for( yCbCr = 0; yCbCr < 3; yCbCr++ )
2575      {
2576        isChroma = (yCbCr!=0)? 1:0;
2577
2578        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
2579        {
2580          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
2581          {
2582            m_count_PreDblk    [addr][yCbCr][j][k] = 0;
2583            m_offsetOrg_PreDblk[addr][yCbCr][j][k] = 0;
2584          } 
2585        }
2586        if( yCbCr == 0 )
2587        {
2588          picWidthTmp  = m_iPicWidth;
2589          picHeightTmp = m_iPicHeight;
2590        }
2591        else if( yCbCr == 1 )
2592        {
2593          picWidthTmp  = m_iPicWidth  >> isChroma;
2594          picHeightTmp = m_iPicHeight >> isChroma;
2595          lcuWidth     = lcuWidth    >> isChroma;
2596          lcuHeight    = lcuHeight   >> isChroma;
2597          lPelX       = lPelX      >> isChroma;
2598          tPelY       = tPelY      >> isChroma;
2599        }
2600        rPelX       = lPelX + lcuWidth  ;
2601        bPelY       = tPelY + lcuHeight ;
2602        rPelX       = rPelX > picWidthTmp  ? picWidthTmp  : rPelX;
2603        bPelY       = bPelY > picHeightTmp ? picHeightTmp : bPelY;
2604        lcuWidth     = rPelX - lPelX;
2605        lcuHeight    = bPelY - tPelY;
2606
2607        stride    =  (yCbCr == 0)? pcPic->getStride(): pcPic->getCStride();
2608        pTableBo = (yCbCr==0)?m_lumaTableBo:m_chromaTableBo;
2609
2610        //if(iSaoType == BO)
2611
2612        numSkipLine = isChroma? 1:3;
2613        numSkipLineRight = isChroma? 2:4;
2614
2615        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_BO];
2616        count = m_count_PreDblk[addr][yCbCr][SAO_BO];
2617
2618        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
2619        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
2620
2621        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
2622        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
2623
2624        for (y=0; y<lcuHeight; y++)
2625        {
2626          for (x=0; x<lcuWidth; x++)
2627          {
2628            if( x < startX && y < startY )
2629              continue;
2630
2631            classIdx = pTableBo[pRec[x]];
2632            if (classIdx)
2633            {
2634              stats[classIdx] += (pOrg[x] - pRec[x]); 
2635              count[classIdx] ++;
2636            }
2637          }
2638          pOrg += stride;
2639          pRec += stride;
2640        }
2641
2642        Int signLeft;
2643        Int signRight;
2644        Int signDown;
2645        Int signDown1;
2646        Int signDown2;
2647
2648        UInt uiEdgeType;
2649
2650        //if (iSaoType == EO_0)
2651
2652        numSkipLine = isChroma? 1:3;
2653        numSkipLineRight = isChroma? 3:5;
2654
2655        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_0];
2656        count = m_count_PreDblk[addr][yCbCr][SAO_EO_0];
2657
2658        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
2659        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
2660
2661        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
2662        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
2663        firstX   = (lPelX == 0) ? 1 : 0;
2664        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
2665
2666        for (y=0; y<lcuHeight; y++)
2667        {
2668          signLeft = xSign(pRec[firstX] - pRec[firstX-1]);
2669          for (x=firstX; x< endX; x++)
2670          {
2671            signRight =  xSign(pRec[x] - pRec[x+1]); 
2672            uiEdgeType =  signRight + signLeft + 2;
2673            signLeft  = -signRight;
2674
2675            if( x < startX && y < startY )
2676              continue;
2677
2678            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2679            count[m_auiEoTable[uiEdgeType]] ++;
2680          }
2681          pOrg += stride;
2682          pRec += stride;
2683        }
2684
2685        //if (iSaoType == EO_1)
2686
2687        numSkipLine = isChroma? 2:4;
2688        numSkipLineRight = isChroma? 2:4;
2689
2690        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_1];
2691        count = m_count_PreDblk[addr][yCbCr][SAO_EO_1];
2692
2693        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
2694        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
2695
2696        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
2697        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
2698        firstY = (tPelY == 0) ? 1 : 0;
2699        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
2700        if (firstY == 1)
2701        {
2702          pOrg += stride;
2703          pRec += stride;
2704        }
2705
2706        for (x=0; x< lcuWidth; x++)
2707        {
2708          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
2709        }
2710        for (y=firstY; y<endY; y++)
2711        {
2712          for (x=0; x<lcuWidth; x++)
2713          {
2714            signDown     =  xSign(pRec[x] - pRec[x+stride]); 
2715            uiEdgeType    =  signDown + m_iUpBuff1[x] + 2;
2716            m_iUpBuff1[x] = -signDown;
2717
2718            if( x < startX && y < startY )
2719              continue;
2720
2721            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2722            count[m_auiEoTable[uiEdgeType]] ++;
2723          }
2724          pOrg += stride;
2725          pRec += stride;
2726        }
2727
2728        //if (iSaoType == EO_2)
2729
2730        numSkipLine = isChroma? 2:4;
2731        numSkipLineRight = isChroma? 3:5;
2732
2733        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_2];
2734        count = m_count_PreDblk[addr][yCbCr][SAO_EO_2];
2735
2736        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
2737        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
2738
2739        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
2740        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
2741        firstX   = (lPelX == 0) ? 1 : 0;
2742        firstY = (tPelY == 0) ? 1 : 0;
2743        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
2744        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
2745        if (firstY == 1)
2746        {
2747          pOrg += stride;
2748          pRec += stride;
2749        }
2750
2751        for (x=firstX; x<endX; x++)
2752        {
2753          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride-1]);
2754        }
2755        for (y=firstY; y<endY; y++)
2756        {
2757          signDown2 = xSign(pRec[stride+startX] - pRec[startX-1]);
2758          for (x=firstX; x<endX; x++)
2759          {
2760            signDown1      =  xSign(pRec[x] - pRec[x+stride+1]) ;
2761            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
2762            m_iUpBufft[x+1] = -signDown1; 
2763
2764            if( x < startX && y < startY )
2765              continue;
2766
2767            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2768            count[m_auiEoTable[uiEdgeType]] ++;
2769          }
2770          m_iUpBufft[firstX] = signDown2;
2771          ipSwap     = m_iUpBuff1;
2772          m_iUpBuff1 = m_iUpBufft;
2773          m_iUpBufft = ipSwap;
2774
2775          pRec += stride;
2776          pOrg += stride;
2777        }
2778
2779        //if (iSaoType == EO_3)
2780
2781        numSkipLine = isChroma? 2:4;
2782        numSkipLineRight = isChroma? 3:5;
2783
2784        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_3];
2785        count = m_count_PreDblk[addr][yCbCr][SAO_EO_3];
2786
2787        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
2788        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
2789
2790        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
2791        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
2792        firstX   = (lPelX == 0) ? 1 : 0;
2793        firstY = (tPelY == 0) ? 1 : 0;
2794        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
2795        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
2796        if (firstY == 1)
2797        {
2798          pOrg += stride;
2799          pRec += stride;
2800        }
2801
2802        for (x=firstX-1; x<endX; x++)
2803        {
2804          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride+1]);
2805        }
2806
2807        for (y=firstY; y<endY; y++)
2808        {
2809          for (x=firstX; x<endX; x++)
2810          {
2811            signDown1      =  xSign(pRec[x] - pRec[x+stride-1]) ;
2812            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
2813            m_iUpBuff1[x-1] = -signDown1; 
2814
2815            if( x < startX && y < startY )
2816              continue;
2817
2818            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
2819            count[m_auiEoTable[uiEdgeType]] ++;
2820          }
2821          m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
2822
2823          pRec += stride;
2824          pOrg += stride;
2825        }
2826      }
2827    }
2828  }
2829}
2830
2831
2832/** get SAO statistics
2833 * \param  *psQTPart,  iYCbCr
2834 */
2835Void TEncSampleAdaptiveOffset::getSaoStats(SAOQTPart *psQTPart, Int iYCbCr)
2836{
2837  Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;
2838  Int i;
2839  Int iNumTotalType = MAX_NUM_SAO_TYPE;
2840  Int LcuIdxX;
2841  Int LcuIdxY;
2842  Int iAddr;
2843  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
2844  Int iDownPartIdx;
2845  Int iPartStart;
2846  Int iPartEnd;
2847  SAOQTPart*  pOnePart; 
2848
2849  if (m_uiMaxSplitLevel == 0)
2850  {
2851    iPartIdx = 0;
2852    pOnePart = &(psQTPart[iPartIdx]);
2853    for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
2854    {
2855      for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
2856      {
2857        iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
2858        calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
2859      }
2860    }
2861  }
2862  else
2863  {
2864    for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel-1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)
2865    {
2866      pOnePart = &(psQTPart[iPartIdx]);
2867      for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
2868      {
2869        for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
2870        {
2871          iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
2872          calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
2873        }
2874      }
2875    }
2876    for (iLevelIdx = m_uiMaxSplitLevel-1; iLevelIdx>=0; iLevelIdx-- )
2877    {
2878      iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx-1] : 0;
2879      iPartEnd   = m_aiNumCulPartsLevel[iLevelIdx];
2880
2881      for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)
2882      {
2883        pOnePart = &(psQTPart[iPartIdx]);
2884        for (i=0; i< NUM_DOWN_PART; i++)
2885        {
2886          iDownPartIdx = pOnePart->DownPartsIdx[i];
2887          for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)
2888          {
2889            for (iClassIdx=0; iClassIdx< (iTypeIdx < SAO_BO ? m_iNumClass[iTypeIdx] : SAO_MAX_BO_CLASSES) +1; iClassIdx++)
2890            {
2891              m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];
2892              m_iCount [iPartIdx][iTypeIdx][iClassIdx]    += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];
2893            }
2894          }
2895        }
2896      }
2897    }
2898  }
2899}
2900
2901/** reset offset statistics
2902 * \param
2903 */
2904Void TEncSampleAdaptiveOffset::resetStats()
2905{
2906  for (Int i=0;i<m_iNumTotalParts;i++)
2907  {
2908    m_dCostPartBest[i] = MAX_DOUBLE;
2909    m_iTypePartBest[i] = -1;
2910    m_iDistOrg[i] = 0;
2911    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
2912    {
2913      m_iDist[i][j] = 0;
2914      m_iRate[i][j] = 0;
2915      m_dCost[i][j] = 0;
2916      for (Int k=0;k<MAX_NUM_SAO_CLASS;k++)
2917      {
2918        m_iCount [i][j][k] = 0;
2919        m_iOffset[i][j][k] = 0;
2920        m_iOffsetOrg[i][j][k] = 0;
2921      } 
2922    }
2923  }
2924}
2925
2926/** Sample adaptive offset process
2927 * \param pcSaoParam
2928 * \param dLambdaLuma
2929 * \param dLambdaChroma
2930 */
2931#if SAO_ENCODING_CHOICE
2932Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma, Int depth)
2933#else
2934Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
2935#endif
2936{
2937  if(m_bUseNIF)
2938  {
2939    m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
2940  }
2941
2942  m_uiSaoBitIncreaseY = max(g_bitDepthY - 10, 0);
2943  m_uiSaoBitIncreaseC = max(g_bitDepthC - 10, 0);
2944  m_iOffsetThY = 1 << min(g_bitDepthY - 5, 5);
2945  m_iOffsetThC = 1 << min(g_bitDepthC - 5, 5);
2946  resetSAOParam(pcSaoParam);
2947  if( !m_saoLcuBasedOptimization || !m_saoLcuBoundary )
2948  {
2949    resetStats();
2950  }
2951  Double dCostFinal = 0;
2952  if ( m_saoLcuBasedOptimization)
2953  {
2954#if SAO_ENCODING_CHOICE
2955    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth);
2956#else
2957    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);
2958#endif
2959  }
2960  else
2961  {
2962    pcSaoParam->bSaoFlag[0] = 1;
2963    pcSaoParam->bSaoFlag[1] = 0;
2964    dCostFinal = 0;
2965    Double lambdaRdo =  dLambdaLuma;
2966    resetStats();
2967    getSaoStats(pcSaoParam->psSaoPart[0], 0);
2968    runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0);
2969    pcSaoParam->bSaoFlag[0] = dCostFinal < 0 ? 1:0;
2970    if(pcSaoParam->bSaoFlag[0])
2971    {
2972      convertQT2SaoUnit(pcSaoParam, 0, 0);
2973      assignSaoUnitSyntax(pcSaoParam->saoLcuParam[0],  pcSaoParam->psSaoPart[0], pcSaoParam->oneUnitFlag[0], 0);
2974    }
2975  }
2976  if (pcSaoParam->bSaoFlag[0])
2977  {
2978    processSaoUnitAll( pcSaoParam->saoLcuParam[0], pcSaoParam->oneUnitFlag[0], 0);
2979  }
2980  if (pcSaoParam->bSaoFlag[1])
2981  {
2982    processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);
2983    processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);
2984  }
2985}
2986/** Check merge SAO unit
2987 * \param saoUnitCurr current SAO unit
2988 * \param saoUnitCheck SAO unit tobe check
2989 * \param dir direction
2990 */
2991Void TEncSampleAdaptiveOffset::checkMerge(SaoLcuParam * saoUnitCurr, SaoLcuParam * saoUnitCheck, Int dir)
2992{
2993  Int i ;
2994  Int countDiff = 0;
2995  if (saoUnitCurr->partIdx != saoUnitCheck->partIdx)
2996  {
2997    if (saoUnitCurr->typeIdx !=-1)
2998    {
2999      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
3000      {
3001        for (i=0;i<saoUnitCurr->length;i++)
3002        {
3003          countDiff += (saoUnitCurr->offset[i] != saoUnitCheck->offset[i]);
3004        }
3005        countDiff += (saoUnitCurr->subTypeIdx != saoUnitCheck->subTypeIdx);
3006        if (countDiff ==0)
3007        {
3008          saoUnitCurr->partIdx = saoUnitCheck->partIdx;
3009          if (dir == 1)
3010          {
3011            saoUnitCurr->mergeUpFlag = 1;
3012            saoUnitCurr->mergeLeftFlag = 0;
3013          }
3014          else
3015          {
3016            saoUnitCurr->mergeUpFlag = 0;
3017            saoUnitCurr->mergeLeftFlag = 1;
3018          }
3019        }
3020      }
3021    }
3022    else
3023    {
3024      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
3025      {
3026        saoUnitCurr->partIdx = saoUnitCheck->partIdx;
3027        if (dir == 1)
3028        {
3029          saoUnitCurr->mergeUpFlag = 1;
3030          saoUnitCurr->mergeLeftFlag = 0;
3031        }
3032        else
3033        {
3034          saoUnitCurr->mergeUpFlag = 0;
3035          saoUnitCurr->mergeLeftFlag = 1;
3036        }
3037      }
3038    }
3039  }
3040}
3041/** Assign SAO unit syntax from picture-based algorithm
3042 * \param saoLcuParam SAO LCU parameters
3043 * \param saoPart SAO part
3044 * \param oneUnitFlag SAO one unit flag
3045 * \param iYCbCr color component Index
3046 */
3047Void TEncSampleAdaptiveOffset::assignSaoUnitSyntax(SaoLcuParam* saoLcuParam,  SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr)
3048{
3049  if (saoPart->bSplit == 0)
3050  {
3051    oneUnitFlag = 1;
3052  }
3053  else
3054  {
3055    Int i,j, addr, addrUp, addrLeft,  idx, idxUp, idxLeft,  idxCount;
3056
3057    oneUnitFlag = 0;
3058
3059    idxCount = -1;
3060    saoLcuParam[0].mergeUpFlag = 0;
3061    saoLcuParam[0].mergeLeftFlag = 0;
3062
3063    for (j=0;j<m_iNumCuInHeight;j++)
3064    {
3065      for (i=0;i<m_iNumCuInWidth;i++)
3066      {
3067        addr     = i + j*m_iNumCuInWidth;
3068        addrLeft = (addr%m_iNumCuInWidth == 0) ? -1 : addr - 1;
3069        addrUp   = (addr<m_iNumCuInWidth)      ? -1 : addr - m_iNumCuInWidth;
3070        idx      = saoLcuParam[addr].partIdxTmp;
3071        idxLeft  = (addrLeft == -1) ? -1 : saoLcuParam[addrLeft].partIdxTmp;
3072        idxUp    = (addrUp == -1)   ? -1 : saoLcuParam[addrUp].partIdxTmp;
3073
3074        if(idx!=idxLeft && idx!=idxUp)
3075        {
3076          saoLcuParam[addr].mergeUpFlag   = 0; idxCount++;
3077          saoLcuParam[addr].mergeLeftFlag = 0;
3078          saoLcuParam[addr].partIdx = idxCount;
3079        }
3080        else if (idx==idxLeft)
3081        {
3082          saoLcuParam[addr].mergeUpFlag   = 1;
3083          saoLcuParam[addr].mergeLeftFlag = 1;
3084          saoLcuParam[addr].partIdx = saoLcuParam[addrLeft].partIdx;
3085        }
3086        else if (idx==idxUp)
3087        {
3088          saoLcuParam[addr].mergeUpFlag   = 1;
3089          saoLcuParam[addr].mergeLeftFlag = 0;
3090          saoLcuParam[addr].partIdx = saoLcuParam[addrUp].partIdx;
3091        }
3092        if (addrUp != -1)
3093        {
3094          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrUp], 1);
3095        }
3096        if (addrLeft != -1)
3097        {
3098          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);
3099        }
3100      }
3101    }
3102  }
3103}
3104/** rate distortion optimization of all SAO units
3105 * \param saoParam SAO parameters
3106 * \param lambda
3107 * \param lambdaChroma
3108 */
3109#if SAO_ENCODING_CHOICE
3110Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
3111#else
3112Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
3113#endif
3114{
3115
3116  Int idxY;
3117  Int idxX;
3118  Int frameHeightInCU = saoParam->numCuInHeight;
3119  Int frameWidthInCU  = saoParam->numCuInWidth;
3120  Int j, k;
3121  Int addr = 0;
3122  Int addrUp = -1;
3123  Int addrLeft = -1;
3124  Int compIdx = 0;
3125  SaoLcuParam mergeSaoParam[3][2];
3126  Double compDistortion[3];
3127
3128  saoParam->bSaoFlag[0] = true;
3129#if AUXILIARY_PICTURES
3130  saoParam->bSaoFlag[1] = m_pcPic->getChromaFormat() == CHROMA_400 ? false : true;
3131#else
3132  saoParam->bSaoFlag[1] = true;
3133#endif
3134  saoParam->oneUnitFlag[0] = false;
3135  saoParam->oneUnitFlag[1] = false;
3136  saoParam->oneUnitFlag[2] = false;
3137
3138#if SAO_ENCODING_CHOICE
3139#if SAO_ENCODING_CHOICE_CHROMA
3140  Int numNoSao[2];
3141  numNoSao[0] = 0;// Luma
3142  numNoSao[1] = 0;// Chroma
3143  if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
3144  {
3145    saoParam->bSaoFlag[0] = false;
3146  }
3147  if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
3148  {
3149    saoParam->bSaoFlag[1] = false;
3150  }
3151#else
3152  Int numNoSao = 0;
3153
3154  if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
3155  {
3156    saoParam->bSaoFlag[0] = false;
3157    saoParam->bSaoFlag[1] = false;
3158  }
3159#endif
3160#endif
3161
3162  for (idxY = 0; idxY< frameHeightInCU; idxY++)
3163  {
3164    for (idxX = 0; idxX< frameWidthInCU; idxX++)
3165    {
3166      addr     = idxX  + frameWidthInCU*idxY;
3167      addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
3168      addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
3169      Int allowMergeLeft = 1;
3170      Int allowMergeUp   = 1;
3171      UInt rate;
3172      Double bestCost, mergeCost;
3173      if (idxX!=0)
3174      { 
3175        // check tile id and slice id
3176        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
3177        {
3178          allowMergeLeft = 0;
3179        }
3180      }
3181      else
3182      {
3183        allowMergeLeft = 0;
3184      }
3185      if (idxY!=0)
3186      {
3187        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
3188        {
3189          allowMergeUp = 0;
3190        }
3191      }
3192      else
3193      {
3194        allowMergeUp = 0;
3195      }
3196
3197      compDistortion[0] = 0; 
3198      compDistortion[1] = 0; 
3199      compDistortion[2] = 0;
3200      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
3201      if (allowMergeLeft)
3202      {
3203        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
3204      }
3205      if (allowMergeUp)
3206      {
3207        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
3208      }
3209      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
3210      // reset stats Y, Cb, Cr
3211      for ( compIdx=0;compIdx<3;compIdx++)
3212      {
3213        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
3214        {
3215          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
3216          {
3217            m_iOffset   [compIdx][j][k] = 0;
3218            if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){
3219              m_iCount    [compIdx][j][k] = m_count_PreDblk    [addr][compIdx][j][k];
3220              m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
3221            }
3222            else
3223            {
3224              m_iCount    [compIdx][j][k] = 0;
3225              m_iOffsetOrg[compIdx][j][k] = 0;
3226            }
3227          } 
3228        }
3229        saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
3230        saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
3231        saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
3232        saoParam->saoLcuParam[compIdx][addr].subTypeIdx    = 0;
3233#if SAO_ENCODING_CHOICE
3234  if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
3235#endif
3236        {
3237          calcSaoStatsCu(addr, compIdx,  compIdx);
3238
3239       }
3240      }
3241      saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0,  lambda, &mergeSaoParam[0][0], &compDistortion[0]);
3242      sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
3243     if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] )
3244      {
3245        // Cost of new SAO_params
3246        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
3247        m_pcRDGoOnSbacCoder->resetBits();
3248        if (allowMergeLeft)
3249        {
3250          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
3251        }
3252        if (allowMergeUp)
3253        {
3254          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
3255        }
3256        for ( compIdx=0;compIdx<3;compIdx++)
3257        {
3258        if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1]))
3259          {
3260           m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx);
3261          }
3262        }
3263
3264        rate = m_pcEntropyCoder->getNumberOfWrittenBits();
3265        bestCost = compDistortion[0] + (Double)rate;
3266        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3267
3268        // Cost of Merge
3269        for(Int mergeUp=0; mergeUp<2; ++mergeUp)
3270        {
3271          if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) )
3272          {
3273            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
3274            m_pcRDGoOnSbacCoder->resetBits();
3275            if (allowMergeLeft)
3276            {
3277              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); 
3278            }
3279            if ( allowMergeUp && (mergeUp==1) )
3280            {
3281              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); 
3282            }
3283
3284            rate = m_pcEntropyCoder->getNumberOfWrittenBits();
3285            mergeCost = compDistortion[mergeUp+1] + (Double)rate;
3286            if (mergeCost < bestCost)
3287            {
3288              bestCost = mergeCost;
3289              m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);             
3290              for ( compIdx=0;compIdx<3;compIdx++)
3291              {
3292                mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp;
3293                mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;
3294                if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1]))
3295                {
3296                  copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );             
3297                }
3298              }
3299            }
3300          }
3301        }
3302#if SAO_ENCODING_CHOICE
3303#if SAO_ENCODING_CHOICE_CHROMA
3304if( saoParam->saoLcuParam[0][addr].typeIdx == -1)
3305{
3306  numNoSao[0]++;
3307}
3308if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
3309{
3310  numNoSao[1]+=2;
3311}
3312#else
3313        for ( compIdx=0;compIdx<3;compIdx++)
3314        {
3315          if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
3316          {
3317            numNoSao++;
3318          }
3319        }
3320#endif
3321#endif
3322        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3323        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
3324      }
3325    }
3326  }
3327#if SAO_ENCODING_CHOICE
3328#if SAO_ENCODING_CHOICE_CHROMA
3329  if( !saoParam->bSaoFlag[0])
3330  {
3331    m_depthSaoRate[0][depth] = 1.0;
3332  }
3333  else
3334  {
3335    m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
3336  }
3337  if( !saoParam->bSaoFlag[1]) 
3338  {
3339    m_depthSaoRate[1][depth] = 1.0;
3340  }
3341  else 
3342  {
3343    m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
3344  }
3345#else
3346  if( depth == 0)
3347  {
3348    // update SAO Rate
3349    m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
3350  }
3351#endif
3352#endif
3353
3354}
3355/** rate distortion optimization of SAO unit
3356 * \param saoParam SAO parameters
3357 * \param addr address
3358 * \param addrUp above address
3359 * \param addrLeft left address
3360 * \param yCbCr color component index
3361 * \param lambda
3362 */
3363inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)
3364{
3365  Int64 estDist = 0;
3366  Int classIdx;
3367  Int bitDepth = (compIdx==0) ? g_bitDepthY : g_bitDepthC;
3368  Int saoBitIncrease = (compIdx==0) ? m_uiSaoBitIncreaseY : m_uiSaoBitIncreaseC;
3369  Int saoOffsetTh = (compIdx==0) ? m_iOffsetThY : m_iOffsetThC;
3370
3371  for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
3372  {
3373    if( typeIdx == SAO_BO)
3374    {
3375      currentDistortionTableBo[classIdx-1] = 0;
3376      currentRdCostTableBo[classIdx-1] = lambda;
3377    }
3378    if(m_iCount [compIdx][typeIdx][classIdx])
3379    {
3380      m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi(bitDepth, (Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<(bitDepth-8)) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<saoBitIncrease));
3381      m_iOffset[compIdx][typeIdx][classIdx] = Clip3(-saoOffsetTh+1, saoOffsetTh-1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);
3382      if (typeIdx < 4)
3383      {
3384        if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )
3385        {
3386          m_iOffset[compIdx][typeIdx][classIdx] = 0;
3387        }
3388        if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)
3389        {
3390          m_iOffset[compIdx][typeIdx][classIdx] = 0;
3391        }
3392      }
3393      m_iOffset[compIdx][typeIdx][classIdx] = estIterOffset( typeIdx, classIdx, lambda, m_iOffset[compIdx][typeIdx][classIdx], m_iCount [compIdx][typeIdx][classIdx], m_iOffsetOrg[compIdx][typeIdx][classIdx], shift, saoBitIncrease, currentDistortionTableBo, currentRdCostTableBo, saoOffsetTh );
3394    }
3395    else
3396    {
3397      m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;
3398      m_iOffset[compIdx][typeIdx][classIdx] = 0;
3399    }
3400    if( typeIdx != SAO_BO )
3401    {
3402      estDist   += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << saoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);
3403    }
3404
3405  }
3406  return estDist;
3407}
3408
3409inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
3410{
3411  return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
3412}
3413inline Int64 TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo, Int offsetTh )
3414{
3415  //Clean up, best_q_offset.
3416  Int64 iterOffset, tempOffset;
3417  Int64 tempDist, tempRate;
3418  Double tempCost, tempMinCost;
3419  Int64 offsetOutput = 0;
3420  iterOffset = offsetInput;
3421  // 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.
3422  tempMinCost = lambda; 
3423  while (iterOffset != 0)
3424  {
3425    // Calculate the bits required for signalling the offset
3426    tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
3427    if (abs((Int)iterOffset)==offsetTh-1) 
3428    { 
3429      tempRate --;
3430    }
3431    // Do the dequntization before distorion calculation
3432    tempOffset  = iterOffset << bitIncrease;
3433    tempDist    = estSaoDist( count, tempOffset, offsetOrg, shift);
3434    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
3435    if(tempCost < tempMinCost)
3436    {
3437      tempMinCost = tempCost;
3438      offsetOutput = iterOffset;
3439      if(typeIdx == SAO_BO)
3440      {
3441        currentDistortionTableBo[classIdx-1] = (Int) tempDist;
3442        currentRdCostTableBo[classIdx-1] = tempCost;
3443      }
3444    }
3445    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
3446  }
3447  return offsetOutput;
3448}
3449
3450
3451Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
3452{
3453  Int typeIdx;
3454
3455  Int64 estDist;
3456  Int classIdx;
3457  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8);
3458  Int64 bestDist;
3459
3460  SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
3461  SaoLcuParam*  saoLcuParamNeighbor = NULL; 
3462
3463  resetSaoUnit(saoLcuParam);
3464  resetSaoUnit(&compSaoParam[0]);
3465  resetSaoUnit(&compSaoParam[1]);
3466
3467
3468  Double dCostPartBest = MAX_DOUBLE;
3469
3470  Double  bestRDCostTableBo = MAX_DOUBLE;
3471  Int     bestClassTableBo    = 0;
3472  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
3473  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
3474
3475
3476  SaoLcuParam   saoLcuParamRdo;   
3477  Double   estRate = 0;
3478
3479  resetSaoUnit(&saoLcuParamRdo);
3480
3481  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3482  m_pcRDGoOnSbacCoder->resetBits();
3483 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
3484 
3485  dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
3486  copySaoUnit(saoLcuParam, &saoLcuParamRdo );
3487  bestDist = 0;
3488 
3489
3490
3491  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
3492  {
3493    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
3494
3495    if( typeIdx == SAO_BO )
3496    {
3497      // Estimate Best Position
3498      Double currentRDCost = 0.0;
3499
3500      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
3501      {
3502        currentRDCost = 0.0;
3503        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
3504        {
3505          currentRDCost += currentRdCostTableBo[uj];
3506        }
3507
3508        if( currentRDCost < bestRDCostTableBo)
3509        {
3510          bestRDCostTableBo = currentRDCost;
3511          bestClassTableBo  = i;
3512        }
3513      }
3514
3515      // Re code all Offsets
3516      // Code Center
3517      estDist = 0;
3518      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
3519      {
3520        estDist += currentDistortionTableBo[classIdx];
3521      }
3522    }
3523    resetSaoUnit(&saoLcuParamRdo);
3524    saoLcuParamRdo.length = m_iNumClass[typeIdx];
3525    saoLcuParamRdo.typeIdx = typeIdx;
3526    saoLcuParamRdo.mergeLeftFlag = 0;
3527    saoLcuParamRdo.mergeUpFlag   = 0;
3528    saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
3529    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
3530    {
3531      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
3532    }
3533    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3534    m_pcRDGoOnSbacCoder->resetBits();
3535    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
3536
3537    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
3538    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
3539
3540    if(m_dCost[yCbCr][typeIdx] < dCostPartBest)
3541    {
3542      dCostPartBest = m_dCost[yCbCr][typeIdx];
3543      copySaoUnit(saoLcuParam, &saoLcuParamRdo );
3544      bestDist = estDist;       
3545    }
3546  }
3547  compDistortion[0] += ((Double)bestDist/lambda);
3548  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3549 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
3550  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
3551
3552
3553  // merge left or merge up
3554
3555  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
3556  {
3557    saoLcuParamNeighbor = NULL;
3558    if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
3559    {
3560      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
3561    }
3562    else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
3563    {
3564      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
3565    }
3566    if (saoLcuParamNeighbor!=NULL)
3567    {
3568      estDist = 0;
3569      typeIdx = saoLcuParamNeighbor->typeIdx;
3570      if (typeIdx>=0) 
3571      {
3572        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
3573        Int   merge_iOffset;
3574        for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
3575        {
3576          merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
3577          estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
3578        }
3579      }
3580      else
3581      {
3582        estDist = 0;
3583      }
3584
3585      copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
3586      compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
3587      compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
3588
3589      compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
3590    } 
3591  } 
3592}
3593Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)
3594{
3595  Int typeIdx;
3596
3597  Int64 estDist[2];
3598  Int classIdx;
3599  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC-8);
3600  Int64 bestDist = 0;
3601
3602  SaoLcuParam*  saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])};
3603  SaoLcuParam*  saoLcuParamNeighbor[2] = {NULL, NULL}; 
3604  SaoLcuParam*  saoMergeParam[2][2];
3605  saoMergeParam[0][0] = &crSaoParam[0];
3606  saoMergeParam[0][1] = &crSaoParam[1]; 
3607  saoMergeParam[1][0] = &cbSaoParam[0];
3608  saoMergeParam[1][1] = &cbSaoParam[1];
3609
3610  resetSaoUnit(saoLcuParam[0]);
3611  resetSaoUnit(saoLcuParam[1]);
3612  resetSaoUnit(saoMergeParam[0][0]);
3613  resetSaoUnit(saoMergeParam[0][1]);
3614  resetSaoUnit(saoMergeParam[1][0]);
3615  resetSaoUnit(saoMergeParam[1][1]);
3616
3617
3618  Double costPartBest = MAX_DOUBLE;
3619
3620  Double  bestRDCostTableBo;
3621  Int     bestClassTableBo[2]    = {0, 0};
3622  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
3623  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
3624
3625  SaoLcuParam   saoLcuParamRdo[2];   
3626  Double   estRate = 0;
3627
3628  resetSaoUnit(&saoLcuParamRdo[0]);
3629  resetSaoUnit(&saoLcuParamRdo[1]);
3630
3631  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3632  m_pcRDGoOnSbacCoder->resetBits();
3633  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1);
3634  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2);
3635 
3636  costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
3637  copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
3638  copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
3639
3640  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
3641  {
3642    if( typeIdx == SAO_BO )
3643    {
3644      // Estimate Best Position
3645      for(Int compIdx = 0; compIdx < 2; compIdx++)
3646      {
3647        Double currentRDCost = 0.0;
3648        bestRDCostTableBo = MAX_DOUBLE;
3649        estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
3650        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
3651        {
3652          currentRDCost = 0.0;
3653          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
3654          {
3655            currentRDCost += currentRdCostTableBo[uj];
3656          }
3657
3658          if( currentRDCost < bestRDCostTableBo)
3659          {
3660            bestRDCostTableBo = currentRDCost;
3661            bestClassTableBo[compIdx]  = i;
3662          }
3663        }
3664
3665        // Re code all Offsets
3666        // Code Center
3667        estDist[compIdx] = 0;
3668        for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)
3669        {
3670          estDist[compIdx] += currentDistortionTableBo[classIdx];
3671        }
3672      }
3673    }
3674    else
3675    {
3676      estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
3677      estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
3678    }
3679
3680    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3681    m_pcRDGoOnSbacCoder->resetBits();
3682
3683    for(Int compIdx = 0; compIdx < 2; compIdx++)
3684    {
3685      resetSaoUnit(&saoLcuParamRdo[compIdx]);
3686      saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];
3687      saoLcuParamRdo[compIdx].typeIdx = typeIdx;
3688      saoLcuParamRdo[compIdx].mergeLeftFlag = 0;
3689      saoLcuParamRdo[compIdx].mergeUpFlag   = 0;
3690      saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
3691      for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)
3692      {
3693        saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];
3694      }
3695
3696      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);
3697    }
3698    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
3699    m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1])  + lambda * (Double) estRate);
3700   
3701    if(m_dCost[1][typeIdx] < costPartBest)
3702    {
3703      costPartBest = m_dCost[1][typeIdx];
3704      copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
3705      copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
3706      bestDist = (estDist[0]+estDist[1]);       
3707    }
3708  }
3709
3710  distortion[0] += ((Double)bestDist/lambda);
3711  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
3712  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1);
3713  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2);
3714  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
3715
3716  // merge left or merge up
3717
3718  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
3719  {
3720    for(Int compIdx = 0; compIdx < 2; compIdx++)
3721    {
3722      saoLcuParamNeighbor[compIdx] = NULL;
3723      if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
3724      {
3725        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrLeft]);
3726      }
3727      else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
3728      {
3729        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrUp]);
3730      }
3731      if (saoLcuParamNeighbor[compIdx]!=NULL)
3732      {
3733        estDist[compIdx] = 0;
3734        typeIdx = saoLcuParamNeighbor[compIdx]->typeIdx;
3735        if (typeIdx>=0) 
3736        {
3737          Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->subTypeIdx:0;
3738          Int   merge_iOffset;
3739          for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
3740          {
3741            merge_iOffset = saoLcuParamNeighbor[compIdx]->offset[classIdx];
3742            estDist[compIdx]   += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1],  shift);
3743          }
3744        }
3745        else
3746        {
3747          estDist[compIdx] = 0;
3748        }
3749
3750        copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );
3751        saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag   = idxNeighbor;
3752        saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor;
3753        distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);
3754      }
3755    } 
3756  } 
3757}
3758
3759#endif
3760
3761//! \}
Note: See TracBrowser for help on using the repository browser.