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

Last change on this file since 1606 was 475, checked in by nokia, 11 years ago

Integrate auxiliary picture layers (JCTVC-O0041)

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