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

Last change on this file since 1287 was 1287, checked in by seregin, 9 years ago

port rev 4322 (g_bitDepth)

  • Property svn:eol-style set to native
File size: 71.1 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2015, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     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, const BitDepths& bitDpeths, 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_nuhLayerId > m_commonDecoderParams.getTargetLayerId()) )
238#else
239        (nalu.m_nuhLayerId > m_tgtLayerId) )
240#endif
241      {
242        bNewPicture = false;
243      }
244      else
245      {
246        bNewPicture = m_acTDecTop[nalu.m_nuhLayerId].decode(nalu, m_iSkipFrame, m_aiPOCLastDisplay[nalu.m_nuhLayerId], curLayerId, bNewPOC);
247
248#if SVC_POC
249        if( (bNewPicture && m_acTDecTop[nalu.m_nuhLayerId].getParseIdc() == 3) || (m_acTDecTop[nalu.m_nuhLayerId].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_nuhLayerId].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_nuhLayerId].getParseIdc() == 3) || m_acTDecTop[nalu.m_nuhLayerId].getParseIdc() == 0 || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && 
286        !m_acTDecTop[nalu.m_nuhLayerId].getFirstSliceInSequence() )
287#else
288    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
289        !m_acTDecTop[nalu.m_nuhLayerId].getFirstSliceInSequence() )
290#endif
291    {
292      if (!loopFiltered[curLayerId] || bitstreamFile)
293      {
294        m_acTDecTop[curLayerId].executeLoopFilters(poc, pcListPic);
295      }
296      loopFiltered[curLayerId] = (nalu.m_nalUnitType == NAL_UNIT_EOS);
297
298      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
299      {
300        m_acTDecTop[nalu.m_nuhLayerId].setFirstSliceInSequence(true);
301      }
302    }
303    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
304              m_acTDecTop[nalu.m_nuhLayerId].getFirstSliceInSequence () ) 
305    {
306      m_acTDecTop[nalu.m_nuhLayerId].setFirstSliceInPicture (true);
307    }
308
309#if SVC_POC
310    if( bNewPicture && m_acTDecTop[nalu.m_nuhLayerId].getParseIdc() == 0 )
311    {
312      outputAllPictures( nalu.m_nuhLayerId, true );
313    }
314#endif
315
316    if( pcListPic )
317    {
318      if ( m_pchReconFile[curLayerId] && !openedReconFile[curLayerId] )
319      {
320        const BitDepths &bitDepths=pcListPic->front()->getSlice(0)->getBitDepths(); // use bit depths of first reconstructed picture.
321        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
322        {
323          if (m_outputBitDepth[channelType] == 0)
324          {
325            m_outputBitDepth[channelType] = bitDepths.recon[channelType];
326          }
327        }
328        m_acTVideoIOYuvReconFile[curLayerId].open( m_pchReconFile[curLayerId], true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
329
330        openedReconFile[curLayerId] = true;
331      }
332#if ALIGNED_BUMPING
333      Bool outputPicturesFlag = true; 
334
335      if( m_acTDecTop[nalu.m_nuhLayerId].getNoOutputPriorPicsFlag() )
336      {
337        outputPicturesFlag = false;
338      }
339
340      if (nalu.m_nalUnitType == NAL_UNIT_EOS) // End of sequence
341      {
342        flushAllPictures( nalu.m_nuhLayerId, outputPicturesFlag );       
343      }
344
345#if SVC_POC
346      if( bNewPicture && m_acTDecTop[nalu.m_nuhLayerId].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_nuhLayerId, outputPicturesFlag );
359        }
360        else
361        {
362          this->checkOutputBeforeDecoding( nalu.m_nuhLayerId );
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
410#if CONFORMANCE_BITSTREAM_MODE
411  for(UInt layer = layerIdxmin; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
412#else
413  for(UInt layer = layerIdxmin; layer <= m_tgtLayerId; layer++)
414#endif
415#else
416  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
417#endif
418  {
419    m_acTDecTop[layer].deletePicBuffer();
420  }
421
422  // destroy internal classes
423  xDestroyDecLib();
424}
425#else
426Void TAppDecTop::decode()
427{
428  Int                 poc;
429  TComList<TComPic*>* pcListPic = NULL;
430
431  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
432  if (!bitstreamFile)
433  {
434    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
435    exit(EXIT_FAILURE);
436  }
437
438  InputByteStream bytestream(bitstreamFile);
439
440  if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-")
441  {
442    m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out);
443    if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good())
444    {
445      fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str());
446      exit(EXIT_FAILURE);
447    }
448  }
449
450  // create & initialize internal classes
451  xCreateDecLib();
452  xInitDecLib  ();
453  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
454
455  // main decoder loop
456  Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
457  Bool loopFiltered = false;
458
459  while (!!bitstreamFile)
460  {
461    /* location serves to work around a design fault in the decoder, whereby
462     * the process of reading a new slice that is the first slice of a new frame
463     * requires the TDecTop::decode() method to be called again with the same
464     * nal unit. */
465#if RExt__DECODER_DEBUG_BIT_STATISTICS
466    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
467    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
468#else
469    streampos location = bitstreamFile.tellg();
470#endif
471    AnnexBStats stats = AnnexBStats();
472
473    vector<uint8_t> nalUnit;
474    InputNALUnit nalu;
475    byteStreamNALUnit(bytestream, nalUnit, stats);
476
477    // call actual decoding function
478    Bool bNewPicture = false;
479    if (nalUnit.empty())
480    {
481      /* this can happen if the following occur:
482       *  - empty input file
483       *  - two back-to-back start_code_prefixes
484       *  - start_code_prefix immediately followed by EOF
485       */
486      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
487    }
488    else
489    {
490      read(nalu, nalUnit);
491      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
492      {
493        bNewPicture = false;
494      }
495      else
496      {
497        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
498        if (bNewPicture)
499        {
500          bitstreamFile.clear();
501          /* location points to the current nalunit payload[1] due to the
502           * need for the annexB parser to read three extra bytes.
503           * [1] except for the first NAL unit in the file
504           *     (but bNewPicture doesn't happen then) */
505#if RExt__DECODER_DEBUG_BIT_STATISTICS
506          bitstreamFile.seekg(location);
507          bytestream.reset();
508          TComCodingStatistics::SetStatistics(backupStats);
509#else
510          bitstreamFile.seekg(location-streamoff(3));
511          bytestream.reset();
512#endif
513        }
514      }
515    }
516
517    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
518        !m_cTDecTop.getFirstSliceInSequence () )
519    {
520      if (!loopFiltered || bitstreamFile)
521      {
522        m_cTDecTop.executeLoopFilters(poc, pcListPic);
523      }
524      loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS);
525      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
526      {
527        m_cTDecTop.setFirstSliceInSequence(true);
528      }
529    }
530    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
531              m_cTDecTop.getFirstSliceInSequence () ) 
532    {
533      m_cTDecTop.setFirstSliceInPicture (true);
534    }
535
536    if( pcListPic )
537    {
538      if ( m_pchReconFile && !openedReconFile )
539      {
540        const BitDepths &bitDepths=pcListPic->front()->getPicSym()->getSPS().getBitDepths(); // use bit depths of first reconstructed picture.
541        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
542        {
543          if (m_outputBitDepth[channelType] == 0)
544          {
545            m_outputBitDepth[channelType] = bitDepths.recon[channelType];
546          }
547        }
548
549        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
550        openedReconFile = true;
551      }
552      // write reconstruction to file
553      if( bNewPicture )
554      {
555        xWriteOutput( pcListPic, nalu.m_temporalId );
556      }
557      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() )
558      {
559        m_cTDecTop.checkNoOutputPriorPics( pcListPic );
560        m_cTDecTop.setNoOutputPriorPicsFlag (false);
561      }
562      if ( bNewPicture &&
563           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
564            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
565            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
566            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
567            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
568      {
569        xFlushOutput( pcListPic );
570      }
571      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
572      {
573        xWriteOutput( pcListPic, nalu.m_temporalId );
574        m_cTDecTop.setFirstSliceInPicture (false);
575      }
576      // write reconstruction to file -- for additional bumping as defined in C.5.2.3
577      if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31)
578      {
579        xWriteOutput( pcListPic, nalu.m_temporalId );
580      }
581    }
582  }
583
584  xFlushOutput( pcListPic );
585  // delete buffers
586  m_cTDecTop.deletePicBuffer();
587
588  // destroy internal classes
589  xDestroyDecLib();
590}
591#endif
592
593// ====================================================================================================================
594// Protected member functions
595// ====================================================================================================================
596
597Void TAppDecTop::xCreateDecLib()
598{
599#if SVC_EXTENSION
600  // initialize global variables
601  initROM();
602
603#if CONFORMANCE_BITSTREAM_MODE
604  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
605#else
606  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
607#endif
608  {
609    // set layer ID
610    m_acTDecTop[layer].setLayerId                      ( layer );
611
612    // create decoder class
613    m_acTDecTop[layer].create();
614
615    m_acTDecTop[layer].setLayerDec(m_apcTDecTop);
616  }
617#else
618  // create decoder class
619  m_cTDecTop.create();
620#endif
621}
622
623Void TAppDecTop::xDestroyDecLib()
624{
625#if SVC_EXTENSION
626  // destroy ROM
627  destroyROM();
628
629#if CONFORMANCE_BITSTREAM_MODE
630  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
631#else
632  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
633#endif
634  {
635    if ( m_pchReconFile[layer] )
636    {
637      m_acTVideoIOYuvReconFile[layer].close();
638    }
639
640    // destroy decoder class
641    m_acTDecTop[layer].destroy();
642  }
643#else
644  if ( m_pchReconFile )
645  {
646    m_cTVideoIOYuvReconFile. close();
647  }
648
649  // destroy decoder class
650  m_cTDecTop.destroy();
651#endif
652}
653
654Void TAppDecTop::xInitDecLib()
655{
656  // initialize decoder class
657#if SVC_EXTENSION
658#if CONFORMANCE_BITSTREAM_MODE
659  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
660#else
661  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
662#endif
663  {
664    m_acTDecTop[layer].init();
665    m_acTDecTop[layer].setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
666#if CONFORMANCE_BITSTREAM_MODE
667    m_acTDecTop[layer].setNumLayer( MAX_LAYERS );
668#else
669    m_acTDecTop[layer].setNumLayer( m_tgtLayerId + 1 );
670#endif
671    m_acTDecTop[layer].setCommonDecoderParams( &m_commonDecoderParams );
672  }
673#if CONFORMANCE_BITSTREAM_MODE
674  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
675  {
676    m_acTDecTop[layer].setConfModeFlag( m_confModeFlag );
677  }
678#endif
679#else
680  m_cTDecTop.init();
681  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
682#if O0043_BEST_EFFORT_DECODING
683  m_cTDecTop.setForceDecodeBitDepth(m_forceDecodeBitDepth);
684#endif
685  if (!m_outputDecodedSEIMessagesFilename.empty())
686  {
687    std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout;
688    m_cTDecTop.setDecodedSEIMessageOutputStream(&os);
689  }
690#endif
691}
692
693/** \param pcListPic list of pictures to be written to file
694    \param tId       temporal sub-layer ID
695    \todo            DYN_REF_FREE should be revised
696 */
697#if SVC_EXTENSION
698Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt layerId, UInt tId )
699#else
700Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId )
701#endif
702{
703  if (pcListPic->empty())
704  {
705    return;
706  }
707
708  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
709  Int numPicsNotYetDisplayed = 0;
710  Int dpbFullness = 0;
711  const TComSPS* activeSPS = &(pcListPic->front()->getPicSym()->getSPS());
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_nuhLayerId == 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_nuhLayerId == (*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#if SVC_EXTENSION
1299        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfo, pic->getSlice(0)->getBitDepths(), pic->getLayerId());
1300#else
1301        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfo, pic->getSlice(0)->getBitDepths());
1302#endif
1303      }
1304      else  // using the last CRI SEI received
1305      {
1306        const SEIColourRemappingInfo *seiColourRemappingInfoCopy;
1307        seiColourRemappingInfoCopy = seiColourRemappingInfoPrevious;
1308#if SVC_EXTENSION
1309        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfoCopy, pic->getSlice(0)->getBitDepths(), pic->getLayerId());
1310#else
1311        applyColourRemapping(*pic->getPicYuvRec(), seiColourRemappingInfoCopy, pic->getSlice(0)->getBitDepths());
1312#endif
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        TComPictureHash recon_digest;
1545        Int numChar = calcMD5(*pic->getPicYuvRec(), recon_digest, pic->getSlice(0)->getBitDepths());
1546        fprintf(fptr, "%8d%9d    MD5:%s\n", pic->getLayerId(), pic->getSlice(0)->getPOC(), hashToString(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        char tempFileName[256];
1571        strcpy(tempFileName, this->getDecodedYuvLayerFileName( layerId ).c_str());
1572
1573        const TComVPS *vps = m_acTDecTop->getLayerDec(layerId)->getParameterSetManager()->getActiveVPS();
1574        const TComSPS *sps = m_acTDecTop->getLayerDec(layerId)->getParameterSetManager()->getActiveSPS();
1575        const BitDepths &bitDpeths = vps->getBitDepths(sps, layerId);
1576        Int bitDepth[] = {bitDpeths.recon[CHANNEL_TYPE_LUMA], bitDpeths.recon[CHANNEL_TYPE_CHROMA]};
1577
1578        m_confReconFile[layerId].open(tempFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepth ); // write mode
1579        this->setDecodedYuvLayerRefresh( layerId, false );
1580      }
1581
1582      std::vector<TComPic>::iterator itPic;
1583      for(itPic = layerBuffer->begin(); itPic != layerBuffer->end(); itPic++)
1584      {
1585        TComPic checkPic = *itPic;
1586        const Window &conf = checkPic.getConformanceWindow();
1587        const Window &defDisp = m_respectDefDispWindow ? checkPic.getDefDisplayWindow() : Window();
1588        Int xScal = 1, yScal = 1;
1589 
1590        UInt chromaFormatIdc = checkPic.getSlice(0)->getChromaFormatIdc();
1591        xScal = TComSPS::getWinUnitX( chromaFormatIdc );
1592        yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1593 
1594        if( checkPic.getPOC() <= pocValue )
1595        {
1596          TComPicYuv* pPicCYuvRec = checkPic.getPicYuvRec();
1597          m_confReconFile[layerId].write( pPicCYuvRec, m_outputColourSpaceConvert,
1598            conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
1599            conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
1600            conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
1601            conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
1602          layerBuffer->erase(itPic);
1603          itPic = layerBuffer->begin();  // Ensure doesn't go to infinite loop
1604          if(layerBuffer->size() == 0)
1605          {
1606            break;
1607          }
1608        }
1609      }
1610    }
1611  }
1612#endif
1613
1614  // Remove the picture from the listOfPocs
1615  listOfPocs.erase( listOfPocs.begin() );
1616}
1617
1618const TComVPS *TAppDecTop::findDpbParametersFromVps(std::vector<Int> const &listOfPocs, std::vector<Int> const *listOfPocsInEachLayer, std::vector<Int> const *listOfPocsPositionInEachLayer, DpbStatus &maxDpbLimit)
1619{
1620  Int targetOutputLsIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx();
1621  const TComVPS *vps = NULL;
1622
1623  if( targetOutputLsIdx == 0 )   // Only base layer is output
1624  {
1625    const TComSPS *sps = NULL;
1626    assert( listOfPocsInEachLayer[0].size() != 0 );
1627    TComList<TComPic*>::iterator iterPic;
1628    Int j;
1629    for(j = 0, iterPic = m_acTDecTop[0].getListPic()->begin(); j < listOfPocsPositionInEachLayer[0][0]; j++) // Picture to be output
1630    {
1631      iterPic++;
1632    }
1633    TComPic *pic = *iterPic;
1634    sps = pic->getSlice(0)->getSPS();   assert( sps->getLayerId() == 0 );
1635    vps = pic->getSlice(0)->getVPS();
1636    Int highestTId = sps->getMaxTLayers() - 1;
1637
1638    maxDpbLimit.m_numAUsNotDisplayed = sps->getNumReorderPics( highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1639    maxDpbLimit.m_maxLatencyIncrease = sps->getMaxLatencyIncrease( highestTId ) > 0;
1640    if( maxDpbLimit.m_maxLatencyIncrease )
1641    {
1642      maxDpbLimit.m_maxLatencyPictures = sps->getMaxLatencyIncrease( highestTId ) + sps->getNumReorderPics( highestTId ) - 1;
1643    }
1644    maxDpbLimit.m_numPicsInSubDpb[0] = sps->getMaxDecPicBuffering( highestTId );
1645  }
1646  else
1647  {
1648    // -------------------------------------
1649    // Find the VPS used for the pictures
1650    // -------------------------------------
1651    for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1652    {
1653      if( m_acTDecTop[i].getListPic()->empty() )
1654      {
1655        assert( listOfPocsInEachLayer[i].size() == 0 );
1656        continue;
1657      }
1658
1659      std::vector<Int>::const_iterator it;
1660      it = find( listOfPocsInEachLayer[i].begin(), listOfPocsInEachLayer[i].end(), listOfPocs[0] );
1661      TComList<TComPic*>::iterator iterPic;
1662
1663      if( it != listOfPocsInEachLayer[i].end() )
1664      {
1665        Int picPosition = (Int)std::distance( listOfPocsInEachLayer[i].begin(), it );
1666        Int j;
1667
1668        // Picture to be output
1669        for( j = 0, iterPic = m_acTDecTop[i].getListPic()->begin(); j < listOfPocsPositionInEachLayer[i][picPosition]; j++ )
1670        {
1671          iterPic++;
1672        }
1673
1674        TComPic *pic = *iterPic;
1675        vps = pic->getSlice(0)->getVPS();
1676        break;
1677      }
1678    }
1679
1680    Int targetLsIdx       = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1681    Int highestTId = vps->getMaxTLayers() - 1;
1682
1683    maxDpbLimit.m_numAUsNotDisplayed = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1684    maxDpbLimit.m_maxLatencyIncrease  = vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) > 0;
1685
1686    if( maxDpbLimit.m_maxLatencyIncrease )
1687    {
1688      maxDpbLimit.m_maxLatencyPictures = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ) + vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) - 1;
1689    }
1690
1691    for(Int i = 0; i < vps->getNumLayersInIdList( targetLsIdx ); i++)
1692    {
1693      maxDpbLimit.m_numPicsInSubDpb[i] = vps->getMaxVpsDecPicBufferingMinus1( targetOutputLsIdx, i, highestTId) + 1;
1694    }
1695    // -------------------------------------
1696  }
1697  return vps;
1698}
1699
1700Void TAppDecTop::emptyUnusedPicturesNotNeededForOutput()
1701{
1702  for( Int layerIdx = 0; layerIdx < MAX_VPS_LAYER_IDX_PLUS1; layerIdx++ )
1703  {
1704    TComList <TComPic*> *pcListPic = m_acTDecTop[layerIdx].getListPic();
1705    TComList<TComPic*>::iterator iterPic = pcListPic->begin();
1706    while ( iterPic != pcListPic->end() )
1707    {
1708      TComPic *pic = *iterPic;
1709
1710      assert( pic->getPicSym() );
1711
1712      if( !pic->getSlice(0)->isReferenced() && !pic->getOutputMark() )
1713      {
1714        // Emtpy the picture buffer
1715        pic->setReconMark( false );
1716      }
1717      iterPic++;
1718    }
1719  }
1720}
1721
1722Bool TAppDecTop::ifInvokeBumpingBeforeDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit, const Int layerIdx, const Int subDpbIdx )
1723{
1724  Bool retVal = false;
1725  // Number of reorder picutres
1726  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1727
1728  // Number of pictures in each sub-DPB
1729  retVal |= ( dpbStatus.m_numPicsInSubDpb[subDpbIdx] >= dpbLimit.m_numPicsInSubDpb[subDpbIdx] );
1730
1731  return retVal;
1732}
1733
1734Bool TAppDecTop::ifInvokeBumpingAfterDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit )
1735{
1736  Bool retVal = false;
1737
1738  // Number of reorder picutres
1739  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1740
1741  return retVal;
1742}
1743
1744Void TAppDecTop::xFindDPBStatus( std::vector<Int> &listOfPocs
1745                            , std::vector<Int> *listOfPocsInEachLayer
1746                            , std::vector<Int> *listOfPocsPositionInEachLayer
1747                            , DpbStatus &dpbStatus
1748                            , Bool notOutputCurrAu
1749                            )
1750{
1751  const TComVPS *vps = NULL;
1752  dpbStatus.init();
1753
1754  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1755  {
1756    if( m_acTDecTop[i].getListPic()->empty() )
1757    {
1758      continue;
1759    }
1760   
1761    // To check # AUs that have at least one picture not output,
1762    // For each layer, populate listOfPOcs if not already present
1763    TComList<TComPic*>::iterator iterPic = m_acTDecTop[i].getListPic()->begin();
1764    Int picPositionInList = 0;
1765    while (iterPic != m_acTDecTop[i].getListPic()->end())
1766    {
1767      TComPic* pic = *(iterPic);
1768      if( pic->getReconMark() )
1769      {
1770        if( vps == NULL )
1771        {
1772          vps = pic->getSlice(0)->getVPS();
1773        }
1774
1775        if( !(pic->isCurrAu() && notOutputCurrAu ) )
1776        {
1777          std::vector<Int>::iterator it;
1778          if( pic->getOutputMark() ) // && pic->getPOC() > m_aiPOCLastDisplay[i])
1779          {
1780            it = find( listOfPocs.begin(), listOfPocs.end(), pic->getPOC() ); // Check if already included
1781
1782            if( it == listOfPocs.end() )  // New POC value - i.e. new AU - add to the list
1783            {
1784              listOfPocs.push_back( pic->getPOC() );
1785            }
1786            listOfPocsInEachLayer         [i].push_back( pic->getPOC()    );    // POC to be output in each layer
1787            listOfPocsPositionInEachLayer [i].push_back( picPositionInList  );  // For ease of access
1788          }
1789
1790          if( pic->getSlice(0)->isReferenced() || pic->getOutputMark() )
1791          {
1792            dpbStatus.m_numPicsInSubDpb[i]++;  // Count pictures that are "used for reference" or "needed for output"
1793          }
1794        }
1795      }
1796
1797      iterPic++;
1798      picPositionInList++;
1799    }
1800  }
1801
1802  assert( vps != NULL );    // No picture in any DPB?
1803  std::sort( listOfPocs.begin(), listOfPocs.end() );    // Sort in increasing order of POC
1804  Int targetLsIdx = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1805
1806  // Update status
1807  dpbStatus.m_numAUsNotDisplayed = (Int)listOfPocs.size();   // Number of AUs not displayed
1808  dpbStatus.m_numLayers = vps->getNumLayersInIdList( targetLsIdx );
1809
1810  for( Int i = 0; i < dpbStatus.m_numLayers; i++ )
1811  {
1812    dpbStatus.m_layerIdToSubDpbIdMap[vps->getLayerSetLayerIdList(targetLsIdx, i)] = i;
1813    dpbStatus.m_targetDecLayerIdList[i] = vps->getLayerSetLayerIdList(targetLsIdx, i);  // Layer Id stored in a particular sub-DPB
1814  }
1815  dpbStatus.m_numSubDpbs = vps->getNumSubDpbs( targetLsIdx ); 
1816
1817  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1818  {
1819    dpbStatus.m_numPicsNotDisplayedInLayer[i] = (Int)listOfPocsInEachLayer[i].size();
1820  }
1821  assert( dpbStatus.m_numAUsNotDisplayed != -1 );
1822} 
1823
1824Void TAppDecTop::outputAllPictures(Int layerId, Bool notOutputCurrPic)
1825{
1826  { // All pictures in the DPB in that layer are to be output; this means other pictures would also be output
1827    std::vector<Int>  listOfPocs;
1828    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1829    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1830
1831    DpbStatus dpbStatus;
1832
1833    // Find the status of the DPB
1834    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus, notOutputCurrPic);
1835
1836    if( listOfPocs.size() )
1837    {
1838      while( listOfPocsInEachLayer[layerId].size() )    // As long as there picture in the layer to be output
1839      {
1840        bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
1841      }
1842    }
1843  }
1844}
1845#endif //ALIGNED_BUMPING
1846
1847#if Q0074_COLOUR_REMAPPING_SEI
1848Void xInitColourRemappingLut( const BitDepths &bitDepths, std::vector<Int>(&preLut)[3], std::vector<Int>(&postLut)[3], const SEIColourRemappingInfo* const pCriSEI )
1849{
1850  for ( Int c=0 ; c<3 ; c++ )
1851  { 
1852    Int bitDepth = bitDepths.recon[toChannelType(ComponentID(c))];
1853    preLut[c].resize(1 << bitDepth);
1854    postLut[c].resize(1 << pCriSEI->m_colourRemapBitDepth);
1855   
1856    Int bitDepthDiff = pCriSEI->m_colourRemapBitDepth - bitDepth;
1857    Int iShift1 = (bitDepthDiff>0) ? bitDepthDiff : 0; //bit scale from bitdepth to ColourRemapBitdepth (manage only case colourRemapBitDepth>= bitdepth)
1858    if( bitDepthDiff<0 )
1859      printf ("Warning: CRI SEI - colourRemapBitDepth (%d) <bitDepth (%d) - case not handled\n", pCriSEI->m_colourRemapBitDepth, bitDepth);
1860    bitDepthDiff = pCriSEI->m_colourRemapBitDepth - pCriSEI->m_colourRemapInputBitDepth;
1861    Int iShift2 = (bitDepthDiff>0) ? bitDepthDiff : 0; //bit scale from ColourRemapInputBitdepth to ColourRemapBitdepth (manage only case colourRemapBitDepth>= colourRemapInputBitDepth)
1862    if( bitDepthDiff<0 )
1863      printf ("Warning: CRI SEI - colourRemapBitDepth (%d) <colourRemapInputBitDepth (%d) - case not handled\n", pCriSEI->m_colourRemapBitDepth, pCriSEI->m_colourRemapInputBitDepth);
1864
1865    //Fill preLut
1866    for ( Int k=0 ; k<(1<<bitDepth) ; k++ )
1867    {
1868      Int iSample = k << iShift1 ;
1869      for ( Int iPivot=0 ; iPivot<=pCriSEI->m_preLutNumValMinus1[c] ; iPivot++ )
1870      {
1871        Int iCodedPrev  = pCriSEI->m_preLutCodedValue[c][iPivot]    << iShift2; //Coded in CRInputBitdepth
1872        Int iCodedNext  = pCriSEI->m_preLutCodedValue[c][iPivot+1]  << iShift2; //Coded in CRInputBitdepth
1873        Int iTargetPrev = pCriSEI->m_preLutTargetValue[c][iPivot];              //Coded in CRBitdepth
1874        Int iTargetNext = pCriSEI->m_preLutTargetValue[c][iPivot+1];            //Coded in CRBitdepth
1875        if ( iCodedPrev <= iSample && iSample <= iCodedNext )
1876        {
1877          Float fInterpol = (Float)( (iCodedNext - iSample)*iTargetPrev + (iSample - iCodedPrev)*iTargetNext ) * 1.f / (Float)(iCodedNext - iCodedPrev);
1878          preLut[c][k]  = (Int)( 0.5f + fInterpol );
1879          iPivot = pCriSEI->m_preLutNumValMinus1[c] + 1;
1880        }
1881      }
1882    }
1883   
1884    //Fill postLut
1885    for ( Int k=0 ; k<(1<<pCriSEI->m_colourRemapBitDepth) ; k++ )
1886    {
1887      Int iSample = k;
1888      for ( Int iPivot=0 ; iPivot<=pCriSEI->m_postLutNumValMinus1[c] ; iPivot++ )
1889      {
1890        Int iCodedPrev  = pCriSEI->m_postLutCodedValue[c][iPivot];    //Coded in CRBitdepth
1891        Int iCodedNext  = pCriSEI->m_postLutCodedValue[c][iPivot+1];  //Coded in CRBitdepth
1892        Int iTargetPrev = pCriSEI->m_postLutTargetValue[c][iPivot];   //Coded in CRBitdepth
1893        Int iTargetNext = pCriSEI->m_postLutTargetValue[c][iPivot+1]; //Coded in CRBitdepth
1894        if ( iCodedPrev <= iSample && iSample <= iCodedNext )
1895        {
1896          Float fInterpol =  (Float)( (iCodedNext - iSample)*iTargetPrev + (iSample - iCodedPrev)*iTargetNext ) * 1.f / (Float)(iCodedNext - iCodedPrev) ;
1897          postLut[c][k]  = (Int)( 0.5f + fInterpol );
1898          iPivot = pCriSEI->m_postLutNumValMinus1[c] + 1;
1899        }
1900      }
1901    }
1902  }
1903}
1904
1905static Void applyColourRemapping(TComPicYuv& pic, const SEIColourRemappingInfo* pCriSEI, const BitDepths& bitDpeths, UInt layerId )
1906{ 
1907  if( !storeCriSEI.size() )
1908#if SVC_EXTENSION
1909    storeCriSEI.resize(MAX_LAYERS);
1910#else
1911    storeCriSEI.resize(1);
1912#endif
1913
1914  if ( pCriSEI ) //if a CRI SEI has just been retrieved, keep it in memory (persistence management)
1915    storeCriSEI[layerId] = *pCriSEI;
1916
1917  if( !storeCriSEI[layerId].m_colourRemapCancelFlag && pCriSEI) 
1918  {
1919    Int iHeight  = pic.getHeight(COMPONENT_Y);
1920    Int iWidth   = pic.getWidth(COMPONENT_Y);
1921    Int iStride  = pic.getStride(COMPONENT_Y);
1922    Int iCStride = pic.getStride(COMPONENT_Cb);
1923
1924    Pel *YUVIn[3], *YUVOut[3];
1925    YUVIn[0] = pic.getAddr(COMPONENT_Y);
1926    YUVIn[1] = pic.getAddr(COMPONENT_Cb);
1927    YUVIn[2] = pic.getAddr(COMPONENT_Cr);
1928   
1929    TComPicYuv picColourRemapped;
1930#if SVC_EXTENSION
1931#if AUXILIARY_PICTURES
1932    picColourRemapped.create( pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), pic.getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, NULL );
1933#else
1934    picColourRemapped.create( pic.getWidth(), pic.getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, NULL );
1935#endif
1936#else
1937    picColourRemapped.create( pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), pic.getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth );
1938#endif
1939    YUVOut[0] = picColourRemapped.getAddr(COMPONENT_Y);
1940    YUVOut[1] = picColourRemapped.getAddr(COMPONENT_Cb);
1941    YUVOut[2] = picColourRemapped.getAddr(COMPONENT_Cr);
1942
1943    std::vector<Int> preLut[3];
1944    std::vector<Int> postLut[3];
1945    xInitColourRemappingLut( bitDpeths, preLut, postLut, &storeCriSEI[layerId] );
1946   
1947    Int roundingOffset = (storeCriSEI[layerId].m_log2MatrixDenom==0) ? 0 : (1 << (storeCriSEI[layerId].m_log2MatrixDenom - 1));
1948
1949    for( Int y = 0; y < iHeight ; y++ )
1950    {
1951      for( Int x = 0; x < iWidth ; x++ )
1952      {
1953        Int YUVPre[3], YUVMat[3];
1954        YUVPre[0] = preLut[0][ YUVIn[0][x]   ];
1955        YUVPre[1] = preLut[1][ YUVIn[1][x>>1] ];
1956        YUVPre[2] = preLut[2][ YUVIn[2][x>>1] ];
1957
1958        YUVMat[0] = ( storeCriSEI[layerId].m_colourRemapCoeffs[0][0]*YUVPre[0]
1959                    + storeCriSEI[layerId].m_colourRemapCoeffs[0][1]*YUVPre[1] 
1960                    + storeCriSEI[layerId].m_colourRemapCoeffs[0][2]*YUVPre[2] 
1961                    + roundingOffset ) >> ( storeCriSEI[layerId].m_log2MatrixDenom );
1962        YUVMat[0] = Clip3( 0, (1<<storeCriSEI[layerId].m_colourRemapBitDepth)-1, YUVMat[0] );
1963        YUVOut[0][x] = postLut[0][ YUVMat[0] ];
1964
1965        if( (y&1) && (x&1) )
1966        {
1967          for(Int c=1 ; c<3 ; c++)
1968          {
1969            YUVMat[c] = ( storeCriSEI[layerId].m_colourRemapCoeffs[c][0]*YUVPre[0] 
1970                        + storeCriSEI[layerId].m_colourRemapCoeffs[c][1]*YUVPre[1] 
1971                        + storeCriSEI[layerId].m_colourRemapCoeffs[c][2]*YUVPre[2] 
1972                        + roundingOffset ) >> ( storeCriSEI[layerId].m_log2MatrixDenom );
1973            YUVMat[c] = Clip3( 0, (1<<storeCriSEI[layerId].m_colourRemapBitDepth)-1, YUVMat[c] );
1974            YUVOut[c][x>>1] = postLut[c][ YUVMat[c] ];   
1975          }
1976        }
1977      }
1978      YUVIn[0]  += iStride;
1979      YUVOut[0] += iStride;
1980      if( y&1 )
1981      {
1982        YUVIn[1]  += iCStride;
1983        YUVIn[2]  += iCStride;
1984        YUVOut[1] += iCStride;
1985        YUVOut[2] += iCStride;
1986      }
1987    }
1988
1989    //Write remapped picture in decoding order
1990    Char  cTemp[255];
1991    sprintf(cTemp, "seiColourRemappedPic_L%d_%dx%d_%dbits.yuv", layerId, iWidth, iHeight, storeCriSEI[layerId].m_colourRemapBitDepth );
1992    picColourRemapped.dump( cTemp, true, storeCriSEI[layerId].m_colourRemapBitDepth );
1993
1994    picColourRemapped.destroy();
1995
1996    storeCriSEI[layerId].m_colourRemapCancelFlag = !storeCriSEI[layerId].m_colourRemapPersistenceFlag; //Handling persistence
1997  }
1998  else
1999  {
2000    //Write no remapped picture in decoding order
2001    if (storeCriSEI[layerId].m_colourRemapBitDepth == 8 || storeCriSEI[layerId].m_colourRemapBitDepth == 10)
2002    {
2003      Char  cTemp[255];
2004      sprintf(cTemp, "seiColourRemappedPic_L%d_%dx%d_%dbits.yuv", layerId, pic.getWidth(COMPONENT_Y), pic.getHeight(COMPONENT_Y), storeCriSEI[layerId].m_colourRemapBitDepth );
2005      pic.dump( cTemp, true, storeCriSEI[layerId].m_colourRemapBitDepth );
2006    }
2007  }
2008}
2009#endif
2010//! \}
Note: See TracBrowser for help on using the repository browser.