Ticket #623: TComSampleAdaptiveOffset.cpp

File TComSampleAdaptiveOffset.cpp, 38.6 KB (added by ywhe, 12 years ago)

fixed the memory leak for SAO data st.ored in APS. The fixed fucntion is SAOParam::~SAOParam()

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