source: SHVCSoftware/trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 844

Last change on this file since 844 was 713, checked in by seregin, 11 years ago

merge with SHM-6-dev

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