source: SHVCSoftware/branches/HM-10.0-dev-SHM/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 558

Last change on this file since 558 was 51, checked in by suehring, 12 years ago

import HM 10.0 (HEVCSoftware/trunk rev. 3352)

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