source: 3DVCSoftware/branches/HTM-10.0rc1-dev0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 852

Last change on this file since 852 was 845, checked in by tech, 11 years ago

Fixed missing braces.
Added some generic functionality for debugging.

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