source: 3DVCSoftware/branches/HTM-13.1-dev0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 1314

Last change on this file since 1314 was 1175, checked in by tech, 10 years ago

Added direct dependency type for qtl.
Updated cfg files.
updated copy right headers.

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-2015, 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.