source: 3DVCSoftware/tags/HTM-DEV-0.1/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 324

Last change on this file since 324 was 324, checked in by tech, 11 years ago

Initial development version for update to latest HM version.
Includes MV-HEVC and basic extensions for 3D-HEVC.

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