source: SHVCSoftware/branches/SHM-2.0avc-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1564

Last change on this file since 1564 was 191, checked in by seregin, 12 years ago

unix2dos for *.cpp and *.h

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