source: 3DVCSoftware/trunk/source/Lib/TLibCommon/TComLoopFilter.cpp @ 56

Last change on this file since 56 was 56, checked in by hschwarz, 12 years ago

updated trunk (move to HM6.1)

  • Property svn:eol-style set to native
File size: 35.3 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     TComLoopFilter.cpp
35    \brief    deblocking filter
36*/
37
38#include "TComLoopFilter.h"
39#include "TComSlice.h"
40#include "TComMv.h"
41
42//! \ingroup TLibCommon
43//! \{
44
45// ====================================================================================================================
46// Constants
47// ====================================================================================================================
48
49#define   EDGE_VER    0
50#define   EDGE_HOR    1
51#define   QpUV(iQpY)  ( g_aucChromaScale[ max( min( (iQpY), MAX_QP ), MIN_QP ) ] )
52
53#define DEFAULT_INTRA_TC_OFFSET 2 ///< Default intra TC offset
54
55// ====================================================================================================================
56// Tables
57// ====================================================================================================================
58
59const UChar tctable_8x8[56] =
60{
61  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,6,6,7,8,9,9,10,10,11,11,12,12,13,13,14,14
62};
63
64const UChar betatable_8x8[52] =
65{
66  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64
67};
68
69// ====================================================================================================================
70// Constructor / destructor / create / destroy
71// ====================================================================================================================
72
73TComLoopFilter::TComLoopFilter()
74: m_uiNumPartitions( 0 )
75{
76  m_uiDisableDeblockingFilterIdc = 0;
77  m_bLFCrossTileBoundary = true;
78}
79
80TComLoopFilter::~TComLoopFilter()
81{
82}
83
84// ====================================================================================================================
85// Public member functions
86// ====================================================================================================================
87#if DBL_CONTROL
88Void TComLoopFilter::setCfg( Bool DeblockingFilterControlPresent, UInt uiDisableDblkIdc, Int iBetaOffset_div2, Int iTcOffset_div2, Bool bLFCrossTileBoundary)
89#else
90Void TComLoopFilter::setCfg( UInt uiDisableDblkIdc, Int iBetaOffset_div2, Int iTcOffset_div2, Bool bLFCrossTileBoundary)
91#endif
92{
93#if !DBL_CONTROL
94  m_uiDisableDeblockingFilterIdc  = uiDisableDblkIdc;
95#endif
96  m_bLFCrossTileBoundary = bLFCrossTileBoundary;
97
98#if DBL_CONTROL
99  if (DeblockingFilterControlPresent)
100  {
101    m_uiDisableDeblockingFilterIdc  = uiDisableDblkIdc;
102    m_betaOffsetDiv2 = iBetaOffset_div2;
103    m_tcOffsetDiv2 = iTcOffset_div2;
104  } 
105  else // use default values
106  {
107    m_uiDisableDeblockingFilterIdc = 0;
108    m_betaOffsetDiv2 = 0;
109    m_tcOffsetDiv2 = 0;
110  }
111#else
112  m_betaOffsetDiv2 = iBetaOffset_div2;
113  m_tcOffsetDiv2 = iTcOffset_div2;
114#endif
115}
116
117Void TComLoopFilter::create( UInt uiMaxCUDepth )
118{
119  m_uiNumPartitions = 1 << ( uiMaxCUDepth<<1 );
120  for( UInt uiDir = 0; uiDir < 2; uiDir++ )
121  {
122    m_aapucBS       [uiDir] = new UChar[m_uiNumPartitions];
123    for( UInt uiPlane = 0; uiPlane < 3; uiPlane++ )
124    {
125      m_aapbEdgeFilter[uiDir][uiPlane] = new Bool [m_uiNumPartitions];
126    }
127  }
128}
129
130Void TComLoopFilter::destroy()
131{
132  for( UInt uiDir = 0; uiDir < 2; uiDir++ )
133  {
134    delete [] m_aapucBS       [uiDir];
135    for( UInt uiPlane = 0; uiPlane < 3; uiPlane++ )
136    {
137      delete [] m_aapbEdgeFilter[uiDir][uiPlane];
138    }
139  }
140}
141
142/**
143 - call deblocking function for every CU
144 .
145 \param  pcPic   picture class (TComPic) pointer
146 */
147Void TComLoopFilter::loopFilterPic( TComPic* pcPic )
148{
149  if (m_uiDisableDeblockingFilterIdc == 1)
150  {
151    return;
152  }
153 
154  // Horizontal filtering
155  for ( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++ )
156  {
157    TComDataCU* pcCU = pcPic->getCU( uiCUAddr );
158
159    ::memset( m_aapucBS       [EDGE_VER], 0, sizeof( UChar ) * m_uiNumPartitions );
160    for( Int iPlane = 0; iPlane < 3; iPlane++ )
161    {
162      ::memset( m_aapbEdgeFilter[EDGE_VER][iPlane], 0, sizeof( bool  ) * m_uiNumPartitions );
163    }
164
165    // CU-based deblocking
166    xDeblockCU( pcCU, 0, 0, EDGE_VER );
167  }
168
169  // Vertical filtering
170  for ( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++ )
171  {
172    TComDataCU* pcCU = pcPic->getCU( uiCUAddr );
173
174      ::memset( m_aapucBS       [EDGE_HOR], 0, sizeof( UChar ) * m_uiNumPartitions );
175    for( Int iPlane = 0; iPlane < 3; iPlane++ )
176    {
177      ::memset( m_aapbEdgeFilter[EDGE_HOR][iPlane], 0, sizeof( bool  ) * m_uiNumPartitions );
178    }
179
180    // CU-based deblocking
181    xDeblockCU( pcCU, 0, 0, EDGE_HOR );
182  }
183}
184
185
186// ====================================================================================================================
187// Protected member functions
188// ====================================================================================================================
189
190/**
191 - Deblocking filter process in CU-based (the same function as conventional's)
192 .
193 \param Edge          the direction of the edge in block boundary (horizonta/vertical), which is added newly
194*/
195Void TComLoopFilter::xDeblockCU( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, Int Edge )
196{
197  if(pcCU->getPic()==0||pcCU->getPartitionSize(uiAbsZorderIdx)==SIZE_NONE)
198  {
199    return;
200  }
201  TComPic* pcPic     = pcCU->getPic();
202  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
203  UInt uiQNumParts   = uiCurNumParts>>2;
204 
205  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
206  {
207    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
208    {
209      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
210      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
211      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
212      {
213        xDeblockCU( pcCU, uiAbsZorderIdx, uiDepth+1, Edge );
214      }
215    }
216    return;
217  }
218 
219  xSetLoopfilterParam( pcCU, uiAbsZorderIdx );
220 
221  xSetEdgefilterTU   ( pcCU, uiAbsZorderIdx , uiAbsZorderIdx, uiDepth );
222  xSetEdgefilterPU   ( pcCU, uiAbsZorderIdx );
223 
224  Int iDir = Edge;
225  for( UInt uiPartIdx = uiAbsZorderIdx; uiPartIdx < uiAbsZorderIdx + uiCurNumParts; uiPartIdx++ )
226  {
227    UInt uiBSCheck = ((iDir == EDGE_VER && uiPartIdx%2 == 0) || (iDir == EDGE_HOR && (uiPartIdx-((uiPartIdx>>2)<<2))/2 == 0));
228    if ( m_aapbEdgeFilter[iDir][0][uiPartIdx] && uiBSCheck )
229    {
230      xGetBoundaryStrengthSingle ( pcCU, uiAbsZorderIdx, iDir, uiPartIdx );
231    }
232  }
233 
234  UInt uiPelsInPart = g_uiMaxCUWidth >> g_uiMaxCUDepth;
235  UInt PartIdxIncr = DEBLOCK_SMALLEST_BLOCK / uiPelsInPart ? DEBLOCK_SMALLEST_BLOCK / uiPelsInPart : 1 ;
236 
237  UInt uiSizeInPU = pcPic->getNumPartInWidth()>>(uiDepth);
238 
239  for ( UInt iEdge = 0; iEdge < uiSizeInPU ; iEdge+=PartIdxIncr)
240  {
241    xEdgeFilterLuma     ( pcCU, uiAbsZorderIdx, uiDepth, iDir, iEdge );
242    if ( (iEdge % ( (DEBLOCK_SMALLEST_BLOCK<<1)/uiPelsInPart ) ) == 0 )
243    {
244      xEdgeFilterChroma   ( pcCU, uiAbsZorderIdx, uiDepth, iDir, iEdge );
245    }
246  }
247}
248
249Void TComLoopFilter::xSetEdgefilterMultiple( TComDataCU* pcCU, UInt uiScanIdx, UInt uiDepth, Int iDir, Int iEdgeIdx, Bool bValue,UInt uiWidthInBaseUnits, UInt uiHeightInBaseUnits, Bool nonSquare )
250{ 
251  if ( uiWidthInBaseUnits == 0 )
252  {
253    uiWidthInBaseUnits  = pcCU->getPic()->getNumPartInWidth () >> uiDepth;
254  }
255  if ( uiHeightInBaseUnits == 0 )
256  {
257    uiHeightInBaseUnits = pcCU->getPic()->getNumPartInHeight() >> uiDepth;
258  }
259  const UInt uiNumElem = iDir == 0 ? uiHeightInBaseUnits : uiWidthInBaseUnits;
260  assert( uiNumElem > 0 );
261  assert( uiWidthInBaseUnits > 0 );
262  assert( uiHeightInBaseUnits > 0 );
263  for( UInt ui = 0; ui < uiNumElem; ui++ )
264  {
265    const UInt uiBsIdx = xCalcBsIdx( pcCU, uiScanIdx, iDir, iEdgeIdx, ui );
266    m_aapbEdgeFilter[iDir][0][uiBsIdx] = bValue;
267    m_aapbEdgeFilter[iDir][1][uiBsIdx] = bValue;
268    m_aapbEdgeFilter[iDir][2][uiBsIdx] = bValue;
269    if (iEdgeIdx == 0)
270    {
271      m_aapucBS[iDir][uiBsIdx] = bValue;
272    }
273  }
274}
275
276Void TComLoopFilter::xSetEdgefilterTU( TComDataCU* pcCU, UInt absTUPartIdx, UInt uiAbsZorderIdx, UInt uiDepth )
277{
278  if( pcCU->getTransformIdx( uiAbsZorderIdx ) + pcCU->getDepth( uiAbsZorderIdx) > uiDepth )
279  {
280    const UInt uiCurNumParts = pcCU->getPic()->getNumPartInCU() >> (uiDepth<<1);
281    const UInt uiQNumParts   = uiCurNumParts>>2;
282    const UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiDepth ] + 2;
283    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
284    {
285      UInt nsAddr = 0;
286      nsAddr = pcCU->getNSAbsPartIdx( uiLog2TrSize - 1, uiAbsZorderIdx, absTUPartIdx, uiPartIdx, uiDepth + 1 - pcCU->getDepth( uiAbsZorderIdx ) );
287      xSetEdgefilterTU( pcCU,nsAddr, uiAbsZorderIdx, uiDepth + 1 );
288    }
289    return;
290  }
291
292  Int trWidth  = pcCU->getWidth( uiAbsZorderIdx ) >> pcCU->getTransformIdx( uiAbsZorderIdx );
293  Int trHeight = pcCU->getHeight( uiAbsZorderIdx ) >> pcCU->getTransformIdx( uiAbsZorderIdx );
294  pcCU->getNSQTSize( uiDepth - pcCU->getDepth( uiAbsZorderIdx ), uiAbsZorderIdx, trWidth, trHeight );
295
296  UInt uiWidthInBaseUnits  = trWidth >> 2;
297  UInt uiHeightInBaseUnits = trHeight >> 2;
298
299  xSetEdgefilterMultiple( pcCU, absTUPartIdx, uiDepth, EDGE_VER, 0, m_stLFCUParam.bInternalEdge, uiWidthInBaseUnits, uiHeightInBaseUnits );
300  xSetEdgefilterMultiple( pcCU, absTUPartIdx, uiDepth, EDGE_HOR, 0, m_stLFCUParam.bInternalEdge, uiWidthInBaseUnits, uiHeightInBaseUnits );
301}
302
303Void TComLoopFilter::xSetEdgefilterPU( TComDataCU* pcCU, UInt uiAbsZorderIdx )
304{
305  const UInt uiDepth = pcCU->getDepth( uiAbsZorderIdx );
306  const UInt uiWidthInBaseUnits  = pcCU->getPic()->getNumPartInWidth () >> uiDepth;
307  const UInt uiHeightInBaseUnits = pcCU->getPic()->getNumPartInHeight() >> uiDepth;
308  const UInt uiHWidthInBaseUnits  = uiWidthInBaseUnits  >> 1;
309  const UInt uiHHeightInBaseUnits = uiHeightInBaseUnits >> 1;
310  const UInt uiQWidthInBaseUnits  = uiWidthInBaseUnits  >> 2;
311  const UInt uiQHeightInBaseUnits = uiHeightInBaseUnits >> 2;
312 
313  xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, 0, m_stLFCUParam.bLeftEdge );
314  xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, 0, m_stLFCUParam.bTopEdge );
315 
316  switch ( pcCU->getPartitionSize( uiAbsZorderIdx ) )
317  {
318    case SIZE_2Nx2N:
319    {
320      break;
321    }
322    case SIZE_2NxN:
323    {
324      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHHeightInBaseUnits, m_stLFCUParam.bInternalEdge );
325      break;
326    }
327    case SIZE_Nx2N:
328    {
329      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiHWidthInBaseUnits, m_stLFCUParam.bInternalEdge );
330      break;
331    }
332    case SIZE_NxN:
333    {
334      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiHWidthInBaseUnits, m_stLFCUParam.bInternalEdge );
335      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHHeightInBaseUnits, m_stLFCUParam.bInternalEdge );
336      break;
337    }
338    case SIZE_2NxnU:
339    {
340      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiQHeightInBaseUnits, m_stLFCUParam.bInternalEdge );
341      break;
342    }
343    case SIZE_2NxnD:
344    {
345      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHeightInBaseUnits - uiQHeightInBaseUnits, m_stLFCUParam.bInternalEdge );
346      break;
347    }
348    case SIZE_nLx2N:
349    {
350      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiQWidthInBaseUnits, m_stLFCUParam.bInternalEdge );
351      break;
352    }
353    case SIZE_nRx2N:
354    {
355      xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiWidthInBaseUnits - uiQWidthInBaseUnits, m_stLFCUParam.bInternalEdge );
356      break;
357    }
358    default:
359    {
360      break;
361    }
362  }
363}
364
365
366Void TComLoopFilter::xSetLoopfilterParam( TComDataCU* pcCU, UInt uiAbsZorderIdx )
367{
368  UInt uiX           = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[ uiAbsZorderIdx ] ];
369  UInt uiY           = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[ uiAbsZorderIdx ] ];
370 
371  TComDataCU* pcTempCU;
372  UInt        uiTempPartIdx;
373
374  m_stLFCUParam.bInternalEdge = m_uiDisableDeblockingFilterIdc ? false : true ;
375 
376  if ( (uiX == 0) || (m_uiDisableDeblockingFilterIdc == 1) )
377  {
378    m_stLFCUParam.bLeftEdge = false;
379  }
380  else
381  {
382    m_stLFCUParam.bLeftEdge = true;
383  }
384  if ( m_stLFCUParam.bLeftEdge )
385  {
386    pcTempCU = pcCU->getPULeft( uiTempPartIdx, uiAbsZorderIdx, !pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
387    if ( pcTempCU )
388    {
389      m_stLFCUParam.bLeftEdge = true;
390    }
391    else
392    {
393      m_stLFCUParam.bLeftEdge = false;
394    }
395  }
396 
397  if ( (uiY == 0 ) || (m_uiDisableDeblockingFilterIdc == 1) )
398  {
399    m_stLFCUParam.bTopEdge = false;
400  }
401  else
402  {
403    m_stLFCUParam.bTopEdge = true;
404  }
405  if ( m_stLFCUParam.bTopEdge )
406  {
407    pcTempCU = pcCU->getPUAbove( uiTempPartIdx, uiAbsZorderIdx, !pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false , false, false, !m_bLFCrossTileBoundary);
408    if ( pcTempCU )
409    {
410      m_stLFCUParam.bTopEdge = true;
411    }
412    else
413    {
414      m_stLFCUParam.bTopEdge = false;
415    }
416  }
417}
418
419Void TComLoopFilter::xGetBoundaryStrengthSingle ( TComDataCU* pcCU, UInt uiAbsZorderIdx, Int iDir, UInt uiAbsPartIdx )
420{
421  TComSlice* const pcSlice = pcCU->getSlice();
422 
423  const UInt uiPartQ = uiAbsPartIdx;
424  TComDataCU* const pcCUQ = pcCU;
425 
426  UInt uiPartP;
427  TComDataCU* pcCUP;
428  UInt uiBs = 0;
429 
430  //-- Calculate Block Index
431  if (iDir == EDGE_VER)
432  {
433    pcCUP = pcCUQ->getPULeft(uiPartP, uiPartQ, !pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
434  }
435  else  // (iDir == EDGE_HOR)
436  {
437    pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, false, false, !m_bLFCrossTileBoundary);
438  }
439 
440  //-- Set BS for Intra MB : BS = 4 or 3
441  if ( pcCUP->isIntra(uiPartP) || pcCUQ->isIntra(uiPartQ) )
442  {
443    uiBs = 2;
444  }
445 
446  //-- Set BS for not Intra MB : BS = 2 or 1 or 0
447  if ( !pcCUP->isIntra(uiPartP) && !pcCUQ->isIntra(uiPartQ) )
448  {
449#if NSQT_LFFIX
450    UInt nsPartQ = uiPartQ;
451    UInt nsPartP = uiPartP;
452    if(pcCUQ->getPredictionMode(uiPartQ) == MODE_INTER && pcCUQ->useNonSquarePU(uiPartQ))
453    {
454      nsPartQ = pcCUQ->getNSQTPartIdx( uiAbsPartIdx );
455    }
456    if(pcCUP->getPredictionMode(uiPartP) == MODE_INTER && pcCUP->useNonSquarePU(uiPartP))
457    {
458      nsPartP = pcCUP->getNSQTPartIdx( uiPartP );
459    }
460
461    if ( m_aapucBS[iDir][uiAbsPartIdx] && (pcCUQ->getCbf( nsPartQ, TEXT_LUMA, pcCUQ->getTransformIdx(nsPartQ)) != 0 || pcCUP->getCbf( nsPartP, TEXT_LUMA, pcCUP->getTransformIdx(nsPartP) ) != 0) )
462#else
463    if ( m_aapucBS[iDir][uiAbsPartIdx] && (pcCUQ->getCbf( uiPartQ, TEXT_LUMA, pcCUQ->getTransformIdx(uiPartQ)) != 0 || pcCUP->getCbf( uiPartP, TEXT_LUMA, pcCUP->getTransformIdx(uiPartP) ) != 0) )
464#endif
465    {
466      uiBs = 1;
467    }
468    else
469    {
470      if (iDir == EDGE_HOR)
471      {
472        pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, true, false, !m_bLFCrossTileBoundary);
473      }
474      if (pcSlice->isInterB())
475      {
476        Int iRefIdx;
477        Int *piRefP0, *piRefP1, *piRefQ0, *piRefQ1;
478        iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP);
479        piRefP0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
480        iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartP);
481        piRefP1 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx);
482        iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ);
483        piRefQ0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
484        iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartQ);
485        piRefQ1 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx);
486       
487       
488        TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP);
489        TComMv pcMvP1 = pcCUP->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartP);
490        TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ);
491        TComMv pcMvQ1 = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartQ);
492       
493        if ( ((piRefP0==piRefQ0)&&(piRefP1==piRefQ1)) || ((piRefP0==piRefQ1)&&(piRefP1==piRefQ0)) )
494        {
495          uiBs = 0;
496          if ( piRefP0 != piRefP1 )   // Different L0 & L1
497          {
498            if ( piRefP0 == piRefQ0 )
499            {
500              pcMvP0 -= pcMvQ0;   pcMvP1 -= pcMvQ1;
501              uiBs = (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
502              (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4);
503            }
504            else
505            {
506              pcMvP0 -= pcMvQ1;   pcMvP1 -= pcMvQ0;
507              uiBs = (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
508              (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4);
509            }
510          }
511          else    // Same L0 & L1
512          {
513            TComMv pcMvSub0 = pcMvP0 - pcMvQ0;
514            TComMv pcMvSub1 = pcMvP1 - pcMvQ1;
515            pcMvP0 -= pcMvQ1;   pcMvP1 -= pcMvQ0;
516            uiBs = ( (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
517                    (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4) ) &&
518            ( (pcMvSub0.getAbsHor() >= 4) | (pcMvSub0.getAbsVer() >= 4) |
519             (pcMvSub1.getAbsHor() >= 4) | (pcMvSub1.getAbsVer() >= 4) );
520          }
521        }
522        else // for all different Ref_Idx
523        {
524          uiBs = 1;
525        }
526      }
527      else  // pcSlice->isInterP()
528      {
529        Int iRefIdx;
530        Int *piRefP0, *piRefQ0;
531        iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP);
532        piRefP0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
533        iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ);
534        piRefQ0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
535        TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP);
536        TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ);
537       
538        pcMvP0 -= pcMvQ0;
539        uiBs = (piRefP0 != piRefQ0) | (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4);
540      }
541    }   // enf of "if( one of BCBP == 0 )"
542  }   // enf of "if( not Intra )"
543 
544  m_aapucBS[iDir][uiAbsPartIdx] = uiBs;
545}
546
547
548Void TComLoopFilter::xEdgeFilterLuma( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, Int iDir, Int iEdge  )
549{
550  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
551  Pel* piSrc    = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx );
552  Pel* piTmpSrc = piSrc;
553 
554  Int  iStride = pcPicYuvRec->getStride();
555  Int iQP = 0;
556  Int iQP_P = 0;
557  Int iQP_Q = 0;
558  UInt uiNumParts = pcCU->getPic()->getNumPartInWidth()>>uiDepth;
559 
560  UInt  uiPelsInPart = g_uiMaxCUWidth >> g_uiMaxCUDepth;
561#if !DBL_H0473_PART_1
562  UInt  PartIdxIncr = DEBLOCK_SMALLEST_BLOCK / uiPelsInPart ? DEBLOCK_SMALLEST_BLOCK / uiPelsInPart : 1;
563  UInt  uiBlocksInPart = uiPelsInPart / DEBLOCK_SMALLEST_BLOCK ? uiPelsInPart / DEBLOCK_SMALLEST_BLOCK : 1;
564#endif
565  UInt  uiBsAbsIdx = 0, uiBs = 0;
566  Int   iOffset, iSrcStep;
567 
568  Bool  bPCMFilter = (pcCU->getSlice()->getSPS()->getUsePCM() && pcCU->getSlice()->getSPS()->getPCMFilterDisableFlag())? true : false;
569  Bool  bPartPNoFilter = false;
570  Bool  bPartQNoFilter = false; 
571  UInt  uiPartPIdx = 0;
572  UInt  uiPartQIdx = 0;
573  TComDataCU* pcCUP = pcCU; 
574  TComDataCU* pcCUQ = pcCU;
575 
576  if (iDir == EDGE_VER)
577  {
578    iOffset = 1;
579    iSrcStep = iStride;
580    piTmpSrc += iEdge*uiPelsInPart;
581  }
582  else  // (iDir == EDGE_HOR)
583  {
584    iOffset = iStride;
585    iSrcStep = 1;
586    piTmpSrc += iEdge*uiPelsInPart*iStride;
587  }
588 
589#if !DBL_H0473_PART_1
590  for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx+=PartIdxIncr )
591  {
592    uiBs = 0;
593    for (UInt iIdxInside = 0; iIdxInside<PartIdxIncr; iIdxInside++)
594    {
595      uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, iDir, iEdge, iIdx+iIdxInside);
596      if (uiBs < m_aapucBS[iDir][uiBsAbsIdx])
597      {
598        uiBs = m_aapucBS[iDir][uiBsAbsIdx];
599      }
600    }
601   
602#else
603  for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx++ )
604  {
605    uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, iDir, iEdge, iIdx);
606    uiBs = m_aapucBS[iDir][uiBsAbsIdx];
607#endif
608    if ( uiBs )
609    {
610      iQP_Q = pcCU->getQP( uiBsAbsIdx );
611      uiPartQIdx = uiBsAbsIdx;
612      // Derive neighboring PU index
613      if (iDir == EDGE_VER)
614      {
615        pcCUP = pcCUQ->getPULeft (uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
616      }
617      else  // (iDir == EDGE_HOR)
618      {
619        pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, false, false, !m_bLFCrossTileBoundary);
620      }
621
622      iQP_P = pcCUP->getQP(uiPartPIdx);
623     
624      if(pcCU->getIPCMFlag(uiPartQIdx)) 
625      {
626        iQP_Q = 0; 
627      }
628      if(pcCUP->getIPCMFlag(uiPartPIdx)) 
629      {
630        iQP_P = 0; 
631      }
632     
633      iQP = (iQP_P + iQP_Q + 1) >> 1;
634      Int iBitdepthScale = (1<<(g_uiBitIncrement+g_uiBitDepth-8));
635     
636      Int iIndexTC = Clip3(0, MAX_QP+DEFAULT_INTRA_TC_OFFSET, Int(iQP + DEFAULT_INTRA_TC_OFFSET*(uiBs-1) + (m_tcOffsetDiv2 << 1)));
637      Int iIndexB = Clip3(0, MAX_QP, iQP + (m_betaOffsetDiv2 << 1));
638     
639      Int iTc =  tctable_8x8[iIndexTC]*iBitdepthScale;
640      Int iBeta = betatable_8x8[iIndexB]*iBitdepthScale;
641      Int iSideThreshold = (iBeta+(iBeta>>1))>>3;
642      Int iThrCut = iTc*10;
643     
644     
645#if !DBL_H0473_PART_1     
646      for (UInt iBlkIdx = 0; iBlkIdx< uiBlocksInPart; iBlkIdx ++)
647      {
648        Int dp0 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+0), iOffset);
649        Int dq0 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+0), iOffset);
650        Int dp3 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+3), iOffset);
651        Int dq3 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+3), iOffset);
652        Int d0 = dp0 + dq0;
653        Int d3 = dp3 + dq3;
654       
655        Int dp4 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+4), iOffset);
656        Int dq4 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+4), iOffset);
657        Int dp7 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+7), iOffset);
658        Int dq7 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+7), iOffset);
659        Int d4 = dp4 + dq4;
660        Int d7 = dp7 + dq7;
661#else
662        Int dp0 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+0), iOffset);
663        Int dq0 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+0), iOffset);
664        Int dp3 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+3), iOffset);
665        Int dq3 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+3), iOffset);
666        Int d0 = dp0 + dq0;
667        Int d3 = dp3 + dq3;
668
669        Int dp = dp0 + dp3;
670        Int dq = dq0 + dq3;
671        Int d =  d0 + d3;
672#endif
673       
674        if (bPCMFilter)
675        {
676          // Check if each of PUs is I_PCM
677          bPartPNoFilter = (pcCUP->getIPCMFlag(uiPartPIdx));
678          bPartQNoFilter = (pcCUQ->getIPCMFlag(uiPartQIdx));
679        }
680#if LOSSLESS_CODING
681        // check if each of PUs is lossless coded
682        bPartPNoFilter = bPartPNoFilter || (pcCU->isLosslessCoded(uiAbsZorderIdx) );
683        bPartQNoFilter = bPartQNoFilter || (pcCU->isLosslessCoded(uiAbsZorderIdx) );
684#endif
685#if !DBL_H0473_PART_1         
686        if (d0+d3 < iBeta)
687        {
688          Bool bFilterP = (dp0+dp3 < iSideThreshold);
689          Bool bFilterQ = (dq0+dq3 < iSideThreshold);
690         
691          Bool sw =  xUseStrongFiltering( iOffset, 2*d0, iBeta, iTc , piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+0))
692          && xUseStrongFiltering( iOffset, 2*d3, iBeta, iTc , piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+3));
693         
694#else
695        if (d < iBeta)
696        { 
697          Bool bFilterP = (dp < iSideThreshold);
698          Bool bFilterQ = (dq < iSideThreshold);
699
700          Bool sw =  xUseStrongFiltering( iOffset, 2*d0, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+0))
701                  && xUseStrongFiltering( iOffset, 2*d3, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+3));
702#endif
703
704          for ( Int i = 0; i < DEBLOCK_SMALLEST_BLOCK/2; i++)
705          {
706#if !DBL_H0473_PART_1         
707            xPelFilterLuma( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+i), iOffset, d0+d3, iBeta, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ);
708#else
709            xPelFilterLuma( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+i), iOffset, d, iBeta, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ);
710#endif
711
712          }
713        }
714#if !DBL_H0473_PART_1             
715        if (d4+d7 < iBeta)
716        {
717          Bool bFilterP = (dp4+dp7 < iSideThreshold);
718          Bool bFilterQ = (dq4+dq7 < iSideThreshold);
719         
720          Bool sw =  xUseStrongFiltering( iOffset, 2*d4, iBeta, iTc , piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+4))
721          && xUseStrongFiltering( iOffset, 2*d7, iBeta, iTc , piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+7));
722          for ( Int i = DEBLOCK_SMALLEST_BLOCK/2; i < DEBLOCK_SMALLEST_BLOCK; i++)
723          {
724            xPelFilterLuma( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*DEBLOCK_SMALLEST_BLOCK+i), iOffset, d4+d7, iBeta, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ);
725          }
726        }
727      }
728#endif
729    }
730  }
731}
732
733
734Void TComLoopFilter::xEdgeFilterChroma( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, Int iDir, Int iEdge )
735{
736  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
737  Int         iStride     = pcPicYuvRec->getCStride();
738  Pel*        piSrcCb     = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
739  Pel*        piSrcCr     = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
740  Int iQP = 0;
741  Int iQP_P = 0;
742  Int iQP_Q = 0;
743 
744  UInt  uiPelsInPartChroma = g_uiMaxCUWidth >> (g_uiMaxCUDepth+1);
745 
746  Int   iOffset, iSrcStep;
747 
748  const UInt uiLCUWidthInBaseUnits = pcCU->getPic()->getNumPartInWidth();
749 
750  Bool  bPCMFilter = (pcCU->getSlice()->getSPS()->getUsePCM() && pcCU->getSlice()->getSPS()->getPCMFilterDisableFlag())? true : false;
751  Bool  bPartPNoFilter = false;
752  Bool  bPartQNoFilter = false; 
753  UInt  uiPartPIdx;
754  UInt  uiPartQIdx;
755  TComDataCU* pcCUP; 
756  TComDataCU* pcCUQ = pcCU;
757 
758  // Vertical Position
759  UInt uiEdgeNumInLCUVert = g_auiZscanToRaster[uiAbsZorderIdx]%uiLCUWidthInBaseUnits + iEdge;
760  UInt uiEdgeNumInLCUHor = g_auiZscanToRaster[uiAbsZorderIdx]/uiLCUWidthInBaseUnits + iEdge;
761 
762  if ( ( (uiEdgeNumInLCUVert%(DEBLOCK_SMALLEST_BLOCK/uiPelsInPartChroma))&&(iDir==0) ) || ( (uiEdgeNumInLCUHor%(DEBLOCK_SMALLEST_BLOCK/uiPelsInPartChroma))&& iDir ) )
763  {
764    return;
765  }
766 
767  UInt  uiNumParts = pcCU->getPic()->getNumPartInWidth()>>uiDepth;
768 
769  UInt  uiBsAbsIdx;
770  UChar ucBs;
771 
772  Pel* piTmpSrcCb = piSrcCb;
773  Pel* piTmpSrcCr = piSrcCr;
774 
775 
776  if (iDir == EDGE_VER)
777  {
778    iOffset   = 1;
779    iSrcStep  = iStride;
780    piTmpSrcCb += iEdge*uiPelsInPartChroma;
781    piTmpSrcCr += iEdge*uiPelsInPartChroma;
782  }
783  else  // (iDir == EDGE_HOR)
784  {
785    iOffset   = iStride;
786    iSrcStep  = 1;
787    piTmpSrcCb += iEdge*iStride*uiPelsInPartChroma;
788    piTmpSrcCr += iEdge*iStride*uiPelsInPartChroma;
789  }
790 
791  for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx++ )
792  {
793    ucBs = 0;
794   
795    uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, iDir, iEdge, iIdx);
796    ucBs = m_aapucBS[iDir][uiBsAbsIdx];
797   
798    if ( ucBs > 1)
799    {
800      iQP_Q = pcCU->getQP( uiBsAbsIdx );
801      uiPartQIdx = uiBsAbsIdx;
802      // Derive neighboring PU index
803      if (iDir == EDGE_VER)
804      {
805        pcCUP = pcCUQ->getPULeft (uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
806      }
807      else  // (iDir == EDGE_HOR)
808      {
809        pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getSPS()->getLFCrossSliceBoundaryFlag(), false, false, false, !m_bLFCrossTileBoundary);
810      }
811
812      iQP_P = pcCUP->getQP(uiPartPIdx);
813     
814      if(pcCU->getIPCMFlag(uiPartQIdx)) 
815      {
816        iQP_Q = 0; 
817      }
818      if(pcCUP->getIPCMFlag(uiPartPIdx)) 
819      {
820        iQP_P = 0; 
821      }
822     
823      iQP = QpUV((iQP_P + iQP_Q + 1) >> 1);
824      Int iBitdepthScale = (1<<(g_uiBitIncrement+g_uiBitDepth-8));
825     
826      Int iIndexTC = Clip3(0, MAX_QP+DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET*(ucBs - 1) + (m_tcOffsetDiv2 << 1));
827      Int iTc =  tctable_8x8[iIndexTC]*iBitdepthScale;
828     
829      if(bPCMFilter)
830      {
831        // Check if each of PUs is IPCM
832        bPartPNoFilter = (pcCUP->getIPCMFlag(uiPartPIdx));
833        bPartQNoFilter = (pcCUQ->getIPCMFlag(uiPartQIdx));
834      }
835     
836#if LOSSLESS_CODING
837      // check if each of PUs is lossless coded
838      bPartPNoFilter = bPartPNoFilter || (pcCU->isLosslessCoded(uiAbsZorderIdx) );
839      bPartQNoFilter = bPartQNoFilter || (pcCU->isLosslessCoded(uiAbsZorderIdx) );
840#endif
841      for ( UInt uiStep = 0; uiStep < uiPelsInPartChroma; uiStep++ )
842      {
843        xPelFilterChroma( piTmpSrcCb + iSrcStep*(uiStep+iIdx*uiPelsInPartChroma), iOffset, iTc , bPartPNoFilter, bPartQNoFilter);
844        xPelFilterChroma( piTmpSrcCr + iSrcStep*(uiStep+iIdx*uiPelsInPartChroma), iOffset, iTc , bPartPNoFilter, bPartQNoFilter);
845      }
846    }
847  }
848}
849
850/**
851 - Deblocking for the luminance component with strong or weak filter
852 .
853 \param piSrc           pointer to picture data
854 \param iOffset         offset value for picture data
855 \param d               d value
856 \param beta            beta value
857 \param tc              tc value
858 \param sw              decision strong/weak filter
859 \param bPartPNoFilter  indicator to disable filtering on partP
860 \param bPartQNoFilter  indicator to disable filtering on partQ
861 \param iThrCut         threshold value for weak filter decision
862 \param bFilterSecondP  decision weak filter/no filter for partP
863 \param bFilterSecondQ  decision weak filter/no filter for partQ
864*/
865__inline Void TComLoopFilter::xPelFilterLuma( Pel* piSrc, Int iOffset, Int d, Int beta, Int tc , Bool sw, Bool bPartPNoFilter, Bool bPartQNoFilter, Int iThrCut, Bool bFilterSecondP, Bool bFilterSecondQ)
866{
867  Int delta;
868 
869  Pel m4  = piSrc[0];
870  Pel m3  = piSrc[-iOffset];
871  Pel m5  = piSrc[ iOffset];
872  Pel m2  = piSrc[-iOffset*2];
873  Pel m6  = piSrc[ iOffset*2];
874  Pel m1  = piSrc[-iOffset*3];
875  Pel m7  = piSrc[ iOffset*3];
876  Pel m0  = piSrc[-iOffset*4];
877
878  if (sw)
879  {
880#if DBL_STRONG_FILTER_CLIP
881    piSrc[-iOffset]   = Clip3(m3-2*tc, m3+2*tc, ((m1 + 2*m2 + 2*m3 + 2*m4 + m5 + 4) >> 3));
882    piSrc[0]          = Clip3(m4-2*tc, m4+2*tc, ((m2 + 2*m3 + 2*m4 + 2*m5 + m6 + 4) >> 3));
883    piSrc[-iOffset*2] = Clip3(m2-2*tc, m2+2*tc, ((m1 + m2 + m3 + m4 + 2)>>2));
884    piSrc[ iOffset]   = Clip3(m5-2*tc, m5+2*tc, ((m3 + m4 + m5 + m6 + 2)>>2));
885    piSrc[-iOffset*3] = Clip3(m1-2*tc, m1+2*tc, ((2*m0 + 3*m1 + m2 + m3 + m4 + 4 )>>3));
886    piSrc[ iOffset*2] = Clip3(m6-2*tc, m6+2*tc, ((m3 + m4 + m5 + 3*m6 + 2*m7 +4 )>>3));
887#else
888    piSrc[-iOffset] = ( m1 + 2*m2 + 2*m3 + 2*m4 + m5 + 4) >> 3;
889    piSrc[0] = ( m2 + 2*m3 + 2*m4 + 2*m5 + m6 + 4) >> 3;
890   
891    piSrc[-iOffset*2] = ( m1 + m2 + m3 + m4 + 2)>>2;
892    piSrc[ iOffset] = ( m3 + m4 + m5 + m6 + 2)>>2;
893   
894    piSrc[-iOffset*3] = ( 2*m0 + 3*m1 + m2 + m3 + m4 + 4 )>>3;
895    piSrc[ iOffset*2] = ( m3 + m4 + m5 + 3*m6 + 2*m7 +4 )>>3;
896#endif
897  }
898  else
899  {
900    /* Weak filter */
901    delta = (9*(m4-m3) -3*(m5-m2) + 8)>>4 ;
902
903    if ( abs(delta) < iThrCut )
904    {
905      delta = Clip3(-tc, tc, delta);       
906      piSrc[-iOffset] = Clip((m3+delta));
907      piSrc[0] = Clip((m4-delta));
908
909      Int tc2 = tc>>1;
910      if(bFilterSecondP)
911      {
912        Int delta1 = Clip3(-tc2, tc2, (( ((m1+m3+1)>>1)- m2+delta)>>1));
913        piSrc[-iOffset*2] = Clip((m2+delta1));
914      }
915      if(bFilterSecondQ)
916      {
917        Int delta2 = Clip3(-tc2, tc2, (( ((m6+m4+1)>>1)- m5-delta)>>1));
918        piSrc[ iOffset] = Clip((m5+delta2));
919      }
920    }
921  }
922
923  if(bPartPNoFilter)
924  {
925    piSrc[-iOffset] = m3;
926    piSrc[-iOffset*2] = m2;
927    piSrc[-iOffset*3] = m1;
928  }
929  if(bPartQNoFilter)
930  {
931    piSrc[0] = m4;
932    piSrc[ iOffset] = m5;
933    piSrc[ iOffset*2] = m6;
934  }
935}
936
937/**
938 - Deblocking of one line/column for the chrominance component
939 .
940 \param piSrc           pointer to picture data
941 \param iOffset         offset value for picture data
942 \param tc              tc value
943 \param bPartPNoFilter  indicator to disable filtering on partP
944 \param bPartQNoFilter  indicator to disable filtering on partQ
945 */
946__inline Void TComLoopFilter::xPelFilterChroma( Pel* piSrc, Int iOffset, Int tc, Bool bPartPNoFilter, Bool bPartQNoFilter)
947{
948  int delta;
949 
950  Pel m4  = piSrc[0];
951  Pel m3  = piSrc[-iOffset];
952  Pel m5  = piSrc[ iOffset];
953  Pel m2  = piSrc[-iOffset*2];
954 
955  delta = Clip3(-tc,tc, (((( m4 - m3 ) << 2 ) + m2 - m5 + 4 ) >> 3) );
956  piSrc[-iOffset] = Clip(m3+delta);
957  piSrc[0] = Clip(m4-delta);
958
959  if(bPartPNoFilter)
960  {
961    piSrc[-iOffset] = m3;
962  }
963  if(bPartQNoFilter)
964  {
965    piSrc[0] = m4;
966  }
967}
968
969/**
970 - Decision between strong and weak filter
971 .
972 \param offset         offset value for picture data
973 \param d               d value
974 \param beta            beta value
975 \param tc              tc value
976 \param piSrc           pointer to picture data
977 */
978__inline Bool TComLoopFilter::xUseStrongFiltering( Int offset, Int d, Int beta, Int tc, Pel* piSrc)
979{
980  Pel m4  = piSrc[0];
981  Pel m3  = piSrc[-offset];
982  Pel m7  = piSrc[ offset*3];
983  Pel m0  = piSrc[-offset*4];
984
985  Int d_strong = abs(m0-m3) + abs(m7-m4);
986
987  return ( (d_strong < (beta>>3)) && (d<(beta>>2)) && ( abs(m3-m4) < ((tc*5+1)>>1)) );
988}
989
990__inline Int TComLoopFilter::xCalcDP( Pel* piSrc, Int iOffset)
991{
992  return abs( piSrc[-iOffset*3] - 2*piSrc[-iOffset*2] + piSrc[-iOffset] ) ;
993}
994 
995__inline Int TComLoopFilter::xCalcDQ( Pel* piSrc, Int iOffset)
996{
997  return abs( piSrc[0] - 2*piSrc[iOffset] + piSrc[iOffset*2] );
998}
999//! \}
Note: See TracBrowser for help on using the repository browser.