source: 3DVCSoftware/tags/HTM-DEV-0.1/source/Lib/TLibCommon/TComLoopFilter.cpp @ 324

Last change on this file since 324 was 324, checked in by tech, 11 years ago

Initial development version for update to latest HM version.
Includes MV-HEVC and basic extensions for 3D-HEVC.

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