source: 3DVCSoftware/branches/HTM-6.0-dev0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 308

Last change on this file since 308 was 296, checked in by tech, 11 years ago

Reintegrated branch 5.1-dev0 rev. 295.

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