source: SHVCSoftware/trunk/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 1473

Last change on this file since 1473 was 713, checked in by seregin, 11 years ago

merge with SHM-6-dev

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