source: 3DVCSoftware/branches/HTM-11.2-dev3-Sharp/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 997

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