source: 3DVCSoftware/tags/HTM-7.0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 445

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