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

Last change on this file since 614 was 595, checked in by seregin, 11 years ago

merge with SHM-5.0-dev branch

  • Property svn:eol-style set to native
File size: 23.7 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  m_signTable = NULL; 
113
114 
115  m_lineBufWidth = 0;
116  m_signLineBuf1 = NULL;
117  m_signLineBuf2 = NULL;
118}
119
120
121TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset()
122{
123  destroy();
124 
125  if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
126  if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
127}
128
129#if AUXILIARY_PICTURES
130Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, ChromaFormat chromaFormatIDC, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
131#else
132Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
133#endif
134{
135  destroy();
136
137  m_picWidth = picWidth;   
138  m_picHeight= picHeight;
139  m_maxCUWidth= maxCUWidth; 
140  m_maxCUHeight= maxCUHeight;
141
142  m_numCTUInWidth = (m_picWidth/m_maxCUWidth) + ((m_picWidth % m_maxCUWidth)?1:0);
143  m_numCTUInHeight= (m_picHeight/m_maxCUHeight) + ((m_picHeight % m_maxCUHeight)?1:0);
144  m_numCTUsPic = m_numCTUInHeight*m_numCTUInWidth;
145
146  //temporary picture buffer
147  if ( !m_tempPicYuv )
148  {
149    m_tempPicYuv = new TComPicYuv;
150#if AUXILIARY_PICTURES
151    m_tempPicYuv->create( m_picWidth, m_picHeight, chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
152#else
153    m_tempPicYuv->create( m_picWidth, m_picHeight, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
154#endif
155  }
156
157  //bit-depth related
158  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
159  {
160    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC;
161    m_offsetStepLog2  [compIdx] = max(bitDepthSample - MAX_SAO_TRUNCATED_BITDEPTH, 0);
162    g_saoMaxOffsetQVal[compIdx] = (1<<(min(bitDepthSample,MAX_SAO_TRUNCATED_BITDEPTH)-5))-1; //Table 9-32, inclusive
163  }
164
165  //look-up table for clipping
166  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
167  {
168    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC; //exclusive
169    Int maxSampleValue = (1<< bitDepthSample); //exclusive
170    Int maxOffsetValue = (g_saoMaxOffsetQVal[compIdx] << m_offsetStepLog2[compIdx]); 
171
172    m_offsetClipTable[compIdx] = new Int[(maxSampleValue + maxOffsetValue -1)+ (maxOffsetValue)+1 ]; //positive & negative range plus 0
173    m_offsetClip[compIdx] = &(m_offsetClipTable[compIdx][maxOffsetValue]);
174
175    //assign clipped values
176    Int* offsetClipPtr = m_offsetClip[compIdx];
177    for(Int k=0; k< maxSampleValue; k++)
178    {
179      *(offsetClipPtr + k) = k;
180    }
181    for(Int k=0; k< maxOffsetValue; k++ )
182    {
183      *(offsetClipPtr + maxSampleValue+ k) = maxSampleValue-1;
184      *(offsetClipPtr -k -1 )              = 0;
185    }
186    if(compIdx == SAO_Y) //g_bitDepthY is always larger than or equal to g_bitDepthC
187    {
188      m_signTable = new Short[ 2*(maxSampleValue-1) + 1 ];
189      m_sign = &(m_signTable[maxSampleValue-1]);
190
191      m_sign[0] = 0;
192      for(Int k=1; k< maxSampleValue; k++)
193      {
194        m_sign[k] = 1;
195        m_sign[-k]= -1;
196      }
197    }
198  } 
199
200}
201
202Void TComSampleAdaptiveOffset::destroy()
203{
204  if ( m_tempPicYuv )
205  {
206    m_tempPicYuv->destroy();
207    delete m_tempPicYuv;
208    m_tempPicYuv = NULL;
209  }
210
211  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
212  {
213    if(m_offsetClipTable[compIdx])
214    {
215      delete[] m_offsetClipTable[compIdx]; m_offsetClipTable[compIdx] = NULL;
216    }
217  }
218  if( m_signTable )
219  {
220    delete[] m_signTable; m_signTable = NULL;
221  }
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        signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
399        for (x=startX; x< endX; x++)
400        {
401          signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
402          edgeType =  signRight + signLeft;
403          signLeft  = -signRight;
404
405          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
406        }
407        srcLine  += srcStride;
408        resLine += resStride;
409      }
410
411    }
412    break;
413  case SAO_TYPE_EO_90:
414    {
415      offset += 2;
416      Char *signUpLine = m_signLineBuf1;
417
418      startY = isAboveAvail ? 0 : 1;
419      endY   = isBelowAvail ? height : height-1;
420      if (!isAboveAvail)
421      {
422        srcLine += srcStride;
423        resLine += resStride;
424      }
425
426      Pel* srcLineAbove= srcLine- srcStride;
427      for (x=0; x< width; x++)
428      {
429        signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
430      }
431
432      Pel* srcLineBelow;
433      for (y=startY; y<endY; y++)
434      {
435        srcLineBelow= srcLine+ srcStride;
436
437        for (x=0; x< width; x++)
438        {
439          signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
440          edgeType = signDown + signUpLine[x];
441          signUpLine[x]= -signDown;
442
443          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
444        }
445        srcLine += srcStride;
446        resLine += resStride;
447      }
448
449    }
450    break;
451  case SAO_TYPE_EO_135:
452    {
453      offset += 2;
454      Char *signUpLine, *signDownLine, *signTmpLine;
455
456      signUpLine  = m_signLineBuf1;
457      signDownLine= m_signLineBuf2;
458
459      startX = isLeftAvail ? 0 : 1 ;
460      endX   = isRightAvail ? width : (width-1);
461
462      //prepare 2nd line's upper sign
463      Pel* srcLineBelow= srcLine+ srcStride;
464      for (x=startX; x< endX+1; x++)
465      {
466        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x- 1]];
467      }
468
469      //1st line
470      Pel* srcLineAbove= srcLine- srcStride;
471      firstLineStartX = isAboveLeftAvail ? 0 : 1;
472      firstLineEndX   = isAboveAvail? endX: 1;
473      for(x= firstLineStartX; x< firstLineEndX; x++)
474      {
475        edgeType  =  m_sign[srcLine[x] - srcLineAbove[x- 1]] - signUpLine[x+1];
476        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
477      }
478      srcLine  += srcStride;
479      resLine  += resStride;
480
481
482      //middle lines
483      for (y= 1; y< height-1; y++)
484      {
485        srcLineBelow= srcLine+ srcStride;
486
487        for (x=startX; x<endX; x++)
488        {
489          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x+ 1]] ;
490          edgeType =  signDown + signUpLine[x];
491          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
492
493          signDownLine[x+1] = -signDown; 
494        }
495        signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
496
497        signTmpLine  = signUpLine;
498        signUpLine   = signDownLine;
499        signDownLine = signTmpLine;
500
501        srcLine += srcStride;
502        resLine += resStride;
503      }
504
505      //last line
506      srcLineBelow= srcLine+ srcStride;
507      lastLineStartX = isBelowAvail ? startX : (width -1);
508      lastLineEndX   = isBelowRightAvail ? width : (width -1);
509      for(x= lastLineStartX; x< lastLineEndX; x++)
510      {
511        edgeType =  m_sign[srcLine[x] - srcLineBelow[x+ 1]] + signUpLine[x];
512        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
513
514      }
515    }
516    break;
517  case SAO_TYPE_EO_45:
518    {
519      offset += 2;
520      Char *signUpLine = m_signLineBuf1+1;
521
522      startX = isLeftAvail ? 0 : 1;
523      endX   = isRightAvail ? width : (width -1);
524
525      //prepare 2nd line upper sign
526      Pel* srcLineBelow= srcLine+ srcStride;
527      for (x=startX-1; x< endX; x++)
528      {
529        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
530      }
531
532
533      //first line
534      Pel* srcLineAbove= srcLine- srcStride;
535      firstLineStartX = isAboveAvail ? startX : (width -1 );
536      firstLineEndX   = isAboveRightAvail ? width : (width-1);
537      for(x= firstLineStartX; x< firstLineEndX; x++)
538      {
539        edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] -signUpLine[x-1];
540        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
541      }
542      srcLine += srcStride;
543      resLine += resStride;
544
545      //middle lines
546      for (y= 1; y< height-1; y++)
547      {
548        srcLineBelow= srcLine+ srcStride;
549
550        for(x= startX; x< endX; x++)
551        {
552          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
553          edgeType =  signDown + signUpLine[x];
554          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
555          signUpLine[x-1] = -signDown; 
556        }
557        signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
558        srcLine  += srcStride;
559        resLine += resStride;
560      }
561
562      //last line
563      srcLineBelow= srcLine+ srcStride;
564      lastLineStartX = isBelowLeftAvail ? 0 : 1;
565      lastLineEndX   = isBelowAvail ? endX : 1;
566      for(x= lastLineStartX; x< lastLineEndX; x++)
567      {
568        edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + signUpLine[x];
569        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
570
571      }
572    }
573    break;
574  case SAO_TYPE_BO:
575    {
576      Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
577      for (y=0; y< height; y++)
578      {
579        for (x=0; x< width; x++)
580        {
581          resLine[x] = offsetClip[ srcLine[x] + offset[srcLine[x] >> shiftBits] ];
582        }
583        srcLine += srcStride;
584        resLine += resStride;
585      }
586    }
587    break;
588  default:
589    {
590      printf("Not a supported SAO types\n");
591      assert(0);
592      exit(-1);
593    }
594  }
595
596
597}
598
599Void TComSampleAdaptiveOffset::offsetCTU(Int ctu, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic)
600{
601  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
602
603  if( 
604    (saoblkParam[SAO_Y ].modeIdc == SAO_MODE_OFF) &&
605    (saoblkParam[SAO_Cb].modeIdc == SAO_MODE_OFF) &&
606    (saoblkParam[SAO_Cr].modeIdc == SAO_MODE_OFF)
607    )
608  {
609    return;
610  }
611
612  //block boundary availability
613  pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
614
615  Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
616  Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
617  Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
618  Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
619
620  for(Int compIdx= 0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
621  {
622    SAOOffset& ctbOffset = saoblkParam[compIdx];
623
624    if(ctbOffset.modeIdc != SAO_MODE_OFF)
625    {
626      Bool isLuma     = (compIdx == SAO_Y);
627      Int  formatShift= isLuma?0:1;
628
629      Int  blkWidth   = (width  >> formatShift);
630      Int  blkHeight  = (height >> formatShift);
631      Int  blkYPos    = (yPos   >> formatShift);
632      Int  blkXPos    = (xPos   >> formatShift);
633
634      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
635      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
636
637      Int  resStride  = isLuma?resYuv->getStride():resYuv->getCStride();
638      Pel* resBlk     = getPicBuf(resYuv, compIdx)+ blkYPos*resStride+ blkXPos;
639
640      offsetBlock( compIdx, ctbOffset.typeIdc, ctbOffset.offset
641                  , srcBlk, resBlk, srcStride, resStride, blkWidth, blkHeight
642                  , isLeftAvail, isRightAvail
643                  , isAboveAvail, isBelowAvail
644                  , isAboveLeftAvail, isAboveRightAvail
645                  , isBelowLeftAvail, isBelowRightAvail
646                  );
647    }
648  } //compIdx
649
650}
651
652
653Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pDecPic)
654{
655  if(!m_picSAOEnabled[SAO_Y] && !m_picSAOEnabled[SAO_Cb] && !m_picSAOEnabled[SAO_Cr])
656  {
657    return;
658  }
659  TComPicYuv* resYuv = pDecPic->getPicYuvRec();
660  TComPicYuv* srcYuv = m_tempPicYuv;
661  resYuv->copyToPic(srcYuv);
662  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
663  {
664    offsetCTU(ctu, srcYuv, resYuv, (pDecPic->getPicSym()->getSAOBlkParam())[ctu], pDecPic);
665  } //ctu
666}
667
668
669Pel* TComSampleAdaptiveOffset::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
670{
671  Pel* pBuf = NULL;
672  switch(compIdx)
673  {
674  case SAO_Y:
675    {
676      pBuf = pPicYuv->getLumaAddr();
677    }
678    break;
679  case SAO_Cb:
680    {
681      pBuf = pPicYuv->getCbAddr();
682    }
683    break;
684  case SAO_Cr:
685    {
686      pBuf = pPicYuv->getCrAddr();
687    }
688    break;
689  default:
690    {
691      printf("Not a legal component ID for SAO\n");
692      assert(0);
693      exit(-1);
694    }
695  }
696
697  return pBuf;
698}
699
700/** PCM LF disable process.
701 * \param pcPic picture (TComPic) pointer
702 * \returns Void
703 *
704 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
705 */
706Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic)
707{
708  xPCMRestoration(pcPic);
709}
710
711/** Picture-level PCM restoration.
712 * \param pcPic picture (TComPic) pointer
713 * \returns Void
714 */
715Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic)
716{
717  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
718
719  if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnableFlag())
720  {
721    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
722    {
723      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
724
725      xPCMCURestoration(pcCU, 0, 0); 
726    } 
727  }
728}
729
730/** PCM CU restoration.
731 * \param pcCU pointer to current CU
732 * \param uiAbsPartIdx part index
733 * \param uiDepth CU depth
734 * \returns Void
735 */
736Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
737{
738  TComPic* pcPic     = pcCU->getPic();
739  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
740  UInt uiQNumParts   = uiCurNumParts>>2;
741
742  // go to sub-CU
743  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
744  {
745    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
746    {
747      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
748      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
749#if REPN_FORMAT_IN_VPS
750      if( ( uiLPelX < pcCU->getSlice()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getPicHeightInLumaSamples() ) )
751#else
752      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
753#endif
754        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
755    }
756    return;
757  }
758
759  // restore PCM samples
760  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx))
761  {
762    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
763    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
764    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
765  }
766}
767
768/** PCM sample restoration.
769 * \param pcCU pointer to current CU
770 * \param uiAbsPartIdx part index
771 * \param uiDepth CU depth
772 * \param ttText texture component type
773 * \returns Void
774 */
775Void TComSampleAdaptiveOffset::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
776{
777  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
778  Pel* piSrc;
779  Pel* piPcm;
780  UInt uiStride;
781  UInt uiWidth;
782  UInt uiHeight;
783  UInt uiPcmLeftShiftBit; 
784  UInt uiX, uiY;
785  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
786  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
787  UInt uiChromaOffset = uiLumaOffset>>2;
788
789  if( ttText == TEXT_LUMA )
790  {
791    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
792    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
793    uiStride  = pcPicYuvRec->getStride();
794    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
795    uiHeight = (g_uiMaxCUHeight >> uiDepth);
796    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
797    {
798      uiPcmLeftShiftBit = 0;
799    }
800    else
801    {
802      uiPcmLeftShiftBit = g_bitDepthY - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
803    }
804  }
805  else
806  {
807    if( ttText == TEXT_CHROMA_U )
808    {
809      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
810      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
811    }
812    else
813    {
814      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
815      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
816    }
817
818    uiStride = pcPicYuvRec->getCStride();
819    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
820    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
821    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
822    {
823      uiPcmLeftShiftBit = 0;
824    }
825    else
826    {
827      uiPcmLeftShiftBit = g_bitDepthC - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
828    }
829  }
830
831  for( uiY = 0; uiY < uiHeight; uiY++ )
832  {
833    for( uiX = 0; uiX < uiWidth; uiX++ )
834    {
835      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
836    }
837    piPcm += uiWidth;
838    piSrc += uiStride;
839  }
840}
841
842//! \}
Note: See TracBrowser for help on using the repository browser.