source: 3DVCSoftware/branches/HTM-6.0-Mediatek/source/Lib/TLibDecoder/TDecTop.cpp @ 369

Last change on this file since 369 was 303, checked in by mediatek-htm, 12 years ago

Added FCO_FIX, FCO_FIX_SPS_CHANGE, and FCO_DVP_REFINE_C0132_C0170 macros to support FCO.
The new macros are default disabled in CTC.

  • Property svn:eol-style set to native
File size: 49.6 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     TDecTop.cpp
35    \brief    decoder class
36*/
37
38#include "NALread.h"
39#include "../../App/TAppDecoder/TAppDecTop.h"
40#include "TDecTop.h"
41
42//! \ingroup TLibDecoder
43//! \{
44
45
46CamParsCollector::CamParsCollector()
47: m_bInitialized( false )
48{
49  m_aaiCodedOffset         = new Int* [ MAX_VIEW_NUM ];
50  m_aaiCodedScale          = new Int* [ MAX_VIEW_NUM ];
51  m_aiViewOrderIndex       = new Int  [ MAX_VIEW_NUM ];
52#if QC_MVHEVC_B0046
53  m_aiViewId               = new Int  [ MAX_VIEW_NUM ];
54#endif
55  m_aiViewReceived         = new Int  [ MAX_VIEW_NUM ];
56  for( UInt uiId = 0; uiId < MAX_VIEW_NUM; uiId++ )
57  {
58    m_aaiCodedOffset      [ uiId ] = new Int [ MAX_VIEW_NUM ];
59    m_aaiCodedScale       [ uiId ] = new Int [ MAX_VIEW_NUM ];
60  }
61
62#if MERL_VSP_C0152
63  xCreateLUTs( (UInt)MAX_VIEW_NUM, (UInt)MAX_VIEW_NUM, m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT );
64  m_iLog2Precision   = LOG2_DISP_PREC_LUT;
65  m_uiBitDepthForLUT = 8; // fixed
66#endif
67}
68
69CamParsCollector::~CamParsCollector()
70{
71  for( UInt uiId = 0; uiId < MAX_VIEW_NUM; uiId++ )
72  {
73    delete [] m_aaiCodedOffset      [ uiId ];
74    delete [] m_aaiCodedScale       [ uiId ];
75  }
76  delete [] m_aaiCodedOffset;
77  delete [] m_aaiCodedScale;
78  delete [] m_aiViewOrderIndex;
79  delete [] m_aiViewReceived;
80
81#if MERL_VSP_C0152
82  xDeleteArray( m_adBaseViewShiftLUT, MAX_VIEW_NUM, MAX_VIEW_NUM, 2 );
83  xDeleteArray( m_aiBaseViewShiftLUT, MAX_VIEW_NUM, MAX_VIEW_NUM, 2 );
84#endif
85}
86
87Void
88CamParsCollector::init( FILE* pCodedScaleOffsetFile )
89{
90  m_bInitialized            = true;
91  m_pCodedScaleOffsetFile   = pCodedScaleOffsetFile;
92  m_uiCamParsCodedPrecision = 0;
93  m_bCamParsVaryOverTime    = false;
94  m_iLastViewId             = -1;
95  m_iLastPOC                = -1;
96  m_uiMaxViewId             = 0;
97}
98
99#if MERL_VSP_C0152
100Void
101CamParsCollector::xCreateLUTs( UInt uiNumberSourceViews, UInt uiNumberTargetViews, Double****& radLUT, Int****& raiLUT)
102{
103  //AOF( m_uiBitDepthForLUT == 8 );
104  //AOF(radLUT == NULL && raiLUT == NULL );
105
106  uiNumberSourceViews = Max( 1, uiNumberSourceViews );
107  uiNumberTargetViews = Max( 1, uiNumberTargetViews );
108
109  radLUT         = new Double***[ uiNumberSourceViews ];
110  raiLUT         = new Int   ***[ uiNumberSourceViews ];
111
112  for( UInt uiSourceView = 0; uiSourceView < uiNumberSourceViews; uiSourceView++ )
113  {
114    radLUT        [ uiSourceView ] = new Double**[ uiNumberTargetViews ];
115    raiLUT        [ uiSourceView ] = new Int   **[ uiNumberTargetViews ];
116
117    for( UInt uiTargetView = 0; uiTargetView < uiNumberTargetViews; uiTargetView++ )
118    {
119      radLUT        [ uiSourceView ][ uiTargetView ]      = new Double*[ 2 ];
120      radLUT        [ uiSourceView ][ uiTargetView ][ 0 ] = new Double [ 257 ];
121      radLUT        [ uiSourceView ][ uiTargetView ][ 1 ] = new Double [ 257 ];
122
123      raiLUT        [ uiSourceView ][ uiTargetView ]      = new Int*   [ 2 ];
124      raiLUT        [ uiSourceView ][ uiTargetView ][ 0 ] = new Int    [ 257 ];
125      raiLUT        [ uiSourceView ][ uiTargetView ][ 1 ] = new Int    [ 257 ];
126    }
127  }
128}
129
130Void
131  CamParsCollector::xInitLUTs( UInt uiSourceView, UInt uiTargetView, Int iScale, Int iOffset, Double****& radLUT, Int****& raiLUT)
132{
133  Int     iLog2DivLuma   = m_uiBitDepthForLUT + m_uiCamParsCodedPrecision + 1 - m_iLog2Precision;   AOF( iLog2DivLuma > 0 );
134  Int     iLog2DivChroma = iLog2DivLuma + 1;
135
136  iOffset <<= m_uiBitDepthForLUT;
137
138  Double dScale  = (Double) iScale  / (( Double ) ( 1 << iLog2DivLuma ));
139  Double dOffset = (Double) iOffset / (( Double ) ( 1 << iLog2DivLuma ));
140
141  // offsets including rounding offsets
142  Int64 iOffsetLuma   = iOffset + ( ( 1 << iLog2DivLuma   ) >> 1 );
143  Int64 iOffsetChroma = iOffset + ( ( 1 << iLog2DivChroma ) >> 1 );
144
145
146  for( UInt uiDepthValue = 0; uiDepthValue < 256; uiDepthValue++ )
147  {
148
149    // real-valued look-up tables
150    Double  dShiftLuma      = ( (Double)uiDepthValue * dScale + dOffset ) * Double( 1 << m_iLog2Precision );
151    Double  dShiftChroma    = dShiftLuma / 2;
152    radLUT[ uiSourceView ][ uiTargetView ][ 0 ][ uiDepthValue ] = dShiftLuma;
153    radLUT[ uiSourceView ][ uiTargetView ][ 1 ][ uiDepthValue ] = dShiftChroma;
154
155    // integer-valued look-up tables
156    Int64   iTempScale      = (Int64)uiDepthValue * iScale;
157    Int64   iShiftLuma      = ( iTempScale + iOffsetLuma   ) >> iLog2DivLuma;
158    Int64   iShiftChroma    = ( iTempScale + iOffsetChroma ) >> iLog2DivChroma;
159    raiLUT[ uiSourceView ][ uiTargetView ][ 0 ][ uiDepthValue ] = (Int)iShiftLuma;
160    raiLUT[ uiSourceView ][ uiTargetView ][ 1 ][ uiDepthValue ] = (Int)iShiftChroma;
161
162    // maximum deviation
163    //dMaxDispDev     = Max( dMaxDispDev,    fabs( Double( (Int) iTestScale   ) - dShiftLuma * Double( 1 << iLog2DivLuma ) ) / Double( 1 << iLog2DivLuma ) );
164    //dMaxRndDispDvL  = Max( dMaxRndDispDvL, fabs( Double( (Int) iShiftLuma   ) - dShiftLuma   ) );
165    //dMaxRndDispDvC  = Max( dMaxRndDispDvC, fabs( Double( (Int) iShiftChroma ) - dShiftChroma ) );
166  }
167
168  radLUT[ uiSourceView ][ uiTargetView ][ 0 ][ 256 ] = radLUT[ uiSourceView ][ uiTargetView ][ 0 ][ 255 ];
169  radLUT[ uiSourceView ][ uiTargetView ][ 1 ][ 256 ] = radLUT[ uiSourceView ][ uiTargetView ][ 1 ][ 255 ];
170  raiLUT[ uiSourceView ][ uiTargetView ][ 0 ][ 256 ] = raiLUT[ uiSourceView ][ uiTargetView ][ 0 ][ 255 ];
171  raiLUT[ uiSourceView ][ uiTargetView ][ 1 ][ 256 ] = raiLUT[ uiSourceView ][ uiTargetView ][ 1 ][ 255 ];
172}
173#endif // end MERL_VSP_C0152
174
175Void
176CamParsCollector::uninit()
177{
178  m_bInitialized = false;
179}
180
181Void
182CamParsCollector::setSlice( TComSlice* pcSlice )
183{
184  if( pcSlice == 0 )
185  {
186    AOF( xIsComplete() );
187    if( m_bCamParsVaryOverTime || m_iLastPOC == 0 )
188    {
189      xOutput( m_iLastPOC );
190    }
191    return;
192  }
193
194  AOF( pcSlice->getSPS()->getViewId() < MAX_VIEW_NUM );
195#if !FCO_FIX  // Under flexible coding order, depth may need the camera parameters
196  if ( pcSlice->getSPS()->isDepth  () )
197  {
198    return;
199  }
200#endif
201  Bool  bFirstAU          = ( pcSlice->getPOC()               == 0 );
202  Bool  bFirstSliceInAU   = ( pcSlice->getPOC()               != Int ( m_iLastPOC ) );
203  Bool  bFirstSliceInView = ( pcSlice->getSPS()->getViewId()  != UInt( m_iLastViewId ) || bFirstSliceInAU );
204  AOT(  bFirstSliceInAU  &&   pcSlice->getSPS()->getViewId()  != 0 );
205#if FCO_FIX
206#else
207  AOT( !bFirstSliceInAU  &&   pcSlice->getSPS()->getViewId()   < UInt( m_iLastViewId ) );
208#endif
209  AOT( !bFirstSliceInAU  &&   pcSlice->getSPS()->getViewId()   > UInt( m_iLastViewId + 1 ) );
210  AOT( !bFirstAU         &&   pcSlice->getSPS()->getViewId()   > m_uiMaxViewId );
211  if ( !bFirstSliceInView )
212  {
213    if( m_bCamParsVaryOverTime ) // check consistency of slice parameters here
214    {
215      UInt uiViewId = pcSlice->getSPS()->getViewId();
216      for( UInt uiBaseId = 0; uiBaseId < uiViewId; uiBaseId++ )
217      {
218        AOF( m_aaiCodedScale [ uiBaseId ][ uiViewId ] == pcSlice->getCodedScale    () [ uiBaseId ] );
219        AOF( m_aaiCodedOffset[ uiBaseId ][ uiViewId ] == pcSlice->getCodedOffset   () [ uiBaseId ] );
220        AOF( m_aaiCodedScale [ uiViewId ][ uiBaseId ] == pcSlice->getInvCodedScale () [ uiBaseId ] );
221        AOF( m_aaiCodedOffset[ uiViewId ][ uiBaseId ] == pcSlice->getInvCodedOffset() [ uiBaseId ] );
222      }
223    }
224    return;
225  }
226
227  if( bFirstSliceInAU )
228  {
229    if( !bFirstAU )
230    {
231      AOF( xIsComplete() );
232      xOutput( m_iLastPOC );
233    }
234    ::memset( m_aiViewReceived, 0x00, MAX_VIEW_NUM * sizeof( Int ) );
235  }
236
237  UInt uiViewId                 = pcSlice->getSPS()->getViewId();
238  m_aiViewReceived[ uiViewId ]  = 1;
239  if( bFirstAU )
240  {
241    m_uiMaxViewId                     = Max( m_uiMaxViewId, uiViewId );
242    m_aiViewOrderIndex[ uiViewId ]    = pcSlice->getSPS()->getViewOrderIdx();
243    if( uiViewId == 1 )
244    {
245      m_uiCamParsCodedPrecision       = pcSlice->getSPS()->getCamParPrecision     ();
246      m_bCamParsVaryOverTime          = pcSlice->getSPS()->hasCamParInSliceHeader ();
247    }
248    else if( uiViewId > 1 )
249    {
250      AOF( m_uiCamParsCodedPrecision == pcSlice->getSPS()->getCamParPrecision     () );
251      AOF( m_bCamParsVaryOverTime    == pcSlice->getSPS()->hasCamParInSliceHeader () );
252    }
253    for( UInt uiBaseId = 0; uiBaseId < uiViewId; uiBaseId++ )
254    {
255      if( m_bCamParsVaryOverTime )
256      {
257        m_aaiCodedScale [ uiBaseId ][ uiViewId ]  = pcSlice->getCodedScale    () [ uiBaseId ];
258        m_aaiCodedOffset[ uiBaseId ][ uiViewId ]  = pcSlice->getCodedOffset   () [ uiBaseId ];
259        m_aaiCodedScale [ uiViewId ][ uiBaseId ]  = pcSlice->getInvCodedScale () [ uiBaseId ];
260        m_aaiCodedOffset[ uiViewId ][ uiBaseId ]  = pcSlice->getInvCodedOffset() [ uiBaseId ];
261#if MERL_VSP_C0152
262        xInitLUTs( uiBaseId, uiViewId, m_aaiCodedScale[ uiBaseId ][ uiViewId ], m_aaiCodedOffset[ uiBaseId ][ uiViewId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT);
263        xInitLUTs( uiViewId, uiBaseId, m_aaiCodedScale[ uiViewId ][ uiBaseId ], m_aaiCodedOffset[ uiViewId ][ uiBaseId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT);
264#endif
265      }
266      else
267      {
268        m_aaiCodedScale [ uiBaseId ][ uiViewId ]  = pcSlice->getSPS()->getCodedScale    () [ uiBaseId ];
269        m_aaiCodedOffset[ uiBaseId ][ uiViewId ]  = pcSlice->getSPS()->getCodedOffset   () [ uiBaseId ];
270        m_aaiCodedScale [ uiViewId ][ uiBaseId ]  = pcSlice->getSPS()->getInvCodedScale () [ uiBaseId ];
271        m_aaiCodedOffset[ uiViewId ][ uiBaseId ]  = pcSlice->getSPS()->getInvCodedOffset() [ uiBaseId ];
272#if MERL_VSP_C0152
273        xInitLUTs( uiBaseId, uiViewId, m_aaiCodedScale[ uiBaseId ][ uiViewId ], m_aaiCodedOffset[ uiBaseId ][ uiViewId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT );
274        xInitLUTs( uiViewId, uiBaseId, m_aaiCodedScale[ uiViewId ][ uiBaseId ], m_aaiCodedOffset[ uiViewId ][ uiBaseId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT );
275#endif
276      }
277    }
278  }
279  else
280  {
281    AOF( m_aiViewOrderIndex[ uiViewId ] == pcSlice->getSPS()->getViewOrderIdx() );
282    if( m_bCamParsVaryOverTime )
283    {
284      for( UInt uiBaseId = 0; uiBaseId < uiViewId; uiBaseId++ )
285      {
286        m_aaiCodedScale [ uiBaseId ][ uiViewId ]  = pcSlice->getCodedScale    () [ uiBaseId ];
287        m_aaiCodedOffset[ uiBaseId ][ uiViewId ]  = pcSlice->getCodedOffset   () [ uiBaseId ];
288        m_aaiCodedScale [ uiViewId ][ uiBaseId ]  = pcSlice->getInvCodedScale () [ uiBaseId ];
289        m_aaiCodedOffset[ uiViewId ][ uiBaseId ]  = pcSlice->getInvCodedOffset() [ uiBaseId ];
290#if MERL_VSP_C0152
291        xInitLUTs( uiBaseId, uiViewId, m_aaiCodedScale[ uiBaseId ][ uiViewId ], m_aaiCodedOffset[ uiBaseId ][ uiViewId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT );
292        xInitLUTs( uiViewId, uiBaseId, m_aaiCodedScale[ uiViewId ][ uiBaseId ], m_aaiCodedOffset[ uiViewId ][ uiBaseId ], m_adBaseViewShiftLUT, m_aiBaseViewShiftLUT );
293#endif
294      }
295    }
296  }
297  m_iLastViewId = (Int)pcSlice->getSPS()->getViewId();
298  m_iLastPOC    = (Int)pcSlice->getPOC();
299}
300
301Bool
302CamParsCollector::xIsComplete()
303{
304  for( UInt uiView = 0; uiView <= m_uiMaxViewId; uiView++ )
305  {
306    if( m_aiViewReceived[ uiView ] == 0 )
307    {
308      return false;
309    }
310  }
311  return true;
312}
313
314Void
315CamParsCollector::xOutput( Int iPOC )
316{
317  if( m_pCodedScaleOffsetFile )
318  {
319    if( iPOC == 0 )
320    {
321      fprintf( m_pCodedScaleOffsetFile, "#     ViewId ViewOrderIdx\n" );
322      fprintf( m_pCodedScaleOffsetFile, "#----------- ------------\n" );
323      for( UInt uiViewId = 0; uiViewId <= m_uiMaxViewId; uiViewId++ )
324      {
325        fprintf( m_pCodedScaleOffsetFile, "%12d %12d\n", uiViewId, m_aiViewOrderIndex[ uiViewId ] );
326      }
327      fprintf( m_pCodedScaleOffsetFile, "\n\n");
328      fprintf( m_pCodedScaleOffsetFile, "# StartFrame     EndFrame   TargetView     BaseView   CodedScale  CodedOffset    Precision\n" );
329      fprintf( m_pCodedScaleOffsetFile, "#----------- ------------ ------------ ------------ ------------ ------------ ------------\n" );
330    }
331    if( iPOC == 0 || m_bCamParsVaryOverTime )
332    {
333      Int iS = iPOC;
334      Int iE = ( m_bCamParsVaryOverTime ? iPOC : ~( 1 << 31 ) );
335      for( UInt uiViewId = 0; uiViewId <= m_uiMaxViewId; uiViewId++ )
336      {
337        for( UInt uiBaseId = 0; uiBaseId <= m_uiMaxViewId; uiBaseId++ )
338        {
339          if( uiViewId != uiBaseId )
340          {
341            fprintf( m_pCodedScaleOffsetFile, "%12d %12d %12d %12d %12d %12d %12d\n",
342              iS, iE, uiViewId, uiBaseId, m_aaiCodedScale[ uiBaseId ][ uiViewId ], m_aaiCodedOffset[ uiBaseId ][ uiViewId ], m_uiCamParsCodedPrecision );
343          }
344        }
345      }
346    }
347  }
348}
349
350TDecTop::TDecTop()
351: m_SEIs(0)
352, m_tAppDecTop( NULL )
353, m_nalUnitTypeBaseView( NAL_UNIT_INVALID )
354{
355  m_pcPic = 0;
356  m_iGopSize      = 0;
357  m_bGopSizeSet   = false;
358  m_iMaxRefPicNum = 0;
359  m_uiValidPS = 0;
360#if ENC_DEC_TRACE
361  if(!g_hTrace) g_hTrace = fopen( "TraceDec.txt", "wb" );
362  g_bJustDoIt = g_bEncDecTraceDisable;
363  g_nSymbolCounter = 0;
364#endif
365  m_bRefreshPending = 0;
366  m_pocCRA = 0;
367  m_pocRandomAccess = MAX_INT;         
368  m_prevPOC                = MAX_INT;
369  m_bFirstSliceInPicture    = true;
370  m_bFirstSliceInSequence   = true;
371  m_pcCamParsCollector = 0;
372#if QC_MVHEVC_B0046
373  m_bFirstNal                  = false;
374#endif
375}
376
377TDecTop::~TDecTop()
378{
379#if ENC_DEC_TRACE
380  if(g_hTrace) fclose( g_hTrace );
381  g_hTrace=NULL;
382#endif
383}
384
385Void TDecTop::create()
386{
387  m_cGopDecoder.create();
388  m_apcSlicePilot = new TComSlice;
389  m_uiSliceIdx = m_uiLastSliceIdx = 0;
390}
391
392Void TDecTop::destroy()
393{
394  m_cGopDecoder.destroy();
395 
396  delete m_apcSlicePilot;
397  m_apcSlicePilot = NULL;
398 
399  m_cSliceDecoder.destroy();
400  m_tAppDecTop = NULL;
401
402#if DEPTH_MAP_GENERATION
403  m_cDepthMapGenerator.destroy();
404#endif
405#if H3D_IVRP
406  m_cResidualGenerator.destroy();
407#endif
408
409}
410
411Void TDecTop::init( TAppDecTop* pcTAppDecTop, Bool bFirstInstance )
412{
413  // initialize ROM
414  if( bFirstInstance )
415  {
416  initROM();
417  }
418  m_cGopDecoder.init( &m_cEntropyDecoder, &m_cSbacDecoder, &m_cBinCABAC, &m_cCavlcDecoder, &m_cSliceDecoder, &m_cLoopFilter, &m_cAdaptiveLoopFilter, &m_cSAO
419#if DEPTH_MAP_GENERATION
420                    , &m_cDepthMapGenerator
421#endif
422#if H3D_IVRP
423                    , &m_cResidualGenerator
424#endif
425    );
426  m_cSliceDecoder.init( &m_cEntropyDecoder, &m_cCuDecoder );
427  m_cEntropyDecoder.init(&m_cPrediction);
428  m_tAppDecTop = pcTAppDecTop;
429#if DEPTH_MAP_GENERATION
430#if VIDYO_VPS_INTEGRATION
431  m_cDepthMapGenerator.init( &m_cPrediction, m_tAppDecTop->getVPSAccess(), m_tAppDecTop->getSPSAccess(), m_tAppDecTop->getAUPicAccess() );
432#else
433  m_cDepthMapGenerator.init( &m_cPrediction, m_tAppDecTop->getSPSAccess(), m_tAppDecTop->getAUPicAccess() );
434#endif
435#endif
436#if H3D_IVRP
437  m_cResidualGenerator.init( &m_cTrQuant, &m_cDepthMapGenerator );
438#endif
439}
440
441Void TDecTop::deletePicBuffer ( )
442{
443  TComList<TComPic*>::iterator  iterPic   = m_cListPic.begin();
444  Int iSize = Int( m_cListPic.size() );
445 
446  for (Int i = 0; i < iSize; i++ )
447  {
448    if( *iterPic )
449    {
450      TComPic* pcPic = *(iterPic++);
451      pcPic->destroy();
452   
453      delete pcPic;
454      pcPic = NULL;
455    }
456  }
457 
458  // destroy ALF temporary buffers
459  m_cAdaptiveLoopFilter.destroy();
460
461  m_cSAO.destroy();
462 
463  m_cLoopFilter.        destroy();
464 
465  // destroy ROM
466  if(m_viewId == 0 && m_isDepth == false)
467  {
468    destroyROM();
469  }
470}
471
472#if H3D_IVRP
473Void
474TDecTop::deleteExtraPicBuffers( Int iPoc )
475{
476  TComPic*                      pcPic = 0;
477  TComList<TComPic*>::iterator  cIter = m_cListPic.begin();
478  TComList<TComPic*>::iterator  cEnd  = m_cListPic.end  ();
479  for( ; cIter != cEnd; cIter++ )
480  {
481    if( (*cIter)->getPOC() == iPoc )
482    {
483      pcPic = *cIter;
484      break;
485    }
486  }
487  //AOF( pcPic );
488  if ( pcPic )
489  {
490    pcPic->removeResidualBuffer   ();
491  }
492}
493#endif
494
495
496Void
497TDecTop::compressMotion( Int iPoc )
498{
499  TComPic*                      pcPic = 0;
500  TComList<TComPic*>::iterator  cIter = m_cListPic.begin();
501  TComList<TComPic*>::iterator  cEnd  = m_cListPic.end  ();
502  for( ; cIter != cEnd; cIter++ )
503  {
504    if( (*cIter)->getPOC() == iPoc )
505    {
506      pcPic = *cIter;
507      break;
508    }
509  }
510//  AOF( pcPic );
511  if ( pcPic )
512  {
513    pcPic->compressMotion();
514  }
515}
516
517Void TDecTop::xUpdateGopSize (TComSlice* pcSlice)
518{
519  if ( !pcSlice->isIntra() && !m_bGopSizeSet)
520  {
521    m_iGopSize    = pcSlice->getPOC();
522    m_bGopSizeSet = true;
523   
524    m_cGopDecoder.setGopSize(m_iGopSize);
525  }
526}
527
528Void TDecTop::xGetNewPicBuffer ( TComSlice* pcSlice, TComPic*& rpcPic )
529{
530  xUpdateGopSize(pcSlice);
531 
532  m_iMaxRefPicNum = pcSlice->getSPS()->getMaxDecPicBuffering(pcSlice->getTLayer())+pcSlice->getSPS()->getNumReorderPics(pcSlice->getTLayer()) + 1; // +1 to have space for the picture currently being decoded
533
534#if DEPTH_MAP_GENERATION
535  UInt uiPdm                  = ( pcSlice->getSPS()->getViewId() ? pcSlice->getSPS()->getPredDepthMapGeneration() : m_tAppDecTop->getSPSAccess()->getPdm() );
536  Bool bNeedPrdDepthMapBuffer = ( !pcSlice->getSPS()->isDepth() && uiPdm > 0 );
537#endif
538
539  if (m_cListPic.size() < (UInt)m_iMaxRefPicNum)
540  {
541    rpcPic = new TComPic();
542   
543    rpcPic->create ( pcSlice->getSPS()->getPicWidthInLumaSamples(), pcSlice->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, true);
544   
545#if DEPTH_MAP_GENERATION
546    if( bNeedPrdDepthMapBuffer )
547    {
548      rpcPic->addPrdDepthMapBuffer( PDM_SUB_SAMP_EXP_X(uiPdm), PDM_SUB_SAMP_EXP_Y(uiPdm) );
549    }
550#endif
551   
552    m_cListPic.pushBack( rpcPic );
553   
554    return;
555  }
556 
557  Bool bBufferIsAvailable = false;
558  TComList<TComPic*>::iterator  iterPic   = m_cListPic.begin();
559  while (iterPic != m_cListPic.end())
560  {
561    rpcPic = *(iterPic++);
562    if ( rpcPic->getReconMark() == false && rpcPic->getOutputMark() == false)
563    {
564      rpcPic->setOutputMark(false);
565      bBufferIsAvailable = true;
566      break;
567    }
568
569    if ( rpcPic->getSlice( 0 )->isReferenced() == false  && rpcPic->getOutputMark() == false)
570    {
571      rpcPic->setOutputMark(false);
572      rpcPic->setReconMark( false );
573      rpcPic->getPicYuvRec()->setBorderExtension( false );
574      bBufferIsAvailable = true;
575      break;
576    }
577  }
578 
579  if ( !bBufferIsAvailable )
580  {
581    //There is no room for this picture, either because of faulty encoder or dropped NAL. Extend the buffer.
582    m_iMaxRefPicNum++;
583    rpcPic = new TComPic();
584    m_cListPic.pushBack( rpcPic );
585  }
586  rpcPic->destroy(); 
587  rpcPic->create ( pcSlice->getSPS()->getPicWidthInLumaSamples(), pcSlice->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, true);
588#if DEPTH_MAP_GENERATION
589  if( bNeedPrdDepthMapBuffer && !rpcPic->getPredDepthMap() )
590  {
591    rpcPic->addPrdDepthMapBuffer( PDM_SUB_SAMP_EXP_X(uiPdm), PDM_SUB_SAMP_EXP_Y(uiPdm) );
592  }
593#endif
594}
595
596Void TDecTop::executeDeblockAndAlf(UInt& ruiPOC, TComList<TComPic*>*& rpcListPic, Int& iSkipFrame, Int& iPOCLastDisplay)
597{
598  if (!m_pcPic)
599  {
600    /* nothing to deblock */
601    return;
602  }
603 
604  TComPic*&   pcPic         = m_pcPic;
605
606  // Execute Deblock and ALF only + Cleanup
607
608  m_cGopDecoder.decompressGop(NULL, pcPic, true);
609
610  TComSlice::sortPicList( m_cListPic ); // sorting for application output
611  ruiPOC              = pcPic->getSlice(m_uiSliceIdx-1)->getPOC();
612  rpcListPic          = &m_cListPic; 
613  m_cCuDecoder.destroy();       
614  m_bFirstSliceInPicture  = true;
615
616  return;
617}
618
619Void TDecTop::xCreateLostPicture(Int iLostPoc) 
620{
621  printf("\ninserting lost poc : %d\n",iLostPoc);
622  TComSlice cFillSlice;
623  cFillSlice.setSPS( m_parameterSetManagerDecoder.getFirstSPS() );
624  cFillSlice.setPPS( m_parameterSetManagerDecoder.getFirstPPS() );
625  cFillSlice.initSlice();
626  cFillSlice.initTiles();
627  TComPic *cFillPic;
628  xGetNewPicBuffer(&cFillSlice,cFillPic);
629  cFillPic->getSlice(0)->setSPS( m_parameterSetManagerDecoder.getFirstSPS() );
630  cFillPic->getSlice(0)->setPPS( m_parameterSetManagerDecoder.getFirstPPS() );
631  cFillPic->getSlice(0)->initSlice();
632  cFillPic->getSlice(0)->initTiles();
633
634 
635 
636  TComList<TComPic*>::iterator iterPic = m_cListPic.begin();
637  Int closestPoc = 1000000;
638  while ( iterPic != m_cListPic.end())
639  {
640    TComPic * rpcPic = *(iterPic++);
641    if(abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc)<closestPoc&&abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc)!=0&&rpcPic->getPicSym()->getSlice(0)->getPOC()!=m_apcSlicePilot->getPOC())
642    {
643      closestPoc=abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc);
644    }
645  }
646  iterPic = m_cListPic.begin();
647  while ( iterPic != m_cListPic.end())
648  {
649    TComPic *rpcPic = *(iterPic++);
650    if(abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc)==closestPoc&&rpcPic->getPicSym()->getSlice(0)->getPOC()!=m_apcSlicePilot->getPOC())
651    {
652      printf("copying picture %d to %d (%d)\n",rpcPic->getPicSym()->getSlice(0)->getPOC() ,iLostPoc,m_apcSlicePilot->getPOC());
653      rpcPic->getPicYuvRec()->copyToPic(cFillPic->getPicYuvRec());
654      break;
655    }
656  }
657  cFillPic->setCurrSliceIdx(0);
658  for(Int i=0; i<cFillPic->getNumCUsInFrame(); i++) 
659  {
660    cFillPic->getCU(i)->initCU(cFillPic,i);
661  }
662  cFillPic->getSlice(0)->setReferenced(true);
663  cFillPic->getSlice(0)->setPOC(iLostPoc);
664  cFillPic->setReconMark(true);
665  cFillPic->setOutputMark(true);
666  if(m_pocRandomAccess == MAX_INT)
667  {
668    m_pocRandomAccess = iLostPoc;
669  }
670}
671
672
673Void TDecTop::xActivateParameterSets()
674{
675  m_parameterSetManagerDecoder.applyPrefetchedPS();
676
677  TComPPS *pps = m_parameterSetManagerDecoder.getPPS(m_apcSlicePilot->getPPSId());
678  assert (pps != 0);
679
680  TComSPS *sps = m_parameterSetManagerDecoder.getSPS(pps->getSPSId());
681  assert (sps != 0);
682#if VIDYO_VPS_INTEGRATION
683  TComVPS *vps = m_parameterSetManagerDecoder.getVPS(sps->getVPSId());
684  assert (vps != 0);
685#if !QC_REM_IDV_B0046
686  if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )
687#else
688  if( (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) && !sps->getViewId() )
689#endif
690    // VPS can only be activated on IDR or CRA...
691    getTAppDecTop()->getVPSAccess()->setActiveVPSId( sps->getVPSId() );
692#endif
693  m_apcSlicePilot->setPPS(pps);
694  m_apcSlicePilot->setSPS(sps);
695#if QC_MVHEVC_B0046
696  TComVPS *vps = m_parameterSetManagerDecoder.getVPS(sps->getVPSId());
697#endif
698#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
699  m_apcSlicePilot->setVPS(vps);
700#endif
701  pps->setSPS(sps);
702
703  if(sps->getUseSAO() || sps->getUseALF()|| sps->getScalingListFlag() || sps->getUseDF())
704  {
705    m_apcSlicePilot->setAPS( m_parameterSetManagerDecoder.getAPS(m_apcSlicePilot->getAPSId())  );
706  }
707  pps->setMinCuDQPSize( sps->getMaxCUWidth() >> ( pps->getMaxCuDQPDepth()) );
708
709  for (Int i = 0; i < sps->getMaxCUDepth() - 1; i++)
710  {
711    sps->setAMPAcc( i, sps->getUseAMP() );
712  }
713
714  for (Int i = sps->getMaxCUDepth() - 1; i < sps->getMaxCUDepth(); i++)
715  {
716    sps->setAMPAcc( i, 0 );
717  }
718
719  m_cSAO.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
720  m_cLoopFilter.        create( g_uiMaxCUDepth );
721}
722
723Bool TDecTop::xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay )
724{
725  TComPic*&   pcPic         = m_pcPic;
726  m_apcSlicePilot->initSlice();
727
728  //!!!KS: DIRTY HACK
729  m_apcSlicePilot->setPPSId(0);
730  m_apcSlicePilot->setPPS(m_parameterSetManagerDecoder.getPrefetchedPPS(0));
731  m_apcSlicePilot->setSPS(m_parameterSetManagerDecoder.getPrefetchedSPS(0));
732#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
733#if QC_MVHEVC_B0046
734  m_apcSlicePilot->setIsDepth(false);
735#endif
736  m_apcSlicePilot->setVPS(m_parameterSetManagerDecoder.getPrefetchedVPS(0));
737#endif
738  m_apcSlicePilot->initTiles();
739#if QC_MVHEVC_B0046
740  m_apcSlicePilot->setViewId( nalu.m_layerId );
741  m_apcSlicePilot->setViewId( nalu.m_layerId );
742  m_apcSlicePilot->setViewOrderIdx(m_apcSlicePilot->getVPS()->getViewId(nalu.m_layerId), nalu.m_layerId);
743  Int iNumDirectRef = m_apcSlicePilot->getVPS()->getNumDirectRefLayer(nalu.m_layerId);
744  m_apcSlicePilot->getSPS()->setNumberOfUsableInterViewRefs(iNumDirectRef);
745  for(Int iNumIvRef = 0; iNumIvRef < iNumDirectRef; iNumIvRef ++)
746  {
747    Int iDeltaLayerId = m_apcSlicePilot->getVPS()->getDirectRefLayerId( nalu.m_layerId, iNumIvRef);
748    m_apcSlicePilot->getSPS()->setUsableInterViewRef(iNumIvRef, (iDeltaLayerId-nalu.m_layerId));
749  }
750#endif
751  if (m_bFirstSliceInPicture)
752  {
753    m_uiSliceIdx     = 0;
754    m_uiLastSliceIdx = 0;
755  }
756  m_apcSlicePilot->setSliceIdx(m_uiSliceIdx);
757  if (!m_bFirstSliceInPicture)
758  {
759    m_apcSlicePilot->copySliceInfo( pcPic->getPicSym()->getSlice(m_uiSliceIdx-1) );
760  }
761
762  m_apcSlicePilot->setNalUnitType(nalu.m_nalUnitType);
763  if( m_bFirstSliceInPicture )
764  {
765#if QC_MVHEVC_B0046
766    if( nalu.m_layerId == 0 ) { m_nalUnitTypeBaseView = nalu.m_nalUnitType; }
767    else                     { m_nalUnitTypeBaseView = m_tAppDecTop->getTDecTop( 0, 0 )->getNalUnitTypeBaseView(); }
768#else
769#if VIDYO_VPS_INTEGRATION
770    if( m_apcSlicePilot->getVPS()->getViewId(nalu.m_layerId) == 0 ) { m_nalUnitTypeBaseView = nalu.m_nalUnitType; }
771    else { m_nalUnitTypeBaseView = m_tAppDecTop->getTDecTop( 0, m_apcSlicePilot->getVPS()->getDepthFlag(nalu.m_layerId) )->getNalUnitTypeBaseView(); }
772#else
773    if( nalu.m_viewId == 0 ) { m_nalUnitTypeBaseView = nalu.m_nalUnitType; }
774    else                     { m_nalUnitTypeBaseView = m_tAppDecTop->getTDecTop( 0, nalu.m_isDepth )->getNalUnitTypeBaseView(); }
775#endif
776#endif
777    m_apcSlicePilot->setNalUnitTypeBaseViewMvc( m_nalUnitTypeBaseView );
778  }
779
780  m_apcSlicePilot->setReferenced(nalu.m_nalRefFlag);
781  m_apcSlicePilot->setTLayerInfo(nalu.m_temporalId);
782
783  // ALF CU parameters should be part of the slice header -> needs to be fixed
784#if MTK_DEPTH_MERGE_TEXTURE_CANDIDATE_C0137
785  m_cEntropyDecoder.decodeSliceHeader (m_apcSlicePilot, &m_parameterSetManagerDecoder, m_cGopDecoder.getAlfCuCtrlParam(), m_cGopDecoder.getAlfParamSet(),m_apcSlicePilot->getVPS()->getDepthFlag(nalu.m_layerId));
786#else
787  m_cEntropyDecoder.decodeSliceHeader (m_apcSlicePilot, &m_parameterSetManagerDecoder, m_cGopDecoder.getAlfCuCtrlParam(), m_cGopDecoder.getAlfParamSet());
788#endif
789  // byte align
790  {
791    Int numBitsForByteAlignment = nalu.m_Bitstream->getNumBitsUntilByteAligned();
792    if ( numBitsForByteAlignment > 0 )
793    {
794      UInt bitsForByteAlignment;
795      nalu.m_Bitstream->read( numBitsForByteAlignment, bitsForByteAlignment );
796      assert( bitsForByteAlignment == ( ( 1 << numBitsForByteAlignment ) - 1 ) );
797    }
798  }
799
800  // exit when a new picture is found
801  if (m_apcSlicePilot->isNextSlice() && m_apcSlicePilot->getPOC()!=m_prevPOC && !m_bFirstSliceInSequence)
802  {
803    if (m_prevPOC >= m_pocRandomAccess)
804    {
805      m_prevPOC = m_apcSlicePilot->getPOC();
806      return true;
807    }
808    m_prevPOC = m_apcSlicePilot->getPOC();
809  }
810  // actual decoding starts here
811  xActivateParameterSets();
812  m_apcSlicePilot->initTiles();
813
814  if (m_apcSlicePilot->isNextSlice()) 
815  {
816    m_prevPOC = m_apcSlicePilot->getPOC();
817  }
818  m_bFirstSliceInSequence = false;
819  if (m_apcSlicePilot->isNextSlice())
820  {
821    // Skip pictures due to random access
822    if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay))
823    {
824      return false;
825    }
826  }
827  //detect lost reference picture and insert copy of earlier frame.
828  while(m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPS(), true, m_pocRandomAccess) > 0)
829  {
830    xCreateLostPicture(m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPS(), false)-1);
831  }
832  if (m_bFirstSliceInPicture)
833  {
834    // Buffer initialize for prediction.
835    m_cPrediction.initTempBuff();
836    m_apcSlicePilot->applyReferencePictureSet(m_cListPic, m_apcSlicePilot->getRPS());
837    //  Get a new picture buffer
838    xGetNewPicBuffer (m_apcSlicePilot, pcPic);
839
840#if INTER_VIEW_VECTOR_SCALING_C0115
841    pcPic->setViewOrderIdx( m_apcSlicePilot->getVPS()->getViewOrderIdx(nalu.m_layerId) );    // will be changed to view_id
842#endif
843    /* transfer any SEI messages that have been received to the picture */
844    pcPic->setSEIs(m_SEIs);
845    m_SEIs = NULL;
846
847    // Recursive structure
848    m_cCuDecoder.create ( g_uiMaxCUDepth, g_uiMaxCUWidth, g_uiMaxCUHeight );
849    m_cCuDecoder.init   ( &m_cEntropyDecoder, &m_cTrQuant, &m_cPrediction );
850    m_cTrQuant.init     ( g_uiMaxCUWidth, g_uiMaxCUHeight, m_apcSlicePilot->getSPS()->getMaxTrSize());
851
852    m_cSliceDecoder.create( m_apcSlicePilot, m_apcSlicePilot->getSPS()->getPicWidthInLumaSamples(), m_apcSlicePilot->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
853#if DEPTH_MAP_GENERATION
854    UInt uiPdm = ( m_apcSlicePilot->getSPS()->getViewId() ? m_apcSlicePilot->getSPS()->getPredDepthMapGeneration() : m_tAppDecTop->getSPSAccess()->getPdm() );
855    m_cDepthMapGenerator.create( true, m_apcSlicePilot->getSPS()->getPicWidthInLumaSamples(), m_apcSlicePilot->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUDepth, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiBitDepth + g_uiBitIncrement, PDM_SUB_SAMP_EXP_X(uiPdm), PDM_SUB_SAMP_EXP_Y(uiPdm) );
856    TComDepthMapGenerator* pcDMG0 = m_tAppDecTop->getDecTop0()->getDepthMapGenerator();
857    if( m_apcSlicePilot->getSPS()->getViewId() == 1 && ( pcDMG0->getSubSampExpX() != PDM_SUB_SAMP_EXP_X(uiPdm) || pcDMG0->getSubSampExpY() != PDM_SUB_SAMP_EXP_Y(uiPdm) ) )
858    {
859      pcDMG0->create( true, m_apcSlicePilot->getSPS()->getPicWidthInLumaSamples(), m_apcSlicePilot->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUDepth, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiBitDepth + g_uiBitIncrement, PDM_SUB_SAMP_EXP_X(uiPdm), PDM_SUB_SAMP_EXP_Y(uiPdm) );
860    }
861#endif
862#if H3D_IVRP
863    m_cResidualGenerator.create( true, m_apcSlicePilot->getSPS()->getPicWidthInLumaSamples(), m_apcSlicePilot->getSPS()->getPicHeightInLumaSamples(), g_uiMaxCUDepth, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiBitDepth + g_uiBitIncrement );
864#endif
865  }
866
867  //  Set picture slice pointer
868  TComSlice*  pcSlice = m_apcSlicePilot;
869  Bool bNextSlice     = pcSlice->isNextSlice();
870
871  UInt uiCummulativeTileWidth;
872  UInt uiCummulativeTileHeight;
873  UInt i, j, p;
874
875
876  if( pcSlice->getPPS()->getColumnRowInfoPresent() == 1 )
877  {
878    //set NumColumnsMins1 and NumRowsMinus1
879    pcPic->getPicSym()->setNumColumnsMinus1( pcSlice->getPPS()->getNumColumnsMinus1() );
880    pcPic->getPicSym()->setNumRowsMinus1( pcSlice->getPPS()->getNumRowsMinus1() );
881
882    //create the TComTileArray
883    pcPic->getPicSym()->xCreateTComTileArray();
884
885    if( pcSlice->getPPS()->getUniformSpacingIdr() == 1)
886    {
887      //set the width for each tile
888      for(j=0; j < pcPic->getPicSym()->getNumRowsMinus1()+1; j++)
889      {
890        for(p=0; p < pcPic->getPicSym()->getNumColumnsMinus1()+1; p++)
891        {
892          pcPic->getPicSym()->getTComTile( j * (pcPic->getPicSym()->getNumColumnsMinus1()+1) + p )->
893            setTileWidth( (p+1)*pcPic->getPicSym()->getFrameWidthInCU()/(pcPic->getPicSym()->getNumColumnsMinus1()+1) 
894            - (p*pcPic->getPicSym()->getFrameWidthInCU())/(pcPic->getPicSym()->getNumColumnsMinus1()+1) );
895        }
896      }
897
898      //set the height for each tile
899      for(j=0; j < pcPic->getPicSym()->getNumColumnsMinus1()+1; j++)
900      {
901        for(p=0; p < pcPic->getPicSym()->getNumRowsMinus1()+1; p++)
902        {
903          pcPic->getPicSym()->getTComTile( p * (pcPic->getPicSym()->getNumColumnsMinus1()+1) + j )->
904            setTileHeight( (p+1)*pcPic->getPicSym()->getFrameHeightInCU()/(pcPic->getPicSym()->getNumRowsMinus1()+1) 
905            - (p*pcPic->getPicSym()->getFrameHeightInCU())/(pcPic->getPicSym()->getNumRowsMinus1()+1) );   
906        }
907      }
908    }
909    else
910    {
911      //set the width for each tile
912      for(j=0; j < pcSlice->getPPS()->getNumRowsMinus1()+1; j++)
913      {
914        uiCummulativeTileWidth = 0;
915        for(i=0; i < pcSlice->getPPS()->getNumColumnsMinus1(); i++)
916        {
917          pcPic->getPicSym()->getTComTile(j * (pcSlice->getPPS()->getNumColumnsMinus1()+1) + i)->setTileWidth( pcSlice->getPPS()->getColumnWidth(i) );
918          uiCummulativeTileWidth += pcSlice->getPPS()->getColumnWidth(i);
919        }
920        pcPic->getPicSym()->getTComTile(j * (pcSlice->getPPS()->getNumColumnsMinus1()+1) + i)->setTileWidth( pcPic->getPicSym()->getFrameWidthInCU()-uiCummulativeTileWidth );
921      }
922
923      //set the height for each tile
924      for(j=0; j < pcSlice->getPPS()->getNumColumnsMinus1()+1; j++)
925      {
926        uiCummulativeTileHeight = 0;
927        for(i=0; i < pcSlice->getPPS()->getNumRowsMinus1(); i++)
928        { 
929          pcPic->getPicSym()->getTComTile(i * (pcSlice->getPPS()->getNumColumnsMinus1()+1) + j)->setTileHeight( pcSlice->getPPS()->getRowHeight(i) );
930          uiCummulativeTileHeight += pcSlice->getPPS()->getRowHeight(i);
931        }
932        pcPic->getPicSym()->getTComTile(i * (pcSlice->getPPS()->getNumColumnsMinus1()+1) + j)->setTileHeight( pcPic->getPicSym()->getFrameHeightInCU()-uiCummulativeTileHeight );
933      }
934    }
935  }
936  else
937  {
938    //set NumColumnsMins1 and NumRowsMinus1
939    pcPic->getPicSym()->setNumColumnsMinus1( pcSlice->getSPS()->getNumColumnsMinus1() );
940    pcPic->getPicSym()->setNumRowsMinus1( pcSlice->getSPS()->getNumRowsMinus1() );
941
942    //create the TComTileArray
943    pcPic->getPicSym()->xCreateTComTileArray();
944
945    //automatically set the column and row boundary if UniformSpacingIdr = 1
946    if( pcSlice->getSPS()->getUniformSpacingIdr() == 1 )
947    {
948      //set the width for each tile
949      for(j=0; j < pcPic->getPicSym()->getNumRowsMinus1()+1; j++)
950      {
951        for(p=0; p < pcPic->getPicSym()->getNumColumnsMinus1()+1; p++)
952        {
953          pcPic->getPicSym()->getTComTile( j * (pcPic->getPicSym()->getNumColumnsMinus1()+1) + p )->
954            setTileWidth( (p+1)*pcPic->getPicSym()->getFrameWidthInCU()/(pcPic->getPicSym()->getNumColumnsMinus1()+1) 
955            - (p*pcPic->getPicSym()->getFrameWidthInCU())/(pcPic->getPicSym()->getNumColumnsMinus1()+1) );
956        }
957      }
958
959      //set the height for each tile
960      for(j=0; j < pcPic->getPicSym()->getNumColumnsMinus1()+1; j++)
961      {
962        for(p=0; p < pcPic->getPicSym()->getNumRowsMinus1()+1; p++)
963        {
964          pcPic->getPicSym()->getTComTile( p * (pcPic->getPicSym()->getNumColumnsMinus1()+1) + j )->
965            setTileHeight( (p+1)*pcPic->getPicSym()->getFrameHeightInCU()/(pcPic->getPicSym()->getNumRowsMinus1()+1) 
966            - (p*pcPic->getPicSym()->getFrameHeightInCU())/(pcPic->getPicSym()->getNumRowsMinus1()+1) );   
967        }
968      }
969    }
970    else
971    {
972      //set the width for each tile
973      for(j=0; j < pcSlice->getSPS()->getNumRowsMinus1()+1; j++)
974      {
975        uiCummulativeTileWidth = 0;
976        for(i=0; i < pcSlice->getSPS()->getNumColumnsMinus1(); i++)
977        {
978          pcPic->getPicSym()->getTComTile(j * (pcSlice->getSPS()->getNumColumnsMinus1()+1) + i)->setTileWidth( pcSlice->getSPS()->getColumnWidth(i) );
979          uiCummulativeTileWidth += pcSlice->getSPS()->getColumnWidth(i);
980        }
981        pcPic->getPicSym()->getTComTile(j * (pcSlice->getSPS()->getNumColumnsMinus1()+1) + i)->setTileWidth( pcPic->getPicSym()->getFrameWidthInCU()-uiCummulativeTileWidth );
982      }
983
984      //set the height for each tile
985      for(j=0; j < pcSlice->getSPS()->getNumColumnsMinus1()+1; j++)
986      {
987        uiCummulativeTileHeight = 0;
988        for(i=0; i < pcSlice->getSPS()->getNumRowsMinus1(); i++)
989        { 
990          pcPic->getPicSym()->getTComTile(i * (pcSlice->getSPS()->getNumColumnsMinus1()+1) + j)->setTileHeight( pcSlice->getSPS()->getRowHeight(i) );
991          uiCummulativeTileHeight += pcSlice->getSPS()->getRowHeight(i);
992        }
993        pcPic->getPicSym()->getTComTile(i * (pcSlice->getSPS()->getNumColumnsMinus1()+1) + j)->setTileHeight( pcPic->getPicSym()->getFrameHeightInCU()-uiCummulativeTileHeight );
994      }
995    }
996  }
997
998  pcPic->getPicSym()->xInitTiles();
999
1000  //generate the Coding Order Map and Inverse Coding Order Map
1001  UInt uiEncCUAddr;
1002  for(i=0, uiEncCUAddr=0; i<pcPic->getPicSym()->getNumberOfCUsInFrame(); i++, uiEncCUAddr = pcPic->getPicSym()->xCalculateNxtCUAddr(uiEncCUAddr))
1003  {
1004    pcPic->getPicSym()->setCUOrderMap(i, uiEncCUAddr);
1005    pcPic->getPicSym()->setInverseCUOrderMap(uiEncCUAddr, i);
1006  }
1007  pcPic->getPicSym()->setCUOrderMap(pcPic->getPicSym()->getNumberOfCUsInFrame(), pcPic->getPicSym()->getNumberOfCUsInFrame());
1008  pcPic->getPicSym()->setInverseCUOrderMap(pcPic->getPicSym()->getNumberOfCUsInFrame(), pcPic->getPicSym()->getNumberOfCUsInFrame());
1009
1010  //convert the start and end CU addresses of the slice and entropy slice into encoding order
1011  pcSlice->setEntropySliceCurStartCUAddr( pcPic->getPicSym()->getPicSCUEncOrder(pcSlice->getEntropySliceCurStartCUAddr()) );
1012  pcSlice->setEntropySliceCurEndCUAddr( pcPic->getPicSym()->getPicSCUEncOrder(pcSlice->getEntropySliceCurEndCUAddr()) );
1013  if(pcSlice->isNextSlice())
1014  {
1015    pcSlice->setSliceCurStartCUAddr(pcPic->getPicSym()->getPicSCUEncOrder(pcSlice->getSliceCurStartCUAddr()));
1016    pcSlice->setSliceCurEndCUAddr(pcPic->getPicSym()->getPicSCUEncOrder(pcSlice->getSliceCurEndCUAddr()));
1017  }
1018
1019  if (m_bFirstSliceInPicture) 
1020  {
1021    if(pcPic->getNumAllocatedSlice() != 1)
1022    {
1023      pcPic->clearSliceBuffer();
1024    }
1025  }
1026  else
1027  {
1028    pcPic->allocateNewSlice();
1029  }
1030  assert(pcPic->getNumAllocatedSlice() == (m_uiSliceIdx + 1));
1031  m_apcSlicePilot = pcPic->getPicSym()->getSlice(m_uiSliceIdx); 
1032  pcPic->getPicSym()->setSlice(pcSlice, m_uiSliceIdx);
1033
1034  pcPic->setTLayer(nalu.m_temporalId);
1035
1036  if (bNextSlice)
1037  {
1038    pcSlice->checkCRA(pcSlice->getRPS(), m_pocCRA, m_cListPic); 
1039
1040    if ( !pcSlice->getPPS()->getEnableTMVPFlag() && pcPic->getTLayer() == 0 )
1041    {
1042      pcSlice->decodingMarkingForNoTMVP( m_cListPic, pcSlice->getPOC() );
1043    }
1044
1045    // Set reference list
1046#if !QC_MVHEVC_B0046
1047#if VIDYO_VPS_INTEGRATION
1048    pcSlice->setViewId( pcSlice->getVPS()->getViewId(nalu.m_layerId) );
1049    pcSlice->setIsDepth( pcSlice->getVPS()->getDepthFlag(nalu.m_layerId) );
1050#else
1051    pcSlice->setViewId(m_viewId);
1052    pcSlice->setIsDepth(m_isDepth);
1053#endif
1054#endif
1055
1056#if INTER_VIEW_VECTOR_SCALING_C0115
1057#if VIDYO_VPS_INTEGRATION
1058    pcSlice->setViewOrderIdx( pcSlice->getVPS()->getViewOrderIdx(nalu.m_layerId) );        // will be changed to view_id
1059#else
1060    pcSlice->setViewOrderIdx( pcPic->getViewOrderIdx() );
1061#endif
1062#endif
1063
1064#if INTER_VIEW_VECTOR_SCALING_C0115
1065    pcSlice->setIVScalingFlag( pcSlice->getVPS()->getIVScalingFlag());
1066#endif
1067
1068    assert( m_tAppDecTop != NULL );
1069    TComPic * const pcTexturePic = m_isDepth ? m_tAppDecTop->getPicFromView(  m_viewId, pcSlice->getPOC(), false ) : NULL;
1070
1071#if FLEX_CODING_ORDER_M23723
1072    if (pcTexturePic != NULL)
1073    {
1074      assert( !m_isDepth || pcTexturePic != NULL );
1075      pcSlice->setTexturePic( pcTexturePic );
1076    }
1077#else
1078    assert( !m_isDepth || pcTexturePic != NULL );
1079    pcSlice->setTexturePic( pcTexturePic );
1080#endif
1081
1082
1083    std::vector<TComPic*> apcInterViewRefPics = m_tAppDecTop->getInterViewRefPics( m_viewId, pcSlice->getPOC(), m_isDepth, pcSlice->getSPS() );
1084    pcSlice->setRefPicListMvc( m_cListPic, apcInterViewRefPics );
1085
1086    // For generalized B
1087    // note: maybe not existed case (always L0 is copied to L1 if L1 is empty)
1088    if (pcSlice->isInterB() && pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0)
1089    {
1090      Int iNumRefIdx = pcSlice->getNumRefIdx(REF_PIC_LIST_0);
1091      pcSlice->setNumRefIdx        ( REF_PIC_LIST_1, iNumRefIdx );
1092
1093      for (Int iRefIdx = 0; iRefIdx < iNumRefIdx; iRefIdx++)
1094      {
1095        pcSlice->setRefPic(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx), REF_PIC_LIST_1, iRefIdx);
1096      }
1097    }
1098    if (pcSlice->isInterB())
1099    {
1100      Bool bLowDelay = true;
1101      Int  iCurrPOC  = pcSlice->getPOC();
1102      Int iRefIdx = 0;
1103
1104      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)
1105      {
1106        if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
1107        {
1108          bLowDelay = false;
1109        }
1110      }
1111      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
1112      {
1113        if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
1114        {
1115          bLowDelay = false;
1116        }
1117      }
1118
1119      pcSlice->setCheckLDC(bLowDelay);           
1120    }
1121
1122    //---------------
1123    pcSlice->setRefPOCnViewListsMvc();
1124
1125    if(!pcSlice->getRefPicListModificationFlagLC())
1126    {
1127      pcSlice->generateCombinedList();
1128    }
1129
1130    if( pcSlice->getRefPicListCombinationFlag() && pcSlice->getPPS()->getWPBiPredIdc()==1 && pcSlice->getSliceType()==B_SLICE )
1131    {
1132      pcSlice->setWpParamforLC();
1133    }
1134    pcSlice->setNoBackPredFlag( false );
1135    if ( pcSlice->getSliceType() == B_SLICE && !pcSlice->getRefPicListCombinationFlag())
1136    {
1137      if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
1138      {
1139        pcSlice->setNoBackPredFlag( true );
1140        for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )
1141        {
1142          if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ) 
1143          {
1144            pcSlice->setNoBackPredFlag( false );
1145            break;
1146          }
1147        }
1148      }
1149    }
1150  }
1151
1152  pcPic->setCurrSliceIdx(m_uiSliceIdx);
1153  if(pcSlice->getSPS()->getScalingListFlag())
1154  {
1155    if(pcSlice->getAPS()->getScalingListEnabled())
1156    {
1157      pcSlice->setScalingList ( pcSlice->getAPS()->getScalingList()  );
1158      if(pcSlice->getScalingList()->getScalingListPresentFlag())
1159      {
1160        pcSlice->setDefaultScalingList();
1161      }
1162      m_cTrQuant.setScalingListDec(pcSlice->getScalingList());
1163    }
1164    m_cTrQuant.setUseScalingList(true);
1165  }
1166  else
1167  {
1168    m_cTrQuant.setFlatScalingList();
1169    m_cTrQuant.setUseScalingList(false);
1170  }
1171
1172#if HHI_DMM_WEDGE_INTRA || HHI_DMM_PRED_TEX
1173  if( m_parameterSetManagerDecoder.getPrefetchedSPS(0)->getUseDMM() && g_aacWedgeLists.empty() )
1174  {
1175    initWedgeLists();
1176  }
1177#endif
1178
1179#if FCO_DVP_REFINE_C0132_C0170
1180  if(m_bFirstSliceInPicture)
1181  {
1182    pcPic->setDepthCoded(false);
1183
1184    if(m_viewId != 0)
1185    {
1186      if( m_isDepth == 0)
1187      {
1188        TComPic * recDepthMapBuffer;
1189        recDepthMapBuffer = m_tAppDecTop->getPicFromView( m_viewId, pcSlice->getPOC(), true );
1190        pcPic->setRecDepthMap(recDepthMapBuffer);
1191
1192        if(recDepthMapBuffer != NULL)
1193        {
1194          pcPic->setDepthCoded(true);
1195        }
1196      }
1197    }
1198  }
1199#endif
1200
1201
1202#if MERL_VSP_C0152 // set BW LUT
1203  if( m_pcCamParsCollector ) // Initialize the LUT elements
1204  {
1205    m_pcCamParsCollector->setSlice( pcSlice );
1206  }
1207  if( pcSlice->getViewId() !=0 )
1208  {
1209    TComPic* pcBaseTxtPic = m_tAppDecTop->getPicFromView(  0, pcSlice->getPOC(), false );  // get base view reconstructed texture
1210    TComPic* pcBaseDepthPic = m_tAppDecTop->getPicFromView(  0, pcSlice->getPOC(), true ); // get base view reconstructed depth
1211     pcSlice->setRefPicBaseTxt(pcBaseTxtPic);
1212     pcSlice->setRefPicBaseDepth(pcBaseDepthPic);
1213  }
1214  getTAppDecTop()->setBWVSPLUT( pcSlice, pcSlice->getViewId(),  pcSlice->getPOC() ); // get the LUT for backward warping
1215#endif
1216
1217  //  Decode a picture
1218  m_cGopDecoder.decompressGop(nalu.m_Bitstream, pcPic, false);
1219
1220#if QC_IV_AS_LT_B0046
1221  std::vector<TComPic*> apcInterViewRefPics = m_tAppDecTop->getInterViewRefPics( m_viewId, pcSlice->getPOC(), m_isDepth, pcSlice->getSPS() );
1222  for( Int k = 0; k < apcInterViewRefPics.size(); k++ )
1223  {
1224    TComPic*  pcPicIv = apcInterViewRefPics[k];
1225    pcPicIv->setIsLongTerm( 0 );
1226  }
1227#endif
1228  if( m_pcCamParsCollector )
1229  {
1230    m_pcCamParsCollector->setSlice( pcSlice );
1231  }
1232
1233  m_bFirstSliceInPicture = false;
1234  m_uiSliceIdx++;
1235
1236  return false;
1237}
1238
1239#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
1240Void TDecTop::xDecodeVPS()
1241{
1242  TComVPS* vps = new TComVPS();
1243 
1244  m_cEntropyDecoder.decodeVPS( vps );
1245  m_parameterSetManagerDecoder.storePrefetchedVPS(vps); 
1246#if !QC_MVHEVC_B0046
1247  getTAppDecTop()->getVPSAccess()->addVPS( vps );
1248#endif
1249}
1250#endif
1251
1252Void TDecTop::xDecodeSPS()
1253{
1254  TComSPS* sps = new TComSPS();
1255  TComRPSList* rps = new TComRPSList();
1256  sps->setRPSList(rps);
1257#if HHI_MPI || OL_QTLIMIT_PREDCODING_B0068
1258  m_cEntropyDecoder.decodeSPS( sps, m_isDepth );
1259#else
1260  m_cEntropyDecoder.decodeSPS( sps );
1261#endif
1262  m_parameterSetManagerDecoder.storePrefetchedSPS(sps);
1263  m_cAdaptiveLoopFilter.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
1264}
1265
1266Void TDecTop::xDecodePPS()
1267{
1268  TComPPS* pps = new TComPPS();
1269  m_cEntropyDecoder.decodePPS( pps, &m_parameterSetManagerDecoder );
1270  m_parameterSetManagerDecoder.storePrefetchedPPS( pps );
1271
1272  //!!!KS: Activate parameter sets for parsing APS (unless dependency is resolved)
1273  m_apcSlicePilot->setPPSId(pps->getPPSId());
1274  xActivateParameterSets();
1275  m_apcSlicePilot->initTiles();
1276}
1277
1278Void TDecTop::xDecodeAPS()
1279{
1280  TComAPS  *aps = new TComAPS();
1281  allocAPS (aps);
1282  decodeAPS(aps);
1283  m_parameterSetManagerDecoder.storePrefetchedAPS(aps);
1284}
1285
1286Void TDecTop::xDecodeSEI()
1287{
1288  m_SEIs = new SEImessages;
1289  m_cEntropyDecoder.decodeSEI(*m_SEIs);
1290}
1291
1292Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay)
1293{
1294  // Initialize entropy decoder
1295  m_cEntropyDecoder.setEntropyDecoder (&m_cCavlcDecoder);
1296  m_cEntropyDecoder.setBitstream      (nalu.m_Bitstream);
1297
1298  switch (nalu.m_nalUnitType)
1299  {
1300#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
1301    case NAL_UNIT_VPS:
1302      xDecodeVPS();
1303      return false;
1304#endif
1305    case NAL_UNIT_SPS:
1306      xDecodeSPS();
1307      return false;
1308
1309    case NAL_UNIT_PPS:
1310      xDecodePPS();
1311      return false;
1312    case NAL_UNIT_APS:
1313      xDecodeAPS();
1314      return false;
1315
1316    case NAL_UNIT_SEI:
1317      xDecodeSEI();
1318      return false;
1319
1320    case NAL_UNIT_CODED_SLICE:
1321    case NAL_UNIT_CODED_SLICE_IDR:
1322#if !QC_REM_IDV_B0046
1323    case NAL_UNIT_CODED_SLICE_IDV:
1324#endif
1325    case NAL_UNIT_CODED_SLICE_CRA:
1326    case NAL_UNIT_CODED_SLICE_TLA:
1327      return xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay);
1328      break;
1329    default:
1330      assert (1);
1331  }
1332
1333  return false;
1334}
1335
1336#if QC_MVHEVC_B0046
1337Void TDecTop::xCopyVPS( TComVPS* pVPSV0 )
1338{
1339  m_parameterSetManagerDecoder.storePrefetchedVPS(pVPSV0); 
1340}
1341
1342Void TDecTop::xCopySPS( TComSPS* pSPSV0 )
1343{
1344  TComSPS* sps = new TComSPS();
1345  sps = pSPSV0;
1346  m_parameterSetManagerDecoder.storePrefetchedSPS(sps);
1347  m_cAdaptiveLoopFilter.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
1348}
1349
1350Void TDecTop::xCopyPPS(TComPPS* pPPSV0 )
1351{
1352  m_parameterSetManagerDecoder.storePrefetchedPPS( pPPSV0 );
1353
1354  //!!!KS: Activate parameter sets for parsing APS (unless dependency is resolved)
1355  m_apcSlicePilot->setPPSId(pPPSV0->getPPSId());
1356  xActivateParameterSets();
1357  m_apcSlicePilot->initTiles();
1358}
1359#endif
1360/** Function for checking if picture should be skipped because of random access
1361 * \param iSkipFrame skip frame counter
1362 * \param iPOCLastDisplay POC of last picture displayed
1363 * \returns true if the picture shold be skipped in the random access.
1364 * This function checks the skipping of pictures in the case of -s option random access.
1365 * All pictures prior to the random access point indicated by the counter iSkipFrame are skipped.
1366 * It also checks the type of Nal unit type at the random access point.
1367 * If the random access point is CRA, pictures with POC equal to or greater than the CRA POC are decoded.
1368 * If the random access point is IDR all pictures after the random access point are decoded.
1369 * If the random access point is not IDR or CRA, a warning is issues, and decoding of pictures with POC
1370 * equal to or greater than the random access point POC is attempted. For non IDR/CRA random
1371 * access point there is no guarantee that the decoder will not crash.
1372 */
1373Bool TDecTop::isRandomAccessSkipPicture(Int& iSkipFrame,  Int& iPOCLastDisplay)
1374{
1375  if (iSkipFrame) 
1376  {
1377    iSkipFrame--;   // decrement the counter
1378    return true;
1379  }
1380  else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet.
1381  {
1382    if( m_apcSlicePilot->getNalUnitTypeBaseViewMvc() == NAL_UNIT_CODED_SLICE_CRA )
1383    {
1384      m_pocRandomAccess = m_apcSlicePilot->getPOC(); // set the POC random access since we need to skip the reordered pictures in CRA.
1385    }
1386    else if( m_apcSlicePilot->getNalUnitTypeBaseViewMvc() == NAL_UNIT_CODED_SLICE_IDR )
1387    {
1388      m_pocRandomAccess = 0; // no need to skip the reordered pictures in IDR, they are decodable.
1389    }
1390    else 
1391    {
1392      static bool warningMessage = false;
1393      if(!warningMessage)
1394      {
1395        printf("\nWarning: this is not a valid random access point and the data is discarded until the first CRA picture");
1396        warningMessage = true;
1397      }
1398      return true;
1399    }
1400  }
1401  else if (m_apcSlicePilot->getPOC() < m_pocRandomAccess)  // skip the reordered pictures if necessary
1402  {
1403    iPOCLastDisplay++;
1404    return true;
1405  }
1406  // if we reach here, then the picture is not skipped.
1407  return false; 
1408}
1409
1410Void TDecTop::allocAPS (TComAPS* pAPS)
1411{
1412  // we don't know the SPS before it has been activated. These fields could exist
1413  // depending on the corresponding flags in the APS, but SAO/ALF allocation functions will
1414  // have to be moved for that
1415  pAPS->createScalingList();
1416  pAPS->createSaoParam();
1417  m_cSAO.allocSaoParam(pAPS->getSaoParam());
1418  pAPS->createAlfParam();
1419}
1420
1421//! \}
Note: See TracBrowser for help on using the repository browser.