Ignore:
Timestamp:
1 Sep 2013, 22:47:26 (11 years ago)
Author:
tech
Message:

Merged DEV-2.0-dev0@604.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp

    r443 r608  
    44 * granted under this license. 
    55 *
    6  * Copyright (c) 2010-2012, ITU/ISO/IEC
     6 * Copyright (c) 2010-2013, ITU/ISO/IEC
    77 * All rights reserved.
    88 *
     
    3232 */
    3333
    34 /** \file     TEncSampleAdaptiveOffset.cpp
     34/**
     35 \file     TEncSampleAdaptiveOffset.cpp
    3536 \brief       estimation part of sample adaptive offset class
    3637 */
     
    4344//! \ingroup TLibEncoder
    4445//! \{
    45 #if LGE_SAO_MIGRATION_D0091
     46
    4647TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
    4748{
    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;
     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;
    6162#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;
     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;
    7071#endif
    7172}
    72 
    7373TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
    7474{
     
    8484// ====================================================================================================================
    8585
    86 inline 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
     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))));
    9489}
    9590
     
    9792 * \param  x
    9893 */
    99 inline 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 }
     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
    107100
    108101/** process SAO for one partition
     
    111104Void TEncSampleAdaptiveOffset::rdoSaoOnePart(SAOQTPart *psQTPart, Int iPartIdx, Double dLambda, Int yCbCr)
    112105{
    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     {
     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;
    137290        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 
     291          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
     292      }
    333293    }
    334294    else
    335295    {
    336         //     pOnePart->bEnableFlag = 0;
    337         pOnePart->iLength     = 0;
    338     }
     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        {
     302          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pOnePart->PartLevel][CI_TEMP_BEST] );
     303        }
     304      }
     305    }
     306  }
     307
     308  pOnePart->bProcessed = true;
     309  pOnePart->bSplit     = false;
     310  pOnePart->iMinDist   =        m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];
     311  pOnePart->iMinRate   = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);
     312  pOnePart->dMinCost   = pOnePart->iMinDist + dLambda * pOnePart->iMinRate;
     313  pOnePart->iBestType  = m_iTypePartBest[iPartIdx];
     314  if (pOnePart->iBestType != -1)
     315  {
     316    //     pOnePart->bEnableFlag =  1;
     317    pOnePart->iLength = m_iNumClass[pOnePart->iBestType];
     318    Int minIndex = 0;
     319    if( pOnePart->iBestType == SAO_BO )
     320    {
     321      pOnePart->subTypeIdx = bestClassTableBo;
     322      minIndex = pOnePart->subTypeIdx;
     323    }
     324    for (Int i=0; i< pOnePart->iLength ; i++)
     325    {
     326      pOnePart->iOffset[i] = (Int) m_iOffset[iPartIdx][pOnePart->iBestType][minIndex+i+1];
     327    }
     328
     329  }
     330  else
     331  {
     332    //     pOnePart->bEnableFlag = 0;
     333    pOnePart->iLength     = 0;
     334  }
    339335}
    340336
     
    343339Void TEncSampleAdaptiveOffset::disablePartTree(SAOQTPart *psQTPart, Int iPartIdx)
    344340{
    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     }
     341  SAOQTPart*  pOnePart= &(psQTPart[iPartIdx]);
     342  pOnePart->bSplit      = false;
     343  pOnePart->iLength     =  0;
     344  pOnePart->iBestType   = -1;
     345
     346  if (pOnePart->PartLevel < m_uiMaxSplitLevel)
     347  {
     348    for (Int i=0; i<NUM_DOWN_PART; i++)
     349    {
     350      disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
     351    }
     352  }
    357353}
    358354
     
    362358Void TEncSampleAdaptiveOffset::runQuadTreeDecision(SAOQTPart *psQTPart, Int iPartIdx, Double &dCostFinal, Int iMaxLevel, Double dLambda, Int yCbCr)
    363359{
    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             }
     360  SAOQTPart*  pOnePart = &(psQTPart[iPartIdx]);
     361
     362  UInt uiDepth = pOnePart->PartLevel;
     363  UInt uhNextDepth = uiDepth+1;
     364
     365  if (iPartIdx == 0)
     366  {
     367    dCostFinal = 0;
     368  }
     369
     370  //SAO for this part
     371  if(!pOnePart->bProcessed)
     372  {
     373    rdoSaoOnePart (psQTPart, iPartIdx, dLambda, yCbCr);
     374  }
     375
     376  //SAO for sub 4 parts
     377  if (pOnePart->PartLevel < iMaxLevel)
     378  {
     379    Double      dCostNotSplit = dLambda + pOnePart->dMinCost;
     380    Double      dCostSplit    = dLambda;
     381
     382    for (Int i=0; i< NUM_DOWN_PART ;i++)
     383    {
     384      if( m_bUseSBACRD ) 
     385      {
     386        if ( 0 == i) //initialize RD with previous depth buffer
     387        {
     388          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
    417389        }
    418390        else
    419391        {
    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         }
     392          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
     393        }
     394      } 
     395      runQuadTreeDecision(psQTPart, pOnePart->DownPartsIdx[i], dCostFinal, iMaxLevel, dLambda, yCbCr);
     396      dCostSplit += dCostFinal;
     397      if( m_bUseSBACRD )
     398      {
     399        m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_TEMP_BEST]);
     400      }
     401    }
     402
     403    if(dCostSplit < dCostNotSplit)
     404    {
     405      dCostFinal = dCostSplit;
     406      pOnePart->bSplit      = true;
     407      pOnePart->iLength     =  0;
     408      pOnePart->iBestType   = -1;
     409      if( m_bUseSBACRD )
     410      {
     411        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
     412      }
    431413    }
    432414    else
    433415    {
    434         dCostFinal = pOnePart->dMinCost;
    435     }
     416      dCostFinal = dCostNotSplit;
     417      pOnePart->bSplit = false;
     418      for (Int i=0; i<NUM_DOWN_PART; i++)
     419      {
     420        disablePartTree(psQTPart, pOnePart->DownPartsIdx[i]);
     421      }
     422      if( m_bUseSBACRD )
     423      {
     424        m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
     425      }
     426    }
     427  }
     428  else
     429  {
     430    dCostFinal = pOnePart->dMinCost;
     431  }
    436432}
    437433
     
    446442      if (m_iCount [i][j])
    447443      {
    448         delete [] m_iCount [i][j];
     444        delete [] m_iCount [i][j]; 
    449445      }
    450446      if (m_iOffset[i][j])
     
    454450      if (m_iOffsetOrg[i][j])
    455451      {
    456         delete [] m_iOffsetOrg[i][j];
     452        delete [] m_iOffsetOrg[i][j]; 
    457453      }
    458454    }
     
    463459    if (m_iDist[i])
    464460    {
    465       delete [] m_iDist[i];
     461      delete [] m_iDist[i]; 
    466462    }
    467463    if (m_dCost[i])
     
    471467    if (m_iCount [i])
    472468    {
    473       delete [] m_iCount [i];
     469      delete [] m_iCount [i]; 
    474470    }
    475471    if (m_iOffset[i])
     
    479475    if (m_iOffsetOrg[i])
    480476    {
    481       delete [] m_iOffsetOrg[i];
    482     }
     477      delete [] m_iOffsetOrg[i];
     478    }
     479
    483480  }
    484481  if (m_iDistOrg)
     
    528525        if (m_count_PreDblk [i][j][k])
    529526        {
    530           delete [] m_count_PreDblk [i][j][k];
     527          delete [] m_count_PreDblk [i][j][k]; 
    531528        }
    532529        if (m_offsetOrg_PreDblk[i][j][k])
     
    537534      if (m_count_PreDblk [i][j])
    538535      {
    539         delete [] m_count_PreDblk [i][j];
     536        delete [] m_count_PreDblk [i][j]; 
    540537      }
    541538      if (m_offsetOrg_PreDblk[i][j])
    542539      {
    543         delete [] m_offsetOrg_PreDblk[i][j];
     540        delete [] m_offsetOrg_PreDblk[i][j]; 
    544541      }
    545542    }
    546543    if (m_count_PreDblk [i])
    547544    {
    548       delete [] m_count_PreDblk [i];
     545      delete [] m_count_PreDblk [i]; 
    549546    }
    550547    if (m_offsetOrg_PreDblk[i])
    551548    {
    552       delete [] m_offsetOrg_PreDblk[i];
     549      delete [] m_offsetOrg_PreDblk[i]; 
    553550    }
    554551  }
     
    588585Void TEncSampleAdaptiveOffset::createEncBuffer()
    589586{
    590   m_iDistOrg = new Int64 [m_iNumTotalParts];
    591   m_dCostPartBest = new Double [m_iNumTotalParts];
    592   m_iTypePartBest = new Int [m_iNumTotalParts];
     587  m_iDistOrg = new Int64 [m_iNumTotalParts]; 
     588  m_dCostPartBest = new Double [m_iNumTotalParts]; 
     589  m_iTypePartBest = new Int [m_iNumTotalParts]; 
    593590
    594591  m_iRate = new Int64* [m_iNumTotalParts];
     
    603600  {
    604601    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];
     602    m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE]; 
     603    m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 
     604
     605    m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
     606    m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
     607    m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
    611608
    612609    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
    613610    {
    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];
     611      m_iCount [i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
     612      m_iOffset[i][j]   = new Int64 [MAX_NUM_SAO_CLASS]; 
     613      m_iOffsetOrg[i][j]= new Int64 [MAX_NUM_SAO_CLASS]; 
    617614    }
    618615  }
     
    627624    for (Int j=0;j<3;j++)
    628625    {
    629       m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
    630       m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
     626      m_count_PreDblk [i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
     627      m_offsetOrg_PreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE]; 
    631628
    632629      for (Int k=0;k<MAX_NUM_SAO_TYPE;k++)
    633630      {
    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];
     631        m_count_PreDblk [i][j][k]   = new Int64 [MAX_NUM_SAO_CLASS]; 
     632        m_offsetOrg_PreDblk[i][j][k]= new Int64 [MAX_NUM_SAO_CLASS]; 
    636633      }
    637634    }
     
    668665
    669666/** Start SAO encoder
    670  * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
     667 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder 
    671668 */
    672669Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
    673670{
    674   m_bUseSBACRD = true;
     671    m_bUseSBACRD = true;
    675672  m_pcPic = pcPic;
    676673  m_pcEntropyCoder = pcEntropyCoder;
     
    696693}
    697694
    698 inline int xSign(int x)
    699 {
    700   return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
     695inline Int xSign(Int x)
     696{
     697  return ((x >> 31) | ((Int)( (((UInt) -x)) >> 31)));
    701698}
    702699
     
    711708 * \param  pbBorderAvail availabilities of block border pixels
    712709 */
    713 Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail)
     710Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr)
    714711{
    715712  Int64 *stats, *count;
     
    718715  UInt edgeType;
    719716  Int x, y;
     717  Pel *pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo;
    720718
    721719  //--------- Band offset-----------//
     
    728726    for (x=0; x< width; x++)
    729727    {
    730       classIdx = m_lumaTableBo[pRec[x]];
     728      classIdx = pTableBo[pRec[x]];
    731729      if (classIdx)
    732730      {
    733         stats[classIdx] += (pOrg[x] - pRec[x]);
     731        stats[classIdx] += (pOrg[x] - pRec[x]); 
    734732        count[classIdx] ++;
    735733      }
     
    744742  pRec   = pRecStart;
    745743
     744
    746745  startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
    747746  endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
     
    751750    for (x=startX; x< endX; x++)
    752751    {
    753       signRight =  xSign(pRec[x] - pRec[x+1]);
     752      signRight =  xSign(pRec[x] - pRec[x+1]); 
    754753      edgeType =  signRight + signLeft + 2;
    755754      signLeft  = -signRight;
     
    784783    for (x=0; x< width; x++)
    785784    {
    786       signDown     =  xSign(pRec[x] - pRec[x+stride]);
     785      signDown     =  xSign(pRec[x] - pRec[x+stride]); 
    787786      edgeType    =  signDown + m_iUpBuff1[x] + 2;
    788787      m_iUpBuff1[x] = -signDown;
     
    843842      count[m_auiEoTable[edgeType]] ++;
    844843
    845       m_iUpBufft[x+1] = -signDown1;
     844      m_iUpBufft[x+1] = -signDown1; 
    846845    }
    847846    m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]);
     
    989988      posOffset = (yPos* stride) + xPos;
    990989
    991       calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail);
    992     }
    993   }
     990      calcSaoStatsBlock(pPicRec+ posOffset, pPicOrg+ posOffset, stride, ppStats, ppCount,width, height, pbBorderAvail, iYCbCr);
     991    }
     992  }
     993
    994994}
    995995
     
    10061006  Pel* pRec;
    10071007  Int iStride;
    1008   Int iLcuWidth = pTmpSPS->getMaxCUHeight();
    1009   Int iLcuHeight = pTmpSPS->getMaxCUWidth();
     1008  Int iLcuHeight = pTmpSPS->getMaxCUHeight();
     1009  Int iLcuWidth = pTmpSPS->getMaxCUWidth();
    10101010  UInt uiLPelX   = pTmpCu->getCUPelX();
    10111011  UInt uiTPelY   = pTmpCu->getCUPelY();
     
    10211021  Int iEndX;
    10221022  Int iEndY;
     1023  Pel* pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo;
    10231024
    10241025  Int iIsChroma = (iYCbCr!=0)? 1:0;
     
    10291030  }
    10301031
    1031 #if SAO_SKIP_RIGHT
    10321032  Int numSkipLineRight = iIsChroma? 3:5;
    10331033  if (m_saoLcuBasedOptimization == 0)
     
    10351035    numSkipLineRight = 0;
    10361036  }
    1037 #endif
    10381037
    10391038  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
     
    10651064    pRec = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr, iAddr);
    10661065
    1067 #if SAO_SKIP_RIGHT
    10681066    iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
    1069 #endif
    1070 
    10711067    iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight : iLcuHeight-numSkipLine;
    10721068    for (y=0; y<iEndY; y++)
    10731069    {
    1074 #if SAO_SKIP_RIGHT
    10751070      for (x=0; x<iEndX; x++)
    1076 #else
    1077       for (x=0; x<iLcuWidth; x++)
    1078 #endif
    1079       {
    1080         iClassIdx = m_lumaTableBo[pRec[x]];
     1071      {
     1072        iClassIdx = pTableBo[pRec[x]];
    10811073        if (iClassIdx)
    10821074        {
     
    11141106
    11151107      iStartX = (uiLPelX == 0) ? 1 : 0;
    1116 #if SAO_SKIP_RIGHT
    11171108      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
    1118 #else
    1119       iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
    1120 #endif
    11211109      for (y=0; y<iLcuHeight-numSkipLine; y++)
    11221110      {
     
    11501138
    11511139      iStartY = (uiTPelY == 0) ? 1 : 0;
    1152 #if SAO_SKIP_RIGHT
    11531140      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth : iLcuWidth-numSkipLineRight;
    1154 #endif
    11551141      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight-numSkipLine;
    11561142      if (uiTPelY == 0)
     
    11661152      for (y=iStartY; y<iEndY; y++)
    11671153      {
    1168 #if SAO_SKIP_RIGHT
    11691154        for (x=0; x<iEndX; x++)
    1170 #else
    1171         for (x=0; x<iLcuWidth; x++)
    1172 #endif
    11731155        {
    11741156          iSignDown     =  xSign(pRec[x] - pRec[x+iStride]);
     
    11971179
    11981180      iStartX = (uiLPelX == 0) ? 1 : 0;
    1199 #if SAO_SKIP_RIGHT
    12001181      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
    1201 #else
    1202       iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
    1203 #endif
    12041182
    12051183      iStartY = (uiTPelY == 0) ? 1 : 0;
     
    12491227
    12501228      iStartX = (uiLPelX == 0) ? 1 : 0;
    1251 #if SAO_SKIP_RIGHT
    12521229      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth-numSkipLineRight;
    1253 #else
    1254       iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
    1255 #endif
    12561230
    12571231      iStartY = (uiTPelY == 0) ? 1 : 0;
     
    12971271  Pel* pRec;
    12981272  Int stride;
    1299   Int lcuWidth = pTmpSPS->getMaxCUHeight();
    1300   Int lcuHeight = pTmpSPS->getMaxCUWidth();
     1273  Int lcuHeight = pTmpSPS->getMaxCUHeight();
     1274  Int lcuWidth = pTmpSPS->getMaxCUWidth();
    13011275  UInt rPelX;
    13021276  UInt bPelY;
     
    13231297  UInt lPelX, tPelY;
    13241298  TComDataCU *pTmpCu;
     1299  Pel* pTableBo;
    13251300
    13261301  for (idxY = 0; idxY< frameHeightInCU; idxY++)
     
    13281303    for (idxX = 0; idxX< frameWidthInCU; idxX++)
    13291304    {
    1330       lcuWidth = pTmpSPS->getMaxCUHeight();
    1331       lcuHeight = pTmpSPS->getMaxCUWidth();
     1305      lcuHeight = pTmpSPS->getMaxCUHeight();
     1306      lcuWidth = pTmpSPS->getMaxCUWidth();
    13321307      addr     = idxX  + frameWidthInCU*idxY;
    13331308      pTmpCu = pcPic->getCU(addr);
     
    13681343
    13691344        stride    =  (yCbCr == 0)? pcPic->getStride(): pcPic->getCStride();
     1345        pTableBo = (yCbCr==0)?m_lumaTableBo:m_chromaTableBo;
    13701346
    13711347        //if(iSaoType == BO)
     
    13901366              continue;
    13911367
    1392             classIdx = m_lumaTableBo[pRec[x]];
     1368            classIdx = pTableBo[pRec[x]];
    13931369            if (classIdx)
    13941370            {
     
    17031679#endif
    17041680{
    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;
     1681  if(m_bUseNIF)
     1682  {
     1683    m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
     1684  }
     1685
     1686  m_uiSaoBitIncreaseY = max(g_bitDepthY - 10, 0);
     1687  m_uiSaoBitIncreaseC = max(g_bitDepthC - 10, 0);
     1688  m_iOffsetThY = 1 << min(g_bitDepthY - 5, 5);
     1689  m_iOffsetThC = 1 << min(g_bitDepthC - 5, 5);
     1690  resetSAOParam(pcSaoParam);
     1691  if( !m_saoLcuBasedOptimization || !m_saoLcuBoundary )
     1692  {
     1693    resetStats();
     1694  }
     1695  Double dCostFinal = 0;
     1696  if ( m_saoLcuBasedOptimization)
     1697  {
     1698#if SAO_ENCODING_CHOICE
     1699    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma, depth);
    17111700#else
    1712     m_dLambdaLuma    = dLambda;
    1713     m_dLambdaChroma  = dLambda;
     1701    rdoSaoUnitAll(pcSaoParam, dLambdaLuma, dLambdaChroma);
    17141702#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 */
    1779 Void 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 */
    1835 Void 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
    1898 Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
    1899 #else
    1900 Void 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 */
    2155 inline 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 
    2200 inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
    2201 {
    2202     return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
    2203 }
    2204 inline 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 
    2241 Void 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 
    2380 Void 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
    2545 TEncSampleAdaptiveOffset::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 }
    2561 TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
    2562 {
    2563 
    2564 }
    2565 // ====================================================================================================================
    2566 // Constants
    2567 // ====================================================================================================================
    2568 
    2569 
    2570 // ====================================================================================================================
    2571 // Tables
    2572 // ====================================================================================================================
    2573 
    2574 inline 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  */
    2587 inline 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  */
    2601 Void 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  */
    2842 Void 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  */
    2861 Void 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  */
    2939 Void 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  */
    3045 Void 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  */
    3109 Void 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  */
    3132 Void TEncSampleAdaptiveOffset::endSaoEnc()
    3133 {
    3134   m_pcPic = NULL;
    3135   m_pcEntropyCoder = NULL;
    3136 }
    3137 
    3138 inline 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  */
    3153 Void 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  */
    3398 Void 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  */
    3448 Void 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  */
    3687 Void 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  */
    3756 Void 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  */
    3784 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
    3785 #else
    3786 /** Sample adaptive offset process
    3787  * \param dLambda
    3788  */
    3789 Void 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);
    38291703  }
    38301704  else
     
    38321706    pcSaoParam->bSaoFlag[0] = 1;
    38331707    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     }
     1708    dCostFinal = 0;
     1709    Double lambdaRdo =  dLambdaLuma;
     1710    resetStats();
     1711    getSaoStats(pcSaoParam->psSaoPart[0], 0);
     1712    runQuadTreeDecision(pcSaoParam->psSaoPart[0], 0, dCostFinal, m_uiMaxSplitLevel, lambdaRdo, 0);
     1713    pcSaoParam->bSaoFlag[0] = dCostFinal < 0 ? 1:0;
     1714    if(pcSaoParam->bSaoFlag[0])
     1715    {
     1716      convertQT2SaoUnit(pcSaoParam, 0, 0);
     1717      assignSaoUnitSyntax(pcSaoParam->saoLcuParam[0],  pcSaoParam->psSaoPart[0], pcSaoParam->oneUnitFlag[0], 0);
     1718    }
     1719  }
     1720  if (pcSaoParam->bSaoFlag[0])
     1721  {
     1722    processSaoUnitAll( pcSaoParam->saoLcuParam[0], pcSaoParam->oneUnitFlag[0], 0);
     1723  }
     1724  if (pcSaoParam->bSaoFlag[1])
     1725  {
     1726    processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);
     1727    processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);
    38591728  }
    38601729}
     
    38781747          countDiff += (saoUnitCurr->offset[i] != saoUnitCheck->offset[i]);
    38791748        }
    3880         countDiff += (saoUnitCurr->bandPosition != saoUnitCheck->bandPosition);
     1749        countDiff += (saoUnitCurr->subTypeIdx != saoUnitCheck->subTypeIdx);
    38811750        if (countDiff ==0)
    38821751        {
     
    39291798  {
    39301799    Int i,j, addr, addrUp, addrLeft,  idx, idxUp, idxLeft,  idxCount;
    3931     Int run;
    3932     Int runPartBeginAddr=0;
    3933     Int runPart;
    3934     Int runPartPrevious;
    39351800
    39361801    oneUnitFlag = 0;
     
    39421807    for (j=0;j<m_iNumCuInHeight;j++)
    39431808    {
    3944       run = 0;
    3945       runPartPrevious = -1;
    39461809      for (i=0;i<m_iNumCuInWidth;i++)
    39471810      {
     
    39791842          checkMerge(&saoLcuParam[addr], &saoLcuParam[addrLeft], 0);
    39801843        }
    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         }
    40211844      }
    40221845    }
     
    40281851 * \param lambdaChroma
    40291852 */
     1853#if SAO_ENCODING_CHOICE
     1854Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma, Int depth)
     1855#else
    40301856Void TEncSampleAdaptiveOffset::rdoSaoUnitAll(SAOParam *saoParam, Double lambda, Double lambdaChroma)
     1857#endif
    40311858{
    40321859
     
    40401867  Int addrLeft = -1;
    40411868  Int compIdx = 0;
    4042   Double lambdaComp;
     1869  SaoLcuParam mergeSaoParam[3][2];
     1870  Double compDistortion[3];
    40431871
    40441872  saoParam->bSaoFlag[0] = true;
    40451873  saoParam->bSaoFlag[1] = true;
    4046   saoParam->bSaoFlag[2] = true;
    40471874  saoParam->oneUnitFlag[0] = false;
    40481875  saoParam->oneUnitFlag[1] = false;
    40491876  saoParam->oneUnitFlag[2] = false;
    40501877
     1878#if SAO_ENCODING_CHOICE
     1879#if SAO_ENCODING_CHOICE_CHROMA
     1880  Int numNoSao[2];
     1881  numNoSao[0] = 0;// Luma
     1882  numNoSao[1] = 0;// Chroma
     1883  if( depth > 0 && m_depthSaoRate[0][depth-1] > SAO_ENCODING_RATE )
     1884  {
     1885    saoParam->bSaoFlag[0] = false;
     1886  }
     1887  if( depth > 0 && m_depthSaoRate[1][depth-1] > SAO_ENCODING_RATE_CHROMA )
     1888  {
     1889    saoParam->bSaoFlag[1] = false;
     1890  }
     1891#else
     1892  Int numNoSao = 0;
     1893
     1894  if( depth > 0 && m_depth0SaoRate > SAO_ENCODING_RATE )
     1895  {
     1896    saoParam->bSaoFlag[0] = false;
     1897    saoParam->bSaoFlag[1] = false;
     1898  }
     1899#endif
     1900#endif
    40511901
    40521902  for (idxY = 0; idxY< frameHeightInCU; idxY++)
     
    40571907      addrUp   = addr < frameWidthInCU ? -1:idxX   + frameWidthInCU*(idxY-1);
    40581908      addrLeft = idxX == 0               ? -1:idxX-1 + frameWidthInCU*idxY;
     1909      Int allowMergeLeft = 1;
     1910      Int allowMergeUp   = 1;
     1911      UInt rate;
     1912      Double bestCost, mergeCost;
     1913      if (idxX!=0)
     1914      {
     1915        // check tile id and slice id
     1916        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()))
     1917        {
     1918          allowMergeLeft = 0;
     1919        }
     1920      }
     1921      else
     1922      {
     1923        allowMergeLeft = 0;
     1924      }
     1925      if (idxY!=0)
     1926      {
     1927        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()))
     1928        {
     1929          allowMergeUp = 0;
     1930        }
     1931      }
     1932      else
     1933      {
     1934        allowMergeUp = 0;
     1935      }
     1936
     1937      compDistortion[0] = 0;
     1938      compDistortion[1] = 0;
     1939      compDistortion[2] = 0;
     1940      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
     1941      if (allowMergeLeft)
     1942      {
     1943        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
     1944      }
     1945      if (allowMergeUp)
     1946      {
     1947        m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
     1948      }
     1949      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
    40591950      // reset stats Y, Cb, Cr
    40601951      for ( compIdx=0;compIdx<3;compIdx++)
     
    40641955          for ( k=0;k< MAX_NUM_SAO_CLASS;k++)
    40651956          {
    4066             m_iCount    [compIdx][j][k] = 0;
    40671957            m_iOffset   [compIdx][j][k] = 0;
    4068             m_iOffsetOrg[compIdx][j][k] = 0;
     1958            if( m_saoLcuBasedOptimization && m_saoLcuBoundary ){
     1959              m_iCount    [compIdx][j][k] = m_count_PreDblk    [addr][compIdx][j][k];
     1960              m_iOffsetOrg[compIdx][j][k] = m_offsetOrg_PreDblk[addr][compIdx][j][k];
     1961            }
     1962            else
     1963            {
     1964              m_iCount    [compIdx][j][k] = 0;
     1965              m_iOffsetOrg[compIdx][j][k] = 0;
     1966            }
    40691967          } 
    40701968        }
    40711969        saoParam->saoLcuParam[compIdx][addr].typeIdx       =  -1;
    40721970        saoParam->saoLcuParam[compIdx][addr].mergeUpFlag   = 0;
    4073         saoParam->saoLcuParam[compIdx][addr].run           = 0;
    4074         saoParam->saoLcuParam[compIdx][addr].runDiff       = 0;
    40751971        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 )
     1972        saoParam->saoLcuParam[compIdx][addr].subTypeIdx    = 0;
     1973#if SAO_ENCODING_CHOICE
     1974  if( (compIdx ==0 && saoParam->bSaoFlag[0])|| (compIdx >0 && saoParam->bSaoFlag[1]) )
     1975#endif
     1976        {
     1977          calcSaoStatsCu(addr, compIdx,  compIdx);
     1978
     1979       }
     1980      }
     1981      saoComponentParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, 0,  lambda, &mergeSaoParam[0][0], &compDistortion[0]);
     1982      sao2ChromaParamDist(allowMergeLeft, allowMergeUp, saoParam, addr, addrUp, addrLeft, lambdaChroma, &mergeSaoParam[1][0], &mergeSaoParam[2][0], &compDistortion[0]);
     1983     if( saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] )
     1984      {
     1985        // Cost of new SAO_params
     1986        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
     1987        m_pcRDGoOnSbacCoder->resetBits();
     1988        if (allowMergeLeft)
     1989        {
     1990          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
     1991        }
     1992        if (allowMergeUp)
     1993        {
     1994          m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(0);
     1995        }
     1996        for ( compIdx=0;compIdx<3;compIdx++)
     1997        {
     1998        if( (compIdx ==0 && saoParam->bSaoFlag[0]) || (compIdx >0 && saoParam->bSaoFlag[1]))
    40841999          {
    4085             saoParam->bSaoFlag[compIdx] = false;
     2000           m_pcEntropyCoder->encodeSaoOffset(&saoParam->saoLcuParam[compIdx][addr], compIdx);
    40862001          }
    40872002        }
     2003
     2004        rate = m_pcEntropyCoder->getNumberOfWrittenBits();
     2005        bestCost = compDistortion[0] + (Double)rate;
     2006        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2007
     2008        // Cost of Merge
     2009        for(Int mergeUp=0; mergeUp<2; ++mergeUp)
     2010        {
     2011          if ( (allowMergeLeft && (mergeUp==0)) || (allowMergeUp && (mergeUp==1)) )
     2012          {
     2013            m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
     2014            m_pcRDGoOnSbacCoder->resetBits();
     2015            if (allowMergeLeft)
     2016            {
     2017              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1-mergeUp);
     2018            }
     2019            if ( allowMergeUp && (mergeUp==1) )
     2020            {
     2021              m_pcEntropyCoder->m_pcEntropyCoderIf->codeSaoMerge(1);
     2022            }
     2023
     2024            rate = m_pcEntropyCoder->getNumberOfWrittenBits();
     2025            mergeCost = compDistortion[mergeUp+1] + (Double)rate;
     2026            if (mergeCost < bestCost)
     2027            {
     2028              bestCost = mergeCost;
     2029              m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);             
     2030              for ( compIdx=0;compIdx<3;compIdx++)
     2031              {
     2032                mergeSaoParam[compIdx][mergeUp].mergeLeftFlag = 1-mergeUp;
     2033                mergeSaoParam[compIdx][mergeUp].mergeUpFlag = mergeUp;
     2034                if( (compIdx==0 && saoParam->bSaoFlag[0]) || (compIdx>0 && saoParam->bSaoFlag[1]))
     2035                {
     2036                  copySaoUnit(&saoParam->saoLcuParam[compIdx][addr], &mergeSaoParam[compIdx][mergeUp] );             
     2037                }
     2038              }
     2039            }
     2040          }
     2041        }
     2042#if SAO_ENCODING_CHOICE
     2043#if SAO_ENCODING_CHOICE_CHROMA
     2044if( saoParam->saoLcuParam[0][addr].typeIdx == -1)
     2045{
     2046  numNoSao[0]++;
     2047}
     2048if( saoParam->saoLcuParam[1][addr].typeIdx == -1)
     2049{
     2050  numNoSao[1]+=2;
     2051}
     2052#else
     2053        for ( compIdx=0;compIdx<3;compIdx++)
     2054        {
     2055          if( depth == 0 && saoParam->saoLcuParam[compIdx][addr].typeIdx == -1)
     2056          {
     2057            numNoSao++;
     2058          }
     2059        }
    40882060#endif
    4089       }
    4090     }
    4091   }
     2061#endif
     2062        m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2063        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
     2064      }
     2065    }
     2066  }
     2067#if SAO_ENCODING_CHOICE
     2068#if SAO_ENCODING_CHOICE_CHROMA
     2069  if( !saoParam->bSaoFlag[0])
     2070  {
     2071    m_depthSaoRate[0][depth] = 1.0;
     2072  }
     2073  else
     2074  {
     2075    m_depthSaoRate[0][depth] = numNoSao[0]/((Double) frameHeightInCU*frameWidthInCU);
     2076  }
     2077  if( !saoParam->bSaoFlag[1])
     2078  {
     2079    m_depthSaoRate[1][depth] = 1.0;
     2080  }
     2081  else
     2082  {
     2083    m_depthSaoRate[1][depth] = numNoSao[1]/((Double) frameHeightInCU*frameWidthInCU*2);
     2084  }
     2085#else
     2086  if( depth == 0)
     2087  {
     2088    // update SAO Rate
     2089    m_depth0SaoRate = numNoSao/((Double) frameHeightInCU*frameWidthInCU*3);
     2090  }
     2091#endif
     2092#endif
    40922093
    40932094}
     
    41002101 * \param lambda
    41012102 */
    4102 Void TEncSampleAdaptiveOffset::rdoSaoUnit(SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda)
     2103inline Int64 TEncSampleAdaptiveOffset::estSaoTypeDist(Int compIdx, Int typeIdx, Int shift, Double lambda, Int *currentDistortionTableBo, Double *currentRdCostTableBo)
     2104{
     2105  Int64 estDist = 0;
     2106  Int classIdx;
     2107  Int bitDepth = (compIdx==0) ? g_bitDepthY : g_bitDepthC;
     2108  Int saoBitIncrease = (compIdx==0) ? m_uiSaoBitIncreaseY : m_uiSaoBitIncreaseC;
     2109  Int saoOffsetTh = (compIdx==0) ? m_iOffsetThY : m_iOffsetThC;
     2110
     2111  for(classIdx=1; classIdx < ( (typeIdx < SAO_BO) ?  m_iNumClass[typeIdx]+1 : SAO_MAX_BO_CLASSES+1); classIdx++)
     2112  {
     2113    if( typeIdx == SAO_BO)
     2114    {
     2115      currentDistortionTableBo[classIdx-1] = 0;
     2116      currentRdCostTableBo[classIdx-1] = lambda;
     2117    }
     2118    if(m_iCount [compIdx][typeIdx][classIdx])
     2119    {
     2120      m_iOffset[compIdx][typeIdx][classIdx] = (Int64) xRoundIbdi(bitDepth, (Double)(m_iOffsetOrg[compIdx][typeIdx][classIdx]<<(bitDepth-8)) / (Double)(m_iCount [compIdx][typeIdx][classIdx]<<saoBitIncrease));
     2121      m_iOffset[compIdx][typeIdx][classIdx] = Clip3(-saoOffsetTh+1, saoOffsetTh-1, (Int)m_iOffset[compIdx][typeIdx][classIdx]);
     2122      if (typeIdx < 4)
     2123      {
     2124        if ( m_iOffset[compIdx][typeIdx][classIdx]<0 && classIdx<3 )
     2125        {
     2126          m_iOffset[compIdx][typeIdx][classIdx] = 0;
     2127        }
     2128        if ( m_iOffset[compIdx][typeIdx][classIdx]>0 && classIdx>=3)
     2129        {
     2130          m_iOffset[compIdx][typeIdx][classIdx] = 0;
     2131        }
     2132      }
     2133      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 );
     2134    }
     2135    else
     2136    {
     2137      m_iOffsetOrg[compIdx][typeIdx][classIdx] = 0;
     2138      m_iOffset[compIdx][typeIdx][classIdx] = 0;
     2139    }
     2140    if( typeIdx != SAO_BO )
     2141    {
     2142      estDist   += estSaoDist( m_iCount [compIdx][typeIdx][classIdx], m_iOffset[compIdx][typeIdx][classIdx] << saoBitIncrease, m_iOffsetOrg[compIdx][typeIdx][classIdx], shift);
     2143    }
     2144
     2145  }
     2146  return estDist;
     2147}
     2148
     2149inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 offsetOrg, Int shift)
     2150{
     2151  return (( count*offset*offset-offsetOrg*offset*2 ) >> shift);
     2152}
     2153inline 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 )
     2154{
     2155  //Clean up, best_q_offset.
     2156  Int64 iterOffset, tempOffset;
     2157  Int64 tempDist, tempRate;
     2158  Double tempCost, tempMinCost;
     2159  Int64 offsetOutput = 0;
     2160  iterOffset = offsetInput;
     2161  // 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.
     2162  tempMinCost = lambda;
     2163  while (iterOffset != 0)
     2164  {
     2165    // Calculate the bits required for signalling the offset
     2166    tempRate = (typeIdx == SAO_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
     2167    if (abs((Int)iterOffset)==offsetTh-1)
     2168    { 
     2169      tempRate --;
     2170    }
     2171    // Do the dequntization before distorion calculation
     2172    tempOffset  = iterOffset << bitIncrease;
     2173    tempDist    = estSaoDist( count, tempOffset, offsetOrg, shift);
     2174    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
     2175    if(tempCost < tempMinCost)
     2176    {
     2177      tempMinCost = tempCost;
     2178      offsetOutput = iterOffset;
     2179      if(typeIdx == SAO_BO)
     2180      {
     2181        currentDistortionTableBo[classIdx-1] = (Int) tempDist;
     2182        currentRdCostTableBo[classIdx-1] = tempCost;
     2183      }
     2184    }
     2185    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
     2186  }
     2187  return offsetOutput;
     2188}
     2189
     2190
     2191Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
    41032192{
    41042193  Int typeIdx;
    41052194
    41062195  Int64 estDist;
    4107   Int64 offsetOrg;
    4108   Int64 offset;
    4109   Int64 count;
    41102196  Int classIdx;
    4111   Int shift = g_uiBitIncrement << 1;
    4112   //   Double dAreaWeight =  0;
    4113   Double complexityCost = 0;
    4114   SaoLcuParam*  saoLcuParam = NULL;   
     2197  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8);
     2198  Int64 bestDist;
     2199
     2200  SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
    41152201  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;
     2202
     2203  resetSaoUnit(saoLcuParam);
     2204  resetSaoUnit(&compSaoParam[0]);
     2205  resetSaoUnit(&compSaoParam[1]);
     2206
     2207
     2208  Double dCostPartBest = MAX_DOUBLE;
    41332209
    41342210  Double  bestRDCostTableBo = MAX_DOUBLE;
     
    41362212  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
    41372213  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;
     2214
     2215
     2216  SaoLcuParam   saoLcuParamRdo;   
     2217  Double   estRate = 0;
     2218
     2219  resetSaoUnit(&saoLcuParamRdo);
     2220
     2221  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2222  m_pcRDGoOnSbacCoder->resetBits();
     2223 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
     2224 
     2225  dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ;
     2226  copySaoUnit(saoLcuParam, &saoLcuParamRdo );
     2227  bestDist = 0;
     2228 
     2229
     2230
     2231  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
     2232  {
     2233    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
     2234
     2235    if( typeIdx == SAO_BO )
     2236    {
     2237      // Estimate Best Position
     2238      Double currentRDCost = 0.0;
     2239
     2240      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
     2241      {
     2242        currentRDCost = 0.0;
     2243        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++)
     2244        {
     2245          currentRDCost += currentRdCostTableBo[uj];
     2246        }
     2247
     2248        if( currentRDCost < bestRDCostTableBo)
     2249        {
     2250          bestRDCostTableBo = currentRDCost;
     2251          bestClassTableBo  = i;
     2252        }
     2253      }
     2254
     2255      // Re code all Offsets
     2256      // Code Center
     2257      estDist = 0;
     2258      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
     2259      {
     2260        estDist += currentDistortionTableBo[classIdx];
     2261      }
     2262    }
     2263    resetSaoUnit(&saoLcuParamRdo);
     2264    saoLcuParamRdo.length = m_iNumClass[typeIdx];
     2265    saoLcuParamRdo.typeIdx = typeIdx;
     2266    saoLcuParamRdo.mergeLeftFlag = 0;
     2267    saoLcuParamRdo.mergeUpFlag   = 0;
     2268    saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
     2269    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
     2270    {
     2271      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
     2272    }
     2273    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2274    m_pcRDGoOnSbacCoder->resetBits();
     2275    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
     2276
     2277    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
     2278    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
     2279
     2280    if(m_dCost[yCbCr][typeIdx] < dCostPartBest)
     2281    {
     2282      dCostPartBest = m_dCost[yCbCr][typeIdx];
     2283      copySaoUnit(saoLcuParam, &saoLcuParamRdo );
     2284      bestDist = estDist;       
     2285    }
     2286  }
     2287  compDistortion[0] += ((Double)bestDist/lambda);
     2288  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2289 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
     2290  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
     2291
     2292
     2293  // merge left or merge up
     2294
     2295  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)
     2296  {
     2297    saoLcuParamNeighbor = NULL;
     2298    if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
     2299    {
     2300      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]);
     2301    }
     2302    else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
     2303    {
     2304      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]);
     2305    }
     2306    if (saoLcuParamNeighbor!=NULL)
     2307    {
     2308      estDist = 0;
     2309      typeIdx = saoLcuParamNeighbor->typeIdx;
     2310      if (typeIdx>=0)
     2311      {
     2312        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
     2313        Int   merge_iOffset;
     2314        for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
     2315        {
     2316          merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
     2317          estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
     2318        }
    41602319      }
    41612320      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
     2321      {
     2322        estDist = 0;
     2323      }
     2324
     2325      copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
     2326      compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
     2327      compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
     2328
     2329      compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
     2330    }
     2331  }
     2332}
     2333Void TEncSampleAdaptiveOffset::sao2ChromaParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Double lambda, SaoLcuParam *crSaoParam, SaoLcuParam *cbSaoParam, Double *distortion)
     2334{
     2335  Int typeIdx;
     2336
     2337  Int64 estDist[2];
     2338  Int classIdx;
     2339  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepthC-8);
     2340  Int64 bestDist = 0;
     2341
     2342  SaoLcuParam*  saoLcuParam[2] = {&(saoParam->saoLcuParam[1][addr]), &(saoParam->saoLcuParam[2][addr])};
     2343  SaoLcuParam*  saoLcuParamNeighbor[2] = {NULL, NULL};
     2344  SaoLcuParam*  saoMergeParam[2][2];
     2345  saoMergeParam[0][0] = &crSaoParam[0];
     2346  saoMergeParam[0][1] = &crSaoParam[1];
     2347  saoMergeParam[1][0] = &cbSaoParam[0];
     2348  saoMergeParam[1][1] = &cbSaoParam[1];
     2349
     2350  resetSaoUnit(saoLcuParam[0]);
     2351  resetSaoUnit(saoLcuParam[1]);
     2352  resetSaoUnit(saoMergeParam[0][0]);
     2353  resetSaoUnit(saoMergeParam[0][1]);
     2354  resetSaoUnit(saoMergeParam[1][0]);
     2355  resetSaoUnit(saoMergeParam[1][1]);
     2356
     2357
     2358  Double costPartBest = MAX_DOUBLE;
     2359
     2360  Double  bestRDCostTableBo;
     2361  Int     bestClassTableBo[2]    = {0, 0};
     2362  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
     2363  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];
     2364
     2365  SaoLcuParam   saoLcuParamRdo[2];   
     2366  Double   estRate = 0;
     2367
     2368  resetSaoUnit(&saoLcuParamRdo[0]);
     2369  resetSaoUnit(&saoLcuParamRdo[1]);
     2370
     2371  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2372  m_pcRDGoOnSbacCoder->resetBits();
     2373  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[0], 1);
     2374  m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[1], 2);
     2375 
     2376  costPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ;
     2377  copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
     2378  copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
     2379
     2380  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
     2381  {
     2382    if( typeIdx == SAO_BO )
     2383    {
     2384      // Estimate Best Position
     2385      for(Int compIdx = 0; compIdx < 2; compIdx++)
     2386      {
    42812387        Double currentRDCost = 0.0;
    4282 
     2388        bestRDCostTableBo = MAX_DOUBLE;
     2389        estDist[compIdx] = estSaoTypeDist(compIdx+1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
    42832390        for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
    42842391        {
     
    42922399          {
    42932400            bestRDCostTableBo = currentRDCost;
    4294             bestClassTableBo  = i;
     2401            bestClassTableBo[compIdx]  = i;
    42952402          }
    42962403        }
     
    42982405        // Re code all Offsets
    42992406        // 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)
     2407        estDist[compIdx] = 0;
     2408        for(classIdx = bestClassTableBo[compIdx]; classIdx < bestClassTableBo[compIdx]+SAO_BO_LEN; classIdx++)
     2409        {
     2410          estDist[compIdx] += currentDistortionTableBo[classIdx];
     2411        }
     2412      }
     2413    }
     2414    else
     2415    {
     2416      estDist[0] = estSaoTypeDist(1, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
     2417      estDist[1] = estSaoTypeDist(2, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);
     2418    }
     2419
     2420    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2421    m_pcRDGoOnSbacCoder->resetBits();
     2422
     2423    for(Int compIdx = 0; compIdx < 2; compIdx++)
     2424    {
     2425      resetSaoUnit(&saoLcuParamRdo[compIdx]);
     2426      saoLcuParamRdo[compIdx].length = m_iNumClass[typeIdx];
     2427      saoLcuParamRdo[compIdx].typeIdx = typeIdx;
     2428      saoLcuParamRdo[compIdx].mergeLeftFlag = 0;
     2429      saoLcuParamRdo[compIdx].mergeUpFlag   = 0;
     2430      saoLcuParamRdo[compIdx].subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo[compIdx] : 0;
     2431      for (classIdx = 0; classIdx < saoLcuParamRdo[compIdx].length; classIdx++)
     2432      {
     2433        saoLcuParamRdo[compIdx].offset[classIdx] = (Int)m_iOffset[compIdx+1][typeIdx][classIdx+saoLcuParamRdo[compIdx].subTypeIdx+1];
     2434      }
     2435
     2436      m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo[compIdx], compIdx+1);
     2437    }
     2438    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
     2439    m_dCost[1][typeIdx] = (Double)((Double)(estDist[0] + estDist[1])  + lambda * (Double) estRate);
     2440   
     2441    if(m_dCost[1][typeIdx] < costPartBest)
     2442    {
     2443      costPartBest = m_dCost[1][typeIdx];
     2444      copySaoUnit(saoLcuParam[0], &saoLcuParamRdo[0] );
     2445      copySaoUnit(saoLcuParam[1], &saoLcuParamRdo[1] );
     2446      bestDist = (estDist[0]+estDist[1]);       
     2447    }
     2448  }
     2449
     2450  distortion[0] += ((Double)bestDist/lambda);
     2451  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
     2452  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[0], 1);
     2453  m_pcEntropyCoder->encodeSaoOffset(saoLcuParam[1], 2);
     2454  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
     2455
     2456  // merge left or merge up
     2457
     2458  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)
     2459  {
     2460    for(Int compIdx = 0; compIdx < 2; compIdx++)
     2461    {
     2462      saoLcuParamNeighbor[compIdx] = NULL;
     2463      if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0)
     2464      {
     2465        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrLeft]);
     2466      }
     2467      else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1)
     2468      {
     2469        saoLcuParamNeighbor[compIdx] = &(saoParam->saoLcuParam[compIdx+1][addrUp]);
     2470      }
     2471      if (saoLcuParamNeighbor[compIdx]!=NULL)
     2472      {
     2473        estDist[compIdx] = 0;
     2474        typeIdx = saoLcuParamNeighbor[compIdx]->typeIdx;
     2475        if (typeIdx>=0)
     2476        {
     2477          Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor[compIdx]->subTypeIdx:0;
     2478          Int   merge_iOffset;
     2479          for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
    43072480          {
    4308           estDist += currentDistortionTableBo[classIdx];
     2481            merge_iOffset = saoLcuParamNeighbor[compIdx]->offset[classIdx];
     2482            estDist[compIdx]   += estSaoDist(m_iCount [compIdx+1][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[compIdx+1][typeIdx][classIdx+mergeBandPosition+1],  shift);
    43092483          }
    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           }
    43792484        }
    43802485        else
    43812486        {
    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     }
     2487          estDist[compIdx] = 0;
     2488        }
     2489
     2490        copySaoUnit(saoMergeParam[compIdx][idxNeighbor], saoLcuParamNeighbor[compIdx] );
     2491        saoMergeParam[compIdx][idxNeighbor]->mergeUpFlag   = idxNeighbor;
     2492        saoMergeParam[compIdx][idxNeighbor]->mergeLeftFlag = !idxNeighbor;
     2493        distortion[idxNeighbor+1] += ((Double)estDist[compIdx]/lambda);
     2494      }
     2495    }
    44282496  }
    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 
     2497}
    44772498
    44782499//! \}
Note: See TracChangeset for help on using the changeset viewer.