source: 3DVCSoftware/branches/HTM-10.0-dev0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 852

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

Update HM-12.0 -> HM-13.0.

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