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

Last change on this file since 1257 was 1246, checked in by seregin, 9 years ago

port rev 4240

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