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

Last change on this file since 851 was 609, checked in by seregin, 11 years ago

merge SAO fix from SHM-5.0-dev

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