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

Last change on this file since 2 was 2, checked in by seregin, 12 years ago

Initial import by Vadim Seregin <vseregin@…>

File size: 43.2 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-2012, 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
47SAOParam::~SAOParam()
48{
49  for (Int i = 0 ; i<3; i++)
50  {
51    if (psSaoPart[i])
52    {
53      delete [] psSaoPart[i];
54    }
55  }
56}
57
58// ====================================================================================================================
59// Tables
60// ====================================================================================================================
61
62TComSampleAdaptiveOffset::TComSampleAdaptiveOffset()
63{
64  m_pClipTable = NULL;
65  m_pClipTableBase = NULL;
66  m_iOffsetBo = NULL;
67  m_lumaTableBo = NULL;
68  m_iUpBuff1 = NULL;
69  m_iUpBuff2 = NULL;
70  m_iUpBufft = NULL;
71  ipSwap = NULL;
72
73  m_pTmpU1 = NULL;
74  m_pTmpU2 = NULL;
75  m_pTmpL1 = NULL;
76  m_pTmpL2 = NULL;
77  m_iLcuPartIdx = NULL;
78}
79
80TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset()
81{
82
83}
84
85const Int TComSampleAdaptiveOffset::m_aiNumCulPartsLevel[5] =
86{
87  1,   //level 0
88  5,   //level 1
89  21,  //level 2
90  85,  //level 3
91  341, //level 4
92};
93
94const UInt TComSampleAdaptiveOffset::m_auiEoTable[9] =
95{
96  1, //0   
97  2, //1   
98  0, //2
99  3, //3
100  4, //4
101  0, //5 
102  0, //6 
103  0, //7
104  0
105};
106
107const Int TComSampleAdaptiveOffset::m_iNumClass[MAX_NUM_SAO_TYPE] =
108{
109  SAO_EO_LEN,
110  SAO_EO_LEN,
111  SAO_EO_LEN,
112  SAO_EO_LEN,
113  SAO_BO_LEN
114};
115
116const UInt TComSampleAdaptiveOffset::m_uiMaxDepth = SAO_MAX_DEPTH;
117
118
119/** convert Level Row Col to Idx
120 * \param   level,  row,  col
121 */
122Int  TComSampleAdaptiveOffset::convertLevelRowCol2Idx(int level, int row, int col)
123{
124  Int idx;
125  if (level == 0)
126  {
127    idx = 0;
128  }
129  else if (level == 1)
130  {
131    idx = 1 + row*2 + col;
132  }
133  else if (level == 2)
134  {
135    idx = 5 + row*4 + col;
136  }
137  else if (level == 3)
138  {
139    idx = 21 + row*8 + col;
140  }
141  else // (level == 4)
142  {
143    idx = 85 + row*16 + col;
144  }
145  return idx;
146}
147
148/** create SampleAdaptiveOffset memory.
149 * \param
150 */
151Void TComSampleAdaptiveOffset::create( UInt uiSourceWidth, UInt uiSourceHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth)
152{
153  m_iPicWidth  = uiSourceWidth;
154  m_iPicHeight = uiSourceHeight;
155
156  m_uiMaxCUWidth  = uiMaxCUWidth;
157  m_uiMaxCUHeight = uiMaxCUHeight;
158
159  m_iNumCuInWidth  = m_iPicWidth / m_uiMaxCUWidth;
160  m_iNumCuInWidth += ( m_iPicWidth % m_uiMaxCUWidth ) ? 1 : 0;
161
162  m_iNumCuInHeight  = m_iPicHeight / m_uiMaxCUHeight;
163  m_iNumCuInHeight += ( m_iPicHeight % m_uiMaxCUHeight ) ? 1 : 0;
164
165  Int iMaxSplitLevelHeight = (Int)(logf((float)m_iNumCuInHeight)/logf(2.0));
166  Int iMaxSplitLevelWidth  = (Int)(logf((float)m_iNumCuInWidth )/logf(2.0));
167
168  m_uiMaxSplitLevel = (iMaxSplitLevelHeight < iMaxSplitLevelWidth)?(iMaxSplitLevelHeight):(iMaxSplitLevelWidth);
169  m_uiMaxSplitLevel = (m_uiMaxSplitLevel< m_uiMaxDepth)?(m_uiMaxSplitLevel):(m_uiMaxDepth);
170  /* various structures are overloaded to store per component data.
171   * m_iNumTotalParts must allow for sufficient storage in any allocated arrays */
172  m_iNumTotalParts  = max(3,m_aiNumCulPartsLevel[m_uiMaxSplitLevel]);
173
174  UInt uiInternalBitDepth = g_uiBitDepth+g_uiBitIncrement;
175  UInt uiPixelRange = 1<<uiInternalBitDepth;
176  UInt uiBoRangeShift = uiInternalBitDepth - SAO_BO_BITS;
177
178  m_lumaTableBo = new Pel [uiPixelRange];
179  for (Int k2=0; k2<uiPixelRange; k2++)
180  {
181    m_lumaTableBo[k2] = 1 + (k2>>uiBoRangeShift);
182  }
183  m_iUpBuff1 = new Int[m_iPicWidth+2];
184  m_iUpBuff2 = new Int[m_iPicWidth+2];
185  m_iUpBufft = new Int[m_iPicWidth+2];
186
187  m_iUpBuff1++;
188  m_iUpBuff2++;
189  m_iUpBufft++;
190  Pel i;
191
192  UInt uiMaxY  = g_uiIBDI_MAX;
193  UInt uiMinY  = 0;
194
195  Int iCRangeExt = uiMaxY>>1;
196
197  m_pClipTableBase = new Pel[uiMaxY+2*iCRangeExt];
198  m_iOffsetBo      = new Int[uiMaxY+2*iCRangeExt];
199
200  for(i=0;i<(uiMinY+iCRangeExt);i++)
201  {
202    m_pClipTableBase[i] = uiMinY;
203  }
204
205  for(i=uiMinY+iCRangeExt;i<(uiMaxY+  iCRangeExt);i++)
206  {
207    m_pClipTableBase[i] = i-iCRangeExt;
208  }
209
210  for(i=uiMaxY+iCRangeExt;i<(uiMaxY+2*iCRangeExt);i++)
211  {
212    m_pClipTableBase[i] = uiMaxY;
213  }
214
215  m_pClipTable = &(m_pClipTableBase[iCRangeExt]);
216
217  m_iLcuPartIdx = new Int [m_iNumCuInHeight*m_iNumCuInWidth];
218  m_pTmpL1 = new Pel [m_uiMaxCUHeight+1];
219  m_pTmpL2 = new Pel [m_uiMaxCUHeight+1];
220  m_pTmpU1 = new Pel [m_iPicWidth];
221  m_pTmpU2 = new Pel [m_iPicWidth];
222}
223
224/** destroy SampleAdaptiveOffset memory.
225 * \param
226 */
227Void TComSampleAdaptiveOffset::destroy()
228{
229  if (m_pClipTableBase)
230  {
231    delete [] m_pClipTableBase; m_pClipTableBase = NULL;
232  }
233  if (m_iOffsetBo)
234  {
235    delete [] m_iOffsetBo; m_iOffsetBo = NULL;
236  }
237  if (m_lumaTableBo)
238  {
239    delete[] m_lumaTableBo; m_lumaTableBo = NULL;
240  }
241
242  if (m_iUpBuff1)
243  {
244    m_iUpBuff1--;
245    delete [] m_iUpBuff1; m_iUpBuff1 = NULL;
246  }
247  if (m_iUpBuff2)
248  {
249    m_iUpBuff2--;
250    delete [] m_iUpBuff2; m_iUpBuff2 = NULL;
251  }
252  if (m_iUpBufft)
253  {
254    m_iUpBufft--;
255    delete [] m_iUpBufft; m_iUpBufft = NULL;
256  }
257  if (m_pTmpL1)
258  {
259    delete [] m_pTmpL1; m_pTmpL1 = NULL;
260  }
261  if (m_pTmpL2)
262  {
263    delete [] m_pTmpL2; m_pTmpL2 = NULL;
264  }
265  if (m_pTmpU1)
266  {
267    delete [] m_pTmpU1; m_pTmpU1 = NULL;
268  }
269  if (m_pTmpU2)
270  {
271    delete [] m_pTmpU2; m_pTmpU2 = NULL;
272  }
273  if(m_iLcuPartIdx)
274  {
275    delete []m_iLcuPartIdx; m_iLcuPartIdx = NULL;
276  }
277}
278
279/** allocate memory for SAO parameters
280 * \param    *pcSaoParam
281 */
282Void TComSampleAdaptiveOffset::allocSaoParam(SAOParam *pcSaoParam)
283{
284  pcSaoParam->iMaxSplitLevel = m_uiMaxSplitLevel;
285  pcSaoParam->psSaoPart[0] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
286  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,0);
287  pcSaoParam->psSaoPart[1] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
288  pcSaoParam->psSaoPart[2] = new SAOQTPart[ m_aiNumCulPartsLevel[pcSaoParam->iMaxSplitLevel] ];
289  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,1);
290  initSAOParam(pcSaoParam, 0, 0, 0, -1, 0, m_iNumCuInWidth-1,  0, m_iNumCuInHeight-1,2);
291  pcSaoParam->numCuInWidth  = m_iNumCuInWidth;
292  pcSaoParam->numCuInHeight = m_iNumCuInHeight;
293  pcSaoParam->saoLcuParam[0] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
294  pcSaoParam->saoLcuParam[1] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
295  pcSaoParam->saoLcuParam[2] = new SaoLcuParam [m_iNumCuInHeight*m_iNumCuInWidth];
296}
297
298/** initialize SAO parameters
299 * \param    *pcSaoParam,  iPartLevel,  iPartRow,  iPartCol,  iParentPartIdx,  StartCUX,  EndCUX,  StartCUY,  EndCUY,  iYCbCr
300 */
301Void TComSampleAdaptiveOffset::initSAOParam(SAOParam *pcSaoParam, Int iPartLevel, Int iPartRow, Int iPartCol, Int iParentPartIdx, Int StartCUX, Int EndCUX, Int StartCUY, Int EndCUY, Int iYCbCr)
302{
303  Int j;
304  Int iPartIdx = convertLevelRowCol2Idx(iPartLevel, iPartRow, iPartCol);
305
306  SAOQTPart* pSaoPart;
307
308  pSaoPart = &(pcSaoParam->psSaoPart[iYCbCr][iPartIdx]);
309
310  pSaoPart->PartIdx   = iPartIdx;
311  pSaoPart->PartLevel = iPartLevel;
312  pSaoPart->PartRow   = iPartRow;
313  pSaoPart->PartCol   = iPartCol;
314
315  pSaoPart->StartCUX  = StartCUX;
316  pSaoPart->EndCUX    = EndCUX;
317  pSaoPart->StartCUY  = StartCUY;
318  pSaoPart->EndCUY    = EndCUY;
319
320  pSaoPart->UpPartIdx = iParentPartIdx;
321  pSaoPart->iBestType   = -1;
322  pSaoPart->iLength     =  0;
323
324#if SAO_TYPE_CODING
325  pSaoPart->subTypeIdx = 0;
326#else
327  pSaoPart->bandPosition = 0;
328#endif
329
330  for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
331  {
332    pSaoPart->iOffset[j] = 0;
333  }
334
335  if(pSaoPart->PartLevel != m_uiMaxSplitLevel)
336  {
337    Int DownLevel    = (iPartLevel+1 );
338    Int DownRowStart = (iPartRow << 1);
339    Int DownColStart = (iPartCol << 1);
340
341    Int iDownRowIdx, iDownColIdx;
342    Int NumCUWidth,  NumCUHeight;
343    Int NumCULeft;
344    Int NumCUTop;
345
346    Int DownStartCUX, DownStartCUY;
347    Int DownEndCUX, DownEndCUY;
348
349    NumCUWidth  = EndCUX - StartCUX +1;
350    NumCUHeight = EndCUY - StartCUY +1;
351    NumCULeft   = (NumCUWidth  >> 1);
352    NumCUTop    = (NumCUHeight >> 1);
353
354    DownStartCUX= StartCUX;
355    DownEndCUX  = DownStartCUX + NumCULeft - 1;
356    DownStartCUY= StartCUY;
357    DownEndCUY  = DownStartCUY + NumCUTop  - 1;
358    iDownRowIdx = DownRowStart + 0;
359    iDownColIdx = DownColStart + 0;
360
361    pSaoPart->DownPartsIdx[0]= convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
362
363    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx, DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
364
365    DownStartCUX = StartCUX + NumCULeft;
366    DownEndCUX   = EndCUX;
367    DownStartCUY = StartCUY;
368    DownEndCUY   = DownStartCUY + NumCUTop -1;
369    iDownRowIdx  = DownRowStart + 0;
370    iDownColIdx  = DownColStart + 1;
371
372    pSaoPart->DownPartsIdx[1] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
373
374    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx,  DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
375
376    DownStartCUX = StartCUX;
377    DownEndCUX   = DownStartCUX + NumCULeft -1;
378    DownStartCUY = StartCUY + NumCUTop;
379    DownEndCUY   = EndCUY;
380    iDownRowIdx  = DownRowStart + 1;
381    iDownColIdx  = DownColStart + 0;
382
383    pSaoPart->DownPartsIdx[2] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
384
385    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx, DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
386
387    DownStartCUX = StartCUX+ NumCULeft;
388    DownEndCUX   = EndCUX;
389    DownStartCUY = StartCUY + NumCUTop;
390    DownEndCUY   = EndCUY;
391    iDownRowIdx  = DownRowStart + 1;
392    iDownColIdx  = DownColStart + 1;
393
394    pSaoPart->DownPartsIdx[3] = convertLevelRowCol2Idx(DownLevel, iDownRowIdx, iDownColIdx);
395
396    initSAOParam(pcSaoParam, DownLevel, iDownRowIdx, iDownColIdx, iPartIdx,DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY, iYCbCr);
397  }
398  else
399  {
400    pSaoPart->DownPartsIdx[0]=pSaoPart->DownPartsIdx[1]= pSaoPart->DownPartsIdx[2]= pSaoPart->DownPartsIdx[3]= -1; 
401  }
402}
403
404/** free memory of SAO parameters
405 * \param   pcSaoParam
406 */
407Void TComSampleAdaptiveOffset::freeSaoParam(SAOParam *pcSaoParam)
408{
409  delete [] pcSaoParam->psSaoPart[0];
410  delete [] pcSaoParam->psSaoPart[1];
411  delete [] pcSaoParam->psSaoPart[2];
412  pcSaoParam->psSaoPart[0] = 0;
413  pcSaoParam->psSaoPart[1] = 0;
414  pcSaoParam->psSaoPart[2] = 0;
415  if( pcSaoParam->saoLcuParam[0]) 
416  {
417    delete [] pcSaoParam->saoLcuParam[0]; pcSaoParam->saoLcuParam[0] = NULL;
418  }
419  if( pcSaoParam->saoLcuParam[1]) 
420  {
421    delete [] pcSaoParam->saoLcuParam[1]; pcSaoParam->saoLcuParam[1] = NULL;
422  }
423  if( pcSaoParam->saoLcuParam[2]) 
424  {
425    delete [] pcSaoParam->saoLcuParam[2]; pcSaoParam->saoLcuParam[2] = NULL;
426  }
427} 
428
429/** reset SAO parameters
430 * \param   pcSaoParam
431 */
432Void TComSampleAdaptiveOffset::resetSAOParam(SAOParam *pcSaoParam)
433{
434  Int iNumComponet = 3;
435  for(Int c=0; c<iNumComponet; c++)
436  {
437#if SAO_TYPE_SHARING
438if (c<2)
439  {
440#endif
441    pcSaoParam->bSaoFlag[c] = 0;
442#if SAO_TYPE_SHARING
443  }
444#endif
445    for(Int i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
446    {
447      pcSaoParam->psSaoPart[c][i].iBestType     = -1;
448      pcSaoParam->psSaoPart[c][i].iLength       =  0;
449      pcSaoParam->psSaoPart[c][i].bSplit        = false; 
450      pcSaoParam->psSaoPart[c][i].bProcessed    = false;
451      pcSaoParam->psSaoPart[c][i].dMinCost      = MAX_DOUBLE;
452      pcSaoParam->psSaoPart[c][i].iMinDist      = MAX_INT;
453      pcSaoParam->psSaoPart[c][i].iMinRate      = MAX_INT;
454#if SAO_TYPE_CODING
455      pcSaoParam->psSaoPart[c][i].subTypeIdx    = 0;
456#else
457      pcSaoParam->psSaoPart[c][i].bandPosition = 0;
458#endif
459      for (Int j=0;j<MAX_NUM_SAO_OFFSETS;j++)
460      {
461        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
462        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
463        pcSaoParam->psSaoPart[c][i].iOffset[j] = 0;
464      }
465    }
466    pcSaoParam->oneUnitFlag[0]   = 0;
467    pcSaoParam->oneUnitFlag[1]   = 0;
468    pcSaoParam->oneUnitFlag[2]   = 0;
469    resetLcuPart(pcSaoParam->saoLcuParam[0]);
470    resetLcuPart(pcSaoParam->saoLcuParam[1]);
471    resetLcuPart(pcSaoParam->saoLcuParam[2]);
472  }
473}
474
475/** get the sign of input variable
476 * \param   x
477 */
478inline int xSign(int x)
479{
480  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
481}
482
483/** initialize variables for SAO process
484 * \param  pcPic picture data pointer
485 * \param  numSlicesInPic number of slices in picture
486 */
487Void TComSampleAdaptiveOffset::createPicSaoInfo(TComPic* pcPic, Int numSlicesInPic)
488{
489  m_pcPic   = pcPic;
490  m_uiNumSlicesInPic = numSlicesInPic;
491#if REMOVE_FGS
492  m_iSGDepth = 0;
493#else
494  m_iSGDepth         = pcPic->getSliceGranularityForNDBFilter();
495#endif
496  m_bUseNIF = ( pcPic->getIndependentSliceBoundaryForNDBFilter() || pcPic->getIndependentTileBoundaryForNDBFilter() );
497  if(m_bUseNIF)
498  {
499    m_pcYuvTmp = pcPic->getYuvPicBufferForIndependentBoundaryProcessing();
500  }
501}
502
503Void TComSampleAdaptiveOffset::destroyPicSaoInfo()
504{
505
506}
507
508/** sample adaptive offset process for one LCU
509 * \param   iAddr, iSaoType, iYCbCr
510 */
511Void TComSampleAdaptiveOffset::processSaoCu(Int iAddr, Int iSaoType, Int iYCbCr)
512{
513  if(!m_bUseNIF)
514  {
515    processSaoCuOrg( iAddr, iSaoType, iYCbCr);
516  }
517  else
518  { 
519    Int  isChroma = (iYCbCr != 0)? 1:0;
520    Int  stride   = (iYCbCr != 0)?(m_pcPic->getCStride()):(m_pcPic->getStride());
521    Pel* pPicRest = getPicYuvAddr(m_pcPic->getPicYuvRec(), iYCbCr);
522    Pel* pPicDec  = getPicYuvAddr(m_pcYuvTmp, iYCbCr);
523
524    std::vector<NDBFBlockInfo>& vFilterBlocks = *(m_pcPic->getCU(iAddr)->getNDBFilterBlocks());
525
526    //variables
527    UInt  xPos, yPos, width, height;
528    Bool* pbBorderAvail;
529    UInt  posOffset;
530
531    for(Int i=0; i< vFilterBlocks.size(); i++)
532    {
533      xPos        = vFilterBlocks[i].posX   >> isChroma;
534      yPos        = vFilterBlocks[i].posY   >> isChroma;
535      width       = vFilterBlocks[i].width  >> isChroma;
536      height      = vFilterBlocks[i].height >> isChroma;
537      pbBorderAvail = vFilterBlocks[i].isBorderAvailable;
538
539      posOffset = (yPos* stride) + xPos;
540
541      processSaoBlock(pPicDec+ posOffset, pPicRest+ posOffset, stride, iSaoType, xPos, yPos, width, height, pbBorderAvail);
542    }
543  }
544}
545
546/** Perform SAO for non-cross-slice or non-cross-tile process
547 * \param  pDec to-be-filtered block buffer pointer
548 * \param  pRest filtered block buffer pointer
549 * \param  stride picture buffer stride
550 * \param  saoType SAO offset type
551 * \param  xPos x coordinate
552 * \param  yPos y coordinate
553 * \param  width block width
554 * \param  height block height
555 * \param  pbBorderAvail availabilities of block border pixels
556 */
557Void TComSampleAdaptiveOffset::processSaoBlock(Pel* pDec, Pel* pRest, Int stride, Int saoType, UInt xPos, UInt yPos, UInt width, UInt height, Bool* pbBorderAvail)
558{
559  //variables
560  Int startX, startY, endX, endY, x, y;
561  Int signLeft,signRight,signDown,signDown1;
562  UInt edgeType;
563
564  switch (saoType)
565  {
566  case SAO_EO_0: // dir: -
567    {
568
569      startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
570      endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
571      for (y=0; y< height; y++)
572      {
573        signLeft = xSign(pDec[startX] - pDec[startX-1]);
574        for (x=startX; x< endX; x++)
575        {
576          signRight =  xSign(pDec[x] - pDec[x+1]); 
577          edgeType =  signRight + signLeft + 2;
578          signLeft  = -signRight;
579
580          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
581        }
582        pDec  += stride;
583        pRest += stride;
584      }
585      break;
586    }
587  case SAO_EO_1: // dir: |
588    {
589      startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
590      endY   = (pbBorderAvail[SGU_B]) ? height : height-1;
591      if (!pbBorderAvail[SGU_T])
592      {
593        pDec  += stride;
594        pRest += stride;
595      }
596      for (x=0; x< width; x++)
597      {
598        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x-stride]);
599      }
600      for (y=startY; y<endY; y++)
601      {
602        for (x=0; x< width; x++)
603        {
604          signDown  = xSign(pDec[x] - pDec[x+stride]); 
605          edgeType = signDown + m_iUpBuff1[x] + 2;
606          m_iUpBuff1[x]= -signDown;
607
608          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
609        }
610        pDec  += stride;
611        pRest += stride;
612      }
613      break;
614    }
615  case SAO_EO_2: // dir: 135
616    {
617      Int posShift= stride + 1;
618
619      startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
620      endX   = (pbBorderAvail[SGU_R]) ? width : (width-1);
621
622      //prepare 2nd line upper sign
623      pDec += stride;
624      for (x=startX; x< endX+1; x++)
625      {
626        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x- posShift]);
627      }
628
629      //1st line
630      pDec -= stride;
631      if(pbBorderAvail[SGU_TL])
632      {
633        x= 0;
634        edgeType      =  xSign(pDec[x] - pDec[x- posShift]) - m_iUpBuff1[x+1] + 2;
635        pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
636
637      }
638      if(pbBorderAvail[SGU_T])
639      {
640        for(x= 1; x< endX; x++)
641        {
642          edgeType      =  xSign(pDec[x] - pDec[x- posShift]) - m_iUpBuff1[x+1] + 2;
643          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
644        }
645      }
646      pDec   += stride;
647      pRest  += stride;
648
649
650      //middle lines
651      for (y= 1; y< height-1; y++)
652      {
653        for (x=startX; x<endX; x++)
654        {
655          signDown1      =  xSign(pDec[x] - pDec[x+ posShift]) ;
656          edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
657          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
658
659          m_iUpBufft[x+1] = -signDown1; 
660        }
661        m_iUpBufft[startX] = xSign(pDec[stride+startX] - pDec[startX-1]);
662
663        ipSwap     = m_iUpBuff1;
664        m_iUpBuff1 = m_iUpBufft;
665        m_iUpBufft = ipSwap;
666
667        pDec  += stride;
668        pRest += stride;
669      }
670
671      //last line
672      if(pbBorderAvail[SGU_B])
673      {
674        for(x= startX; x< width-1; x++)
675        {
676          edgeType =  xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
677          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
678        }
679      }
680      if(pbBorderAvail[SGU_BR])
681      {
682        x= width -1;
683        edgeType =  xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
684        pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
685      }
686      break;
687    } 
688  case SAO_EO_3: // dir: 45
689    {
690      Int  posShift     = stride - 1;
691      startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
692      endX   = (pbBorderAvail[SGU_R]) ? width : (width -1);
693
694      //prepare 2nd line upper sign
695      pDec += stride;
696      for (x=startX-1; x< endX; x++)
697      {
698        m_iUpBuff1[x] = xSign(pDec[x] - pDec[x- posShift]);
699      }
700
701
702      //first line
703      pDec -= stride;
704      if(pbBorderAvail[SGU_T])
705      {
706        for(x= startX; x< width -1; x++)
707        {
708          edgeType = xSign(pDec[x] - pDec[x- posShift]) -m_iUpBuff1[x-1] + 2;
709          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
710        }
711      }
712      if(pbBorderAvail[SGU_TR])
713      {
714        x= width-1;
715        edgeType = xSign(pDec[x] - pDec[x- posShift]) -m_iUpBuff1[x-1] + 2;
716        pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
717      }
718      pDec  += stride;
719      pRest += stride;
720
721      //middle lines
722      for (y= 1; y< height-1; y++)
723      {
724        for(x= startX; x< endX; x++)
725        {
726          signDown1      =  xSign(pDec[x] - pDec[x+ posShift]) ;
727          edgeType      =  signDown1 + m_iUpBuff1[x] + 2;
728
729          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
730          m_iUpBuff1[x-1] = -signDown1; 
731        }
732        m_iUpBuff1[endX-1] = xSign(pDec[endX-1 + stride] - pDec[endX]);
733
734        pDec  += stride;
735        pRest += stride;
736      }
737
738      //last line
739      if(pbBorderAvail[SGU_BL])
740      {
741        x= 0;
742        edgeType = xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
743        pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
744
745      }
746      if(pbBorderAvail[SGU_B])
747      {
748        for(x= 1; x< endX; x++)
749        {
750          edgeType = xSign(pDec[x] - pDec[x+ posShift]) + m_iUpBuff1[x] + 2;
751          pRest[x] = m_pClipTable[pDec[x] + m_iOffsetEo[edgeType]];
752        }
753      }
754      break;
755    }   
756  case SAO_BO:
757    {
758      for (y=0; y< height; y++)
759      {
760        for (x=0; x< width; x++)
761        {
762          pRest[x] = m_iOffsetBo[pDec[x]];
763        }
764        pRest += stride;
765        pDec  += stride;
766      }
767      break;
768    }
769  default: break;
770  }
771
772}
773
774/** sample adaptive offset process for one LCU crossing LCU boundary
775 * \param   iAddr, iSaoType, iYCbCr
776 */
777Void TComSampleAdaptiveOffset::processSaoCuOrg(Int iAddr, Int iSaoType, Int iYCbCr)
778{
779  Int x,y;
780  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
781  Pel* pRec;
782  Int  iStride;
783  Int  iLcuWidth  = m_uiMaxCUWidth;
784  Int  iLcuHeight = m_uiMaxCUHeight;
785  UInt uiLPelX    = pTmpCu->getCUPelX();
786  UInt uiTPelY    = pTmpCu->getCUPelY();
787  UInt uiRPelX;
788  UInt uiBPelY;
789  Int  iSignLeft;
790  Int  iSignRight;
791  Int  iSignDown;
792  Int  iSignDown1;
793  Int  iSignDown2;
794  UInt uiEdgeType;
795  Int iPicWidthTmp;
796  Int iPicHeightTmp;
797  Int iStartX;
798  Int iStartY;
799  Int iEndX;
800  Int iEndY;
801  Int iIsChroma = (iYCbCr!=0)? 1:0;
802  Int iShift;
803  Int iCuHeightTmp;
804  Pel *pTmpLSwap;
805  Pel *pTmpL;
806  Pel *pTmpU;
807
808  iPicWidthTmp  = m_iPicWidth  >> iIsChroma;
809  iPicHeightTmp = m_iPicHeight >> iIsChroma;
810  iLcuWidth     = iLcuWidth    >> iIsChroma;
811  iLcuHeight    = iLcuHeight   >> iIsChroma;
812  uiLPelX       = uiLPelX      >> iIsChroma;
813  uiTPelY       = uiTPelY      >> iIsChroma;
814  uiRPelX       = uiLPelX + iLcuWidth  ;
815  uiBPelY       = uiTPelY + iLcuHeight ;
816  uiRPelX       = uiRPelX > iPicWidthTmp  ? iPicWidthTmp  : uiRPelX;
817  uiBPelY       = uiBPelY > iPicHeightTmp ? iPicHeightTmp : uiBPelY;
818  iLcuWidth     = uiRPelX - uiLPelX;
819  iLcuHeight    = uiBPelY - uiTPelY;
820
821  if(pTmpCu->getPic()==0)
822  {
823    return;
824  }
825  if (iYCbCr == 0)
826  {
827    pRec       = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
828    iStride    = m_pcPic->getStride();
829  } 
830  else if (iYCbCr == 1)
831  {
832    pRec       = m_pcPic->getPicYuvRec()->getCbAddr(iAddr);
833    iStride    = m_pcPic->getCStride();
834  }
835  else 
836  {
837    pRec       = m_pcPic->getPicYuvRec()->getCrAddr(iAddr);
838    iStride    = m_pcPic->getCStride();
839  }
840
841//   if (iSaoType!=SAO_BO_0 || iSaoType!=SAO_BO_1)
842  {
843    iCuHeightTmp = (m_uiMaxCUHeight >> iIsChroma);
844    iShift = (m_uiMaxCUWidth>> iIsChroma)-1;
845    for (Int i=0;i<iCuHeightTmp+1;i++)
846    {
847      m_pTmpL2[i] = pRec[iShift];
848      pRec += iStride;
849    }
850    pRec -= (iStride*(iCuHeightTmp+1));
851
852    pTmpL = m_pTmpL1; 
853    pTmpU = &(m_pTmpU1[uiLPelX]); 
854  }
855
856  switch (iSaoType)
857  {
858  case SAO_EO_0: // dir: -
859    {
860      iStartX = (uiLPelX == 0) ? 1 : 0;
861      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
862      for (y=0; y<iLcuHeight; y++)
863      {
864        iSignLeft = xSign(pRec[iStartX] - pTmpL[y]);
865        for (x=iStartX; x< iEndX; x++)
866        {
867          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
868          uiEdgeType =  iSignRight + iSignLeft + 2;
869          iSignLeft  = -iSignRight;
870
871          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
872        }
873        pRec += iStride;
874      }
875      break;
876    }
877  case SAO_EO_1: // dir: |
878    {
879      iStartY = (uiTPelY == 0) ? 1 : 0;
880      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
881      if (uiTPelY == 0)
882      {
883        pRec += iStride;
884      }
885      for (x=0; x< iLcuWidth; x++)
886      {
887        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x]);
888      }
889      for (y=iStartY; y<iEndY; y++)
890      {
891        for (x=0; x<iLcuWidth; x++)
892        {
893          iSignDown  = xSign(pRec[x] - pRec[x+iStride]); 
894          uiEdgeType = iSignDown + m_iUpBuff1[x] + 2;
895          m_iUpBuff1[x]= -iSignDown;
896
897          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
898        }
899        pRec += iStride;
900      }
901      break;
902    }
903  case SAO_EO_2: // dir: 135
904    {
905      iStartX = (uiLPelX == 0)            ? 1 : 0;
906      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
907
908      iStartY = (uiTPelY == 0) ?             1 : 0;
909      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
910
911      if (uiTPelY == 0)
912      {
913        pRec += iStride;
914      }
915
916      for (x=iStartX; x<iEndX; x++)
917      {
918        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x-1]);
919      }
920      for (y=iStartY; y<iEndY; y++)
921      {
922        iSignDown2 = xSign(pRec[iStride+iStartX] - pTmpL[y]);
923        for (x=iStartX; x<iEndX; x++)
924        {
925          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
926          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
927          m_iUpBufft[x+1] = -iSignDown1; 
928          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
929        }
930        m_iUpBufft[iStartX] = iSignDown2;
931
932        ipSwap     = m_iUpBuff1;
933        m_iUpBuff1 = m_iUpBufft;
934        m_iUpBufft = ipSwap;
935
936        pRec += iStride;
937      }
938      break;
939    } 
940  case SAO_EO_3: // dir: 45
941    {
942      iStartX = (uiLPelX == 0) ? 1 : 0;
943      iEndX   = (uiRPelX == iPicWidthTmp) ? iLcuWidth-1 : iLcuWidth;
944
945      iStartY = (uiTPelY == 0) ? 1 : 0;
946      iEndY   = (uiBPelY == iPicHeightTmp) ? iLcuHeight-1 : iLcuHeight;
947
948      if (iStartY == 1)
949      {
950        pRec += iStride;
951      }
952
953      for (x=iStartX-1; x<iEndX; x++)
954      {
955        m_iUpBuff1[x] = xSign(pRec[x] - pTmpU[x+1]);
956      }
957      for (y=iStartY; y<iEndY; y++)
958      {
959        x=iStartX;
960        iSignDown1      =  xSign(pRec[x] - pTmpL[y+1]) ;
961        uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
962        m_iUpBuff1[x-1] = -iSignDown1; 
963        pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
964        for (x=iStartX+1; x<iEndX; x++)
965        {
966          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
967          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
968          m_iUpBuff1[x-1] = -iSignDown1; 
969          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
970        }
971        m_iUpBuff1[iEndX-1] = xSign(pRec[iEndX-1 + iStride] - pRec[iEndX]);
972
973        pRec += iStride;
974      } 
975      break;
976    }   
977  case SAO_BO:
978    {
979      for (y=0; y<iLcuHeight; y++)
980      {
981        for (x=0; x<iLcuWidth; x++)
982        {
983          pRec[x] = m_iOffsetBo[pRec[x]];
984        }
985        pRec += iStride;
986      }
987      break;
988    }
989  default: break;
990  }
991//   if (iSaoType!=SAO_BO_0 || iSaoType!=SAO_BO_1)
992  {
993    pTmpLSwap = m_pTmpL1;
994    m_pTmpL1  = m_pTmpL2;
995    m_pTmpL2  = pTmpLSwap;
996  }
997}
998/** Sample adaptive offset process
999 * \param pcPic, pcSaoParam 
1000 */
1001Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pcPic, SAOParam* pcSaoParam)
1002{
1003#if SAO_LUM_CHROMA_ONOFF_FLAGS && SAO_TYPE_SHARING
1004  if (pcSaoParam->bSaoFlag[0] || pcSaoParam->bSaoFlag[1])
1005#elif SAO_LUM_CHROMA_ONOFF_FLAGS
1006  if (pcSaoParam->bSaoFlag[0] || pcSaoParam->bSaoFlag[1] || pcSaoParam->bSaoFlag[2])
1007#else
1008  if (pcSaoParam->bSaoFlag[0])
1009#endif
1010  {
1011#if FULL_NBIT
1012    m_uiSaoBitIncrease = g_uiBitDepth + (g_uiBitDepth-8) - min((Int)(g_uiBitDepth + (g_uiBitDepth-8)), 10);
1013#else
1014    m_uiSaoBitIncrease = g_uiBitDepth + g_uiBitIncrement - min((Int)(g_uiBitDepth + g_uiBitIncrement), 10);
1015#endif
1016
1017    if(m_bUseNIF)
1018    {
1019      m_pcPic->getPicYuvRec()->copyToPic(m_pcYuvTmp);
1020    }
1021    if (m_saoLcuBasedOptimization)
1022    {
1023      pcSaoParam->oneUnitFlag[0] = 0; 
1024      pcSaoParam->oneUnitFlag[1] = 0; 
1025      pcSaoParam->oneUnitFlag[2] = 0; 
1026    }
1027    Int iY  = 0;
1028#if SAO_LUM_CHROMA_ONOFF_FLAGS
1029    if (pcSaoParam->bSaoFlag[0])
1030#endif
1031    {
1032      processSaoUnitAll( pcSaoParam->saoLcuParam[iY], pcSaoParam->oneUnitFlag[iY], iY);
1033    }
1034#if SAO_TYPE_SHARING
1035    if(pcSaoParam->bSaoFlag[1])
1036    {
1037       processSaoUnitAll( pcSaoParam->saoLcuParam[1], pcSaoParam->oneUnitFlag[1], 1);//Cb
1038       processSaoUnitAll( pcSaoParam->saoLcuParam[2], pcSaoParam->oneUnitFlag[2], 2);//Cr
1039    }
1040#else
1041    Int iCb = 1;
1042    Int iCr = 2;
1043    if (pcSaoParam->bSaoFlag[iCb])
1044    {
1045      processSaoUnitAll( pcSaoParam->saoLcuParam[iCb], pcSaoParam->oneUnitFlag[iCb], iCb);
1046    }
1047    if (pcSaoParam->bSaoFlag[iCr])
1048    {
1049      processSaoUnitAll( pcSaoParam->saoLcuParam[iCr], pcSaoParam->oneUnitFlag[iCr], iCr);
1050    }
1051#endif
1052    m_pcPic = NULL;
1053  }
1054}
1055
1056Pel* TComSampleAdaptiveOffset::getPicYuvAddr(TComPicYuv* pcPicYuv, Int iYCbCr, Int iAddr)
1057{
1058  switch (iYCbCr)
1059  {
1060  case 0:
1061    return pcPicYuv->getLumaAddr(iAddr);
1062    break;
1063  case 1:
1064    return pcPicYuv->getCbAddr(iAddr);
1065    break;
1066  case 2:
1067    return pcPicYuv->getCrAddr(iAddr);
1068    break;
1069  default:
1070    return NULL;
1071    break;
1072  }
1073}
1074/** Process SAO all units
1075 * \param saoLcuParam SAO LCU parameters
1076 * \param oneUnitFlag one unit flag
1077 * \param yCbCr color componet index
1078 */
1079Void TComSampleAdaptiveOffset::processSaoUnitAll(SaoLcuParam* saoLcuParam, Bool oneUnitFlag, Int yCbCr)
1080{
1081  Pel *pRec;
1082  Int picWidthTmp;
1083
1084  if (yCbCr == 0)
1085  {
1086    pRec        = m_pcPic->getPicYuvRec()->getLumaAddr();
1087    picWidthTmp = m_iPicWidth;
1088  } 
1089  else if (yCbCr == 1)
1090  {
1091    pRec        = m_pcPic->getPicYuvRec()->getCbAddr();
1092    picWidthTmp = m_iPicWidth>>1;
1093  }
1094  else 
1095  {
1096    pRec        = m_pcPic->getPicYuvRec()->getCrAddr();
1097    picWidthTmp = m_iPicWidth>>1;
1098  }
1099
1100  memcpy(m_pTmpU1, pRec, sizeof(Pel)*picWidthTmp);
1101
1102  int  i;
1103  UInt edgeType;
1104  Pel* ppLumaTable = NULL;
1105  Int  typeIdx;
1106
1107  Int offset[LUMA_GROUP_NUM+1];
1108  Int idxX;
1109  Int idxY;
1110  Int addr;
1111  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
1112  Int frameHeightInCU = m_pcPic->getFrameHeightInCU();
1113  Int stride;
1114  Pel *tmpUSwap;
1115  Int isChroma = (yCbCr == 0) ? 0:1;
1116  Bool mergeLeftFlag;
1117
1118  offset[0] = 0;
1119  for (idxY = 0; idxY< frameHeightInCU; idxY++)
1120  { 
1121    addr = idxY * frameWidthInCU;
1122    if (yCbCr == 0)
1123    {
1124      pRec  = m_pcPic->getPicYuvRec()->getLumaAddr(addr);
1125      stride = m_pcPic->getStride();
1126      picWidthTmp = m_iPicWidth;
1127    }
1128    else if (yCbCr == 1)
1129    {
1130      pRec  = m_pcPic->getPicYuvRec()->getCbAddr(addr);
1131      stride = m_pcPic->getCStride();
1132      picWidthTmp = m_iPicWidth>>1;
1133    }
1134    else
1135    {
1136      pRec  = m_pcPic->getPicYuvRec()->getCrAddr(addr);
1137      stride = m_pcPic->getCStride();
1138      picWidthTmp = m_iPicWidth>>1;
1139    }
1140
1141    //     pRec += iStride*(m_uiMaxCUHeight-1);
1142    for (i=0;i<(m_uiMaxCUHeight>>isChroma)+1;i++)
1143    {
1144      m_pTmpL1[i] = pRec[0];
1145      pRec+=stride;
1146    }
1147    pRec-=(stride<<1);
1148
1149    memcpy(m_pTmpU2, pRec, sizeof(Pel)*picWidthTmp);
1150
1151    for (idxX = 0; idxX < frameWidthInCU; idxX++)
1152    {
1153      addr = idxY * frameWidthInCU + idxX;
1154
1155      if (oneUnitFlag)
1156      {
1157        typeIdx = saoLcuParam[0].typeIdx;
1158        mergeLeftFlag = (addr == 0)? 0:1;
1159      }
1160      else
1161      {
1162        typeIdx = saoLcuParam[addr].typeIdx;
1163        mergeLeftFlag = saoLcuParam[addr].mergeLeftFlag;
1164      }
1165      if (typeIdx>=0)
1166      {
1167        if (!mergeLeftFlag)
1168        {
1169
1170          if (typeIdx == SAO_BO)
1171          {
1172            for (i=0; i<SAO_MAX_BO_CLASSES+1;i++)
1173            {
1174              offset[i] = 0;
1175            }
1176            for (i=0; i<saoLcuParam[addr].length; i++)
1177            {
1178#if SAO_TYPE_CODING
1179              offset[ (saoLcuParam[addr].subTypeIdx +i)%SAO_MAX_BO_CLASSES  +1] = saoLcuParam[addr].offset[i] << m_uiSaoBitIncrease;
1180#else
1181              offset[ (saoLcuParam[addr].bandPosition +i)%SAO_MAX_BO_CLASSES  +1] = saoLcuParam[addr].offset[i] << m_uiSaoBitIncrease;
1182#endif
1183            }
1184
1185            ppLumaTable = m_lumaTableBo;
1186
1187#if FULL_NBIT
1188            for (i=0;i<(1<<(g_uiBitDepth));i++)
1189#else
1190            for (i=0;i<(1<<(g_uiBitIncrement+8));i++)
1191#endif
1192            {
1193              m_iOffsetBo[i] = m_pClipTable[i + offset[ppLumaTable[i]]];
1194            }
1195
1196          }
1197          if (typeIdx == SAO_EO_0 || typeIdx == SAO_EO_1 || typeIdx == SAO_EO_2 || typeIdx == SAO_EO_3)
1198          {
1199            for (i=0;i<saoLcuParam[addr].length;i++)
1200            {
1201              offset[i+1] = saoLcuParam[addr].offset[i] << m_uiSaoBitIncrease;
1202            }
1203            for (edgeType=0;edgeType<6;edgeType++)
1204            {
1205              m_iOffsetEo[edgeType]= offset[m_auiEoTable[edgeType]];
1206            }
1207          }
1208        }
1209        processSaoCu(addr, typeIdx, yCbCr);
1210      }
1211      else
1212      {
1213        if (idxX != (frameWidthInCU-1))
1214        {
1215          if (yCbCr == 0)
1216          {
1217            pRec  = m_pcPic->getPicYuvRec()->getLumaAddr(addr);
1218            stride = m_pcPic->getStride();
1219          }
1220          else if (yCbCr == 1)
1221          {
1222            pRec  = m_pcPic->getPicYuvRec()->getCbAddr(addr);
1223            stride = m_pcPic->getCStride();
1224          }
1225          else
1226          {
1227            pRec  = m_pcPic->getPicYuvRec()->getCrAddr(addr);
1228            stride = m_pcPic->getCStride();
1229          }
1230          Int widthShift = m_uiMaxCUWidth>>isChroma;
1231          for (i=0;i<(m_uiMaxCUHeight>>isChroma)+1;i++)
1232          {
1233            m_pTmpL1[i] = pRec[widthShift-1];
1234            pRec+=stride;
1235          }
1236        }
1237      }
1238    }
1239    tmpUSwap = m_pTmpU1;
1240    m_pTmpU1 = m_pTmpU2;
1241    m_pTmpU2 = tmpUSwap;
1242  }
1243
1244}
1245/** Reset SAO LCU part
1246 * \param saoLcuParam
1247 */
1248Void TComSampleAdaptiveOffset::resetLcuPart(SaoLcuParam* saoLcuParam)
1249{
1250  Int i,j;
1251  for (i=0;i<m_iNumCuInWidth*m_iNumCuInHeight;i++)
1252  {
1253    saoLcuParam[i].mergeUpFlag     =  1;
1254    saoLcuParam[i].mergeLeftFlag =  0;
1255    saoLcuParam[i].partIdx   =  0;
1256    saoLcuParam[i].typeIdx      = -1;
1257    for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1258    {
1259      saoLcuParam[i].offset[j] = 0;
1260    }
1261#if SAO_TYPE_CODING
1262    saoLcuParam[i].subTypeIdx = 0;
1263#else
1264    saoLcuParam[i].bandPosition = 0;
1265#endif
1266  }
1267}
1268
1269/** convert QP part to SAO unit
1270* \param saoParam SAO parameter
1271* \param partIdx SAO part index
1272* \param yCbCr color component index
1273 */
1274Void TComSampleAdaptiveOffset::convertQT2SaoUnit(SAOParam *saoParam, UInt partIdx, Int yCbCr)
1275{
1276
1277  SAOQTPart*  saoPart= &(saoParam->psSaoPart[yCbCr][partIdx]);
1278  if (!saoPart->bSplit)
1279  {
1280    convertOnePart2SaoUnit(saoParam, partIdx, yCbCr);
1281    return;
1282  }
1283
1284  if (saoPart->PartLevel < m_uiMaxSplitLevel)
1285  {
1286    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[0], yCbCr);
1287    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[1], yCbCr);
1288    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[2], yCbCr);
1289    convertQT2SaoUnit(saoParam, saoPart->DownPartsIdx[3], yCbCr);
1290  }
1291}
1292/** convert one SAO part to SAO unit
1293* \param saoParam SAO parameter
1294* \param partIdx SAO part index
1295* \param yCbCr color component index
1296 */
1297Void TComSampleAdaptiveOffset::convertOnePart2SaoUnit(SAOParam *saoParam, UInt partIdx, Int yCbCr)
1298{
1299  Int j;
1300  Int idxX;
1301  Int idxY;
1302  Int addr;
1303  Int frameWidthInCU = m_pcPic->getFrameWidthInCU();
1304  SAOQTPart* saoQTPart = saoParam->psSaoPart[yCbCr];
1305  SaoLcuParam* saoLcuParam = saoParam->saoLcuParam[yCbCr];
1306
1307  for (idxY = saoQTPart[partIdx].StartCUY; idxY<= saoQTPart[partIdx].EndCUY; idxY++)
1308  {
1309    for (idxX = saoQTPart[partIdx].StartCUX; idxX<= saoQTPart[partIdx].EndCUX; idxX++)
1310    {
1311      addr = idxY * frameWidthInCU + idxX;
1312      saoLcuParam[addr].partIdxTmp = (Int)partIdx; 
1313      saoLcuParam[addr].typeIdx    = saoQTPart[partIdx].iBestType;
1314#if SAO_TYPE_CODING
1315      saoLcuParam[addr].subTypeIdx = saoQTPart[partIdx].subTypeIdx;
1316#else
1317      saoLcuParam[addr].bandPosition = saoQTPart[partIdx].bandPosition;
1318#endif
1319      if (saoLcuParam[addr].typeIdx!=-1)
1320      {
1321        saoLcuParam[addr].length    = saoQTPart[partIdx].iLength;
1322        for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1323        {
1324          saoLcuParam[addr].offset[j] = saoQTPart[partIdx].iOffset[j];
1325        }
1326      }
1327      else
1328      {
1329        saoLcuParam[addr].length    = 0;
1330#if SAO_TYPE_CODING
1331        saoLcuParam[addr].subTypeIdx = saoQTPart[partIdx].subTypeIdx;
1332#else
1333        saoLcuParam[addr].bandPosition = saoQTPart[partIdx].bandPosition;
1334#endif
1335        for (j=0;j<MAX_NUM_SAO_OFFSETS;j++)
1336        {
1337          saoLcuParam[addr].offset[j] = 0;
1338        }
1339      }
1340    }
1341  }
1342}
1343
1344Void TComSampleAdaptiveOffset::resetSaoUnit(SaoLcuParam* saoUnit)
1345{
1346  saoUnit->partIdx       = 0;
1347  saoUnit->partIdxTmp    = 0;
1348  saoUnit->mergeLeftFlag = 0;
1349  saoUnit->mergeUpFlag   = 0;
1350  saoUnit->typeIdx       = -1;
1351  saoUnit->length        = 0;
1352#if SAO_TYPE_CODING
1353  saoUnit->subTypeIdx    = 0;
1354#else
1355  saoUnit->bandPosition  = 0;
1356#endif
1357
1358  for (Int i=0;i<4;i++)
1359  {
1360    saoUnit->offset[i] = 0;
1361  }
1362}
1363
1364#if SAO_SINGLE_MERGE
1365Void TComSampleAdaptiveOffset::copySaoUnit(SaoLcuParam* saoUnitDst, SaoLcuParam* saoUnitSrc )
1366{
1367  saoUnitDst->mergeLeftFlag = saoUnitSrc->mergeLeftFlag;
1368  saoUnitDst->mergeUpFlag   = saoUnitSrc->mergeUpFlag;
1369  saoUnitDst->typeIdx       = saoUnitSrc->typeIdx;
1370  saoUnitDst->length        = saoUnitSrc->length;
1371
1372#if SAO_TYPE_CODING
1373  saoUnitDst->subTypeIdx  = saoUnitSrc->subTypeIdx;
1374#else
1375  saoUnitDst->bandPosition  = saoUnitSrc->bandPosition;
1376#endif
1377  for (Int i=0;i<4;i++)
1378  {
1379    saoUnitDst->offset[i] = saoUnitSrc->offset[i];
1380  }
1381}
1382#endif
1383
1384#if REMOVE_ALF
1385/** PCM LF disable process.
1386 * \param pcPic picture (TComPic) pointer
1387 * \returns Void
1388 *
1389 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
1390 */
1391Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic)
1392{
1393  xPCMRestoration(pcPic);
1394}
1395
1396/** Picture-level PCM restoration.
1397 * \param pcPic picture (TComPic) pointer
1398 * \returns Void
1399 */
1400Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic)
1401{
1402  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
1403
1404  if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnableFlag())
1405  {
1406    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
1407    {
1408      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
1409
1410      xPCMCURestoration(pcCU, 0, 0); 
1411    } 
1412  }
1413}
1414
1415/** PCM CU restoration.
1416 * \param pcCU pointer to current CU
1417 * \param uiAbsPartIdx part index
1418 * \param uiDepth CU depth
1419 * \returns Void
1420 */
1421Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
1422{
1423  TComPic* pcPic     = pcCU->getPic();
1424  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
1425  UInt uiQNumParts   = uiCurNumParts>>2;
1426
1427  // go to sub-CU
1428  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
1429  {
1430    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
1431    {
1432      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
1433      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
1434      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
1435        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
1436    }
1437    return;
1438  }
1439
1440  // restore PCM samples
1441  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx))
1442  {
1443    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
1444    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
1445    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
1446  }
1447}
1448
1449/** PCM sample restoration.
1450 * \param pcCU pointer to current CU
1451 * \param uiAbsPartIdx part index
1452 * \param uiDepth CU depth
1453 * \param ttText texture component type
1454 * \returns Void
1455 */
1456Void TComSampleAdaptiveOffset::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
1457{
1458  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
1459  Pel* piSrc;
1460  Pel* piPcm;
1461  UInt uiStride;
1462  UInt uiWidth;
1463  UInt uiHeight;
1464  UInt uiPcmLeftShiftBit; 
1465  UInt uiX, uiY;
1466  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
1467  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
1468  UInt uiChromaOffset = uiLumaOffset>>2;
1469
1470  if( ttText == TEXT_LUMA )
1471  {
1472    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
1473    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
1474    uiStride  = pcPicYuvRec->getStride();
1475    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
1476    uiHeight = (g_uiMaxCUHeight >> uiDepth);
1477    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
1478    {
1479      uiPcmLeftShiftBit = 0;
1480    }
1481    else
1482    {
1483        uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
1484    }
1485  }
1486  else
1487  {
1488    if( ttText == TEXT_CHROMA_U )
1489    {
1490      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
1491      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
1492    }
1493    else
1494    {
1495      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
1496      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
1497    }
1498
1499    uiStride = pcPicYuvRec->getCStride();
1500    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
1501    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
1502    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
1503    {
1504      uiPcmLeftShiftBit = 0;
1505    }
1506    else
1507    {
1508      uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
1509    }
1510  }
1511
1512  for( uiY = 0; uiY < uiHeight; uiY++ )
1513  {
1514    for( uiX = 0; uiX < uiWidth; uiX++ )
1515    {
1516      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
1517    }
1518    piPcm += uiWidth;
1519    piSrc += uiStride;
1520  }
1521}
1522#endif
1523
1524//! \}
Note: See TracBrowser for help on using the repository browser.