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

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

remove picture list clearing

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