source: SHVCSoftware/branches/SHM-5.0-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp @ 1510

Last change on this file since 1510 was 601, checked in by seregin, 11 years ago

remove global array for SaoMaxOffsetQVal

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