source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 476

Last change on this file since 476 was 443, checked in by tech, 12 years ago
  • Reintegrated branch 6.2-dev0 rev. 442.
  • Changed version number.
  • Added coding results.
File size: 141.4 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#if LGE_SAO_MIGRATION_D0091
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#if SAO_ENCODING_CHOICE_CHROMA
62    m_depthSaoRate[0][0] = 0;
63    m_depthSaoRate[0][1] = 0;
64    m_depthSaoRate[0][2] = 0;
65    m_depthSaoRate[0][3] = 0;
66    m_depthSaoRate[1][0] = 0;
67    m_depthSaoRate[1][1] = 0;
68    m_depthSaoRate[1][2] = 0;
69    m_depthSaoRate[1][3] = 0;
70#endif
71}
72
73TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
74{
75
76}
77// ====================================================================================================================
78// Constants
79// ====================================================================================================================
80
81
82// ====================================================================================================================
83// Tables
84// ====================================================================================================================
85
86inline Double xRoundIbdi2(Double x)
87{
88#if FULL_NBIT
89    Int bitDepthMinus8 = g_uiBitDepth - 8;
90    return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)) : ((Int)(((Int)(x)-(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)));
91#else
92    return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)-(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)));
93#endif
94}
95
96/** rounding with IBDI
97 * \param  x
98 */
99inline Double xRoundIbdi(Double x)
100{
101#if FULL_NBIT
102    return (g_uiBitDepth > 8 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
103#else
104    return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
105#endif
106}
107
108/** process SAO for one partition
109 * \param  *psQTPart, iPartIdx, dLambda
110 */
111Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda, Int yCbCr)
112{
113    Int iTypeIdx;
114    Int iNumTotalType = MAX_NUM_SAO_TYPE;
115    SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
116
117    Int64 iEstDist;
118    Int iClassIdx;
119    Int uiShift = g_uiBitIncrement << 1;
120    UInt uiDepth = pOnePart->PartLevel;
121
122    m_iDistOrg [iPartIdx] =  0;
123
124    Double  bestRDCostTableBo = MAX_DOUBLE;
125    Int     bestClassTableBo    = 0;
126    Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
127    Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
128
129    Int addr;
130    Int allowMergeLeft;
131    Int allowMergeUp;
132    Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
133    SaoLcuParam  saoLcuParamRdo;
134
135    for (iTypeIdx=-1; iTypeIdx<iNumTotalType; iTypeIdx++)
136    {
137        if( m_bUseSBACRD )
138        {
139            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
140            m_pcRDGoOnSbacCoder->resetBits();
141        }
142        else
143        {
144            m_pcEntropyCoder->resetEntropy();
145            m_pcEntropyCoder->resetBits();
146        }
147
148        iEstDist = 0;
149
150        if (iTypeIdx == -1)
151        {     
152            for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
153            {
154                for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
155                {
156                    addr = ry * frameWidthInCU + rx;
157                    // get bits for iTypeIdx = -1
158                    allowMergeLeft = 1;
159                    allowMergeUp   = 1;
160                    if (rx != 0)
161                    { 
162                        // check tile id and slice id
163                        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
164                        {
165                            allowMergeLeft = 0;
166                        }
167                    }
168                    if (ry!=0)
169                    {
170                        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
171                        {
172                            allowMergeUp = 0;
173                        }
174                    }
175
176                    // reset
177                    resetSaoUnit(&saoLcuParamRdo);
178       
179                    // set merge flag
180                    saoLcuParamRdo.mergeUpFlag   = 1;
181                    saoLcuParamRdo.mergeLeftFlag = 1;
182       
183                    if (ry == pOnePart->StartCUY) 
184                    {
185                        saoLcuParamRdo.mergeUpFlag = 0;
186                    } 
187
188                    if (rx == pOnePart->StartCUX) 
189                    {
190                        saoLcuParamRdo.mergeLeftFlag = 0;
191                    }
192
193                    m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
194
195                }
196            }
197        }
198
199        if (iTypeIdx>=0)
200        {
201            iEstDist = estSaoTypeDist(iPartIdx, iTypeIdx, uiShift, dLambda, currentDistortionTableBo, currentRdCostTableBo);
202            if( iTypeIdx == SAO_BO )
203            {
204                // Estimate Best Position
205                Double currentRDCost = 0.0;
206   
207                for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
208                {
209                    currentRDCost = 0.0;
210                    for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
211                    {
212                        currentRDCost += currentRdCostTableBo[uj];
213                    }
214
215                    if( currentRDCost < bestRDCostTableBo)
216                    {
217                        bestRDCostTableBo = currentRDCost;
218                        bestClassTableBo  = i;
219                    }
220                }
221
222                // Re code all Offsets
223                // Code Center
224                for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++)
225                {
226                    iEstDist += currentDistortionTableBo[iClassIdx];
227                }
228            }
229
230            for (Int ry = pOnePart->StartCUY; ry<= pOnePart->EndCUY; ry++)
231            {
232                for (Int rx = pOnePart->StartCUX; rx <= pOnePart->EndCUX; rx++)
233                {
234                    addr = ry * frameWidthInCU + rx;         
235       
236                    // get bits for iTypeIdx = -1
237                    allowMergeLeft = 1;
238                    allowMergeUp   = 1;
239                    if (rx != 0)
240                    { 
241                        // check tile id and slice id
242                        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
243                        {
244                            allowMergeLeft = 0;
245                        }
246                    }
247                    if (ry!=0)
248                    {
249                        if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
250                        {
251                            allowMergeUp = 0;
252                        }
253                    }
254   
255                    // reset
256                    resetSaoUnit(&saoLcuParamRdo);
257
258                    // set merge flag
259                    saoLcuParamRdo.mergeUpFlag   = 1;
260                    saoLcuParamRdo.mergeLeftFlag = 1;
261   
262                    if (ry == pOnePart->StartCUY) 
263                    {
264                        saoLcuParamRdo.mergeUpFlag = 0;
265                    } 
266   
267                    if (rx == pOnePart->StartCUX) 
268                    {
269                        saoLcuParamRdo.mergeLeftFlag = 0;
270                    }
271
272                    // set type and offsets
273                    saoLcuParamRdo.typeIdx = iTypeIdx;
274                    saoLcuParamRdo.subTypeIdx = (iTypeIdx==SAO_BO)?bestClassTableBo:0;
275                    saoLcuParamRdo.length = m_iNumClass[iTypeIdx];
276                    for (iClassIdx = 0; iClassIdx < saoLcuParamRdo.length; iClassIdx++)
277                    {
278                        saoLcuParamRdo.offset[iClassIdx] = (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+saoLcuParamRdo.subTypeIdx+1];
279                    }
280
281                    m_pcEntropyCoder->encodeSaoUnitInterleaving(yCbCr, 1, rx, ry,  &saoLcuParamRdo, 1,  1,  allowMergeLeft, allowMergeUp);
282
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->subTypeIdx = bestClassTableBo;
326            minIndex = pOnePart->subTypeIdx;
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, Int yCbCr)
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, yCbCr);
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, yCbCr);
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  if (m_iDistOrg)
485  {
486    delete [] m_iDistOrg ; m_iDistOrg = NULL;
487  }
488  if (m_dCostPartBest)
489  {
490    delete [] m_dCostPartBest ; m_dCostPartBest = NULL;
491  }
492  if (m_iTypePartBest)
493  {
494    delete [] m_iTypePartBest ; m_iTypePartBest = NULL;
495  }
496  if (m_iRate)
497  {
498    delete [] m_iRate ; m_iRate = NULL;
499  }
500  if (m_iDist)
501  {
502    delete [] m_iDist ; m_iDist = NULL;
503  }
504  if (m_dCost)
505  {
506    delete [] m_dCost ; m_dCost = NULL;
507  }
508  if (m_iCount)
509  {
510    delete [] m_iCount  ; m_iCount = NULL;
511  }
512  if (m_iOffset)
513  {
514    delete [] m_iOffset ; m_iOffset = NULL;
515  }
516  if (m_iOffsetOrg)
517  {
518    delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;
519  }
520  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
521
522  for (Int i=0;i<numLcu;i++)
523  {
524    for (Int j=0;j<3;j++)
525    {
526      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
527      {
528        if (m_count_PreDblk [i][j][k])
529        {
530          delete [] m_count_PreDblk [i][j][k];
531        }
532        if (m_offsetOrg_PreDblk[i][j][k])
533        {
534          delete [] m_offsetOrg_PreDblk[i][j][k];
535        }
536      }
537      if (m_count_PreDblk [i][j])
538      {
539        delete [] m_count_PreDblk [i][j];
540      }
541      if (m_offsetOrg_PreDblk[i][j])
542      {
543        delete [] m_offsetOrg_PreDblk[i][j];
544      }
545    }
546    if (m_count_PreDblk [i])
547    {
548      delete [] m_count_PreDblk [i];
549    }
550    if (m_offsetOrg_PreDblk[i])
551    {
552      delete [] m_offsetOrg_PreDblk[i];
553    }
554  }
555  if (m_count_PreDblk)
556  {
557    delete [] m_count_PreDblk  ; m_count_PreDblk = NULL;
558  }
559  if (m_offsetOrg_PreDblk)
560  {
561    delete [] m_offsetOrg_PreDblk ; m_offsetOrg_PreDblk = NULL;
562  }
563
564  Int iMaxDepth = 4;
565  Int iDepth;
566  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
567  {
568    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
569    {
570      delete m_pppcRDSbacCoder[iDepth][iCIIdx];
571      delete m_pppcBinCoderCABAC[iDepth][iCIIdx];
572    }
573  }
574
575  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
576  {
577    delete [] m_pppcRDSbacCoder[iDepth];
578    delete [] m_pppcBinCoderCABAC[iDepth];
579  }
580
581  delete [] m_pppcRDSbacCoder;
582  delete [] m_pppcBinCoderCABAC;
583}
584
585/** create Encoder Buffer for SAO
586 * \param
587 */
588Void TEncSampleAdaptiveOffset::createEncBuffer()
589{
590  m_iDistOrg = new Int64 [m_iNumTotalParts];
591  m_dCostPartBest = new Double [m_iNumTotalParts];
592  m_iTypePartBest = new Int [m_iNumTotalParts];
593
594  m_iRate = new Int64* [m_iNumTotalParts];
595  m_iDist = new Int64* [m_iNumTotalParts];
596  m_dCost = new Double*[m_iNumTotalParts];
597
598  m_iCount  = new Int64 **[m_iNumTotalParts];
599  m_iOffset = new Int64 **[m_iNumTotalParts];
600  m_iOffsetOrg = new Int64 **[m_iNumTotalParts];
601
602  for (Int i=0;i<m_iNumTotalParts;i++)
603  {
604    m_iRate[i] = new Int64  [MAX_NUM_SAO_TYPE];
605    m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE];
606    m_dCost[i] = new Double [MAX_NUM_SAO_TYPE];
607
608    m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE];
609    m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE];
610    m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE];
611
612    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
613    {
614      m_iCount [i][j]   = new Int64 [MAX_NUM_SAO_CLASS];
615      m_iOffset[i][j]   = new Int64 [MAX_NUM_SAO_CLASS];
616      m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS];
617    }
618  }
619  Int numLcu = m_iNumCuInWidth * m_iNumCuInHeight;
620  m_count_PreDblk  = new Int64 ***[numLcu];
621  m_offsetOrg_PreDblk = new Int64 ***[numLcu];
622  for (Int i=0; i<numLcu; i++)
623  {
624    m_count_PreDblk[i]  = new Int64 **[3];
625    m_offsetOrg_PreDblk[i] = new Int64 **[3];
626
627    for (Int j=0;j<3;j++)
628    {
629      m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
630      m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
631
632      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
633      {
634        m_count_PreDblk [i][j][k]   = new Int64 [MAX_NUM_SAO_CLASS];
635        m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS];
636      }
637    }
638  }
639
640  Int iMaxDepth = 4;
641  m_pppcRDSbacCoder = new TEncSbac** [iMaxDepth+1];
642#if FAST_BIT_EST
643  m_pppcBinCoderCABAC = new TEncBinCABACCounter** [iMaxDepth+1];
644#else
645  m_pppcBinCoderCABAC = new TEncBinCABAC** [iMaxDepth+1];
646#endif
647
648  for ( Int iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
649  {
650    m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM];
651#if FAST_BIT_EST
652    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM];
653#else
654    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM];
655#endif
656    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
657    {
658      m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac;
659#if FAST_BIT_EST
660      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter;
661#else
662      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC;
663#endif
664      m_pppcRDSbacCoder   [iDepth][iCIIdx]->init( m_pppcBinCoderCABAC [iDepth][iCIIdx] );
665    }
666  }
667}
668
669/** Start SAO encoder
670 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
671 */
672Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
673{
674  m_bUseSBACRD = true;
675  m_pcPic = pcPic;
676  m_pcEntropyCoder = pcEntropyCoder;
677
678  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
679  m_pcEntropyCoder->setEntropyCoder(m_pcRDGoOnSbacCoder, pcPic->getSlice(0));
680  m_pcEntropyCoder->resetEntropy();
681  m_pcEntropyCoder->resetBits();
682
683  if( m_bUseSBACRD )
684  {
685    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
686    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
687  }
688}
689
690/** End SAO encoder
691 */
692Void TEncSampleAdaptiveOffset::endSaoEnc()
693{
694  m_pcPic = NULL;
695  m_pcEntropyCoder = NULL;
696}
697
698inline int xSign(int x)
699{
700  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
701}
702
703/** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
704 * \param  pRecStart to-be-filtered block buffer pointer
705 * \param  pOrgStart original block buffer pointer
706 * \param  stride picture buffer stride
707 * \param  ppStat statistics buffer
708 * \param  ppCount counter buffer
709 * \param  width block width
710 * \param  height block height
711 * \param  pbBorderAvail availabilities of block border pixels
712 */
713Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail)
714{
715  Int64 *stats, *count;
716  Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
717  Pel *pOrg, *pRec;
718  UInt edgeType;
719  Int x, y;
720
721  //--------- Band offset-----------//
722  stats = ppStats[SAO_BO];
723  count = ppCount[SAO_BO];
724  pOrg   = pOrgStart;
725  pRec   = pRecStart;
726  for (y=0; y< height; y++)
727  {
728    for (x=0; x< width; x++)
729    {
730      classIdx = m_lumaTableBo[pRec[x]];
731      if (classIdx)
732      {
733        stats[classIdx] += (pOrg[x] - pRec[x]);
734        count[classIdx] ++;
735      }
736    }
737    pOrg += stride;
738    pRec += stride;
739  }
740  //---------- Edge offset 0--------------//
741  stats = ppStats[SAO_EO_0];
742  count = ppCount[SAO_EO_0];
743  pOrg   = pOrgStart;
744  pRec   = pRecStart;
745
746  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
747  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
748  for (y=0; y< height; y++)
749  {
750    signLeft = xSign(pRec[startX] - pRec[startX-1]);
751    for (x=startX; x< endX; x++)
752    {
753      signRight =  xSign(pRec[x] - pRec[x+1]);
754      edgeType =  signRight + signLeft + 2;
755      signLeft  = -signRight;
756
757      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
758      count[m_auiEoTable[edgeType]] ++;
759    }
760    pRec  += stride;
761    pOrg += stride;
762  }
763
764  //---------- Edge offset 1--------------//
765  stats = ppStats[SAO_EO_1];
766  count = ppCount[SAO_EO_1];
767  pOrg   = pOrgStart;
768  pRec   = pRecStart;
769
770  startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
771  endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
772  if (!pbBorderAvail[SGU_T])
773  {
774    pRec  += stride;
775    pOrg  += stride;
776  }
777
778  for (x=0; x< width; x++)
779  {
780    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
781  }
782  for (y=startY; y<endY; y++)
783  {
784    for (x=0; x< width; x++)
785    {
786      signDown     =  xSign(pRec[x] - pRec[x+stride]);
787      edgeType    =  signDown + m_iUpBuff1[x] + 2;
788      m_iUpBuff1[x] = -signDown;
789
790      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
791      count[m_auiEoTable[edgeType]] ++;
792    }
793    pOrg += stride;
794    pRec += stride;
795  }
796  //---------- Edge offset 2--------------//
797  stats = ppStats[SAO_EO_2];
798  count = ppCount[SAO_EO_2];
799  pOrg   = pOrgStart;
800  pRec   = pRecStart;
801
802  posShift= stride + 1;
803
804  startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
805  endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
806
807  //prepare 2nd line upper sign
808  pRec += stride;
809  for (x=startX; x< endX+1; x++)
810  {
811    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
812  }
813
814  //1st line
815  pRec -= stride;
816  if(pbBorderAvail[SGU_TL])
817  {
818    x= 0;
819    edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
820    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
821    count[m_auiEoTable[edgeType]] ++;
822  }
823  if(pbBorderAvail[SGU_T])
824  {
825    for(x= 1; x< endX; x++)
826    {
827      edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
828      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
829      count[m_auiEoTable[edgeType]] ++;
830    }
831  }
832  pRec   += stride;
833  pOrg   += stride;
834
835  //middle lines
836  for (y= 1; y< height-1; y++)
837  {
838    for (x=startX; x<endX; x++)
839    {
840      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
841      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
842      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
843      count[m_auiEoTable[edgeType]] ++;
844
845      m_iUpBufft[x+1] = -signDown1;
846    }
847    m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]);
848
849    ipSwap     = m_iUpBuff1;
850    m_iUpBuff1 = m_iUpBufft;
851    m_iUpBufft = ipSwap;
852
853    pRec  += stride;
854    pOrg  += stride;
855  }
856
857  //last line
858  if(pbBorderAvail[SGU_B])
859  {
860    for(x= startX; x< width-1; x++)
861    {
862      edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
863      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
864      count[m_auiEoTable[edgeType]] ++;
865    }
866  }
867  if(pbBorderAvail[SGU_BR])
868  {
869    x= width -1;
870    edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
871    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
872    count[m_auiEoTable[edgeType]] ++;
873  }
874
875  //---------- Edge offset 3--------------//
876
877  stats = ppStats[SAO_EO_3];
878  count = ppCount[SAO_EO_3];
879  pOrg   = pOrgStart;
880  pRec   = pRecStart;
881
882  posShift     = stride - 1;
883  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
884  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
885
886  //prepare 2nd line upper sign
887  pRec += stride;
888  for (x=startX-1; x< endX; x++)
889  {
890    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
891  }
892
893
894  //first line
895  pRec -= stride;
896  if(pbBorderAvail[SGU_T])
897  {
898    for(x= startX; x< width -1; x++)
899    {
900      edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
901      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
902      count[m_auiEoTable[edgeType]] ++;
903    }
904  }
905  if(pbBorderAvail[SGU_TR])
906  {
907    x= width-1;
908    edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
909    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
910    count[m_auiEoTable[edgeType]] ++;
911  }
912  pRec  += stride;
913  pOrg  += stride;
914
915  //middle lines
916  for (y= 1; y< height-1; y++)
917  {
918    for(x= startX; x< endX; x++)
919    {
920      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
921      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
922
923      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
924      count[m_auiEoTable[edgeType]] ++;
925      m_iUpBuff1[x-1] = -signDown1; 
926
927    }
928    m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
929
930    pRec  += stride;
931    pOrg  += stride;
932  }
933
934  //last line
935  if(pbBorderAvail[SGU_BL])
936  {
937    x= 0;
938    edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
939    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
940    count[m_auiEoTable[edgeType]] ++;
941
942  }
943  if(pbBorderAvail[SGU_B])
944  {
945    for(x= 1; x< endX; x++)
946    {
947      edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
948      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
949      count[m_auiEoTable[edgeType]] ++;
950    }
951  }
952}
953
954/** Calculate SAO statistics for current LCU
955 * \param  iAddr,  iPartIdx,  iYCbCr
956 */
957Void TEncSampleAdaptiveOffset::calcSaoStatsCu(Int iAddr, Int iPartIdx, Int iYCbCr)
958{
959  if(!m_bUseNIF)
960  {
961    calcSaoStatsCuOrg( iAddr, iPartIdx, iYCbCr);
962  }
963  else
964  {
965    Int64** ppStats = m_iOffsetOrg[iPartIdx];
966    Int64** ppCount = m_iCount    [iPartIdx];
967
968    //parameters
969    Int  isChroma = (iYCbCr != 0)? 1:0;
970    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
971    Pel* pPicOrg = getPicYuvAddr (m_pcPic->getPicYuvOrg(), iYCbCr);
972    Pel* pPicRec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
973
974    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
975
976    //variables
977    UInt  xPos, yPos, width, height;
978    Bool* pbBorderAvail;
979    UInt  posOffset;
980
981    for(Int i=0; i< vFilterBlocks.size(); i++)
982    {
983      xPos        = vFilterBlocks[i].posX   >> isChroma;
984      yPos        = vFilterBlocks[i].posY   >> isChroma;
985      width       = vFilterBlocks[i].width  >> isChroma;
986      height      = vFilterBlocks[i].height >> isChroma;
987      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
988
989      posOffset = (yPos* stride) + xPos;
990
991      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);
992    }
993  }
994}
995
996/** Calculate SAO statistics for current LCU without non-crossing slice
997 * \param  iAddr,  iPartIdx,  iYCbCr
998 */
999Void TEncSampleAdaptiveOffset::calcSaoStatsCuOrg(Int iAddr, Int iPartIdx, Int iYCbCr)
1000{
1001  Int x,y;
1002  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
1003  TComSPS *pTmpSPS =  m_pcPic->getSlice(0)->getSPS();
1004
1005  Pel* pOrg;
1006  Pel* pRec;
1007  Int iStride;
1008  Int iLcuWidth  = pTmpSPS->getMaxCUHeight();
1009  Int iLcuHeight = pTmpSPS->getMaxCUWidth();
1010  UInt uiLPelX   = pTmpCu->getCUPelX();
1011  UInt uiTPelY   = pTmpCu->getCUPelY();
1012  UInt uiRPelX;
1013  UInt uiBPelY;
1014  Int64* iStats;
1015  Int64* iCount;
1016  Int iClassIdx;
1017  Int iPicWidthTmp;
1018  Int iPicHeightTmp;
1019  Int iStartX;
1020  Int iStartY;
1021  Int iEndX;
1022  Int iEndY;
1023
1024  Int iIsChroma = (iYCbCr!=0)? 1:0;
1025  Int numSkipLine = iIsChroma? 2:4;
1026  if (m_saoLcuBasedOptimization == 0)
1027  {
1028    numSkipLine = 0;
1029  }
1030
1031#if SAO_SKIP_RIGHT
1032  Int numSkipLineRight = iIsChroma? 3:5;
1033  if (m_saoLcuBasedOptimization == 0)
1034  {
1035    numSkipLineRight = 0;
1036  }
1037#endif
1038
1039  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
1040  iPicHeightTmp = m_iPicHeight >> iIsChroma;
1041  iLcuWidth     = iLcuWidth    >> iIsChroma;
1042  iLcuHeight    = iLcuHeight   >> iIsChroma;
1043  uiLPelX       = uiLPelX      >> iIsChroma;
1044  uiTPelY       = uiTPelY      >> iIsChroma;
1045  uiRPelX       = uiLPelX + iLcuWidth  ;
1046  uiBPelY       = uiTPelY + iLcuHeight ;
1047  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
1048  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
1049  iLcuWidth     = uiRPelX - uiLPelX;
1050  iLcuHeight    = uiBPelY - uiTPelY;
1051
1052  iStride    =  (iYCbCr == 0)? m_pcPic->getStride(): m_pcPic->getCStride();
1053
1054//if(iSaoType == BO_0 || iSaoType == BO_1)
1055  {
1056    if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1057    {
1058      numSkipLine = iIsChroma? 1:3;
1059      numSkipLineRight = iIsChroma? 2:4;
1060    }
1061    iStats = m_iOffsetOrg[iPartIdx][SAO_BO];
1062    iCount = m_iCount    [iPartIdx][SAO_BO];
1063
1064    pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1065    pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1066
1067#if SAO_SKIP_RIGHT
1068    iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
1069#endif
1070
1071    iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeight-numSkipLine;
1072    for (y=0; y<iEndY; y++)
1073    {
1074#if SAO_SKIP_RIGHT
1075      for (x=0; x<iEndX; x++)
1076#else
1077      for (x=0; x<iLcuWidth; x++)
1078#endif
1079      {
1080        iClassIdx = m_lumaTableBo[pRec[x]];
1081        if (iClassIdx)
1082        {
1083          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
1084          iCount[iClassIdx] ++;
1085        }
1086      }
1087      pOrg += iStride;
1088      pRec += iStride;
1089    }
1090
1091  }
1092  Int iSignLeft;
1093  Int iSignRight;
1094  Int iSignDown;
1095  Int iSignDown1;
1096  Int iSignDown2;
1097
1098  UInt uiEdgeType;
1099
1100//if (iSaoType == EO_0  || iSaoType == EO_1 || iSaoType == EO_2 || iSaoType == EO_3)
1101  {
1102  //if (iSaoType == EO_0)
1103    {
1104      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1105      {
1106        numSkipLine = iIsChroma? 1:3;
1107        numSkipLineRight = iIsChroma? 3:5;
1108      }
1109      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];
1110      iCount = m_iCount    [iPartIdx][SAO_EO_0];
1111
1112      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1113      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1114
1115      iStartX = (uiLPelX == 0) ? 1 : 0;
1116#if SAO_SKIP_RIGHT
1117      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1118#else
1119      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1120#endif
1121      for (y=0; y<iLcuHeight-numSkipLine; y++)
1122      {
1123        iSignLeft = xSign(pRec[iStartX] - pRec[iStartX-1]);
1124        for (x=iStartX; x< iEndX; x++)
1125        {
1126          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
1127          uiEdgeType =  iSignRight + iSignLeft + 2;
1128          iSignLeft  = -iSignRight;
1129
1130          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1131          iCount[m_auiEoTable[uiEdgeType]] ++;
1132        }
1133        pOrg += iStride;
1134        pRec += iStride;
1135      }
1136    }
1137
1138  //if (iSaoType == EO_1)
1139    {
1140      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1141      {
1142        numSkipLine = iIsChroma? 2:4;
1143        numSkipLineRight = iIsChroma? 2:4;
1144      }
1145      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];
1146      iCount = m_iCount    [iPartIdx][SAO_EO_1];
1147
1148      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1149      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1150
1151      iStartY = (uiTPelY == 0) ? 1 : 0;
1152#if SAO_SKIP_RIGHT
1153      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
1154#endif
1155      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1156      if (uiTPelY == 0)
1157      {
1158        pOrg += iStride;
1159        pRec += iStride;
1160      }
1161
1162      for (x=0; x< iLcuWidth; x++)
1163      {
1164        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
1165      }
1166      for (y=iStartY; y<iEndY; y++)
1167      {
1168#if SAO_SKIP_RIGHT
1169        for (x=0; x<iEndX; x++)
1170#else
1171        for (x=0; x<iLcuWidth; x++)
1172#endif
1173        {
1174          iSignDown     =  xSign(pRec[x] - pRec[x+iStride]); 
1175          uiEdgeType    =  iSignDown + m_iUpBuff1[x] + 2;
1176          m_iUpBuff1[x] = -iSignDown;
1177
1178          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1179          iCount[m_auiEoTable[uiEdgeType]] ++;
1180        }
1181        pOrg += iStride;
1182        pRec += iStride;
1183      }
1184    }
1185  //if (iSaoType == EO_2)
1186    {
1187      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1188      {
1189        numSkipLine = iIsChroma? 2:4;
1190        numSkipLineRight = iIsChroma? 3:5;
1191      }
1192      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];
1193      iCount = m_iCount    [iPartIdx][SAO_EO_2];
1194
1195      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1196      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1197
1198      iStartX = (uiLPelX == 0) ? 1 : 0;
1199#if SAO_SKIP_RIGHT
1200      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1201#else
1202      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1203#endif
1204
1205      iStartY = (uiTPelY == 0) ? 1 : 0;
1206      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1207      if (uiTPelY == 0)
1208      {
1209        pOrg += iStride;
1210        pRec += iStride;
1211      }
1212
1213      for (x=iStartX; x<iEndX; x++)
1214      {
1215        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
1216      }
1217      for (y=iStartY; y<iEndY; y++)
1218      {
1219        iSignDown2 = xSign(pRec[iStride+iStartX] - pRec[iStartX-1]);
1220        for (x=iStartX; x<iEndX; x++)
1221        {
1222          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
1223          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1224          m_iUpBufft[x+1] = -iSignDown1; 
1225          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1226          iCount[m_auiEoTable[uiEdgeType]] ++;
1227        }
1228        m_iUpBufft[iStartX] = iSignDown2;
1229        ipSwap     = m_iUpBuff1;
1230        m_iUpBuff1 = m_iUpBufft;
1231        m_iUpBufft = ipSwap;
1232
1233        pRec += iStride;
1234        pOrg += iStride;
1235      }
1236    } 
1237  //if (iSaoType == EO_3  )
1238    {
1239      if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
1240      {
1241        numSkipLine = iIsChroma? 2:4;
1242        numSkipLineRight = iIsChroma? 3:5;
1243      }
1244      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];
1245      iCount = m_iCount    [iPartIdx][SAO_EO_3];
1246
1247      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
1248      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
1249
1250      iStartX = (uiLPelX == 0) ? 1 : 0;
1251#if SAO_SKIP_RIGHT
1252      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
1253#else
1254      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1255#endif
1256
1257      iStartY = (uiTPelY == 0) ? 1 : 0;
1258      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
1259      if (iStartY == 1)
1260      {
1261        pOrg += iStride;
1262        pRec += iStride;
1263      }
1264
1265      for (x=iStartX-1; x<iEndX; x++)
1266      {
1267        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
1268      }
1269
1270      for (y=iStartY; y<iEndY; y++)
1271      {
1272        for (x=iStartX; x<iEndX; x++)
1273        {
1274          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
1275          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1276          m_iUpBuff1[x-1] = -iSignDown1; 
1277          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1278          iCount[m_auiEoTable[uiEdgeType]] ++;
1279        }
1280        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
1281
1282        pRec += iStride;
1283        pOrg += iStride;
1284      } 
1285    } 
1286  }
1287}
1288
1289
1290Void TEncSampleAdaptiveOffset::calcSaoStatsCu_BeforeDblk( TComPic* pcPic )
1291{
1292  Int addr, yCbCr;
1293  Int x,y;
1294  TComSPS *pTmpSPS =  pcPic->getSlice(0)->getSPS();
1295
1296  Pel* pOrg;
1297  Pel* pRec;
1298  Int stride;
1299  Int lcuWidth  = pTmpSPS->getMaxCUHeight();
1300  Int lcuHeight = pTmpSPS->getMaxCUWidth();
1301  UInt rPelX;
1302  UInt bPelY;
1303  Int64* stats;
1304  Int64* count;
1305  Int classIdx;
1306  Int picWidthTmp = 0;
1307  Int picHeightTmp = 0;
1308  Int startX;
1309  Int startY;
1310  Int endX;
1311  Int endY;
1312  Int firstX, firstY;
1313
1314  Int idxY;
1315  Int idxX;
1316  Int frameHeightInCU = m_iNumCuInHeight;
1317  Int frameWidthInCU  = m_iNumCuInWidth;
1318  Int j, k;
1319
1320  Int isChroma;
1321  Int numSkipLine, numSkipLineRight;
1322
1323  UInt lPelX, tPelY;
1324  TComDataCU *pTmpCu;
1325
1326  for (idxY = 0; idxY< frameHeightInCU; idxY++)
1327  {
1328    for (idxX = 0; idxX< frameWidthInCU; idxX++)
1329    {
1330      lcuWidth  = pTmpSPS->getMaxCUHeight();
1331      lcuHeight = pTmpSPS->getMaxCUWidth();
1332      addr     = idxX  + frameWidthInCU*idxY;
1333      pTmpCu = pcPic->getCU(addr);
1334      lPelX   = pTmpCu->getCUPelX();
1335      tPelY   = pTmpCu->getCUPelY();
1336      for( yCbCr = 0; yCbCr < 3; yCbCr++ )
1337      {
1338        isChroma = (yCbCr!=0)? 1:0;
1339
1340        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
1341        {
1342          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
1343          {
1344            m_count_PreDblk    [addr][yCbCr][j][k] = 0;
1345            m_offsetOrg_PreDblk[addr][yCbCr][j][k] = 0;
1346          } 
1347        }
1348        if( yCbCr == 0 )
1349        {
1350          picWidthTmp  = m_iPicWidth;
1351          picHeightTmp = m_iPicHeight;
1352        }
1353        else if( yCbCr == 1 )
1354        {
1355          picWidthTmp  = m_iPicWidth  >> isChroma;
1356          picHeightTmp = m_iPicHeight >> isChroma;
1357          lcuWidth     = lcuWidth    >> isChroma;
1358          lcuHeight    = lcuHeight   >> isChroma;
1359          lPelX       = lPelX      >> isChroma;
1360          tPelY       = tPelY      >> isChroma;
1361        }
1362        rPelX       = lPelX + lcuWidth  ;
1363        bPelY       = tPelY + lcuHeight ;
1364        rPelX       = rPelX > picWidthTmp  ? picWidthTmp  : rPelX;
1365        bPelY       = bPelY > picHeightTmp ? picHeightTmp : bPelY;
1366        lcuWidth     = rPelX - lPelX;
1367        lcuHeight    = bPelY - tPelY;
1368
1369        stride    =  (yCbCr == 0)? pcPic->getStride(): pcPic->getCStride();
1370
1371        //if(iSaoType == BO)
1372
1373        numSkipLine = isChroma? 1:3;
1374        numSkipLineRight = isChroma? 2:4;
1375
1376        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_BO];
1377        count = m_count_PreDblk[addr][yCbCr][SAO_BO];
1378
1379        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1380        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1381
1382        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
1383        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
1384
1385        for (y=0; y<lcuHeight; y++)
1386        {
1387          for (x=0; x<lcuWidth; x++)
1388          {
1389            if( x < startX && y < startY )
1390              continue;
1391
1392            classIdx = m_lumaTableBo[pRec[x]];
1393            if (classIdx)
1394            {
1395              stats[classIdx] += (pOrg[x] - pRec[x]); 
1396              count[classIdx] ++;
1397            }
1398          }
1399          pOrg += stride;
1400          pRec += stride;
1401        }
1402
1403        Int signLeft;
1404        Int signRight;
1405        Int signDown;
1406        Int signDown1;
1407        Int signDown2;
1408
1409        UInt uiEdgeType;
1410
1411        //if (iSaoType == EO_0)
1412
1413        numSkipLine = isChroma? 1:3;
1414        numSkipLineRight = isChroma? 3:5;
1415
1416        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_0];
1417        count = m_count_PreDblk[addr][yCbCr][SAO_EO_0];
1418
1419        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1420        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1421
1422        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1423        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight-numSkipLine;
1424        firstX   = (lPelX == 0) ? 1 : 0;
1425        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1426
1427        for (y=0; y<lcuHeight; y++)
1428        {
1429          signLeft = xSign(pRec[firstX] - pRec[firstX-1]);
1430          for (x=firstX; x< endX; x++)
1431          {
1432            signRight =  xSign(pRec[x] - pRec[x+1]); 
1433            uiEdgeType =  signRight + signLeft + 2;
1434            signLeft  = -signRight;
1435
1436            if( x < startX && y < startY )
1437              continue;
1438
1439            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1440            count[m_auiEoTable[uiEdgeType]] ++;
1441          }
1442          pOrg += stride;
1443          pRec += stride;
1444        }
1445
1446        //if (iSaoType == EO_1)
1447
1448        numSkipLine = isChroma? 2:4;
1449        numSkipLineRight = isChroma? 2:4;
1450
1451        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_1];
1452        count = m_count_PreDblk[addr][yCbCr][SAO_EO_1];
1453
1454        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1455        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1456
1457        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth-numSkipLineRight;
1458        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1459        firstY = (tPelY == 0) ? 1 : 0;
1460        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1461        if (firstY == 1)
1462        {
1463          pOrg += stride;
1464          pRec += stride;
1465        }
1466
1467        for (x=0; x< lcuWidth; x++)
1468        {
1469          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
1470        }
1471        for (y=firstY; y<endY; y++)
1472        {
1473          for (x=0; x<lcuWidth; x++)
1474          {
1475            signDown     =  xSign(pRec[x] - pRec[x+stride]); 
1476            uiEdgeType    =  signDown + m_iUpBuff1[x] + 2;
1477            m_iUpBuff1[x] = -signDown;
1478
1479            if( x < startX && y < startY )
1480              continue;
1481
1482            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1483            count[m_auiEoTable[uiEdgeType]] ++;
1484          }
1485          pOrg += stride;
1486          pRec += stride;
1487        }
1488
1489        //if (iSaoType == EO_2)
1490
1491        numSkipLine = isChroma? 2:4;
1492        numSkipLineRight = isChroma? 3:5;
1493
1494        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_2];
1495        count = m_count_PreDblk[addr][yCbCr][SAO_EO_2];
1496
1497        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1498        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1499
1500        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1501        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1502        firstX   = (lPelX == 0) ? 1 : 0;
1503        firstY = (tPelY == 0) ? 1 : 0;
1504        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1505        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1506        if (firstY == 1)
1507        {
1508          pOrg += stride;
1509          pRec += stride;
1510        }
1511
1512        for (x=firstX; x<endX; x++)
1513        {
1514          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride-1]);
1515        }
1516        for (y=firstY; y<endY; y++)
1517        {
1518          signDown2 = xSign(pRec[stride+startX] - pRec[startX-1]);
1519          for (x=firstX; x<endX; x++)
1520          {
1521            signDown1      =  xSign(pRec[x] - pRec[x+stride+1]) ;
1522            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1523            m_iUpBufft[x+1] = -signDown1; 
1524
1525            if( x < startX && y < startY )
1526              continue;
1527
1528            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1529            count[m_auiEoTable[uiEdgeType]] ++;
1530          }
1531          m_iUpBufft[firstX] = signDown2;
1532          ipSwap     = m_iUpBuff1;
1533          m_iUpBuff1 = m_iUpBufft;
1534          m_iUpBufft = ipSwap;
1535
1536          pRec += stride;
1537          pOrg += stride;
1538        }
1539
1540        //if (iSaoType == EO_3)
1541
1542        numSkipLine = isChroma? 2:4;
1543        numSkipLineRight = isChroma? 3:5;
1544
1545        stats = m_offsetOrg_PreDblk[addr][yCbCr][SAO_EO_3];
1546        count = m_count_PreDblk[addr][yCbCr][SAO_EO_3];
1547
1548        pOrg = getPicYuvAddr(pcPic->getPicYuvOrg(), yCbCr, addr);
1549        pRec = getPicYuvAddr(pcPic->getPicYuvRec(), yCbCr, addr);
1550
1551        startX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth-numSkipLineRight;
1552        startY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight-numSkipLine;
1553        firstX   = (lPelX == 0) ? 1 : 0;
1554        firstY = (tPelY == 0) ? 1 : 0;
1555        endX   = (rPelX == picWidthTmp) ? lcuWidth-1 : lcuWidth;
1556        endY   = (bPelY == picHeightTmp) ? lcuHeight-1 : lcuHeight;
1557        if (firstY == 1)
1558        {
1559          pOrg += stride;
1560          pRec += stride;
1561        }
1562
1563        for (x=firstX-1; x<endX; x++)
1564        {
1565          m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride+1]);
1566        }
1567
1568        for (y=firstY; y<endY; y++)
1569        {
1570          for (x=firstX; x<endX; x++)
1571          {
1572            signDown1      =  xSign(pRec[x] - pRec[x+stride-1]) ;
1573            uiEdgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1574            m_iUpBuff1[x-1] = -signDown1; 
1575
1576            if( x < startX && y < startY )
1577              continue;
1578
1579            stats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
1580            count[m_auiEoTable[uiEdgeType]] ++;
1581          }
1582          m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
1583
1584          pRec += stride;
1585          pOrg += stride;
1586        }
1587      }
1588    }
1589  }
1590}
1591
1592
1593/** get SAO statistics
1594 * \param  *psQTPart,  iYCbCr
1595 */
1596Void TEncSampleAdaptiveOffset::getSaoStats(SAOQTPart *psQTPart, Int iYCbCr)
1597{
1598  Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;
1599  Int i;
1600  Int iNumTotalType = MAX_NUM_SAO_TYPE;
1601  Int LcuIdxX;
1602  Int LcuIdxY;
1603  Int iAddr;
1604  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
1605  Int iDownPartIdx;
1606  Int iPartStart;
1607  Int iPartEnd;
1608  SAOQTPart*  pOnePart; 
1609
1610  if (m_uiMaxSplitLevel == 0)
1611  {
1612    iPartIdx = 0;
1613    pOnePart = &(psQTPart[iPartIdx]);
1614    for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
1615    {
1616      for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
1617      {
1618        iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
1619        calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
1620      }
1621    }
1622  }
1623  else
1624  {
1625    for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel-1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)
1626    {
1627      pOnePart = &(psQTPart[iPartIdx]);
1628      for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
1629      {
1630        for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
1631        {
1632          iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
1633          calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
1634        }
1635      }
1636    }
1637    for (iLevelIdx = m_uiMaxSplitLevel-1; iLevelIdx>=0; iLevelIdx-- )
1638    {
1639      iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx-1] : 0;
1640      iPartEnd   = m_aiNumCulPartsLevel[iLevelIdx];
1641
1642      for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)
1643      {
1644        pOnePart = &(psQTPart[iPartIdx]);
1645        for (i=0; i< NUM_DOWN_PART; i++)
1646        {
1647          iDownPartIdx = pOnePart->DownPartsIdx[i];
1648          for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)
1649          {
1650            for (iClassIdx=0; iClassIdx< (iTypeIdx < SAO_BO ? m_iNumClass[iTypeIdx] : SAO_MAX_BO_CLASSES) +1; iClassIdx++)
1651            {
1652              m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];
1653              m_iCount [iPartIdx][iTypeIdx][iClassIdx]    += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];
1654            }
1655          }
1656        }
1657      }
1658    }
1659  }
1660}
1661
1662/** reset offset statistics
1663 * \param
1664 */
1665Void TEncSampleAdaptiveOffset::resetStats()
1666{
1667  for (Int i=0;i<m_iNumTotalParts;i++)
1668  {
1669    m_dCostPartBest[i] = MAX_DOUBLE;
1670    m_iTypePartBest[i] = -1;
1671    m_iDistOrg[i] = 0;
1672    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
1673    {
1674      m_iDist[i][j] = 0;
1675      m_iRate[i][j] = 0;
1676      m_dCost[i][j] = 0;
1677      for (Int k=0;k<MAX_NUM_SAO_CLASS;k++)
1678      {
1679        m_iCount [i][j][k] = 0;
1680        m_iOffset[i][j][k] = 0;
1681        m_iOffsetOrg[i][j][k] = 0;
1682      } 
1683    }
1684  }
1685}
1686
1687#if SAO_CHROMA_LAMBDA
1688/** Sample adaptive offset process
1689 * \param pcSaoParam
1690 * \param dLambdaLuma
1691 * \param dLambdaChroma
1692 */
1693#if SAO_ENCODING_CHOICE
1694Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma, Int depth)
1695#else
1696Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
1697#endif
1698#else
1699/** Sample adaptive offset process
1700 * \param dLambda
1701 */
1702Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)
1703#endif
1704{
1705    m_eSliceType          =  m_pcPic->getSlice(0)->getSliceType();
1706    m_iPicNalReferenceIdc = (m_pcPic->getSlice(0)->isReferenced() ? 1 :0);
1707
1708#if SAO_CHROMA_LAMBDA
1709    m_dLambdaLuma    = dLambdaLuma;
1710    m_dLambdaChroma  = dLambdaChroma;
1711#else
1712    m_dLambdaLuma    = dLambda;
1713    m_dLambdaChroma  = dLambda;
1714#endif
1715
1716    if(m_bUseNIF)
1717    {
1718        m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
1719    }
1720
1721#if FULL_NBIT
1722    m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth-8) - min((Int)(g_uiBitDepth + (g_uiBitDepth-8)), 10);
1723#else
1724    m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement - min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);
1725#endif
1726
1727#if FULL_NBIT
1728    m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + (g_uiBitDepth-8)-5),5) );
1729#else
1730    m_iOffsetTh = 1 << ( min((Int)(g_uiBitDepth + g_uiBitIncrement-5),5) );
1731#endif
1732
1733    resetSAOParam(pcSaoParam);
1734    if( !m_saoLcuBasedOptimization || !m_saoLcuBoundary )
1735    {
1736        resetStats();
1737    }
1738    Double dCostFinal = 0;
1739    if ( m_saoLcuBasedOptimization)
1740    {
1741#if SAO_ENCODING_CHOICE
1742        rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth);
1743#else
1744        rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);
1745#endif
1746    }
1747    else
1748    {
1749        pcSaoParam->bSaoFlag[0] = 1;
1750        pcSaoParam->bSaoFlag[1] = 0;
1751        dCostFinal = 0;
1752        Double lambdaRdo =  dLambdaLuma;
1753        resetStats();
1754        getSaoStats(pcSaoParam->psSaoPart[0], 0);
1755        runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0);
1756        pcSaoParam->bSaoFlag[0] = dCostFinal < 0 ? 1:0;
1757        if(pcSaoParam->bSaoFlag[0])
1758        {
1759            convertQT2SaoUnit(pcSaoParam, 0, 0);
1760            assignSaoUnitSyntax(pcSaoParam->saoLcuParam[0],  pcSaoParam->psSaoPart[0], pcSaoParam->oneUnitFlag[0], 0);
1761        }
1762    }
1763
1764    if (pcSaoParam->bSaoFlag[0])
1765    {
1766        processSaoUnitAll( pcSaoParam->saoLcuParam[0], pcSaoParam->oneUnitFlag[0], 0);
1767    }
1768    if (pcSaoParam->bSaoFlag[1])
1769    {
1770        processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);
1771        processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);
1772    }
1773}
1774/** Check merge SAO unit
1775* \param saoUnitCurr current SAO unit
1776* \param saoUnitCheck SAO unit tobe check
1777* \param dir direction
1778*/
1779Void TEncSampleAdaptiveOffset::checkMerge(SaoLcuParam * saoUnitCurr, SaoLcuParam * saoUnitCheck, Int dir)
1780{
1781    Int i ;
1782    Int countDiff = 0;
1783    if (saoUnitCurr->partIdx != saoUnitCheck->partIdx)
1784    {
1785        if (saoUnitCurr->typeIdx !=-1)
1786        {
1787            if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
1788            {
1789                for (i=0;i<saoUnitCurr->length;i++)
1790                {
1791                    countDiff += (saoUnitCurr->offset[i] != saoUnitCheck->offset[i]);
1792                }
1793                countDiff += (saoUnitCurr->subTypeIdx != saoUnitCheck->subTypeIdx);
1794                if (countDiff ==0)
1795                {
1796                    saoUnitCurr->partIdx = saoUnitCheck->partIdx;
1797                    if (dir == 1)
1798                    {
1799                        saoUnitCurr->mergeUpFlag = 1;
1800                        saoUnitCurr->mergeLeftFlag = 0;
1801                    }
1802                    else
1803                    {
1804                        saoUnitCurr->mergeUpFlag = 0;
1805                        saoUnitCurr->mergeLeftFlag = 1;
1806                    }
1807                }
1808            }
1809        }
1810        else
1811        {
1812            if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
1813            {
1814                saoUnitCurr->partIdx = saoUnitCheck->partIdx;
1815                if (dir == 1)
1816                {
1817                    saoUnitCurr->mergeUpFlag = 1;
1818                    saoUnitCurr->mergeLeftFlag = 0;
1819                }
1820                else
1821                {
1822                    saoUnitCurr->mergeUpFlag = 0;
1823                    saoUnitCurr->mergeLeftFlag = 1;
1824                }
1825            }
1826        }
1827    }
1828}
1829/** Assign SAO unit syntax from picture-based algorithm
1830* \param saoLcuParam SAO LCU parameters
1831* \param saoPart SAO part
1832* \param oneUnitFlag SAO one unit flag
1833* \param iYCbCr color component Index
1834*/
1835Void TEncSampleAdaptiveOffset::assignSaoUnitSyntax(SaoLcuParam* saoLcuParam,  SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr)
1836{
1837    if (saoPart->bSplit == 0)
1838    {
1839        oneUnitFlag = 1;
1840    }
1841    else
1842    {
1843        Int i,j, addr, addrUp, addrLeft,  idx, idxUp, idxLeft,  idxCount;
1844   
1845        oneUnitFlag = 0;
1846       
1847        idxCount = -1;
1848        saoLcuParam[0].mergeUpFlag = 0;
1849        saoLcuParam[0].mergeLeftFlag = 0;
1850       
1851        for (j=0;j<m_iNumCuInHeight;j++)
1852        {
1853            for (i=0;i<m_iNumCuInWidth;i++)
1854            {
1855                addr     = i + j*m_iNumCuInWidth;
1856                addrLeft = (addr%m_iNumCuInWidth == 0) ? -1 : addr - 1;
1857                addrUp   = (addr<m_iNumCuInWidth)      ? -1 : addr - m_iNumCuInWidth;
1858                idx      = saoLcuParam[addr].partIdxTmp;
1859                idxLeft  = (addrLeft == -1) ? -1 : saoLcuParam[addrLeft].partIdxTmp;
1860                idxUp    = (addrUp == -1)   ? -1 : saoLcuParam[addrUp].partIdxTmp;
1861
1862                if(idx!=idxLeft && idx!=idxUp)
1863                {
1864                    saoLcuParam[addr].mergeUpFlag   = 0; idxCount++;
1865                    saoLcuParam[addr].mergeLeftFlag = 0;
1866                    saoLcuParam[addr].partIdx = idxCount;
1867                }
1868                else if (idx==idxLeft)
1869                {       
1870                    saoLcuParam[addr].mergeUpFlag   = 1;
1871                    saoLcuParam[addr].mergeLeftFlag = 1;
1872                    saoLcuParam[addr].partIdx = saoLcuParam[addrLeft].partIdx;
1873                }
1874                else if (idx==idxUp)
1875                {
1876                    saoLcuParam[addr].mergeUpFlag   = 1;
1877                    saoLcuParam[addr].mergeLeftFlag = 0;
1878                    saoLcuParam[addr].partIdx = saoLcuParam[addrUp].partIdx;
1879                }
1880                if (addrUp != -1)
1881                {
1882                    checkMerge(&saoLcuParam[addr], &saoLcuParam[addrUp], 1);
1883                }
1884                if (addrLeft != -1)
1885                {
1886                    checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);
1887                }
1888            }
1889        }
1890    }
1891}
1892/** rate distortion optimization of all SAO units
1893* \param saoParam SAO parameters
1894* \param lambda
1895* \param lambdaChroma
1896*/
1897#if SAO_ENCODING_CHOICE
1898Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
1899#else
1900Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
1901#endif
1902{
1903    Int idxY;
1904    Int idxX;
1905    Int frameHeightInCU = saoParam->numCuInHeight;
1906    Int frameWidthInCU  = saoParam->numCuInWidth;
1907    Int j, k;
1908    Int addr = 0;
1909    Int addrUp = -1;
1910    Int addrLeft = -1;
1911    Int compIdx = 0;
1912    SaoLcuParam mergeSaoParam[3][2];
1913    Double compDistortion[3];
1914
1915    saoParam->bSaoFlag[0] = true;
1916    saoParam->bSaoFlag[1] = true;
1917    saoParam->oneUnitFlag[0] = false;
1918    saoParam->oneUnitFlag[1] = false;
1919    saoParam->oneUnitFlag[2] = false;
1920
1921#if SAO_ENCODING_CHOICE
1922#if SAO_ENCODING_CHOICE_CHROMA
1923    Int numNoSao[2];
1924    numNoSao[0] = 0;// Luma
1925    numNoSao[1] = 0;// Chroma
1926    if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
1927    {
1928        saoParam->bSaoFlag[0] = false;
1929    }
1930
1931    if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
1932    {
1933        saoParam->bSaoFlag[1] = false;
1934    }
1935#else
1936    Int numNoSao = 0;
1937
1938    if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
1939    {
1940        saoParam->bSaoFlag[0] = false;
1941        saoParam->bSaoFlag[1] = false;
1942    }
1943#endif
1944#endif
1945
1946    for (idxY = 0; idxY< frameHeightInCU; idxY++)
1947    {
1948        for (idxX = 0; idxX< frameWidthInCU; idxX++)
1949        {
1950            addr     = idxX  + frameWidthInCU*idxY;
1951            addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
1952            addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
1953            Int allowMergeLeft = 1;
1954            Int allowMergeUp   = 1;
1955            UInt rate;
1956            Double bestCost, mergeCost;
1957
1958            if (idxX!=0)
1959            { 
1960                // check tile id and slice id
1961                if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-1) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-1)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1962                {
1963                    allowMergeLeft = 0;
1964                }
1965            }
1966            else
1967            {
1968                allowMergeLeft = 0;
1969            }
1970            if (idxY!=0)
1971            {
1972                if ( (m_pcPic->getPicSym()->getTileIdxMap(addr-m_iNumCuInWidth) != m_pcPic->getPicSym()->getTileIdxMap(addr)) || (m_pcPic->getCU(addr-m_iNumCuInWidth)->getSlice()->getSliceIdx() != m_pcPic->getCU(addr)->getSlice()->getSliceIdx()))
1973                {
1974                    allowMergeUp = 0;
1975                }
1976            }
1977            else
1978            {
1979                allowMergeUp = 0;
1980            }
1981
1982            compDistortion[0] = 0; 
1983            compDistortion[1] = 0; 
1984            compDistortion[2] = 0;
1985            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
1986
1987            if (allowMergeLeft)
1988            {
1989                m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
1990            }
1991            if (allowMergeUp)
1992            {
1993                m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
1994            }
1995
1996            m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
1997
1998            // reset stats Y, Cb, Cr
1999            for ( compIdx=0;compIdx<3;compIdx++)
2000            {
2001                for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
2002                {
2003                    for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
2004                    {
2005                        m_iOffset   [compIdx][j][k] = 0;
2006                        if( m_saoLcuBasedOptimization && m_saoLcuBoundary )
2007                        {
2008                            m_iCount    [compIdx][j][k] = m_count_PreDblk    [addr][compIdx][j][k];
2009                            m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
2010                        }
2011                        else
2012                        {
2013                            m_iCount    [compIdx][j][k] = 0;
2014                            m_iOffsetOrg[compIdx][j][k] = 0;
2015                        }
2016                    } 
2017                }
2018                saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
2019                saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
2020                saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
2021                saoParam->saoLcuParam[compIdx][addr].subTypeIdx    = 0;
2022#if SAO_ENCODING_CHOICE
2023                if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
2024#endif
2025                {
2026                    calcSaoStatsCu(addr, compIdx,  compIdx);
2027                }
2028            }
2029            saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0,  lambda, &mergeSaoParam[0][0], &compDistortion[0]);
2030            sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
2031            if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] )
2032            {
2033                // Cost of new SAO_params
2034                m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2035                m_pcRDGoOnSbacCoder->resetBits();
2036                if (allowMergeLeft)
2037                {
2038                    m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0); 
2039                }
2040                if (allowMergeUp)
2041                {
2042                    m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
2043                }
2044                for ( compIdx=0;compIdx<3;compIdx++)
2045                {
2046                    if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1]))
2047                    {
2048                        m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx);
2049                    }
2050                }
2051   
2052                rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2053                bestCost = compDistortion[0] + (Double)rate;
2054                m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2055   
2056                // Cost of Merge
2057                for(Int mergeUp=0; mergeUp<2; ++mergeUp)
2058                {
2059                    if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) )
2060                    {
2061                        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2062                        m_pcRDGoOnSbacCoder->resetBits();
2063                        if (allowMergeLeft)
2064                        {
2065                            m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp); 
2066                        }
2067                        if ( allowMergeUp && (mergeUp==1) )
2068                        {
2069                            m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1); 
2070                        }
2071   
2072                        rate = m_pcEntropyCoder->getNumberOfWrittenBits();
2073                        mergeCost = compDistortion[mergeUp+1] + (Double)rate;
2074                        if (mergeCost < bestCost)
2075                        {
2076                            bestCost = mergeCost;
2077                            m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);             
2078                            for ( compIdx=0;compIdx<3;compIdx++)
2079                            {
2080                                mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp;
2081                                mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;
2082                                if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1]))
2083                                {
2084                                    copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );             
2085                                }
2086                            }
2087                        }
2088                    }
2089                }
2090#if SAO_ENCODING_CHOICE
2091#if SAO_ENCODING_CHOICE_CHROMA
2092                if( saoParam->saoLcuParam[0][addr].typeIdx == -1)
2093                {
2094                    numNoSao[0]++;
2095                }
2096                if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
2097                {
2098                    numNoSao[1]+=2;
2099                }
2100#else
2101                for ( compIdx=0;compIdx<3;compIdx++)
2102                {
2103                    if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
2104                    {
2105                        numNoSao++;
2106                    }
2107                }
2108#endif
2109#endif
2110                m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2111                m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
2112            }
2113        }
2114    }
2115#if SAO_ENCODING_CHOICE
2116#if SAO_ENCODING_CHOICE_CHROMA
2117#if SAO_ENCODING_CHOICE_CHROMA_BF
2118    if( !saoParam->bSaoFlag[0]) 
2119    {
2120        m_depthSaoRate[0][depth] = 1.0;
2121    }
2122    else
2123    {
2124        m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
2125    }
2126    if( !saoParam->bSaoFlag[1]) 
2127    {
2128        m_depthSaoRate[1][depth] = 1.0;
2129    }
2130    else 
2131    {
2132        m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
2133    }
2134#else
2135    m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
2136    m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
2137#endif
2138#else
2139    if( depth == 0)
2140    {
2141        // update SAO Rate
2142        m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
2143    }
2144#endif
2145#endif
2146}
2147/** rate distortion optimization of SAO unit
2148* \param saoParam SAO parameters
2149* \param addr address
2150* \param addrUp above address
2151* \param addrLeft left address
2152* \param yCbCr color component index
2153* \param lambda
2154*/
2155inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)
2156{
2157    Int64 estDist = 0;
2158    Int classIdx;
2159    for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
2160    {
2161        if( typeIdx == SAO_BO)
2162        {
2163            currentDistortionTableBo[classIdx-1] = 0;
2164            currentRdCostTableBo[classIdx-1] = lambda;
2165        }
2166        if(m_iCount [compIdx][typeIdx][classIdx])
2167        {
2168#if FULL_NBIT
2169            m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitDepth-8)   / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));
2170#else
2171            m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<g_uiBitIncrement) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<m_uiSaoBitIncrease));
2172#endif
2173            m_iOffset[compIdx][typeIdx][classIdx] = Clip3(-m_iOffsetTh+1, m_iOffsetTh-1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);
2174            if (typeIdx < 4)
2175            {
2176                if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )
2177                {
2178                    m_iOffset[compIdx][typeIdx][classIdx] = 0;
2179                }
2180                if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)
2181                {
2182                    m_iOffset[compIdx][typeIdx][classIdx] = 0;
2183                }
2184            }
2185            m_iOffset[compIdx][typeIdx][classIdx] = estIterOffset( typeIdx, classIdx, lambda, m_iOffset[compIdx][typeIdx][classIdx], m_iCount [compIdx][typeIdx][classIdx], m_iOffsetOrg[compIdx][typeIdx][classIdx], shift, m_uiSaoBitIncrease, currentDistortionTableBo, currentRdCostTableBo );
2186        }
2187        else
2188        {
2189            m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;
2190            m_iOffset[compIdx][typeIdx][classIdx] = 0;
2191        }
2192        if( typeIdx != SAO_BO )
2193        {
2194            estDist   += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << m_uiSaoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);
2195        }
2196    }
2197    return estDist;
2198}
2199
2200inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
2201{
2202    return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
2203}
2204inline Int64 TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, double lambda, Int64 offsetInput, Int64 count, Int64 offsetOrg, Int shift, Int bitIncrease, Int *currentDistortionTableBo, Double *currentRdCostTableBo )
2205{
2206    //Clean up, best_q_offset.
2207    Int64 iterOffset, tempOffset;
2208    Int64 tempDist, tempRate;
2209    Double tempCost, tempMinCost;
2210    Int64 offsetOutput = 0;
2211    iterOffset = offsetInput;
2212    // 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.
2213    tempMinCost = lambda; 
2214    while (iterOffset != 0)
2215    {
2216        // Calculate the bits required for signalling the offset
2217        tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
2218        if (abs((Int)iterOffset)==m_iOffsetTh-1) 
2219        { 
2220            tempRate --;
2221        }
2222        // Do the dequntization before distorion calculation
2223        tempOffset  = iterOffset << bitIncrease;
2224        tempDist    = estSaoDist( count, tempOffset, offsetOrg, shift);
2225        tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
2226        if(tempCost < tempMinCost)
2227        {
2228            tempMinCost = tempCost;
2229            offsetOutput = iterOffset;
2230            if(typeIdx == SAO_BO)
2231            {
2232                currentDistortionTableBo[classIdx-1] = (Int) tempDist;
2233                currentRdCostTableBo[classIdx-1] = tempCost;
2234            }
2235        }
2236        iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
2237    }
2238    return offsetOutput;
2239}
2240
2241Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
2242{
2243    Int typeIdx;
2244    Int64 estDist;
2245    Int classIdx;
2246
2247    Int shift = g_uiBitIncrement << 1;
2248
2249    Int64 bestDist;
2250
2251    SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
2252    SaoLcuParam*  saoLcuParamNeighbor = NULL; 
2253
2254    resetSaoUnit(saoLcuParam);
2255    resetSaoUnit(&compSaoParam[0]);
2256    resetSaoUnit(&compSaoParam[1]);
2257
2258    Double dCostPartBest = MAX_DOUBLE;
2259
2260    Double  bestRDCostTableBo = MAX_DOUBLE;
2261    Int     bestClassTableBo    = 0;
2262    Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2263    Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2264
2265    SaoLcuParam   saoLcuParamRdo;   
2266    Double   estRate = 0;
2267
2268    resetSaoUnit(&saoLcuParamRdo);
2269
2270    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2271    m_pcRDGoOnSbacCoder->resetBits();
2272    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2273    dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2274
2275    copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2276
2277    bestDist = 0;
2278
2279    for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2280    {
2281        estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2282        if( typeIdx == SAO_BO )
2283        {
2284            // Estimate Best Position
2285            Double currentRDCost = 0.0;
2286
2287            for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2288            {
2289                currentRDCost = 0.0;
2290                for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2291                {
2292                    currentRDCost += currentRdCostTableBo[uj];
2293                }
2294
2295                if( currentRDCost < bestRDCostTableBo)
2296                {
2297                    bestRDCostTableBo = currentRDCost;
2298                    bestClassTableBo  = i;
2299                }
2300            }
2301
2302            // Re code all Offsets
2303            // Code Center
2304            estDist = 0;
2305            for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
2306            {
2307                estDist += currentDistortionTableBo[classIdx];
2308            }
2309        }
2310        resetSaoUnit(&saoLcuParamRdo);
2311        saoLcuParamRdo.length = m_iNumClass[typeIdx];
2312        saoLcuParamRdo.typeIdx = typeIdx;
2313        saoLcuParamRdo.mergeLeftFlag = 0;
2314        saoLcuParamRdo.mergeUpFlag   = 0;
2315        saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
2316        for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
2317        {
2318            saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
2319        }
2320        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2321        m_pcRDGoOnSbacCoder->resetBits();
2322        m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
2323
2324        estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2325        m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
2326
2327        if(m_dCost[yCbCr][typeIdx] < dCostPartBest)
2328        {
2329            dCostPartBest = m_dCost[yCbCr][typeIdx];
2330            copySaoUnit(saoLcuParam, &saoLcuParamRdo );
2331            bestDist = estDist;       
2332        }
2333    }
2334
2335    compDistortion[0] += ((Double)bestDist/lambda);
2336    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2337    m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
2338    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2339
2340    // merge left or merge up
2341    for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2342    {
2343        saoLcuParamNeighbor = NULL;
2344        if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2345        {
2346            saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
2347        }
2348        else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2349        {
2350            saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
2351        }
2352        if (saoLcuParamNeighbor!=NULL)
2353        {
2354            estDist = 0;
2355            typeIdx = saoLcuParamNeighbor->typeIdx;
2356            if (typeIdx>=0) 
2357            {
2358                Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
2359                Int   merge_iOffset;
2360                for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2361                {
2362                    merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
2363                    estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
2364                }
2365            }
2366            else
2367            {
2368                estDist = 0;
2369            }
2370
2371            copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
2372            compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
2373            compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
2374
2375            compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
2376        } 
2377    }
2378}
2379
2380Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)
2381{
2382    Int typeIdx;
2383
2384    Int64 estDist[2];
2385    Int classIdx;
2386    Int shift = g_uiBitIncrement << 1;
2387    Int64 bestDist = 0;
2388
2389    SaoLcuParam*  saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])};
2390    SaoLcuParam*  saoLcuParamNeighbor[2] = {NULL, NULL}; 
2391    SaoLcuParam*  saoMergeParam[2][2];
2392    saoMergeParam[0][0] = &crSaoParam[0];
2393    saoMergeParam[0][1] = &crSaoParam[1]; 
2394    saoMergeParam[1][0] = &cbSaoParam[0];
2395    saoMergeParam[1][1] = &cbSaoParam[1];
2396
2397    resetSaoUnit(saoLcuParam[0]);
2398    resetSaoUnit(saoLcuParam[1]);
2399    resetSaoUnit(saoMergeParam[0][0]);
2400    resetSaoUnit(saoMergeParam[0][1]);
2401    resetSaoUnit(saoMergeParam[1][0]);
2402    resetSaoUnit(saoMergeParam[1][1]);
2403
2404    Double costPartBest = MAX_DOUBLE;
2405
2406    Double  bestRDCostTableBo;
2407    Int     bestClassTableBo[2]    = {0, 0};
2408    Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2409    Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2410
2411    SaoLcuParam   saoLcuParamRdo[2];   
2412    Double   estRate = 0;
2413
2414    resetSaoUnit(&saoLcuParamRdo[0]);
2415    resetSaoUnit(&saoLcuParamRdo[1]);
2416
2417    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2418    m_pcRDGoOnSbacCoder->resetBits();
2419    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1);
2420    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2);
2421
2422    costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
2423    copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2424    copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2425
2426    for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
2427    {
2428        if( typeIdx == SAO_BO )
2429        {
2430            // Estimate Best Position
2431            for(Int compIdx = 0; compIdx < 2; compIdx++)
2432            {
2433                Double currentRDCost = 0.0;
2434                bestRDCostTableBo = MAX_DOUBLE;
2435                estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2436
2437                for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2438                {
2439                    currentRDCost = 0.0;
2440                    for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2441                    {
2442                        currentRDCost += currentRdCostTableBo[uj];
2443                    }
2444
2445                    if( currentRDCost < bestRDCostTableBo)
2446                    {
2447                        bestRDCostTableBo = currentRDCost;
2448                        bestClassTableBo[compIdx]  = i;
2449                    }
2450                }
2451
2452                // Re code all Offsets
2453                // Code Center
2454                estDist[compIdx] = 0;
2455                for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)
2456                {
2457                    estDist[compIdx] += currentDistortionTableBo[classIdx];
2458                }
2459            }
2460        }
2461        else
2462        {
2463            estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2464            estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
2465        }
2466
2467        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2468        m_pcRDGoOnSbacCoder->resetBits();
2469
2470        for(Int compIdx = 0; compIdx < 2; compIdx++)
2471        {
2472            resetSaoUnit(&saoLcuParamRdo[compIdx]);
2473            saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];
2474            saoLcuParamRdo[compIdx].typeIdx = typeIdx;
2475            saoLcuParamRdo[compIdx].mergeLeftFlag = 0;
2476            saoLcuParamRdo[compIdx].mergeUpFlag   = 0;
2477            saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
2478            for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)
2479            {
2480                saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];
2481            }
2482            m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);
2483        }
2484        estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
2485        m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1])  + lambda * (Double) estRate);
2486
2487        if(m_dCost[1][typeIdx] < costPartBest)
2488        {
2489            costPartBest = m_dCost[1][typeIdx];
2490            copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
2491            copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
2492            bestDist = (estDist[0]+estDist[1]);       
2493        }
2494    }
2495
2496    distortion[0] += ((Double)bestDist/lambda);
2497    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
2498    m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1);
2499    m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2);
2500    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
2501
2502    // merge left or merge up
2503
2504    for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
2505    {
2506        for(Int compIdx = 0; compIdx < 2; compIdx++)
2507        {
2508            saoLcuParamNeighbor[compIdx] = NULL;
2509            if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
2510            {
2511                saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrLeft]);
2512            }
2513            else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
2514            {
2515                saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrUp]);
2516            }
2517            if (saoLcuParamNeighbor[compIdx]!=NULL)
2518            {
2519                estDist[compIdx] = 0;
2520                typeIdx = saoLcuParamNeighbor[compIdx]->typeIdx;
2521                if (typeIdx>=0) 
2522                {
2523                    Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->subTypeIdx:0;
2524                    Int   merge_iOffset;
2525                    for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
2526                    {
2527                        merge_iOffset = saoLcuParamNeighbor[compIdx]->offset[classIdx];
2528                        estDist[compIdx]   += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1],  shift);
2529                    }
2530                }
2531                else
2532                {
2533                    estDist[compIdx] = 0;
2534                }
2535
2536                copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );
2537                saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag   = idxNeighbor;
2538                saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor;
2539                distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);
2540            }
2541        } 
2542    } 
2543}
2544#else
2545TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
2546{
2547  m_pcEntropyCoder = NULL;
2548  m_pppcRDSbacCoder = NULL;
2549  m_pcRDGoOnSbacCoder = NULL;
2550  m_pppcBinCoderCABAC = NULL;           
2551  m_iCount = NULL;     
2552  m_iOffset = NULL;     
2553  m_iOffsetOrg = NULL; 
2554  m_iRate = NULL;       
2555  m_iDist = NULL;       
2556  m_dCost = NULL;       
2557  m_dCostPartBest = NULL; 
2558  m_iDistOrg = NULL;     
2559  m_iTypePartBest = NULL; 
2560}
2561TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
2562{
2563
2564}
2565// ====================================================================================================================
2566// Constants
2567// ====================================================================================================================
2568
2569
2570// ====================================================================================================================
2571// Tables
2572// ====================================================================================================================
2573
2574inline Double xRoundIbdi2(Double x)
2575{
2576#if FULL_NBIT
2577  Int bitDepthMinus8 = g_uiBitDepth - 8;
2578  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)) : ((Int)(((Int)(x)-(1<<(bitDepthMinus8-1)))/(1<<bitDepthMinus8)));
2579#else
2580  return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)-(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)));
2581#endif
2582}
2583
2584/** rounding with IBDI
2585 * \param  x
2586 */
2587inline Double xRoundIbdi(Double x)
2588{
2589#if FULL_NBIT
2590  return (g_uiBitDepth > 8 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
2591#else
2592  return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
2593#endif
2594}
2595
2596
2597
2598/** process SAO for one partition
2599 * \param  *psQTPart, iPartIdx, dLambda
2600 */
2601Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda)
2602{
2603  Int iTypeIdx;
2604  Int iNumTotalType = MAX_NUM_SAO_TYPE;
2605  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
2606
2607  Int64 iEstDist;
2608  Int64 iOffsetOrg;
2609  Int64 iOffset;
2610  Int64 iCount;
2611  Int iClassIdx;
2612  Int uiShift = g_uiBitIncrement << 1;
2613  UInt uiDepth = pOnePart->PartLevel;
2614
2615  m_iDistOrg [iPartIdx] =  0;
2616
2617  Double  bestRDCostTableBo = MAX_DOUBLE;
2618  Int     bestClassTableBo    = 0;
2619  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
2620  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
2621
2622#if HHI_INTERVIEW_SKIP
2623  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
2624  Int LcuIdxX = psQTPart->StartCUX;
2625  Int LcuIdxY = psQTPart->StartCUY;
2626  Int iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
2627  TComDataCU *pcCU = m_pcPic->getCU(iAddr);
2628  Bool bRenderable = pcCU->getRenderable(0) ;
2629
2630#endif
2631  for (iTypeIdx=-1; iTypeIdx<iNumTotalType; iTypeIdx++)
2632  {
2633    if( m_bUseSBACRD )
2634    {
2635      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
2636      m_pcRDGoOnSbacCoder->resetBits();
2637    }
2638    else
2639    {
2640      m_pcEntropyCoder->resetEntropy();
2641      m_pcEntropyCoder->resetBits();
2642    }
2643
2644    iEstDist = 0;
2645
2646    m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoTypeIdx(iTypeIdx+1);
2647
2648    if (iTypeIdx>=0)
2649    {
2650
2651      for(iClassIdx=1; iClassIdx < ( (iTypeIdx < SAO_BO) ?  m_iNumClass[iTypeIdx]+1 : SAO_MAX_BO_CLASSES+1); iClassIdx++)
2652      {
2653        if( iTypeIdx == SAO_BO)
2654        {
2655          currentDistortionTableBo[iClassIdx-1] = 0;
2656          currentRdCostTableBo[iClassIdx-1] = dLambda;
2657        }
2658#if HHI_INTERVIEW_SKIP
2659        if(m_iCount [iPartIdx][iTypeIdx][iClassIdx] && !bRenderable)
2660#else
2661        if(m_iCount [iPartIdx][iTypeIdx][iClassIdx])
2662#endif
2663        {
2664#if FULL_NBIT
2665          m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]<<g_uiBitDepth-8) / (Double)(m_iCount [iPartIdx][iTypeIdx][iClassIdx]<<m_uiSaoBitIncrease));
2666#else
2667          m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]<<g_uiBitIncrement) / (Double)(m_iCount [iPartIdx][iTypeIdx][iClassIdx]<<m_uiSaoBitIncrease));
2668#endif
2669          m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = Clip3(-m_iOffsetTh, m_iOffsetTh-1, (Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);
2670
2671          if (iTypeIdx < 4)
2672          {
2673            if ( m_iOffset[iPartIdx][iTypeIdx][iClassIdx]<0 && iClassIdx<3 )
2674            {
2675              m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;
2676            }
2677            if ( m_iOffset[iPartIdx][iTypeIdx][iClassIdx]>0 && iClassIdx>=3)
2678            {
2679              m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;
2680            }
2681          }
2682          {
2683            //Clean up, best_q_offset.
2684            Int64 iIterOffset, iTempOffset;
2685            Int64 iTempDist, iTempRate;
2686            Double dTempCost, dTempMinCost;
2687            UInt uiLength, uiTemp;
2688
2689            iIterOffset = m_iOffset[iPartIdx][iTypeIdx][iClassIdx];
2690            m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;
2691            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.
2692
2693            while (iIterOffset != 0)
2694            {
2695              // Calculate the bits required for signalling the offset
2696              uiLength = 1;
2697              uiTemp = (UInt)((iIterOffset <= 0) ? ( (-iIterOffset<<1) + 1 ) : (iIterOffset<<1));
2698              while( 1 != uiTemp )
2699              {
2700                uiTemp >>= 1;
2701                uiLength += 2;
2702              }
2703              iTempRate = (uiLength >> 1) + ((uiLength+1) >> 1);
2704
2705              // Do the dequntization before distorion calculation
2706              iTempOffset    =  iIterOffset << m_uiSaoBitIncrease;
2707              iTempDist  = (( m_iCount [iPartIdx][iTypeIdx][iClassIdx]*iTempOffset*iTempOffset-m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]*iTempOffset*2 ) >> uiShift);
2708
2709              dTempCost = ((Double)iTempDist + dLambda * (Double) iTempRate);
2710              if(dTempCost < dTempMinCost)
2711              {
2712                dTempMinCost = dTempCost;
2713                m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = iIterOffset;
2714                if(iTypeIdx == SAO_BO)
2715                {
2716                  currentDistortionTableBo[iClassIdx-1] = (Int) iTempDist;
2717                  currentRdCostTableBo[iClassIdx-1] = dTempCost;
2718                }
2719              }
2720              iIterOffset = (iIterOffset > 0) ? (iIterOffset-1):(iIterOffset+1);
2721            }
2722
2723          }
2724        }
2725        else
2726        {
2727          m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] = 0;
2728          m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;
2729        }
2730        if( iTypeIdx != SAO_BO )
2731        {
2732          iCount     =  m_iCount [iPartIdx][iTypeIdx][iClassIdx];
2733          iOffset    =  m_iOffset[iPartIdx][iTypeIdx][iClassIdx] << m_uiSaoBitIncrease;
2734          iOffsetOrg =  m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx];
2735          iEstDist   += (( iCount*iOffset*iOffset-iOffsetOrg*iOffset*2 ) >> uiShift);
2736          if (iTypeIdx < 4)
2737          {
2738            if (iClassIdx<3)
2739            {
2740              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);
2741            }
2742            else
2743            {
2744              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUvlc((Int)-m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);
2745            }
2746          }
2747          else
2748          {
2749            m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoSvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);
2750          }
2751        }
2752      }
2753
2754      if( iTypeIdx == SAO_BO )
2755      {
2756        // Estimate Best Position
2757        Double currentRDCost = 0.0;
2758
2759        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
2760        {
2761          currentRDCost = 0.0;
2762          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
2763          {
2764            currentRDCost += currentRdCostTableBo[uj];
2765          }
2766
2767          if( currentRDCost < bestRDCostTableBo)
2768          {
2769            bestRDCostTableBo = currentRDCost;
2770            bestClassTableBo  = i;
2771          }
2772        }
2773
2774        // Re code all Offsets
2775        // Code Center
2776        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUflc( (UInt) (bestClassTableBo) );
2777
2778        for(iClassIdx = bestClassTableBo; iClassIdx < bestClassTableBo+SAO_BO_LEN; iClassIdx++)
2779        {
2780          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoSvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx+1]);
2781          iEstDist += currentDistortionTableBo[iClassIdx];
2782        }
2783      }
2784
2785      m_iDist[iPartIdx][iTypeIdx] = iEstDist;
2786      m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder->getNumberOfWrittenBits();
2787
2788      m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + dLambda * (Double) m_iRate[iPartIdx][iTypeIdx]);
2789
2790      if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx])
2791      {
2792        m_iDistOrg [iPartIdx] = 0;
2793        m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx];
2794        m_iTypePartBest[iPartIdx] = iTypeIdx;
2795        if( m_bUseSBACRD )
2796          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
2797      }
2798    }
2799    else
2800    {
2801      if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] )
2802      {
2803        m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder->getNumberOfWrittenBits()*dLambda ; 
2804        m_iTypePartBest[iPartIdx] = -1;
2805        if( m_bUseSBACRD )
2806          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
2807      }
2808    }
2809  }
2810
2811  pOnePart->bProcessed = true;
2812  pOnePart->bSplit     = false;
2813  pOnePart->iMinDist   =        m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];
2814  pOnePart->iMinRate   = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);
2815  pOnePart->dMinCost   = pOnePart->iMinDist + dLambda * pOnePart->iMinRate;
2816  pOnePart->iBestType  = m_iTypePartBest[iPartIdx];
2817  if (pOnePart->iBestType != -1)
2818  {
2819    //     pOnePart->bEnableFlag =  1;
2820    pOnePart->iLength = m_iNumClass[pOnePart->iBestType];
2821    Int minIndex = 0;
2822    if( pOnePart->iBestType == SAO_BO )
2823    {
2824      pOnePart->bandPosition = bestClassTableBo;
2825      minIndex = pOnePart->bandPosition;
2826    }
2827    for (Int i=0; i< pOnePart->iLength ; i++)
2828    {
2829      pOnePart->iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart->iBestType][minIndex+i+1];
2830    }
2831
2832  }
2833  else
2834  {
2835    //     pOnePart->bEnableFlag = 0;
2836    pOnePart->iLength     = 0;
2837  }
2838}
2839
2840/** Run partition tree disable
2841 */
2842Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx)
2843{
2844  SAOQTPart*  pOnePart= &(psQTPart[iPartIdx]);
2845  pOnePart->bSplit      = false;
2846  pOnePart->iLength     =  0;
2847  pOnePart->iBestType   = -1;
2848
2849  if (pOnePart->PartLevel < m_uiMaxSplitLevel)
2850  {
2851    for (Int i=0; i<NUM_DOWN_PART; i++)
2852    {
2853      disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
2854    }
2855  }
2856}
2857
2858/** Run quadtree decision function
2859 * \param  iPartIdx, pcPicOrg, pcPicDec, pcPicRest, &dCostFinal
2860 */
2861Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda)
2862{
2863  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
2864
2865  UInt uiDepth = pOnePart->PartLevel;
2866  UInt uhNextDepth = uiDepth+1;
2867
2868  if (iPartIdx == 0)
2869  {
2870    dCostFinal = 0;
2871  }
2872
2873  //SAO for this part
2874  if(!pOnePart->bProcessed)
2875  {
2876    rdoSaoOnePart (psQTPart, iPartIdx, dLambda);
2877  }
2878
2879  //SAO for sub 4 parts
2880  if (pOnePart->PartLevel < iMaxLevel)
2881  {
2882    Double      dCostNotSplit = dLambda + pOnePart->dMinCost;
2883    Double      dCostSplit    = dLambda;
2884
2885    for (Int i=0; i< NUM_DOWN_PART ;i++)
2886    {
2887      if( m_bUseSBACRD ) 
2888      {
2889        if ( 0 == i) //initialize RD with previous depth buffer
2890        {
2891          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
2892        }
2893        else
2894        {
2895          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
2896        }
2897      } 
2898      runQuadTreeDecision(psQTPart, pOnePart->DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda);
2899      dCostSplit += dCostFinal;
2900      if( m_bUseSBACRD )
2901      {
2902        m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]);
2903      }
2904    }
2905
2906    if(dCostSplit < dCostNotSplit)
2907    {
2908      dCostFinal = dCostSplit;
2909      pOnePart->bSplit      = true;
2910      pOnePart->iLength     =  0;
2911      pOnePart->iBestType   = -1;
2912      if( m_bUseSBACRD )
2913      {
2914        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
2915      }
2916    }
2917    else
2918    {
2919      dCostFinal = dCostNotSplit;
2920      pOnePart->bSplit = false;
2921      for (Int i=0; i<NUM_DOWN_PART; i++)
2922      {
2923        disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
2924      }
2925      if( m_bUseSBACRD )
2926      {
2927        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
2928      }
2929    }
2930  }
2931  else
2932  {
2933    dCostFinal = pOnePart->dMinCost;
2934  }
2935}
2936
2937/** delete allocated memory of TEncSampleAdaptiveOffset class.
2938 */
2939Void TEncSampleAdaptiveOffset::destroyEncBuffer()
2940{
2941  for (Int i=0;i<m_iNumTotalParts;i++)
2942  {
2943    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
2944    {
2945      if (m_iCount [i][j])
2946      {
2947        delete [] m_iCount [i][j]; 
2948      }
2949      if (m_iOffset[i][j])
2950      {
2951        delete [] m_iOffset[i][j]; 
2952      }
2953      if (m_iOffsetOrg[i][j])
2954      {
2955        delete [] m_iOffsetOrg[i][j]; 
2956      }
2957    }
2958    if (m_iRate[i])
2959    {
2960      delete [] m_iRate[i];
2961    }
2962    if (m_iDist[i])
2963    {
2964      delete [] m_iDist[i]; 
2965    }
2966    if (m_dCost[i])
2967    {
2968      delete [] m_dCost[i]; 
2969    }
2970    if (m_iCount [i])
2971    {
2972      delete [] m_iCount [i]; 
2973    }
2974    if (m_iOffset[i])
2975    {
2976      delete [] m_iOffset[i]; 
2977    }
2978    if (m_iOffsetOrg[i])
2979    {
2980      delete [] m_iOffsetOrg[i]; 
2981    }
2982
2983  }
2984  if (m_iDistOrg)
2985  {
2986    delete [] m_iDistOrg ; m_iDistOrg = NULL;
2987  }
2988  if (m_dCostPartBest)
2989  {
2990    delete [] m_dCostPartBest ; m_dCostPartBest = NULL;
2991  }
2992  if (m_iTypePartBest)
2993  {
2994    delete [] m_iTypePartBest ; m_iTypePartBest = NULL;
2995  }
2996  if (m_iRate)
2997  {
2998    delete [] m_iRate ; m_iRate = NULL;
2999  }
3000  if (m_iDist)
3001  {
3002    delete [] m_iDist ; m_iDist = NULL;
3003  }
3004  if (m_dCost)
3005  {
3006    delete [] m_dCost ; m_dCost = NULL;
3007  }
3008  if (m_iCount)
3009  {
3010    delete [] m_iCount  ; m_iCount = NULL;
3011  }
3012  if (m_iOffset)
3013  {
3014    delete [] m_iOffset ; m_iOffset = NULL;
3015  }
3016  if (m_iOffsetOrg)
3017  {
3018    delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;
3019  }
3020
3021  Int iMaxDepth = 4;
3022  Int iDepth;
3023  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
3024  {
3025    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
3026    {
3027      delete m_pppcRDSbacCoder[iDepth][iCIIdx];
3028      delete m_pppcBinCoderCABAC[iDepth][iCIIdx];
3029    }
3030  }
3031
3032  for ( iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
3033  {
3034    delete [] m_pppcRDSbacCoder[iDepth];
3035    delete [] m_pppcBinCoderCABAC[iDepth];
3036  }
3037
3038  delete [] m_pppcRDSbacCoder;
3039  delete [] m_pppcBinCoderCABAC;
3040}
3041
3042/** create Encoder Buffer for SAO
3043 * \param
3044 */
3045Void TEncSampleAdaptiveOffset::createEncBuffer()
3046{
3047  m_iDistOrg = new Int64 [m_iNumTotalParts]; 
3048  m_dCostPartBest = new Double [m_iNumTotalParts]; 
3049  m_iTypePartBest = new Int [m_iNumTotalParts]; 
3050
3051  m_iRate = new Int64* [m_iNumTotalParts];
3052  m_iDist = new Int64* [m_iNumTotalParts];
3053  m_dCost = new Double*[m_iNumTotalParts];
3054
3055  m_iCount  = new Int64 **[m_iNumTotalParts];
3056  m_iOffset = new Int64 **[m_iNumTotalParts];
3057  m_iOffsetOrg = new Int64 **[m_iNumTotalParts];
3058
3059  for (Int i=0;i<m_iNumTotalParts;i++)
3060  {
3061    m_iRate[i] = new Int64  [MAX_NUM_SAO_TYPE];
3062    m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE]; 
3063    m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 
3064
3065    m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
3066    m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
3067    m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
3068
3069    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
3070    {
3071      m_iCount [i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
3072      m_iOffset[i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
3073      m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 
3074    }
3075  }
3076
3077  Int iMaxDepth = 4;
3078  m_pppcRDSbacCoder = new TEncSbac** [iMaxDepth+1];
3079#if FAST_BIT_EST
3080  m_pppcBinCoderCABAC = new TEncBinCABACCounter** [iMaxDepth+1];
3081#else
3082  m_pppcBinCoderCABAC = new TEncBinCABAC** [iMaxDepth+1];
3083#endif
3084
3085  for ( Int iDepth = 0; iDepth < iMaxDepth+1; iDepth++ )
3086  {
3087    m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM];
3088#if FAST_BIT_EST
3089    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM];
3090#else
3091    m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM];
3092#endif
3093    for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ )
3094    {
3095      m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac;
3096#if FAST_BIT_EST
3097      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter;
3098#else
3099      m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC;
3100#endif
3101      m_pppcRDSbacCoder   [iDepth][iCIIdx]->init( m_pppcBinCoderCABAC [iDepth][iCIIdx] );
3102    }
3103  }
3104}
3105
3106/** Start SAO encoder
3107 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
3108 */
3109Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
3110{
3111  if( pcRDGoOnSbacCoder )
3112    m_bUseSBACRD = true;
3113  else
3114    m_bUseSBACRD = false;
3115
3116  m_pcPic = pcPic;
3117  m_pcEntropyCoder = pcEntropyCoder;
3118
3119  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
3120  m_pcEntropyCoder->resetEntropy();
3121  m_pcEntropyCoder->resetBits();
3122
3123  if( m_bUseSBACRD )
3124  {
3125    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
3126    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
3127  }
3128}
3129
3130/** End SAO encoder
3131 */
3132Void TEncSampleAdaptiveOffset::endSaoEnc()
3133{
3134  m_pcPic = NULL;
3135  m_pcEntropyCoder = NULL;
3136}
3137
3138inline int xSign(int x)
3139{
3140  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
3141}
3142
3143/** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
3144 * \param  pRecStart to-be-filtered block buffer pointer
3145 * \param  pOrgStart original block buffer pointer
3146 * \param  stride picture buffer stride
3147 * \param  ppStat statistics buffer
3148 * \param  ppCount counter buffer
3149 * \param  width block width
3150 * \param  height block height
3151 * \param  pbBorderAvail availabilities of block border pixels
3152 */
3153Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail)
3154{
3155  Int64 *stats, *count;
3156  Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
3157  Pel *pOrg, *pRec;
3158  UInt edgeType;
3159  Int x, y;
3160
3161  //--------- Band offset-----------//
3162  stats = ppStats[SAO_BO];
3163  count = ppCount[SAO_BO];
3164  pOrg   = pOrgStart;
3165  pRec   = pRecStart;
3166  for (y=0; y< height; y++)
3167  {
3168    for (x=0; x< width; x++)
3169    {
3170      classIdx = m_lumaTableBo[pRec[x]];
3171      if (classIdx)
3172      {
3173        stats[classIdx] += (pOrg[x] - pRec[x]); 
3174        count[classIdx] ++;
3175      }
3176    }
3177    pOrg += stride;
3178    pRec += stride;
3179  }
3180  //---------- Edge offset 0--------------//
3181  stats = ppStats[SAO_EO_0];
3182  count = ppCount[SAO_EO_0];
3183  pOrg   = pOrgStart;
3184  pRec   = pRecStart;
3185
3186
3187  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
3188  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
3189  for (y=0; y< height; y++)
3190  {
3191    signLeft = xSign(pRec[startX] - pRec[startX-1]);
3192    for (x=startX; x< endX; x++)
3193    {
3194      signRight =  xSign(pRec[x] - pRec[x+1]); 
3195      edgeType =  signRight + signLeft + 2;
3196      signLeft  = -signRight;
3197
3198      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3199      count[m_auiEoTable[edgeType]] ++;
3200    }
3201    pRec  += stride;
3202    pOrg += stride;
3203  }
3204
3205  //---------- Edge offset 1--------------//
3206  stats = ppStats[SAO_EO_1];
3207  count = ppCount[SAO_EO_1];
3208  pOrg   = pOrgStart;
3209  pRec   = pRecStart;
3210
3211  startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
3212  endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
3213  if (!pbBorderAvail[SGU_T])
3214  {
3215    pRec  += stride;
3216    pOrg  += stride;
3217  }
3218
3219  for (x=0; x< width; x++)
3220  {
3221    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]);
3222  }
3223  for (y=startY; y<endY; y++)
3224  {
3225    for (x=0; x< width; x++)
3226    {
3227      signDown     =  xSign(pRec[x] - pRec[x+stride]); 
3228      edgeType    =  signDown + m_iUpBuff1[x] + 2;
3229      m_iUpBuff1[x] = -signDown;
3230
3231      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3232      count[m_auiEoTable[edgeType]] ++;
3233    }
3234    pOrg += stride;
3235    pRec += stride;
3236  }
3237  //---------- Edge offset 2--------------//
3238  stats = ppStats[SAO_EO_2];
3239  count = ppCount[SAO_EO_2];
3240  pOrg   = pOrgStart;
3241  pRec   = pRecStart;
3242
3243  posShift= stride + 1;
3244
3245  startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
3246  endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
3247
3248  //prepare 2nd line upper sign
3249  pRec += stride;
3250  for (x=startX; x< endX+1; x++)
3251  {
3252    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
3253  }
3254
3255  //1st line
3256  pRec -= stride;
3257  if(pbBorderAvail[SGU_TL])
3258  {
3259    x= 0;
3260    edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
3261    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3262    count[m_auiEoTable[edgeType]] ++;
3263  }
3264  if(pbBorderAvail[SGU_T])
3265  {
3266    for(x= 1; x< endX; x++)
3267    {
3268      edgeType      =  xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
3269      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3270      count[m_auiEoTable[edgeType]] ++;
3271    }
3272  }
3273  pRec   += stride;
3274  pOrg   += stride;
3275
3276  //middle lines
3277  for (y= 1; y< height-1; y++)
3278  {
3279    for (x=startX; x<endX; x++)
3280    {
3281      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
3282      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
3283      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3284      count[m_auiEoTable[edgeType]] ++;
3285
3286      m_iUpBufft[x+1] = -signDown1; 
3287    }
3288    m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]);
3289
3290    ipSwap     = m_iUpBuff1;
3291    m_iUpBuff1 = m_iUpBufft;
3292    m_iUpBufft = ipSwap;
3293
3294    pRec  += stride;
3295    pOrg  += stride;
3296  }
3297
3298  //last line
3299  if(pbBorderAvail[SGU_B])
3300  {
3301    for(x= startX; x< width-1; x++)
3302    {
3303      edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
3304      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3305      count[m_auiEoTable[edgeType]] ++;
3306    }
3307  }
3308  if(pbBorderAvail[SGU_BR])
3309  {
3310    x= width -1;
3311    edgeType =  xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
3312    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3313    count[m_auiEoTable[edgeType]] ++;
3314  }
3315
3316  //---------- Edge offset 3--------------//
3317
3318  stats = ppStats[SAO_EO_3];
3319  count = ppCount[SAO_EO_3];
3320  pOrg   = pOrgStart;
3321  pRec   = pRecStart;
3322
3323  posShift     = stride - 1;
3324  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
3325  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
3326
3327  //prepare 2nd line upper sign
3328  pRec += stride;
3329  for (x=startX-1; x< endX; x++)
3330  {
3331    m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
3332  }
3333
3334
3335  //first line
3336  pRec -= stride;
3337  if(pbBorderAvail[SGU_T])
3338  {
3339    for(x= startX; x< width -1; x++)
3340    {
3341      edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
3342      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3343      count[m_auiEoTable[edgeType]] ++;
3344    }
3345  }
3346  if(pbBorderAvail[SGU_TR])
3347  {
3348    x= width-1;
3349    edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
3350    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3351    count[m_auiEoTable[edgeType]] ++;
3352  }
3353  pRec  += stride;
3354  pOrg  += stride;
3355
3356  //middle lines
3357  for (y= 1; y< height-1; y++)
3358  {
3359    for(x= startX; x< endX; x++)
3360    {
3361      signDown1      =  xSign(pRec[x] - pRec[x+ posShift]) ;
3362      edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
3363
3364      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3365      count[m_auiEoTable[edgeType]] ++;
3366      m_iUpBuff1[x-1] = -signDown1; 
3367
3368    }
3369    m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]);
3370
3371    pRec  += stride;
3372    pOrg  += stride;
3373  }
3374
3375  //last line
3376  if(pbBorderAvail[SGU_BL])
3377  {
3378    x= 0;
3379    edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
3380    stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3381    count[m_auiEoTable[edgeType]] ++;
3382
3383  }
3384  if(pbBorderAvail[SGU_B])
3385  {
3386    for(x= 1; x< endX; x++)
3387    {
3388      edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
3389      stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
3390      count[m_auiEoTable[edgeType]] ++;
3391    }
3392  }
3393}
3394
3395/** Calculate SAO statistics for current LCU
3396 * \param  iAddr,  iPartIdx,  iYCbCr
3397 */
3398Void TEncSampleAdaptiveOffset::calcSaoStatsCu(Int iAddr, Int iPartIdx, Int iYCbCr)
3399{
3400  if(!m_bUseNIF)
3401  {
3402    calcSaoStatsCuOrg( iAddr, iPartIdx, iYCbCr);
3403  }
3404  else
3405  {
3406    Int64** ppStats = m_iOffsetOrg[iPartIdx];
3407    Int64** ppCount = m_iCount    [iPartIdx];
3408
3409    //parameters
3410    Int  isChroma = (iYCbCr != 0)? 1:0;
3411    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
3412    Pel* pPicOrg = getPicYuvAddr (m_pcPic->getPicYuvOrg(), iYCbCr);
3413    Pel* pPicRec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
3414
3415    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
3416
3417    //variables
3418    UInt  xPos, yPos, width, height;
3419    Bool* pbBorderAvail;
3420    UInt  posOffset;
3421
3422    for(Int i=0; i< vFilterBlocks.size(); i++)
3423    {
3424      xPos        = vFilterBlocks[i].posX   >> isChroma;
3425      yPos        = vFilterBlocks[i].posY   >> isChroma;
3426      width       = vFilterBlocks[i].width  >> isChroma;
3427      height      = vFilterBlocks[i].height >> isChroma;
3428      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
3429
3430      posOffset = (yPos* stride) + xPos;
3431
3432#if HHI_INTERVIEW_SKIP
3433      if( !m_pcPic->getCU(iAddr)->getRenderable(0 ))
3434      {
3435      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);
3436      }
3437#else
3438      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);
3439#endif
3440    }
3441  }
3442
3443}
3444
3445/** Calculate SAO statistics for current LCU without non-crossing slice
3446 * \param  iAddr,  iPartIdx,  iYCbCr
3447 */
3448Void TEncSampleAdaptiveOffset::calcSaoStatsCuOrg(Int iAddr, Int iPartIdx, Int iYCbCr)
3449{
3450  Int x,y;
3451  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
3452  TComSPS *pTmpSPS =  m_pcPic->getSlice(0)->getSPS();
3453
3454  Pel* pOrg;
3455  Pel* pRec;
3456  Int iStride;
3457  Int iLcuWidth  = pTmpSPS->getMaxCUHeight();
3458  Int iLcuHeight = pTmpSPS->getMaxCUWidth();
3459  UInt uiLPelX   = pTmpCu->getCUPelX();
3460  UInt uiTPelY   = pTmpCu->getCUPelY();
3461  UInt uiRPelX;
3462  UInt uiBPelY;
3463  Int64* iStats;
3464  Int64* iCount;
3465  Int iClassIdx;
3466  Int iPicWidthTmp;
3467  Int iPicHeightTmp;
3468  Int iStartX;
3469  Int iStartY;
3470  Int iEndX;
3471  Int iEndY;
3472
3473  Int iIsChroma = (iYCbCr!=0)? 1:0;
3474  Int numSkipLine = iIsChroma? 2:4;
3475  if (m_saoInterleavingFlag == 0)
3476  {
3477    numSkipLine = 0;
3478  }
3479
3480  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
3481  iPicHeightTmp = m_iPicHeight >> iIsChroma;
3482  iLcuWidth     = iLcuWidth    >> iIsChroma;
3483  iLcuHeight    = iLcuHeight   >> iIsChroma;
3484  uiLPelX       = uiLPelX      >> iIsChroma;
3485  uiTPelY       = uiTPelY      >> iIsChroma;
3486  uiRPelX       = uiLPelX + iLcuWidth  ;
3487  uiBPelY       = uiTPelY + iLcuHeight ;
3488  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
3489  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
3490  iLcuWidth     = uiRPelX - uiLPelX;
3491  iLcuHeight    = uiBPelY - uiTPelY;
3492
3493  iStride    =  (iYCbCr == 0)? m_pcPic->getStride(): m_pcPic->getCStride();
3494
3495//if(iSaoType == BO_0 || iSaoType == BO_1)
3496#if HHI_INTERVIEW_SKIP
3497  if( !m_pcPic->getCU(iAddr)->getRenderable(0) )
3498#endif
3499  {
3500    iStats = m_iOffsetOrg[iPartIdx][SAO_BO];
3501    iCount = m_iCount    [iPartIdx][SAO_BO];
3502
3503    pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
3504    pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
3505
3506    iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeight-numSkipLine;
3507    for (y=0; y<iEndY; y++)
3508    {
3509      for (x=0; x<iLcuWidth; x++)
3510      {
3511        iClassIdx = m_lumaTableBo[pRec[x]];
3512        if (iClassIdx)
3513        {
3514          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
3515          iCount[iClassIdx] ++;
3516        }
3517      }
3518      pOrg += iStride;
3519      pRec += iStride;
3520    }
3521
3522  }
3523  Int iSignLeft;
3524  Int iSignRight;
3525  Int iSignDown;
3526  Int iSignDown1;
3527  Int iSignDown2;
3528
3529  UInt uiEdgeType;
3530
3531//if (iSaoType == EO_0  || iSaoType == EO_1 || iSaoType == EO_2 || iSaoType == EO_3)
3532#if HHI_INTERVIEW_SKIP
3533  if( !m_pcPic->getCU(iAddr)->getRenderable(0) )
3534#endif
3535  {
3536  //if (iSaoType == EO_0)
3537    {
3538      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];
3539      iCount = m_iCount    [iPartIdx][SAO_EO_0];
3540
3541      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
3542      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
3543
3544      iStartX = (uiLPelX == 0) ? 1 : 0;
3545      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
3546      for (y=0; y<iLcuHeight-numSkipLine; y++)
3547      {
3548        iSignLeft = xSign(pRec[iStartX] - pRec[iStartX-1]);
3549        for (x=iStartX; x< iEndX; x++)
3550        {
3551          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
3552          uiEdgeType =  iSignRight + iSignLeft + 2;
3553          iSignLeft  = -iSignRight;
3554
3555          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
3556          iCount[m_auiEoTable[uiEdgeType]] ++;
3557        }
3558        pOrg += iStride;
3559        pRec += iStride;
3560      }
3561    }
3562
3563  //if (iSaoType == EO_1)
3564    {
3565      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];
3566      iCount = m_iCount    [iPartIdx][SAO_EO_1];
3567
3568      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
3569      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
3570
3571      iStartY = (uiTPelY == 0) ? 1 : 0;
3572      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
3573      if (uiTPelY == 0)
3574      {
3575        pOrg += iStride;
3576        pRec += iStride;
3577      }
3578
3579      for (x=0; x< iLcuWidth; x++)
3580      {
3581        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
3582      }
3583      for (y=iStartY; y<iEndY; y++)
3584      {
3585        for (x=0; x<iLcuWidth; x++)
3586        {
3587          iSignDown     =  xSign(pRec[x] - pRec[x+iStride]); 
3588          uiEdgeType    =  iSignDown + m_iUpBuff1[x] + 2;
3589          m_iUpBuff1[x] = -iSignDown;
3590
3591          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
3592          iCount[m_auiEoTable[uiEdgeType]] ++;
3593        }
3594        pOrg += iStride;
3595        pRec += iStride;
3596      }
3597    }
3598  //if (iSaoType == EO_2)
3599    {
3600      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];
3601      iCount = m_iCount    [iPartIdx][SAO_EO_2];
3602
3603      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
3604      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
3605
3606      iStartX = (uiLPelX == 0) ? 1 : 0;
3607      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
3608
3609      iStartY = (uiTPelY == 0) ? 1 : 0;
3610      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
3611      if (uiTPelY == 0)
3612      {
3613        pOrg += iStride;
3614        pRec += iStride;
3615      }
3616
3617      for (x=iStartX; x<iEndX; x++)
3618      {
3619        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
3620      }
3621      for (y=iStartY; y<iEndY; y++)
3622      {
3623        iSignDown2 = xSign(pRec[iStride+iStartX] - pRec[iStartX-1]);
3624        for (x=iStartX; x<iEndX; x++)
3625        {
3626          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
3627          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
3628          m_iUpBufft[x+1] = -iSignDown1; 
3629          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
3630          iCount[m_auiEoTable[uiEdgeType]] ++;
3631        }
3632        m_iUpBufft[iStartX] = iSignDown2;
3633        ipSwap     = m_iUpBuff1;
3634        m_iUpBuff1 = m_iUpBufft;
3635        m_iUpBufft = ipSwap;
3636
3637        pRec += iStride;
3638        pOrg += iStride;
3639      }
3640    } 
3641  //if (iSaoType == EO_3  )
3642    {
3643      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];
3644      iCount = m_iCount    [iPartIdx][SAO_EO_3];
3645
3646      pOrg = getPicYuvAddr(m_pcPic->getPicYuvOrg(), iYCbCr, iAddr);
3647      pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
3648
3649      iStartX = (uiLPelX == 0) ? 1 : 0;
3650      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
3651
3652      iStartY = (uiTPelY == 0) ? 1 : 0;
3653      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
3654      if (iStartY == 1)
3655      {
3656        pOrg += iStride;
3657        pRec += iStride;
3658      }
3659
3660      for (x=iStartX-1; x<iEndX; x++)
3661      {
3662        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
3663      }
3664
3665      for (y=iStartY; y<iEndY; y++)
3666      {
3667        for (x=iStartX; x<iEndX; x++)
3668        {
3669          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
3670          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
3671          m_iUpBuff1[x-1] = -iSignDown1; 
3672          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
3673          iCount[m_auiEoTable[uiEdgeType]] ++;
3674        }
3675        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
3676
3677        pRec += iStride;
3678        pOrg += iStride;
3679      } 
3680    } 
3681  }
3682}
3683
3684/** get SAO statistics
3685 * \param  *psQTPart,  iYCbCr
3686 */
3687Void TEncSampleAdaptiveOffset::getSaoStats(SAOQTPart *psQTPart, Int iYCbCr)
3688{
3689  Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;
3690  Int i;
3691  Int iNumTotalType = MAX_NUM_SAO_TYPE;
3692  Int LcuIdxX;
3693  Int LcuIdxY;
3694  Int iAddr;
3695  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
3696  Int iDownPartIdx;
3697  Int iPartStart;
3698  Int iPartEnd;
3699  SAOQTPart*  pOnePart; 
3700
3701  if (m_uiMaxSplitLevel == 0)
3702  {
3703    iPartIdx = 0;
3704    pOnePart = &(psQTPart[iPartIdx]);
3705    for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
3706    {
3707      for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
3708      {
3709        iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
3710        calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
3711      }
3712    }
3713  }
3714  else
3715  {
3716    for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel-1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)
3717    {
3718      pOnePart = &(psQTPart[iPartIdx]);
3719      for (LcuIdxY = pOnePart->StartCUY; LcuIdxY<= pOnePart->EndCUY; LcuIdxY++)
3720      {
3721        for (LcuIdxX = pOnePart->StartCUX; LcuIdxX<= pOnePart->EndCUX; LcuIdxX++)
3722        {
3723          iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
3724          calcSaoStatsCu(iAddr, iPartIdx, iYCbCr);
3725        }
3726      }
3727    }
3728    for (iLevelIdx = m_uiMaxSplitLevel-1; iLevelIdx>=0; iLevelIdx-- )
3729    {
3730      iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx-1] : 0;
3731      iPartEnd   = m_aiNumCulPartsLevel[iLevelIdx];
3732
3733      for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)
3734      {
3735        pOnePart = &(psQTPart[iPartIdx]);
3736        for (i=0; i< NUM_DOWN_PART; i++)
3737        {
3738          iDownPartIdx = pOnePart->DownPartsIdx[i];
3739          for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)
3740          {
3741            for (iClassIdx=0; iClassIdx< (iTypeIdx < SAO_BO ? m_iNumClass[iTypeIdx] : SAO_MAX_BO_CLASSES) +1; iClassIdx++)
3742            {
3743              m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];
3744              m_iCount [iPartIdx][iTypeIdx][iClassIdx]    += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];
3745            }
3746          }
3747        }
3748      }
3749    }
3750  }
3751}
3752
3753/** reset offset statistics
3754 * \param
3755 */
3756Void TEncSampleAdaptiveOffset::resetStats()
3757{
3758  for (Int i=0;i<m_iNumTotalParts;i++)
3759  {
3760    m_dCostPartBest[i] = MAX_DOUBLE;
3761    m_iTypePartBest[i] = -1;
3762    m_iDistOrg[i] = 0;
3763    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
3764    {
3765      m_iDist[i][j] = 0;
3766      m_iRate[i][j] = 0;
3767      m_dCost[i][j] = 0;
3768      for (Int k=0;k<MAX_NUM_SAO_CLASS;k++)
3769      {
3770        m_iCount [i][j][k] = 0;
3771        m_iOffset[i][j][k] = 0;
3772        m_iOffsetOrg[i][j][k] = 0;
3773      } 
3774    }
3775  }
3776}
3777
3778#if SAO_CHROMA_LAMBDA
3779/** Sample adaptive offset process
3780 * \param pcSaoParam
3781 * \param dLambdaLuma
3782 * \param dLambdaChroma
3783 */
3784Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
3785#else
3786/** Sample adaptive offset process
3787 * \param dLambda
3788 */
3789Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)
3790#endif
3791{
3792
3793  m_eSliceType          =  m_pcPic->getSlice(0)->getSliceType();
3794  m_iPicNalReferenceIdc = (m_pcPic->getSlice(0)->isReferenced() ? 1 :0);
3795
3796#if SAO_CHROMA_LAMBDA
3797  m_dLambdaLuma    = dLambdaLuma;
3798  m_dLambdaChroma  = dLambdaChroma;
3799#else
3800  m_dLambdaLuma    = dLambda;
3801  m_dLambdaChroma  = dLambda;
3802#endif
3803
3804  if(m_bUseNIF)
3805  {
3806    m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
3807  }
3808
3809#if FULL_NBIT
3810  m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth-8) - min((Int)(g_uiBitDepth + (g_uiBitDepth-8)), 10);
3811#else
3812  m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement - min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);
3813#endif
3814
3815  const Int iOffsetBitRange8Bit = 4;
3816  Int iOffsetBitDepth = g_uiBitDepth + g_uiBitIncrement - m_uiSaoBitIncrease;
3817  Int iOffsetBitRange = iOffsetBitRange8Bit + (iOffsetBitDepth - 8);
3818  m_iOffsetTh = 1 << (iOffsetBitRange - 1);
3819  resetSAOParam(pcSaoParam);
3820  resetStats();
3821
3822  Int iY  = 0;
3823  Double dCostFinal = 0;
3824
3825
3826  if ( m_saoInterleavingFlag)
3827  {
3828    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);
3829  }
3830  else
3831  {
3832    pcSaoParam->bSaoFlag[0] = 1;
3833    pcSaoParam->bSaoFlag[1] = 0;
3834    pcSaoParam->bSaoFlag[2] = 0;
3835    for (Int compIdx=0;compIdx<3;compIdx++)
3836    {
3837      if (pcSaoParam->bSaoFlag[iY])
3838      {
3839        dCostFinal = 0;
3840        Double lambdaRdo = (compIdx==0 ? dLambdaLuma: dLambdaChroma);
3841        resetStats();
3842        getSaoStats(pcSaoParam->psSaoPart[compIdx], compIdx);
3843        runQuadTreeDecision(pcSaoParam->psSaoPart[compIdx], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo);
3844        pcSaoParam->bSaoFlag[compIdx] = dCostFinal < 0 ? 1:0;
3845        if(pcSaoParam->bSaoFlag[compIdx])
3846        {
3847          convertQT2SaoUnit(pcSaoParam, 0, compIdx);
3848          assignSaoUnitSyntax(pcSaoParam->saoLcuParam[compIdx],  pcSaoParam->psSaoPart[compIdx], pcSaoParam->oneUnitFlag[compIdx], compIdx);
3849        }
3850      }
3851    }
3852  }
3853  for (Int compIdx=0;compIdx<3;compIdx++)
3854  {
3855    if (pcSaoParam->bSaoFlag[compIdx])
3856    {
3857      processSaoUnitAll( pcSaoParam->saoLcuParam[compIdx], pcSaoParam->oneUnitFlag[compIdx], compIdx);
3858    }
3859  }
3860}
3861/** Check merge SAO unit
3862 * \param saoUnitCurr current SAO unit
3863 * \param saoUnitCheck SAO unit tobe check
3864 * \param dir direction
3865 */
3866Void TEncSampleAdaptiveOffset::checkMerge(SaoLcuParam * saoUnitCurr, SaoLcuParam * saoUnitCheck, Int dir)
3867{
3868  Int i ;
3869  Int countDiff = 0;
3870  if (saoUnitCurr->partIdx != saoUnitCheck->partIdx)
3871  {
3872    if (saoUnitCurr->typeIdx !=-1)
3873    {
3874      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
3875      {
3876        for (i=0;i<saoUnitCurr->length;i++)
3877        {
3878          countDiff += (saoUnitCurr->offset[i] != saoUnitCheck->offset[i]);
3879        }
3880        countDiff += (saoUnitCurr->bandPosition != saoUnitCheck->bandPosition);
3881        if (countDiff ==0)
3882        {
3883          saoUnitCurr->partIdx = saoUnitCheck->partIdx;
3884          if (dir == 1)
3885          {
3886            saoUnitCurr->mergeUpFlag = 1;
3887            saoUnitCurr->mergeLeftFlag = 0;
3888          }
3889          else
3890          {
3891            saoUnitCurr->mergeUpFlag = 0;
3892            saoUnitCurr->mergeLeftFlag = 1;
3893          }
3894        }
3895      }
3896    }
3897    else
3898    {
3899      if (saoUnitCurr->typeIdx == saoUnitCheck->typeIdx)
3900      {
3901        saoUnitCurr->partIdx = saoUnitCheck->partIdx;
3902        if (dir == 1)
3903        {
3904          saoUnitCurr->mergeUpFlag = 1;
3905          saoUnitCurr->mergeLeftFlag = 0;
3906        }
3907        else
3908        {
3909          saoUnitCurr->mergeUpFlag = 0;
3910          saoUnitCurr->mergeLeftFlag = 1;
3911        }
3912      }
3913    }
3914  }
3915}
3916/** Assign SAO unit syntax from picture-based algorithm
3917 * \param saoLcuParam SAO LCU parameters
3918 * \param saoPart SAO part
3919 * \param oneUnitFlag SAO one unit flag
3920 * \param iYCbCr color component Index
3921 */
3922Void TEncSampleAdaptiveOffset::assignSaoUnitSyntax(SaoLcuParam* saoLcuParam,  SAOQTPart* saoPart, Bool &oneUnitFlag, Int yCbCr)
3923{
3924  if (saoPart->bSplit == 0)
3925  {
3926    oneUnitFlag = 1;
3927  }
3928  else
3929  {
3930    Int i,j, addr, addrUp, addrLeft,  idx, idxUp, idxLeft,  idxCount;
3931    Int run;
3932    Int runPartBeginAddr=0;
3933    Int runPart;
3934    Int runPartPrevious;
3935
3936    oneUnitFlag = 0;
3937
3938    idxCount = -1;
3939    saoLcuParam[0].mergeUpFlag = 0;
3940    saoLcuParam[0].mergeLeftFlag = 0;
3941
3942    for (j=0;j<m_iNumCuInHeight;j++)
3943    {
3944      run = 0;
3945      runPartPrevious = -1;
3946      for (i=0;i<m_iNumCuInWidth;i++)
3947      {
3948        addr     = i + j*m_iNumCuInWidth;
3949        addrLeft = (addr%m_iNumCuInWidth == 0) ? -1 : addr - 1;
3950        addrUp   = (addr<m_iNumCuInWidth)      ? -1 : addr - m_iNumCuInWidth;
3951        idx      = saoLcuParam[addr].partIdxTmp;
3952        idxLeft  = (addrLeft == -1) ? -1 : saoLcuParam[addrLeft].partIdxTmp;
3953        idxUp    = (addrUp == -1)   ? -1 : saoLcuParam[addrUp].partIdxTmp;
3954
3955        if(idx!=idxLeft && idx!=idxUp)
3956        {
3957          saoLcuParam[addr].mergeUpFlag   = 0; idxCount++;
3958          saoLcuParam[addr].mergeLeftFlag = 0;
3959          saoLcuParam[addr].partIdx = idxCount;
3960        }
3961        else if (idx==idxLeft)
3962        {
3963          saoLcuParam[addr].mergeUpFlag   = 1;
3964          saoLcuParam[addr].mergeLeftFlag = 1;
3965          saoLcuParam[addr].partIdx = saoLcuParam[addrLeft].partIdx;
3966        }
3967        else if (idx==idxUp)
3968        {
3969          saoLcuParam[addr].mergeUpFlag   = 1;
3970          saoLcuParam[addr].mergeLeftFlag = 0;
3971          saoLcuParam[addr].partIdx = saoLcuParam[addrUp].partIdx;
3972        }
3973        if (addrUp != -1)
3974        {
3975          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrUp], 1);
3976        }
3977        if (addrLeft != -1)
3978        {
3979          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);
3980        }
3981        runPart = saoLcuParam[addr].partIdx;
3982        if (runPart == runPartPrevious)
3983        {
3984          run ++;
3985          saoLcuParam[addr].run = -1;
3986          saoLcuParam[runPartBeginAddr].run = run;
3987        }
3988        else
3989        {
3990          runPartBeginAddr = addr;
3991          run = 0;
3992          saoLcuParam[addr].run = run;
3993        }
3994        runPartPrevious = runPart;
3995      }
3996    }
3997
3998    for (j=0;j<m_iNumCuInHeight;j++)
3999    {
4000      for (i=0;i<m_iNumCuInWidth;i++)
4001      {
4002        addr     =  i + j*m_iNumCuInWidth;
4003        addrLeft =  (addr%m_iNumCuInWidth == 0) ? -1 : addr - 1;
4004        addrUp  =  (addr<m_iNumCuInWidth)      ? -1 : addr - m_iNumCuInWidth;
4005
4006        if (saoLcuParam[addr].run == -1)
4007        {
4008          if (addrLeft != -1)
4009          {
4010            saoLcuParam[addr].run = saoLcuParam[addrLeft].run-1;
4011          }
4012        }
4013        if (addrUp>=0)
4014        {
4015          saoLcuParam[addr].runDiff = saoLcuParam[addr].run - saoLcuParam[addrUp].run;
4016        }
4017        else
4018        {
4019          saoLcuParam[addr].runDiff = saoLcuParam[addr].run ;
4020        }
4021      }
4022    }
4023  }
4024}
4025/** rate distortion optimization of all SAO units
4026 * \param saoParam SAO parameters
4027 * \param lambda
4028 * \param lambdaChroma
4029 */
4030Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
4031{
4032
4033  Int idxY;
4034  Int idxX;
4035  Int frameHeightInCU = saoParam->numCuInHeight;
4036  Int frameWidthInCU  = saoParam->numCuInWidth;
4037  Int j, k;
4038  Int addr = 0;
4039  Int addrUp = -1;
4040  Int addrLeft = -1;
4041  Int compIdx = 0;
4042  Double lambdaComp;
4043
4044  saoParam->bSaoFlag[0] = true;
4045  saoParam->bSaoFlag[1] = true;
4046  saoParam->bSaoFlag[2] = true;
4047  saoParam->oneUnitFlag[0] = false;
4048  saoParam->oneUnitFlag[1] = false;
4049  saoParam->oneUnitFlag[2] = false;
4050
4051
4052  for (idxY = 0; idxY< frameHeightInCU; idxY++)
4053  {
4054    for (idxX = 0; idxX< frameWidthInCU; idxX++)
4055    {
4056      addr     = idxX  + frameWidthInCU*idxY;
4057      addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
4058      addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
4059      // reset stats Y, Cb, Cr
4060      for ( compIdx=0;compIdx<3;compIdx++)
4061      {
4062        for ( j=0;j<MAX_NUM_SAO_TYPE;j++)
4063        {
4064          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
4065          {
4066            m_iCount    [compIdx][j][k] = 0;
4067            m_iOffset   [compIdx][j][k] = 0;
4068            m_iOffsetOrg[compIdx][j][k] = 0;
4069          } 
4070        }
4071        saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
4072        saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
4073        saoParam->saoLcuParam[compIdx][addr].run           = 0;
4074        saoParam->saoLcuParam[compIdx][addr].runDiff       = 0;
4075        saoParam->saoLcuParam[compIdx][addr].mergeLeftFlag = 0;
4076        saoParam->saoLcuParam[compIdx][addr].bandPosition  = 0;
4077        lambdaComp = compIdx==0 ? lambda : lambdaChroma;
4078        calcSaoStatsCu(addr, compIdx,  compIdx);
4079        rdoSaoUnit (saoParam, addr, addrUp, addrLeft, compIdx,  lambdaComp);
4080#if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_3
4081        if (compIdx!=0)
4082        {
4083          if ( saoParam->saoLcuParam[compIdx][0].typeIdx == -1 )
4084          {
4085            saoParam->bSaoFlag[compIdx] = false;
4086          }
4087        }
4088#endif
4089      }
4090    }
4091  }
4092
4093}
4094/** rate distortion optimization of SAO unit
4095 * \param saoParam SAO parameters
4096 * \param addr address
4097 * \param addrUp above address
4098 * \param addrLeft left address
4099 * \param yCbCr color component index
4100 * \param lambda
4101 */
4102Void TEncSampleAdaptiveOffset::rdoSaoUnit(SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda)
4103{
4104  Int typeIdx;
4105
4106  Int64 estDist;
4107  Int64 offsetOrg;
4108  Int64 offset;
4109  Int64 count;
4110  Int classIdx;
4111  Int shift = g_uiBitIncrement << 1;
4112  //   Double dAreaWeight =  0;
4113  Double complexityCost = 0;
4114  SaoLcuParam*  saoLcuParam = NULL;   
4115  SaoLcuParam*  saoLcuParamNeighbor = NULL; 
4116  Int   merge_iOffset [33];
4117  Int64 merge_iDist;
4118  Int   merge_iRate;
4119  Double merge_dCost;
4120  Int offsetTh = m_iOffsetTh;
4121
4122  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
4123
4124  saoLcuParam->mergeUpFlag   = 0;
4125  saoLcuParam->mergeLeftFlag = 0;
4126  saoLcuParam->run    = 0;
4127  saoLcuParam->runDiff= 0;
4128
4129
4130  m_iTypePartBest[yCbCr] = -1;
4131  m_dCostPartBest[yCbCr] = 0;
4132  m_iDistOrg[yCbCr] = 0;
4133
4134  Double  bestRDCostTableBo = MAX_DOUBLE;
4135  Int     bestClassTableBo    = 0;
4136  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
4137  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
4138  Int     bestClassTableBoMerge = 0;
4139
4140#if HHI_INTERVIEW_SKIP
4141  Bool bRenderable = m_pcPic->getCU(addr)->getRenderable(0) ;
4142#endif
4143  for (typeIdx=-1; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
4144  {
4145    m_pcEntropyCoder->resetEntropy();
4146    m_pcEntropyCoder->resetBits();
4147
4148    if (m_saoInterleavingFlag)
4149    {
4150#if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_1
4151      if(yCbCr>0 && typeIdx>3 )
4152      {
4153        continue;
4154      }
4155#endif
4156#if !REMOVE_SAO_LCU_ENC_CONSTRAINTS_2
4157      if (yCbCr>0 )
4158      {
4159        offsetTh = 2<<g_uiBitIncrement;
4160      }
4161      else
4162#endif
4163      {
4164        offsetTh = m_iOffsetTh;
4165      }
4166    }
4167
4168    estDist = 0;
4169    m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoTypeIdx(typeIdx+1);
4170    if (typeIdx>=0)
4171    {
4172
4173      for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
4174      {
4175        if( typeIdx == SAO_BO)
4176        {
4177          currentDistortionTableBo[classIdx-1] = 0;
4178          currentRdCostTableBo[classIdx-1] = lambda;
4179        }
4180#if HHI_INTERVIEW_SKIP
4181        if(m_iCount [yCbCr][typeIdx][classIdx] && !bRenderable)
4182#else
4183        if(m_iCount [yCbCr][typeIdx][classIdx])
4184#endif
4185        {
4186          m_iOffset[yCbCr][typeIdx][classIdx] = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[yCbCr][typeIdx][classIdx]<<g_uiBitIncrement) / (Double)(m_iCount [yCbCr][typeIdx][classIdx]<<m_uiSaoBitIncrease));
4187          m_iOffset[yCbCr][typeIdx][classIdx] = Clip3(-offsetTh, offsetTh, (Int)m_iOffset[yCbCr][typeIdx][classIdx]);
4188          if (typeIdx < 4)
4189          {
4190            if ( m_iOffset[yCbCr][typeIdx][classIdx]<0 && classIdx<3 )
4191            {
4192              m_iOffset[yCbCr][typeIdx][classIdx] = 0;
4193            }
4194            if ( m_iOffset[yCbCr][typeIdx][classIdx]>0 && classIdx>=3)
4195            {
4196              m_iOffset[yCbCr][typeIdx][classIdx] = 0;
4197            }
4198          }
4199          {
4200            //Clean up, best_q_offset.
4201            Int64 iIterOffset, iTempOffset;
4202            Int64 iTempDist, iTempRate;
4203            Double dTempCost, dTempMinCost;
4204            UInt uiLength, uiTemp;
4205
4206            iIterOffset = m_iOffset[yCbCr][typeIdx][classIdx];
4207            m_iOffset[yCbCr][typeIdx][classIdx] = 0;
4208            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.
4209
4210            while (iIterOffset != 0)
4211            {
4212              // Calculate the bits required for signalling the offset
4213              uiLength = 1;
4214              uiTemp = (UInt)((iIterOffset <= 0) ? ( (-iIterOffset<<1) + 1 ) : (iIterOffset<<1));
4215              while( 1 != uiTemp )
4216              {
4217                uiTemp >>= 1;
4218                uiLength += 2;
4219              }
4220              iTempRate = (uiLength >> 1) + ((uiLength+1) >> 1);
4221
4222              // Do the dequntization before distorion calculation
4223              iTempOffset    =  iIterOffset << m_uiSaoBitIncrease;
4224              iTempDist  = (( m_iCount [yCbCr][typeIdx][classIdx]*iTempOffset*iTempOffset-m_iOffsetOrg[yCbCr][typeIdx][classIdx]*iTempOffset*2 ) >> shift);
4225              dTempCost = ((Double)iTempDist + lambda * (Double) iTempRate);
4226              if(dTempCost < dTempMinCost)
4227              {
4228                dTempMinCost = dTempCost;
4229                m_iOffset[yCbCr][typeIdx][classIdx] = iIterOffset;
4230                if(typeIdx == SAO_BO)
4231                {
4232                  currentDistortionTableBo[classIdx-1] = (Int) iTempDist;
4233                  currentRdCostTableBo[classIdx-1] = dTempCost;
4234                }
4235              }
4236              iIterOffset = (iIterOffset > 0) ? (iIterOffset-1):(iIterOffset+1);
4237            }
4238          }
4239
4240        }
4241        else
4242        {
4243          m_iOffsetOrg[yCbCr][typeIdx][classIdx] = 0;
4244          m_iOffset[yCbCr][typeIdx][classIdx] = 0;
4245        }
4246        if( typeIdx != SAO_BO )
4247        {
4248          count     =  m_iCount [yCbCr][typeIdx][classIdx];
4249          offset    =  m_iOffset[yCbCr][typeIdx][classIdx] << m_uiSaoBitIncrease;
4250          offsetOrg =  m_iOffsetOrg[yCbCr][typeIdx][classIdx];
4251#if HHI_INTERVIEW_SKIP
4252          if (!bRenderable)
4253          {
4254          estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4255          }
4256#else
4257          estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4258#endif
4259          if (typeIdx < 4)
4260          {
4261            if (classIdx<3)
4262            {
4263              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx]);
4264            }
4265            else
4266            {
4267              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUvlc((Int)-m_iOffset[yCbCr][typeIdx][classIdx]);
4268            }
4269          }
4270          else
4271          {
4272            m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoSvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx]);
4273          }
4274        }
4275
4276      }
4277
4278      if( typeIdx == SAO_BO )
4279      {
4280        // Estimate Best Position
4281        Double currentRDCost = 0.0;
4282
4283        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
4284        {
4285          currentRDCost = 0.0;
4286          for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
4287          {
4288            currentRDCost += currentRdCostTableBo[uj];
4289          }
4290
4291          if( currentRDCost < bestRDCostTableBo)
4292          {
4293            bestRDCostTableBo = currentRDCost;
4294            bestClassTableBo  = i;
4295          }
4296        }
4297
4298        // Re code all Offsets
4299        // Code Center
4300        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoUflc( (UInt) (bestClassTableBo) );
4301
4302        for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
4303        {
4304          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoSvlc((Int)m_iOffset[yCbCr][typeIdx][classIdx+1]);
4305#if HHI_INTERVIEW_SKIP
4306          if (!bRenderable)
4307          {
4308          estDist += currentDistortionTableBo[classIdx];
4309          }
4310#else
4311          estDist += currentDistortionTableBo[classIdx];
4312#endif
4313        }
4314      }
4315
4316      m_iDist[yCbCr][typeIdx] = estDist;
4317      m_iRate[yCbCr][typeIdx] = m_pcEntropyCoder->getNumberOfWrittenBits();
4318
4319      m_dCost[yCbCr][typeIdx] = (Double)((Double)m_iDist[yCbCr][typeIdx] + lambda * (Double) m_iRate[yCbCr][typeIdx]);
4320
4321      if(m_dCost[yCbCr][typeIdx] < m_dCostPartBest[yCbCr])
4322      {
4323        m_iDistOrg [yCbCr] = (Int64)complexityCost;
4324        m_dCostPartBest[yCbCr] = m_dCost[yCbCr][typeIdx];
4325        m_iTypePartBest[yCbCr] = typeIdx;
4326      }
4327    }
4328    else
4329    {
4330      if(m_iDistOrg[yCbCr] < m_dCostPartBest[yCbCr])
4331      {
4332        m_dCostPartBest[yCbCr] = (Double) m_iDistOrg[yCbCr] + m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
4333        m_iTypePartBest[yCbCr] = -1;
4334      }
4335    }
4336  }
4337
4338  // merge left or merge up
4339
4340  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
4341  {
4342    saoLcuParamNeighbor = NULL;
4343    if (addrLeft>=0 && idxNeighbor ==0)
4344    {
4345      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
4346    }
4347    else if (addrUp>=0 && idxNeighbor ==1)
4348    {
4349      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
4350    }
4351    if (saoLcuParamNeighbor!=NULL)
4352    {
4353      if (saoLcuParamNeighbor->typeIdx>=0) //new
4354      {
4355        m_pcEntropyCoder->resetEntropy();
4356        m_pcEntropyCoder->resetBits();
4357
4358        estDist = 0;
4359        typeIdx = saoLcuParamNeighbor->typeIdx;
4360        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoFlag(1);
4361        if (saoLcuParamNeighbor->typeIdx == SAO_BO)
4362        {
4363          for(classIdx = saoLcuParamNeighbor->bandPosition+1; classIdx < saoLcuParamNeighbor->bandPosition+SAO_BO_LEN+1; classIdx++)
4364          {
4365            merge_iOffset[classIdx] = saoLcuParamNeighbor->offset[classIdx-1-saoLcuParamNeighbor->bandPosition];
4366
4367            count     =  m_iCount [yCbCr][typeIdx][classIdx];
4368            offset    =  merge_iOffset[classIdx];
4369            offsetOrg =  m_iOffsetOrg[yCbCr][typeIdx][classIdx];
4370#if HHI_INTERVIEW_SKIP
4371          if (!bRenderable)
4372          {
4373            estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4374          }
4375#else
4376          estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4377#endif
4378          }
4379        }
4380        else
4381        {
4382          for(classIdx=1; classIdx < m_iNumClass[typeIdx]+1; classIdx++)
4383          {
4384            merge_iOffset[classIdx] = saoLcuParamNeighbor->offset[classIdx-1];
4385
4386            count     =  m_iCount [yCbCr][typeIdx][classIdx];
4387            offset    =  merge_iOffset[classIdx];
4388            offsetOrg =  m_iOffsetOrg[yCbCr][typeIdx][classIdx];
4389#if HHI_INTERVIEW_SKIP
4390          if (!bRenderable)
4391          {
4392            estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4393          }
4394#else
4395          estDist   += (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
4396#endif
4397          }
4398        }
4399        merge_iDist = estDist;
4400        merge_iRate = m_pcEntropyCoder->getNumberOfWrittenBits();
4401        merge_dCost = (Double)((Double)merge_iDist + m_dLambdaLuma * (Double) merge_iRate) ;
4402
4403        if(merge_dCost < m_dCostPartBest[yCbCr])
4404        {
4405          m_iDistOrg [yCbCr] = (Int64)complexityCost;
4406          m_dCostPartBest[yCbCr] = merge_dCost;
4407          m_iTypePartBest[yCbCr] = typeIdx;
4408          if (typeIdx == SAO_BO)
4409          {
4410            bestClassTableBoMerge   = saoLcuParamNeighbor->bandPosition;
4411            for(classIdx = saoLcuParamNeighbor->bandPosition+1; classIdx < saoLcuParamNeighbor->bandPosition+SAO_BO_LEN+1; classIdx++)
4412            {
4413              m_iOffset[yCbCr][typeIdx][classIdx] = merge_iOffset[classIdx];
4414            }
4415          }
4416          else 
4417          {
4418            for(classIdx=1; classIdx < m_iNumClass[typeIdx]+1; classIdx++)
4419            {
4420              m_iOffset[yCbCr][typeIdx][classIdx] = merge_iOffset[classIdx];
4421            }
4422          }
4423          saoLcuParam->mergeUpFlag   = idxNeighbor;
4424          saoLcuParam->mergeLeftFlag = !idxNeighbor;
4425        }
4426      }
4427    }
4428  } 
4429
4430  saoLcuParam->typeIdx  = m_iTypePartBest[yCbCr];
4431  if (saoLcuParam->typeIdx != -1)
4432  {
4433    saoLcuParam->length = m_iNumClass[saoLcuParam->typeIdx];
4434    Int minIndex = 0;
4435    if( saoLcuParam->typeIdx == SAO_BO )
4436    {
4437      if ((saoLcuParam->mergeUpFlag )||(saoLcuParam->mergeLeftFlag)) 
4438      {
4439        saoLcuParam->bandPosition = bestClassTableBoMerge;
4440      }
4441      else
4442      {
4443        saoLcuParam->bandPosition = bestClassTableBo;
4444      }
4445      minIndex = saoLcuParam->bandPosition;
4446    }
4447    for (Int i=0; i< saoLcuParam->length ; i++)
4448    {
4449      saoLcuParam->offset[i] = (Int) m_iOffset[yCbCr][saoLcuParam->typeIdx][minIndex+i+1];
4450    }
4451  }
4452  else
4453  {
4454    saoLcuParam->length = 0;
4455  }
4456
4457  if (addrUp>=0)
4458  {
4459    if (saoLcuParam->typeIdx == -1 && saoParam->saoLcuParam[yCbCr][addrUp].typeIdx == -1)
4460    {
4461      saoLcuParam->mergeUpFlag   = 1;
4462      saoLcuParam->mergeLeftFlag = 0;
4463    }
4464  }
4465  if (addrLeft>=0)
4466  {
4467    if (saoLcuParam->typeIdx == -1 && saoParam->saoLcuParam[yCbCr][addrLeft].typeIdx == -1)
4468    {
4469      saoLcuParam->mergeUpFlag   = 0;
4470      saoLcuParam->mergeLeftFlag = 1;
4471    }
4472  }
4473
4474}
4475#endif
4476
4477
4478//! \}
Note: See TracBrowser for help on using the repository browser.