source: 3DVCSoftware/branches/HTM-6.2-dev2-MERL/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1003

Last change on this file since 1003 was 296, checked in by tech, 12 years ago

Reintegrated branch 5.1-dev0 rev. 295.

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