source: SHVCSoftware/trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 310

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

reintegrate SHM-2.1-dev branch

File size: 77.0 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  saoParam->bSaoFlag[1] = true;
1874  saoParam->oneUnitFlag[0] = false;
1875  saoParam->oneUnitFlag[1] = false;
1876  saoParam->oneUnitFlag[2] = false;
1877
1878#if SAO_ENCODING_CHOICE
1879#if SAO_ENCODING_CHOICE_CHROMA
1880  Int numNoSao[2];
1881  numNoSao[0] = 0;// Luma
1882  numNoSao[1] = 0;// Chroma
1883  if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
1884  {
1885    saoParam->bSaoFlag[0] = false;
1886  }
1887  if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
1888  {
1889    saoParam->bSaoFlag[1] = false;
1890  }
1891#else
1892  Int numNoSao = 0;
1893
1894  if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
1895  {
1896    saoParam->bSaoFlag[0] = false;
1897    saoParam->bSaoFlag[1] = false;
1898  }
1899#endif
1900#endif
1901
1902  for (idxY = 0; idxY< frameHeightInCU; idxY++)
1903  {
1904    for (idxX = 0; idxX< frameWidthInCU; idxX++)
1905    {
1906      addr     = idxX  + frameWidthInCU*idxY;
1907      addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
1908      addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
1909      Int allowMergeLeft = 1;
1910      Int allowMergeUp   = 1;
1911      UInt rate;
1912      Double bestCost, mergeCost;
1913      if (idxX!=0)
1914      { 
1915        // check tile id and slice id
1916        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()))
1917        {
1918          allowMergeLeft = 0;
1919        }
1920      }
1921      else
1922      {
1923        allowMergeLeft = 0;
1924      }
1925      if (idxY!=0)
1926      {
1927        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()))
1928        {
1929          allowMergeUp = 0;
1930        }
1931      }
1932      else
1933      {
1934        allowMergeUp = 0;
1935      }
1936
1937      compDistortion[0] = 0; 
1938      compDistortion[1] = 0; 
1939      compDistortion[2] = 0;
1940      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
1941      if (allowMergeLeft)
1942      {
1943        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
1944      }
1945      if (allowMergeUp)
1946      {
1947        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
1948      }
1949      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
1950      // reset stats Y, Cb, Cr
1951      for ( compIdx=0;compIdx<3;compIdx++)
1952      {
1953        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
1954        {
1955          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
1956          {
1957            m_iOffset   [compIdx][j][k] = 0;
1958            if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){
1959              m_iCount    [compIdx][j][k] = m_count_PreDblk    [addr][compIdx][j][k];
1960              m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
1961            }
1962            else
1963            {
1964              m_iCount    [compIdx][j][k] = 0;
1965              m_iOffsetOrg[compIdx][j][k] = 0;
1966            }
1967          } 
1968        }
1969        saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
1970        saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
1971        saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
1972        saoParam->saoLcuParam[compIdx][addr].subTypeIdx    = 0;
1973#if SAO_ENCODING_CHOICE
1974  if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
1975#endif
1976        {
1977          calcSaoStatsCu(addr, compIdx,  compIdx);
1978
1979       }
1980      }
1981      saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0,  lambda, &mergeSaoParam[0][0], &compDistortion[0]);
1982      sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
1983     if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] )
1984      {
1985        // Cost of new SAO_params
1986        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
1987        m_pcRDGoOnSbacCoder->resetBits();
1988        if (allowMergeLeft)
1989        {
1990          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
1991        }
1992        if (allowMergeUp)
1993        {
1994          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
1995        }
1996        for ( compIdx=0;compIdx<3;compIdx++)
1997        {
1998        if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1]))
1999          {
2000           m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx);
2001          }
2002        }
2003
2004        rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2005        bestCost = compDistortion[0] + (Double)rate;
2006        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2007
2008        // Cost of Merge
2009        for(Int mergeUp=0; mergeUp<2; ++mergeUp)
2010        {
2011          if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) )
2012          {
2013            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2014            m_pcRDGoOnSbacCoder->resetBits();
2015            if (allowMergeLeft)
2016            {
2017              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); 
2018            }
2019            if ( allowMergeUp && (mergeUp==1) )
2020            {
2021              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); 
2022            }
2023
2024            rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2025            mergeCost = compDistortion[mergeUp+1] + (Double)rate;
2026            if (mergeCost < bestCost)
2027            {
2028              bestCost = mergeCost;
2029              m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);             
2030              for ( compIdx=0;compIdx<3;compIdx++)
2031              {
2032                mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp;
2033                mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;
2034                if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1]))
2035                {
2036                  copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );             
2037                }
2038              }
2039            }
2040          }
2041        }
2042#if SAO_ENCODING_CHOICE
2043#if SAO_ENCODING_CHOICE_CHROMA
2044if( saoParam->saoLcuParam[0][addr].typeIdx == -1)
2045{
2046  numNoSao[0]++;
2047}
2048if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
2049{
2050  numNoSao[1]+=2;
2051}
2052#else
2053        for ( compIdx=0;compIdx<3;compIdx++)
2054        {
2055          if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
2056          {
2057            numNoSao++;
2058          }
2059        }
2060#endif
2061#endif
2062        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2063        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2064      }
2065    }
2066  }
2067#if SAO_ENCODING_CHOICE
2068#if SAO_ENCODING_CHOICE_CHROMA
2069  if( !saoParam->bSaoFlag[0])
2070  {
2071    m_depthSaoRate[0][depth] = 1.0;
2072  }
2073  else
2074  {
2075    m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
2076  }
2077  if( !saoParam->bSaoFlag[1]) 
2078  {
2079    m_depthSaoRate[1][depth] = 1.0;
2080  }
2081  else 
2082  {
2083    m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
2084  }
2085#else
2086  if( depth == 0)
2087  {
2088    // update SAO Rate
2089    m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
2090  }
2091#endif
2092#endif
2093
2094}
2095/** rate distortion optimization of SAO unit
2096 * \param saoParam SAO parameters
2097 * \param addr address
2098 * \param addrUp above address
2099 * \param addrLeft left address
2100 * \param yCbCr color component index
2101 * \param lambda
2102 */
2103inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)
2104{
2105  Int64 estDist = 0;
2106  Int classIdx;
2107  Int bitDepth = (compIdx==0) ? g_bitDepthY : g_bitDepthC;
2108  Int saoBitIncrease = (compIdx==0) ? m_uiSaoBitIncreaseY : m_uiSaoBitIncreaseC;
2109  Int saoOffsetTh = (compIdx==0) ? m_iOffsetThY : m_iOffsetThC;
2110
2111  for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
2112  {
2113    if( typeIdx == SAO_BO)
2114    {
2115      currentDistortionTableBo[classIdx-1] = 0;
2116      currentRdCostTableBo[classIdx-1] = lambda;
2117    }
2118    if(m_iCount [compIdx][typeIdx][classIdx])
2119    {
2120      m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi(bitDepth, (Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<(bitDepth-8)) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<saoBitIncrease));
2121      m_iOffset[compIdx][typeIdx][classIdx] = Clip3(-saoOffsetTh+1, saoOffsetTh-1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);
2122      if (typeIdx < 4)
2123      {
2124        if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )
2125        {
2126          m_iOffset[compIdx][typeIdx][classIdx] = 0;
2127        }
2128        if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)
2129        {
2130          m_iOffset[compIdx][typeIdx][classIdx] = 0;
2131        }
2132      }
2133      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 );
2134    }
2135    else
2136    {
2137      m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;
2138      m_iOffset[compIdx][typeIdx][classIdx] = 0;
2139    }
2140    if( typeIdx != SAO_BO )
2141    {
2142      estDist   += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << saoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);
2143    }
2144
2145  }
2146  return estDist;
2147}
2148
2149inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
2150{
2151  return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
2152}
2153inline 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 )
2154{
2155  //Clean up, best_q_offset.
2156  Int64 iterOffset, tempOffset;
2157  Int64 tempDist, tempRate;
2158  Double tempCost, tempMinCost;
2159  Int64 offsetOutput = 0;
2160  iterOffset = offsetInput;
2161  // 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.
2162  tempMinCost = lambda; 
2163  while (iterOffset != 0)
2164  {
2165    // Calculate the bits required for signalling the offset
2166    tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
2167    if (abs((Int)iterOffset)==offsetTh-1) 
2168    { 
2169      tempRate --;
2170    }
2171    // Do the dequntization before distorion calculation
2172    tempOffset  = iterOffset << bitIncrease;
2173    tempDist    = estSaoDist( count, tempOffset, offsetOrg, shift);
2174    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
2175    if(tempCost < tempMinCost)
2176    {
2177      tempMinCost = tempCost;
2178      offsetOutput = iterOffset;
2179      if(typeIdx == SAO_BO)
2180      {
2181        currentDistortionTableBo[classIdx-1] = (Int) tempDist;
2182        currentRdCostTableBo[classIdx-1] = tempCost;
2183      }
2184    }
2185    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
2186  }
2187  return offsetOutput;
2188}
2189
2190
2191Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
2192{
2193  Int typeIdx;
2194
2195  Int64 estDist;
2196  Int classIdx;
2197  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8);
2198  Int64 bestDist;
2199
2200  SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
2201  SaoLcuParam*  saoLcuParamNeighbor = NULL; 
2202
2203  resetSaoUnit(saoLcuParam);
2204  resetSaoUnit(&compSaoParam[0]);
2205  resetSaoUnit(&compSaoParam[1]);
2206
2207
2208  Double dCostPartBest = MAX_DOUBLE;
2209
2210  Double  bestRDCostTableBo = MAX_DOUBLE;
2211  Int     bestClassTableBo    = 0;
2212  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2213  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2214
2215
2216  SaoLcuParam   saoLcuParamRdo;   
2217  Double   estRate = 0;
2218
2219  resetSaoUnit(&saoLcuParamRdo);
2220
2221  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2222  m_pcRDGoOnSbacCoder->resetBits();
2223 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2224 
2225  dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2226  copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2227  bestDist = 0;
2228 
2229
2230
2231  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2232  {
2233    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2234
2235    if( typeIdx == SAO_BO )
2236    {
2237      // Estimate Best Position
2238      Double currentRDCost = 0.0;
2239
2240      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2241      {
2242        currentRDCost = 0.0;
2243        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2244        {
2245          currentRDCost += currentRdCostTableBo[uj];
2246        }
2247
2248        if( currentRDCost < bestRDCostTableBo)
2249        {
2250          bestRDCostTableBo = currentRDCost;
2251          bestClassTableBo  = i;
2252        }
2253      }
2254
2255      // Re code all Offsets
2256      // Code Center
2257      estDist = 0;
2258      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
2259      {
2260        estDist += currentDistortionTableBo[classIdx];
2261      }
2262    }
2263    resetSaoUnit(&saoLcuParamRdo);
2264    saoLcuParamRdo.length = m_iNumClass[typeIdx];
2265    saoLcuParamRdo.typeIdx = typeIdx;
2266    saoLcuParamRdo.mergeLeftFlag = 0;
2267    saoLcuParamRdo.mergeUpFlag   = 0;
2268    saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
2269    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
2270    {
2271      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
2272    }
2273    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2274    m_pcRDGoOnSbacCoder->resetBits();
2275    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2276
2277    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2278    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
2279
2280    if(m_dCost[yCbCr][typeIdx] < dCostPartBest)
2281    {
2282      dCostPartBest = m_dCost[yCbCr][typeIdx];
2283      copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2284      bestDist = estDist;       
2285    }
2286  }
2287  compDistortion[0] += ((Double)bestDist/lambda);
2288  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2289 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
2290  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2291
2292
2293  // merge left or merge up
2294
2295  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2296  {
2297    saoLcuParamNeighbor = NULL;
2298    if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2299    {
2300      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
2301    }
2302    else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2303    {
2304      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
2305    }
2306    if (saoLcuParamNeighbor!=NULL)
2307    {
2308      estDist = 0;
2309      typeIdx = saoLcuParamNeighbor->typeIdx;
2310      if (typeIdx>=0) 
2311      {
2312        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
2313        Int   merge_iOffset;
2314        for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2315        {
2316          merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
2317          estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
2318        }
2319      }
2320      else
2321      {
2322        estDist = 0;
2323      }
2324
2325      copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
2326      compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
2327      compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
2328
2329      compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
2330    } 
2331  } 
2332}
2333Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)
2334{
2335  Int typeIdx;
2336
2337  Int64 estDist[2];
2338  Int classIdx;
2339  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC-8);
2340  Int64 bestDist = 0;
2341
2342  SaoLcuParam*  saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])};
2343  SaoLcuParam*  saoLcuParamNeighbor[2] = {NULL, NULL}; 
2344  SaoLcuParam*  saoMergeParam[2][2];
2345  saoMergeParam[0][0] = &crSaoParam[0];
2346  saoMergeParam[0][1] = &crSaoParam[1]; 
2347  saoMergeParam[1][0] = &cbSaoParam[0];
2348  saoMergeParam[1][1] = &cbSaoParam[1];
2349
2350  resetSaoUnit(saoLcuParam[0]);
2351  resetSaoUnit(saoLcuParam[1]);
2352  resetSaoUnit(saoMergeParam[0][0]);
2353  resetSaoUnit(saoMergeParam[0][1]);
2354  resetSaoUnit(saoMergeParam[1][0]);
2355  resetSaoUnit(saoMergeParam[1][1]);
2356
2357
2358  Double costPartBest = MAX_DOUBLE;
2359
2360  Double  bestRDCostTableBo;
2361  Int     bestClassTableBo[2]    = {0, 0};
2362  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2363  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2364
2365  SaoLcuParam   saoLcuParamRdo[2];   
2366  Double   estRate = 0;
2367
2368  resetSaoUnit(&saoLcuParamRdo[0]);
2369  resetSaoUnit(&saoLcuParamRdo[1]);
2370
2371  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2372  m_pcRDGoOnSbacCoder->resetBits();
2373  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1);
2374  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2);
2375 
2376  costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2377  copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2378  copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2379
2380  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2381  {
2382    if( typeIdx == SAO_BO )
2383    {
2384      // Estimate Best Position
2385      for(Int compIdx = 0; compIdx < 2; compIdx++)
2386      {
2387        Double currentRDCost = 0.0;
2388        bestRDCostTableBo = MAX_DOUBLE;
2389        estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2390        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2391        {
2392          currentRDCost = 0.0;
2393          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2394          {
2395            currentRDCost += currentRdCostTableBo[uj];
2396          }
2397
2398          if( currentRDCost < bestRDCostTableBo)
2399          {
2400            bestRDCostTableBo = currentRDCost;
2401            bestClassTableBo[compIdx]  = i;
2402          }
2403        }
2404
2405        // Re code all Offsets
2406        // Code Center
2407        estDist[compIdx] = 0;
2408        for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)
2409        {
2410          estDist[compIdx] += currentDistortionTableBo[classIdx];
2411        }
2412      }
2413    }
2414    else
2415    {
2416      estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2417      estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2418    }
2419
2420    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2421    m_pcRDGoOnSbacCoder->resetBits();
2422
2423    for(Int compIdx = 0; compIdx < 2; compIdx++)
2424    {
2425      resetSaoUnit(&saoLcuParamRdo[compIdx]);
2426      saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];
2427      saoLcuParamRdo[compIdx].typeIdx = typeIdx;
2428      saoLcuParamRdo[compIdx].mergeLeftFlag = 0;
2429      saoLcuParamRdo[compIdx].mergeUpFlag   = 0;
2430      saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
2431      for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)
2432      {
2433        saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];
2434      }
2435
2436      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);
2437    }
2438    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2439    m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1])  + lambda * (Double) estRate);
2440   
2441    if(m_dCost[1][typeIdx] < costPartBest)
2442    {
2443      costPartBest = m_dCost[1][typeIdx];
2444      copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2445      copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2446      bestDist = (estDist[0]+estDist[1]);       
2447    }
2448  }
2449
2450  distortion[0] += ((Double)bestDist/lambda);
2451  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2452  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1);
2453  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2);
2454  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2455
2456  // merge left or merge up
2457
2458  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2459  {
2460    for(Int compIdx = 0; compIdx < 2; compIdx++)
2461    {
2462      saoLcuParamNeighbor[compIdx] = NULL;
2463      if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2464      {
2465        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrLeft]);
2466      }
2467      else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2468      {
2469        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrUp]);
2470      }
2471      if (saoLcuParamNeighbor[compIdx]!=NULL)
2472      {
2473        estDist[compIdx] = 0;
2474        typeIdx = saoLcuParamNeighbor[compIdx]->typeIdx;
2475        if (typeIdx>=0) 
2476        {
2477          Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->subTypeIdx:0;
2478          Int   merge_iOffset;
2479          for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2480          {
2481            merge_iOffset = saoLcuParamNeighbor[compIdx]->offset[classIdx];
2482            estDist[compIdx]   += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1],  shift);
2483          }
2484        }
2485        else
2486        {
2487          estDist[compIdx] = 0;
2488        }
2489
2490        copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );
2491        saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag   = idxNeighbor;
2492        saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor;
2493        distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);
2494      }
2495    } 
2496  } 
2497}
2498
2499//! \}
Note: See TracBrowser for help on using the repository browser.