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

Last change on this file since 567 was 2, checked in by seregin, 12 years ago

Initial import by Vadim Seregin <vseregin@…>

File size: 93.1 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-2012, 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/** \file     TEncSampleAdaptiveOffset.cpp
35 \brief       estimation part of sample adaptive offset class
36 */
37#include "TEncSampleAdaptiveOffset.h"
38#include <string.h>
39#include <stdlib.h>
40#include <stdio.h>
41#include <math.h>
42
43//! \ingroup TLibEncoder
44//! \{
45
46TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
47{
48  m_pcEntropyCoder = NULL;
49  m_pppcRDSbacCoder = NULL;
50  m_pcRDGoOnSbacCoder = NULL;
51  m_pppcBinCoderCABAC = NULL;           
52  m_iCount = NULL;     
53  m_iOffset = NULL;     
54  m_iOffsetOrg = NULL; 
55  m_iRate = NULL;       
56  m_iDist = NULL;       
57  m_dCost = NULL;       
58  m_dCostPartBest = NULL; 
59  m_iDistOrg = NULL;     
60  m_iTypePartBest = NULL; 
61#if SAO_ENCODING_CHOICE_CHROMA
62  m_depthSaoRate[0][0] = 0;
63  m_depthSaoRate[0][1] = 0;
64  m_depthSaoRate[0][2] = 0;
65  m_depthSaoRate[0][3] = 0;
66  m_depthSaoRate[1][0] = 0;
67  m_depthSaoRate[1][1] = 0;
68  m_depthSaoRate[1][2] = 0;
69  m_depthSaoRate[1][3] = 0;
70#endif
71}
72TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
73{
74
75}
76// ====================================================================================================================
77// Constants
78// ====================================================================================================================
79
80
81// ====================================================================================================================
82// Tables
83// ====================================================================================================================
84
85inline Double xRoundIbdi2(Double x)
86{
87#if FULL_NBIT
88  Int bitDepthMinus8 = g_uiBitDepth - 8;
89  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)) : ((Int)(((Int)(x)-(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)));
90#else
91  return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)-(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)));
92#endif
93}
94
95/** rounding with IBDI
96 * \param  x
97 */
98inline Double xRoundIbdi(Double x)
99{
100#if FULL_NBIT
101  return (g_uiBitDepth > 8 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
102#else
103  return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
104#endif
105}
106
107
108
109/** process SAO for one partition
110 * \param  *psQTPart, iPartIdx, dLambda
111 */
112#if PICTURE_SAO_RDO_FIX
113Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda, Int yCbCr)
114#else
115Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda)
116#endif
117{
118  Int iTypeIdx;
119  Int iNumTotalType = MAX_NUM_SAO_TYPE;
120  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
121
122  Int64 iEstDist;
123  Int iClassIdx;
124  Int uiShift = g_uiBitIncrement << 1;
125  UInt uiDepth = pOnePart->PartLevel;
126
127  m_iDistOrg [iPartIdx] =  0;
128
129  Double  bestRDCostTableBo = MAX_DOUBLE;
130  Int     bestClassTableBo    = 0;
131  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
132  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
133
134#if PICTURE_SAO_RDO_FIX
135  Int addr;
136  Int allowMergeLeft;
137  Int allowMergeUp;
138  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
139  SaoLcuParam  saoLcuParamRdo;
140#endif
141
142  for (iTypeIdx=-1; iTypeIdx<iNumTotalType; iTypeIdx++)
143  {
144    if( m_bUseSBACRD )
145    {
146      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
147      m_pcRDGoOnSbacCoder->resetBits();
148    }
149    else
150    {
151      m_pcEntropyCoder->resetEntropy();
152      m_pcEntropyCoder->resetBits();
153    }
154
155    iEstDist = 0;
156
157#if PICTURE_SAO_RDO_FIX
158    if (iTypeIdx == -1)
159    {     
160      for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
161      {
162        for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
163        {
164          addr = ry * frameWidthInCU + rx;         
165
166          // get bits for iTypeIdx = -1
167          allowMergeLeft = 1;
168          allowMergeUp   = 1;
169          if (rx != 0)
170          { 
171            // check tile id and slice id
172            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()))
173            {
174              allowMergeLeft = 0;
175            }
176          }
177          if (ry!=0)
178          {
179            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()))
180            {
181              allowMergeUp = 0;
182            }
183          }
184
185          // reset
186          resetSaoUnit(&saoLcuParamRdo);
187
188          // set merge flag
189          saoLcuParamRdo.mergeUpFlag   = 1;
190          saoLcuParamRdo.mergeLeftFlag = 1;
191
192          if (ry == pOnePart->StartCUY) 
193          {
194            saoLcuParamRdo.mergeUpFlag = 0;
195          } 
196         
197          if (rx == pOnePart->StartCUX) 
198          {
199            saoLcuParamRdo.mergeLeftFlag = 0;
200          }
201
202          m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
203
204        }
205      }
206    }
207#else
208    m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoTypeIdx(iTypeIdx+1);
209#endif
210
211    if (iTypeIdx>=0)
212    {
213      iEstDist = estSaoTypeDist(iPartIdx, iTypeIdx, uiShift, dLambda, currentDistortionTableBo, currentRdCostTableBo);
214      if( iTypeIdx == SAO_BO )
215      {
216        // Estimate Best Position
217        Double currentRDCost = 0.0;
218
219        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
220        {
221          currentRDCost = 0.0;
222          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
223          {
224            currentRDCost += currentRdCostTableBo[uj];
225          }
226
227          if( currentRDCost < bestRDCostTableBo)
228          {
229            bestRDCostTableBo = currentRDCost;
230            bestClassTableBo  = i;
231          }
232        }
233
234        // Re code all Offsets
235        // Code Center
236        for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++)
237        {
238          iEstDist += currentDistortionTableBo[iClassIdx];
239        }
240      }
241
242#if PICTURE_SAO_RDO_FIX     
243      for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
244      {
245        for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
246        {
247          addr = ry * frameWidthInCU + rx;         
248
249          // get bits for iTypeIdx = -1
250          allowMergeLeft = 1;
251          allowMergeUp   = 1;
252          if (rx != 0)
253          { 
254            // check tile id and slice id
255            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()))
256            {
257              allowMergeLeft = 0;
258            }
259          }
260          if (ry!=0)
261          {
262            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()))
263            {
264              allowMergeUp = 0;
265            }
266          }
267
268          // reset
269          resetSaoUnit(&saoLcuParamRdo);
270         
271          // set merge flag
272          saoLcuParamRdo.mergeUpFlag   = 1;
273          saoLcuParamRdo.mergeLeftFlag = 1;
274
275          if (ry == pOnePart->StartCUY) 
276          {
277            saoLcuParamRdo.mergeUpFlag = 0;
278          } 
279         
280          if (rx == pOnePart->StartCUX) 
281          {
282            saoLcuParamRdo.mergeLeftFlag = 0;
283          }
284
285          // set type and offsets
286          saoLcuParamRdo.typeIdx = iTypeIdx;
287#if SAO_TYPE_CODING
288          saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
289#else
290          saoLcuParamRdo.bandPosition = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
291#endif       
292          saoLcuParamRdo.length = m_iNumClass[iTypeIdx];
293          for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++)
294          {
295#if SAO_TYPE_CODING
296            saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1];
297#else
298            saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.bandPosition+1];
299#endif           
300          }
301
302          m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
303
304        }
305      }
306#else // #if PICTURE_SAO_RDO_FIX
307
308      SaoLcuParam  saoLcuParamRdo;   
309      resetSaoUnit(&saoLcuParamRdo);
310      saoLcuParamRdo.typeIdx = iTypeIdx;
311#if SAO_TYPE_CODING
312      saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
313#else
314      saoLcuParamRdo.bandPosition = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
315#endif
316      saoLcuParamRdo.length = m_iNumClass[iTypeIdx];
317      for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++)
318      {
319#if SAO_TYPE_CODING
320        saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1];
321#else
322        saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.bandPosition+1];
323#endif
324      }
325      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
326      m_pcRDGoOnSbacCoder->resetBits();
327#if SAO_TYPE_SHARING
328      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, iPartIdx);
329#else
330      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo);
331#endif
332#endif // #if PICTURE_SAO_RDO_FIX
333
334      m_iDist[iPartIdx][iTypeIdx] = iEstDist;
335      m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder->getNumberOfWrittenBits();
336
337      m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]);
338
339      if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx])
340      {
341        m_iDistOrg [iPartIdx] = 0;
342        m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx];
343        m_iTypePartBest[iPartIdx] = iTypeIdx;
344        if( m_bUseSBACRD )
345          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
346      }
347    }
348    else
349    {
350      if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] )
351      {
352        m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder->getNumberOfWrittenBits()*dLambda ; 
353        m_iTypePartBest[iPartIdx] = -1;
354        if( m_bUseSBACRD )
355          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
356      }
357    }
358  }
359
360  pOnePart->bProcessed = true;
361  pOnePart->bSplit     = false;
362  pOnePart->iMinDist   =        m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];
363  pOnePart->iMinRate   = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);
364  pOnePart->dMinCost   = pOnePart->iMinDist + dLambda * pOnePart->iMinRate;
365  pOnePart->iBestType  = m_iTypePartBest[iPartIdx];
366  if (pOnePart->iBestType != -1)
367  {
368    //     pOnePart->bEnableFlag =  1;
369    pOnePart->iLength = m_iNumClass[pOnePart->iBestType];
370    Int minIndex = 0;
371    if( pOnePart->iBestType == SAO_BO )
372    {
373#if SAO_TYPE_CODING
374      pOnePart->subTypeIdx = bestClassTableBo;
375      minIndex = pOnePart->subTypeIdx;
376#else
377      pOnePart->bandPosition = bestClassTableBo;
378      minIndex = pOnePart->bandPosition;
379#endif
380    }
381    for (Int i=0; i< pOnePart->iLength ; i++)
382    {
383      pOnePart->iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart->iBestType][minIndex+i+1];
384    }
385
386  }
387  else
388  {
389    //     pOnePart->bEnableFlag = 0;
390    pOnePart->iLength     = 0;
391  }
392}
393
394/** Run partition tree disable
395 */
396Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx)
397{
398  SAOQTPart*  pOnePart= &(psQTPart[iPartIdx]);
399  pOnePart->bSplit      = false;
400  pOnePart->iLength     =  0;
401  pOnePart->iBestType   = -1;
402
403  if (pOnePart->PartLevel < m_uiMaxSplitLevel)
404  {
405    for (Int i=0; i<NUM_DOWN_PART; i++)
406    {
407      disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
408    }
409  }
410}
411
412/** Run quadtree decision function
413 * \param  iPartIdx, pcPicOrg, pcPicDec, pcPicRest, &dCostFinal
414 */
415#if PICTURE_SAO_RDO_FIX
416Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda, Int yCbCr)
417#else
418Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda)
419#endif
420{
421  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
422
423  UInt uiDepth = pOnePart->PartLevel;
424  UInt uhNextDepth = uiDepth+1;
425
426  if (iPartIdx == 0)
427  {
428    dCostFinal = 0;
429  }
430
431  //SAO for this part
432  if(!pOnePart->bProcessed)
433  {
434#if PICTURE_SAO_RDO_FIX
435    rdoSaoOnePart (psQTPart, iPartIdx, dLambda, yCbCr);
436#else
437    rdoSaoOnePart (psQTPart, iPartIdx, dLambda);
438#endif
439  }
440
441  //SAO for sub 4 parts
442  if (pOnePart->PartLevel < iMaxLevel)
443  {
444    Double      dCostNotSplit = dLambda + pOnePart->dMinCost;
445    Double      dCostSplit    = dLambda;
446
447    for (Int i=0; i< NUM_DOWN_PART ;i++)
448    {
449      if( m_bUseSBACRD ) 
450      {
451        if ( 0 == i) //initialize RD with previous depth buffer
452        {
453          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
454        }
455        else
456        {
457          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
458        }
459      } 
460#if PICTURE_SAO_RDO_FIX
461      runQuadTreeDecision(psQTPart, pOnePart->DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda, yCbCr);
462#else
463      runQuadTreeDecision(psQTPart, pOnePart->DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda);
464#endif
465      dCostSplit += dCostFinal;
466      if( m_bUseSBACRD )
467      {
468        m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]);
469      }
470    }
471
472    if(dCostSplit < dCostNotSplit)
473    {
474      dCostFinal = dCostSplit;
475      pOnePart->bSplit      = true;
476      pOnePart->iLength     =  0;
477      pOnePart->iBestType   = -1;
478      if( m_bUseSBACRD )
479      {
480        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
481      }
482    }
483    else
484    {
485      dCostFinal = dCostNotSplit;
486      pOnePart->bSplit = false;
487      for (Int i=0; i<NUM_DOWN_PART; i++)
488      {
489        disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
490      }
491      if( m_bUseSBACRD )
492      {
493        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
494      }
495    }
496  }
497  else
498  {
499    dCostFinal = pOnePart->dMinCost;
500  }
501}
502
503/** delete allocated memory of TEncSampleAdaptiveOffset class.
504 */
505Void TEncSampleAdaptiveOffset::destroyEncBuffer()
506{
507  for (Int i=0;i<m_iNumTotalParts;i++)
508  {
509    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
510    {
511      if (m_iCount [i][j])
512      {
513        delete [] m_iCount [i][j]; 
514      }
515      if (m_iOffset[i][j])
516      {
517        delete [] m_iOffset[i][j]; 
518      }
519      if (m_iOffsetOrg[i][j])
520      {
521        delete [] m_iOffsetOrg[i][j]; 
522      }
523    }
524    if (m_iRate[i])
525    {
526      delete [] m_iRate[i];
527    }
528    if (m_iDist[i])
529    {
530      delete [] m_iDist[i]; 
531    }
532    if (m_dCost[i])
533    {
534      delete [] m_dCost[i]; 
535    }
536    if (m_iCount [i])
537    {
538      delete [] m_iCount [i]; 
539    }
540    if (m_iOffset[i])
541    {
542      delete [] m_iOffset[i]; 
543    }
544    if (m_iOffsetOrg[i])
545    {
546      delete [] m_iOffsetOrg[i]; 
547    }
548
549  }
550  if (m_iDistOrg)
551  {
552    delete [] m_iDistOrg ; m_iDistOrg = NULL;
553  }
554  if (m_dCostPartBest)
555  {
556    delete [] m_dCostPartBest ; m_dCostPartBest = NULL;
557  }
558  if (m_iTypePartBest)
559  {
560    delete [] m_iTypePartBest ; m_iTypePartBest = NULL;
561  }
562  if (m_iRate)
563  {
564    delete [] m_iRate ; m_iRate = NULL;
565  }
566  if (m_iDist)
567  {
568    delete [] m_iDist ; m_iDist = NULL;
569  }
570  if (m_dCost)
571  {
572    delete [] m_dCost ; m_dCost = NULL;
573  }
574  if (m_iCount)
575  {
576    delete [] m_iCount  ; m_iCount = NULL;
577  }
578  if (m_iOffset)
579  {
580    delete [] m_iOffset ; m_iOffset = NULL;
581  }
582  if (m_iOffsetOrg)
583  {
584    delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;
585  }
586#if SAO_LCU_BOUNDARY
587  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
588
589  for (Int i=0;i<numLcu;i++)
590  {
591    for (Int j=0;j<3;j++)
592    {
593      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
594      {
595        if (m_count_PreDblk [i][j][k])
596        {
597          delete [] m_count_PreDblk [i][j][k]; 
598        }
599        if (m_offsetOrg_PreDblk[i][j][k])
600        {
601          delete [] m_offsetOrg_PreDblk[i][j][k];
602        }
603      }
604      if (m_count_PreDblk [i][j])
605      {
606        delete [] m_count_PreDblk [i][j]; 
607      }
608      if (m_offsetOrg_PreDblk[i][j])
609      {
610        delete [] m_offsetOrg_PreDblk[i][j]; 
611      }
612    }
613    if (m_count_PreDblk [i])
614    {
615      delete [] m_count_PreDblk [i]; 
616    }
617    if (m_offsetOrg_PreDblk[i])
618    {
619      delete [] m_offsetOrg_PreDblk[i]; 
620    }
621  }
622  if (m_count_PreDblk)
623  {
624    delete [] m_count_PreDblk  ; m_count_PreDblk = NULL;
625  }
626  if (m_offsetOrg_PreDblk)
627  {
628    delete [] m_offsetOrg_PreDblk ; m_offsetOrg_PreDblk = NULL;
629  }
630#endif
631
632  Int iMaxDepth = 4;
633  Int iDepth;
634  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
635  {
636    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
637    {
638      delete m_pppcRDSbacCoder[iDepth][iCIIdx];
639      delete m_pppcBinCoderCABAC[iDepth][iCIIdx];
640    }
641  }
642
643  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
644  {
645    delete [] m_pppcRDSbacCoder[iDepth];
646    delete [] m_pppcBinCoderCABAC[iDepth];
647  }
648
649  delete [] m_pppcRDSbacCoder;
650  delete [] m_pppcBinCoderCABAC;
651}
652
653/** create Encoder Buffer for SAO
654 * \param
655 */
656Void TEncSampleAdaptiveOffset::createEncBuffer()
657{
658  m_iDistOrg = new Int64 [m_iNumTotalParts]; 
659  m_dCostPartBest = new Double [m_iNumTotalParts]; 
660  m_iTypePartBest = new Int [m_iNumTotalParts]; 
661
662  m_iRate = new Int64* [m_iNumTotalParts];
663  m_iDist = new Int64* [m_iNumTotalParts];
664  m_dCost = new Double*[m_iNumTotalParts];
665
666  m_iCount  = new Int64 **[m_iNumTotalParts];
667  m_iOffset = new Int64 **[m_iNumTotalParts];
668  m_iOffsetOrg = new Int64 **[m_iNumTotalParts];
669
670  for (Int i=0;i<m_iNumTotalParts;i++)
671  {
672    m_iRate[i] = new Int64  [MAX_NUM_SAO_TYPE];
673    m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE]; 
674    m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 
675
676    m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
677    m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
678    m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
679
680    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
681    {
682      m_iCount [i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
683      m_iOffset[i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
684      m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 
685    }
686  }
687#if SAO_LCU_BOUNDARY
688  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
689  m_count_PreDblk  = new Int64 ***[numLcu];
690  m_offsetOrg_PreDblk = new Int64 ***[numLcu];
691  for (Int i=0; i<numLcu; i++)
692  {
693    m_count_PreDblk[i]  = new Int64 **[3];
694    m_offsetOrg_PreDblk[i] = new Int64 **[3];
695
696    for (Int j=0;j<3;j++)
697    {
698      m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
699      m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
700
701      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
702      {
703        m_count_PreDblk [i][j][k]   = new Int64 [MAX_NUM_SAO_CLASS]; 
704        m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS]; 
705      }
706    }
707  }
708#endif
709
710  Int iMaxDepth = 4;
711  m_pppcRDSbacCoder = new TEncSbac** [iMaxDepth+1];
712#if FAST_BIT_EST
713  m_pppcBinCoderCABAC = new TEncBinCABACCounter** [iMaxDepth+1];
714#else
715  m_pppcBinCoderCABAC = new TEncBinCABAC** [iMaxDepth+1];
716#endif
717
718  for ( Int iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
719  {
720    m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM];
721#if FAST_BIT_EST
722    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM];
723#else
724    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM];
725#endif
726    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
727    {
728      m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac;
729#if FAST_BIT_EST
730      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter;
731#else
732      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC;
733#endif
734      m_pppcRDSbacCoder   [iDepth][iCIIdx]->init( m_pppcBinCoderCABAC [iDepth][iCIIdx] );
735    }
736  }
737}
738
739/** Start SAO encoder
740 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
741 */
742Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
743{
744    m_bUseSBACRD = true;
745  m_pcPic = pcPic;
746  m_pcEntropyCoder = pcEntropyCoder;
747
748  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
749  m_pcEntropyCoder->setEntropyCoder(m_pcRDGoOnSbacCoder, pcPic->getSlice(0));
750  m_pcEntropyCoder->resetEntropy();
751  m_pcEntropyCoder->resetBits();
752
753  if( m_bUseSBACRD )
754  {
755    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
756    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
757  }
758}
759
760/** End SAO encoder
761 */
762Void TEncSampleAdaptiveOffset::endSaoEnc()
763{
764  m_pcPic = NULL;
765  m_pcEntropyCoder = NULL;
766}
767
768inline int xSign(int x)
769{
770  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
771}
772
773/** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
774 * \param  pRecStart to-be-filtered block buffer pointer
775 * \param  pOrgStart original block buffer pointer
776 * \param  stride picture buffer stride
777 * \param  ppStat statistics buffer
778 * \param  ppCount counter buffer
779 * \param  width block width
780 * \param  height block height
781 * \param  pbBorderAvail availabilities of block border pixels
782 */
783Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail)
784{
785  Int64 *stats, *count;
786  Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
787  Pel *pOrg, *pRec;
788  UInt edgeType;
789  Int x, y;
790
791  //--------- Band offset-----------//
792  stats = ppStats[SAO_BO];
793  count = ppCount[SAO_BO];
794  pOrg   = pOrgStart;
795  pRec   = pRecStart;
796  for (y=0; y< height; y++)
797  {
798    for (x=0; x< width; x++)
799    {
800      classIdx = m_lumaTableBo[pRec[x]];
801      if (classIdx)
802      {
803        stats[classIdx] += (pOrg[x] - pRec[x]); 
804        count[classIdx] ++;
805      }
806    }
807    pOrg += stride;
808    pRec += stride;
809  }
810  //---------- Edge offset 0--------------//
811  stats = ppStats[SAO_EO_0];
812  count = ppCount[SAO_EO_0];
813  pOrg   = pOrgStart;
814  pRec   = pRecStart;
815
816
817  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
818  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
819  for (y=0; y< height; y++)
820  {
821    signLeft = xSign(pRec[startX] - pRec[startX-1]);
822    for (x=startX; x< endX; x++)
823    {
824      signRight =  xSign(pRec[x] - pRec[x+1]); 
825      edgeType =  signRight + signLeft + 2;
826      signLeft  = -signRight;
827
828      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
829      count[m_auiEoTable[edgeType]] ++;
830    }
831    pRec  += stride;
832    pOrg += stride;
833  }
834
835  //---------- Edge offset 1--------------//
836  stats = ppStats[SAO_EO_1];
837  count = ppCount[SAO_EO_1];
838  pOrg   = pOrgStart;
839  pRec   = pRecStart;
840
841  startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
842  endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
843  if (!pbBorderAvail[SGU_T])
844  {
845    pRec  += stride;
846    pOrg  += stride;
847  }
848
849  for (x=0; x< width; x++)
850  {
851    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
852  }
853  for (y=startY; y<endY; y++)
854  {
855    for (x=0; x< width; x++)
856    {
857      signDown     =  xSign(pRec[x] - pRec[x+stride]); 
858      edgeType    =  signDown + m_iUpBuff1[x] + 2;
859      m_iUpBuff1[x] = -signDown;
860
861      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
862      count[m_auiEoTable[edgeType]] ++;
863    }
864    pOrg += stride;
865    pRec += stride;
866  }
867  //---------- Edge offset 2--------------//
868  stats = ppStats[SAO_EO_2];
869  count = ppCount[SAO_EO_2];
870  pOrg   = pOrgStart;
871  pRec   = pRecStart;
872
873  posShift= stride + 1;
874
875  startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
876  endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
877
878  //prepare 2nd line upper sign
879  pRec += stride;
880  for (x=startX; x< endX+1; x++)
881  {
882    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
883  }
884
885  //1st line
886  pRec -= stride;
887  if(pbBorderAvail[SGU_TL])
888  {
889    x= 0;
890    edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
891    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
892    count[m_auiEoTable[edgeType]] ++;
893  }
894  if(pbBorderAvail[SGU_T])
895  {
896    for(x= 1; x< endX; x++)
897    {
898      edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
899      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
900      count[m_auiEoTable[edgeType]] ++;
901    }
902  }
903  pRec   += stride;
904  pOrg   += stride;
905
906  //middle lines
907  for (y= 1; y< height-1; y++)
908  {
909    for (x=startX; x<endX; x++)
910    {
911      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
912      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
913      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
914      count[m_auiEoTable[edgeType]] ++;
915
916      m_iUpBufft[x+1] = -signDown1; 
917    }
918    m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]);
919
920    ipSwap     = m_iUpBuff1;
921    m_iUpBuff1 = m_iUpBufft;
922    m_iUpBufft = ipSwap;
923
924    pRec  += stride;
925    pOrg  += stride;
926  }
927
928  //last line
929  if(pbBorderAvail[SGU_B])
930  {
931    for(x= startX; x< width-1; x++)
932    {
933      edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
934      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
935      count[m_auiEoTable[edgeType]] ++;
936    }
937  }
938  if(pbBorderAvail[SGU_BR])
939  {
940    x= width -1;
941    edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
942    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
943    count[m_auiEoTable[edgeType]] ++;
944  }
945
946  //---------- Edge offset 3--------------//
947
948  stats = ppStats[SAO_EO_3];
949  count = ppCount[SAO_EO_3];
950  pOrg   = pOrgStart;
951  pRec   = pRecStart;
952
953  posShift     = stride - 1;
954  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
955  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
956
957  //prepare 2nd line upper sign
958  pRec += stride;
959  for (x=startX-1; x< endX; x++)
960  {
961    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
962  }
963
964
965  //first line
966  pRec -= stride;
967  if(pbBorderAvail[SGU_T])
968  {
969    for(x= startX; x< width -1; x++)
970    {
971      edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
972      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
973      count[m_auiEoTable[edgeType]] ++;
974    }
975  }
976  if(pbBorderAvail[SGU_TR])
977  {
978    x= width-1;
979    edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
980    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
981    count[m_auiEoTable[edgeType]] ++;
982  }
983  pRec  += stride;
984  pOrg  += stride;
985
986  //middle lines
987  for (y= 1; y< height-1; y++)
988  {
989    for(x= startX; x< endX; x++)
990    {
991      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
992      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
993
994      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
995      count[m_auiEoTable[edgeType]] ++;
996      m_iUpBuff1[x-1] = -signDown1; 
997
998    }
999    m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
1000
1001    pRec  += stride;
1002    pOrg  += stride;
1003  }
1004
1005  //last line
1006  if(pbBorderAvail[SGU_BL])
1007  {
1008    x= 0;
1009    edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
1010    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
1011    count[m_auiEoTable[edgeType]] ++;
1012
1013  }
1014  if(pbBorderAvail[SGU_B])
1015  {
1016    for(x= 1; x< endX; x++)
1017    {
1018      edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
1019      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
1020      count[m_auiEoTable[edgeType]] ++;
1021    }
1022  }
1023}
1024
1025/** Calculate SAO statistics for current LCU
1026 * \param  iAddr,  iPartIdx,  iYCbCr
1027 */
1028Void TEncSampleAdaptiveOffset::calcSaoStatsCu(Int iAddr, Int iPartIdx, Int iYCbCr)
1029{
1030  if(!m_bUseNIF)
1031  {
1032    calcSaoStatsCuOrg( iAddr, iPartIdx, iYCbCr);
1033  }
1034  else
1035  {
1036    Int64** ppStats = m_iOffsetOrg[iPartIdx];
1037    Int64** ppCount = m_iCount    [iPartIdx];
1038
1039    //parameters
1040    Int  isChroma = (iYCbCr != 0)? 1:0;
1041    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
1042    Pel* pPicOrg = getPicYuvAddr (m_pcPic->getPicYuvOrg(), iYCbCr);
1043    Pel* pPicRec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
1044
1045    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
1046
1047    //variables
1048    UInt  xPos, yPos, width, height;
1049    Bool* pbBorderAvail;
1050    UInt  posOffset;
1051
1052    for(Int i=0; i< vFilterBlocks.size(); i++)
1053    {
1054      xPos        = vFilterBlocks[i].posX   >> isChroma;
1055      yPos        = vFilterBlocks[i].posY   >> isChroma;
1056      width       = vFilterBlocks[i].width  >> isChroma;
1057      height      = vFilterBlocks[i].height >> isChroma;
1058      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
1059
1060      posOffset = (yPos* stride) + xPos;
1061
1062      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);
1063    }
1064  }
1065
1066}
1067
1068/** Calculate SAO statistics for current LCU without non-crossing slice
1069 * \param  iAddr,  iPartIdx,  iYCbCr
1070 */
1071Void TEncSampleAdaptiveOffset::calcSaoStatsCuOrg(Int iAddr, Int iPartIdx, Int iYCbCr)
1072{
1073  Int x,y;
1074  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
1075  TComSPS *pTmpSPS =  m_pcPic->getSlice(0)->getSPS();
1076
1077  Pel* pOrg;
1078  Pel* pRec;
1079  Int iStride;
1080  Int iLcuWidth  = pTmpSPS->getMaxCUHeight();
1081  Int iLcuHeight = pTmpSPS->getMaxCUWidth();
1082  UInt uiLPelX   = pTmpCu->getCUPelX();
1083  UInt uiTPelY   = pTmpCu->getCUPelY();
1084  UInt uiRPelX;
1085  UInt uiBPelY;
1086  Int64* iStats;
1087  Int64* iCount;
1088  Int iClassIdx;
1089  Int iPicWidthTmp;
1090  Int iPicHeightTmp;
1091  Int iStartX;
1092  Int iStartY;
1093  Int iEndX;
1094  Int iEndY;
1095
1096  Int iIsChroma = (iYCbCr!=0)? 1:0;
1097  Int numSkipLine = iIsChroma? 2:4;
1098  if (m_saoLcuBasedOptimization == 0)
1099  {
1100    numSkipLine = 0;
1101  }
1102
1103#if SAO_SKIP_RIGHT
1104  Int numSkipLineRight = iIsChroma? 3:5;
1105  if (m_saoLcuBasedOptimization == 0)
1106  {
1107    numSkipLineRight = 0;
1108  }
1109#endif
1110
1111  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
1112  iPicHeightTmp = m_iPicHeight >> iIsChroma;
1113  iLcuWidth     = iLcuWidth    >> iIsChroma;
1114  iLcuHeight    = iLcuHeight   >> iIsChroma;
1115  uiLPelX       = uiLPelX      >> iIsChroma;
1116  uiTPelY       = uiTPelY      >> iIsChroma;
1117  uiRPelX       = uiLPelX + iLcuWidth  ;
1118  uiBPelY       = uiTPelY + iLcuHeight ;
1119  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
1120  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
1121  iLcuWidth     = uiRPelX - uiLPelX;
1122  iLcuHeight    = uiBPelY - uiTPelY;
1123
1124  iStride    =  (iYCbCr == 0)? m_pcPic->getStride(): m_pcPic->getCStride();
1125
1126//if(iSaoType == BO_0 || iSaoType == BO_1)
1127  {
1128#if SAO_LCU_BOUNDARY
1129    if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1130    {
1131      numSkipLine = iIsChroma? 1:3;
1132      numSkipLineRight = iIsChroma? 2:4;
1133    }
1134#endif
1135    iStats = m_iOffsetOrg[iPartIdx][SAO_BO];
1136    iCount = m_iCount    [iPartIdx][SAO_BO];
1137
1138    pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1139    pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1140
1141#if SAO_SKIP_RIGHT
1142    iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
1143#endif
1144
1145    iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeight-numSkipLine;
1146    for (y=0; y<iEndY; y++)
1147    {
1148#if SAO_SKIP_RIGHT
1149      for (x=0; x<iEndX; x++)
1150#else
1151      for (x=0; x<iLcuWidth; x++)
1152#endif
1153      {
1154        iClassIdx = m_lumaTableBo[pRec[x]];
1155        if (iClassIdx)
1156        {
1157          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
1158          iCount[iClassIdx] ++;
1159        }
1160      }
1161      pOrg += iStride;
1162      pRec += iStride;
1163    }
1164
1165  }
1166  Int iSignLeft;
1167  Int iSignRight;
1168  Int iSignDown;
1169  Int iSignDown1;
1170  Int iSignDown2;
1171
1172  UInt uiEdgeType;
1173
1174//if (iSaoType == EO_0  || iSaoType == EO_1 || iSaoType == EO_2 || iSaoType == EO_3)
1175  {
1176  //if (iSaoType == EO_0)
1177    {
1178#if SAO_LCU_BOUNDARY
1179      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1180      {
1181        numSkipLine = iIsChroma? 1:3;
1182        numSkipLineRight = iIsChroma? 3:5;
1183      }
1184#endif
1185      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];
1186      iCount = m_iCount    [iPartIdx][SAO_EO_0];
1187
1188      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1189      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1190
1191      iStartX = (uiLPelX == 0) ? 1 : 0;
1192#if SAO_SKIP_RIGHT
1193      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1194#else
1195      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1196#endif
1197      for (y=0; y<iLcuHeight-numSkipLine; y++)
1198      {
1199        iSignLeft = xSign(pRec[iStartX] - pRec[iStartX-1]);
1200        for (x=iStartX; x< iEndX; x++)
1201        {
1202          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
1203          uiEdgeType =  iSignRight + iSignLeft + 2;
1204          iSignLeft  = -iSignRight;
1205
1206          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1207          iCount[m_auiEoTable[uiEdgeType]] ++;
1208        }
1209        pOrg += iStride;
1210        pRec += iStride;
1211      }
1212    }
1213
1214  //if (iSaoType == EO_1)
1215    {
1216#if SAO_LCU_BOUNDARY
1217      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1218      {
1219        numSkipLine = iIsChroma? 2:4;
1220        numSkipLineRight = iIsChroma? 2:4;
1221      }
1222#endif
1223      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];
1224      iCount = m_iCount    [iPartIdx][SAO_EO_1];
1225
1226      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1227      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1228
1229      iStartY = (uiTPelY == 0) ? 1 : 0;
1230#if SAO_SKIP_RIGHT
1231      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
1232#endif
1233      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1234      if (uiTPelY == 0)
1235      {
1236        pOrg += iStride;
1237        pRec += iStride;
1238      }
1239
1240      for (x=0; x< iLcuWidth; x++)
1241      {
1242        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
1243      }
1244      for (y=iStartY; y<iEndY; y++)
1245      {
1246#if SAO_SKIP_RIGHT
1247        for (x=0; x<iEndX; x++)
1248#else
1249        for (x=0; x<iLcuWidth; x++)
1250#endif
1251        {
1252          iSignDown     =  xSign(pRec[x] - pRec[x+iStride]); 
1253          uiEdgeType    =  iSignDown + m_iUpBuff1[x] + 2;
1254          m_iUpBuff1[x] = -iSignDown;
1255
1256          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1257          iCount[m_auiEoTable[uiEdgeType]] ++;
1258        }
1259        pOrg += iStride;
1260        pRec += iStride;
1261      }
1262    }
1263  //if (iSaoType == EO_2)
1264    {
1265#if SAO_LCU_BOUNDARY
1266      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1267      {
1268        numSkipLine = iIsChroma? 2:4;
1269        numSkipLineRight = iIsChroma? 3:5;
1270      }
1271#endif
1272      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];
1273      iCount = m_iCount    [iPartIdx][SAO_EO_2];
1274
1275      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1276      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1277
1278      iStartX = (uiLPelX == 0) ? 1 : 0;
1279#if SAO_SKIP_RIGHT
1280      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1281#else
1282      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1283#endif
1284
1285      iStartY = (uiTPelY == 0) ? 1 : 0;
1286      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1287      if (uiTPelY == 0)
1288      {
1289        pOrg += iStride;
1290        pRec += iStride;
1291      }
1292
1293      for (x=iStartX; x<iEndX; x++)
1294      {
1295        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
1296      }
1297      for (y=iStartY; y<iEndY; y++)
1298      {
1299        iSignDown2 = xSign(pRec[iStride+iStartX] - pRec[iStartX-1]);
1300        for (x=iStartX; x<iEndX; x++)
1301        {
1302          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
1303          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1304          m_iUpBufft[x+1] = -iSignDown1; 
1305          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1306          iCount[m_auiEoTable[uiEdgeType]] ++;
1307        }
1308        m_iUpBufft[iStartX] = iSignDown2;
1309        ipSwap     = m_iUpBuff1;
1310        m_iUpBuff1 = m_iUpBufft;
1311        m_iUpBufft = ipSwap;
1312
1313        pRec += iStride;
1314        pOrg += iStride;
1315      }
1316    } 
1317  //if (iSaoType == EO_3  )
1318    {
1319#if SAO_LCU_BOUNDARY
1320      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1321      {
1322        numSkipLine = iIsChroma? 2:4;
1323        numSkipLineRight = iIsChroma? 3:5;
1324      }
1325#endif
1326      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];
1327      iCount = m_iCount    [iPartIdx][SAO_EO_3];
1328
1329      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1330      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1331
1332      iStartX = (uiLPelX == 0) ? 1 : 0;
1333#if SAO_SKIP_RIGHT
1334      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1335#else
1336      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1337#endif
1338
1339      iStartY = (uiTPelY == 0) ? 1 : 0;
1340      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1341      if (iStartY == 1)
1342      {
1343        pOrg += iStride;
1344        pRec += iStride;
1345      }
1346
1347      for (x=iStartX-1; x<iEndX; x++)
1348      {
1349        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
1350      }
1351
1352      for (y=iStartY; y<iEndY; y++)
1353      {
1354        for (x=iStartX; x<iEndX; x++)
1355        {
1356          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
1357          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1358          m_iUpBuff1[x-1] = -iSignDown1; 
1359          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1360          iCount[m_auiEoTable[uiEdgeType]] ++;
1361        }
1362        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
1363
1364        pRec += iStride;
1365        pOrg += iStride;
1366      } 
1367    } 
1368  }
1369}
1370
1371
1372#if SAO_LCU_BOUNDARY
1373Void TEncSampleAdaptiveOffset::calcSaoStatsCu_BeforeDblk( TComPic* pcPic )
1374{
1375  Int addr, yCbCr;
1376  Int x,y;
1377  TComSPS *pTmpSPS =  pcPic->getSlice(0)->getSPS();
1378
1379  Pel* pOrg;
1380  Pel* pRec;
1381  Int stride;
1382  Int lcuWidth  = pTmpSPS->getMaxCUHeight();
1383  Int lcuHeight = pTmpSPS->getMaxCUWidth();
1384  UInt rPelX;
1385  UInt bPelY;
1386  Int64* stats;
1387  Int64* count;
1388  Int classIdx;
1389  Int picWidthTmp = 0;
1390  Int picHeightTmp = 0;
1391  Int startX;
1392  Int startY;
1393  Int endX;
1394  Int endY;
1395  Int firstX, firstY;
1396
1397  Int idxY;
1398  Int idxX;
1399  Int frameHeightInCU = m_iNumCuInHeight;
1400  Int frameWidthInCU  = m_iNumCuInWidth;
1401  Int j, k;
1402
1403  Int isChroma;
1404  Int numSkipLine, numSkipLineRight;
1405
1406  UInt lPelX, tPelY;
1407  TComDataCU *pTmpCu;
1408
1409  for (idxY = 0; idxY< frameHeightInCU; idxY++)
1410  {
1411    for (idxX = 0; idxX< frameWidthInCU; idxX++)
1412    {
1413      lcuWidth  = pTmpSPS->getMaxCUHeight();
1414      lcuHeight = pTmpSPS->getMaxCUWidth();
1415      addr     = idxX  + frameWidthInCU*idxY;
1416      pTmpCu = pcPic->getCU(addr);
1417      lPelX   = pTmpCu->getCUPelX();
1418      tPelY   = pTmpCu->getCUPelY();
1419      for( yCbCr = 0; yCbCr < 3; yCbCr++ )
1420      {
1421        isChroma = (yCbCr!=0)? 1:0;
1422
1423        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
1424        {
1425          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
1426          {
1427            m_count_PreDblk    [addr][yCbCr][j][k] = 0;
1428            m_offsetOrg_PreDblk[addr][yCbCr][j][k] = 0;
1429          } 
1430        }
1431        if( yCbCr == 0 )
1432        {
1433          picWidthTmp  = m_iPicWidth;
1434          picHeightTmp = m_iPicHeight;
1435        }
1436        else if( yCbCr == 1 )
1437        {
1438          picWidthTmp  = m_iPicWidth  >> isChroma;
1439          picHeightTmp = m_iPicHeight >> isChroma;
1440          lcuWidth     = lcuWidth    >> isChroma;
1441          lcuHeight    = lcuHeight   >> isChroma;
1442          lPelX       = lPelX      >> isChroma;
1443          tPelY       = tPelY      >> isChroma;
1444        }
1445        rPelX       = lPelX + lcuWidth  ;
1446        bPelY       = tPelY + lcuHeight ;
1447        rPelX       = rPelX > picWidthTmp  ? picWidthTmp  : rPelX;
1448        bPelY       = bPelY > picHeightTmp ? picHeightTmp : bPelY;
1449        lcuWidth     = rPelX - lPelX;
1450        lcuHeight    = bPelY - tPelY;
1451
1452        stride    =  (yCbCr == 0)? pcPic->getStride(): pcPic->getCStride();
1453
1454        //if(iSaoType == BO)
1455
1456        numSkipLine = isChroma? 1:3;
1457        numSkipLineRight = isChroma? 2:4;
1458
1459        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_BO];
1460        count = m_count_PreDblk[addr][yCbCr][SAO_BO];
1461
1462        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1463        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1464
1465        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
1466        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
1467
1468        for (y=0; y<lcuHeight; y++)
1469        {
1470          for (x=0; x<lcuWidth; x++)
1471          {
1472            if( x < startX && y < startY )
1473              continue;
1474
1475            classIdx = m_lumaTableBo[pRec[x]];
1476            if (classIdx)
1477            {
1478              stats[classIdx] += (pOrg[x] - pRec[x]); 
1479              count[classIdx] ++;
1480            }
1481          }
1482          pOrg += stride;
1483          pRec += stride;
1484        }
1485
1486        Int signLeft;
1487        Int signRight;
1488        Int signDown;
1489        Int signDown1;
1490        Int signDown2;
1491
1492        UInt uiEdgeType;
1493
1494        //if (iSaoType == EO_0)
1495
1496        numSkipLine = isChroma? 1:3;
1497        numSkipLineRight = isChroma? 3:5;
1498
1499        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_0];
1500        count = m_count_PreDblk[addr][yCbCr][SAO_EO_0];
1501
1502        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1503        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1504
1505        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1506        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
1507        firstX   = (lPelX == 0) ? 1 : 0;
1508        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1509
1510        for (y=0; y<lcuHeight; y++)
1511        {
1512          signLeft = xSign(pRec[firstX] - pRec[firstX-1]);
1513          for (x=firstX; x< endX; x++)
1514          {
1515            signRight =  xSign(pRec[x] - pRec[x+1]); 
1516            uiEdgeType =  signRight + signLeft + 2;
1517            signLeft  = -signRight;
1518
1519            if( x < startX && y < startY )
1520              continue;
1521
1522            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1523            count[m_auiEoTable[uiEdgeType]] ++;
1524          }
1525          pOrg += stride;
1526          pRec += stride;
1527        }
1528
1529        //if (iSaoType == EO_1)
1530
1531        numSkipLine = isChroma? 2:4;
1532        numSkipLineRight = isChroma? 2:4;
1533
1534        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_1];
1535        count = m_count_PreDblk[addr][yCbCr][SAO_EO_1];
1536
1537        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1538        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1539
1540        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
1541        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1542        firstY = (tPelY == 0) ? 1 : 0;
1543        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1544        if (firstY == 1)
1545        {
1546          pOrg += stride;
1547          pRec += stride;
1548        }
1549
1550        for (x=0; x< lcuWidth; x++)
1551        {
1552          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
1553        }
1554        for (y=firstY; y<endY; y++)
1555        {
1556          for (x=0; x<lcuWidth; x++)
1557          {
1558            signDown     =  xSign(pRec[x] - pRec[x+stride]); 
1559            uiEdgeType    =  signDown + m_iUpBuff1[x] + 2;
1560            m_iUpBuff1[x] = -signDown;
1561
1562            if( x < startX && y < startY )
1563              continue;
1564
1565            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1566            count[m_auiEoTable[uiEdgeType]] ++;
1567          }
1568          pOrg += stride;
1569          pRec += stride;
1570        }
1571
1572        //if (iSaoType == EO_2)
1573
1574        numSkipLine = isChroma? 2:4;
1575        numSkipLineRight = isChroma? 3:5;
1576
1577        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_2];
1578        count = m_count_PreDblk[addr][yCbCr][SAO_EO_2];
1579
1580        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1581        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1582
1583        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1584        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1585        firstX   = (lPelX == 0) ? 1 : 0;
1586        firstY = (tPelY == 0) ? 1 : 0;
1587        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1588        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1589        if (firstY == 1)
1590        {
1591          pOrg += stride;
1592          pRec += stride;
1593        }
1594
1595        for (x=firstX; x<endX; x++)
1596        {
1597          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride-1]);
1598        }
1599        for (y=firstY; y<endY; y++)
1600        {
1601          signDown2 = xSign(pRec[stride+startX] - pRec[startX-1]);
1602          for (x=firstX; x<endX; x++)
1603          {
1604            signDown1      =  xSign(pRec[x] - pRec[x+stride+1]) ;
1605            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1606            m_iUpBufft[x+1] = -signDown1; 
1607
1608            if( x < startX && y < startY )
1609              continue;
1610
1611            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1612            count[m_auiEoTable[uiEdgeType]] ++;
1613          }
1614          m_iUpBufft[firstX] = signDown2;
1615          ipSwap     = m_iUpBuff1;
1616          m_iUpBuff1 = m_iUpBufft;
1617          m_iUpBufft = ipSwap;
1618
1619          pRec += stride;
1620          pOrg += stride;
1621        }
1622
1623        //if (iSaoType == EO_3)
1624
1625        numSkipLine = isChroma? 2:4;
1626        numSkipLineRight = isChroma? 3:5;
1627
1628        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_3];
1629        count = m_count_PreDblk[addr][yCbCr][SAO_EO_3];
1630
1631        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1632        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1633
1634        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1635        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1636        firstX   = (lPelX == 0) ? 1 : 0;
1637        firstY = (tPelY == 0) ? 1 : 0;
1638        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1639        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1640        if (firstY == 1)
1641        {
1642          pOrg += stride;
1643          pRec += stride;
1644        }
1645
1646        for (x=firstX-1; x<endX; x++)
1647        {
1648          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride+1]);
1649        }
1650
1651        for (y=firstY; y<endY; y++)
1652        {
1653          for (x=firstX; x<endX; x++)
1654          {
1655            signDown1      =  xSign(pRec[x] - pRec[x+stride-1]) ;
1656            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1657            m_iUpBuff1[x-1] = -signDown1; 
1658
1659            if( x < startX && y < startY )
1660              continue;
1661
1662            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1663            count[m_auiEoTable[uiEdgeType]] ++;
1664          }
1665          m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
1666
1667          pRec += stride;
1668          pOrg += stride;
1669        }
1670      }
1671    }
1672  }
1673}
1674#endif
1675
1676
1677/** get SAO statistics
1678 * \param  *psQTPart,  iYCbCr
1679 */
1680Void TEncSampleAdaptiveOffset::getSaoStats(SAOQTPart *psQTPart, Int iYCbCr)
1681{
1682  Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;
1683  Int i;
1684  Int iNumTotalType = MAX_NUM_SAO_TYPE;
1685  Int LcuIdxX;
1686  Int LcuIdxY;
1687  Int iAddr;
1688  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
1689  Int iDownPartIdx;
1690  Int iPartStart;
1691  Int iPartEnd;
1692  SAOQTPart*  pOnePart; 
1693
1694  if (m_uiMaxSplitLevel == 0)
1695  {
1696    iPartIdx = 0;
1697    pOnePart = &(psQTPart[iPartIdx]);
1698    for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
1699    {
1700      for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
1701      {
1702        iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
1703        calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
1704      }
1705    }
1706  }
1707  else
1708  {
1709    for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel-1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)
1710    {
1711      pOnePart = &(psQTPart[iPartIdx]);
1712      for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
1713      {
1714        for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
1715        {
1716          iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
1717          calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
1718        }
1719      }
1720    }
1721    for (iLevelIdx = m_uiMaxSplitLevel-1; iLevelIdx>=0; iLevelIdx-- )
1722    {
1723      iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx-1] : 0;
1724      iPartEnd   = m_aiNumCulPartsLevel[iLevelIdx];
1725
1726      for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)
1727      {
1728        pOnePart = &(psQTPart[iPartIdx]);
1729        for (i=0; i< NUM_DOWN_PART; i++)
1730        {
1731          iDownPartIdx = pOnePart->DownPartsIdx[i];
1732          for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)
1733          {
1734            for (iClassIdx=0; iClassIdx< (iTypeIdx < SAO_BO ? m_iNumClass[iTypeIdx] : SAO_MAX_BO_CLASSES) +1; iClassIdx++)
1735            {
1736              m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];
1737              m_iCount [iPartIdx][iTypeIdx][iClassIdx]    += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];
1738            }
1739          }
1740        }
1741      }
1742    }
1743  }
1744}
1745
1746/** reset offset statistics
1747 * \param
1748 */
1749Void TEncSampleAdaptiveOffset::resetStats()
1750{
1751  for (Int i=0;i<m_iNumTotalParts;i++)
1752  {
1753    m_dCostPartBest[i] = MAX_DOUBLE;
1754    m_iTypePartBest[i] = -1;
1755    m_iDistOrg[i] = 0;
1756    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
1757    {
1758      m_iDist[i][j] = 0;
1759      m_iRate[i][j] = 0;
1760      m_dCost[i][j] = 0;
1761      for (Int k=0;k<MAX_NUM_SAO_CLASS;k++)
1762      {
1763        m_iCount [i][j][k] = 0;
1764        m_iOffset[i][j][k] = 0;
1765        m_iOffsetOrg[i][j][k] = 0;
1766      } 
1767    }
1768  }
1769}
1770
1771#if SAO_CHROMA_LAMBDA
1772/** Sample adaptive offset process
1773 * \param pcSaoParam
1774 * \param dLambdaLuma
1775 * \param dLambdaChroma
1776 */
1777#if SAO_ENCODING_CHOICE
1778Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma, Int depth)
1779#else
1780Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
1781#endif
1782#else
1783/** Sample adaptive offset process
1784 * \param dLambda
1785 */
1786Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)
1787#endif
1788{
1789
1790  m_eSliceType          =  m_pcPic->getSlice(0)->getSliceType();
1791  m_iPicNalReferenceIdc = (m_pcPic->getSlice(0)->isReferenced() ? 1 :0);
1792
1793#if SAO_CHROMA_LAMBDA
1794  m_dLambdaLuma    = dLambdaLuma;
1795  m_dLambdaChroma  = dLambdaChroma;
1796#else
1797  m_dLambdaLuma    = dLambda;
1798  m_dLambdaChroma  = dLambda;
1799#endif
1800
1801  if(m_bUseNIF)
1802  {
1803    m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
1804  }
1805
1806#if FULL_NBIT
1807  m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth-8) - min((Int)(g_uiBitDepth + (g_uiBitDepth-8)), 10);
1808#else
1809  m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement - min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);
1810#endif
1811 
1812#if FULL_NBIT
1813  m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + (g_uiBitDepth-8)-5),5) );
1814#else
1815  m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + g_uiBitIncrement-5),5) );
1816#endif
1817  resetSAOParam(pcSaoParam);
1818#if SAO_LCU_BOUNDARY
1819  if( !m_saoLcuBasedOptimization || !m_saoLcuBoundary )
1820  {
1821    resetStats();
1822  }
1823#else
1824  resetStats();
1825#endif
1826#if !SAO_TYPE_SHARING
1827  Int iY  = 0;
1828#endif
1829  Double dCostFinal = 0;
1830  if ( m_saoLcuBasedOptimization)
1831  {
1832#if SAO_ENCODING_CHOICE
1833    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth);
1834#else
1835    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);
1836#endif
1837  }
1838  else
1839  {
1840#if SAO_TYPE_SHARING
1841    pcSaoParam->bSaoFlag[0] = 1;
1842    pcSaoParam->bSaoFlag[1] = 0;
1843    dCostFinal = 0;
1844    Double lambdaRdo =  dLambdaLuma;
1845    resetStats();
1846    getSaoStats(pcSaoParam->psSaoPart[0], 0);
1847#if PICTURE_SAO_RDO_FIX
1848    runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0);
1849#else
1850    runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo);
1851#endif
1852    pcSaoParam->bSaoFlag[0] = dCostFinal < 0 ? 1:0;
1853    if(pcSaoParam->bSaoFlag[0])
1854    {
1855      convertQT2SaoUnit(pcSaoParam, 0, 0);
1856      assignSaoUnitSyntax(pcSaoParam->saoLcuParam[0],  pcSaoParam->psSaoPart[0], pcSaoParam->oneUnitFlag[0], 0);
1857    }
1858#else
1859    pcSaoParam->bSaoFlag[0] = 1;
1860    pcSaoParam->bSaoFlag[1] = 0;
1861    pcSaoParam->bSaoFlag[2] = 0;
1862    for (Int compIdx=0;compIdx<3;compIdx++)
1863    {
1864      if (pcSaoParam->bSaoFlag[iY])
1865      {
1866        dCostFinal = 0;
1867        Double lambdaRdo = (compIdx==0 ? dLambdaLuma: dLambdaChroma);
1868        resetStats();
1869        getSaoStats(pcSaoParam->psSaoPart[compIdx], compIdx);
1870#if PICTURE_SAO_RDO_FIX
1871        runQuadTreeDecision(pcSaoParam->psSaoPart[compIdx], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, compIdx);       
1872#else
1873        runQuadTreeDecision(pcSaoParam->psSaoPart[compIdx], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo);
1874#endif
1875
1876        pcSaoParam->bSaoFlag[compIdx] = dCostFinal < 0 ? 1:0;
1877        if(pcSaoParam->bSaoFlag[compIdx])
1878        {
1879          convertQT2SaoUnit(pcSaoParam, 0, compIdx);
1880          assignSaoUnitSyntax(pcSaoParam->saoLcuParam[compIdx],  pcSaoParam->psSaoPart[compIdx], pcSaoParam->oneUnitFlag[compIdx], compIdx);
1881        }
1882      }
1883    }
1884#endif
1885  }
1886#if SAO_TYPE_SHARING
1887  if (pcSaoParam->bSaoFlag[0])
1888  {
1889    processSaoUnitAll( pcSaoParam->saoLcuParam[0], pcSaoParam->oneUnitFlag[0], 0);
1890  }
1891  if (pcSaoParam->bSaoFlag[1])
1892  {
1893    processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);
1894    processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);
1895  }
1896#else
1897  for (Int compIdx=0;compIdx<3;compIdx++)
1898  {
1899    if (pcSaoParam->bSaoFlag[compIdx])
1900    {
1901      processSaoUnitAll( pcSaoParam->saoLcuParam[compIdx], pcSaoParam->oneUnitFlag[compIdx], compIdx);
1902    }
1903  }
1904#endif
1905}
1906/** Check merge SAO unit
1907 * \param saoUnitCurr current SAO unit
1908 * \param saoUnitCheck SAO unit tobe check
1909 * \param dir direction
1910 */
1911Void TEncSampleAdaptiveOffset::checkMerge(SaoLcuParam * saoUnitCurr, SaoLcuParam * saoUnitCheck, Int dir)
1912{
1913  Int i ;
1914  Int countDiff = 0;
1915  if (saoUnitCurr->partIdx != saoUnitCheck->partIdx)
1916  {
1917    if (saoUnitCurr->typeIdx !=-1)
1918    {
1919      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
1920      {
1921        for (i=0;i<saoUnitCurr->length;i++)
1922        {
1923          countDiff += (saoUnitCurr->offset[i] != saoUnitCheck->offset[i]);
1924        }
1925#if SAO_TYPE_CODING
1926        countDiff += (saoUnitCurr->subTypeIdx != saoUnitCheck->subTypeIdx);
1927#else
1928        countDiff += (saoUnitCurr->bandPosition != saoUnitCheck->bandPosition);
1929#endif
1930        if (countDiff ==0)
1931        {
1932          saoUnitCurr->partIdx = saoUnitCheck->partIdx;
1933          if (dir == 1)
1934          {
1935            saoUnitCurr->mergeUpFlag = 1;
1936            saoUnitCurr->mergeLeftFlag = 0;
1937          }
1938          else
1939          {
1940            saoUnitCurr->mergeUpFlag = 0;
1941            saoUnitCurr->mergeLeftFlag = 1;
1942          }
1943        }
1944      }
1945    }
1946    else
1947    {
1948      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
1949      {
1950        saoUnitCurr->partIdx = saoUnitCheck->partIdx;
1951        if (dir == 1)
1952        {
1953          saoUnitCurr->mergeUpFlag = 1;
1954          saoUnitCurr->mergeLeftFlag = 0;
1955        }
1956        else
1957        {
1958          saoUnitCurr->mergeUpFlag = 0;
1959          saoUnitCurr->mergeLeftFlag = 1;
1960        }
1961      }
1962    }
1963  }
1964}
1965/** Assign SAO unit syntax from picture-based algorithm
1966 * \param saoLcuParam SAO LCU parameters
1967 * \param saoPart SAO part
1968 * \param oneUnitFlag SAO one unit flag
1969 * \param iYCbCr color component Index
1970 */
1971Void TEncSampleAdaptiveOffset::assignSaoUnitSyntax(SaoLcuParam* saoLcuParam,  SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr)
1972{
1973  if (saoPart->bSplit == 0)
1974  {
1975    oneUnitFlag = 1;
1976  }
1977  else
1978  {
1979    Int i,j, addr, addrUp, addrLeft,  idx, idxUp, idxLeft,  idxCount;
1980
1981    oneUnitFlag = 0;
1982
1983    idxCount = -1;
1984    saoLcuParam[0].mergeUpFlag = 0;
1985    saoLcuParam[0].mergeLeftFlag = 0;
1986
1987    for (j=0;j<m_iNumCuInHeight;j++)
1988    {
1989      for (i=0;i<m_iNumCuInWidth;i++)
1990      {
1991        addr     = i + j*m_iNumCuInWidth;
1992        addrLeft = (addr%m_iNumCuInWidth == 0) ? -1 : addr - 1;
1993        addrUp   = (addr<m_iNumCuInWidth)      ? -1 : addr - m_iNumCuInWidth;
1994        idx      = saoLcuParam[addr].partIdxTmp;
1995        idxLeft  = (addrLeft == -1) ? -1 : saoLcuParam[addrLeft].partIdxTmp;
1996        idxUp    = (addrUp == -1)   ? -1 : saoLcuParam[addrUp].partIdxTmp;
1997
1998        if(idx!=idxLeft && idx!=idxUp)
1999        {
2000          saoLcuParam[addr].mergeUpFlag   = 0; idxCount++;
2001          saoLcuParam[addr].mergeLeftFlag = 0;
2002          saoLcuParam[addr].partIdx = idxCount;
2003        }
2004        else if (idx==idxLeft)
2005        {
2006          saoLcuParam[addr].mergeUpFlag   = 1;
2007          saoLcuParam[addr].mergeLeftFlag = 1;
2008          saoLcuParam[addr].partIdx = saoLcuParam[addrLeft].partIdx;
2009        }
2010        else if (idx==idxUp)
2011        {
2012          saoLcuParam[addr].mergeUpFlag   = 1;
2013          saoLcuParam[addr].mergeLeftFlag = 0;
2014          saoLcuParam[addr].partIdx = saoLcuParam[addrUp].partIdx;
2015        }
2016        if (addrUp != -1)
2017        {
2018          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrUp], 1);
2019        }
2020        if (addrLeft != -1)
2021        {
2022          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);
2023        }
2024      }
2025    }
2026  }
2027}
2028/** rate distortion optimization of all SAO units
2029 * \param saoParam SAO parameters
2030 * \param lambda
2031 * \param lambdaChroma
2032 */
2033#if SAO_ENCODING_CHOICE
2034Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
2035#else
2036Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
2037#endif
2038{
2039
2040  Int idxY;
2041  Int idxX;
2042  Int frameHeightInCU = saoParam->numCuInHeight;
2043  Int frameWidthInCU  = saoParam->numCuInWidth;
2044  Int j, k;
2045  Int addr = 0;
2046  Int addrUp = -1;
2047  Int addrLeft = -1;
2048  Int compIdx = 0;
2049#if !SAO_TYPE_SHARING
2050  Double lambdaComp;
2051#endif
2052#if SAO_SINGLE_MERGE
2053  SaoLcuParam mergeSaoParam[3][2];
2054  Double compDistortion[3];
2055#endif
2056
2057  saoParam->bSaoFlag[0] = true;
2058  saoParam->bSaoFlag[1] = true;
2059#if !SAO_TYPE_SHARING
2060  saoParam->bSaoFlag[2] = true;
2061#endif
2062  saoParam->oneUnitFlag[0] = false;
2063  saoParam->oneUnitFlag[1] = false;
2064  saoParam->oneUnitFlag[2] = false;
2065
2066#if SAO_ENCODING_CHOICE
2067#if SAO_ENCODING_CHOICE_CHROMA
2068  Int numNoSao[2];
2069  numNoSao[0] = 0;// Luma
2070  numNoSao[1] = 0;// Chroma
2071  if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
2072  {
2073    saoParam->bSaoFlag[0] = false;
2074  }
2075  if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
2076  {
2077    saoParam->bSaoFlag[1] = false;
2078#if !SAO_TYPE_SHARING
2079    saoParam->bSaoFlag[2] = false;
2080#endif
2081  }
2082#else
2083  Int numNoSao = 0;
2084
2085  if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
2086  {
2087    saoParam->bSaoFlag[0] = false;
2088    saoParam->bSaoFlag[1] = false;
2089#if !SAO_TYPE_SHARING
2090    saoParam->bSaoFlag[2] = false;
2091#endif
2092  }
2093#endif
2094#endif
2095
2096  for (idxY = 0; idxY< frameHeightInCU; idxY++)
2097  {
2098    for (idxX = 0; idxX< frameWidthInCU; idxX++)
2099    {
2100      addr     = idxX  + frameWidthInCU*idxY;
2101      addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
2102      addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
2103#if SAO_SINGLE_MERGE
2104      Int allowMergeLeft = 1;
2105      Int allowMergeUp   = 1;
2106      UInt rate;
2107      Double bestCost, mergeCost;
2108      if (idxX!=0)
2109      { 
2110        // check tile id and slice id
2111        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()))
2112        {
2113          allowMergeLeft = 0;
2114        }
2115      }
2116      else
2117      {
2118        allowMergeLeft = 0;
2119      }
2120      if (idxY!=0)
2121      {
2122        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()))
2123        {
2124          allowMergeUp = 0;
2125        }
2126      }
2127      else
2128      {
2129        allowMergeUp = 0;
2130      }
2131
2132      compDistortion[0] = 0; 
2133      compDistortion[1] = 0; 
2134      compDistortion[2] = 0;
2135      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2136      if (allowMergeLeft)
2137      {
2138#if SAO_MERGE_ONE_CTX
2139        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
2140#else
2141        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeLeft(0, 0); 
2142#endif
2143      }
2144      if (allowMergeUp)
2145      {
2146#if SAO_MERGE_ONE_CTX
2147        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
2148#else
2149        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeUp(0);
2150#endif
2151      }
2152      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2153#endif
2154      // reset stats Y, Cb, Cr
2155      for ( compIdx=0;compIdx<3;compIdx++)
2156      {
2157        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
2158        {
2159          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
2160          {
2161#if SAO_LCU_BOUNDARY
2162            m_iOffset   [compIdx][j][k] = 0;
2163            if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){
2164              m_iCount    [compIdx][j][k] = m_count_PreDblk    [addr][compIdx][j][k];
2165              m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
2166            }
2167            else
2168            {
2169              m_iCount    [compIdx][j][k] = 0;
2170              m_iOffsetOrg[compIdx][j][k] = 0;
2171            }
2172#else
2173            m_iCount    [compIdx][j][k] = 0;
2174            m_iOffset   [compIdx][j][k] = 0;
2175            m_iOffsetOrg[compIdx][j][k] = 0;
2176#endif
2177          } 
2178        }
2179        saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
2180        saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
2181        saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
2182#if SAO_TYPE_CODING
2183        saoParam->saoLcuParam[compIdx][addr].subTypeIdx    = 0;
2184#else
2185        saoParam->saoLcuParam[compIdx][addr].bandPosition  = 0;
2186#endif
2187#if !SAO_TYPE_SHARING
2188       lambdaComp = compIdx==0 ? lambda : lambdaChroma;
2189#endif
2190#if SAO_ENCODING_CHOICE
2191#if SAO_TYPE_SHARING
2192  if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
2193#else
2194  if( saoParam->bSaoFlag[compIdx] )
2195#endif
2196#endif
2197        {
2198          calcSaoStatsCu(addr, compIdx,  compIdx);
2199
2200#if SAO_TYPE_SHARING
2201       }
2202      }
2203      saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0,  lambda, &mergeSaoParam[0][0], &compDistortion[0]);
2204      sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
2205#else
2206#if SAO_SINGLE_MERGE
2207          saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, compIdx,  lambdaComp, &mergeSaoParam[compIdx][0], &compDistortion[0]);
2208#else
2209          rdoSaoUnit (idxX, idxY, saoParam, addr, addrUp, addrLeft, compIdx,  lambdaComp);
2210#endif
2211#if SAO_ENCODING_CHOICE
2212#if !SAO_SINGLE_MERGE
2213#if SAO_ENCODING_CHOICE_CHROMA
2214          if( saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
2215          {
2216            numNoSao[compIdx>0?1:0]++;
2217          }
2218#else
2219          if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
2220          {
2221            numNoSao++;
2222          }
2223#endif
2224#endif
2225        }
2226#endif
2227#if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_3
2228        if (compIdx!=0)
2229        {
2230          if ( saoParam->saoLcuParam[compIdx][0].typeIdx == -1 )
2231          {
2232            saoParam->bSaoFlag[compIdx] = false;
2233          }
2234        }
2235#endif
2236      }
2237#endif
2238#if SAO_SINGLE_MERGE   
2239#if SAO_TYPE_SHARING
2240     if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] )
2241#else
2242     if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] || saoParam->bSaoFlag[2])
2243#endif
2244      {
2245        // Cost of new SAO_params
2246        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2247        m_pcRDGoOnSbacCoder->resetBits();
2248        if (allowMergeLeft)
2249        {
2250#if SAO_MERGE_ONE_CTX
2251          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
2252#else
2253          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeLeft(0, 0); 
2254#endif
2255        }
2256        if (allowMergeUp)
2257        {
2258#if SAO_MERGE_ONE_CTX
2259          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
2260#else
2261          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeUp(0);
2262#endif
2263        }
2264        for ( compIdx=0;compIdx<3;compIdx++)
2265        {
2266#if SAO_TYPE_SHARING
2267        if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1]))
2268#else
2269        if( saoParam->bSaoFlag[compIdx])
2270#endif
2271          {
2272#if SAO_TYPE_SHARING
2273           m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx);
2274#else
2275           m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr]);
2276#endif
2277          }
2278        }
2279
2280        rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2281        bestCost = compDistortion[0] + (Double)rate;
2282        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2283
2284        // Cost of Merge
2285        for(Int mergeUp=0; mergeUp<2; ++mergeUp)
2286        {
2287          if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) )
2288          {
2289            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2290            m_pcRDGoOnSbacCoder->resetBits();
2291            if (allowMergeLeft)
2292            {
2293#if SAO_MERGE_ONE_CTX
2294              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); 
2295#else
2296              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeLeft(1-mergeUp, 0); 
2297#endif
2298            }
2299            if ( allowMergeUp && (mergeUp==1) )
2300            {
2301#if SAO_MERGE_ONE_CTX
2302              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); 
2303#else
2304              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMergeUp(1); 
2305#endif
2306            }
2307
2308            rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2309            mergeCost = compDistortion[mergeUp+1] + (Double)rate;
2310            if (mergeCost < bestCost)
2311            {
2312              bestCost = mergeCost;
2313              m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);             
2314              for ( compIdx=0;compIdx<3;compIdx++)
2315              {
2316                mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp;
2317                mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;
2318#if SAO_TYPE_SHARING
2319                if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1]))
2320#else
2321                if( saoParam->bSaoFlag[compIdx])
2322#endif
2323                {
2324                  copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );             
2325                }
2326              }
2327            }
2328          }
2329        }
2330#if SAO_ENCODING_CHOICE
2331#if SAO_ENCODING_CHOICE_CHROMA
2332if( saoParam->saoLcuParam[0][addr].typeIdx == -1)
2333{
2334  numNoSao[0]++;
2335}
2336#if SAO_TYPE_SHARING
2337if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
2338{
2339  numNoSao[1]+=2;
2340}
2341#else
2342if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
2343{
2344  numNoSao[1]++;
2345}
2346if( saoParam->saoLcuParam[2][addr].typeIdx == -1)
2347{
2348  numNoSao[1]++;
2349}
2350#endif
2351#else
2352        for ( compIdx=0;compIdx<3;compIdx++)
2353        {
2354          if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
2355          {
2356            numNoSao++;
2357          }
2358        }
2359#endif
2360#endif
2361        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2362        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2363      }
2364#endif
2365    }
2366  }
2367#if SAO_ENCODING_CHOICE
2368#if SAO_ENCODING_CHOICE_CHROMA
2369m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
2370m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
2371#else
2372  if( depth == 0)
2373  {
2374    // update SAO Rate
2375    m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
2376  }
2377#endif
2378#endif
2379
2380}
2381/** rate distortion optimization of SAO unit
2382 * \param saoParam SAO parameters
2383 * \param addr address
2384 * \param addrUp above address
2385 * \param addrLeft left address
2386 * \param yCbCr color component index
2387 * \param lambda
2388 */
2389inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)
2390{
2391  Int64 estDist = 0;
2392  Int classIdx;
2393  for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
2394  {
2395    if( typeIdx == SAO_BO)
2396    {
2397      currentDistortionTableBo[classIdx-1] = 0;
2398      currentRdCostTableBo[classIdx-1] = lambda;
2399    }
2400    if(m_iCount [compIdx][typeIdx][classIdx])
2401    {
2402#if FULL_NBIT
2403      m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitDepth-8)   / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));
2404#else
2405      m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitIncrement) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));
2406#endif
2407      m_iOffset[compIdx][typeIdx][classIdx] = Clip3(-m_iOffsetTh+1, m_iOffsetTh-1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);
2408      if (typeIdx < 4)
2409      {
2410        if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )
2411        {
2412          m_iOffset[compIdx][typeIdx][classIdx] = 0;
2413        }
2414        if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)
2415        {
2416          m_iOffset[compIdx][typeIdx][classIdx] = 0;
2417        }
2418      }
2419      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, m_uiSaoBitIncrease, currentDistortionTableBo, currentRdCostTableBo );
2420    }
2421    else
2422    {
2423      m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;
2424      m_iOffset[compIdx][typeIdx][classIdx] = 0;
2425    }
2426    if( typeIdx != SAO_BO )
2427    {
2428      estDist   += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << m_uiSaoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);
2429    }
2430
2431  }
2432  return estDist;
2433}
2434
2435inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
2436{
2437  return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
2438}
2439inline Int64 TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo )
2440{
2441  //Clean up, best_q_offset.
2442  Int64 iterOffset, tempOffset;
2443  Int64 tempDist, tempRate;
2444  Double tempCost, tempMinCost;
2445  Int64 offsetOutput = 0;
2446  iterOffset = offsetInput;
2447  // 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.
2448  tempMinCost = lambda; 
2449  while (iterOffset != 0)
2450  {
2451    // Calculate the bits required for signalling the offset
2452    tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
2453    if (abs((Int)iterOffset)==m_iOffsetTh-1) 
2454    { 
2455      tempRate --;
2456    }
2457    // Do the dequntization before distorion calculation
2458    tempOffset  = iterOffset << bitIncrease;
2459    tempDist    = estSaoDist( count, tempOffset, offsetOrg, shift);
2460    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
2461    if(tempCost < tempMinCost)
2462    {
2463      tempMinCost = tempCost;
2464      offsetOutput = iterOffset;
2465      if(typeIdx == SAO_BO)
2466      {
2467        currentDistortionTableBo[classIdx-1] = (Int) tempDist;
2468        currentRdCostTableBo[classIdx-1] = tempCost;
2469      }
2470    }
2471    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
2472  }
2473  return offsetOutput;
2474}
2475
2476
2477#if SAO_SINGLE_MERGE
2478Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
2479{
2480  Int typeIdx;
2481
2482  Int64 estDist;
2483  Int classIdx;
2484  Int shift = g_uiBitIncrement << 1;
2485  Int64 bestDist;
2486
2487  SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
2488  SaoLcuParam*  saoLcuParamNeighbor = NULL; 
2489
2490  resetSaoUnit(saoLcuParam);
2491  resetSaoUnit(&compSaoParam[0]);
2492  resetSaoUnit(&compSaoParam[1]);
2493
2494
2495  Double dCostPartBest = MAX_DOUBLE;
2496
2497  Double  bestRDCostTableBo = MAX_DOUBLE;
2498  Int     bestClassTableBo    = 0;
2499  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2500  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2501
2502
2503  SaoLcuParam   saoLcuParamRdo;   
2504  Double   estRate = 0;
2505
2506  resetSaoUnit(&saoLcuParamRdo);
2507
2508  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2509  m_pcRDGoOnSbacCoder->resetBits();
2510#if SAO_TYPE_SHARING
2511 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2512#else
2513 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo);
2514#endif
2515 
2516  dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2517  copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2518  bestDist = 0;
2519 
2520
2521
2522  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2523  {
2524    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2525
2526    if( typeIdx == SAO_BO )
2527    {
2528      // Estimate Best Position
2529      Double currentRDCost = 0.0;
2530
2531      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2532      {
2533        currentRDCost = 0.0;
2534        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2535        {
2536          currentRDCost += currentRdCostTableBo[uj];
2537        }
2538
2539        if( currentRDCost < bestRDCostTableBo)
2540        {
2541          bestRDCostTableBo = currentRDCost;
2542          bestClassTableBo  = i;
2543        }
2544      }
2545
2546      // Re code all Offsets
2547      // Code Center
2548      estDist = 0;
2549      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
2550      {
2551        estDist += currentDistortionTableBo[classIdx];
2552      }
2553    }
2554    resetSaoUnit(&saoLcuParamRdo);
2555    saoLcuParamRdo.length = m_iNumClass[typeIdx];
2556    saoLcuParamRdo.typeIdx = typeIdx;
2557    saoLcuParamRdo.mergeLeftFlag = 0;
2558    saoLcuParamRdo.mergeUpFlag   = 0;
2559#if SAO_TYPE_CODING
2560    saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
2561#else
2562    saoLcuParamRdo.bandPosition = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
2563#endif
2564    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
2565    {
2566#if SAO_TYPE_CODING
2567      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
2568#else
2569      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.bandPosition+1];
2570#endif
2571    }
2572    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2573    m_pcRDGoOnSbacCoder->resetBits();
2574#if SAO_TYPE_SHARING
2575    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2576#else
2577    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo);
2578#endif
2579
2580    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2581    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
2582
2583    if(m_dCost[yCbCr][typeIdx] < dCostPartBest)
2584    {
2585      dCostPartBest = m_dCost[yCbCr][typeIdx];
2586      copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2587      bestDist = estDist;       
2588    }
2589  }
2590  compDistortion[0] += ((Double)bestDist/lambda);
2591  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2592#if SAO_TYPE_SHARING
2593 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
2594#else
2595 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam);
2596#endif
2597  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2598
2599
2600  // merge left or merge up
2601
2602  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2603  {
2604    saoLcuParamNeighbor = NULL;
2605    if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2606    {
2607      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
2608    }
2609    else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2610    {
2611      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
2612    }
2613    if (saoLcuParamNeighbor!=NULL)
2614    {
2615      estDist = 0;
2616      typeIdx = saoLcuParamNeighbor->typeIdx;
2617      if (typeIdx>=0) 
2618      {
2619#if SAO_TYPE_CODING
2620        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
2621#else
2622        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->bandPosition:0;
2623#endif       
2624        Int   merge_iOffset;
2625        for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2626        {
2627          merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
2628          estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
2629        }
2630      }
2631      else
2632      {
2633        estDist = 0;
2634      }
2635
2636      copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
2637      compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
2638      compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
2639
2640      compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
2641    } 
2642  } 
2643}
2644#if SAO_TYPE_SHARING
2645Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)
2646{
2647  Int typeIdx;
2648
2649  Int64 estDist[2];
2650  Int classIdx;
2651  Int shift = g_uiBitIncrement << 1;
2652  Int64 bestDist = 0;
2653
2654  SaoLcuParam*  saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])};
2655  SaoLcuParam*  saoLcuParamNeighbor[2] = {NULL, NULL}; 
2656  SaoLcuParam*  saoMergeParam[2][2];
2657  saoMergeParam[0][0] = &crSaoParam[0];
2658  saoMergeParam[0][1] = &crSaoParam[1]; 
2659  saoMergeParam[1][0] = &cbSaoParam[0];
2660  saoMergeParam[1][1] = &cbSaoParam[1];
2661
2662  resetSaoUnit(saoLcuParam[0]);
2663  resetSaoUnit(saoLcuParam[1]);
2664  resetSaoUnit(saoMergeParam[0][0]);
2665  resetSaoUnit(saoMergeParam[0][1]);
2666  resetSaoUnit(saoMergeParam[1][0]);
2667  resetSaoUnit(saoMergeParam[1][1]);
2668
2669
2670  Double costPartBest = MAX_DOUBLE;
2671
2672  Double  bestRDCostTableBo;
2673  Int     bestClassTableBo[2]    = {0, 0};
2674  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2675  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2676
2677  SaoLcuParam   saoLcuParamRdo[2];   
2678  Double   estRate = 0;
2679
2680  resetSaoUnit(&saoLcuParamRdo[0]);
2681  resetSaoUnit(&saoLcuParamRdo[1]);
2682
2683  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2684  m_pcRDGoOnSbacCoder->resetBits();
2685  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1);
2686  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2);
2687 
2688  costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2689  copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2690  copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2691
2692  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2693  {
2694    if( typeIdx == SAO_BO )
2695    {
2696      // Estimate Best Position
2697      for(Int compIdx = 0; compIdx < 2; compIdx++)
2698      {
2699        Double currentRDCost = 0.0;
2700        bestRDCostTableBo = MAX_DOUBLE;
2701        estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2702        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2703        {
2704          currentRDCost = 0.0;
2705          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2706          {
2707            currentRDCost += currentRdCostTableBo[uj];
2708          }
2709
2710          if( currentRDCost < bestRDCostTableBo)
2711          {
2712            bestRDCostTableBo = currentRDCost;
2713            bestClassTableBo[compIdx]  = i;
2714          }
2715        }
2716
2717        // Re code all Offsets
2718        // Code Center
2719        estDist[compIdx] = 0;
2720        for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)
2721        {
2722          estDist[compIdx] += currentDistortionTableBo[classIdx];
2723        }
2724      }
2725    }
2726    else
2727    {
2728      estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2729      estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2730    }
2731
2732    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2733    m_pcRDGoOnSbacCoder->resetBits();
2734
2735    for(Int compIdx = 0; compIdx < 2; compIdx++)
2736    {
2737      resetSaoUnit(&saoLcuParamRdo[compIdx]);
2738      saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];
2739      saoLcuParamRdo[compIdx].typeIdx = typeIdx;
2740      saoLcuParamRdo[compIdx].mergeLeftFlag = 0;
2741      saoLcuParamRdo[compIdx].mergeUpFlag   = 0;
2742#if SAO_TYPE_CODING
2743      saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
2744#else
2745      saoLcuParamRdo[compIdx].bandPosition = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
2746#endif
2747      for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)
2748      {
2749#if SAO_TYPE_CODING
2750        saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];
2751#else
2752        saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].bandPosition+1];
2753#endif
2754      }
2755
2756      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);
2757    }
2758    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2759    m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1])  + lambda * (Double) estRate);
2760   
2761    if(m_dCost[1][typeIdx] < costPartBest)
2762    {
2763      costPartBest = m_dCost[1][typeIdx];
2764      copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2765      copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2766      bestDist = (estDist[0]+estDist[1]);       
2767    }
2768  }
2769
2770  distortion[0] += ((Double)bestDist/lambda);
2771  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2772  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1);
2773  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2);
2774  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2775
2776  // merge left or merge up
2777
2778  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2779  {
2780    for(Int compIdx = 0; compIdx < 2; compIdx++)
2781    {
2782      saoLcuParamNeighbor[compIdx] = NULL;
2783      if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2784      {
2785        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrLeft]);
2786      }
2787      else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2788      {
2789        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrUp]);
2790      }
2791      if (saoLcuParamNeighbor[compIdx]!=NULL)
2792      {
2793        estDist[compIdx] = 0;
2794        typeIdx = saoLcuParamNeighbor[compIdx]->typeIdx;
2795        if (typeIdx>=0) 
2796        {
2797#if SAO_TYPE_CODING
2798          Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->subTypeIdx:0;
2799#else
2800          Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->bandPosition:0;
2801#endif
2802          Int   merge_iOffset;
2803          for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2804          {
2805            merge_iOffset = saoLcuParamNeighbor[compIdx]->offset[classIdx];
2806            estDist[compIdx]   += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1],  shift);
2807          }
2808        }
2809        else
2810        {
2811          estDist[compIdx] = 0;
2812        }
2813
2814        copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );
2815        saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag   = idxNeighbor;
2816        saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor;
2817        distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);
2818      }
2819    } 
2820  } 
2821}
2822#endif
2823#else
2824Void TEncSampleAdaptiveOffset::rdoSaoUnit(Int rx, Int ry, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda)
2825{
2826  Int typeIdx;
2827
2828  Int64 estDist;
2829  Int classIdx;
2830  Int shift = g_uiBitIncrement << 1;
2831  //   Double dAreaWeight =  0;
2832  SaoLcuParam*  saoLcuParam = NULL;   
2833  SaoLcuParam*  saoLcuParamNeighbor = NULL; 
2834  Int   merge_iOffset [33];
2835  Double merge_dCost;
2836  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
2837  saoLcuParam->mergeUpFlag   = 0;
2838  saoLcuParam->mergeLeftFlag = 0;
2839
2840  m_iTypePartBest[yCbCr] = -1;
2841  m_dCostPartBest[yCbCr] = MAX_DOUBLE;
2842
2843  Double  bestRDCostTableBo = MAX_DOUBLE;
2844  Int     bestClassTableBo    = 0;
2845  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2846  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2847  Int     bestClassTableBoMerge = 0;
2848
2849  SaoLcuParam   saoLcuParamRdo;   
2850  Double   estRate = 0;
2851
2852  resetSaoUnit(saoLcuParam);
2853  resetSaoUnit(&saoLcuParamRdo);
2854
2855  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2856  m_pcRDGoOnSbacCoder->resetBits();
2857  Int allowMergeLeft = 1;
2858  Int allowMergeUp   = 1;
2859  if (rx!=0)
2860  { 
2861    // check tile id and slice id
2862    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()))
2863    {
2864      allowMergeLeft = 0;
2865    }
2866  }
2867  if (ry!=0)
2868  {
2869    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()))
2870    {
2871      allowMergeUp = 0;
2872    }
2873  }
2874  m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
2875  m_dCostPartBest[yCbCr] = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2876  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2877
2878  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2879  {
2880    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2881
2882    if( typeIdx == SAO_BO )
2883    {
2884      // Estimate Best Position
2885      Double currentRDCost = 0.0;
2886
2887      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2888      {
2889        currentRDCost = 0.0;
2890        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2891        {
2892          currentRDCost += currentRdCostTableBo[uj];
2893        }
2894
2895        if( currentRDCost < bestRDCostTableBo)
2896        {
2897          bestRDCostTableBo = currentRDCost;
2898          bestClassTableBo  = i;
2899        }
2900      }
2901
2902      // Re code all Offsets
2903      // Code Center
2904      estDist = 0;
2905      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
2906      {
2907        estDist += currentDistortionTableBo[classIdx];
2908      }
2909    }
2910    resetSaoUnit(&saoLcuParamRdo);
2911    saoLcuParamRdo.length = m_iNumClass[typeIdx];
2912    saoLcuParamRdo.typeIdx = typeIdx;
2913    saoLcuParamRdo.mergeLeftFlag = 0;
2914    saoLcuParamRdo.mergeUpFlag   = 0;
2915    saoLcuParamRdo.bandPosition = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
2916    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
2917    {
2918      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.bandPosition+1];
2919    }
2920    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2921    m_pcRDGoOnSbacCoder->resetBits();
2922    m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
2923    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2924    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
2925
2926    if(m_dCost[yCbCr][typeIdx] < m_dCostPartBest[yCbCr])
2927    {
2928      m_dCostPartBest[yCbCr] = m_dCost[yCbCr][typeIdx];
2929      m_iTypePartBest[yCbCr] = typeIdx;
2930      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2931    }
2932  }
2933
2934  // merge left or merge up
2935
2936  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2937  {
2938    saoLcuParamNeighbor = NULL;
2939    if (addrLeft>=0 && idxNeighbor ==0)
2940    {
2941      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
2942    }
2943    else if (addrUp>=0 && idxNeighbor ==1)
2944    {
2945      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
2946    }
2947    if (saoLcuParamNeighbor!=NULL)
2948    {
2949        Int mergeBandPosition = 0;
2950        estDist = 0;
2951        typeIdx = saoLcuParamNeighbor->typeIdx;
2952        if (saoLcuParamNeighbor->typeIdx>=0) //new
2953        {
2954          mergeBandPosition = (saoLcuParamNeighbor->typeIdx == SAO_BO)?saoLcuParamNeighbor->bandPosition:0;
2955          for(classIdx = mergeBandPosition+1; classIdx < mergeBandPosition+m_iNumClass[typeIdx]+1; classIdx++)
2956          {
2957            merge_iOffset[classIdx] = saoLcuParamNeighbor->offset[classIdx-1-saoLcuParamNeighbor->bandPosition];
2958            estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx], merge_iOffset[classIdx], m_iOffsetOrg[yCbCr][typeIdx][classIdx],  shift);
2959          }
2960        }
2961        else
2962        {
2963          saoLcuParamRdo.typeIdx = -1;
2964          saoLcuParamRdo.length  = 0;
2965          estDist = 0;
2966        }
2967        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2968        m_pcRDGoOnSbacCoder->resetBits();
2969        saoLcuParamRdo.mergeUpFlag   = idxNeighbor;
2970        saoLcuParamRdo.mergeLeftFlag = !idxNeighbor;
2971        m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
2972        estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2973
2974        merge_dCost = (Double)((Double)estDist + m_dLambdaLuma * estRate) ;
2975
2976        if(merge_dCost < m_dCostPartBest[yCbCr])
2977        {
2978          m_dCostPartBest[yCbCr] = merge_dCost;
2979          m_iTypePartBest[yCbCr] = typeIdx;
2980          if (typeIdx>=0)
2981          {
2982            bestClassTableBoMerge   = mergeBandPosition;
2983            for(classIdx = mergeBandPosition+1; classIdx < mergeBandPosition+m_iNumClass[typeIdx]+1; classIdx++)
2984            {
2985              m_iOffset[yCbCr][typeIdx][classIdx] = merge_iOffset[classIdx];
2986            }
2987          }
2988          saoLcuParam->mergeUpFlag   = idxNeighbor;
2989          saoLcuParam->mergeLeftFlag = !idxNeighbor;
2990          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2991        }
2992    }
2993  } 
2994
2995  saoLcuParam->typeIdx  = m_iTypePartBest[yCbCr];
2996  if (saoLcuParam->typeIdx != -1)
2997  {
2998    saoLcuParam->length = m_iNumClass[saoLcuParam->typeIdx];
2999    Int minIndex = 0;
3000    if( saoLcuParam->typeIdx == SAO_BO )
3001    {
3002      if ((saoLcuParam->mergeUpFlag )||(saoLcuParam->mergeLeftFlag)) 
3003      {
3004        saoLcuParam->bandPosition = bestClassTableBoMerge;
3005      }
3006      else
3007      {
3008        saoLcuParam->bandPosition = bestClassTableBo;
3009      }
3010      minIndex = saoLcuParam->bandPosition;
3011    }
3012    for (Int i=0; i< saoLcuParam->length ; i++)
3013    {
3014      saoLcuParam->offset[i] = (Int) m_iOffset[yCbCr][saoLcuParam->typeIdx][minIndex+i+1];
3015    }
3016  }
3017  else
3018  {
3019    saoLcuParam->length = 0;
3020  }
3021
3022  m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
3023  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_CURR_BEST] );
3024}
3025#endif
3026
3027//! \}
Note: See TracBrowser for help on using the repository browser.