source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1199

Last change on this file since 1199 was 1179, checked in by tech, 10 years ago

Merged branch 13.1-dev0@1178.

File size: 46.4 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-2015, 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#if SAO_SGN_FUNC
923          signLeft = (Char)sgn(srcLine[startX] - srcLine[startX-1]);
924#else
925          signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
926#endif
927          for (x=startX; x<endX; x++)
928          {
929#if SAO_SGN_FUNC
930            signRight =  (Char)sgn(srcLine[x] - srcLine[x+1]);
931#else
932            signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
933#endif
934            edgeType  =  signRight + signLeft;
935            signLeft  = -signRight;
936
937            diff [edgeType] += (orgLine[x] - srcLine[x]);
938            count[edgeType] ++;
939          }
940          srcLine  += srcStride;
941          orgLine  += orgStride;
942        }
943#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
944        if(isCalculatePreDeblockSamples)
945        {
946          if(isBelowAvail)
947          {
948            startX = isLeftAvail  ? 0 : 1;
949            endX   = isRightAvail ? width : (width -1);
950
951            for(y=0; y<skipLinesB[typeIdx]; y++)
952            {
953#if SAO_SGN_FUNC
954              signLeft = (Char)sgn(srcLine[startX] - srcLine[startX-1]);
955#else
956              signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
957#endif
958              for (x=startX; x<endX; x++)
959              {
960#if SAO_SGN_FUNC
961                signRight =  (Char)sgn(srcLine[x] - srcLine[x+1]);
962#else
963                signRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
964#endif
965                edgeType  =  signRight + signLeft;
966                signLeft  = -signRight;
967
968                diff [edgeType] += (orgLine[x] - srcLine[x]);
969                count[edgeType] ++;
970              }
971              srcLine  += srcStride;
972              orgLine  += orgStride;
973            }
974          }
975        }
976#endif
977      }
978      break;
979    case SAO_TYPE_EO_90:
980      {
981        diff +=2;
982        count+=2;
983        Char *signUpLine = m_signLineBuf1;
984
985#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
986        startX = (!isCalculatePreDeblockSamples) ? 0
987                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : width)
988                                                 ;
989#endif
990        startY = isAboveAvail ? 0 : 1;
991#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
992        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : width) 
993                                                 : width
994                                                 ;
995#else
996        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : width ;
997#endif
998        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
999        if (!isAboveAvail)
1000        {
1001          srcLine += srcStride;
1002          orgLine += orgStride;
1003        }
1004
1005        Pel* srcLineAbove = srcLine - srcStride;
1006#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1007        for (x=startX; x<endX; x++) 
1008#else
1009        for (x=0; x< endX; x++) 
1010#endif
1011        {
1012#if SAO_SGN_FUNC
1013          signUpLine[x] = (Char)sgn(srcLine[x] - srcLineAbove[x]);
1014#else
1015          signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
1016#endif
1017        }
1018
1019        Pel* srcLineBelow;
1020        for (y=startY; y<endY; y++)
1021        {
1022          srcLineBelow = srcLine + srcStride;
1023
1024#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1025          for (x=startX; x<endX; x++)
1026#else
1027          for (x=0; x<endX; x++)
1028#endif
1029          {
1030#if SAO_SGN_FUNC
1031            signDown  = (Char)sgn(srcLine[x] - srcLineBelow[x]); 
1032#else
1033            signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
1034#endif
1035            edgeType  = signDown + signUpLine[x];
1036            signUpLine[x]= -signDown;
1037
1038            diff [edgeType] += (orgLine[x] - srcLine[x]);
1039            count[edgeType] ++;
1040          }
1041          srcLine += srcStride;
1042          orgLine += orgStride;
1043        }
1044#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1045        if(isCalculatePreDeblockSamples)
1046        {
1047          if(isBelowAvail)
1048          {
1049            startX = 0;
1050            endX   = width;
1051
1052            for(y=0; y<skipLinesB[typeIdx]; y++)
1053            {
1054              srcLineBelow = srcLine + srcStride;
1055              srcLineAbove = srcLine - srcStride;
1056
1057              for (x=startX; x<endX; x++)
1058              {
1059#if SAO_SGN_FUNC
1060                edgeType = sgn(srcLine[x] - srcLineBelow[x]) + sgn(srcLine[x] - srcLineAbove[x]);
1061#else
1062                edgeType = m_sign[srcLine[x] - srcLineBelow[x]] + m_sign[srcLine[x] - srcLineAbove[x]];
1063#endif
1064                diff [edgeType] += (orgLine[x] - srcLine[x]);
1065                count[edgeType] ++;
1066              }
1067              srcLine  += srcStride;
1068              orgLine  += orgStride;
1069            }
1070          }
1071        }
1072#endif
1073
1074      }
1075      break;
1076    case SAO_TYPE_EO_135:
1077      {
1078        diff +=2;
1079        count+=2;
1080        Char *signUpLine, *signDownLine, *signTmpLine;
1081
1082        signUpLine  = m_signLineBuf1;
1083        signDownLine= m_signLineBuf2;
1084
1085#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1086        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1087                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1088                                                 ;
1089#else
1090        startX = isLeftAvail ? 0 : 1 ;
1091#endif
1092
1093#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1094        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1))
1095                                                 : (isRightAvail ? width : (width - 1))
1096                                                 ;
1097#else
1098        endX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);
1099#endif
1100        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1101
1102        //prepare 2nd line's upper sign
1103        Pel* srcLineBelow = srcLine + srcStride;
1104        for (x=startX; x<endX+1; x++)
1105        {
1106#if SAO_SGN_FUNC
1107          signUpLine[x] = (Char)sgn(srcLineBelow[x] - srcLine[x-1]);
1108#else
1109          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x-1]];
1110#endif
1111        }
1112
1113        //1st line
1114        Pel* srcLineAbove = srcLine - srcStride;
1115#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1116        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveLeftAvail ? 0    : 1) : startX;
1117        firstLineEndX   = (!isCalculatePreDeblockSamples) ? (isAboveAvail     ? endX : 1) : endX;
1118#else
1119        firstLineStartX = isAboveLeftAvail ? 0    : 1;
1120        firstLineEndX   = isAboveAvail     ? endX : 1;
1121#endif
1122        for(x=firstLineStartX; x<firstLineEndX; x++)
1123        {
1124#if SAO_SGN_FUNC
1125          edgeType = sgn(srcLine[x] - srcLineAbove[x-1]) - signUpLine[x+1];
1126#else
1127          edgeType = m_sign[srcLine[x] - srcLineAbove[x-1]] - signUpLine[x+1];
1128#endif
1129          diff [edgeType] += (orgLine[x] - srcLine[x]);
1130          count[edgeType] ++;
1131        }
1132        srcLine  += srcStride;
1133        orgLine  += orgStride;
1134
1135
1136        //middle lines
1137        for (y=1; y<endY; y++)
1138        {
1139          srcLineBelow = srcLine + srcStride;
1140
1141          for (x=startX; x<endX; x++)
1142          {
1143#if SAO_SGN_FUNC
1144            signDown = (Char)sgn(srcLine[x] - srcLineBelow[x+1]);
1145#else
1146            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x+1]] ;
1147#endif
1148            edgeType = signDown + signUpLine[x];
1149            diff [edgeType] += (orgLine[x] - srcLine[x]);
1150            count[edgeType] ++;
1151
1152            signDownLine[x+1] = -signDown; 
1153          }
1154#if SAO_SGN_FUNC
1155          signDownLine[startX] = (Char)sgn(srcLineBelow[startX] - srcLine[startX-1]);
1156#else
1157          signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
1158#endif
1159
1160          signTmpLine  = signUpLine;
1161          signUpLine   = signDownLine;
1162          signDownLine = signTmpLine;
1163
1164          srcLine += srcStride;
1165          orgLine += orgStride;
1166        }
1167#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1168        if(isCalculatePreDeblockSamples)
1169        {
1170          if(isBelowAvail)
1171          {
1172            startX = isLeftAvail  ? 0     : 1 ;
1173            endX   = isRightAvail ? width : (width -1);
1174
1175            for(y=0; y<skipLinesB[typeIdx]; y++)
1176            {
1177              srcLineBelow = srcLine + srcStride;
1178              srcLineAbove = srcLine - srcStride;
1179
1180              for (x=startX; x< endX; x++)
1181              {
1182#if SAO_SGN_FUNC
1183                edgeType = sgn(srcLine[x] - srcLineBelow[x+1]) + sgn(srcLine[x] - srcLineAbove[x-1]);
1184#else
1185                edgeType = m_sign[srcLine[x] - srcLineBelow[x+1]] + m_sign[srcLine[x] - srcLineAbove[x-1]];
1186#endif
1187                diff [edgeType] += (orgLine[x] - srcLine[x]);
1188                count[edgeType] ++;
1189              }
1190              srcLine  += srcStride;
1191              orgLine  += orgStride;
1192            }
1193          }
1194        }
1195#endif
1196      }
1197      break;
1198    case SAO_TYPE_EO_45:
1199      {
1200        diff +=2;
1201        count+=2;
1202        Char *signUpLine = m_signLineBuf1+1;
1203
1204#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1205        startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1)
1206                                                 : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1207                                                 ;
1208#else
1209        startX = isLeftAvail ? 0 : 1;
1210#endif
1211#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1212        endX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1))
1213                                                 : (isRightAvail ? width : (width - 1))
1214                                                 ;
1215#else
1216        endX   = isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1);
1217#endif
1218        endY   = isBelowAvail ? (height - skipLinesB[typeIdx]) : (height - 1);
1219
1220        //prepare 2nd line upper sign
1221        Pel* srcLineBelow = srcLine + srcStride;
1222        for (x=startX-1; x<endX; x++)
1223        {
1224#if SAO_SGN_FUNC
1225          signUpLine[x] = (Char)sgn(srcLineBelow[x] - srcLine[x+1]);
1226#else
1227          signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
1228#endif
1229        }
1230
1231
1232        //first line
1233        Pel* srcLineAbove = srcLine - srcStride;
1234#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1235        firstLineStartX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? startX : endX)
1236                                                          : startX
1237                                                          ;
1238        firstLineEndX   = (!isCalculatePreDeblockSamples) ? ((!isRightAvail && isAboveRightAvail) ? width : endX)
1239                                                          : endX
1240                                                          ;
1241#else
1242        firstLineStartX = isAboveAvail ? startX : endX;
1243        firstLineEndX   = (!isRightAvail && isAboveRightAvail) ? width : endX;
1244#endif
1245        for(x=firstLineStartX; x<firstLineEndX; x++)
1246        {
1247#if SAO_SGN_FUNC
1248          edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) - signUpLine[x-1];
1249#else
1250          edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] - signUpLine[x-1];
1251#endif
1252          diff [edgeType] += (orgLine[x] - srcLine[x]);
1253          count[edgeType] ++;
1254        }
1255
1256        srcLine += srcStride;
1257        orgLine += orgStride;
1258
1259        //middle lines
1260        for (y=1; y<endY; y++)
1261        {
1262          srcLineBelow = srcLine + srcStride;
1263
1264          for(x=startX; x<endX; x++)
1265          {
1266#if SAO_SGN_FUNC
1267            signDown = (Char)sgn(srcLine[x] - srcLineBelow[x-1]);
1268#else
1269            signDown = (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
1270#endif
1271            edgeType = signDown + signUpLine[x];
1272
1273            diff [edgeType] += (orgLine[x] - srcLine[x]);
1274            count[edgeType] ++;
1275
1276            signUpLine[x-1] = -signDown; 
1277          }
1278#if SAO_SGN_FUNC
1279          signUpLine[endX-1] = (Char)sgn(srcLineBelow[endX-1] - srcLine[endX]);
1280#else
1281          signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
1282#endif
1283          srcLine  += srcStride;
1284          orgLine  += orgStride;
1285        }
1286#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1287        if(isCalculatePreDeblockSamples)
1288        {
1289          if(isBelowAvail)
1290          {
1291            startX = isLeftAvail  ? 0     : 1 ;
1292            endX   = isRightAvail ? width : (width -1);
1293
1294            for(y=0; y<skipLinesB[typeIdx]; y++)
1295            {
1296              srcLineBelow = srcLine + srcStride;
1297              srcLineAbove = srcLine - srcStride;
1298
1299              for (x=startX; x<endX; x++)
1300              {
1301#if SAO_SGN_FUNC
1302                edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + sgn(srcLine[x] - srcLineAbove[x+1]);
1303#else
1304                edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + m_sign[srcLine[x] - srcLineAbove[x+1]];
1305#endif
1306                diff [edgeType] += (orgLine[x] - srcLine[x]);
1307                count[edgeType] ++;
1308              }
1309              srcLine  += srcStride;
1310              orgLine  += orgStride;
1311            }
1312          }
1313        }
1314#endif
1315      }
1316      break;
1317    case SAO_TYPE_BO:
1318      {
1319#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1320        startX = (!isCalculatePreDeblockSamples)?0
1321                                                :( isRightAvail?(width- skipLinesR[typeIdx]):width)
1322                                                ;
1323        endX   = (!isCalculatePreDeblockSamples)?(isRightAvail ? (width - skipLinesR[typeIdx]) : width )
1324                                                :width
1325                                                ;
1326#else
1327        endX = isRightAvail ? (width- skipLinesR[typeIdx]) : width;
1328#endif
1329        endY = isBelowAvail ? (height- skipLinesB[typeIdx]) : height;
1330        Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
1331        for (y=0; y< endY; y++)
1332        {
1333#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1334          for (x=startX; x< endX; x++)
1335#else
1336          for (x=0; x< endX; x++)
1337#endif
1338          {
1339
1340            Int bandIdx= srcLine[x] >> shiftBits; 
1341            diff [bandIdx] += (orgLine[x] - srcLine[x]);
1342            count[bandIdx] ++;
1343          }
1344          srcLine += srcStride;
1345          orgLine += orgStride;
1346        }
1347#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
1348        if(isCalculatePreDeblockSamples)
1349        {
1350          if(isBelowAvail)
1351          {
1352            startX = 0;
1353            endX   = width;
1354
1355            for(y= 0; y< skipLinesB[typeIdx]; y++)
1356            {
1357              for (x=startX; x< endX; x++)
1358              {
1359                Int bandIdx= srcLine[x] >> shiftBits; 
1360                diff [bandIdx] += (orgLine[x] - srcLine[x]);
1361                count[bandIdx] ++;
1362              }
1363              srcLine  += srcStride;
1364              orgLine  += orgStride;
1365
1366            }
1367
1368          }
1369        }
1370#endif
1371      }
1372      break;
1373    default:
1374      {
1375        printf("Not a supported SAO types\n");
1376        assert(0);
1377        exit(-1);
1378      }
1379    }
1380  }
1381}
1382
1383//! \}
Note: See TracBrowser for help on using the repository browser.