source: SHVCSoftware/branches/SHM-dev/source/App/TAppDecoder/TAppDecTop.cpp @ 1222

Last change on this file since 1222 was 1221, checked in by seregin, 10 years ago

macro cleanup: FIX_ALIGN_BUMPING

  • Property svn:eol-style set to native
File size: 70.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-2014, 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     TAppDecTop.cpp
35    \brief    Decoder application class
36*/
37
38#include <list>
39#include <vector>
40#include <stdio.h>
41#include <fcntl.h>
42#include <assert.h>
43
44#include "TAppDecTop.h"
45#include "TLibDecoder/AnnexBread.h"
46#include "TLibDecoder/NALread.h"
47#if RExt__DECODER_DEBUG_BIT_STATISTICS
48#include "TLibCommon/TComCodingStatistics.h"
49#endif
50#if CONFORMANCE_BITSTREAM_MODE
51#include "TLibCommon/TComPicYuv.h"
52#include "libmd5/MD5.h"
53#endif
54
55//! \ingroup TAppDecoder
56//! \{
57
58#if Q0074_COLOUR_REMAPPING_SEI
59static Void applyColourRemapping(TComPicYuv& pic, const SEIColourRemappingInfo* colourRemappingInfoSEI, UInt layerId=0 );
60static std::vector<SEIColourRemappingInfo> storeCriSEI; //Persistent Colour Remapping Information SEI
61static SEIColourRemappingInfo *seiColourRemappingInfoPrevious=NULL ;
62#endif
63
64// ====================================================================================================================
65// Constructor / destructor / initialization / destroy
66// ====================================================================================================================
67
68#if SVC_EXTENSION
69TAppDecTop::TAppDecTop()
70{
71  for(UInt layer=0; layer < MAX_LAYERS; layer++)
72  {
73    m_aiPOCLastDisplay[layer]  = -MAX_INT;
74    m_apcTDecTop[layer] = &m_acTDecTop[layer];
75  }
76}
77#else
78TAppDecTop::TAppDecTop()
79: m_iPOCLastDisplay(-MAX_INT)
80{
81}
82#endif
83
84Void TAppDecTop::create()
85{
86}
87
88Void TAppDecTop::destroy()
89{
90  if (m_pchBitstreamFile)
91  {
92    free (m_pchBitstreamFile);
93    m_pchBitstreamFile = NULL;
94  }
95#if SVC_EXTENSION
96#if CONFORMANCE_BITSTREAM_MODE
97  for(Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
98#else
99  for( Int i = 0; i <= m_tgtLayerId; i++ )
100#endif
101  {
102    if( m_pchReconFile[i] )
103    {
104      free ( m_pchReconFile[i] );
105      m_pchReconFile[i] = NULL;
106    }
107  }
108#if AVC_BASE
109  if( m_pchBLReconFile )
110  {
111    free ( m_pchBLReconFile );
112    m_pchBLReconFile = NULL;
113  }
114#endif
115#else
116  if (m_pchReconFile)
117  {
118    free (m_pchReconFile);
119    m_pchReconFile = NULL;
120  }
121#endif
122#if Q0074_COLOUR_REMAPPING_SEI
123  if (seiColourRemappingInfoPrevious != NULL)
124  {
125    delete seiColourRemappingInfoPrevious;
126  }
127#endif
128}
129
130// ====================================================================================================================
131// Public member functions
132// ====================================================================================================================
133
134/**
135 - create internal class
136 - initialize internal class
137 - until the end of the bitstream, call decoding function in TDecTop class
138 - delete allocated buffers
139 - destroy internal class
140 .
141 */
142#if SVC_EXTENSION
143Void TAppDecTop::decode()
144{
145  Int                poc;
146  TComList<TComPic*>* pcListPic = NULL;
147
148  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
149  if (!bitstreamFile)
150  {
151    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
152    exit(EXIT_FAILURE);
153  }
154
155  InputByteStream bytestream(bitstreamFile);
156
157  if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-")
158  {
159    m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out);
160    if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good())
161    {
162      fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str());
163      exit(EXIT_FAILURE);
164    }
165  }
166
167  // create & initialize internal classes
168  xCreateDecLib();
169  xInitDecLib  (); 
170
171  // main decoder loop
172  Bool openedReconFile[MAX_LAYERS]; // reconstruction file not yet opened. (must be performed after SPS is seen)
173  Bool loopFiltered[MAX_LAYERS];
174  memset( loopFiltered, false, sizeof( loopFiltered ) );
175
176#if CONFORMANCE_BITSTREAM_MODE
177  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
178#else
179  for(UInt layer=0; layer<=m_tgtLayerId; layer++)
180#endif
181  {
182    openedReconFile[layer] = false;
183    m_aiPOCLastDisplay[layer] += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
184  }
185
186  UInt curLayerId = 0;     // current layer to be reconstructed
187
188#if AVC_BASE
189  TComPic pcBLPic;
190  fstream streamYUV;
191  if( m_pchBLReconFile )
192  {
193    streamYUV.open( m_pchBLReconFile, fstream::in | fstream::binary );
194  }
195  TComList<TComPic*> *cListPic = m_acTDecTop[0].getListPic();
196  m_acTDecTop[0].setBLReconFile( &streamYUV );
197  pcBLPic.setLayerId( 0 );
198  cListPic->pushBack( &pcBLPic );
199#endif
200
201  while (!!bitstreamFile)
202  {
203    /* location serves to work around a design fault in the decoder, whereby
204     * the process of reading a new slice that is the first slice of a new frame
205     * requires the TDecTop::decode() method to be called again with the same
206     * nal unit. */
207#if RExt__DECODER_DEBUG_BIT_STATISTICS
208    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
209    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
210#else
211    streampos location = bitstreamFile.tellg();
212#endif
213    AnnexBStats stats = AnnexBStats();
214
215    vector<uint8_t> nalUnit;
216    InputNALUnit nalu;
217    byteStreamNALUnit(bytestream, nalUnit, stats);
218
219    // call actual decoding function
220    Bool bNewPicture = false;
221    Bool bNewPOC = false;
222
223    if (nalUnit.empty())
224    {
225      /* this can happen if the following occur:
226       *  - empty input file
227       *  - two back-to-back start_code_prefixes
228       *  - start_code_prefix immediately followed by EOF
229       */
230      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
231    }
232    else
233    {
234      read(nalu, nalUnit);
235      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  ||
236#if CONFORMANCE_BITSTREAM_MODE
237        (nalu.m_layerId > m_commonDecoderParams.getTargetLayerId()) )
238#else
239        (nalu.m_layerId > m_tgtLayerId) )
240#endif
241      {
242        bNewPicture = false;
243      }
244      else
245      {
246        bNewPicture = m_acTDecTop[nalu.m_layerId].decode(nalu, m_iSkipFrame, m_aiPOCLastDisplay[nalu.m_layerId], curLayerId, bNewPOC);
247
248#if SVC_POC
249        if( (bNewPicture && m_acTDecTop[nalu.m_layerId].getParseIdc() == 3) || (m_acTDecTop[nalu.m_layerId].getParseIdc() == 0) )
250#else
251        if (bNewPicture)
252#endif
253        {
254          bitstreamFile.clear();
255          /* location points to the current nalunit payload[1] due to the
256           * need for the annexB parser to read three extra bytes.
257           * [1] except for the first NAL unit in the file
258           *     (but bNewPicture doesn't happen then) */
259#if RExt__DECODER_DEBUG_BIT_STATISTICS
260          bitstreamFile.seekg(location);
261          bytestream.reset();
262          TComCodingStatistics::SetStatistics(backupStats);
263#else
264          bitstreamFile.seekg(location-streamoff(3));
265          bytestream.reset();
266#endif
267        }
268#if SVC_POC
269        else if(m_acTDecTop[nalu.m_layerId].getParseIdc() == 1) 
270        {
271          bitstreamFile.clear();
272          // This is before third parse of the NAL unit, and
273          // location points to correct beginning of the NALU
274          bitstreamFile.seekg(location);
275          bytestream.reset();
276#if RExt__DECODER_DEBUG_BIT_STATISTICS
277          TComCodingStatistics::SetStatistics(backupStats);
278#endif
279        }
280#endif
281      }
282    }
283
284#if SVC_POC
285    if( ( (bNewPicture && m_acTDecTop[nalu.m_layerId].getParseIdc() == 3) || m_acTDecTop[nalu.m_layerId].getParseIdc() == 0 || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && 
286        !m_acTDecTop[nalu.m_layerId].getFirstSliceInSequence() )
287#else
288    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
289        !m_acTDecTop[nalu.m_layerId].getFirstSliceInSequence() )
290#endif
291    {
292      // Set bitdepth for each layer when doing DBF
293      g_bitDepth[CHANNEL_TYPE_LUMA]   = g_bitDepthLayer[CHANNEL_TYPE_LUMA][curLayerId];
294      g_bitDepth[CHANNEL_TYPE_CHROMA] = g_bitDepthLayer[CHANNEL_TYPE_CHROMA][curLayerId];
295
296      if (!loopFiltered[curLayerId] || bitstreamFile)
297      {
298        m_acTDecTop[curLayerId].executeLoopFilters(poc, pcListPic);
299      }
300      loopFiltered[curLayerId] = (nalu.m_nalUnitType == NAL_UNIT_EOS);
301
302      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
303      {
304        m_acTDecTop[nalu.m_layerId].setFirstSliceInSequence(true);
305      }
306    }
307    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
308              m_acTDecTop[nalu.m_layerId].getFirstSliceInSequence () ) 
309    {
310      m_acTDecTop[nalu.m_layerId].setFirstSliceInPicture (true);
311    }
312
313#if SVC_POC
314    if( bNewPicture && m_acTDecTop[nalu.m_layerId].getParseIdc() == 0 )
315    {
316      outputAllPictures( nalu.m_layerId, true );
317    }
318#endif
319
320    if( pcListPic )
321    {
322      if ( m_pchReconFile[curLayerId] && !openedReconFile[curLayerId] )
323      {
324        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
325        {
326          if (m_outputBitDepth[channelType] == 0) m_outputBitDepth[channelType] = g_bitDepth[channelType];
327        }
328        m_acTVideoIOYuvReconFile[curLayerId].open( m_pchReconFile[curLayerId], true, m_outputBitDepth, m_outputBitDepth, g_bitDepth ); // write mode
329
330        openedReconFile[curLayerId] = true;
331      }
332#if ALIGNED_BUMPING
333      Bool outputPicturesFlag = true; 
334
335      if( m_acTDecTop[nalu.m_layerId].getNoOutputPriorPicsFlag() )
336      {
337        outputPicturesFlag = false;
338      }
339
340      if (nalu.m_nalUnitType == NAL_UNIT_EOS) // End of sequence
341      {
342        flushAllPictures( nalu.m_layerId, outputPicturesFlag );       
343      }
344
345#if SVC_POC
346      if( bNewPicture && m_acTDecTop[nalu.m_layerId].getParseIdc() != 0 )
347      // New picture, slice header parsed but picture not decoded
348#else
349      if( bNewPicture ) // New picture, slice header parsed but picture not decoded
350#endif
351      {
352         if(   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
353            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
354            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
355            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
356            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP   )
357        {
358          flushAllPictures( nalu.m_layerId, outputPicturesFlag );
359        }
360        else
361        {
362          this->checkOutputBeforeDecoding( nalu.m_layerId );
363        }
364      }
365
366      /* The following code has to be executed when the last DU of the picture is decoded
367         TODO: Need code to identify end of decoding a picture
368      {
369        this->checkOutputAfterDecoding( );
370      } */
371#else
372      if ( bNewPicture && bNewPOC &&
373           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
374            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
375            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
376            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
377            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
378      {
379        xFlushOutput( pcListPic, curLayerId );
380      }
381      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
382      {
383        xFlushOutput( pcListPic, curLayerId );       
384      }
385      // write reconstruction to file
386      if(bNewPicture)
387      {
388        xWriteOutput( pcListPic, curLayerId, nalu.m_temporalId );
389      }
390#endif
391    }
392  }
393#if ALIGNED_BUMPING
394   flushAllPictures( true );   
395#else
396  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
397  {
398    xFlushOutput( m_acTDecTop[layer].getListPic(), layer );
399  }
400#endif
401  // delete buffers
402#if AVC_BASE
403  UInt layerIdxmin = m_acTDecTop[0].getBLReconFile()->is_open() ? 1 : 0;
404
405  if( streamYUV.is_open() )
406  {
407    streamYUV.close();
408  }
409  pcBLPic.destroy();
410
411#if CONFORMANCE_BITSTREAM_MODE
412  for(UInt layer = layerIdxmin; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
413#else
414  for(UInt layer = layerIdxmin; layer <= m_tgtLayerId; layer++)
415#endif
416#else
417  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
418#endif
419  {
420    m_acTDecTop[layer].deletePicBuffer();
421  }
422
423  // destroy internal classes
424  xDestroyDecLib();
425}
426#else
427Void TAppDecTop::decode()
428{
429  Int                 poc;
430  TComList<TComPic*>* pcListPic = NULL;
431
432  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
433  if (!bitstreamFile)
434  {
435    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
436    exit(EXIT_FAILURE);
437  }
438
439  InputByteStream bytestream(bitstreamFile);
440
441  if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-")
442  {
443    m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out);
444    if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good())
445    {
446      fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str());
447      exit(EXIT_FAILURE);
448    }
449  }
450
451  // create & initialize internal classes
452  xCreateDecLib();
453  xInitDecLib  ();
454  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
455
456  // main decoder loop
457  Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
458  Bool loopFiltered = false;
459
460  while (!!bitstreamFile)
461  {
462    /* location serves to work around a design fault in the decoder, whereby
463     * the process of reading a new slice that is the first slice of a new frame
464     * requires the TDecTop::decode() method to be called again with the same
465     * nal unit. */
466#if RExt__DECODER_DEBUG_BIT_STATISTICS
467    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
468    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
469#else
470    streampos location = bitstreamFile.tellg();
471#endif
472    AnnexBStats stats = AnnexBStats();
473
474    vector<uint8_t> nalUnit;
475    InputNALUnit nalu;
476    byteStreamNALUnit(bytestream, nalUnit, stats);
477
478    // call actual decoding function
479    Bool bNewPicture = false;
480    if (nalUnit.empty())
481    {
482      /* this can happen if the following occur:
483       *  - empty input file
484       *  - two back-to-back start_code_prefixes
485       *  - start_code_prefix immediately followed by EOF
486       */
487      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
488    }
489    else
490    {
491      read(nalu, nalUnit);
492      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
493      {
494        bNewPicture = false;
495      }
496      else
497      {
498        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
499        if (bNewPicture)
500        {
501          bitstreamFile.clear();
502          /* location points to the current nalunit payload[1] due to the
503           * need for the annexB parser to read three extra bytes.
504           * [1] except for the first NAL unit in the file
505           *     (but bNewPicture doesn't happen then) */
506#if RExt__DECODER_DEBUG_BIT_STATISTICS
507          bitstreamFile.seekg(location);
508          bytestream.reset();
509          TComCodingStatistics::SetStatistics(backupStats);
510#else
511          bitstreamFile.seekg(location-streamoff(3));
512          bytestream.reset();
513#endif
514        }
515      }
516    }
517
518    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
519        !m_cTDecTop.getFirstSliceInSequence () )
520    {
521      if (!loopFiltered || bitstreamFile)
522      {
523        m_cTDecTop.executeLoopFilters(poc, pcListPic);
524      }
525      loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS);
526      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
527      {
528        m_cTDecTop.setFirstSliceInSequence(true);
529      }
530    }
531    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
532              m_cTDecTop.getFirstSliceInSequence () ) 
533    {
534      m_cTDecTop.setFirstSliceInPicture (true);
535    }
536
537    if( pcListPic )
538    {
539      if ( m_pchReconFile && !openedReconFile )
540      {
541        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
542        {
543          if (m_outputBitDepth[channelType] == 0) m_outputBitDepth[channelType] = g_bitDepth[channelType];
544        }
545
546        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, m_outputBitDepth, g_bitDepth ); // write mode
547        openedReconFile = true;
548      }
549      // write reconstruction to file
550      if( bNewPicture )
551      {
552        xWriteOutput( pcListPic, nalu.m_temporalId );
553      }
554      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() )
555      {
556        m_cTDecTop.checkNoOutputPriorPics( pcListPic );
557        m_cTDecTop.setNoOutputPriorPicsFlag (false);
558      }
559      if ( bNewPicture &&
560           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
561            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
562            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
563            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
564            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
565      {
566        xFlushOutput( pcListPic );
567      }
568      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
569      {
570        xWriteOutput( pcListPic, nalu.m_temporalId );
571        m_cTDecTop.setFirstSliceInPicture (false);
572      }
573      // write reconstruction to file -- for additional bumping as defined in C.5.2.3
574      if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31)
575      {
576        xWriteOutput( pcListPic, nalu.m_temporalId );
577      }
578    }
579  }
580
581  xFlushOutput( pcListPic );
582  // delete buffers
583  m_cTDecTop.deletePicBuffer();
584
585  // destroy internal classes
586  xDestroyDecLib();
587}
588#endif
589
590// ====================================================================================================================
591// Protected member functions
592// ====================================================================================================================
593
594Void TAppDecTop::xCreateDecLib()
595{
596#if SVC_EXTENSION
597  // initialize global variables
598  initROM();
599
600#if CONFORMANCE_BITSTREAM_MODE
601  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
602#else
603  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
604#endif
605  {
606    // set layer ID
607    m_acTDecTop[layer].setLayerId                      ( layer );
608
609    // create decoder class
610    m_acTDecTop[layer].create();
611
612    m_acTDecTop[layer].setLayerDec(m_apcTDecTop);
613  }
614#else
615  // create decoder class
616  m_cTDecTop.create();
617#endif
618}
619
620Void TAppDecTop::xDestroyDecLib()
621{
622#if SVC_EXTENSION
623  // destroy ROM
624  destroyROM();
625
626#if CONFORMANCE_BITSTREAM_MODE
627  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
628#else
629  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
630#endif
631  {
632    if ( m_pchReconFile[layer] )
633    {
634      m_acTVideoIOYuvReconFile[layer].close();
635    }
636
637    // destroy decoder class
638    m_acTDecTop[layer].destroy();
639  }
640#else
641  if ( m_pchReconFile )
642  {
643    m_cTVideoIOYuvReconFile. close();
644  }
645
646  // destroy decoder class
647  m_cTDecTop.destroy();
648#endif
649}
650
651Void TAppDecTop::xInitDecLib()
652{
653  // initialize decoder class
654#if SVC_EXTENSION
655#if CONFORMANCE_BITSTREAM_MODE
656  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
657#else
658  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
659#endif
660  {
661    m_acTDecTop[layer].init();
662    m_acTDecTop[layer].setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
663#if CONFORMANCE_BITSTREAM_MODE
664    m_acTDecTop[layer].setNumLayer( MAX_LAYERS );
665#else
666    m_acTDecTop[layer].setNumLayer( m_tgtLayerId + 1 );
667#endif
668    m_acTDecTop[layer].setCommonDecoderParams( &m_commonDecoderParams );
669  }
670#if CONFORMANCE_BITSTREAM_MODE
671  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
672  {
673    m_acTDecTop[layer].setConfModeFlag( m_confModeFlag );
674  }
675#endif
676#else
677  m_cTDecTop.init();
678  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
679#if O0043_BEST_EFFORT_DECODING
680  m_cTDecTop.setForceDecodeBitDepth(m_forceDecodeBitDepth);
681#endif
682  if (!m_outputDecodedSEIMessagesFilename.empty())
683  {
684    std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout;
685    m_cTDecTop.setDecodedSEIMessageOutputStream(&os);
686  }
687#endif
688}
689
690/** \param pcListPic list of pictures to be written to file
691    \todo            DYN_REF_FREE should be revised
692 */
693#if SVC_EXTENSION
694Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt layerId, UInt tId )
695#else
696Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId )
697#endif
698{
699  if (pcListPic->empty())
700  {
701    return;
702  }
703
704  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
705  Int numPicsNotYetDisplayed = 0;
706  Int dpbFullness = 0;
707#if SVC_EXTENSION
708TComSPS* activeSPS = m_acTDecTop[layerId].getActiveSPS();
709#else
710  TComSPS* activeSPS = m_cTDecTop.getActiveSPS();
711#endif
712  UInt numReorderPicsHighestTid;
713  UInt maxDecPicBufferingHighestTid;
714  UInt maxNrSublayers = activeSPS->getMaxTLayers();
715
716  if(m_iMaxTemporalLayer == -1 || m_iMaxTemporalLayer >= maxNrSublayers)
717  {
718    numReorderPicsHighestTid = activeSPS->getNumReorderPics(maxNrSublayers-1);
719    maxDecPicBufferingHighestTid =  activeSPS->getMaxDecPicBuffering(maxNrSublayers-1); 
720  }
721  else
722  {
723    numReorderPicsHighestTid = activeSPS->getNumReorderPics(m_iMaxTemporalLayer);
724    maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(m_iMaxTemporalLayer); 
725  }
726
727  while (iterPic != pcListPic->end())
728  {
729    TComPic* pcPic = *(iterPic);
730#if SVC_EXTENSION
731    if(pcPic->getOutputMark() && pcPic->getPOC() > m_aiPOCLastDisplay[layerId])
732#else
733    if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay)
734#endif
735    {
736       numPicsNotYetDisplayed++;
737      dpbFullness++;
738    }
739    else if(pcPic->getSlice( 0 )->isReferenced())
740    {
741      dpbFullness++;
742    }
743    iterPic++;
744  }
745
746  iterPic = pcListPic->begin();
747
748  if (numPicsNotYetDisplayed>2)
749  {
750    iterPic++;
751  }
752
753  TComPic* pcPic = *(iterPic);
754  if (numPicsNotYetDisplayed>2 && pcPic->isField()) //Field Decoding
755  {
756    TComList<TComPic*>::iterator endPic   = pcListPic->end();
757    endPic--;
758    iterPic   = pcListPic->begin();
759    while (iterPic != endPic)
760    {
761      TComPic* pcPicTop = *(iterPic);
762      iterPic++;
763      TComPic* pcPicBottom = *(iterPic);
764
765#if SVC_EXTENSION
766      if( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() &&
767        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) &&
768        (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) &&       
769        (pcPicTop->getPOC() == m_aiPOCLastDisplay[layerId]+1 || m_aiPOCLastDisplay[layerId]<0) )
770#else
771      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() &&
772          (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) &&
773          (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) &&
774          (pcPicTop->getPOC() == m_iPOCLastDisplay+1 || m_iPOCLastDisplay < 0))
775#endif
776      {
777        // write to file
778        numPicsNotYetDisplayed = numPicsNotYetDisplayed-2;
779#if SVC_EXTENSION
780        if ( m_pchReconFile[layerId] )
781        {
782          const Window &conf = pcPicTop->getConformanceWindow();
783          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
784          const Bool isTff = pcPicTop->isTopField();
785
786          Bool display = true;
787          if( m_decodedNoDisplaySEIEnabled )
788          {
789            SEIMessages noDisplay = getSeisByType(pcPic->getSEIs(), SEI::NO_DISPLAY );
790            const SEINoDisplay *nd = ( noDisplay.size() > 0 ) ? (SEINoDisplay*) *(noDisplay.begin()) : NULL;
791            if( (nd != NULL) && nd->m_noDisplay )
792            {
793              display = false;
794            }
795          }
796
797          if (display)
798          {           
799            UInt chromaFormatIdc = pcPic->getSlice(0)->getChromaFormatIdc();
800            Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
801
802            m_acTVideoIOYuvReconFile[layerId].write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
803              m_outputColourSpaceConvert,
804              conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
805              conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
806              conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
807              conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
808          }
809        }
810
811        // update POC of display order
812        m_aiPOCLastDisplay[layerId] = pcPicBottom->getPOC();
813#else
814        if ( m_pchReconFile )
815        {
816          const Window &conf = pcPicTop->getConformanceWindow();
817          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
818          const Bool isTff = pcPicTop->isTopField();
819
820          Bool display = true;
821          if( m_decodedNoDisplaySEIEnabled )
822          {
823            SEIMessages noDisplay = getSeisByType(pcPic->getSEIs(), SEI::NO_DISPLAY );
824            const SEINoDisplay *nd = ( noDisplay.size() > 0 ) ? (SEINoDisplay*) *(noDisplay.begin()) : NULL;
825            if( (nd != NULL) && nd->m_noDisplay )
826            {
827              display = false;
828            }
829          }
830
831          if (display)
832          {
833            m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
834                                           m_outputColourSpaceConvert,
835                                           conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
836                                           conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
837                                           conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
838                                           conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
839          }
840        }
841
842        // update POC of display order
843        m_iPOCLastDisplay = pcPicBottom->getPOC();
844#endif
845
846        // erase non-referenced picture in the reference picture list after display
847        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
848        {
849#if !DYN_REF_FREE
850          pcPicTop->setReconMark(false);
851
852          // mark it should be extended later
853          pcPicTop->getPicYuvRec()->setBorderExtension( false );
854
855#else
856          pcPicTop->destroy();
857          pcListPic->erase( iterPic );
858          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
859          continue;
860#endif
861        }
862        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
863        {
864#if !DYN_REF_FREE
865          pcPicBottom->setReconMark(false);
866
867          // mark it should be extended later
868          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
869
870#else
871          pcPicBottom->destroy();
872          pcListPic->erase( iterPic );
873          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
874          continue;
875#endif
876        }
877        pcPicTop->setOutputMark(false);
878        pcPicBottom->setOutputMark(false);
879      }
880    }
881  }
882  else if (!pcPic->isField()) //Frame Decoding
883  {
884    iterPic = pcListPic->begin();
885
886    while (iterPic != pcListPic->end())
887    {
888      pcPic = *(iterPic);
889
890#if SVC_EXTENSION
891      if( pcPic->getOutputMark() && pcPic->getPOC() > m_aiPOCLastDisplay[layerId] &&
892        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) )
893#else
894      if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay &&
895        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
896#endif
897      {
898        // write to file
899         numPicsNotYetDisplayed--;
900        if(pcPic->getSlice(0)->isReferenced() == false)
901        {
902          dpbFullness--;
903        }
904#if SVC_EXTENSION
905        if( m_pchReconFile[layerId] )
906        {
907          const Window &conf = pcPic->getConformanceWindow();
908          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();         
909
910          UInt chromaFormatIdc = pcPic->getSlice(0)->getChromaFormatIdc();
911          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
912
913          m_acTVideoIOYuvReconFile[layerId].write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert,
914            conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
915            conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
916            conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
917            conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
918        }
919
920        // update POC of display order
921        m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
922#else
923        if ( m_pchReconFile )
924        {
925          const Window &conf    = pcPic->getConformanceWindow();
926          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
927
928          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
929                                         m_outputColourSpaceConvert,
930                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
931                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
932                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
933                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() );
934        }
935
936#if Q0074_COLOUR_REMAPPING_SEI
937        if (m_colourRemapSEIEnabled)
938        {
939          SEIMessages colourRemappingInfo = getSeisByType(pcPic->getSEIs(), SEI::COLOUR_REMAPPING_INFO );
940          const SEIColourRemappingInfo *seiColourRemappingInfo = ( colourRemappingInfo.size() > 0 ) ? (SEIColourRemappingInfo*) *(colourRemappingInfo.begin()) : NULL;
941          if (colourRemappingInfo.size() > 1)
942          {
943            printf ("Warning: Got multiple Colour Remapping Information SEI messages. Using first.");
944          }
945          if (seiColourRemappingInfo)
946          {
947            applyColourRemapping(*pcPic->getPicYuvRec(), seiColourRemappingInfo);
948          }
949          else  // using the last CRI SEI received
950          {
951            const SEIColourRemappingInfo *seiColourRemappingInfoCopy;
952            seiColourRemappingInfoCopy = seiColourRemappingInfoPrevious;
953            applyColourRemapping(*pcPic->getPicYuvRec(), seiColourRemappingInfoCopy);
954          }
955
956          // save the last CRI SEI received
957          if( seiColourRemappingInfo != NULL){
958            if (seiColourRemappingInfoPrevious != NULL)
959            {
960              delete seiColourRemappingInfoPrevious;
961              seiColourRemappingInfoPrevious = NULL;
962            }
963            if (seiColourRemappingInfo->m_colourRemapPersistenceFlag)
964            {
965              seiColourRemappingInfoPrevious = new SEIColourRemappingInfo();
966              seiColourRemappingInfoPrevious->copyFrom(seiColourRemappingInfo);
967            }
968          }
969        }
970#endif
971
972        // update POC of display order
973        m_iPOCLastDisplay = pcPic->getPOC();
974#endif
975
976        // erase non-referenced picture in the reference picture list after display
977        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
978        {
979#if !DYN_REF_FREE
980          pcPic->setReconMark(false);
981
982          // mark it should be extended later
983          pcPic->getPicYuvRec()->setBorderExtension( false );
984
985#else
986          pcPic->destroy();
987          pcListPic->erase( iterPic );
988          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
989          continue;
990#endif
991        }
992        pcPic->setOutputMark(false);
993      }
994
995      iterPic++;
996    }
997  }
998}
999
1000/** \param pcListPic list of pictures to be written to file
1001    \todo            DYN_REF_FREE should be revised
1002 */
1003#if SVC_EXTENSION
1004Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, UInt layerId )
1005#else
1006Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic )
1007#endif
1008{
1009  if(!pcListPic || pcListPic->empty())
1010  {
1011    return;
1012  }
1013  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
1014
1015  iterPic   = pcListPic->begin();
1016  TComPic* pcPic = *(iterPic);
1017
1018  if (pcPic->isField()) //Field Decoding
1019  {
1020    TComList<TComPic*>::iterator endPic   = pcListPic->end();
1021    endPic--;
1022    TComPic *pcPicTop, *pcPicBottom = NULL;
1023    while (iterPic != endPic)
1024    {
1025      pcPicTop = *(iterPic);
1026      iterPic++;
1027      pcPicBottom = *(iterPic);
1028
1029      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) )
1030      {
1031        // write to file
1032#if SVC_EXTENSION
1033        if ( m_pchReconFile[layerId] )
1034        {
1035          const Window &conf = pcPicTop->getConformanceWindow();
1036          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
1037          const Bool isTff = pcPicTop->isTopField();         
1038
1039          UInt chromaFormatIdc = pcPic->getSlice(0)->getChromaFormatIdc();
1040          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1041
1042          m_acTVideoIOYuvReconFile[layerId].write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert,
1043            conf.getWindowLeftOffset()  *xScal + defDisp.getWindowLeftOffset(),
1044            conf.getWindowRightOffset() *xScal + defDisp.getWindowRightOffset(),
1045            conf.getWindowTopOffset()   *yScal + defDisp.getWindowTopOffset(),
1046            conf.getWindowBottomOffset()*yScal + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
1047        }
1048
1049        // update POC of display order
1050        m_aiPOCLastDisplay[layerId] = pcPicBottom->getPOC();
1051#else
1052        if ( m_pchReconFile )
1053        {
1054          const Window &conf = pcPicTop->getConformanceWindow();
1055          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
1056          const Bool isTff = pcPicTop->isTopField();
1057          m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
1058                                         m_outputColourSpaceConvert,
1059                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
1060                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
1061                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
1062                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
1063        }
1064
1065        // update POC of display order
1066        m_iPOCLastDisplay = pcPicBottom->getPOC();
1067#endif
1068
1069        // erase non-referenced picture in the reference picture list after display
1070        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
1071        {
1072#if !DYN_REF_FREE
1073          pcPicTop->setReconMark(false);
1074
1075          // mark it should be extended later
1076          pcPicTop->getPicYuvRec()->setBorderExtension( false );
1077
1078#else
1079          pcPicTop->destroy();
1080          pcListPic->erase( iterPic );
1081          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
1082          continue;
1083#endif
1084        }
1085        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
1086        {
1087#if !DYN_REF_FREE
1088          pcPicBottom->setReconMark(false);
1089
1090          // mark it should be extended later
1091          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
1092
1093#else
1094          pcPicBottom->destroy();
1095          pcListPic->erase( iterPic );
1096          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
1097          continue;
1098#endif
1099        }
1100        pcPicTop->setOutputMark(false);
1101        pcPicBottom->setOutputMark(false);
1102
1103#if !DYN_REF_FREE
1104        if(pcPicTop)
1105        {
1106          pcPicTop->destroy();
1107          delete pcPicTop;
1108          pcPicTop = NULL;
1109        }
1110#endif
1111      }
1112    }
1113    if(pcPicBottom)
1114    {
1115      pcPicBottom->destroy();
1116      delete pcPicBottom;
1117      pcPicBottom = NULL;
1118    }
1119  }
1120  else //Frame decoding
1121  {
1122    while (iterPic != pcListPic->end())
1123    {
1124      pcPic = *(iterPic);
1125
1126      if ( pcPic->getOutputMark() )
1127      {
1128        // write to file
1129#if SVC_EXTENSION
1130        if ( m_pchReconFile[layerId] )
1131        {
1132          const Window &conf = pcPic->getConformanceWindow();
1133          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();         
1134
1135          UInt chromaFormatIdc = pcPic->getSlice(0)->getChromaFormatIdc();
1136          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1137
1138          m_acTVideoIOYuvReconFile[layerId].write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert,
1139            conf.getWindowLeftOffset()  *xScal + defDisp.getWindowLeftOffset(),
1140            conf.getWindowRightOffset() *xScal + defDisp.getWindowRightOffset(),
1141            conf.getWindowTopOffset()   *yScal + defDisp.getWindowTopOffset(),
1142            conf.getWindowBottomOffset()*yScal + defDisp.getWindowBottomOffset() );
1143        }
1144
1145        // update POC of display order
1146        m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
1147#else
1148        if ( m_pchReconFile )
1149        {
1150          const Window &conf    = pcPic->getConformanceWindow();
1151          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
1152
1153          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
1154                                         m_outputColourSpaceConvert,
1155                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
1156                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
1157                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
1158                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() );
1159        }
1160
1161#if Q0074_COLOUR_REMAPPING_SEI
1162        if (m_colourRemapSEIEnabled)
1163        {
1164          SEIMessages colourRemappingInfo = getSeisByType(pcPic->getSEIs(), SEI::COLOUR_REMAPPING_INFO );
1165          const SEIColourRemappingInfo *seiColourRemappingInfo = ( colourRemappingInfo.size() > 0 ) ? (SEIColourRemappingInfo*) *(colourRemappingInfo.begin()) : NULL;
1166          if (colourRemappingInfo.size() > 1)
1167          {
1168            printf ("Warning: Got multiple Colour Remapping Information SEI messages. Using first.");
1169          }
1170          if (seiColourRemappingInfo)
1171          {
1172            applyColourRemapping(*pcPic->getPicYuvRec(), seiColourRemappingInfo);
1173          }
1174          else  // using the last CRI SEI received
1175          {
1176            const SEIColourRemappingInfo *seiColourRemappingInfoCopy;
1177            seiColourRemappingInfoCopy = seiColourRemappingInfoPrevious;
1178            applyColourRemapping(*pcPic->getPicYuvRec(), seiColourRemappingInfoCopy);
1179          }
1180
1181          // save the last CRI SEI received
1182          if( seiColourRemappingInfo != NULL){
1183            if (seiColourRemappingInfoPrevious != NULL)
1184            {
1185              delete seiColourRemappingInfoPrevious;
1186              seiColourRemappingInfoPrevious = NULL;
1187            }
1188            if (seiColourRemappingInfo->m_colourRemapPersistenceFlag)
1189            {
1190              seiColourRemappingInfoPrevious = new SEIColourRemappingInfo();
1191              seiColourRemappingInfoPrevious->copyFrom(seiColourRemappingInfo);
1192            }
1193          }
1194        }
1195#endif
1196
1197        // update POC of display order
1198        m_iPOCLastDisplay = pcPic->getPOC();
1199#endif
1200
1201        // erase non-referenced picture in the reference picture list after display
1202        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
1203        {
1204#if !DYN_REF_FREE
1205          pcPic->setReconMark(false);
1206
1207          // mark it should be extended later
1208          pcPic->getPicYuvRec()->setBorderExtension( false );
1209
1210#else
1211          pcPic->destroy();
1212          pcListPic->erase( iterPic );
1213          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
1214          continue;
1215#endif
1216        }
1217        pcPic->setOutputMark(false);
1218      }
1219#if !SVC_EXTENSION
1220#if !DYN_REF_FREE
1221      if(pcPic)
1222      {
1223        pcPic->destroy();
1224        delete pcPic;
1225        pcPic = NULL;
1226      }
1227#endif
1228#endif
1229      iterPic++;
1230    }
1231  }
1232#if SVC_EXTENSION
1233  m_aiPOCLastDisplay[layerId] = -MAX_INT;
1234#else
1235  pcListPic->clear();
1236  m_iPOCLastDisplay = -MAX_INT;
1237#endif
1238}
1239
1240/** \param nalu Input nalu to check whether its LayerId is within targetDecLayerIdSet
1241 */
1242Bool TAppDecTop::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu )
1243{
1244  if ( m_targetDecLayerIdSet.size() == 0 ) // By default, the set is empty, meaning all LayerIds are allowed
1245  {
1246    return true;
1247  }
1248#if SVC_EXTENSION
1249  if (nalu->m_layerId == 0 && (nalu->m_nalUnitType == NAL_UNIT_VPS || nalu->m_nalUnitType == NAL_UNIT_SPS || nalu->m_nalUnitType == NAL_UNIT_PPS || nalu->m_nalUnitType == NAL_UNIT_EOS))
1250  {
1251    return true;
1252  }
1253#endif
1254  for (std::vector<Int>::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++)
1255  {
1256    if ( nalu->m_reservedZero6Bits == (*it) )
1257    {
1258      return true;
1259    }
1260  }
1261  return false;
1262}
1263
1264#if ALIGNED_BUMPING
1265// Function outputs a picture, and marks it as not needed for output.
1266Void TAppDecTop::xOutputAndMarkPic( TComPic *pic, const Char *reconFile, const Int layerId, Int &pocLastDisplay, DpbStatus &dpbStatus )
1267{
1268  if ( reconFile )
1269  {
1270    const Window &conf = pic->getConformanceWindow();
1271    const Window &defDisp = m_respectDefDispWindow ? pic->getDefDisplayWindow() : Window();
1272    Int xScal =  1, yScal = 1;
1273
1274    UInt chromaFormatIdc = pic->getSlice(0)->getChromaFormatIdc();
1275    xScal = TComSPS::getWinUnitX( chromaFormatIdc );
1276    yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1277
1278    TComPicYuv* pPicCYuvRec = pic->getPicYuvRec();
1279    m_acTVideoIOYuvReconFile[layerId].write( pPicCYuvRec, m_outputColourSpaceConvert,
1280      conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
1281      conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
1282      conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
1283      conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
1284
1285#if Q0074_COLOUR_REMAPPING_SEI
1286    if( m_colourRemapSEIEnabled )
1287    {
1288      SEIMessages colourRemappingInfo = getSeisByType(pic->getSEIs(), SEI::COLOUR_REMAPPING_INFO );
1289      const SEIColourRemappingInfo *seiColourRemappingInfo = ( colourRemappingInfo.size() > 0 ) ? (SEIColourRemappingInfo*) *(colourRemappingInfo.begin()) : NULL;
1290      if (colourRemappingInfo.size() > 1)
1291      {
1292        printf ("Warning: Got multiple Colour Remapping Information SEI messages. Using first.");
1293      }
1294
1295      if (seiColourRemappingInfo)
1296      {
1297        //printf ("\n\nColour Remapping is applied to POC : %d and LayerId : %d ",pic->getPOC(), pic->getLayerId());
1298        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfo
1299#if SVC_EXTENSION
1300       , pic->getLayerId()
1301#endif
1302        );
1303      }
1304      else  // using the last CRI SEI received
1305      {
1306        const SEIColourRemappingInfo *seiColourRemappingInfoCopy;
1307        seiColourRemappingInfoCopy = seiColourRemappingInfoPrevious;
1308        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfoCopy
1309#if SVC_EXTENSION
1310        , pic->getLayerId()
1311#endif
1312        );
1313      }
1314
1315      // save the last CRI SEI received
1316      if( seiColourRemappingInfo != NULL){
1317        if (seiColourRemappingInfoPrevious != NULL)
1318        {
1319          delete seiColourRemappingInfoPrevious;
1320          seiColourRemappingInfoPrevious = NULL;
1321        }
1322        if (seiColourRemappingInfo->m_colourRemapPersistenceFlag)
1323        {
1324          seiColourRemappingInfoPrevious = new SEIColourRemappingInfo();
1325          seiColourRemappingInfoPrevious->copyFrom(seiColourRemappingInfo);
1326        }
1327      }
1328    }
1329
1330#endif
1331  }
1332  // update POC of display order
1333  pocLastDisplay = pic->getPOC();
1334
1335  // Mark as not needed for output
1336  pic->setOutputMark(false);
1337
1338  // "erase" non-referenced picture in the reference picture list after display
1339  if ( !pic->getSlice(0)->isReferenced() && pic->getReconMark() == true )
1340  {
1341    pic->setReconMark(false);
1342
1343    // mark it should be extended later
1344    pic->getPicYuvRec()->setBorderExtension( false );
1345
1346    dpbStatus.m_numPicsInSubDpb[dpbStatus.m_layerIdToSubDpbIdMap[layerId]]--;
1347  }
1348}
1349
1350Void TAppDecTop::flushAllPictures(Int layerId, Bool outputPictures)
1351{
1352  // First "empty" all pictures that are not used for reference and not needed for output
1353  emptyUnusedPicturesNotNeededForOutput();
1354
1355  if( outputPictures )  // All pictures in the DPB in that layer are to be output; this means other pictures would also be output
1356  {
1357    std::vector<Int>  listOfPocs;
1358    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1359    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1360
1361    DpbStatus dpbStatus;
1362
1363    // Find the status of the DPB
1364    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
1365
1366    if( listOfPocs.size() )
1367    {
1368      while( listOfPocsInEachLayer[layerId].size() )    // As long as there picture in the layer to be output
1369      {
1370        bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1371      }
1372    }
1373  }
1374
1375  // Now remove all pictures from the layer DPB?
1376  markAllPicturesAsErased(layerId);
1377}
1378
1379Void TAppDecTop::flushAllPictures(Bool outputPictures)
1380{
1381  // First "empty" all pictures that are not used for reference and not needed for output
1382  emptyUnusedPicturesNotNeededForOutput();
1383
1384  if( outputPictures )  // All pictures in the DPB are to be output
1385  {
1386    std::vector<Int>  listOfPocs;
1387    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1388    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1389
1390    DpbStatus dpbStatus;
1391
1392    // Find the status of the DPB
1393    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus, false);
1394
1395    while( dpbStatus.m_numAUsNotDisplayed )
1396    {
1397      bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1398    }
1399  }
1400
1401  // Now remove all pictures from the DPB?
1402  markAllPicturesAsErased();
1403}
1404
1405Void TAppDecTop::markAllPicturesAsErased()
1406{
1407  for(Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++)
1408  {
1409    markAllPicturesAsErased(i);
1410  }
1411}
1412
1413Void TAppDecTop::markAllPicturesAsErased(Int layerIdx)
1414{
1415  TComList<TComPic*>::iterator  iterPic = m_acTDecTop[layerIdx].getListPic()->begin();
1416  Int iSize = Int( m_acTDecTop[layerIdx].getListPic()->size() );
1417 
1418  for (Int i = 0; i < iSize; i++ )
1419  {
1420    TComPic* pcPic = *(iterPic++);
1421
1422    if( pcPic )
1423    {
1424      pcPic->destroy();
1425
1426      // pcPic is statically created for the external (AVC) base layer, no need to delete it
1427      if( !m_acTDecTop[layerIdx].getParameterSetManager()->getActiveVPS()->getNonHEVCBaseLayerFlag() || layerIdx )
1428      {
1429        delete pcPic;
1430        pcPic = NULL;
1431      }
1432    }
1433  }
1434
1435  m_acTDecTop[layerIdx].getListPic()->clear();
1436}
1437
1438Void TAppDecTop::checkOutputBeforeDecoding(Int layerIdx)
1439{   
1440  std::vector<Int>  listOfPocs;
1441  std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1442  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1443
1444  DpbStatus dpbStatus;
1445
1446  // First "empty" all pictures that are not used for reference and not needed for output
1447  emptyUnusedPicturesNotNeededForOutput();
1448
1449  // Find the status of the DPB
1450  xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
1451
1452  // If not picture to be output, return
1453  if( listOfPocs.size() == 0 )
1454  {
1455    return;
1456  }
1457
1458  // Find DPB-information from the VPS
1459  DpbStatus maxDpbLimit;
1460
1461  Int subDpbIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx() == 0 ? dpbStatus.m_layerIdToSubDpbIdMap[0] : dpbStatus.m_layerIdToSubDpbIdMap[layerIdx];
1462
1463  findDpbParametersFromVps(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, maxDpbLimit);
1464
1465  // Assume that listOfPocs is sorted in increasing order - if not have to sort it.
1466  while( ifInvokeBumpingBeforeDecoding(dpbStatus, maxDpbLimit, layerIdx, subDpbIdx) )
1467  {
1468    bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1469  } 
1470}
1471
1472Void TAppDecTop::checkOutputAfterDecoding()
1473{   
1474  std::vector<Int>  listOfPocs;
1475  std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1476  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1477
1478  DpbStatus dpbStatus;
1479
1480  // First "empty" all pictures that are not used for reference and not needed for output
1481  emptyUnusedPicturesNotNeededForOutput();
1482
1483  // Find the status of the DPB
1484  xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus);
1485
1486  // If not picture to be output, return
1487  if( listOfPocs.size() == 0 )
1488  {
1489    return;
1490  }
1491
1492  // Find DPB-information from the VPS
1493  DpbStatus maxDpbLimit;
1494  findDpbParametersFromVps(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, maxDpbLimit);
1495
1496  // Assume that listOfPocs is sorted in increasing order - if not have to sort it.
1497  while( ifInvokeBumpingAfterDecoding(dpbStatus, maxDpbLimit) )
1498  {
1499    bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1500  } 
1501}
1502
1503Void TAppDecTop::bumpingProcess(std::vector<Int> &listOfPocs, std::vector<Int> *listOfPocsInEachLayer, std::vector<Int> *listOfPocsPositionInEachLayer, DpbStatus &dpbStatus)
1504{
1505  // Choose the smallest POC value
1506  Int pocValue = *(listOfPocs.begin());
1507  std::vector<int>::iterator it;
1508  TComList<TComPic*>::iterator iterPic;
1509
1510  for( Int dpbLayerCtr = 0; dpbLayerCtr < dpbStatus.m_numLayers; dpbLayerCtr++)
1511  {
1512    Int layerId  = dpbStatus.m_targetDecLayerIdList[dpbLayerCtr];
1513
1514    // Check if picture with pocValue is present.
1515    it = find( listOfPocsInEachLayer[layerId].begin(), listOfPocsInEachLayer[layerId].end(), pocValue );
1516    if( it != listOfPocsInEachLayer[layerId].end() )  // picture found.
1517    {
1518      Int picPosition = (Int)std::distance( listOfPocsInEachLayer[layerId].begin(), it );
1519      Int j;
1520      for(j = 0, iterPic = m_acTDecTop[layerId].getListPic()->begin(); j < listOfPocsPositionInEachLayer[layerId][picPosition]; j++) // Picture to be output
1521      {
1522        iterPic++;
1523      }
1524      TComPic *pic = *iterPic;
1525
1526      xOutputAndMarkPic( pic, m_pchReconFile[layerId], layerId, m_aiPOCLastDisplay[layerId], dpbStatus );
1527
1528#if CONFORMANCE_BITSTREAM_MODE
1529      FILE *fptr;
1530      if( m_confModeFlag )
1531      {
1532        if( m_metadataFileRefresh )
1533        {
1534          fptr = fopen( this->getMetadataFileName().c_str(), "w" );
1535          fprintf(fptr, " LayerId      POC    MD5\n");
1536          fprintf(fptr, "------------------------\n");
1537        }
1538        else
1539        {
1540          fptr = fopen( this->getMetadataFileName().c_str(), "a+" );
1541        }
1542        this->setMetadataFileRefresh(false);
1543
1544        TComDigest recon_digest;
1545        Int numChar = calcMD5(*pic->getPicYuvRec(), recon_digest);
1546        fprintf(fptr, "%8d%9d    MD5:%s\n", pic->getLayerId(), pic->getSlice(0)->getPOC(), digestToString(recon_digest, numChar).c_str());
1547        fclose(fptr);
1548      }
1549#endif
1550
1551      listOfPocsInEachLayer[layerId].erase( it );
1552      listOfPocsPositionInEachLayer[layerId].erase( listOfPocsPositionInEachLayer[layerId].begin() + picPosition );
1553      dpbStatus.m_numPicsInSubDpb[dpbStatus.m_layerIdToSubDpbIdMap[layerId]]--;
1554    }
1555  }
1556
1557  dpbStatus.m_numAUsNotDisplayed--;
1558
1559#if CONFORMANCE_BITSTREAM_MODE
1560  if( m_confModeFlag )
1561  {
1562    for( Int dpbLayerCtr = 0; dpbLayerCtr < dpbStatus.m_numLayers; dpbLayerCtr++)
1563    {
1564      Int layerId = dpbStatus.m_targetDecLayerIdList[dpbLayerCtr];
1565      // Output all picutres "decoded" in that layer that have POC less than the current picture
1566      std::vector<TComPic> *layerBuffer = (m_acTDecTop->getLayerDec(layerId))->getConfListPic();
1567      // Write all pictures to the file.
1568      if( this->getDecodedYuvLayerRefresh(layerId) )
1569      {
1570        m_outputBitDepth[CHANNEL_TYPE_LUMA]   = g_bitDepth[CHANNEL_TYPE_LUMA]   = g_bitDepthLayer[CHANNEL_TYPE_LUMA][layerId];
1571        m_outputBitDepth[CHANNEL_TYPE_CHROMA] = g_bitDepth[CHANNEL_TYPE_CHROMA] = g_bitDepthLayer[CHANNEL_TYPE_CHROMA][layerId];
1572
1573        char tempFileName[256];
1574        strcpy(tempFileName, this->getDecodedYuvLayerFileName( layerId ).c_str());
1575        m_confReconFile[layerId].open(tempFileName, true, m_outputBitDepth, m_outputBitDepth, g_bitDepth ); // write mode
1576        this->setDecodedYuvLayerRefresh( layerId, false );
1577      }
1578
1579      std::vector<TComPic>::iterator itPic;
1580      for(itPic = layerBuffer->begin(); itPic != layerBuffer->end(); itPic++)
1581      {
1582        TComPic checkPic = *itPic;
1583        const Window &conf = checkPic.getConformanceWindow();
1584        const Window &defDisp = m_respectDefDispWindow ? checkPic.getDefDisplayWindow() : Window();
1585        Int xScal = 1, yScal = 1;
1586 
1587        UInt chromaFormatIdc = checkPic.getSlice(0)->getChromaFormatIdc();
1588        xScal = TComSPS::getWinUnitX( chromaFormatIdc );
1589        yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1590 
1591        if( checkPic.getPOC() <= pocValue )
1592        {
1593          TComPicYuv* pPicCYuvRec = checkPic.getPicYuvRec();
1594          m_confReconFile[layerId].write( pPicCYuvRec, m_outputColourSpaceConvert,
1595            conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
1596            conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
1597            conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
1598            conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
1599          layerBuffer->erase(itPic);
1600          itPic = layerBuffer->begin();  // Ensure doesn't go to infinite loop
1601          if(layerBuffer->size() == 0)
1602          {
1603            break;
1604          }
1605        }
1606      }
1607    }
1608  }
1609#endif
1610
1611  // Remove the picture from the listOfPocs
1612  listOfPocs.erase( listOfPocs.begin() );
1613}
1614
1615TComVPS *TAppDecTop::findDpbParametersFromVps(std::vector<Int> const &listOfPocs, std::vector<Int> const *listOfPocsInEachLayer, std::vector<Int> const *listOfPocsPositionInEachLayer, DpbStatus &maxDpbLimit)
1616{
1617  Int targetOutputLsIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx();
1618  TComVPS *vps = NULL;
1619
1620  if( targetOutputLsIdx == 0 )   // Only base layer is output
1621  {
1622    TComSPS *sps = NULL;
1623    assert( listOfPocsInEachLayer[0].size() != 0 );
1624    TComList<TComPic*>::iterator iterPic;
1625    Int j;
1626    for(j = 0, iterPic = m_acTDecTop[0].getListPic()->begin(); j < listOfPocsPositionInEachLayer[0][0]; j++) // Picture to be output
1627    {
1628      iterPic++;
1629    }
1630    TComPic *pic = *iterPic;
1631    sps = pic->getSlice(0)->getSPS();   assert( sps->getLayerId() == 0 );
1632    vps = pic->getSlice(0)->getVPS();
1633    Int highestTId = sps->getMaxTLayers() - 1;
1634
1635    maxDpbLimit.m_numAUsNotDisplayed = sps->getNumReorderPics( highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1636    maxDpbLimit.m_maxLatencyIncrease = sps->getMaxLatencyIncrease( highestTId ) > 0;
1637    if( maxDpbLimit.m_maxLatencyIncrease )
1638    {
1639      maxDpbLimit.m_maxLatencyPictures = sps->getMaxLatencyIncrease( highestTId ) + sps->getNumReorderPics( highestTId ) - 1;
1640    }
1641    maxDpbLimit.m_numPicsInSubDpb[0] = sps->getMaxDecPicBuffering( highestTId );
1642  }
1643  else
1644  {
1645    // -------------------------------------
1646    // Find the VPS used for the pictures
1647    // -------------------------------------
1648    for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1649    {
1650      if( m_acTDecTop[i].getListPic()->empty() )
1651      {
1652        assert( listOfPocsInEachLayer[i].size() == 0 );
1653        continue;
1654      }
1655
1656      std::vector<Int>::const_iterator it;
1657      it = find( listOfPocsInEachLayer[i].begin(), listOfPocsInEachLayer[i].end(), listOfPocs[0] );
1658      TComList<TComPic*>::iterator iterPic;
1659
1660      if( it != listOfPocsInEachLayer[i].end() )
1661      {
1662        Int picPosition = (Int)std::distance( listOfPocsInEachLayer[i].begin(), it );
1663        Int j;
1664
1665        // Picture to be output
1666        for( j = 0, iterPic = m_acTDecTop[i].getListPic()->begin(); j < listOfPocsPositionInEachLayer[i][picPosition]; j++ )
1667        {
1668          iterPic++;
1669        }
1670
1671        TComPic *pic = *iterPic;
1672        vps = pic->getSlice(0)->getVPS();
1673        break;
1674      }
1675    }
1676
1677    Int targetLsIdx       = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1678    Int highestTId = vps->getMaxTLayers() - 1;
1679
1680    maxDpbLimit.m_numAUsNotDisplayed = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1681    maxDpbLimit.m_maxLatencyIncrease  = vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) > 0;
1682
1683    if( maxDpbLimit.m_maxLatencyIncrease )
1684    {
1685      maxDpbLimit.m_maxLatencyPictures = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ) + vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) - 1;
1686    }
1687
1688    for(Int i = 0; i < vps->getNumLayersInIdList( targetLsIdx ); i++)
1689    {
1690      maxDpbLimit.m_numPicsInSubDpb[i] = vps->getMaxVpsDecPicBufferingMinus1( targetOutputLsIdx, i, highestTId) + 1;
1691    }
1692    // -------------------------------------
1693  }
1694  return vps;
1695}
1696
1697Void TAppDecTop::emptyUnusedPicturesNotNeededForOutput()
1698{
1699  for( Int layerIdx = 0; layerIdx < MAX_VPS_LAYER_IDX_PLUS1; layerIdx++ )
1700  {
1701    TComList <TComPic*> *pcListPic = m_acTDecTop[layerIdx].getListPic();
1702    TComList<TComPic*>::iterator iterPic = pcListPic->begin();
1703    while ( iterPic != pcListPic->end() )
1704    {
1705      TComPic *pic = *iterPic;
1706      if( !pic->getSlice(0)->isReferenced() && !pic->getOutputMark() )
1707      {
1708        // Emtpy the picture buffer
1709        pic->setReconMark( false );
1710      }
1711      iterPic++;
1712    }
1713  }
1714}
1715
1716Bool TAppDecTop::ifInvokeBumpingBeforeDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit, const Int layerIdx, const Int subDpbIdx )
1717{
1718  Bool retVal = false;
1719  // Number of reorder picutres
1720  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1721
1722  // Number of pictures in each sub-DPB
1723  retVal |= ( dpbStatus.m_numPicsInSubDpb[subDpbIdx] >= dpbLimit.m_numPicsInSubDpb[subDpbIdx] );
1724
1725  return retVal;
1726}
1727
1728Bool TAppDecTop::ifInvokeBumpingAfterDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit )
1729{
1730  Bool retVal = false;
1731
1732  // Number of reorder picutres
1733  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1734
1735  return retVal;
1736}
1737
1738Void TAppDecTop::xFindDPBStatus( std::vector<Int> &listOfPocs
1739                            , std::vector<Int> *listOfPocsInEachLayer
1740                            , std::vector<Int> *listOfPocsPositionInEachLayer
1741                            , DpbStatus &dpbStatus
1742                            , Bool notOutputCurrAu
1743                            )
1744{
1745  TComVPS *vps = NULL;
1746  dpbStatus.init();
1747
1748  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1749  {
1750    if( m_acTDecTop[i].getListPic()->empty() )
1751    {
1752      continue;
1753    }
1754   
1755    // To check # AUs that have at least one picture not output,
1756    // For each layer, populate listOfPOcs if not already present
1757    TComList<TComPic*>::iterator iterPic = m_acTDecTop[i].getListPic()->begin();
1758    Int picPositionInList = 0;
1759    while (iterPic != m_acTDecTop[i].getListPic()->end())
1760    {
1761      TComPic* pic = *(iterPic);
1762      if( pic->getReconMark() )
1763      {
1764        if( vps == NULL )
1765        {
1766          vps = pic->getSlice(0)->getVPS();
1767        }
1768
1769        if( !(pic->isCurrAu() && notOutputCurrAu ) )
1770        {
1771          std::vector<Int>::iterator it;
1772          if( pic->getOutputMark() ) // && pic->getPOC() > m_aiPOCLastDisplay[i])
1773          {
1774            it = find( listOfPocs.begin(), listOfPocs.end(), pic->getPOC() ); // Check if already included
1775
1776            if( it == listOfPocs.end() )  // New POC value - i.e. new AU - add to the list
1777            {
1778              listOfPocs.push_back( pic->getPOC() );
1779            }
1780            listOfPocsInEachLayer         [i].push_back( pic->getPOC()    );    // POC to be output in each layer
1781            listOfPocsPositionInEachLayer [i].push_back( picPositionInList  );  // For ease of access
1782          }
1783
1784          if( pic->getSlice(0)->isReferenced() || pic->getOutputMark() )
1785          {
1786            dpbStatus.m_numPicsInSubDpb[i]++;  // Count pictures that are "used for reference" or "needed for output"
1787          }
1788        }
1789      }
1790
1791      iterPic++;
1792      picPositionInList++;
1793    }
1794  }
1795
1796  assert( vps != NULL );    // No picture in any DPB?
1797  std::sort( listOfPocs.begin(), listOfPocs.end() );    // Sort in increasing order of POC
1798  Int targetLsIdx = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1799
1800  // Update status
1801  dpbStatus.m_numAUsNotDisplayed = (Int)listOfPocs.size();   // Number of AUs not displayed
1802  dpbStatus.m_numLayers = vps->getNumLayersInIdList( targetLsIdx );
1803
1804  for( Int i = 0; i < dpbStatus.m_numLayers; i++ )
1805  {
1806    dpbStatus.m_layerIdToSubDpbIdMap[vps->getLayerSetLayerIdList(targetLsIdx, i)] = i;
1807    dpbStatus.m_targetDecLayerIdList[i] = vps->getLayerSetLayerIdList(targetLsIdx, i);  // Layer Id stored in a particular sub-DPB
1808  }
1809  dpbStatus.m_numSubDpbs = vps->getNumSubDpbs( targetLsIdx ); 
1810
1811  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1812  {
1813    dpbStatus.m_numPicsNotDisplayedInLayer[i] = (Int)listOfPocsInEachLayer[i].size();
1814  }
1815  assert( dpbStatus.m_numAUsNotDisplayed != -1 );
1816} 
1817
1818Void TAppDecTop::outputAllPictures(Int layerId, Bool notOutputCurrPic)
1819{
1820  { // All pictures in the DPB in that layer are to be output; this means other pictures would also be output
1821    std::vector<Int>  listOfPocs;
1822    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1823    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1824
1825    DpbStatus dpbStatus;
1826
1827    // Find the status of the DPB
1828    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus, notOutputCurrPic);
1829
1830    if( listOfPocs.size() )
1831    {
1832      while( listOfPocsInEachLayer[layerId].size() )    // As long as there picture in the layer to be output
1833      {
1834        bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1835      }
1836    }
1837  }
1838}
1839#endif //ALIGNED_BUMPING
1840
1841#if Q0074_COLOUR_REMAPPING_SEI
1842Void xInitColourRemappingLut( const Int bitDepthY, const Int bitDepthC, std::vector<Int>(&preLut)[3], std::vector<Int>(&postLut)[3], const SEIColourRemappingInfo* const pCriSEI )
1843{
1844  for ( Int c=0 ; c<3 ; c++ )
1845  { 
1846    Int bitDepth = c ? bitDepthC : bitDepthY ;
1847    preLut[c].resize(1 << bitDepth);
1848    postLut[c].resize(1 << pCriSEI->m_colourRemapBitDepth);
1849   
1850    Int bitDepthDiff = pCriSEI->m_colourRemapBitDepth - bitDepth;
1851    Int iShift1 = (bitDepthDiff>0) ? bitDepthDiff : 0; //bit scale from bitdepth to ColourRemapBitdepth (manage only case colourRemapBitDepth>= bitdepth)
1852    if( bitDepthDiff<0 )
1853      printf ("Warning: CRI SEI - colourRemapBitDepth (%d) <bitDepth (%d) - case not handled\n", pCriSEI->m_colourRemapBitDepth, bitDepth);
1854    bitDepthDiff = pCriSEI->m_colourRemapBitDepth - pCriSEI->m_colourRemapInputBitDepth;
1855    Int iShift2 = (bitDepthDiff>0) ? bitDepthDiff : 0; //bit scale from ColourRemapInputBitdepth to ColourRemapBitdepth (manage only case colourRemapBitDepth>= colourRemapInputBitDepth)
1856    if( bitDepthDiff<0 )
1857      printf ("Warning: CRI SEI - colourRemapBitDepth (%d) <colourRemapInputBitDepth (%d) - case not handled\n", pCriSEI->m_colourRemapBitDepth, pCriSEI->m_colourRemapInputBitDepth);
1858
1859    //Fill preLut
1860    for ( Int k=0 ; k<(1<<bitDepth) ; k++ )
1861    {
1862      Int iSample = k << iShift1 ;
1863      for ( Int iPivot=0 ; iPivot<=pCriSEI->m_preLutNumValMinus1[c] ; iPivot++ )
1864      {
1865        Int iCodedPrev  = pCriSEI->m_preLutCodedValue[c][iPivot]    << iShift2; //Coded in CRInputBitdepth
1866        Int iCodedNext  = pCriSEI->m_preLutCodedValue[c][iPivot+1]  << iShift2; //Coded in CRInputBitdepth
1867        Int iTargetPrev = pCriSEI->m_preLutTargetValue[c][iPivot];              //Coded in CRBitdepth
1868        Int iTargetNext = pCriSEI->m_preLutTargetValue[c][iPivot+1];            //Coded in CRBitdepth
1869        if ( iCodedPrev <= iSample && iSample <= iCodedNext )
1870        {
1871          Float fInterpol = (Float)( (iCodedNext - iSample)*iTargetPrev + (iSample - iCodedPrev)*iTargetNext ) * 1.f / (Float)(iCodedNext - iCodedPrev);
1872          preLut[c][k]  = (Int)( 0.5f + fInterpol );
1873          iPivot = pCriSEI->m_preLutNumValMinus1[c] + 1;
1874        }
1875      }
1876    }
1877   
1878    //Fill postLut
1879    for ( Int k=0 ; k<(1<<pCriSEI->m_colourRemapBitDepth) ; k++ )
1880    {
1881      Int iSample = k;
1882      for ( Int iPivot=0 ; iPivot<=pCriSEI->m_postLutNumValMinus1[c] ; iPivot++ )
1883      {
1884        Int iCodedPrev  = pCriSEI->m_postLutCodedValue[c][iPivot];    //Coded in CRBitdepth
1885        Int iCodedNext  = pCriSEI->m_postLutCodedValue[c][iPivot+1];  //Coded in CRBitdepth
1886        Int iTargetPrev = pCriSEI->m_postLutTargetValue[c][iPivot];   //Coded in CRBitdepth
1887        Int iTargetNext = pCriSEI->m_postLutTargetValue[c][iPivot+1]; //Coded in CRBitdepth
1888        if ( iCodedPrev <= iSample && iSample <= iCodedNext )
1889        {
1890          Float fInterpol =  (Float)( (iCodedNext - iSample)*iTargetPrev + (iSample - iCodedPrev)*iTargetNext ) * 1.f / (Float)(iCodedNext - iCodedPrev) ;
1891          postLut[c][k]  = (Int)( 0.5f + fInterpol );
1892          iPivot = pCriSEI->m_postLutNumValMinus1[c] + 1;
1893        }
1894      }
1895    }
1896  }
1897}
1898
1899static void applyColourRemapping(TComPicYuv& pic, const SEIColourRemappingInfo* pCriSEI, UInt layerId )
1900{ 
1901  if( !storeCriSEI.size() )
1902#if SVC_EXTENSION
1903    storeCriSEI.resize(MAX_LAYERS);
1904#else
1905    storeCriSEI.resize(1);
1906#endif
1907
1908  if ( pCriSEI ) //if a CRI SEI has just been retrieved, keep it in memory (persistence management)
1909    storeCriSEI[layerId] = *pCriSEI;
1910
1911  if( !storeCriSEI[layerId].m_colourRemapCancelFlag && pCriSEI) 
1912  {
1913    Int iHeight  = pic.getHeight(COMPONENT_Y);
1914    Int iWidth   = pic.getWidth(COMPONENT_Y);
1915    Int iStride  = pic.getStride(COMPONENT_Y);
1916    Int iCStride = pic.getStride(COMPONENT_Cb);
1917
1918    Pel *YUVIn[3], *YUVOut[3];
1919    YUVIn[0] = pic.getAddr(COMPONENT_Y);
1920    YUVIn[1] = pic.getAddr(COMPONENT_Cb);
1921    YUVIn[2] = pic.getAddr(COMPONENT_Cr);
1922   
1923    TComPicYuv picColourRemapped;
1924#if SVC_EXTENSION
1925#if AUXILIARY_PICTURES
1926    picColourRemapped.create( pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), pic.getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, NULL );
1927#else
1928    picColourRemapped.create( pic.getWidth(), pic.getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, NULL );
1929#endif
1930#else
1931    picColourRemapped.create( pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), pic.getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
1932#endif
1933    YUVOut[0] = picColourRemapped.getAddr(COMPONENT_Y);
1934    YUVOut[1] = picColourRemapped.getAddr(COMPONENT_Cb);
1935    YUVOut[2] = picColourRemapped.getAddr(COMPONENT_Cr);
1936
1937#if SVC_EXTENSION
1938    Int bitDepthY = g_bitDepthLayer[CHANNEL_TYPE_LUMA][layerId];
1939    Int bitDepthC = g_bitDepthLayer[CHANNEL_TYPE_CHROMA][layerId];
1940
1941#else
1942    Int bitDepthY = g_bitDepth[CHANNEL_TYPE_LUMA];
1943    Int bitDepthC = g_bitDepth[CHANNEL_TYPE_CHROMA];
1944#endif
1945
1946    std::vector<Int> preLut[3];
1947    std::vector<Int> postLut[3];
1948    xInitColourRemappingLut( bitDepthY, bitDepthC, preLut, postLut, &storeCriSEI[layerId] );
1949   
1950    Int roundingOffset = (storeCriSEI[layerId].m_log2MatrixDenom==0) ? 0 : (1 << (storeCriSEI[layerId].m_log2MatrixDenom - 1));
1951
1952    for( Int y = 0; y < iHeight ; y++ )
1953    {
1954      for( Int x = 0; x < iWidth ; x++ )
1955      {
1956        Int YUVPre[3], YUVMat[3];
1957        YUVPre[0] = preLut[0][ YUVIn[0][x]   ];
1958        YUVPre[1] = preLut[1][ YUVIn[1][x>>1] ];
1959        YUVPre[2] = preLut[2][ YUVIn[2][x>>1] ];
1960
1961        YUVMat[0] = ( storeCriSEI[layerId].m_colourRemapCoeffs[0][0]*YUVPre[0]
1962                    + storeCriSEI[layerId].m_colourRemapCoeffs[0][1]*YUVPre[1] 
1963                    + storeCriSEI[layerId].m_colourRemapCoeffs[0][2]*YUVPre[2] 
1964                    + roundingOffset ) >> ( storeCriSEI[layerId].m_log2MatrixDenom );
1965        YUVMat[0] = Clip3( 0, (1<<storeCriSEI[layerId].m_colourRemapBitDepth)-1, YUVMat[0] );
1966        YUVOut[0][x] = postLut[0][ YUVMat[0] ];
1967
1968        if( (y&1) && (x&1) )
1969        {
1970          for(Int c=1 ; c<3 ; c++)
1971          {
1972            YUVMat[c] = ( storeCriSEI[layerId].m_colourRemapCoeffs[c][0]*YUVPre[0] 
1973                        + storeCriSEI[layerId].m_colourRemapCoeffs[c][1]*YUVPre[1] 
1974                        + storeCriSEI[layerId].m_colourRemapCoeffs[c][2]*YUVPre[2] 
1975                        + roundingOffset ) >> ( storeCriSEI[layerId].m_log2MatrixDenom );
1976            YUVMat[c] = Clip3( 0, (1<<storeCriSEI[layerId].m_colourRemapBitDepth)-1, YUVMat[c] );
1977            YUVOut[c][x>>1] = postLut[c][ YUVMat[c] ];   
1978          }
1979        }
1980      }
1981      YUVIn[0]  += iStride;
1982      YUVOut[0] += iStride;
1983      if( y&1 )
1984      {
1985        YUVIn[1]  += iCStride;
1986        YUVIn[2]  += iCStride;
1987        YUVOut[1] += iCStride;
1988        YUVOut[2] += iCStride;
1989      }
1990    }
1991
1992    //Write remapped picture in decoding order
1993    Char  cTemp[255];
1994    sprintf(cTemp, "seiColourRemappedPic_L%d_%dx%d_%dbits.yuv", layerId, iWidth, iHeight, storeCriSEI[layerId].m_colourRemapBitDepth );
1995    picColourRemapped.dump( cTemp, true, storeCriSEI[layerId].m_colourRemapBitDepth );
1996
1997    picColourRemapped.destroy();
1998
1999    storeCriSEI[layerId].m_colourRemapCancelFlag = !storeCriSEI[layerId].m_colourRemapPersistenceFlag; //Handling persistence
2000  }
2001  else
2002  {
2003    //Write no remapped picture in decoding order
2004    if (storeCriSEI[layerId].m_colourRemapBitDepth == 8 || storeCriSEI[layerId].m_colourRemapBitDepth == 10)
2005    {
2006      Char  cTemp[255];
2007      sprintf(cTemp, "seiColourRemappedPic_L%d_%dx%d_%dbits.yuv", layerId, pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), storeCriSEI[layerId].m_colourRemapBitDepth );
2008      pic.dump( cTemp, true, storeCriSEI[layerId].m_colourRemapBitDepth );
2009    }
2010  }
2011}
2012#endif
2013//! \}
Note: See TracBrowser for help on using the repository browser.