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

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

Added direct dependency type for qtl.
Updated cfg files.
updated copy right headers.

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.