source: 3DVCSoftware/branches/HTM-5.1-dev3-MERL/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 222

Last change on this file since 222 was 56, checked in by hschwarz, 13 years ago

updated trunk (move to HM6.1)

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