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

Last change on this file since 1263 was 1260, checked in by seregin, 9 years ago

port rev 4257

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