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

Last change on this file since 1313 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

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