source: 3DVCSoftware/trunk/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 901

Last change on this file since 901 was 872, checked in by tech, 11 years ago

Merged HTM-10.0-dev0@871. (MV-HEVC 7 HLS)

File size: 24.0 KB
RevLine 
[56]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 *
[872]6 * Copyright (c) 2010-2014, ITU/ISO/IEC
[56]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/** \file     TComSampleAdaptiveOffset.cpp
35    \brief    sample adaptive offset class
36*/
37
38#include "TComSampleAdaptiveOffset.h"
39#include <string.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43
44//! \ingroup TLibCommon
45//! \{
[872]46UInt g_saoMaxOffsetQVal[NUM_SAO_COMPONENTS];
[56]47
[872]48SAOOffset::SAOOffset()
49{ 
50  reset();
[56]51}
52
[872]53SAOOffset::~SAOOffset()
[56]54{
55
56}
57
[872]58Void SAOOffset::reset()
[56]59{
[872]60  modeIdc = SAO_MODE_OFF;
61  typeIdc = -1;
62  typeAuxInfo = -1;
63  ::memset(offset, 0, sizeof(Int)* MAX_NUM_SAO_CLASSES);
[56]64}
65
[872]66const SAOOffset& SAOOffset::operator= (const SAOOffset& src)
[56]67{
[872]68  modeIdc = src.modeIdc;
69  typeIdc = src.typeIdc;
70  typeAuxInfo = src.typeAuxInfo;
71  ::memcpy(offset, src.offset, sizeof(Int)* MAX_NUM_SAO_CLASSES);
[56]72
[872]73  return *this;
74}
75
76
77SAOBlkParam::SAOBlkParam()
[56]78{
[872]79  reset();
80}
[56]81
[872]82SAOBlkParam::~SAOBlkParam()
[56]83{
84
[872]85}
[56]86
[872]87Void SAOBlkParam::reset()
[56]88{
[872]89  for(Int compIdx=0; compIdx< 3; compIdx++)
[56]90  {
[872]91    offsetParam[compIdx].reset();
[56]92  }
93}
[608]94
[872]95const SAOBlkParam& SAOBlkParam::operator= (const SAOBlkParam& src)
[56]96{
[872]97  for(Int compIdx=0; compIdx< 3; compIdx++)
[56]98  {
[872]99    offsetParam[compIdx] = src.offsetParam[compIdx];
[56]100  }
[872]101  return *this;
[608]102
[872]103}
[608]104
[872]105TComSampleAdaptiveOffset::TComSampleAdaptiveOffset()
106{
107  m_tempPicYuv = NULL;
108  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
[608]109  {
[872]110    m_offsetClipTable[compIdx] = NULL;
[608]111  }
[872]112  m_signTable = NULL; 
[608]113
[872]114 
115  m_lineBufWidth = 0;
116  m_signLineBuf1 = NULL;
117  m_signLineBuf2 = NULL;
118}
[56]119
120
[872]121TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset()
122{
123  destroy();
124 
125  if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
126  if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
127}
[56]128
[872]129Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
130{
131  destroy();
[56]132
[872]133  m_picWidth = picWidth;   
134  m_picHeight= picHeight;
135  m_maxCUWidth= maxCUWidth; 
136  m_maxCUHeight= maxCUHeight;
[56]137
[872]138  m_numCTUInWidth = (m_picWidth/m_maxCUWidth) + ((m_picWidth % m_maxCUWidth)?1:0);
139  m_numCTUInHeight= (m_picHeight/m_maxCUHeight) + ((m_picHeight % m_maxCUHeight)?1:0);
140  m_numCTUsPic = m_numCTUInHeight*m_numCTUInWidth;
[56]141
[872]142  //temporary picture buffer
143  if ( !m_tempPicYuv )
[56]144  {
[872]145    m_tempPicYuv = new TComPicYuv;
146    m_tempPicYuv->create( m_picWidth, m_picHeight, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
[56]147  }
148
[872]149  //bit-depth related
150  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
[56]151  {
[872]152    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC;
153    m_offsetStepLog2  [compIdx] = max(bitDepthSample - MAX_SAO_TRUNCATED_BITDEPTH, 0);
154    g_saoMaxOffsetQVal[compIdx] = (1<<(min(bitDepthSample,MAX_SAO_TRUNCATED_BITDEPTH)-5))-1; //Table 9-32, inclusive
[56]155  }
156
[872]157  //look-up table for clipping
158  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
[608]159  {
[872]160    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC; //exclusive
161    Int maxSampleValue = (1<< bitDepthSample); //exclusive
162    Int maxOffsetValue = (g_saoMaxOffsetQVal[compIdx] << m_offsetStepLog2[compIdx]); 
[608]163
[872]164    m_offsetClipTable[compIdx] = new Int[(maxSampleValue + maxOffsetValue -1)+ (maxOffsetValue)+1 ]; //positive & negative range plus 0
165    m_offsetClip[compIdx] = &(m_offsetClipTable[compIdx][maxOffsetValue]);
[608]166
[872]167    //assign clipped values
168    Int* offsetClipPtr = m_offsetClip[compIdx];
169    for(Int k=0; k< maxSampleValue; k++)
170    {
171      *(offsetClipPtr + k) = k;
172    }
173    for(Int k=0; k< maxOffsetValue; k++ )
174    {
175      *(offsetClipPtr + maxSampleValue+ k) = maxSampleValue-1;
176      *(offsetClipPtr -k -1 )              = 0;
177    }
178    if(compIdx == SAO_Y) //g_bitDepthY is always larger than or equal to g_bitDepthC
179    {
180      m_signTable = new Short[ 2*(maxSampleValue-1) + 1 ];
181      m_sign = &(m_signTable[maxSampleValue-1]);
[608]182
[872]183      m_sign[0] = 0;
184      for(Int k=1; k< maxSampleValue; k++)
185      {
186        m_sign[k] = 1;
187        m_sign[-k]= -1;
188      }
189    }
190  } 
[608]191
[56]192}
193
194Void TComSampleAdaptiveOffset::destroy()
195{
[872]196  if ( m_tempPicYuv )
[56]197  {
[872]198    m_tempPicYuv->destroy();
199    delete m_tempPicYuv;
200    m_tempPicYuv = NULL;
[56]201  }
202
[872]203  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
[443]204  {
[872]205    if(m_offsetClipTable[compIdx])
206    {
207      delete[] m_offsetClipTable[compIdx]; m_offsetClipTable[compIdx] = NULL;
208    }
[443]209  }
[872]210  if( m_signTable )
[443]211  {
[872]212    delete[] m_signTable; m_signTable = NULL;
[443]213  }
[872]214}
[56]215
[872]216Void TComSampleAdaptiveOffset::invertQuantOffsets(Int compIdx, Int typeIdc, Int typeAuxInfo, Int* dstOffsets, Int* srcOffsets)
217{
218  Int codedOffset[MAX_NUM_SAO_CLASSES];
219
220  ::memcpy(codedOffset, srcOffsets, sizeof(Int)*MAX_NUM_SAO_CLASSES);
221  ::memset(dstOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
222
223  if(typeIdc == SAO_TYPE_START_BO)
[56]224  {
[872]225    for(Int i=0; i< 4; i++)
226    {
227      dstOffsets[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES] = codedOffset[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES]*(1<<m_offsetStepLog2[compIdx]);
228    }
[56]229  }
[872]230  else //EO
[56]231  {
[872]232    for(Int i=0; i< NUM_SAO_EO_CLASSES; i++)
233    {
234      dstOffsets[i] = codedOffset[i] *(1<<m_offsetStepLog2[compIdx]);
235    }
236    assert(dstOffsets[SAO_CLASS_EO_PLAIN] == 0); //keep EO plain offset as zero
[56]237  }
238
239}
240
[872]241Int TComSampleAdaptiveOffset::getMergeList(TComPic* pic, Int ctu, SAOBlkParam* blkParams, std::vector<SAOBlkParam*>& mergeList)
[56]242{
[872]243  Int ctuX = ctu % m_numCTUInWidth;
244  Int ctuY = ctu / m_numCTUInWidth;
245  Int mergedCTUPos;
246  Int numValidMergeCandidates = 0;
[56]247
[872]248  for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++)
249  {
250    SAOBlkParam* mergeCandidate = NULL;
[56]251
[872]252    switch(mergeType)
253    {
254    case SAO_MERGE_ABOVE:
255      {
256        if(ctuY > 0)
257        {
258          mergedCTUPos = ctu- m_numCTUInWidth;
259          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
260          {
261            mergeCandidate = &(blkParams[mergedCTUPos]);
262          }
263        }
264      }
265      break;
266    case SAO_MERGE_LEFT:
267      {
268        if(ctuX > 0)
269        {
270          mergedCTUPos = ctu- 1;
271          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
272          {
273            mergeCandidate = &(blkParams[mergedCTUPos]);
274          }
275        }
276      }
277      break;
278    default:
279      {
280        printf("not a supported merge type");
281        assert(0);
282        exit(-1);
283      }
284    }
[56]285
[872]286    mergeList.push_back(mergeCandidate);
287    if (mergeCandidate != NULL)
288    {
289      numValidMergeCandidates++;
290    }
291  }
[56]292
[872]293  return numValidMergeCandidates;
294}
[56]295
296
[872]297Void TComSampleAdaptiveOffset::reconstructBlkSAOParam(SAOBlkParam& recParam, std::vector<SAOBlkParam*>& mergeList)
298{
299  for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
[56]300  {
[872]301    SAOOffset& offsetParam = recParam[compIdx];
[56]302
[872]303    if(offsetParam.modeIdc == SAO_MODE_OFF)
304    {
305      continue;
306    }
[56]307
[872]308    switch(offsetParam.modeIdc)
309    {
310    case SAO_MODE_NEW:
311      {
312        invertQuantOffsets(compIdx, offsetParam.typeIdc, offsetParam.typeAuxInfo, offsetParam.offset, offsetParam.offset);
313      }
314      break;
315    case SAO_MODE_MERGE:
316      {
317        SAOBlkParam* mergeTarget = mergeList[offsetParam.typeIdc];
318        assert(mergeTarget != NULL);
[56]319
[872]320        offsetParam = (*mergeTarget)[compIdx];
321      }
322      break;
323    default:
324      {
325        printf("Not a supported mode");
326        assert(0);
327        exit(-1);
328      }
329    }
[56]330  }
331}
332
[872]333Void TComSampleAdaptiveOffset::reconstructBlkSAOParams(TComPic* pic, SAOBlkParam* saoBlkParams)
[56]334{
[872]335  m_picSAOEnabled[SAO_Y] = m_picSAOEnabled[SAO_Cb] = m_picSAOEnabled[SAO_Cr] = false;
336
337  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
[56]338  {
[872]339    std::vector<SAOBlkParam*> mergeList;
340    getMergeList(pic, ctu, saoBlkParams, mergeList);
[56]341
[872]342    reconstructBlkSAOParam(saoBlkParams[ctu], mergeList);
343
344    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
[56]345    {
[872]346      if(saoBlkParams[ctu][compIdx].modeIdc != SAO_MODE_OFF)
[56]347      {
[872]348        m_picSAOEnabled[compIdx] = true;
[56]349      }
350    }
351  }
352
353
354}
355
356
[872]357Void TComSampleAdaptiveOffset::offsetBlock(Int compIdx, Int typeIdx, Int* offset 
358                                          , Pel* srcBlk, Pel* resBlk, Int srcStride, Int resStride,  Int width, Int height
359                                          , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail)
[56]360{
[872]361  if(m_lineBufWidth != m_maxCUWidth)
[56]362  {
[872]363    m_lineBufWidth = m_maxCUWidth;
364   
365    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
366    m_signLineBuf1 = new Char[m_lineBufWidth+1];
367   
368    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
369    m_signLineBuf2 = new Char[m_lineBufWidth+1];
[56]370  }
371
[872]372  Int* offsetClip = m_offsetClip[compIdx];
[56]373
[872]374  Int x,y, startX, startY, endX, endY, edgeType;
375  Int firstLineStartX, firstLineEndX, lastLineStartX, lastLineEndX;
376  Char signLeft, signRight, signDown;
[56]377
[872]378  Pel* srcLine = srcBlk;
379  Pel* resLine = resBlk;
[56]380
[872]381  switch(typeIdx)
[56]382  {
[872]383  case SAO_TYPE_EO_0:
[56]384    {
[872]385      offset += 2;
386      startX = isLeftAvail ? 0 : 1;
387      endX   = isRightAvail ? width : (width -1);
[56]388      for (y=0; y< height; y++)
389      {
[872]390        signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
[56]391        for (x=startX; x< endX; x++)
392        {
[872]393          signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
394          edgeType =  signRight + signLeft;
[56]395          signLeft  = -signRight;
396
[872]397          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]398        }
[872]399        srcLine  += srcStride;
400        resLine += resStride;
[56]401      }
[872]402
[56]403    }
[872]404    break;
405  case SAO_TYPE_EO_90:
[56]406    {
[872]407      offset += 2;
408      Char *signUpLine = m_signLineBuf1;
409
410      startY = isAboveAvail ? 0 : 1;
411      endY   = isBelowAvail ? height : height-1;
412      if (!isAboveAvail)
[56]413      {
[872]414        srcLine += srcStride;
415        resLine += resStride;
[56]416      }
[872]417
418      Pel* srcLineAbove= srcLine- srcStride;
[56]419      for (x=0; x< width; x++)
420      {
[872]421        signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
[56]422      }
[872]423
424      Pel* srcLineBelow;
[56]425      for (y=startY; y<endY; y++)
426      {
[872]427        srcLineBelow= srcLine+ srcStride;
428
[56]429        for (x=0; x< width; x++)
430        {
[872]431          signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
432          edgeType = signDown + signUpLine[x];
433          signUpLine[x]= -signDown;
[56]434
[872]435          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]436        }
[872]437        srcLine += srcStride;
438        resLine += resStride;
[56]439      }
[872]440
[56]441    }
[872]442    break;
443  case SAO_TYPE_EO_135:
[56]444    {
[872]445      offset += 2;
446      Char *signUpLine, *signDownLine, *signTmpLine;
[56]447
[872]448      signUpLine  = m_signLineBuf1;
449      signDownLine= m_signLineBuf2;
[56]450
[872]451      startX = isLeftAvail ? 0 : 1 ;
452      endX   = isRightAvail ? width : (width-1);
453
454      //prepare 2nd line's upper sign
455      Pel* srcLineBelow= srcLine+ srcStride;
[56]456      for (x=startX; x< endX+1; x++)
457      {
[872]458        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x- 1]];
[56]459      }
460
461      //1st line
[872]462      Pel* srcLineAbove= srcLine- srcStride;
463      firstLineStartX = isAboveLeftAvail ? 0 : 1;
464      firstLineEndX   = isAboveAvail? endX: 1;
465      for(x= firstLineStartX; x< firstLineEndX; x++)
[56]466      {
[872]467        edgeType  =  m_sign[srcLine[x] - srcLineAbove[x- 1]] - signUpLine[x+1];
468        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]469      }
[872]470      srcLine  += srcStride;
471      resLine  += resStride;
[56]472
473
474      //middle lines
475      for (y= 1; y< height-1; y++)
476      {
[872]477        srcLineBelow= srcLine+ srcStride;
478
[56]479        for (x=startX; x<endX; x++)
480        {
[872]481          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x+ 1]] ;
482          edgeType =  signDown + signUpLine[x];
483          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]484
[872]485          signDownLine[x+1] = -signDown; 
[56]486        }
[872]487        signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
[56]488
[872]489        signTmpLine  = signUpLine;
490        signUpLine   = signDownLine;
491        signDownLine = signTmpLine;
[56]492
[872]493        srcLine += srcStride;
494        resLine += resStride;
[56]495      }
496
497      //last line
[872]498      srcLineBelow= srcLine+ srcStride;
499      lastLineStartX = isBelowAvail ? startX : (width -1);
500      lastLineEndX   = isBelowRightAvail ? width : (width -1);
501      for(x= lastLineStartX; x< lastLineEndX; x++)
[56]502      {
[872]503        edgeType =  m_sign[srcLine[x] - srcLineBelow[x+ 1]] + signUpLine[x];
504        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
505
[56]506      }
[872]507    }
508    break;
509  case SAO_TYPE_EO_45:
[56]510    {
[872]511      offset += 2;
512      Char *signUpLine = m_signLineBuf1+1;
[56]513
[872]514      startX = isLeftAvail ? 0 : 1;
515      endX   = isRightAvail ? width : (width -1);
516
[56]517      //prepare 2nd line upper sign
[872]518      Pel* srcLineBelow= srcLine+ srcStride;
[56]519      for (x=startX-1; x< endX; x++)
520      {
[872]521        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
[56]522      }
523
524
525      //first line
[872]526      Pel* srcLineAbove= srcLine- srcStride;
527      firstLineStartX = isAboveAvail ? startX : (width -1 );
528      firstLineEndX   = isAboveRightAvail ? width : (width-1);
529      for(x= firstLineStartX; x< firstLineEndX; x++)
[56]530      {
[872]531        edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] -signUpLine[x-1];
532        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]533      }
[872]534      srcLine += srcStride;
535      resLine += resStride;
[56]536
537      //middle lines
538      for (y= 1; y< height-1; y++)
539      {
[872]540        srcLineBelow= srcLine+ srcStride;
541
[56]542        for(x= startX; x< endX; x++)
543        {
[872]544          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
545          edgeType =  signDown + signUpLine[x];
546          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
547          signUpLine[x-1] = -signDown; 
[56]548        }
[872]549        signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
550        srcLine  += srcStride;
551        resLine += resStride;
[56]552      }
553
554      //last line
[872]555      srcLineBelow= srcLine+ srcStride;
556      lastLineStartX = isBelowLeftAvail ? 0 : 1;
557      lastLineEndX   = isBelowAvail ? endX : 1;
558      for(x= lastLineStartX; x< lastLineEndX; x++)
[56]559      {
[872]560        edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + signUpLine[x];
561        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
[56]562
563      }
[872]564    }
565    break;
566  case SAO_TYPE_BO:
[56]567    {
[872]568      Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
[56]569      for (y=0; y< height; y++)
570      {
571        for (x=0; x< width; x++)
572        {
[872]573          resLine[x] = offsetClip[ srcLine[x] + offset[srcLine[x] >> shiftBits] ];
[56]574        }
[872]575        srcLine += srcStride;
576        resLine += resStride;
[56]577      }
578    }
[872]579    break;
580  default:
581    {
582      printf("Not a supported SAO types\n");
583      assert(0);
584      exit(-1);
585    }
[56]586  }
587
[872]588
[56]589}
590
[872]591Void TComSampleAdaptiveOffset::offsetCTU(Int ctu, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic)
[56]592{
[872]593  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
[56]594
[872]595  if( 
596    (saoblkParam[SAO_Y ].modeIdc == SAO_MODE_OFF) &&
597    (saoblkParam[SAO_Cb].modeIdc == SAO_MODE_OFF) &&
598    (saoblkParam[SAO_Cr].modeIdc == SAO_MODE_OFF)
599    )
[56]600  {
601    return;
602  }
603
[872]604  //block boundary availability
605  pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
[56]606
[872]607  Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
608  Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
609  Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
610  Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
[56]611
[872]612  for(Int compIdx= 0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
[56]613  {
[872]614    SAOOffset& ctbOffset = saoblkParam[compIdx];
[56]615
[872]616    if(ctbOffset.modeIdc != SAO_MODE_OFF)
[56]617    {
[872]618      Bool isLuma     = (compIdx == SAO_Y);
619      Int  formatShift= isLuma?0:1;
[608]620
[872]621      Int  blkWidth   = (width  >> formatShift);
622      Int  blkHeight  = (height >> formatShift);
623      Int  blkYPos    = (yPos   >> formatShift);
624      Int  blkXPos    = (xPos   >> formatShift);
[56]625
[872]626      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
627      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
[56]628
[872]629      Int  resStride  = isLuma?resYuv->getStride():resYuv->getCStride();
630      Pel* resBlk     = getPicBuf(resYuv, compIdx)+ blkYPos*resStride+ blkXPos;
[56]631
[872]632      offsetBlock( compIdx, ctbOffset.typeIdc, ctbOffset.offset
633                  , srcBlk, resBlk, srcStride, resStride, blkWidth, blkHeight
634                  , isLeftAvail, isRightAvail
635                  , isAboveAvail, isBelowAvail
636                  , isAboveLeftAvail, isAboveRightAvail
637                  , isBelowLeftAvail, isBelowRightAvail
638                  );
639    }
640  } //compIdx
[56]641
[872]642}
[56]643
644
[872]645Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pDecPic)
646{
647  if(!m_picSAOEnabled[SAO_Y] && !m_picSAOEnabled[SAO_Cb] && !m_picSAOEnabled[SAO_Cr])
648  {
649    return;
[56]650  }
[872]651  TComPicYuv* resYuv = pDecPic->getPicYuvRec();
652  TComPicYuv* srcYuv = m_tempPicYuv;
653  resYuv->copyToPic(srcYuv);
654  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
[56]655  {
[872]656    offsetCTU(ctu, srcYuv, resYuv, (pDecPic->getPicSym()->getSAOBlkParam())[ctu], pDecPic);
657  } //ctu
[56]658}
[872]659
660
661Pel* TComSampleAdaptiveOffset::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
[56]662{
[872]663  Pel* pBuf = NULL;
664  switch(compIdx)
[56]665  {
[872]666  case SAO_Y:
[56]667    {
[872]668      pBuf = pPicYuv->getLumaAddr();
[56]669    }
[872]670    break;
671  case SAO_Cb:
[56]672    {
[872]673      pBuf = pPicYuv->getCbAddr();
[56]674    }
[872]675    break;
676  case SAO_Cr:
[443]677    {
[872]678      pBuf = pPicYuv->getCrAddr();
[443]679    }
[56]680    break;
681  default:
682    {
[872]683      printf("Not a legal component ID for SAO\n");
684      assert(0);
685      exit(-1);
[56]686    }
687  }
688
[872]689  return pBuf;
[56]690}
691
[872]692/** PCM LF disable process.
[443]693 * \param pcPic picture (TComPic) pointer
694 * \returns Void
695 *
696 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
697 */
698Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic)
699{
700  xPCMRestoration(pcPic);
701}
702
703/** Picture-level PCM restoration.
704 * \param pcPic picture (TComPic) pointer
705 * \returns Void
706 */
707Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic)
708{
709  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
[608]710
711  if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnableFlag())
[443]712  {
[608]713    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
714    {
715      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
716
717      xPCMCURestoration(pcCU, 0, 0); 
718    } 
[443]719  }
720}
721
722/** PCM CU restoration.
723 * \param pcCU pointer to current CU
724 * \param uiAbsPartIdx part index
725 * \param uiDepth CU depth
726 * \returns Void
727 */
728Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
729{
730  TComPic* pcPic     = pcCU->getPic();
731  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
732  UInt uiQNumParts   = uiCurNumParts>>2;
733
734  // go to sub-CU
735  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
736  {
737    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
738    {
739      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
740      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
741      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
742        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
743    }
744    return;
745  }
746
747  // restore PCM samples
748  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx))
749  {
750    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
751    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
752    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
753  }
754}
755
756/** PCM sample restoration.
757 * \param pcCU pointer to current CU
758 * \param uiAbsPartIdx part index
759 * \param uiDepth CU depth
760 * \param ttText texture component type
761 * \returns Void
762 */
763Void TComSampleAdaptiveOffset::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
764{
765  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
766  Pel* piSrc;
767  Pel* piPcm;
768  UInt uiStride;
769  UInt uiWidth;
770  UInt uiHeight;
771  UInt uiPcmLeftShiftBit; 
772  UInt uiX, uiY;
773  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
774  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
775  UInt uiChromaOffset = uiLumaOffset>>2;
776
777  if( ttText == TEXT_LUMA )
778  {
779    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
780    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
781    uiStride  = pcPicYuvRec->getStride();
782    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
783    uiHeight = (g_uiMaxCUHeight >> uiDepth);
[608]784    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
[443]785    {
786      uiPcmLeftShiftBit = 0;
787    }
788    else
789    {
[608]790      uiPcmLeftShiftBit = g_bitDepthY - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
[443]791    }
792  }
793  else
794  {
795    if( ttText == TEXT_CHROMA_U )
796    {
797      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
798      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
799    }
800    else
801    {
802      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
803      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
804    }
805
806    uiStride = pcPicYuvRec->getCStride();
807    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
808    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
[608]809    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
[443]810    {
811      uiPcmLeftShiftBit = 0;
812    }
813    else
814    {
[608]815      uiPcmLeftShiftBit = g_bitDepthC - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
[443]816    }
817  }
818
819  for( uiY = 0; uiY < uiHeight; uiY++ )
820  {
821    for( uiX = 0; uiX < uiWidth; uiX++ )
822    {
823      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
824    }
825    piPcm += uiWidth;
826    piSrc += uiStride;
827  }
828}
[608]829
[56]830//! \}
Note: See TracBrowser for help on using the repository browser.