source: 3DVCSoftware/branches/HTM-11.0-dev0-Qualcomm/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1314

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

Merged HTM-10.0-dev0@871. (MV-HEVC 7 HLS)

File size: 44.5 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license. 
5 *
6 * Copyright (c) 2010-2014, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/**
35 \file     TEncSampleAdaptiveOffset.cpp
36 \brief       estimation part of sample adaptive offset class
37 */
38#include "TEncSampleAdaptiveOffset.h"
39#include <string.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43
44//! \ingroup TLibEncoder
45//! \{
46
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
62TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset()
63{
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();
259  m_lambda[SAO_Y]= lambdas[0]; m_lambda[SAO_Cb]= lambdas[1]; m_lambda[SAO_Cr]= lambdas[2];
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);
465  Int offsetTh = g_saoMaxOffsetQVal[compIdx];  //inclusive
466
467  ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
468
469  //derive initial offsets
470  Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES);
471  for(Int classIdx=0; classIdx< numClasses; classIdx++)
472  {
473    if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN)  ) 
474    {
475      continue; //offset will be zero
476    }
477
478    if(statData.count[classIdx] == 0)
479    {
480      continue; //offset will be zero
481    }
482
483    quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8)) 
484                                                                  / 
485                                                          (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx])
486                                               );
487    quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]);
488  }
489
490  // adjust offsets
491  switch(typeIdc)
492  {
493    case SAO_TYPE_EO_0:
494    case SAO_TYPE_EO_90:
495    case SAO_TYPE_EO_135:
496    case SAO_TYPE_EO_45:
497      {
498        Int64 classDist;
499        Double classCost;
500        for(Int classIdx=0; classIdx<NUM_SAO_EO_CLASSES; classIdx++) 
501        {         
502          if(classIdx==SAO_CLASS_EO_FULL_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
503          if(classIdx==SAO_CLASS_EO_HALF_VALLEY && quantOffsets[classIdx] < 0) quantOffsets[classIdx] =0;
504          if(classIdx==SAO_CLASS_EO_HALF_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
505          if(classIdx==SAO_CLASS_EO_FULL_PEAK   && quantOffsets[classIdx] > 0) quantOffsets[classIdx] =0;
506
507          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
508          {
509            quantOffsets[classIdx] = estIterOffset( typeIdc, classIdx, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh );
510          }
511        }
512     
513        typeAuxInfo =0;
514      }
515      break;
516    case SAO_TYPE_BO:
517      {
518        Int64  distBOClasses[NUM_SAO_BO_CLASSES];
519        Double costBOClasses[NUM_SAO_BO_CLASSES];
520        ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES);
521        for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++)
522        {         
523          costBOClasses[classIdx]= m_lambda[compIdx];
524          if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero
525          {
526            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 );
527          }
528        }
529
530        //decide the starting band index
531        Double minCost = MAX_DOUBLE, cost;
532        for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++) 
533        {
534          cost  = costBOClasses[band  ];
535          cost += costBOClasses[band+1];
536          cost += costBOClasses[band+2];
537          cost += costBOClasses[band+3];
538
539          if(cost < minCost)
540          {
541            minCost = cost;
542            typeAuxInfo = band;
543          }
544        }
545        //clear those unused classes
546        Int clearQuantOffset[NUM_SAO_BO_CLASSES];
547        ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES);
548        for(Int i=0; i< 4; i++) 
549        {
550          Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES;
551          clearQuantOffset[band] = quantOffsets[band];
552        }
553        ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES);       
554      }
555      break;
556    default:
557      {
558        printf("Not a supported type");
559        assert(0);
560        exit(-1);
561      }
562
563  }
564
565
566}
567
568
569Void TEncSampleAdaptiveOffset::deriveModeNewRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
570{
571  Double minCost, cost;
572  Int rate;
573  UInt previousWrittenBits;
574  Int64 dist[NUM_SAO_COMPONENTS], modeDist[NUM_SAO_COMPONENTS];
575  SAOOffset testOffset[NUM_SAO_COMPONENTS];
576  Int compIdx;
577  Int invQuantOffset[MAX_NUM_SAO_CLASSES];
578
579  modeDist[SAO_Y]= modeDist[SAO_Cb] = modeDist[SAO_Cr] = 0;
580
581  //pre-encode merge flags
582  modeParam[SAO_Y ].modeIdc = SAO_MODE_OFF;
583  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
584  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true);
585  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
586
587  //------ luma --------//
588  compIdx = SAO_Y;
589  //"off" case as initial cost
590  modeParam[compIdx].modeIdc = SAO_MODE_OFF;
591  m_pcRDGoOnSbacCoder->resetBits();
592  m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx]);
593  modeDist[compIdx] = 0;
594  minCost= m_lambda[compIdx]*((Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits());
595  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
596  if(sliceEnabled[compIdx])
597  {
598    for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
599    {
600      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
601      testOffset[compIdx].typeIdc = typeIdc;
602
603      //derive coded offset
604      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
605
606      //inversed quantized offsets
607      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
608
609      //get distortion
610      dist[compIdx] = getDistortion(ctu, compIdx, testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
611
612      //get rate
613      m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
614      m_pcRDGoOnSbacCoder->resetBits();
615      m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx]);
616      rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
617      cost = (Double)dist[compIdx] + m_lambda[compIdx]*((Double)rate);
618      if(cost < minCost)
619      {
620        minCost = cost;
621        modeDist[compIdx] = dist[compIdx];
622        modeParam[compIdx]= testOffset[compIdx];
623        m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
624      }
625    }
626  }
627  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
628  m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
629
630  //------ chroma --------//
631  //"off" case as initial cost
632  cost = 0;
633  previousWrittenBits = 0;
634  m_pcRDGoOnSbacCoder->resetBits();
635  for (Int component = SAO_Cb; component < NUM_SAO_COMPONENTS; component++)
636  {
637    modeParam[component].modeIdc = SAO_MODE_OFF; 
638    modeDist [component] = 0;
639
640    m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, modeParam[component], sliceEnabled[component]);
641
642    const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
643    cost += m_lambda[component] * (currentWrittenBits - previousWrittenBits);
644    previousWrittenBits = currentWrittenBits;
645  }
646
647  minCost = cost;
648
649  //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function
650
651  for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++)
652  {
653    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]);
654    m_pcRDGoOnSbacCoder->resetBits();
655    previousWrittenBits = 0;
656    cost = 0;
657
658    for(compIdx= SAO_Cb; compIdx< NUM_SAO_COMPONENTS; compIdx++)
659    {
660      if(!sliceEnabled[compIdx])
661      {
662        testOffset[compIdx].modeIdc = SAO_MODE_OFF;
663        dist[compIdx]= 0;
664        continue;
665      }
666      testOffset[compIdx].modeIdc = SAO_MODE_NEW;
667      testOffset[compIdx].typeIdc = typeIdc;
668
669      //derive offset & get distortion
670      deriveOffsets(ctu, compIdx, typeIdc, blkStats[ctu][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo);
671      invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset);
672      dist[compIdx]= getDistortion(ctu, compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctu][compIdx][typeIdc]);
673     
674      m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx]);
675
676      const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
677      cost += dist[compIdx] + (m_lambda[compIdx] * (currentWrittenBits - previousWrittenBits));
678      previousWrittenBits = currentWrittenBits;
679    }
680
681    if(cost < minCost)
682    {
683      minCost = cost;
684      for(compIdx= SAO_Cb; compIdx< NUM_SAO_COMPONENTS; compIdx++)
685      {
686        modeDist [compIdx] = dist      [compIdx];
687        modeParam[compIdx] = testOffset[compIdx];
688      }
689    }
690  }
691
692
693  //----- re-gen rate & normalized cost----//
694  modeNormCost = 0;
695  for(UInt component = SAO_Y; component < NUM_SAO_COMPONENTS; component++)
696  {
697    modeNormCost += (Double)modeDist[component] / m_lambda[component];
698  }
699  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
700  m_pcRDGoOnSbacCoder->resetBits();
701  m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
702  modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
703
704}
705
706Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(Int ctu, std::vector<SAOBlkParam*>& mergeList, Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel)
707{
708  Int mergeListSize = (Int)mergeList.size();
709  modeNormCost = MAX_DOUBLE;
710
711  Double cost;
712  SAOBlkParam testBlkParam;
713
714  for(Int mergeType=0; mergeType< mergeListSize; mergeType++)
715  {
716    if(mergeList[mergeType] == NULL)
717    {
718      continue;
719    }
720
721    testBlkParam = *(mergeList[mergeType]);
722    //normalized distortion
723    Double normDist=0;
724    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
725    {
726      testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE;
727      testBlkParam[compIdx].typeIdc = mergeType;
728
729      SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx];
730
731      if( mergedOffsetParam.modeIdc != SAO_MODE_OFF)
732      {
733        //offsets have been reconstructed. Don't call inversed quantization function.
734        normDist += (((Double)getDistortion(ctu, compIdx, mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctu][compIdx][mergedOffsetParam.typeIdc]))
735                       /m_lambda[compIdx]
736                    );
737      }
738
739    }
740
741    //rate
742    m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]);
743    m_pcRDGoOnSbacCoder->resetBits();
744    m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false);
745    Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits();
746
747    cost = normDist+(Double)rate;
748
749    if(cost < modeNormCost)
750    {
751      modeNormCost = cost;
752      modeParam    = testBlkParam;
753      m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
754    }
755  }
756
757  m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]);
758
759
760}
761
762Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams)
763{
764  Bool isAllBlksDisabled = false;
765  if(!sliceEnabled[SAO_Y] && !sliceEnabled[SAO_Cb] && !sliceEnabled[SAO_Cr])
766  {
767    isAllBlksDisabled = true;
768  }
769
770  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]);
771
772  SAOBlkParam modeParam;
773  Double minCost, modeCost;
774
775  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
776  {
777    if(isAllBlksDisabled)
778    {
779      codedParams[ctu].reset();
780      continue;
781    }
782
783    m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]);
784
785    //get merge list
786    std::vector<SAOBlkParam*> mergeList;
787    getMergeList(pic, ctu, reconParams, mergeList);
788
789    minCost = MAX_DOUBLE;
790    for(Int mode=0; mode < NUM_SAO_MODES; mode++)
791    {
792      switch(mode)
793      {
794      case SAO_MODE_OFF:
795        {
796          continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case.
797        }
798        break;
799      case SAO_MODE_NEW:
800        {
801          deriveModeNewRDO(ctu, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
802
803        }
804        break;
805      case SAO_MODE_MERGE:
806        {
807          deriveModeMergeRDO(ctu, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR);
808        }
809        break;
810      default:
811        {
812          printf("Not a supported SAO mode\n");
813          assert(0);
814          exit(-1);
815        }
816      }
817
818      if(modeCost < minCost)
819      {
820        minCost = modeCost;
821        codedParams[ctu] = modeParam;
822        m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
823
824      }
825    } //mode
826    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]);
827
828    //apply reconstructed offsets
829    reconParams[ctu] = codedParams[ctu];
830    reconstructBlkSAOParam(reconParams[ctu], mergeList);
831    offsetCTU(ctu, srcYuv, resYuv, reconParams[ctu], pic);
832  } //ctu
833
834#if SAO_ENCODING_CHOICE
835  Int picTempLayer = pic->getSlice(0)->getDepth();
836  Int numLcusForSAOOff[NUM_SAO_COMPONENTS];
837  numLcusForSAOOff[SAO_Y ] = numLcusForSAOOff[SAO_Cb]= numLcusForSAOOff[SAO_Cr]= 0;
838
839  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
840  {
841    for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
842    {
843      if( reconParams[ctu][compIdx].modeIdc == SAO_MODE_OFF)
844      {
845        numLcusForSAOOff[compIdx]++;
846      }
847    }
848  }
849#if SAO_ENCODING_CHOICE_CHROMA
850  for (Int compIdx=0; compIdx<NUM_SAO_COMPONENTS; compIdx++)
851  {
852    m_saoDisabledRate[compIdx][picTempLayer] = (Double)numLcusForSAOOff[compIdx]/(Double)m_numCTUsPic;
853  }
854#else
855  if (picTempLayer == 0)
856  {
857    m_saoDisabledRate[SAO_Y][0] = (Double)(numLcusForSAOOff[SAO_Y]+numLcusForSAOOff[SAO_Cb]+numLcusForSAOOff[SAO_Cr])/(Double)(m_numCTUsPic*3);
858  }
859#endif                                             
860#endif
861}
862
863
864Void TEncSampleAdaptiveOffset::getBlkStats(Int compIdx, SAOStatData* statsDataTypes 
865                        , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height
866                        , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail
867#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
868                        , Bool isCalculatePreDeblockSamples
869#endif
870                        )
871{
872  if(m_lineBufWidth != m_maxCUWidth)
873  {
874    m_lineBufWidth = m_maxCUWidth;
875
876    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
877    m_signLineBuf1 = new Char[m_lineBufWidth+1]; 
878
879    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
880    m_signLineBuf2 = new Char[m_lineBufWidth+1];
881  }
882
883  Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;
884  Char signLeft, signRight, signDown;
885  Int64 *diff, *count;
886  Pel *srcLine, *orgLine;
887  Int* skipLinesR = m_skipLinesR[compIdx];
888  Int* skipLinesB = m_skipLinesB[compIdx];
889
890  for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++)
891  {
892    SAOStatData& statsData= statsDataTypes[typeIdx];
893    statsData.reset();
894
895    srcLine = srcBlk;
896    orgLine = orgBlk;
897    diff    = statsData.diff;
898    count   = statsData.count;
899    switch(typeIdx)
900    {
901    case SAO_TYPE_EO_0:
902      {
903        diff +=2;
904        count+=2;
905        endY   = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height;
906#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
907        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
908                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
909                                                 ;
910#else
911        startX = isLeftAvail ? 0 : 1;
912#endif
913#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
914        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
915                                                 : (isRightAvail ? width : (width - 1))
916                                                 ;
917#else
918        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
919#endif
920        for (y=0; y<endY; y++)
921        {
922          signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
923          for (x=startX; x<endX; x++)
924          {
925            signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
926            edgeType  =  signRight + signLeft;
927            signLeft  = -signRight;
928
929            diff [edgeType] += (orgLine[x] - srcLine[x]);
930            count[edgeType] ++;
931          }
932          srcLine  += srcStride;
933          orgLine  += orgStride;
934        }
935#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
936        if(isCalculatePreDeblockSamples)
937        {
938          if(isBelowAvail)
939          {
940            startX = isLeftAvail  ? 0 : 1;
941            endX   = isRightAvail ? width : (width -1);
942
943            for(y=0; y<skipLinesB[typeIdx]; y++)
944            {
945              signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
946              for (x=startX; x<endX; x++)
947              {
948                signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
949                edgeType  =  signRight + signLeft;
950                signLeft  = -signRight;
951
952                diff [edgeType] += (orgLine[x] - srcLine[x]);
953                count[edgeType] ++;
954              }
955              srcLine  += srcStride;
956              orgLine  += orgStride;
957            }
958          }
959        }
960#endif
961      }
962      break;
963    case SAO_TYPE_EO_90:
964      {
965        diff +=2;
966        count+=2;
967        Char *signUpLine = m_signLineBuf1;
968
969#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
970        startX = (!isCalculatePreDeblockSamples) ? 0
971                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
972                                                 ;
973#endif
974        startY = isAboveAvail ? 0 : 1;
975#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
976        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width) 
977                                                 : width
978                                                 ;
979#else
980        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : width ;
981#endif
982        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
983        if (!isAboveAvail)
984        {
985          srcLine += srcStride;
986          orgLine += orgStride;
987        }
988
989        Pel* srcLineAbove = srcLine - srcStride;
990#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
991        for (x=startX; x<endX; x++) 
992#else
993        for (x=0; x< endX; x++) 
994#endif
995        {
996          signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
997        }
998
999        Pel* srcLineBelow;
1000        for (y=startY; y<endY; y++)
1001        {
1002          srcLineBelow = srcLine + srcStride;
1003
1004#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1005          for (x=startX; x<endX; x++)
1006#else
1007          for (x=0; x<endX; x++)
1008#endif
1009          {
1010            signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
1011            edgeType  = signDown + signUpLine[x];
1012            signUpLine[x]= -signDown;
1013
1014            diff [edgeType] += (orgLine[x] - srcLine[x]);
1015            count[edgeType] ++;
1016          }
1017          srcLine += srcStride;
1018          orgLine += orgStride;
1019        }
1020#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1021        if(isCalculatePreDeblockSamples)
1022        {
1023          if(isBelowAvail)
1024          {
1025            startX = 0;
1026            endX   = width;
1027
1028            for(y=0; y<skipLinesB[typeIdx]; y++)
1029            {
1030              srcLineBelow = srcLine + srcStride;
1031              srcLineAbove = srcLine - srcStride;
1032
1033              for (x=startX; x<endX; x++)
1034              {
1035                edgeType = m_sign[srcLine[x] - srcLineBelow[x]] + m_sign[srcLine[x] - srcLineAbove[x]];
1036                diff [edgeType] += (orgLine[x] - srcLine[x]);
1037                count[edgeType] ++;
1038              }
1039              srcLine  += srcStride;
1040              orgLine  += orgStride;
1041            }
1042          }
1043        }
1044#endif
1045
1046      }
1047      break;
1048    case SAO_TYPE_EO_135:
1049      {
1050        diff +=2;
1051        count+=2;
1052        Char *signUpLine, *signDownLine, *signTmpLine;
1053
1054        signUpLine  = m_signLineBuf1;
1055        signDownLine= m_signLineBuf2;
1056
1057#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1058        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1059                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1060                                                 ;
1061#else
1062        startX = isLeftAvail ? 0 : 1 ;
1063#endif
1064
1065#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1066        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1))
1067                                                 : (isRightAvail ? width : (width - 1))
1068                                                 ;
1069#else
1070        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
1071#endif
1072        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1073
1074        //prepare 2nd line's upper sign
1075        Pel* srcLineBelow = srcLine + srcStride;
1076        for (x=startX; x<endX+1; x++)
1077        {
1078          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x-1]];
1079        }
1080
1081        //1st line
1082        Pel* srcLineAbove = srcLine - srcStride;
1083#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1084        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0    : 1) : startX;
1085        firstLineEndX   = (!isCalculatePreDeblockSamples) ? (isAboveAvail     ? endX : 1) : endX;
1086#else
1087        firstLineStartX = isAboveLeftAvail ? 0    : 1;
1088        firstLineEndX   = isAboveAvail     ? endX : 1;
1089#endif
1090        for(x=firstLineStartX; x<firstLineEndX; x++)
1091        {
1092          edgeType = m_sign[srcLine[x] - srcLineAbove[x-1]] - signUpLine[x+1];
1093          diff [edgeType] += (orgLine[x] - srcLine[x]);
1094          count[edgeType] ++;
1095        }
1096        srcLine  += srcStride;
1097        orgLine  += orgStride;
1098
1099
1100        //middle lines
1101        for (y=1; y<endY; y++)
1102        {
1103          srcLineBelow = srcLine + srcStride;
1104
1105          for (x=startX; x<endX; x++)
1106          {
1107            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x+1]] ;
1108            edgeType = signDown + signUpLine[x];
1109            diff [edgeType] += (orgLine[x] - srcLine[x]);
1110            count[edgeType] ++;
1111
1112            signDownLine[x+1] = -signDown; 
1113          }
1114          signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
1115
1116          signTmpLine  = signUpLine;
1117          signUpLine   = signDownLine;
1118          signDownLine = signTmpLine;
1119
1120          srcLine += srcStride;
1121          orgLine += orgStride;
1122        }
1123#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1124        if(isCalculatePreDeblockSamples)
1125        {
1126          if(isBelowAvail)
1127          {
1128            startX = isLeftAvail  ? 0     : 1 ;
1129            endX   = isRightAvail ? width : (width -1);
1130
1131            for(y=0; y<skipLinesB[typeIdx]; y++)
1132            {
1133              srcLineBelow = srcLine + srcStride;
1134              srcLineAbove = srcLine - srcStride;
1135
1136              for (x=startX; x< endX; x++)
1137              {
1138                edgeType = m_sign[srcLine[x] - srcLineBelow[x+1]] + m_sign[srcLine[x] - srcLineAbove[x-1]];
1139                diff [edgeType] += (orgLine[x] - srcLine[x]);
1140                count[edgeType] ++;
1141              }
1142              srcLine  += srcStride;
1143              orgLine  += orgStride;
1144            }
1145          }
1146        }
1147#endif
1148      }
1149      break;
1150    case SAO_TYPE_EO_45:
1151      {
1152        diff +=2;
1153        count+=2;
1154        Char *signUpLine = m_signLineBuf1+1;
1155
1156#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1157        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1158                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1159                                                 ;
1160#else
1161        startX = isLeftAvail ? 0 : 1;
1162#endif
1163#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1164        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1165                                                 : (isRightAvail ? width : (width - 1))
1166                                                 ;
1167#else
1168        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1);
1169#endif
1170        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1171
1172        //prepare 2nd line upper sign
1173        Pel* srcLineBelow = srcLine + srcStride;
1174        for (x=startX-1; x<endX; x++)
1175        {
1176          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
1177        }
1178
1179
1180        //first line
1181        Pel* srcLineAbove = srcLine - srcStride;
1182#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1183        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX)
1184                                                          : startX
1185                                                          ;
1186        firstLineEndX   = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX)
1187                                                          : endX
1188                                                          ;
1189#else
1190        firstLineStartX = isAboveAvail ? startX : endX;
1191        firstLineEndX   = (!isRightAvail && isAboveRightAvail) ? width : endX;
1192#endif
1193        for(x=firstLineStartX; x<firstLineEndX; x++)
1194        {
1195          edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] - signUpLine[x-1];
1196          diff [edgeType] += (orgLine[x] - srcLine[x]);
1197          count[edgeType] ++;
1198        }
1199
1200        srcLine += srcStride;
1201        orgLine += orgStride;
1202
1203        //middle lines
1204        for (y=1; y<endY; y++)
1205        {
1206          srcLineBelow = srcLine + srcStride;
1207
1208          for(x=startX; x<endX; x++)
1209          {
1210            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
1211            edgeType = signDown + signUpLine[x];
1212
1213            diff [edgeType] += (orgLine[x] - srcLine[x]);
1214            count[edgeType] ++;
1215
1216            signUpLine[x-1] = -signDown; 
1217          }
1218          signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
1219          srcLine  += srcStride;
1220          orgLine  += orgStride;
1221        }
1222#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1223        if(isCalculatePreDeblockSamples)
1224        {
1225          if(isBelowAvail)
1226          {
1227            startX = isLeftAvail  ? 0     : 1 ;
1228            endX   = isRightAvail ? width : (width -1);
1229
1230            for(y=0; y<skipLinesB[typeIdx]; y++)
1231            {
1232              srcLineBelow = srcLine + srcStride;
1233              srcLineAbove = srcLine - srcStride;
1234
1235              for (x=startX; x<endX; x++)
1236              {
1237                edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + m_sign[srcLine[x] - srcLineAbove[x+1]];
1238                diff [edgeType] += (orgLine[x] - srcLine[x]);
1239                count[edgeType] ++;
1240              }
1241              srcLine  += srcStride;
1242              orgLine  += orgStride;
1243            }
1244          }
1245        }
1246#endif
1247      }
1248      break;
1249    case SAO_TYPE_BO:
1250      {
1251#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1252        startX = (!isCalculatePreDeblockSamples)?0
1253                                                :( isRightAvail?(width- skipLinesR[typeIdx]):width)
1254                                                ;
1255        endX   = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width )
1256                                                :width
1257                                                ;
1258#else
1259        endX = isRightAvail ? (width- skipLinesR[typeIdx]) : width;
1260#endif
1261        endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height;
1262        Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
1263        for (y=0; y< endY; y++)
1264        {
1265#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1266          for (x=startX; x< endX; x++)
1267#else
1268          for (x=0; x< endX; x++)
1269#endif
1270          {
1271
1272            Int bandIdx= srcLine[x] >> shiftBits; 
1273            diff [bandIdx] += (orgLine[x] - srcLine[x]);
1274            count[bandIdx] ++;
1275          }
1276          srcLine += srcStride;
1277          orgLine += orgStride;
1278        }
1279#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1280        if(isCalculatePreDeblockSamples)
1281        {
1282          if(isBelowAvail)
1283          {
1284            startX = 0;
1285            endX   = width;
1286
1287            for(y= 0; y< skipLinesB[typeIdx]; y++)
1288            {
1289              for (x=startX; x< endX; x++)
1290              {
1291                Int bandIdx= srcLine[x] >> shiftBits; 
1292                diff [bandIdx] += (orgLine[x] - srcLine[x]);
1293                count[bandIdx] ++;
1294              }
1295              srcLine  += srcStride;
1296              orgLine  += orgStride;
1297
1298            }
1299
1300          }
1301        }
1302#endif
1303      }
1304      break;
1305    default:
1306      {
1307        printf("Not a supported SAO types\n");
1308        assert(0);
1309        exit(-1);
1310      }
1311    }
1312  }
1313}
1314
1315//! \}
Note: See TracBrowser for help on using the repository browser.