source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 1166

Last change on this file since 1166 was 1029, checked in by seregin, 10 years ago

merge with SHM-upgrade branch

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