Ignore:
Timestamp:
2 Jan 2014, 07:21:30 (11 years ago)
Author:
seregin
Message:

update to HM-12.1 base

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/SHM-4.1-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp

    r494 r532  
    4545//! \{
    4646
     47
     48#if HM_CLEANUP_SAO
     49
     50/** rounding with IBDI
     51 * \param  x
     52 */
     53inline Double xRoundIbdi2(Int bitDepth, Double x)
     54{
     55  return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))));
     56}
     57
     58inline Double xRoundIbdi(Int bitDepth, Double x)
     59{
     60  return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
     61}
     62
     63
     64TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
     65{
     66  m_pppcRDSbacCoder = NULL;           
     67  m_pcRDGoOnSbacCoder = NULL;
     68  m_pppcBinCoderCABAC = NULL;   
     69  m_statData = NULL;
     70#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     71  m_preDBFstatData = NULL;
     72#endif
     73}
     74
     75TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset()
     76{
     77  destroyEncData();
     78}
     79
     80#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     81Void TEncSampleAdaptiveOffset::createEncData(Bool isPreDBFSamplesUsed)
     82#else
     83Void TEncSampleAdaptiveOffset::createEncData()
     84#endif
     85{
     86
     87  //cabac coder for RDO
     88  m_pppcRDSbacCoder = new TEncSbac* [NUM_SAO_CABACSTATE_LABELS];
     89  m_pppcBinCoderCABAC = new TEncBinCABACCounter* [NUM_SAO_CABACSTATE_LABELS];
     90
     91  for(Int cs=0; cs < NUM_SAO_CABACSTATE_LABELS; cs++)
     92  {
     93    m_pppcRDSbacCoder[cs] = new TEncSbac;
     94    m_pppcBinCoderCABAC[cs] = new TEncBinCABACCounter;
     95    m_pppcRDSbacCoder   [cs]->init( m_pppcBinCoderCABAC [cs] );
     96  }
     97
     98
     99  //statistics
     100  m_statData = new SAOStatData**[m_numCTUsPic];
     101  for(Int i=0; i< m_numCTUsPic; i++)
     102  {
     103    m_statData[i] = new SAOStatData*[NUM_SAO_COMPONENTS];
     104    for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
     105    {
     106      m_statData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES];
     107    }
     108  }
     109#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     110  if(isPreDBFSamplesUsed)
     111  {
     112    m_preDBFstatData = new SAOStatData**[m_numCTUsPic];
     113    for(Int i=0; i< m_numCTUsPic; i++)
     114    {
     115      m_preDBFstatData[i] = new SAOStatData*[NUM_SAO_COMPONENTS];
     116      for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
     117      {
     118        m_preDBFstatData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES];
     119      }
     120    }
     121
     122  }
     123#endif
     124
     125#if SAO_ENCODING_CHOICE
     126  ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate));
     127#endif
     128
     129  for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
     130  {
     131    m_skipLinesR[SAO_Y ][typeIdc]= 5;
     132    m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
     133
     134    m_skipLinesB[SAO_Y ][typeIdc]= 4;
     135    m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
     136
     137#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     138    if(isPreDBFSamplesUsed)
     139    {
     140      switch(typeIdc)
     141      {
     142      case SAO_TYPE_EO_0:
     143        {
     144          m_skipLinesR[SAO_Y ][typeIdc]= 5;
     145          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
     146
     147          m_skipLinesB[SAO_Y ][typeIdc]= 3;
     148          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1;
     149        }
     150        break;
     151      case SAO_TYPE_EO_90:
     152        {
     153          m_skipLinesR[SAO_Y ][typeIdc]= 4;
     154          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2;
     155
     156          m_skipLinesB[SAO_Y ][typeIdc]= 4;
     157          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
     158        }
     159        break;
     160      case SAO_TYPE_EO_135:
     161      case SAO_TYPE_EO_45:
     162        {
     163          m_skipLinesR[SAO_Y ][typeIdc]= 5;
     164          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 3;
     165
     166          m_skipLinesB[SAO_Y ][typeIdc]= 4;
     167          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 2;
     168        }
     169        break;
     170      case SAO_TYPE_BO:
     171        {
     172          m_skipLinesR[SAO_Y ][typeIdc]= 4;
     173          m_skipLinesR[SAO_Cb][typeIdc]= m_skipLinesR[SAO_Cr][typeIdc]= 2;
     174
     175          m_skipLinesB[SAO_Y ][typeIdc]= 3;
     176          m_skipLinesB[SAO_Cb][typeIdc]= m_skipLinesB[SAO_Cr][typeIdc]= 1;
     177        }
     178        break;
     179      default:
     180        {
     181          printf("Not a supported type");
     182          assert(0);
     183          exit(-1);
     184        }
     185      }
     186    }
     187#endif   
     188  }
     189
     190}
     191
     192Void TEncSampleAdaptiveOffset::destroyEncData()
     193{
     194  if(m_pppcRDSbacCoder != NULL)
     195  {
     196    for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
     197    {
     198      delete m_pppcRDSbacCoder[cs];
     199    }
     200    delete[] m_pppcRDSbacCoder; m_pppcRDSbacCoder = NULL;
     201  }
     202
     203  if(m_pppcBinCoderCABAC != NULL)
     204  {
     205    for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ )
     206    {
     207      delete m_pppcBinCoderCABAC[cs];
     208    }
     209    delete[] m_pppcBinCoderCABAC; m_pppcBinCoderCABAC = NULL;
     210  }
     211
     212  if(m_statData != NULL)
     213  {
     214    for(Int i=0; i< m_numCTUsPic; i++)
     215    {
     216      for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
     217      {
     218        delete[] m_statData[i][compIdx];
     219      }
     220      delete[] m_statData[i];
     221    }
     222    delete[] m_statData; m_statData = NULL;
     223  }
     224#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     225  if(m_preDBFstatData != NULL)
     226  {
     227    for(Int i=0; i< m_numCTUsPic; i++)
     228    {
     229      for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
     230      {
     231        delete[] m_preDBFstatData[i][compIdx];
     232      }
     233      delete[] m_preDBFstatData[i];
     234    }
     235    delete[] m_preDBFstatData; m_preDBFstatData = NULL;
     236  }
     237
     238#endif
     239}
     240
     241Void TEncSampleAdaptiveOffset::initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice)
     242{
     243  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
     244  m_pcRDGoOnSbacCoder->setSlice(pcSlice);
     245  m_pcRDGoOnSbacCoder->resetEntropy();
     246  m_pcRDGoOnSbacCoder->resetBits();
     247
     248  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[SAO_CABACSTATE_PIC_INIT]);
     249}
     250
     251
     252
     253Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas
     254#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     255                                         , Bool isPreDBFSamplesUsed
     256#endif
     257                                          )
     258{
     259  TComPicYuv* orgYuv= pPic->getPicYuvOrg();
     260  TComPicYuv* resYuv= pPic->getPicYuvRec();
     261  m_labmda[SAO_Y]= lambdas[0]; m_labmda[SAO_Cb]= lambdas[1]; m_labmda[SAO_Cr]= lambdas[2];
     262  TComPicYuv* srcYuv = m_tempPicYuv;
     263  resYuv->copyToPic(srcYuv);
     264  srcYuv->setBorderExtension(false);
     265  srcYuv->extendPicBorder();
     266
     267  //collect statistics
     268  getStatistics(m_statData, orgYuv, srcYuv, pPic);
     269#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     270  if(isPreDBFSamplesUsed)
     271  {
     272    addPreDBFStatistics(m_statData);
     273  }
     274#endif
     275  //slice on/off
     276  decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth());
     277
     278  //block on/off
     279  SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters
     280  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam());
     281  delete[] reconParams;
     282
     283}
     284
     285#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     286Void TEncSampleAdaptiveOffset::getPreDBFStatistics(TComPic* pPic)
     287{
     288  getStatistics(m_preDBFstatData, pPic->getPicYuvOrg(), pPic->getPicYuvRec(), pPic, true);
     289}
     290
     291Void TEncSampleAdaptiveOffset::addPreDBFStatistics(SAOStatData*** blkStats)
     292{
     293  for(Int n=0; n< m_numCTUsPic; n++)
     294  {
     295    for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
     296    {
     297      for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
     298      {
     299        blkStats[n][compIdx][typeIdc] += m_preDBFstatData[n][compIdx][typeIdc];
     300      }
     301    }
     302  }
     303}
     304
     305#endif
     306
     307Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic
     308#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     309                          , Bool isCalculatePreDeblockSamples
     310#endif
     311                          )
     312{
     313  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
     314
     315  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
     316  {
     317    Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
     318    Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
     319    Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
     320    Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
     321
     322    pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
     323
     324    //NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities.
     325    //For simplicity, here only picture boundaries are considered.
     326
     327    isRightAvail      = (xPos + m_maxCUWidth  < m_picWidth );
     328    isBelowAvail      = (yPos + m_maxCUHeight < m_picHeight);
     329    isBelowRightAvail = (isRightAvail && isBelowAvail);
     330    isBelowLeftAvail  = ((xPos > 0) && (isBelowAvail));
     331    isAboveRightAvail = ((yPos > 0) && (isRightAvail));
     332
     333    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
     334    {
     335      Bool isLuma     = (compIdx == SAO_Y);
     336      Int  formatShift= isLuma?0:1;
     337
     338      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
     339      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
     340
     341      Int  orgStride  = isLuma?orgYuv->getStride():orgYuv->getCStride();
     342      Pel* orgBlk     = getPicBuf(orgYuv, compIdx)+ (yPos >> formatShift)*orgStride+ (xPos >> formatShift);
     343
     344      getBlkStats(compIdx, blkStats[ctu][compIdx] 
     345                , srcBlk, orgBlk, srcStride, orgStride, (width  >> formatShift), (height >> formatShift)
     346                , isLeftAvail,  isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail, isBelowLeftAvail, isBelowRightAvail
     347#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     348                , isCalculatePreDeblockSamples
     349#endif
     350                );
     351
     352    }
     353  }
     354}
     355
     356Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer)
     357{
     358  //decide sliceEnabled[compIdx]
     359  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
     360  {
     361    // reset flags & counters
     362    sliceEnabled[compIdx] = true;
     363
     364#if SAO_ENCODING_CHOICE
     365#if SAO_ENCODING_CHOICE_CHROMA
     366    // decide slice-level on/off based on previous results
     367    if( (picTempLayer > 0)
     368      && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==SAO_Y) ? SAO_ENCODING_RATE : SAO_ENCODING_RATE_CHROMA)) )
     369    {
     370      sliceEnabled[compIdx] = false;
     371    }
     372#else
     373    // decide slice-level on/off based on previous results
     374    if( (picTempLayer > 0)
     375      && (m_saoDisabledRate[SAO_Y][0] > SAO_ENCODING_RATE) )
     376    {
     377      sliceEnabled[compIdx] = false;
     378    }
     379#endif
     380#endif
     381  }
     382}
     383
     384Int64 TEncSampleAdaptiveOffset::getDistortion(Int ctu, Int compIdx, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData)
     385{
     386  Int64 dist=0;
     387  Int inputBitDepth    = (compIdx == SAO_Y) ? g_bitDepthY : g_bitDepthC ;
     388  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(inputBitDepth-8);
     389
     390  switch(typeIdc)
     391  {
     392    case SAO_TYPE_EO_0:
     393    case SAO_TYPE_EO_90:
     394    case SAO_TYPE_EO_135:
     395    case SAO_TYPE_EO_45:
     396      {
     397        for (Int offsetIdx=0; offsetIdx<NUM_SAO_EO_CLASSES; offsetIdx++)
     398        {
     399          dist += estSaoDist( statData.count[offsetIdx], invQuantOffset[offsetIdx], statData.diff[offsetIdx], shift);
     400        }       
     401      }
     402      break;
     403    case SAO_TYPE_BO:
     404      {
     405        for (Int offsetIdx=typeAuxInfo; offsetIdx<typeAuxInfo+4; offsetIdx++)
     406        {
     407          Int bandIdx = offsetIdx % NUM_SAO_BO_CLASSES ;
     408          dist += estSaoDist( statData.count[bandIdx], invQuantOffset[bandIdx], statData.diff[bandIdx], shift);
     409        }
     410      }
     411      break;
     412    default:
     413      {
     414        printf("Not a supported type");
     415        assert(0);
     416        exit(-1);
     417      }
     418  }
     419
     420  return dist;
     421}
     422
     423inline Int64 TEncSampleAdaptiveOffset::estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift)
     424{
     425  return (( count*offset*offset-diffSum*offset*2 ) >> shift);
     426}
     427
     428
     429inline Int TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Int classIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh )
     430{
     431  Int iterOffset, tempOffset;
     432  Int64 tempDist, tempRate;
     433  Double tempCost, tempMinCost;
     434  Int offsetOutput = 0;
     435  iterOffset = offsetInput;
     436  // 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.
     437  tempMinCost = lambda;
     438  while (iterOffset != 0)
     439  {
     440    // Calculate the bits required for signaling the offset
     441    tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1);
     442    if (abs((Int)iterOffset)==offsetTh) //inclusive
     443    { 
     444      tempRate --;
     445    }
     446    // Do the dequantization before distortion calculation
     447    tempOffset  = iterOffset << bitIncrease;
     448    tempDist    = estSaoDist( count, tempOffset, diffSum, shift);
     449    tempCost    = ((Double)tempDist + lambda * (Double) tempRate);
     450    if(tempCost < tempMinCost)
     451    {
     452      tempMinCost = tempCost;
     453      offsetOutput = iterOffset;
     454      bestDist = tempDist;
     455      bestCost = tempCost;
     456    }
     457    iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1);
     458  }
     459  return offsetOutput;
     460}
     461
     462
     463Void TEncSampleAdaptiveOffset::deriveOffsets(Int ctu, Int compIdx, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo)
     464{
     465  Int bitDepth = (compIdx== SAO_Y) ? g_bitDepthY : g_bitDepthC;
     466  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8);
     467  Int offsetTh = g_saoMaxOffsetQVal[compIdx];  //inclusive
     468
     469  ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
     470
     471  //derive initial offsets
     472  Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES);
     473  for(Int classIdx=0; classIdx< numClasses; classIdx++)
     474  {
     475    if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN)  )
     476    {
     477      continue; //offset will be zero
     478    }
     479
     480    if(statData.count[classIdx] == 0)
     481    {
     482      continue; //offset will be zero
     483    }
     484
     485    quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8))
     486                                                                  /
     487                                                          (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx])
     488                                               );
     489    quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]);
     490  }
     491
     492  // adjust offsets
     493  switch(typeIdc)
     494  {
     495    case SAO_TYPE_EO_0:
     496    case SAO_TYPE_EO_90:
     497    case SAO_TYPE_EO_135:
     498    case SAO_TYPE_EO_45:
     499      {
     500        Int64 classDist;
     501        Double classCost;
     502        for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++) 
     503        {         
     504          if(classIdx==SAO_CLASS_EO_FULL_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
     505          if(classIdx==SAO_CLASS_EO_HALF_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
     506          if(classIdx==SAO_CLASS_EO_HALF_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
     507          if(classIdx==SAO_CLASS_EO_FULL_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
     508
     509          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
     510          {
     511            quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh );
     512          }
     513        }
     514     
     515        typeAuxInfo =0;
     516      }
     517      break;
     518    case SAO_TYPE_BO:
     519      {
     520        Int64  distBOClasses[NUM_SAO_BO_CLASSES];
     521        Double costBOClasses[NUM_SAO_BO_CLASSES];
     522        ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES);
     523        for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++)
     524        {         
     525          costBOClasses[classIdx]= m_labmda[compIdx];
     526          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
     527          {
     528            quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_labmda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], distBOClasses[classIdx], costBOClasses[classIdx], offsetTh );
     529          }
     530        }
     531
     532        //decide the starting band index
     533        Double minCost = MAX_DOUBLE, cost;
     534        for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++)
     535        {
     536          cost  = costBOClasses[band  ];
     537          cost += costBOClasses[band+1];
     538          cost += costBOClasses[band+2];
     539          cost += costBOClasses[band+3];
     540
     541          if(cost < minCost)
     542          {
     543            minCost = cost;
     544            typeAuxInfo = band;
     545          }
     546        }
     547        //clear those unused classes
     548        Int clearQuantOffset[NUM_SAO_BO_CLASSES];
     549        ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES);
     550        for(Int i=0; i< 4; i++)
     551        {
     552          Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES;
     553          clearQuantOffset[band] = quantOffsets[band];
     554        }
     555        ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES);       
     556      }
     557      break;
     558    default:
     559      {
     560        printf("Not a supported type");
     561        assert(0);
     562        exit(-1);
     563      }
     564
     565  }
     566
     567
     568}
     569
     570
     571Void TEncSampleAdaptiveOffset::deriveModeNewRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
     572{
     573  Double minCost, cost;
     574  Int rate, minRate;
     575  Int64 dist[NUM_SAO_COMPONENTS], modeDist[NUM_SAO_COMPONENTS];
     576  SAOOffset testOffset[NUM_SAO_COMPONENTS];
     577  Int compIdx;
     578  Int invQuantOffset[MAX_NUM_SAO_CLASSES];
     579
     580  modeDist[SAO_Y]= modeDist[SAO_Cb] = modeDist[SAO_Cr] = 0;
     581
     582  //pre-encode merge flags
     583  modeParam[SAO_Y ].modeIdc = SAO_MODE_OFF;
     584  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
     585  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true);
     586  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
     587
     588  //------ luma --------//
     589  compIdx = SAO_Y;
     590  //"off" case as initial cost
     591  modeParam[compIdx].modeIdc = SAO_MODE_OFF;
     592  m_pcRDGoOnSbacCoder->resetBits();
     593  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx]);
     594  minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     595  modeDist[compIdx] = 0;
     596  minCost= m_labmda[compIdx]*((Double)minRate);
     597  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
     598  if(sliceEnabled[compIdx])
     599  {
     600    for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
     601    {
     602      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
     603      testOffset[compIdx].typeIdc = typeIdc;
     604
     605      //derive coded offset
     606      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
     607
     608      //inversed quantized offsets
     609      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
     610
     611      //get distortion
     612      dist[compIdx] = getDistortion(ctu, compIdx, testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
     613
     614      //get rate
     615      m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
     616      m_pcRDGoOnSbacCoder->resetBits();
     617      m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx]);
     618      rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     619      cost = (Double)dist[compIdx] + m_labmda[compIdx]*((Double)rate);
     620      if(cost < minCost)
     621      {
     622        minCost = cost;
     623        minRate = rate;
     624        modeDist[compIdx] = dist[compIdx];
     625        modeParam[compIdx]= testOffset[compIdx];
     626        m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
     627      }
     628    }
     629  }
     630  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
     631  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
     632
     633  //------ chroma --------//
     634  assert(m_labmda[SAO_Cb] == m_labmda[SAO_Cr]);
     635  Double chromaLambda = m_labmda[SAO_Cb];
     636  //"off" case as initial cost
     637  m_pcRDGoOnSbacCoder->resetBits();
     638  modeParam[SAO_Cb].modeIdc = SAO_MODE_OFF;
     639  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, modeParam[SAO_Cb], sliceEnabled[SAO_Cb]);
     640  modeParam[SAO_Cr].modeIdc = SAO_MODE_OFF;
     641  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, modeParam[SAO_Cr], sliceEnabled[SAO_Cr]);
     642  minRate= m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     643  modeDist[SAO_Cb] = modeDist[SAO_Cr]= 0;
     644  minCost= chromaLambda*((Double)minRate);
     645
     646  //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function
     647
     648  for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
     649  {
     650    for(compIdx= SAO_Cb; compIdx< NUM_SAO_COMPONENTS; compIdx++)
     651    {
     652      if(!sliceEnabled[compIdx])
     653      {
     654        testOffset[compIdx].modeIdc = SAO_MODE_OFF;
     655        dist[compIdx]= 0;
     656        continue;
     657      }
     658      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
     659      testOffset[compIdx].typeIdc = typeIdc;
     660
     661      //derive offset & get distortion
     662      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
     663      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
     664      dist[compIdx]= getDistortion(ctu, compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
     665    }
     666
     667    //get rate
     668    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
     669    m_pcRDGoOnSbacCoder->resetBits();
     670    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cb, testOffset[SAO_Cb], sliceEnabled[SAO_Cb]);
     671    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(SAO_Cr, testOffset[SAO_Cr], sliceEnabled[SAO_Cr]);
     672    rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     673
     674    cost = (Double)(dist[SAO_Cb]+ dist[SAO_Cr]) + chromaLambda*((Double)rate);
     675    if(cost < minCost)
     676    {
     677      minCost = cost;
     678      minRate = rate;
     679      modeDist[SAO_Cb] = dist[SAO_Cb];
     680      modeDist[SAO_Cr] = dist[SAO_Cr];
     681      modeParam[SAO_Cb]= testOffset[SAO_Cb];
     682      modeParam[SAO_Cr]= testOffset[SAO_Cr];
     683    }
     684  }
     685
     686
     687  //----- re-gen rate & normalized cost----//
     688  modeNormCost  = (Double)modeDist[SAO_Y]/m_labmda[SAO_Y];
     689  modeNormCost += (Double)(modeDist[SAO_Cb]+ modeDist[SAO_Cr])/chromaLambda;
     690  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
     691  m_pcRDGoOnSbacCoder->resetBits();
     692  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
     693  modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     694
     695}
     696
     697Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
     698{
     699  Int mergeListSize = (Int)mergeList.size();
     700  modeNormCost = MAX_DOUBLE;
     701
     702  Double cost;
     703  SAOBlkParam testBlkParam;
     704
     705  for(Int mergeType=0; mergeType< mergeListSize; mergeType++)
     706  {
     707    if(mergeList[mergeType] == NULL)
     708    {
     709      continue;
     710    }
     711
     712    testBlkParam = *(mergeList[mergeType]);
     713    //normalized distortion
     714    Double normDist=0;
     715    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
     716    {
     717      testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE;
     718      testBlkParam[compIdx].typeIdc = mergeType;
     719
     720      SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx];
     721
     722      if( mergedOffsetParam.modeIdc != SAO_MODE_OFF)
     723      {
     724        //offsets have been reconstructed. Don't call inversed quantization function.
     725        normDist += (((Double)getDistortion(ctu, compIdx, mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctu][compIdx][mergedOffsetParam.typeIdc]))
     726                       /m_labmda[compIdx]
     727                    );
     728      }
     729
     730    }
     731
     732    //rate
     733    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
     734    m_pcRDGoOnSbacCoder->resetBits();
     735    m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
     736    Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
     737
     738    cost = normDist+(Double)rate;
     739
     740    if(cost < modeNormCost)
     741    {
     742      modeNormCost = cost;
     743      modeParam    = testBlkParam;
     744      m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
     745    }
     746  }
     747
     748  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
     749
     750
     751}
     752
     753Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams)
     754{
     755  Bool isAllBlksDisabled = false;
     756  if(!sliceEnabled[SAO_Y] && !sliceEnabled[SAO_Cb] && !sliceEnabled[SAO_Cr])
     757  {
     758    isAllBlksDisabled = true;
     759  }
     760
     761  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]);
     762
     763  SAOBlkParam modeParam;
     764  Double minCost, modeCost;
     765
     766  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
     767  {
     768    if(isAllBlksDisabled)
     769    {
     770      codedParams[ctu].reset();
     771      continue;
     772    }
     773
     774    m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]);
     775
     776    //get merge list
     777    std::vector<SAOBlkParam*> mergeList;
     778    getMergeList(pic, ctu, reconParams, mergeList);
     779
     780    minCost = MAX_DOUBLE;
     781    for(Int mode=0; mode < NUM_SAO_MODES; mode++)
     782    {
     783      switch(mode)
     784      {
     785      case SAO_MODE_OFF:
     786        {
     787          continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case.
     788        }
     789        break;
     790      case SAO_MODE_NEW:
     791        {
     792          deriveModeNewRDO(ctu, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
     793
     794        }
     795        break;
     796      case SAO_MODE_MERGE:
     797        {
     798          deriveModeMergeRDO(ctu, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
     799        }
     800        break;
     801      default:
     802        {
     803          printf("Not a supported SAO mode\n");
     804          assert(0);
     805          exit(-1);
     806        }
     807      }
     808
     809      if(modeCost < minCost)
     810      {
     811        minCost = modeCost;
     812        codedParams[ctu] = modeParam;
     813        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
     814
     815      }
     816    } //mode
     817    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
     818
     819    //apply reconstructed offsets
     820    reconParams[ctu] = codedParams[ctu];
     821    reconstructBlkSAOParam(reconParams[ctu], mergeList);
     822    offsetCTU(ctu, srcYuv, resYuv, reconParams[ctu], pic);
     823  } //ctu
     824
     825#if SAO_ENCODING_CHOICE
     826  Int picTempLayer = pic->getSlice(0)->getDepth();
     827  Int numLcusForSAOOff[NUM_SAO_COMPONENTS];
     828  numLcusForSAOOff[SAO_Y ] = numLcusForSAOOff[SAO_Cb]= numLcusForSAOOff[SAO_Cr]= 0;
     829
     830  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
     831  {
     832    for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
     833    {
     834      if( reconParams[ctu][compIdx].modeIdc == SAO_MODE_OFF)
     835      {
     836        numLcusForSAOOff[compIdx]++;
     837      }
     838    }
     839  }
     840#if SAO_ENCODING_CHOICE_CHROMA
     841  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
     842  {
     843    m_saoDisabledRate[compIdx][picTempLayer] = (Double)numLcusForSAOOff[compIdx]/(Double)m_numCTUsPic;
     844  }
     845#else
     846  if (picTempLayer == 0)
     847  {
     848    m_saoDisabledRate[SAO_Y][0] = (Double)(numLcusForSAOOff[SAO_Y]+numLcusForSAOOff[SAO_Cb]+numLcusForSAOOff[SAO_Cr])/(Double)(m_numCTUsPic*3);
     849  }
     850#endif                                             
     851#endif
     852}
     853
     854
     855Void TEncSampleAdaptiveOffset::getBlkStats(Int compIdx, SAOStatData* statsDataTypes 
     856                        , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height
     857                        , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail
     858#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     859                        , Bool isCalculatePreDeblockSamples
     860#endif
     861                        )
     862{
     863  if(m_lineBufWidth != m_maxCUWidth)
     864  {
     865    m_lineBufWidth = m_maxCUWidth;
     866
     867    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
     868    m_signLineBuf1 = new Char[m_lineBufWidth+1];
     869
     870    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
     871    m_signLineBuf2 = new Char[m_lineBufWidth+1];
     872  }
     873
     874  Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;
     875  Char signLeft, signRight, signDown;
     876  Int64 *diff, *count;
     877  Pel *srcLine, *orgLine;
     878  Int* skipLinesR = m_skipLinesR[compIdx];
     879  Int* skipLinesB = m_skipLinesB[compIdx];
     880
     881  for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++)
     882  {
     883    SAOStatData& statsData= statsDataTypes[typeIdx];
     884    statsData.reset();
     885
     886    srcLine = srcBlk;
     887    orgLine = orgBlk;
     888    diff    = statsData.diff;
     889    count   = statsData.count;
     890    switch(typeIdx)
     891    {
     892    case SAO_TYPE_EO_0:
     893      {
     894        diff +=2;
     895        count+=2;
     896        endY   = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height;
     897#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     898        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
     899                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
     900                                                 ;
     901#else
     902        startX = isLeftAvail ? 0 : 1;
     903#endif
     904#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     905        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
     906                                                 : (isRightAvail ? width : (width - 1))
     907                                                 ;
     908#else
     909        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
     910#endif
     911        for (y=0; y<endY; y++)
     912        {
     913          signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
     914          for (x=startX; x<endX; x++)
     915          {
     916            signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]];
     917            edgeType  =  signRight + signLeft;
     918            signLeft  = -signRight;
     919
     920            diff [edgeType] += (orgLine[x] - srcLine[x]);
     921            count[edgeType] ++;
     922          }
     923          srcLine  += srcStride;
     924          orgLine  += orgStride;
     925        }
     926#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     927        if(isCalculatePreDeblockSamples)
     928        {
     929          if(isBelowAvail)
     930          {
     931            startX = isLeftAvail  ? 0 : 1;
     932            endX   = isRightAvail ? width : (width -1);
     933
     934            for(y=0; y<skipLinesB[typeIdx]; y++)
     935            {
     936              signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
     937              for (x=startX; x<endX; x++)
     938              {
     939                signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]];
     940                edgeType  =  signRight + signLeft;
     941                signLeft  = -signRight;
     942
     943                diff [edgeType] += (orgLine[x] - srcLine[x]);
     944                count[edgeType] ++;
     945              }
     946              srcLine  += srcStride;
     947              orgLine  += orgStride;
     948            }
     949          }
     950        }
     951#endif
     952      }
     953      break;
     954    case SAO_TYPE_EO_90:
     955      {
     956        diff +=2;
     957        count+=2;
     958        Char *signUpLine = m_signLineBuf1;
     959
     960#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     961        startX = (!isCalculatePreDeblockSamples) ? 0
     962                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
     963                                                 ;
     964#endif
     965        startY = isAboveAvail ? 0 : 1;
     966#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     967        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
     968                                                 : width
     969                                                 ;
     970#else
     971        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : width ;
     972#endif
     973        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
     974        if (!isAboveAvail)
     975        {
     976          srcLine += srcStride;
     977          orgLine += orgStride;
     978        }
     979
     980        Pel* srcLineAbove = srcLine - srcStride;
     981#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     982        for (x=startX; x<endX; x++)
     983#else
     984        for (x=0; x< endX; x++)
     985#endif
     986        {
     987          signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
     988        }
     989
     990        Pel* srcLineBelow;
     991        for (y=startY; y<endY; y++)
     992        {
     993          srcLineBelow = srcLine + srcStride;
     994
     995#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     996          for (x=startX; x<endX; x++)
     997#else
     998          for (x=0; x<endX; x++)
     999#endif
     1000          {
     1001            signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]];
     1002            edgeType  = signDown + signUpLine[x];
     1003            signUpLine[x]= -signDown;
     1004
     1005            diff [edgeType] += (orgLine[x] - srcLine[x]);
     1006            count[edgeType] ++;
     1007          }
     1008          srcLine += srcStride;
     1009          orgLine += orgStride;
     1010        }
     1011#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1012        if(isCalculatePreDeblockSamples)
     1013        {
     1014          if(isBelowAvail)
     1015          {
     1016            startX = 0;
     1017            endX   = width;
     1018
     1019            for(y=0; y<skipLinesB[typeIdx]; y++)
     1020            {
     1021              srcLineBelow = srcLine + srcStride;
     1022              srcLineAbove = srcLine - srcStride;
     1023
     1024              for (x=startX; x<endX; x++)
     1025              {
     1026                edgeType = m_sign[srcLine[x] - srcLineBelow[x]] + m_sign[srcLine[x] - srcLineAbove[x]];
     1027                diff [edgeType] += (orgLine[x] - srcLine[x]);
     1028                count[edgeType] ++;
     1029              }
     1030              srcLine  += srcStride;
     1031              orgLine  += orgStride;
     1032            }
     1033          }
     1034        }
     1035#endif
     1036
     1037      }
     1038      break;
     1039    case SAO_TYPE_EO_135:
     1040      {
     1041        diff +=2;
     1042        count+=2;
     1043        Char *signUpLine, *signDownLine, *signTmpLine;
     1044
     1045        signUpLine  = m_signLineBuf1;
     1046        signDownLine= m_signLineBuf2;
     1047
     1048#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1049        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
     1050                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
     1051                                                 ;
     1052#else
     1053        startX = isLeftAvail ? 0 : 1 ;
     1054#endif
     1055
     1056#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1057        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1))
     1058                                                 : (isRightAvail ? width : (width - 1))
     1059                                                 ;
     1060#else
     1061        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
     1062#endif
     1063        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
     1064
     1065        //prepare 2nd line's upper sign
     1066        Pel* srcLineBelow = srcLine + srcStride;
     1067        for (x=startX; x<endX+1; x++)
     1068        {
     1069          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x-1]];
     1070        }
     1071
     1072        //1st line
     1073        Pel* srcLineAbove = srcLine - srcStride;
     1074#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1075        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0    : 1) : startX;
     1076        firstLineEndX   = (!isCalculatePreDeblockSamples) ? (isAboveAvail     ? endX : 1) : endX;
     1077#else
     1078        firstLineStartX = isAboveLeftAvail ? 0    : 1;
     1079        firstLineEndX   = isAboveAvail     ? endX : 1;
     1080#endif
     1081        for(x=firstLineStartX; x<firstLineEndX; x++)
     1082        {
     1083          edgeType = m_sign[srcLine[x] - srcLineAbove[x-1]] - signUpLine[x+1];
     1084          diff [edgeType] += (orgLine[x] - srcLine[x]);
     1085          count[edgeType] ++;
     1086        }
     1087        srcLine  += srcStride;
     1088        orgLine  += orgStride;
     1089
     1090
     1091        //middle lines
     1092        for (y=1; y<endY; y++)
     1093        {
     1094          srcLineBelow = srcLine + srcStride;
     1095
     1096          for (x=startX; x<endX; x++)
     1097          {
     1098            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x+1]] ;
     1099            edgeType = signDown + signUpLine[x];
     1100            diff [edgeType] += (orgLine[x] - srcLine[x]);
     1101            count[edgeType] ++;
     1102
     1103            signDownLine[x+1] = -signDown;
     1104          }
     1105          signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
     1106
     1107          signTmpLine  = signUpLine;
     1108          signUpLine   = signDownLine;
     1109          signDownLine = signTmpLine;
     1110
     1111          srcLine += srcStride;
     1112          orgLine += orgStride;
     1113        }
     1114#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1115        if(isCalculatePreDeblockSamples)
     1116        {
     1117          if(isBelowAvail)
     1118          {
     1119            startX = isLeftAvail  ? 0     : 1 ;
     1120            endX   = isRightAvail ? width : (width -1);
     1121
     1122            for(y=0; y<skipLinesB[typeIdx]; y++)
     1123            {
     1124              srcLineBelow = srcLine + srcStride;
     1125              srcLineAbove = srcLine - srcStride;
     1126
     1127              for (x=startX; x< endX; x++)
     1128              {
     1129                edgeType = m_sign[srcLine[x] - srcLineBelow[x+1]] + m_sign[srcLine[x] - srcLineAbove[x-1]];
     1130                diff [edgeType] += (orgLine[x] - srcLine[x]);
     1131                count[edgeType] ++;
     1132              }
     1133              srcLine  += srcStride;
     1134              orgLine  += orgStride;
     1135            }
     1136          }
     1137        }
     1138#endif
     1139      }
     1140      break;
     1141    case SAO_TYPE_EO_45:
     1142      {
     1143        diff +=2;
     1144        count+=2;
     1145        Char *signUpLine = m_signLineBuf1+1;
     1146
     1147#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1148        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
     1149                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
     1150                                                 ;
     1151#else
     1152        startX = isLeftAvail ? 0 : 1;
     1153#endif
     1154#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1155        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
     1156                                                 : (isRightAvail ? width : (width - 1))
     1157                                                 ;
     1158#else
     1159        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1);
     1160#endif
     1161        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
     1162
     1163        //prepare 2nd line upper sign
     1164        Pel* srcLineBelow = srcLine + srcStride;
     1165        for (x=startX-1; x<endX; x++)
     1166        {
     1167          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
     1168        }
     1169
     1170
     1171        //first line
     1172        Pel* srcLineAbove = srcLine - srcStride;
     1173#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1174        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX)
     1175                                                          : startX
     1176                                                          ;
     1177        firstLineEndX   = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX)
     1178                                                          : endX
     1179                                                          ;
     1180#else
     1181        firstLineStartX = isAboveAvail ? startX : endX;
     1182        firstLineEndX   = (!isRightAvail && isAboveRightAvail) ? width : endX;
     1183#endif
     1184        for(x=firstLineStartX; x<firstLineEndX; x++)
     1185        {
     1186          edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] - signUpLine[x-1];
     1187          diff [edgeType] += (orgLine[x] - srcLine[x]);
     1188          count[edgeType] ++;
     1189        }
     1190
     1191        srcLine += srcStride;
     1192        orgLine += orgStride;
     1193
     1194        //middle lines
     1195        for (y=1; y<endY; y++)
     1196        {
     1197          srcLineBelow = srcLine + srcStride;
     1198
     1199          for(x=startX; x<endX; x++)
     1200          {
     1201            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
     1202            edgeType = signDown + signUpLine[x];
     1203
     1204            diff [edgeType] += (orgLine[x] - srcLine[x]);
     1205            count[edgeType] ++;
     1206
     1207            signUpLine[x-1] = -signDown;
     1208          }
     1209          signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
     1210          srcLine  += srcStride;
     1211          orgLine  += orgStride;
     1212        }
     1213#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1214        if(isCalculatePreDeblockSamples)
     1215        {
     1216          if(isBelowAvail)
     1217          {
     1218            startX = isLeftAvail  ? 0     : 1 ;
     1219            endX   = isRightAvail ? width : (width -1);
     1220
     1221            for(y=0; y<skipLinesB[typeIdx]; y++)
     1222            {
     1223              srcLineBelow = srcLine + srcStride;
     1224              srcLineAbove = srcLine - srcStride;
     1225
     1226              for (x=startX; x<endX; x++)
     1227              {
     1228                edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + m_sign[srcLine[x] - srcLineAbove[x+1]];
     1229                diff [edgeType] += (orgLine[x] - srcLine[x]);
     1230                count[edgeType] ++;
     1231              }
     1232              srcLine  += srcStride;
     1233              orgLine  += orgStride;
     1234            }
     1235          }
     1236        }
     1237#endif
     1238      }
     1239      break;
     1240    case SAO_TYPE_BO:
     1241      {
     1242#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1243        startX = (!isCalculatePreDeblockSamples)?0
     1244                                                :( isRightAvail?(width- skipLinesR[typeIdx]):width)
     1245                                                ;
     1246        endX   = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width )
     1247                                                :width
     1248                                                ;
     1249#else
     1250        endX = isRightAvail ? (width- skipLinesR[typeIdx]) : width;
     1251#endif
     1252        endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height;
     1253        Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
     1254        for (y=0; y< endY; y++)
     1255        {
     1256#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1257          for (x=startX; x< endX; x++)
     1258#else
     1259          for (x=0; x< endX; x++)
     1260#endif
     1261          {
     1262
     1263            Int bandIdx= srcLine[x] >> shiftBits;
     1264            diff [bandIdx] += (orgLine[x] - srcLine[x]);
     1265            count[bandIdx] ++;
     1266          }
     1267          srcLine += srcStride;
     1268          orgLine += orgStride;
     1269        }
     1270#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
     1271        if(isCalculatePreDeblockSamples)
     1272        {
     1273          if(isBelowAvail)
     1274          {
     1275            startX = 0;
     1276            endX   = width;
     1277
     1278            for(y= 0; y< skipLinesB[typeIdx]; y++)
     1279            {
     1280              for (x=startX; x< endX; x++)
     1281              {
     1282                Int bandIdx= srcLine[x] >> shiftBits;
     1283                diff [bandIdx] += (orgLine[x] - srcLine[x]);
     1284                count[bandIdx] ++;
     1285              }
     1286              srcLine  += srcStride;
     1287              orgLine  += orgStride;
     1288
     1289            }
     1290
     1291          }
     1292        }
     1293#endif
     1294      }
     1295      break;
     1296    default:
     1297      {
     1298        printf("Not a supported SAO types\n");
     1299        assert(0);
     1300        exit(-1);
     1301      }
     1302    }
     1303  }
     1304}
     1305
     1306#else
     1307
     1308
     1309
    471310TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
    481311{
     
    16612924}
    16622925
    1663 #if SAO_CHROMA_LAMBDA
    16642926/** Sample adaptive offset process
    16652927 * \param pcSaoParam
     
    16712933#else
    16722934Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambdaLuma, Double dLambdaChroma)
    1673 #endif
    1674 #else
    1675 /** Sample adaptive offset process
    1676  * \param dLambda
    1677  */
    1678 Void TEncSampleAdaptiveOffset::SAOProcess(SAOParam *pcSaoParam, Double dLambda)
    16792935#endif
    16802936{
     
    25013757}
    25023758
     3759#endif
     3760
    25033761//! \}
Note: See TracChangeset for help on using the changeset viewer.