source: SHVCSoftware/branches/SHM-4.1-dev/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 1263

Last change on this file since 1263 was 532, checked in by seregin, 11 years ago

update to HM-12.1 base

  • Property svn:eol-style set to native
File size: 58.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-2013, 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 HM_CLEANUP_SAO
47UInt g_saoMaxOffsetQVal[NUM_SAO_COMPONENTS]; 
48
49SAOOffset::SAOOffset()
50{ 
51  reset();
52}
53
54SAOOffset::~SAOOffset()
55{
56
57}
58
59Void SAOOffset::reset()
60{
61  modeIdc = SAO_MODE_OFF;
62  typeIdc = -1;
63  typeAuxInfo = -1;
64  ::memset(offset, 0, sizeof(Int)* MAX_NUM_SAO_CLASSES);
65}
66
67const SAOOffset& SAOOffset::operator= (const SAOOffset& src)
68{
69  modeIdc = src.modeIdc;
70  typeIdc = src.typeIdc;
71  typeAuxInfo = src.typeAuxInfo;
72  ::memcpy(offset, src.offset, sizeof(Int)* MAX_NUM_SAO_CLASSES);
73
74  return *this;
75}
76
77
78SAOBlkParam::SAOBlkParam()
79{
80  reset();
81}
82
83SAOBlkParam::~SAOBlkParam()
84{
85
86}
87
88Void SAOBlkParam::reset()
89{
90  for(Int compIdx=0; compIdx< 3; compIdx++)
91  {
92    offsetParam[compIdx].reset();
93  }
94}
95
96const SAOBlkParam& SAOBlkParam::operator= (const SAOBlkParam& src)
97{
98  for(Int compIdx=0; compIdx< 3; compIdx++)
99  {
100    offsetParam[compIdx] = src.offsetParam[compIdx];
101  }
102  return *this;
103
104}
105
106TComSampleAdaptiveOffset::TComSampleAdaptiveOffset()
107{
108  m_tempPicYuv = NULL;
109  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
110  {
111    m_offsetClipTable[compIdx] = NULL;
112  }
113  m_signTable = NULL; 
114
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
130#if AUXILIARY_PICTURES
131Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, ChromaFormat chromaFormatIDC, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
132#else
133Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
134#endif
135{
136  destroy();
137
138  m_picWidth = picWidth;   
139  m_picHeight= picHeight;
140  m_maxCUWidth= maxCUWidth; 
141  m_maxCUHeight= maxCUHeight;
142
143  m_numCTUInWidth = (m_picWidth/m_maxCUWidth) + ((m_picWidth % m_maxCUWidth)?1:0);
144  m_numCTUInHeight= (m_picHeight/m_maxCUHeight) + ((m_picHeight % m_maxCUHeight)?1:0);
145  m_numCTUsPic = m_numCTUInHeight*m_numCTUInWidth;
146
147  //temporary picture buffer
148  if ( !m_tempPicYuv )
149  {
150    m_tempPicYuv = new TComPicYuv;
151#if AUXILIARY_PICTURES
152    m_tempPicYuv->create( m_picWidth, m_picHeight, chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
153#else
154    m_tempPicYuv->create( m_picWidth, m_picHeight, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
155#endif
156  }
157
158  //bit-depth related
159  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
160  {
161    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC;
162    m_offsetStepLog2  [compIdx] = max(bitDepthSample - MAX_SAO_TRUNCATED_BITDEPTH, 0);
163    g_saoMaxOffsetQVal[compIdx] = (1<<(min(bitDepthSample,MAX_SAO_TRUNCATED_BITDEPTH)-5))-1; //Table 9-32, inclusive
164  }
165
166  //look-up table for clipping
167  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
168  {
169    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC; //exclusive
170    Int maxSampleValue = (1<< bitDepthSample); //exclusive
171    Int maxOffsetValue = (g_saoMaxOffsetQVal[compIdx] << m_offsetStepLog2[compIdx]); 
172
173    m_offsetClipTable[compIdx] = new Int[(maxSampleValue + maxOffsetValue -1)+ (maxOffsetValue)+1 ]; //positive & negative range plus 0
174    m_offsetClip[compIdx] = &(m_offsetClipTable[compIdx][maxOffsetValue]);
175
176    //assign clipped values
177    Int* offsetClipPtr = m_offsetClip[compIdx];
178    for(Int k=0; k< maxSampleValue; k++)
179    {
180      *(offsetClipPtr + k) = k;
181    }
182    for(Int k=0; k< maxOffsetValue; k++ )
183    {
184      *(offsetClipPtr + maxSampleValue+ k) = maxSampleValue-1;
185      *(offsetClipPtr -k -1 )              = 0;
186    }
187    if(compIdx == SAO_Y) //g_bitDepthY is always larger than or equal to g_bitDepthC
188    {
189      m_signTable = new Short[ 2*(maxSampleValue-1) + 1 ];
190      m_sign = &(m_signTable[maxSampleValue-1]);
191
192      m_sign[0] = 0;
193      for(Int k=1; k< maxSampleValue; k++)
194      {
195        m_sign[k] = 1;
196        m_sign[-k]= -1;
197      }
198    }
199  } 
200
201}
202
203Void TComSampleAdaptiveOffset::destroy()
204{
205  if ( m_tempPicYuv )
206  {
207    m_tempPicYuv->destroy();
208    delete m_tempPicYuv;
209    m_tempPicYuv = NULL;
210  }
211
212  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
213  {
214    if(m_offsetClipTable[compIdx])
215    {
216      delete[] m_offsetClipTable[compIdx]; m_offsetClipTable[compIdx] = NULL;
217    }
218  }
219  if( m_signTable )
220  {
221    delete[] m_signTable; m_signTable = NULL;
222  }
223}
224
225Void TComSampleAdaptiveOffset::invertQuantOffsets(Int compIdx, Int typeIdc, Int typeAuxInfo, Int* dstOffsets, Int* srcOffsets)
226{
227  Int codedOffset[MAX_NUM_SAO_CLASSES];
228
229  ::memcpy(codedOffset, srcOffsets, sizeof(Int)*MAX_NUM_SAO_CLASSES);
230  ::memset(dstOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
231
232  if(typeIdc == SAO_TYPE_START_BO)
233  {
234    for(Int i=0; i< 4; i++)
235    {
236      dstOffsets[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES] = codedOffset[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES]*(1<<m_offsetStepLog2[compIdx]);
237    }
238  }
239  else //EO
240  {
241    for(Int i=0; i< NUM_SAO_EO_CLASSES; i++)
242    {
243      dstOffsets[i] = codedOffset[i] *(1<<m_offsetStepLog2[compIdx]);
244    }
245    assert(dstOffsets[SAO_CLASS_EO_PLAIN] == 0); //keep EO plain offset as zero
246  }
247
248}
249
250Int TComSampleAdaptiveOffset::getMergeList(TComPic* pic, Int ctu, SAOBlkParam* blkParams, std::vector<SAOBlkParam*>& mergeList)
251{
252  Int ctuX = ctu % m_numCTUInWidth;
253  Int ctuY = ctu / m_numCTUInWidth;
254  Int mergedCTUPos;
255  Int numValidMergeCandidates = 0;
256
257  for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++)
258  {
259    SAOBlkParam* mergeCandidate = NULL;
260
261    switch(mergeType)
262    {
263    case SAO_MERGE_ABOVE:
264      {
265        if(ctuY > 0)
266        {
267          mergedCTUPos = ctu- m_numCTUInWidth;
268          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
269          {
270            mergeCandidate = &(blkParams[mergedCTUPos]);
271          }
272        }
273      }
274      break;
275    case SAO_MERGE_LEFT:
276      {
277        if(ctuX > 0)
278        {
279          mergedCTUPos = ctu- 1;
280          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
281          {
282            mergeCandidate = &(blkParams[mergedCTUPos]);
283          }
284        }
285      }
286      break;
287    default:
288      {
289        printf("not a supported merge type");
290        assert(0);
291        exit(-1);
292      }
293    }
294
295    mergeList.push_back(mergeCandidate);
296    if (mergeCandidate != NULL)
297    {
298      numValidMergeCandidates++;
299    }
300  }
301
302  return numValidMergeCandidates;
303}
304
305
306Void TComSampleAdaptiveOffset::reconstructBlkSAOParam(SAOBlkParam& recParam, std::vector<SAOBlkParam*>& mergeList)
307{
308  for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
309  {
310    SAOOffset& offsetParam = recParam[compIdx];
311
312    if(offsetParam.modeIdc == SAO_MODE_OFF)
313    {
314      continue;
315    }
316
317    switch(offsetParam.modeIdc)
318    {
319    case SAO_MODE_NEW:
320      {
321        invertQuantOffsets(compIdx, offsetParam.typeIdc, offsetParam.typeAuxInfo, offsetParam.offset, offsetParam.offset);
322      }
323      break;
324    case SAO_MODE_MERGE:
325      {
326        SAOBlkParam* mergeTarget = mergeList[offsetParam.typeIdc];
327        assert(mergeTarget != NULL);
328
329        offsetParam = (*mergeTarget)[compIdx];
330      }
331      break;
332    default:
333      {
334        printf("Not a supported mode");
335        assert(0);
336        exit(-1);
337      }
338    }
339  }
340}
341
342Void TComSampleAdaptiveOffset::reconstructBlkSAOParams(TComPic* pic, SAOBlkParam* saoBlkParams)
343{
344  m_picSAOEnabled[SAO_Y] = m_picSAOEnabled[SAO_Cb] = m_picSAOEnabled[SAO_Cr] = false;
345
346  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
347  {
348    std::vector<SAOBlkParam*> mergeList;
349    getMergeList(pic, ctu, saoBlkParams, mergeList);
350
351    reconstructBlkSAOParam(saoBlkParams[ctu], mergeList);
352
353    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
354    {
355      if(saoBlkParams[ctu][compIdx].modeIdc != SAO_MODE_OFF)
356      {
357        m_picSAOEnabled[compIdx] = true;
358      }
359    }
360  }
361
362
363}
364
365
366Void TComSampleAdaptiveOffset::offsetBlock(Int compIdx, Int typeIdx, Int* offset 
367                                          , Pel* srcBlk, Pel* resBlk, Int srcStride, Int resStride,  Int width, Int height
368                                          , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail)
369{
370  if(m_lineBufWidth != m_maxCUWidth)
371  {
372    m_lineBufWidth = m_maxCUWidth;
373   
374    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
375    m_signLineBuf1 = new Char[m_lineBufWidth+1];
376   
377    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
378    m_signLineBuf2 = new Char[m_lineBufWidth+1];
379  }
380
381  Int* offsetClip = m_offsetClip[compIdx];
382
383  Int x,y, startX, startY, endX, endY, edgeType;
384  Int firstLineStartX, firstLineEndX, lastLineStartX, lastLineEndX;
385  Char signLeft, signRight, signDown;
386
387  Pel* srcLine = srcBlk;
388  Pel* resLine = resBlk;
389
390  switch(typeIdx)
391  {
392  case SAO_TYPE_EO_0:
393    {
394      offset += 2;
395      startX = isLeftAvail ? 0 : 1;
396      endX   = isRightAvail ? width : (width -1);
397      for (y=0; y< height; y++)
398      {
399        signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
400        for (x=startX; x< endX; x++)
401        {
402          signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
403          edgeType =  signRight + signLeft;
404          signLeft  = -signRight;
405
406          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
407        }
408        srcLine  += srcStride;
409        resLine += resStride;
410      }
411
412    }
413    break;
414  case SAO_TYPE_EO_90:
415    {
416      offset += 2;
417      Char *signUpLine = m_signLineBuf1;
418
419      startY = isAboveAvail ? 0 : 1;
420      endY   = isBelowAvail ? height : height-1;
421      if (!isAboveAvail)
422      {
423        srcLine += srcStride;
424        resLine += resStride;
425      }
426
427      Pel* srcLineAbove= srcLine- srcStride;
428      for (x=0; x< width; x++)
429      {
430        signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
431      }
432
433      Pel* srcLineBelow;
434      for (y=startY; y<endY; y++)
435      {
436        srcLineBelow= srcLine+ srcStride;
437
438        for (x=0; x< width; x++)
439        {
440          signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
441          edgeType = signDown + signUpLine[x];
442          signUpLine[x]= -signDown;
443
444          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
445        }
446        srcLine += srcStride;
447        resLine += resStride;
448      }
449
450    }
451    break;
452  case SAO_TYPE_EO_135:
453    {
454      offset += 2;
455      Char *signUpLine, *signDownLine, *signTmpLine;
456
457      signUpLine  = m_signLineBuf1;
458      signDownLine= m_signLineBuf2;
459
460      startX = isLeftAvail ? 0 : 1 ;
461      endX   = isRightAvail ? width : (width-1);
462
463      //prepare 2nd line's upper sign
464      Pel* srcLineBelow= srcLine+ srcStride;
465      for (x=startX; x< endX+1; x++)
466      {
467        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x- 1]];
468      }
469
470      //1st line
471      Pel* srcLineAbove= srcLine- srcStride;
472      firstLineStartX = isAboveLeftAvail ? 0 : 1;
473      firstLineEndX   = isAboveAvail? endX: 1;
474      for(x= firstLineStartX; x< firstLineEndX; x++)
475      {
476        edgeType  =  m_sign[srcLine[x] - srcLineAbove[x- 1]] - signUpLine[x+1];
477        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
478      }
479      srcLine  += srcStride;
480      resLine  += resStride;
481
482
483      //middle lines
484      for (y= 1; y< height-1; y++)
485      {
486        srcLineBelow= srcLine+ srcStride;
487
488        for (x=startX; x<endX; x++)
489        {
490          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x+ 1]] ;
491          edgeType =  signDown + signUpLine[x];
492          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
493
494          signDownLine[x+1] = -signDown; 
495        }
496        signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
497
498        signTmpLine  = signUpLine;
499        signUpLine   = signDownLine;
500        signDownLine = signTmpLine;
501
502        srcLine += srcStride;
503        resLine += resStride;
504      }
505
506      //last line
507      srcLineBelow= srcLine+ srcStride;
508      lastLineStartX = isBelowAvail ? startX : (width -1);
509      lastLineEndX   = isBelowRightAvail ? width : (width -1);
510      for(x= lastLineStartX; x< lastLineEndX; x++)
511      {
512        edgeType =  m_sign[srcLine[x] - srcLineBelow[x+ 1]] + signUpLine[x];
513        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
514
515      }
516    }
517    break;
518  case SAO_TYPE_EO_45:
519    {
520      offset += 2;
521      Char *signUpLine = m_signLineBuf1+1;
522
523      startX = isLeftAvail ? 0 : 1;
524      endX   = isRightAvail ? width : (width -1);
525
526      //prepare 2nd line upper sign
527      Pel* srcLineBelow= srcLine+ srcStride;
528      for (x=startX-1; x< endX; x++)
529      {
530        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
531      }
532
533
534      //first line
535      Pel* srcLineAbove= srcLine- srcStride;
536      firstLineStartX = isAboveAvail ? startX : (width -1 );
537      firstLineEndX   = isAboveRightAvail ? width : (width-1);
538      for(x= firstLineStartX; x< firstLineEndX; x++)
539      {
540        edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] -signUpLine[x-1];
541        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
542      }
543      srcLine += srcStride;
544      resLine += resStride;
545
546      //middle lines
547      for (y= 1; y< height-1; y++)
548      {
549        srcLineBelow= srcLine+ srcStride;
550
551        for(x= startX; x< endX; x++)
552        {
553          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
554          edgeType =  signDown + signUpLine[x];
555          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
556          signUpLine[x-1] = -signDown; 
557        }
558        signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
559        srcLine  += srcStride;
560        resLine += resStride;
561      }
562
563      //last line
564      srcLineBelow= srcLine+ srcStride;
565      lastLineStartX = isBelowLeftAvail ? 0 : 1;
566      lastLineEndX   = isBelowAvail ? endX : 1;
567      for(x= lastLineStartX; x< lastLineEndX; x++)
568      {
569        edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + signUpLine[x];
570        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
571
572      }
573    }
574    break;
575  case SAO_TYPE_BO:
576    {
577      Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
578      for (y=0; y< height; y++)
579      {
580        for (x=0; x< width; x++)
581        {
582          resLine[x] = offsetClip[ srcLine[x] + offset[srcLine[x] >> shiftBits] ];
583        }
584        srcLine += srcStride;
585        resLine += resStride;
586      }
587    }
588    break;
589  default:
590    {
591      printf("Not a supported SAO types\n");
592      assert(0);
593      exit(-1);
594    }
595  }
596
597
598}
599
600Void TComSampleAdaptiveOffset::offsetCTU(Int ctu, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic)
601{
602  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
603
604  if( 
605    (saoblkParam[SAO_Y ].modeIdc == SAO_MODE_OFF) &&
606    (saoblkParam[SAO_Cb].modeIdc == SAO_MODE_OFF) &&
607    (saoblkParam[SAO_Cr].modeIdc == SAO_MODE_OFF)
608    )
609  {
610    return;
611  }
612
613  //block boundary availability
614  pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
615
616  Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
617  Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
618  Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
619  Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
620
621  for(Int compIdx= 0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
622  {
623    SAOOffset& ctbOffset = saoblkParam[compIdx];
624
625    if(ctbOffset.modeIdc != SAO_MODE_OFF)
626    {
627      Bool isLuma     = (compIdx == SAO_Y);
628      Int  formatShift= isLuma?0:1;
629
630      Int  blkWidth   = (width  >> formatShift);
631      Int  blkHeight  = (height >> formatShift);
632      Int  blkYPos    = (yPos   >> formatShift);
633      Int  blkXPos    = (xPos   >> formatShift);
634
635      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
636      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
637
638      Int  resStride  = isLuma?resYuv->getStride():resYuv->getCStride();
639      Pel* resBlk     = getPicBuf(resYuv, compIdx)+ blkYPos*resStride+ blkXPos;
640
641      offsetBlock( compIdx, ctbOffset.typeIdc, ctbOffset.offset
642                  , srcBlk, resBlk, srcStride, resStride, blkWidth, blkHeight
643                  , isLeftAvail, isRightAvail
644                  , isAboveAvail, isBelowAvail
645                  , isAboveLeftAvail, isAboveRightAvail
646                  , isBelowLeftAvail, isBelowRightAvail
647                  );
648    }
649  } //compIdx
650
651}
652
653
654Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pDecPic)
655{
656  if(!m_picSAOEnabled[SAO_Y] && !m_picSAOEnabled[SAO_Cb] && !m_picSAOEnabled[SAO_Cr])
657  {
658    return;
659  }
660  TComPicYuv* resYuv = pDecPic->getPicYuvRec();
661  TComPicYuv* srcYuv = m_tempPicYuv;
662  resYuv->copyToPic(srcYuv);
663  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
664  {
665    offsetCTU(ctu, srcYuv, resYuv, (pDecPic->getPicSym()->getSAOBlkParam())[ctu], pDecPic);
666  } //ctu
667}
668
669
670Pel* TComSampleAdaptiveOffset::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
671{
672  Pel* pBuf = NULL;
673  switch(compIdx)
674  {
675  case SAO_Y:
676    {
677      pBuf = pPicYuv->getLumaAddr();
678    }
679    break;
680  case SAO_Cb:
681    {
682      pBuf = pPicYuv->getCbAddr();
683    }
684    break;
685  case SAO_Cr:
686    {
687      pBuf = pPicYuv->getCrAddr();
688    }
689    break;
690  default:
691    {
692      printf("Not a legal component ID for SAO\n");
693      assert(0);
694      exit(-1);
695    }
696  }
697
698  return pBuf;
699}
700#else
701
702SAOParam::~SAOParam()
703{
704  for (Int i = 0 ; i<3; i++)
705  {
706    if (psSaoPart[i])
707    {
708      delete [] psSaoPart[i];
709    }
710  }
711}
712
713// ====================================================================================================================
714// Tables
715// ====================================================================================================================
716
717TComSampleAdaptiveOffset::TComSampleAdaptiveOffset()
718{
719  m_pClipTable = NULL;
720  m_pClipTableBase = NULL;
721  m_pChromaClipTable = NULL;
722  m_pChromaClipTableBase = NULL;
723  m_iOffsetBo = NULL;
724  m_iChromaOffsetBo = NULL;
725  m_lumaTableBo = NULL;
726  m_chromaTableBo = NULL;
727  m_iUpBuff1 = NULL;
728  m_iUpBuff2 = NULL;
729  m_iUpBufft = NULL;
730  ipSwap = NULL;
731
732  m_pTmpU1 = NULL;
733  m_pTmpU2 = NULL;
734  m_pTmpL1 = NULL;
735  m_pTmpL2 = NULL;
736}
737
738TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset()
739{
740
741}
742
743const Int TComSampleAdaptiveOffset::m_aiNumCulPartsLevel[5] =
744{
745  1,   //level 0
746  5,   //level 1
747  21,  //level 2
748  85,  //level 3
749  341, //level 4
750};
751
752const UInt TComSampleAdaptiveOffset::m_auiEoTable[9] =
753{
754  1, //0   
755  2, //1   
756  0, //2
757  3, //3
758  4, //4
759  0, //5 
760  0, //6 
761  0, //7
762  0
763};
764
765const Int TComSampleAdaptiveOffset::m_iNumClass[MAX_NUM_SAO_TYPE] =
766{
767  SAO_EO_LEN,
768  SAO_EO_LEN,
769  SAO_EO_LEN,
770  SAO_EO_LEN,
771  SAO_BO_LEN
772};
773
774const UInt TComSampleAdaptiveOffset::m_uiMaxDepth = SAO_MAX_DEPTH;
775
776
777/** convert Level Row Col to Idx
778 * \param   level,  row,  col
779 */
780Int  TComSampleAdaptiveOffset::convertLevelRowCol2Idx(Int level, Int row, Int col)
781{
782  Int idx;
783  if (level == 0)
784  {
785    idx = 0;
786  }
787  else if (level == 1)
788  {
789    idx = 1 + row*2 + col;
790  }
791  else if (level == 2)
792  {
793    idx = 5 + row*4 + col;
794  }
795  else if (level == 3)
796  {
797    idx = 21 + row*8 + col;
798  }
799  else // (level == 4)
800  {
801    idx = 85 + row*16 + col;
802  }
803  return idx;
804}
805
806/** create SampleAdaptiveOffset memory.
807 * \param
808 */
809Void TComSampleAdaptiveOffset::create( UInt uiSourceWidth, UInt uiSourceHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight )
810{
811  m_iPicWidth  = uiSourceWidth;
812  m_iPicHeight = uiSourceHeight;
813
814  m_uiMaxCUWidth  = uiMaxCUWidth;
815  m_uiMaxCUHeight = uiMaxCUHeight;
816
817  m_iNumCuInWidth  = m_iPicWidth / m_uiMaxCUWidth;
818  m_iNumCuInWidth += ( m_iPicWidth % m_uiMaxCUWidth ) ? 1 : 0;
819
820  m_iNumCuInHeight  = m_iPicHeight / m_uiMaxCUHeight;
821  m_iNumCuInHeight += ( m_iPicHeight % m_uiMaxCUHeight ) ? 1 : 0;
822
823  Int iMaxSplitLevelHeight = (Int)(logf((Float)m_iNumCuInHeight)/logf(2.0));
824  Int iMaxSplitLevelWidth  = (Int)(logf((Float)m_iNumCuInWidth )/logf(2.0));
825
826  m_uiMaxSplitLevel = (iMaxSplitLevelHeight < iMaxSplitLevelWidth)?(iMaxSplitLevelHeight):(iMaxSplitLevelWidth);
827  m_uiMaxSplitLevel = (m_uiMaxSplitLevel< m_uiMaxDepth)?(m_uiMaxSplitLevel):(m_uiMaxDepth);
828  /* various structures are overloaded to store per component data.
829   * m_iNumTotalParts must allow for sufficient storage in any allocated arrays */
830  m_iNumTotalParts  = max(3,m_aiNumCulPartsLevel[m_uiMaxSplitLevel]);
831
832  UInt uiPixelRangeY = 1 << g_bitDepthY;
833  UInt uiBoRangeShiftY = g_bitDepthY - SAO_BO_BITS;
834
835  m_lumaTableBo = new Pel [uiPixelRangeY];
836  for (Int k2=0; k2<uiPixelRangeY; k2++)
837  {
838    m_lumaTableBo[k2] = 1 + (k2>>uiBoRangeShiftY);
839  }
840
841  UInt uiPixelRangeC = 1 << g_bitDepthC;
842  UInt uiBoRangeShiftC = g_bitDepthC - SAO_BO_BITS;
843
844  m_chromaTableBo = new Pel [uiPixelRangeC];
845  for (Int k2=0; k2<uiPixelRangeC; k2++)
846  {
847    m_chromaTableBo[k2] = 1 + (k2>>uiBoRangeShiftC);
848  }
849
850  m_iUpBuff1 = new Int[m_iPicWidth+2];
851  m_iUpBuff2 = new Int[m_iPicWidth+2];
852  m_iUpBufft = new Int[m_iPicWidth+2];
853
854  m_iUpBuff1++;
855  m_iUpBuff2++;
856  m_iUpBufft++;
857  Pel i;
858
859  UInt uiMaxY  = (1 << g_bitDepthY) - 1;;
860  UInt uiMinY  = 0;
861
862  Int iCRangeExt = uiMaxY>>1;
863
864  m_pClipTableBase = new Pel[uiMaxY+2*iCRangeExt];
865  m_iOffsetBo      = new Int[uiMaxY+2*iCRangeExt];
866
867  for(i=0;i<(uiMinY+iCRangeExt);i++)
868  {
869    m_pClipTableBase[i] = uiMinY;
870  }
871
872  for(i=uiMinY+iCRangeExt;i<(uiMaxY+  iCRangeExt);i++)
873  {
874    m_pClipTableBase[i] = i-iCRangeExt;
875  }
876
877  for(i=uiMaxY+iCRangeExt;i<(uiMaxY+2*iCRangeExt);i++)
878  {
879    m_pClipTableBase[i] = uiMaxY;
880  }
881
882  m_pClipTable = &(m_pClipTableBase[iCRangeExt]);
883
884  UInt uiMaxC  = (1 << g_bitDepthC) - 1;
885  UInt uiMinC  = 0;
886
887  Int iCRangeExtC = uiMaxC>>1;
888
889  m_pChromaClipTableBase = new Pel[uiMaxC+2*iCRangeExtC];
890  m_iChromaOffsetBo      = new Int[uiMaxC+2*iCRangeExtC];
891
892  for(i=0;i<(uiMinC+iCRangeExtC);i++)
893  {
894    m_pChromaClipTableBase[i] = uiMinC;
895  }
896
897  for(i=uiMinC+iCRangeExtC;i<(uiMaxC+  iCRangeExtC);i++)
898  {
899    m_pChromaClipTableBase[i] = i-iCRangeExtC;
900  }
901
902  for(i=uiMaxC+iCRangeExtC;i<(uiMaxC+2*iCRangeExtC);i++)
903  {
904    m_pChromaClipTableBase[i] = uiMaxC;
905  }
906
907  m_pChromaClipTable = &(m_pChromaClipTableBase[iCRangeExtC]);
908
909  m_pTmpL1 = new Pel [m_uiMaxCUHeight+1];
910  m_pTmpL2 = new Pel [m_uiMaxCUHeight+1];
911  m_pTmpU1 = new Pel [m_iPicWidth];
912  m_pTmpU2 = new Pel [m_iPicWidth];
913}
914
915/** destroy SampleAdaptiveOffset memory.
916 * \param
917 */
918Void TComSampleAdaptiveOffset::destroy()
919{
920  if (m_pClipTableBase)
921  {
922    delete [] m_pClipTableBase; m_pClipTableBase = NULL;
923  }
924  if (m_iOffsetBo)
925  {
926    delete [] m_iOffsetBo; m_iOffsetBo = NULL;
927  }
928  if (m_lumaTableBo)
929  {
930    delete[] m_lumaTableBo; m_lumaTableBo = NULL;
931  }
932
933  if (m_pChromaClipTableBase)
934  {
935    delete [] m_pChromaClipTableBase; m_pChromaClipTableBase = NULL;
936  }
937  if (m_iChromaOffsetBo)
938  {
939    delete [] m_iChromaOffsetBo; m_iChromaOffsetBo = NULL;
940  }
941  if (m_chromaTableBo)
942  {
943    delete[] m_chromaTableBo; m_chromaTableBo = NULL;
944  }
945
946  if (m_iUpBuff1)
947  {
948    m_iUpBuff1--;
949    delete [] m_iUpBuff1; m_iUpBuff1 = NULL;
950  }
951  if (m_iUpBuff2)
952  {
953    m_iUpBuff2--;
954    delete [] m_iUpBuff2; m_iUpBuff2 = NULL;
955  }
956  if (m_iUpBufft)
957  {
958    m_iUpBufft--;
959    delete [] m_iUpBufft; m_iUpBufft = NULL;
960  }
961  if (m_pTmpL1)
962  {
963    delete [] m_pTmpL1; m_pTmpL1 = NULL;
964  }
965  if (m_pTmpL2)
966  {
967    delete [] m_pTmpL2; m_pTmpL2 = NULL;
968  }
969  if (m_pTmpU1)
970  {
971    delete [] m_pTmpU1; m_pTmpU1 = NULL;
972  }
973  if (m_pTmpU2)
974  {
975    delete [] m_pTmpU2; m_pTmpU2 = NULL;
976  }
977}
978
979/** allocate memory for SAO parameters
980 * \param    *pcSaoParam
981 */
982Void TComSampleAdaptiveOffset::allocSaoParam(SAOParam *pcSaoParam)
983{
984  pcSaoParam->iMaxSplitLevel = m_uiMaxSplitLevel;
985  pcSaoParam->psSaoPart[0] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
986  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,0);
987  pcSaoParam->psSaoPart[1] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
988  pcSaoParam->psSaoPart[2] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
989  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,1);
990  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,2);
991  pcSaoParam->numCuInWidth  = m_iNumCuInWidth;
992  pcSaoParam->numCuInHeight = m_iNumCuInHeight;
993  pcSaoParam->saoLcuParam[0] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
994  pcSaoParam->saoLcuParam[1] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
995  pcSaoParam->saoLcuParam[2] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
996}
997
998/** initialize SAO parameters
999 * \param    *pcSaoParam,  iPartLevel,  iPartRow,  iPartCol,  iParentPartIdx,  StartCUX,  EndCUX,  StartCUY,  EndCUY,  iYCbCr
1000 */
1001Void TComSampleAdaptiveOffset::initSAOParam(SAOParam *pcSaoParam, Int iPartLevel, Int iPartRow, Int iPartCol, Int iParentPartIdx, Int StartCUX, Int EndCUX, Int StartCUY, Int EndCUY, Int iYCbCr)
1002{
1003  Int j;
1004  Int iPartIdx = convertLevelRowCol2Idx(iPartLevel, iPartRow, iPartCol);
1005
1006  SAOQTPart* pSaoPart;
1007
1008  pSaoPart = &(pcSaoParam->psSaoPart[iYCbCr][iPartIdx]);
1009
1010  pSaoPart->PartIdx   = iPartIdx;
1011  pSaoPart->PartLevel = iPartLevel;
1012  pSaoPart->PartRow   = iPartRow;
1013  pSaoPart->PartCol   = iPartCol;
1014
1015  pSaoPart->StartCUX  = StartCUX;
1016  pSaoPart->EndCUX    = EndCUX;
1017  pSaoPart->StartCUY  = StartCUY;
1018  pSaoPart->EndCUY    = EndCUY;
1019
1020  pSaoPart->UpPartIdx = iParentPartIdx;
1021  pSaoPart->iBestType   = -1;
1022  pSaoPart->iLength     =  0;
1023
1024  pSaoPart->subTypeIdx = 0;
1025
1026  for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1027  {
1028    pSaoPart->iOffset[j] = 0;
1029  }
1030
1031  if(pSaoPart->PartLevel != m_uiMaxSplitLevel)
1032  {
1033    Int DownLevel    = (iPartLevel+1 );
1034    Int DownRowStart = (iPartRow << 1);
1035    Int DownColStart = (iPartCol << 1);
1036
1037    Int iDownRowIdx, iDownColIdx;
1038    Int NumCUWidth,  NumCUHeight;
1039    Int NumCULeft;
1040    Int NumCUTop;
1041
1042    Int DownStartCUX, DownStartCUY;
1043    Int DownEndCUX, DownEndCUY;
1044
1045    NumCUWidth  = EndCUX - StartCUX +1;
1046    NumCUHeight = EndCUY - StartCUY +1;
1047    NumCULeft   = (NumCUWidth  >> 1);
1048    NumCUTop    = (NumCUHeight >> 1);
1049
1050    DownStartCUX= StartCUX;
1051    DownEndCUX  = DownStartCUX + NumCULeft - 1;
1052    DownStartCUY= StartCUY;
1053    DownEndCUY  = DownStartCUY + NumCUTop  - 1;
1054    iDownRowIdx = DownRowStart + 0;
1055    iDownColIdx = DownColStart + 0;
1056
1057    pSaoPart->DownPartsIdx[0]= convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
1058
1059    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx, DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
1060
1061    DownStartCUX = StartCUX + NumCULeft;
1062    DownEndCUX   = EndCUX;
1063    DownStartCUY = StartCUY;
1064    DownEndCUY   = DownStartCUY + NumCUTop -1;
1065    iDownRowIdx  = DownRowStart + 0;
1066    iDownColIdx  = DownColStart + 1;
1067
1068    pSaoPart->DownPartsIdx[1] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
1069
1070    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx,  DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
1071
1072    DownStartCUX = StartCUX;
1073    DownEndCUX   = DownStartCUX + NumCULeft -1;
1074    DownStartCUY = StartCUY + NumCUTop;
1075    DownEndCUY   = EndCUY;
1076    iDownRowIdx  = DownRowStart + 1;
1077    iDownColIdx  = DownColStart + 0;
1078
1079    pSaoPart->DownPartsIdx[2] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
1080
1081    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx, DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
1082
1083    DownStartCUX = StartCUX+ NumCULeft;
1084    DownEndCUX   = EndCUX;
1085    DownStartCUY = StartCUY + NumCUTop;
1086    DownEndCUY   = EndCUY;
1087    iDownRowIdx  = DownRowStart + 1;
1088    iDownColIdx  = DownColStart + 1;
1089
1090    pSaoPart->DownPartsIdx[3] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
1091
1092    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx,DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
1093  }
1094  else
1095  {
1096    pSaoPart->DownPartsIdx[0]=pSaoPart->DownPartsIdx[1]= pSaoPart->DownPartsIdx[2]= pSaoPart->DownPartsIdx[3]= -1; 
1097  }
1098}
1099
1100/** free memory of SAO parameters
1101 * \param   pcSaoParam
1102 */
1103Void TComSampleAdaptiveOffset::freeSaoParam(SAOParam *pcSaoParam)
1104{
1105  delete [] pcSaoParam->psSaoPart[0];
1106  delete [] pcSaoParam->psSaoPart[1];
1107  delete [] pcSaoParam->psSaoPart[2];
1108  pcSaoParam->psSaoPart[0] = 0;
1109  pcSaoParam->psSaoPart[1] = 0;
1110  pcSaoParam->psSaoPart[2] = 0;
1111  if( pcSaoParam->saoLcuParam[0]) 
1112  {
1113    delete [] pcSaoParam->saoLcuParam[0]; pcSaoParam->saoLcuParam[0] = NULL;
1114  }
1115  if( pcSaoParam->saoLcuParam[1]) 
1116  {
1117    delete [] pcSaoParam->saoLcuParam[1]; pcSaoParam->saoLcuParam[1] = NULL;
1118  }
1119  if( pcSaoParam->saoLcuParam[2]) 
1120  {
1121    delete [] pcSaoParam->saoLcuParam[2]; pcSaoParam->saoLcuParam[2] = NULL;
1122  }
1123} 
1124
1125/** reset SAO parameters
1126 * \param   pcSaoParam
1127 */
1128Void TComSampleAdaptiveOffset::resetSAOParam(SAOParam *pcSaoParam)
1129{
1130  Int iNumComponet = 3;
1131  for(Int c=0; c<iNumComponet; c++)
1132  {
1133if (c<2)
1134  {
1135    pcSaoParam->bSaoFlag[c] = 0;
1136  }
1137    for(Int i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
1138    {
1139      pcSaoParam->psSaoPart[c][i].iBestType     = -1;
1140      pcSaoParam->psSaoPart[c][i].iLength       =  0;
1141      pcSaoParam->psSaoPart[c][i].bSplit        = false; 
1142      pcSaoParam->psSaoPart[c][i].bProcessed    = false;
1143      pcSaoParam->psSaoPart[c][i].dMinCost      = MAX_DOUBLE;
1144      pcSaoParam->psSaoPart[c][i].iMinDist      = MAX_INT;
1145      pcSaoParam->psSaoPart[c][i].iMinRate      = MAX_INT;
1146      pcSaoParam->psSaoPart[c][i].subTypeIdx    = 0;
1147      for (Int j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1148      {
1149        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
1150        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
1151        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
1152      }
1153    }
1154    pcSaoParam->oneUnitFlag[0]   = 0;
1155    pcSaoParam->oneUnitFlag[1]   = 0;
1156    pcSaoParam->oneUnitFlag[2]   = 0;
1157    resetLcuPart(pcSaoParam->saoLcuParam[0]);
1158    resetLcuPart(pcSaoParam->saoLcuParam[1]);
1159    resetLcuPart(pcSaoParam->saoLcuParam[2]);
1160  }
1161}
1162
1163/** get the sign of input variable
1164 * \param   x
1165 */
1166inline Int xSign(Int x)
1167{
1168  return ((x >> 31) | ((Int)( (((UInt) -x)) >> 31)));
1169}
1170
1171/** initialize variables for SAO process
1172 * \param  pcPic picture data pointer
1173 */
1174Void TComSampleAdaptiveOffset::createPicSaoInfo(TComPic* pcPic)
1175{
1176  m_pcPic   = pcPic;
1177  m_bUseNIF = ( pcPic->getIndependentSliceBoundaryForNDBFilter() || pcPic->getIndependentTileBoundaryForNDBFilter() );
1178  if(m_bUseNIF)
1179  {
1180    m_pcYuvTmp = pcPic->getYuvPicBufferForIndependentBoundaryProcessing();
1181  }
1182}
1183
1184Void TComSampleAdaptiveOffset::destroyPicSaoInfo()
1185{
1186
1187}
1188
1189/** sample adaptive offset process for one LCU
1190 * \param   iAddr, iSaoType, iYCbCr
1191 */
1192Void TComSampleAdaptiveOffset::processSaoCu(Int iAddr, Int iSaoType, Int iYCbCr)
1193{
1194  if(!m_bUseNIF)
1195  {
1196    processSaoCuOrg( iAddr, iSaoType, iYCbCr);
1197  }
1198  else
1199  { 
1200    Int  isChroma = (iYCbCr != 0)? 1:0;
1201    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
1202    Pel* pPicRest = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr);
1203    Pel* pPicDec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
1204
1205    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
1206
1207    //variables
1208    UInt  xPos, yPos, width, height;
1209    Bool* pbBorderAvail;
1210    UInt  posOffset;
1211
1212    for(Int i=0; i< vFilterBlocks.size(); i++)
1213    {
1214      xPos        = vFilterBlocks[i].posX   >> isChroma;
1215      yPos        = vFilterBlocks[i].posY   >> isChroma;
1216      width       = vFilterBlocks[i].width  >> isChroma;
1217      height      = vFilterBlocks[i].height >> isChroma;
1218      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
1219
1220      posOffset = (yPos* stride) + xPos;
1221
1222      processSaoBlock(pPicDec+ posOffset, pPicRest+ posOffset, stride, iSaoType, width, height, pbBorderAvail, iYCbCr);
1223    }
1224  }
1225}
1226
1227/** Perform SAO for non-cross-slice or non-cross-tile process
1228 * \param  pDec to-be-filtered block buffer pointer
1229 * \param  pRest filtered block buffer pointer
1230 * \param  stride picture buffer stride
1231 * \param  saoType SAO offset type
1232 * \param  xPos x coordinate
1233 * \param  yPos y coordinate
1234 * \param  width block width
1235 * \param  height block height
1236 * \param  pbBorderAvail availabilities of block border pixels
1237 */
1238Void TComSampleAdaptiveOffset::processSaoBlock(Pel* pDec, Pel* pRest, Int stride, Int saoType, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr)
1239{
1240  //variables
1241  Int startX, startY, endX, endY, x, y;
1242  Int signLeft,signRight,signDown,signDown1;
1243  UInt edgeType;
1244  Pel *pClipTbl = (iYCbCr==0)?m_pClipTable:m_pChromaClipTable;
1245  Int *pOffsetBo = (iYCbCr==0)?m_iOffsetBo: m_iChromaOffsetBo;
1246
1247  switch (saoType)
1248  {
1249  case SAO_EO_0: // dir: -
1250    {
1251
1252      startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
1253      endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
1254      for (y=0; y< height; y++)
1255      {
1256        signLeft = xSign(pDec[startX] - pDec[startX-1]);
1257        for (x=startX; x< endX; x++)
1258        {
1259          signRight =  xSign(pDec[x] - pDec[x+1]); 
1260          edgeType =  signRight + signLeft + 2;
1261          signLeft  = -signRight;
1262
1263          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1264        }
1265        pDec  += stride;
1266        pRest += stride;
1267      }
1268      break;
1269    }
1270  case SAO_EO_1: // dir: |
1271    {
1272      startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
1273      endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
1274      if (!pbBorderAvail[SGU_T])
1275      {
1276        pDec  += stride;
1277        pRest += stride;
1278      }
1279      for (x=0; x< width; x++)
1280      {
1281        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x-stride]);
1282      }
1283      for (y=startY; y<endY; y++)
1284      {
1285        for (x=0; x< width; x++)
1286        {
1287          signDown  = xSign(pDec[x] - pDec[x+stride]); 
1288          edgeType = signDown + m_iUpBuff1[x] + 2;
1289          m_iUpBuff1[x]= -signDown;
1290
1291          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1292        }
1293        pDec  += stride;
1294        pRest += stride;
1295      }
1296      break;
1297    }
1298  case SAO_EO_2: // dir: 135
1299    {
1300      Int posShift= stride + 1;
1301
1302      startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
1303      endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
1304
1305      //prepare 2nd line upper sign
1306      pDec += stride;
1307      for (x=startX; x< endX+1; x++)
1308      {
1309        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x- posShift]);
1310      }
1311
1312      //1st line
1313      pDec -= stride;
1314      if(pbBorderAvail[SGU_TL])
1315      {
1316        x= 0;
1317        edgeType      =  xSign(pDec[x] - pDec[x- posShift]) - m_iUpBuff1[x+1] + 2;
1318        pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1319
1320      }
1321      if(pbBorderAvail[SGU_T])
1322      {
1323        for(x= 1; x< endX; x++)
1324        {
1325          edgeType      =  xSign(pDec[x] - pDec[x- posShift]) - m_iUpBuff1[x+1] + 2;
1326          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1327        }
1328      }
1329      pDec   += stride;
1330      pRest  += stride;
1331
1332
1333      //middle lines
1334      for (y= 1; y< height-1; y++)
1335      {
1336        for (x=startX; x<endX; x++)
1337        {
1338          signDown1      =  xSign(pDec[x] - pDec[x+ posShift]) ;
1339          edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1340          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1341
1342          m_iUpBufft[x+1] = -signDown1; 
1343        }
1344        m_iUpBufft[startX] = xSign(pDec[stride+startX] - pDec[startX-1]);
1345
1346        ipSwap     = m_iUpBuff1;
1347        m_iUpBuff1 = m_iUpBufft;
1348        m_iUpBufft = ipSwap;
1349
1350        pDec  += stride;
1351        pRest += stride;
1352      }
1353
1354      //last line
1355      if(pbBorderAvail[SGU_B])
1356      {
1357        for(x= startX; x< width-1; x++)
1358        {
1359          edgeType =  xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
1360          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1361        }
1362      }
1363      if(pbBorderAvail[SGU_BR])
1364      {
1365        x= width -1;
1366        edgeType =  xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
1367        pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1368      }
1369      break;
1370    } 
1371  case SAO_EO_3: // dir: 45
1372    {
1373      Int  posShift     = stride - 1;
1374      startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
1375      endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
1376
1377      //prepare 2nd line upper sign
1378      pDec += stride;
1379      for (x=startX-1; x< endX; x++)
1380      {
1381        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x- posShift]);
1382      }
1383
1384
1385      //first line
1386      pDec -= stride;
1387      if(pbBorderAvail[SGU_T])
1388      {
1389        for(x= startX; x< width -1; x++)
1390        {
1391          edgeType = xSign(pDec[x] - pDec[x- posShift]) -m_iUpBuff1[x-1] + 2;
1392          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1393        }
1394      }
1395      if(pbBorderAvail[SGU_TR])
1396      {
1397        x= width-1;
1398        edgeType = xSign(pDec[x] - pDec[x- posShift]) -m_iUpBuff1[x-1] + 2;
1399        pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1400      }
1401      pDec  += stride;
1402      pRest += stride;
1403
1404      //middle lines
1405      for (y= 1; y< height-1; y++)
1406      {
1407        for(x= startX; x< endX; x++)
1408        {
1409          signDown1      =  xSign(pDec[x] - pDec[x+ posShift]) ;
1410          edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
1411
1412          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1413          m_iUpBuff1[x-1] = -signDown1; 
1414        }
1415        m_iUpBuff1[endX-1] = xSign(pDec[endX-1 + stride] - pDec[endX]);
1416
1417        pDec  += stride;
1418        pRest += stride;
1419      }
1420
1421      //last line
1422      if(pbBorderAvail[SGU_BL])
1423      {
1424        x= 0;
1425        edgeType = xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
1426        pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1427
1428      }
1429      if(pbBorderAvail[SGU_B])
1430      {
1431        for(x= 1; x< endX; x++)
1432        {
1433          edgeType = xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
1434          pRest[x] = pClipTbl[pDec[x] + m_iOffsetEo[edgeType]];
1435        }
1436      }
1437      break;
1438    }   
1439  case SAO_BO:
1440    {
1441      for (y=0; y< height; y++)
1442      {
1443        for (x=0; x< width; x++)
1444        {
1445          pRest[x] = pOffsetBo[pDec[x]];
1446        }
1447        pRest += stride;
1448        pDec  += stride;
1449      }
1450      break;
1451    }
1452  default: break;
1453  }
1454
1455}
1456
1457/** sample adaptive offset process for one LCU crossing LCU boundary
1458 * \param   iAddr, iSaoType, iYCbCr
1459 */
1460Void TComSampleAdaptiveOffset::processSaoCuOrg(Int iAddr, Int iSaoType, Int iYCbCr)
1461{
1462  Int x,y;
1463  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
1464  Pel* pRec;
1465  Int  iStride;
1466  Int  iLcuWidth  = m_uiMaxCUWidth;
1467  Int  iLcuHeight = m_uiMaxCUHeight;
1468  UInt uiLPelX    = pTmpCu->getCUPelX();
1469  UInt uiTPelY    = pTmpCu->getCUPelY();
1470  UInt uiRPelX;
1471  UInt uiBPelY;
1472  Int  iSignLeft;
1473  Int  iSignRight;
1474  Int  iSignDown;
1475  Int  iSignDown1;
1476  Int  iSignDown2;
1477  UInt uiEdgeType;
1478  Int iPicWidthTmp;
1479  Int iPicHeightTmp;
1480  Int iStartX;
1481  Int iStartY;
1482  Int iEndX;
1483  Int iEndY;
1484  Int iIsChroma = (iYCbCr!=0)? 1:0;
1485  Int iShift;
1486  Int iCuHeightTmp;
1487  Pel *pTmpLSwap;
1488  Pel *pTmpL;
1489  Pel *pTmpU;
1490  Pel *pClipTbl = NULL;
1491  Int *pOffsetBo = NULL;
1492
1493  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
1494  iPicHeightTmp = m_iPicHeight >> iIsChroma;
1495  iLcuWidth     = iLcuWidth    >> iIsChroma;
1496  iLcuHeight    = iLcuHeight   >> iIsChroma;
1497  uiLPelX       = uiLPelX      >> iIsChroma;
1498  uiTPelY       = uiTPelY      >> iIsChroma;
1499  uiRPelX       = uiLPelX + iLcuWidth  ;
1500  uiBPelY       = uiTPelY + iLcuHeight ;
1501  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
1502  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
1503  iLcuWidth     = uiRPelX - uiLPelX;
1504  iLcuHeight    = uiBPelY - uiTPelY;
1505
1506  if(pTmpCu->getPic()==0)
1507  {
1508    return;
1509  }
1510  if (iYCbCr == 0)
1511  {
1512    pRec       = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
1513    iStride    = m_pcPic->getStride();
1514  } 
1515  else if (iYCbCr == 1)
1516  {
1517    pRec       = m_pcPic->getPicYuvRec()->getCbAddr(iAddr);
1518    iStride    = m_pcPic->getCStride();
1519  }
1520  else 
1521  {
1522    pRec       = m_pcPic->getPicYuvRec()->getCrAddr(iAddr);
1523    iStride    = m_pcPic->getCStride();
1524  }
1525
1526//   if (iSaoType!=SAO_BO_0 || iSaoType!=SAO_BO_1)
1527  {
1528    iCuHeightTmp = (m_uiMaxCUHeight >> iIsChroma);
1529    iShift = (m_uiMaxCUWidth>> iIsChroma)-1;
1530    for (Int i=0;i<iCuHeightTmp+1;i++)
1531    {
1532      m_pTmpL2[i] = pRec[iShift];
1533      pRec += iStride;
1534    }
1535    pRec -= (iStride*(iCuHeightTmp+1));
1536
1537    pTmpL = m_pTmpL1; 
1538    pTmpU = &(m_pTmpU1[uiLPelX]); 
1539  }
1540
1541  pClipTbl = (iYCbCr==0)? m_pClipTable:m_pChromaClipTable;
1542  pOffsetBo = (iYCbCr==0)? m_iOffsetBo:m_iChromaOffsetBo;
1543
1544  switch (iSaoType)
1545  {
1546  case SAO_EO_0: // dir: -
1547    {
1548      iStartX = (uiLPelX == 0) ? 1 : 0;
1549      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1550      for (y=0; y<iLcuHeight; y++)
1551      {
1552        iSignLeft = xSign(pRec[iStartX] - pTmpL[y]);
1553        for (x=iStartX; x< iEndX; x++)
1554        {
1555          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
1556          uiEdgeType =  iSignRight + iSignLeft + 2;
1557          iSignLeft  = -iSignRight;
1558
1559          pRec[x] = pClipTbl[pRec[x] + m_iOffsetEo[uiEdgeType]];
1560        }
1561        pRec += iStride;
1562      }
1563      break;
1564    }
1565  case SAO_EO_1: // dir: |
1566    {
1567      iStartY = (uiTPelY == 0) ? 1 : 0;
1568      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
1569      if (uiTPelY == 0)
1570      {
1571        pRec += iStride;
1572      }
1573      for (x=0; x< iLcuWidth; x++)
1574      {
1575        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x]);
1576      }
1577      for (y=iStartY; y<iEndY; y++)
1578      {
1579        for (x=0; x<iLcuWidth; x++)
1580        {
1581          iSignDown  = xSign(pRec[x] - pRec[x+iStride]); 
1582          uiEdgeType = iSignDown + m_iUpBuff1[x] + 2;
1583          m_iUpBuff1[x]= -iSignDown;
1584
1585          pRec[x] = pClipTbl[pRec[x] + m_iOffsetEo[uiEdgeType]];
1586        }
1587        pRec += iStride;
1588      }
1589      break;
1590    }
1591  case SAO_EO_2: // dir: 135
1592    {
1593      iStartX = (uiLPelX == 0)            ? 1 : 0;
1594      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1595
1596      iStartY = (uiTPelY == 0) ?             1 : 0;
1597      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
1598
1599      if (uiTPelY == 0)
1600      {
1601        pRec += iStride;
1602      }
1603
1604      for (x=iStartX; x<iEndX; x++)
1605      {
1606        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x-1]);
1607      }
1608      for (y=iStartY; y<iEndY; y++)
1609      {
1610        iSignDown2 = xSign(pRec[iStride+iStartX] - pTmpL[y]);
1611        for (x=iStartX; x<iEndX; x++)
1612        {
1613          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
1614          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1615          m_iUpBufft[x+1] = -iSignDown1; 
1616          pRec[x] = pClipTbl[pRec[x] + m_iOffsetEo[uiEdgeType]];
1617        }
1618        m_iUpBufft[iStartX] = iSignDown2;
1619
1620        ipSwap     = m_iUpBuff1;
1621        m_iUpBuff1 = m_iUpBufft;
1622        m_iUpBufft = ipSwap;
1623
1624        pRec += iStride;
1625      }
1626      break;
1627    } 
1628  case SAO_EO_3: // dir: 45
1629    {
1630      iStartX = (uiLPelX == 0) ? 1 : 0;
1631      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
1632
1633      iStartY = (uiTPelY == 0) ? 1 : 0;
1634      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
1635
1636      if (iStartY == 1)
1637      {
1638        pRec += iStride;
1639      }
1640
1641      for (x=iStartX-1; x<iEndX; x++)
1642      {
1643        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x+1]);
1644      }
1645      for (y=iStartY; y<iEndY; y++)
1646      {
1647        x=iStartX;
1648        iSignDown1      =  xSign(pRec[x] - pTmpL[y+1]) ;
1649        uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1650        m_iUpBuff1[x-1] = -iSignDown1; 
1651        pRec[x] = pClipTbl[pRec[x] + m_iOffsetEo[uiEdgeType]];
1652        for (x=iStartX+1; x<iEndX; x++)
1653        {
1654          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
1655          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
1656          m_iUpBuff1[x-1] = -iSignDown1; 
1657          pRec[x] = pClipTbl[pRec[x] + m_iOffsetEo[uiEdgeType]];
1658        }
1659        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
1660
1661        pRec += iStride;
1662      } 
1663      break;
1664    }   
1665  case SAO_BO:
1666    {
1667      for (y=0; y<iLcuHeight; y++)
1668      {
1669        for (x=0; x<iLcuWidth; x++)
1670        {
1671          pRec[x] = pOffsetBo[pRec[x]];
1672        }
1673        pRec += iStride;
1674      }
1675      break;
1676    }
1677  default: break;
1678  }
1679//   if (iSaoType!=SAO_BO_0 || iSaoType!=SAO_BO_1)
1680  {
1681    pTmpLSwap = m_pTmpL1;
1682    m_pTmpL1  = m_pTmpL2;
1683    m_pTmpL2  = pTmpLSwap;
1684  }
1685}
1686/** Sample adaptive offset process
1687 * \param pcPic, pcSaoParam 
1688 */
1689Void TComSampleAdaptiveOffset::SAOProcess(SAOParam* pcSaoParam)
1690{
1691  {
1692    m_uiSaoBitIncreaseY = max(g_bitDepthY - 10, 0);
1693    m_uiSaoBitIncreaseC = max(g_bitDepthC - 10, 0);
1694
1695    if(m_bUseNIF)
1696    {
1697      m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
1698    }
1699    if (m_saoLcuBasedOptimization)
1700    {
1701      pcSaoParam->oneUnitFlag[0] = 0; 
1702      pcSaoParam->oneUnitFlag[1] = 0; 
1703      pcSaoParam->oneUnitFlag[2] = 0; 
1704    }
1705    Int iY  = 0;
1706    {
1707      processSaoUnitAll( pcSaoParam->saoLcuParam[iY], pcSaoParam->oneUnitFlag[iY], iY);
1708    }
1709    {
1710       processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);//Cb
1711       processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);//Cr
1712    }
1713    m_pcPic = NULL;
1714  }
1715}
1716
1717Pel* TComSampleAdaptiveOffset::getPicYuvAddr(TComPicYuv* pcPicYuv, Int iYCbCr, Int iAddr)
1718{
1719  switch (iYCbCr)
1720  {
1721  case 0:
1722    return pcPicYuv->getLumaAddr(iAddr);
1723    break;
1724  case 1:
1725    return pcPicYuv->getCbAddr(iAddr);
1726    break;
1727  case 2:
1728    return pcPicYuv->getCrAddr(iAddr);
1729    break;
1730  default:
1731    return NULL;
1732    break;
1733  }
1734}
1735/** Process SAO all units
1736 * \param saoLcuParam SAO LCU parameters
1737 * \param oneUnitFlag one unit flag
1738 * \param yCbCr color componet index
1739 */
1740Void TComSampleAdaptiveOffset::processSaoUnitAll(SaoLcuParam* saoLcuParam, Bool oneUnitFlag, Int yCbCr)
1741{
1742  Pel *pRec;
1743  Int picWidthTmp;
1744
1745  if (yCbCr == 0)
1746  {
1747    pRec        = m_pcPic->getPicYuvRec()->getLumaAddr();
1748    picWidthTmp = m_iPicWidth;
1749  } 
1750  else if (yCbCr == 1)
1751  {
1752    pRec        = m_pcPic->getPicYuvRec()->getCbAddr();
1753    picWidthTmp = m_iPicWidth>>1;
1754  }
1755  else 
1756  {
1757    pRec        = m_pcPic->getPicYuvRec()->getCrAddr();
1758    picWidthTmp = m_iPicWidth>>1;
1759  }
1760
1761  memcpy(m_pTmpU1, pRec, sizeof(Pel)*picWidthTmp);
1762
1763  Int  i;
1764  UInt edgeType;
1765  Pel* ppLumaTable = NULL;
1766  Pel* pClipTable = NULL;
1767  Int* pOffsetBo = NULL;
1768  Int  typeIdx;
1769
1770  Int offset[LUMA_GROUP_NUM+1];
1771  Int idxX;
1772  Int idxY;
1773  Int addr;
1774  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
1775  Int frameHeightInCU = m_pcPic->getFrameHeightInCU();
1776  Int stride;
1777  Pel *tmpUSwap;
1778  Int isChroma = (yCbCr == 0) ? 0:1;
1779  Bool mergeLeftFlag;
1780  Int saoBitIncrease = (yCbCr == 0) ? m_uiSaoBitIncreaseY : m_uiSaoBitIncreaseC;
1781
1782  pOffsetBo = (yCbCr==0) ? m_iOffsetBo : m_iChromaOffsetBo;
1783
1784  offset[0] = 0;
1785  for (idxY = 0; idxY< frameHeightInCU; idxY++)
1786  { 
1787    addr = idxY * frameWidthInCU;
1788    if (yCbCr == 0)
1789    {
1790      pRec  = m_pcPic->getPicYuvRec()->getLumaAddr(addr);
1791      stride = m_pcPic->getStride();
1792      picWidthTmp = m_iPicWidth;
1793    }
1794    else if (yCbCr == 1)
1795    {
1796      pRec  = m_pcPic->getPicYuvRec()->getCbAddr(addr);
1797      stride = m_pcPic->getCStride();
1798      picWidthTmp = m_iPicWidth>>1;
1799    }
1800    else
1801    {
1802      pRec  = m_pcPic->getPicYuvRec()->getCrAddr(addr);
1803      stride = m_pcPic->getCStride();
1804      picWidthTmp = m_iPicWidth>>1;
1805    }
1806
1807    //     pRec += iStride*(m_uiMaxCUHeight-1);
1808    for (i=0;i<(m_uiMaxCUHeight>>isChroma)+1;i++)
1809    {
1810      m_pTmpL1[i] = pRec[0];
1811      pRec+=stride;
1812    }
1813    pRec-=(stride<<1);
1814
1815    memcpy(m_pTmpU2, pRec, sizeof(Pel)*picWidthTmp);
1816
1817    for (idxX = 0; idxX < frameWidthInCU; idxX++)
1818    {
1819      addr = idxY * frameWidthInCU + idxX;
1820
1821      if (oneUnitFlag)
1822      {
1823        typeIdx = saoLcuParam[0].typeIdx;
1824        mergeLeftFlag = (addr == 0)? 0:1;
1825      }
1826      else
1827      {
1828        typeIdx = saoLcuParam[addr].typeIdx;
1829        mergeLeftFlag = saoLcuParam[addr].mergeLeftFlag;
1830      }
1831      if (typeIdx>=0)
1832      {
1833        if (!mergeLeftFlag)
1834        {
1835
1836          if (typeIdx == SAO_BO)
1837          {
1838            for (i=0; i<SAO_MAX_BO_CLASSES+1;i++)
1839            {
1840              offset[i] = 0;
1841            }
1842            for (i=0; i<saoLcuParam[addr].length; i++)
1843            {
1844              offset[ (saoLcuParam[addr].subTypeIdx +i)%SAO_MAX_BO_CLASSES  +1] = saoLcuParam[addr].offset[i] << saoBitIncrease;
1845            }
1846
1847            ppLumaTable = (yCbCr==0)?m_lumaTableBo:m_chromaTableBo;
1848            pClipTable = (yCbCr==0)?m_pClipTable:m_pChromaClipTable;
1849
1850            Int bitDepth = (yCbCr==0) ? g_bitDepthY : g_bitDepthC;
1851            for (i=0;i<(1<<bitDepth);i++)
1852            {
1853              pOffsetBo[i] = pClipTable[i + offset[ppLumaTable[i]]];
1854            }
1855
1856          }
1857          if (typeIdx == SAO_EO_0 || typeIdx == SAO_EO_1 || typeIdx == SAO_EO_2 || typeIdx == SAO_EO_3)
1858          {
1859            for (i=0;i<saoLcuParam[addr].length;i++)
1860            {
1861              offset[i+1] = saoLcuParam[addr].offset[i] << saoBitIncrease;
1862            }
1863            for (edgeType=0;edgeType<6;edgeType++)
1864            {
1865              m_iOffsetEo[edgeType]= offset[m_auiEoTable[edgeType]];
1866            }
1867          }
1868        }
1869        processSaoCu(addr, typeIdx, yCbCr);
1870      }
1871      else
1872      {
1873        if (idxX != (frameWidthInCU-1))
1874        {
1875          if (yCbCr == 0)
1876          {
1877            pRec  = m_pcPic->getPicYuvRec()->getLumaAddr(addr);
1878            stride = m_pcPic->getStride();
1879          }
1880          else if (yCbCr == 1)
1881          {
1882            pRec  = m_pcPic->getPicYuvRec()->getCbAddr(addr);
1883            stride = m_pcPic->getCStride();
1884          }
1885          else
1886          {
1887            pRec  = m_pcPic->getPicYuvRec()->getCrAddr(addr);
1888            stride = m_pcPic->getCStride();
1889          }
1890          Int widthShift = m_uiMaxCUWidth>>isChroma;
1891          for (i=0;i<(m_uiMaxCUHeight>>isChroma)+1;i++)
1892          {
1893            m_pTmpL1[i] = pRec[widthShift-1];
1894            pRec+=stride;
1895          }
1896        }
1897      }
1898    }
1899    tmpUSwap = m_pTmpU1;
1900    m_pTmpU1 = m_pTmpU2;
1901    m_pTmpU2 = tmpUSwap;
1902  }
1903
1904}
1905/** Reset SAO LCU part
1906 * \param saoLcuParam
1907 */
1908Void TComSampleAdaptiveOffset::resetLcuPart(SaoLcuParam* saoLcuParam)
1909{
1910  Int i,j;
1911  for (i=0;i<m_iNumCuInWidth*m_iNumCuInHeight;i++)
1912  {
1913    saoLcuParam[i].mergeUpFlag     =  1;
1914    saoLcuParam[i].mergeLeftFlag =  0;
1915    saoLcuParam[i].partIdx   =  0;
1916    saoLcuParam[i].typeIdx      = -1;
1917    for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1918    {
1919      saoLcuParam[i].offset[j] = 0;
1920    }
1921    saoLcuParam[i].subTypeIdx = 0;
1922  }
1923}
1924
1925/** convert QP part to SAO unit
1926* \param saoParam SAO parameter
1927* \param partIdx SAO part index
1928* \param yCbCr color component index
1929 */
1930Void TComSampleAdaptiveOffset::convertQT2SaoUnit(SAOParam *saoParam, UInt partIdx, Int yCbCr)
1931{
1932
1933  SAOQTPart*  saoPart= &(saoParam->psSaoPart[yCbCr][partIdx]);
1934  if (!saoPart->bSplit)
1935  {
1936    convertOnePart2SaoUnit(saoParam, partIdx, yCbCr);
1937    return;
1938  }
1939
1940  if (saoPart->PartLevel < m_uiMaxSplitLevel)
1941  {
1942    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[0], yCbCr);
1943    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[1], yCbCr);
1944    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[2], yCbCr);
1945    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[3], yCbCr);
1946  }
1947}
1948/** convert one SAO part to SAO unit
1949* \param saoParam SAO parameter
1950* \param partIdx SAO part index
1951* \param yCbCr color component index
1952 */
1953Void TComSampleAdaptiveOffset::convertOnePart2SaoUnit(SAOParam *saoParam, UInt partIdx, Int yCbCr)
1954{
1955  Int j;
1956  Int idxX;
1957  Int idxY;
1958  Int addr;
1959  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
1960  SAOQTPart* saoQTPart = saoParam->psSaoPart[yCbCr];
1961  SaoLcuParam* saoLcuParam = saoParam->saoLcuParam[yCbCr];
1962
1963  for (idxY = saoQTPart[partIdx].StartCUY; idxY<= saoQTPart[partIdx].EndCUY; idxY++)
1964  {
1965    for (idxX = saoQTPart[partIdx].StartCUX; idxX<= saoQTPart[partIdx].EndCUX; idxX++)
1966    {
1967      addr = idxY * frameWidthInCU + idxX;
1968      saoLcuParam[addr].partIdxTmp = (Int)partIdx; 
1969      saoLcuParam[addr].typeIdx    = saoQTPart[partIdx].iBestType;
1970      saoLcuParam[addr].subTypeIdx = saoQTPart[partIdx].subTypeIdx;
1971      if (saoLcuParam[addr].typeIdx!=-1)
1972      {
1973        saoLcuParam[addr].length    = saoQTPart[partIdx].iLength;
1974        for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1975        {
1976          saoLcuParam[addr].offset[j] = saoQTPart[partIdx].iOffset[j];
1977        }
1978      }
1979      else
1980      {
1981        saoLcuParam[addr].length    = 0;
1982        saoLcuParam[addr].subTypeIdx = saoQTPart[partIdx].subTypeIdx;
1983        for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1984        {
1985          saoLcuParam[addr].offset[j] = 0;
1986        }
1987      }
1988    }
1989  }
1990}
1991
1992Void TComSampleAdaptiveOffset::resetSaoUnit(SaoLcuParam* saoUnit)
1993{
1994  saoUnit->partIdx       = 0;
1995  saoUnit->partIdxTmp    = 0;
1996  saoUnit->mergeLeftFlag = 0;
1997  saoUnit->mergeUpFlag   = 0;
1998  saoUnit->typeIdx       = -1;
1999  saoUnit->length        = 0;
2000  saoUnit->subTypeIdx    = 0;
2001
2002  for (Int i=0;i<4;i++)
2003  {
2004    saoUnit->offset[i] = 0;
2005  }
2006}
2007
2008Void TComSampleAdaptiveOffset::copySaoUnit(SaoLcuParam* saoUnitDst, SaoLcuParam* saoUnitSrc )
2009{
2010  saoUnitDst->mergeLeftFlag = saoUnitSrc->mergeLeftFlag;
2011  saoUnitDst->mergeUpFlag   = saoUnitSrc->mergeUpFlag;
2012  saoUnitDst->typeIdx       = saoUnitSrc->typeIdx;
2013  saoUnitDst->length        = saoUnitSrc->length;
2014
2015  saoUnitDst->subTypeIdx  = saoUnitSrc->subTypeIdx;
2016  for (Int i=0;i<4;i++)
2017  {
2018    saoUnitDst->offset[i] = saoUnitSrc->offset[i];
2019  }
2020}
2021#endif
2022/** PCM LF disable process.
2023 * \param pcPic picture (TComPic) pointer
2024 * \returns Void
2025 *
2026 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
2027 */
2028Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic)
2029{
2030  xPCMRestoration(pcPic);
2031}
2032
2033/** Picture-level PCM restoration.
2034 * \param pcPic picture (TComPic) pointer
2035 * \returns Void
2036 */
2037Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic)
2038{
2039  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
2040
2041  if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnableFlag())
2042  {
2043    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2044    {
2045      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
2046
2047      xPCMCURestoration(pcCU, 0, 0); 
2048    } 
2049  }
2050}
2051
2052/** PCM CU restoration.
2053 * \param pcCU pointer to current CU
2054 * \param uiAbsPartIdx part index
2055 * \param uiDepth CU depth
2056 * \returns Void
2057 */
2058Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
2059{
2060  TComPic* pcPic     = pcCU->getPic();
2061  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
2062  UInt uiQNumParts   = uiCurNumParts>>2;
2063
2064  // go to sub-CU
2065  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
2066  {
2067    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
2068    {
2069      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
2070      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
2071#if REPN_FORMAT_IN_VPS
2072      if( ( uiLPelX < pcCU->getSlice()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getPicHeightInLumaSamples() ) )
2073#else
2074      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
2075#endif
2076        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
2077    }
2078    return;
2079  }
2080
2081  // restore PCM samples
2082  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx))
2083  {
2084    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
2085    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
2086    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
2087  }
2088}
2089
2090/** PCM sample restoration.
2091 * \param pcCU pointer to current CU
2092 * \param uiAbsPartIdx part index
2093 * \param uiDepth CU depth
2094 * \param ttText texture component type
2095 * \returns Void
2096 */
2097Void TComSampleAdaptiveOffset::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
2098{
2099  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
2100  Pel* piSrc;
2101  Pel* piPcm;
2102  UInt uiStride;
2103  UInt uiWidth;
2104  UInt uiHeight;
2105  UInt uiPcmLeftShiftBit; 
2106  UInt uiX, uiY;
2107  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
2108  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
2109  UInt uiChromaOffset = uiLumaOffset>>2;
2110
2111  if( ttText == TEXT_LUMA )
2112  {
2113    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
2114    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
2115    uiStride  = pcPicYuvRec->getStride();
2116    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
2117    uiHeight = (g_uiMaxCUHeight >> uiDepth);
2118    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
2119    {
2120      uiPcmLeftShiftBit = 0;
2121    }
2122    else
2123    {
2124      uiPcmLeftShiftBit = g_bitDepthY - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
2125    }
2126  }
2127  else
2128  {
2129    if( ttText == TEXT_CHROMA_U )
2130    {
2131      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
2132      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
2133    }
2134    else
2135    {
2136      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
2137      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
2138    }
2139
2140    uiStride = pcPicYuvRec->getCStride();
2141    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
2142    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
2143    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
2144    {
2145      uiPcmLeftShiftBit = 0;
2146    }
2147    else
2148    {
2149      uiPcmLeftShiftBit = g_bitDepthC - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
2150    }
2151  }
2152
2153  for( uiY = 0; uiY < uiHeight; uiY++ )
2154  {
2155    for( uiX = 0; uiX < uiWidth; uiX++ )
2156    {
2157      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
2158    }
2159    piPcm += uiWidth;
2160    piSrc += uiStride;
2161  }
2162}
2163
2164//! \}
Note: See TracBrowser for help on using the repository browser.