source: 3DVCSoftware/branches/HTM-10.0rc1-dev0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 1288

Last change on this file since 1288 was 845, checked in by tech, 11 years ago

Fixed missing braces.
Added some generic functionality for debugging.

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