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

Last change on this file since 1327 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

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