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

Last change on this file since 1502 was 1502, checked in by seregin, 8 years ago

infer parameters in SPS after activation, fixing chroma scaling for non 4:2:0

  • Property svn:eol-style set to native
File size: 72.8 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// ====================================================================================================================
59// Constructor / destructor / initialization / destroy
60// ====================================================================================================================
61
62#if SVC_EXTENSION
63TAppDecTop::TAppDecTop()
64: m_pcSeiColourRemappingInfoPrevious(NULL)
65{
66  memset( m_apcTDecTop, 0, sizeof(m_apcTDecTop) );
67  memset( m_apcTVideoIOYuvReconFile, 0, sizeof(m_apcTVideoIOYuvReconFile) );
68
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)
77 ,m_pcSeiColourRemappingInfoPrevious(NULL)
78{
79}
80#endif
81
82Void TAppDecTop::create()
83{
84}
85
86Void TAppDecTop::destroy()
87{
88  m_bitstreamFileName.clear();
89#if SVC_EXTENSION
90#if CONFORMANCE_BITSTREAM_MODE
91  for(Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
92#else
93  for( Int i = 0; i <= m_tgtLayerId; i++ )
94#endif
95  {
96    m_reconFileName[i].clear();
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    }
109  }
110#if AVC_BASE
111  m_reconFileNameBL.clear();
112#endif
113#else
114  m_reconFileName.clear();
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{
132  Int                 poc;
133  TComList<TComPic*>* pcListPic = NULL;
134
135  ifstream bitstreamFile(m_bitstreamFileName.c_str(), ifstream::in | ifstream::binary);
136  if (!bitstreamFile)
137  {
138    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_bitstreamFileName.c_str());
139    exit(EXIT_FAILURE);
140  }
141
142  InputByteStream bytestream(bitstreamFile);
143
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
154  // create & initialize internal classes
155  xCreateDecLib();
156  xInitDecLib  ();
157#if !SVC_EXTENSION
158  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
159#endif
160
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
172  // main decoder loop
173#if SVC_EXTENSION
174  Bool openedReconFile[MAX_LAYERS]; // reconstruction file not yet opened. (must be performed after SPS is seen)
175  Bool loopFiltered[MAX_LAYERS];
176  memset( loopFiltered, false, sizeof( loopFiltered ) );
177
178#if CONFORMANCE_BITSTREAM_MODE
179  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
180#else
181  for(UInt layer=0; layer<=m_tgtLayerId; layer++)
182#endif
183  {
184    openedReconFile[layer] = false;
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;
193  if( !m_reconFileNameBL.empty() )
194  {
195    streamYUV.open( m_reconFileNameBL.c_str(), fstream::in | fstream::binary );
196  }
197  m_apcTDecTop[0]->setBLReconFile( &streamYUV );
198  pcBLPic.setLayerId( 0 );
199  m_apcTDecTop[0]->setBlPic(&pcBLPic);
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. */
208#if RExt__DECODER_DEBUG_BIT_STATISTICS
209    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
210    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
211#else
212    streampos location = bitstreamFile.tellg();
213#endif
214    AnnexBStats stats = AnnexBStats();
215
216    InputNALUnit nalu;
217    byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
218
219    // call actual decoding function
220    Bool bNewPicture = false;
221    Bool bNewPOC = false;
222
223    if (nalu.getBitstream().getFifo().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);
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
245      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  ||
246#if CONFORMANCE_BITSTREAM_MODE
247        (nalu.m_nuhLayerId > m_commonDecoderParams.getTargetLayerId()) )
248#else
249        (nalu.m_nuhLayerId > m_tgtLayerId) )
250#endif
251      {
252        bNewPicture = false;
253      }
254      else
255      {
256        bNewPicture = m_apcTDecTop[nalu.m_nuhLayerId]->decode(nalu, m_iSkipFrame, m_aiPOCLastDisplay[nalu.m_nuhLayerId], curLayerId, bNewPOC);
257
258#if SVC_POC
259        if( (bNewPicture && m_apcTDecTop[nalu.m_nuhLayerId]->getParseIdc() == 3) || (m_apcTDecTop[nalu.m_nuhLayerId]->getParseIdc() == 0) )
260#else
261        if (bNewPicture)
262#endif
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) */
269#if RExt__DECODER_DEBUG_BIT_STATISTICS
270          bitstreamFile.seekg(location);
271          bytestream.reset();
272          TComCodingStatistics::SetStatistics(backupStats);
273#else
274          bitstreamFile.seekg(location-streamoff(3));
275          bytestream.reset();
276#endif
277        }
278#if SVC_POC
279        else if(m_apcTDecTop[nalu.m_nuhLayerId]->getParseIdc() == 1) 
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();
286#if RExt__DECODER_DEBUG_BIT_STATISTICS
287          TComCodingStatistics::SetStatistics(backupStats);
288#endif
289        }
290#endif
291      }
292    }
293
294#if SVC_POC
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() )
297#else
298    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
299        !m_apcTDecTop[nalu.m_nuhLayerId]->getFirstSliceInSequence() )
300#endif
301    {
302      if (!loopFiltered[curLayerId] || bitstreamFile)
303      {
304        m_apcTDecTop[curLayerId]->executeLoopFilters(poc, pcListPic);
305      }
306      loopFiltered[curLayerId] = (nalu.m_nalUnitType == NAL_UNIT_EOS);
307
308      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
309      {
310        m_apcTDecTop[nalu.m_nuhLayerId]->setFirstSliceInSequence(true);
311      }
312    }
313    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
314              m_apcTDecTop[nalu.m_nuhLayerId]->getFirstSliceInSequence () ) 
315    {
316      m_apcTDecTop[nalu.m_nuhLayerId]->setFirstSliceInPicture (true);
317    }
318
319#if SVC_POC
320    if( bNewPicture && m_apcTDecTop[nalu.m_nuhLayerId]->getParseIdc() == 0 )
321    {
322      outputAllPictures( nalu.m_nuhLayerId, true );
323    }
324#endif
325
326    if( pcListPic )
327    {
328      if ( !m_reconFileName[curLayerId].empty() && !openedReconFile[curLayerId] )
329      {
330        const BitDepths& bitDepths = m_apcTDecTop[curLayerId]->getParameterSetManager()->getActiveSPS()->getBitDepths();
331
332        for( UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
333        {
334          if( m_outputBitDepth[curLayerId][channelType] == 0 )
335          {
336            m_outputBitDepth[curLayerId][channelType] = bitDepths.recon[channelType];
337          }
338        }
339        m_apcTVideoIOYuvReconFile[curLayerId]->open( m_reconFileName[curLayerId], true, m_outputBitDepth[curLayerId], m_outputBitDepth[curLayerId], bitDepths.recon ); // write mode
340
341        openedReconFile[curLayerId] = true;
342      }
343#if ALIGNED_BUMPING
344      Bool outputPicturesFlag = true; 
345
346      if( m_apcTDecTop[nalu.m_nuhLayerId]->getNoOutputPriorPicsFlag() )
347      {
348        outputPicturesFlag = false;
349      }
350
351      if (nalu.m_nalUnitType == NAL_UNIT_EOS) // End of sequence
352      {
353        flushAllPictures( nalu.m_nuhLayerId, outputPicturesFlag );       
354      }
355
356#if SVC_POC
357      if( bNewPicture && m_apcTDecTop[nalu.m_nuhLayerId]->getParseIdc() != 0 )
358      // New picture, slice header parsed but picture not decoded
359#else
360      if( bNewPicture ) // New picture, slice header parsed but picture not decoded
361#endif
362      {
363         if(   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
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
367            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP   )
368        {
369          flushAllPictures( nalu.m_nuhLayerId, outputPicturesFlag );
370        }
371        else
372        {
373          this->checkOutputBeforeDecoding( nalu.m_nuhLayerId );
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
383      if ( bNewPicture && bNewPOC &&
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      }
392      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
393      {
394        xFlushOutput( pcListPic, curLayerId );       
395      }
396      // write reconstruction to file
397      if(bNewPicture)
398      {
399        xWriteOutput( pcListPic, curLayerId, nalu.m_temporalId );
400      }
401#endif
402    }
403  }
404#if ALIGNED_BUMPING
405   flushAllPictures( true );   
406#else
407  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
408  {
409    xFlushOutput( m_apcTDecTop[layer]->getListPic(), layer );
410  }
411#endif
412  // delete buffers
413#if AVC_BASE
414  UInt layerIdxmin = m_apcTDecTop[0]->getBLReconFile()->is_open() ? 1 : 0;
415
416  if( streamYUV.is_open() )
417  {
418    streamYUV.close();
419  }
420
421#if CONFORMANCE_BITSTREAM_MODE
422  for(UInt layer = layerIdxmin; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
423#else
424  for(UInt layer = layerIdxmin; layer <= m_tgtLayerId; layer++)
425#endif
426#else
427  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
428#endif
429  {
430    m_apcTDecTop[layer]->deletePicBuffer();
431  }
432
433  // destroy internal classes
434  xDestroyDecLib();
435#else
436  Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
437  Bool loopFiltered = false;
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. */
445#if RExt__DECODER_DEBUG_BIT_STATISTICS
446    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
447    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
448#else
449    streampos location = bitstreamFile.tellg();
450#endif
451    AnnexBStats stats = AnnexBStats();
452
453    InputNALUnit nalu;
454    byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
455
456    // call actual decoding function
457    Bool bNewPicture = false;
458    if (nalu.getBitstream().getFifo().empty())
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    {
469      read(nalu);
470      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
471      {
472        bNewPicture = false;
473      }
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) */
484#if RExt__DECODER_DEBUG_BIT_STATISTICS
485          bitstreamFile.seekg(location);
486          bytestream.reset();
487          TComCodingStatistics::SetStatistics(backupStats);
488#else
489          bitstreamFile.seekg(location-streamoff(3));
490          bytestream.reset();
491#endif
492        }
493      }
494    }
495
496    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
497        !m_cTDecTop.getFirstSliceInSequence () )
498    {
499      if (!loopFiltered || bitstreamFile)
500      {
501        m_cTDecTop.executeLoopFilters(poc, pcListPic);
502      }
503      loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS);
504      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
505      {
506        m_cTDecTop.setFirstSliceInSequence(true);
507      }
508    }
509    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
510              m_cTDecTop.getFirstSliceInSequence () ) 
511    {
512      m_cTDecTop.setFirstSliceInPicture (true);
513    }
514
515    if( pcListPic )
516    {
517      if ( (!m_reconFileName.empty()) && (!openedReconFile) )
518      {
519        const BitDepths &bitDepths=pcListPic->front()->getPicSym()->getSPS().getBitDepths(); // use bit depths of first reconstructed picture.
520        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
521        {
522          if (m_outputBitDepth[channelType] == 0)
523          {
524            m_outputBitDepth[channelType] = bitDepths.recon[channelType];
525          }
526        }
527
528        m_cTVideoIOYuvReconFile.open( m_reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
529        openedReconFile = true;
530      }
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      }
541      if ( bNewPicture &&
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      }
550      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
551      {
552        xWriteOutput( pcListPic, nalu.m_temporalId );
553        m_cTDecTop.setFirstSliceInPicture (false);
554      }
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)
557      {
558        xWriteOutput( pcListPic, nalu.m_temporalId );
559      }
560    }
561  }
562
563  xFlushOutput( pcListPic );
564  // delete buffers
565  m_cTDecTop.deletePicBuffer();
566
567  // destroy internal classes
568  xDestroyDecLib();
569#endif
570}
571
572// ====================================================================================================================
573// Protected member functions
574// ====================================================================================================================
575
576Void TAppDecTop::xCreateDecLib()
577{
578#if SVC_EXTENSION
579  // initialize global variables
580  initROM();
581
582#if CONFORMANCE_BITSTREAM_MODE
583  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
584#else
585  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
586#endif
587  {
588    m_apcTDecTop[layer] = new TDecTop;
589    m_apcTVideoIOYuvReconFile[layer] = new TVideoIOYuv;
590
591    // set layer ID
592    m_apcTDecTop[layer]->setLayerId                      ( layer );
593
594    // create decoder class
595    m_apcTDecTop[layer]->create();
596
597    m_apcTDecTop[layer]->setLayerDec(m_apcTDecTop);
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();
610
611#if CONFORMANCE_BITSTREAM_MODE
612  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
613#else
614  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
615#endif
616  {
617    if ( !m_reconFileName[layer].empty() )
618    {
619      m_apcTVideoIOYuvReconFile[layer]->close();
620    }
621
622    // destroy decoder class
623    m_apcTDecTop[layer]->destroy();
624  }
625#else
626  if ( !m_reconFileName.empty() )
627  {
628    m_cTVideoIOYuvReconFile.close();
629  }
630
631  // destroy decoder class
632  m_cTDecTop.destroy();
633#endif
634  if (m_pcSeiColourRemappingInfoPrevious != NULL)
635  {
636    delete m_pcSeiColourRemappingInfoPrevious;
637    m_pcSeiColourRemappingInfoPrevious = NULL;
638  }
639}
640
641Void TAppDecTop::xInitDecLib()
642{
643  // initialize decoder class
644#if SVC_EXTENSION
645#if CONFORMANCE_BITSTREAM_MODE
646  for(UInt layer = 0; layer < MAX_VPS_LAYER_IDX_PLUS1; layer++)
647#else
648  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
649#endif
650  {
651    TDecTop& m_cTDecTop = *m_apcTDecTop[layer];
652#endif
653
654  m_cTDecTop.init();
655  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
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  }
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 );
670#endif
671    m_cTDecTop.setCommonDecoderParams( &m_commonDecoderParams );
672    m_cTDecTop.setConfModeFlag( m_confModeFlag );
673  }
674#endif
675
676  if (m_pcSeiColourRemappingInfoPrevious != NULL)
677  {
678    delete m_pcSeiColourRemappingInfoPrevious;
679    m_pcSeiColourRemappingInfoPrevious = NULL;
680  }
681}
682
683/** \param pcListPic list of pictures to be written to file
684    \param tId       temporal sub-layer ID
685 */
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{
692  if (pcListPic->empty())
693  {
694    return;
695  }
696
697  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
698  Int numPicsNotYetDisplayed = 0;
699  Int dpbFullness = 0;
700  const TComSPS* activeSPS = &(pcListPic->front()->getPicSym()->getSPS());
701  UInt numReorderPicsHighestTid;
702  UInt maxDecPicBufferingHighestTid;
703  UInt maxNrSublayers = activeSPS->getMaxTLayers();
704
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
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    {
725       numPicsNotYetDisplayed++;
726      dpbFullness++;
727    }
728    else if(pcPic->getSlice( 0 )->isReferenced())
729    {
730      dpbFullness++;
731    }
732    iterPic++;
733  }
734
735  iterPic = pcListPic->begin();
736
737  if (numPicsNotYetDisplayed>2)
738  {
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
754#if SVC_EXTENSION
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) )
759#else
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))
764#endif
765      {
766        // write to file
767        numPicsNotYetDisplayed = numPicsNotYetDisplayed-2;
768#if SVC_EXTENSION
769        if ( !m_reconFileName[layerId].empty() )
770        {
771          const Window &conf = pcPicTop->getConformanceWindow();
772          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
773          const Bool isTff = pcPicTop->isTopField();
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)->getSPS()->getChromaFormatIdc();
789            Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
790
791            m_apcTVideoIOYuvReconFile[layerId]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
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          }
798        }
799
800        // update POC of display order
801        m_aiPOCLastDisplay[layerId] = pcPicBottom->getPOC();
802#else
803        if ( !m_reconFileName.empty() )
804        {
805          const Window &conf = pcPicTop->getConformanceWindow();
806          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
807          const Bool isTff = pcPicTop->isTopField();
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          }
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();
858
859    while (iterPic != pcListPic->end())
860    {
861      pcPic = *(iterPic);
862
863#if SVC_EXTENSION
864      if( pcPic->getOutputMark() && pcPic->getPOC() > m_aiPOCLastDisplay[layerId] &&
865        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) )
866#else
867      if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay &&
868        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
869#endif
870      {
871        // write to file
872         numPicsNotYetDisplayed--;
873        if(pcPic->getSlice(0)->isReferenced() == false)
874        {
875          dpbFullness--;
876        }
877#if SVC_EXTENSION
878        if ( !m_reconFileName[layerId].empty() )
879        {
880          const Window &conf = pcPic->getConformanceWindow();
881          const Window  defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();         
882
883          UInt chromaFormatIdc = pcPic->getSlice(0)->getSPS()->getChromaFormatIdc();
884          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
885
886          m_apcTVideoIOYuvReconFile[layerId]->write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert,
887            conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
888            conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
889            conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
890            conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset(),
891            NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range  );
892        }
893
894        // update POC of display order
895        m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
896#else
897        if ( !m_reconFileName.empty() )
898        {
899          const Window &conf    = pcPic->getConformanceWindow();
900          const Window  defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
901
902          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
903                                         m_outputColourSpaceConvert,
904                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
905                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
906                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
907                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(),
908                                         NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range  );
909        }
910
911        if (!m_colourRemapSEIFileName.empty())
912        {
913          xOutputColourRemapPic(pcPic);
914        }
915
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);
929      }
930
931      iterPic++;
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{
944  if(!pcListPic || pcListPic->empty())
945  {
946    return;
947  }
948  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
949
950  iterPic   = pcListPic->begin();
951  TComPic* pcPic = *(iterPic);
952
953  if (pcPic->isField()) //Field Decoding
954  {
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);
963
964      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) )
965      {
966        // write to file
967#if SVC_EXTENSION
968        if ( !m_reconFileName[layerId].empty() )
969        {
970          const Window &conf = pcPicTop->getConformanceWindow();
971          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
972          const Bool isTff = pcPicTop->isTopField();         
973
974          UInt chromaFormatIdc = pcPic->getSlice(0)->getSPS()->getChromaFormatIdc();
975          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
976
977          m_apcTVideoIOYuvReconFile[layerId]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert,
978            conf.getWindowLeftOffset()  *xScal + defDisp.getWindowLeftOffset(),
979            conf.getWindowRightOffset() *xScal + defDisp.getWindowRightOffset(),
980            conf.getWindowTopOffset()   *yScal + defDisp.getWindowTopOffset(),
981            conf.getWindowBottomOffset()*yScal + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
982        }
983
984        // update POC of display order
985        m_aiPOCLastDisplay[layerId] = pcPicBottom->getPOC();
986#else
987        if ( !m_reconFileName.empty() )
988        {
989          const Window &conf = pcPicTop->getConformanceWindow();
990          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
991          const Bool isTff = pcPicTop->isTopField();
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 );
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)
1031    {
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
1046#if SVC_EXTENSION
1047        if ( !m_reconFileName[layerId].empty() )
1048        {
1049          const Window &conf = pcPic->getConformanceWindow();
1050          const Window  defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();         
1051
1052          UInt chromaFormatIdc = pcPic->getSlice(0)->getSPS()->getChromaFormatIdc();
1053          Int xScal =  TComSPS::getWinUnitX( chromaFormatIdc ), yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1054
1055          m_apcTVideoIOYuvReconFile[layerId]->write( pcPic->getPicYuvRec(),
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 );
1062        }
1063
1064        // update POC of display order
1065        m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
1066#else
1067        if ( !m_reconFileName.empty() )
1068        {
1069          const Window &conf    = pcPic->getConformanceWindow();
1070          const Window  defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
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(),
1077                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(),
1078                                         NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
1079        }
1080
1081        if (!m_colourRemapSEIFileName.empty())
1082        {
1083          xOutputColourRemapPic(pcPic);
1084        }
1085
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);
1099      }
1100#if !SVC_EXTENSION
1101      if(pcPic != NULL)
1102      {
1103        pcPic->destroy();
1104        delete pcPic;
1105        pcPic = NULL;
1106      }
1107#endif
1108      iterPic++;
1109    }
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  }
1127#if SVC_EXTENSION
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))
1129  {
1130    return true;
1131  }
1132#endif
1133  for (std::vector<Int>::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++)
1134  {
1135    if ( nalu->m_nuhLayerId == (*it) )
1136    {
1137      return true;
1138    }
1139  }
1140  return false;
1141}
1142
1143Void TAppDecTop::xOutputColourRemapPic(TComPic* pcPic)
1144{
1145  const TComSPS &sps=pcPic->getPicSym()->getSPS();
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  {
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);
1163  }
1164  else  // using the last CRI SEI received
1165  {
1166    // TODO: prevent persistence of CRI SEI across C(L)VS.
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      }
1173      applyColourRemapping(*pcPic->getPicYuvRec(), *m_pcSeiColourRemappingInfoPrevious, sps);
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
1349  if( !criSEI.m_colourRemapCancelFlag && pic.getChromaFormat()!=CHROMA_400) // 4:0:0 not supported.
1350  {
1351    const Int          iHeight         = pic.getHeight(COMPONENT_Y);
1352    const Int          iWidth          = pic.getWidth(COMPONENT_Y);
1353    const ChromaFormat chromaFormatIDC = pic.getChromaFormat();
1354
1355    TComPicYuv picYuvColourRemapped;
1356    picYuvColourRemapped.createWithoutCUInfo( iWidth, iHeight, chromaFormatIDC );
1357
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
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);
1375    YUVOut[COMPONENT_Y]  = picYuvColourRemapped.getAddr(COMPONENT_Y);
1376    YUVOut[COMPONENT_Cb] = picYuvColourRemapped.getAddr(COMPONENT_Cb);
1377    YUVOut[COMPONENT_Cr] = picYuvColourRemapped.getAddr(COMPONENT_Cr);
1378
1379    const Int bitDepth = criSEI.m_colourRemapBitDepth;
1380    BitDepths        bitDepthsCriFile;
1381    bitDepthsCriFile.recon[CHANNEL_TYPE_LUMA]   = bitDepth;
1382    bitDepthsCriFile.recon[CHANNEL_TYPE_CHROMA] = bitDepth; // Different bitdepth is not implemented
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
1412    const Int scaleShiftOut_neg = abs(bitDepth - maxBitDepth);
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));
1419    const Int maxOutputValue = (1 << bitDepth) - 1;
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);
1434        YUVOut[COMPONENT_Y][x] = std::min(maxOutputValue, (YUVLutB_0 + scaleOut_round) >> scaleShiftOut_neg);
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);
1440          YUVOut[COMPONENT_Cb][xc] = std::min(maxOutputValue, (YUVLutB_1 + scaleOut_round) >> scaleShiftOut_neg);
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);
1444          YUVOut[COMPONENT_Cr][xc] = std::min(maxOutputValue, (YUVLutB_2 + scaleOut_round) >> scaleShiftOut_neg);
1445        }
1446      }
1447
1448      YUVIn[COMPONENT_Y]  += iStrideIn;
1449      YUVOut[COMPONENT_Y] += iStrideOut;
1450      if( !(b420 && !(y&1)) )
1451      {
1452         YUVIn[COMPONENT_Cb]  += iCStrideIn;
1453         YUVIn[COMPONENT_Cr]  += iCStrideIn;
1454         YUVOut[COMPONENT_Cb] += iCStrideOut;
1455         YUVOut[COMPONENT_Cr] += iCStrideOut;
1456      }
1457    }
1458    //Write remapped picture in display order
1459    picYuvColourRemapped.dump( m_colourRemapSEIFileName, bitDepthsCriFile, true );
1460    picYuvColourRemapped.destroy();
1461  }
1462}
1463
1464#if ALIGNED_BUMPING
1465// Function outputs a picture, and marks it as not needed for output.
1466Void TAppDecTop::xOutputAndMarkPic( TComPic *pic, std::string& reconFileName, const Int layerId, Int &pocLastDisplay, DpbStatus &dpbStatus )
1467{
1468  if( !reconFileName.empty() )
1469  {
1470    const Window &conf = pic->getConformanceWindow();
1471    const Window &defDisp = m_respectDefDispWindow ? pic->getDefDisplayWindow() : Window();
1472    Int xScal =  1, yScal = 1;
1473
1474    UInt chromaFormatIdc = pic->getSlice(0)->getSPS()->getChromaFormatIdc();
1475    xScal = TComSPS::getWinUnitX( chromaFormatIdc );
1476    yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1477
1478    TComPicYuv* pPicCYuvRec = pic->getPicYuvRec();
1479    m_apcTVideoIOYuvReconFile[layerId]->write( pPicCYuvRec, m_outputColourSpaceConvert,
1480      conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
1481      conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
1482      conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
1483      conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset() );
1484
1485    if( !m_colourRemapSEIFileName.empty() )
1486    {
1487      xOutputColourRemapPic(pic);
1488    }
1489  }
1490  // update POC of display order
1491  pocLastDisplay = pic->getPOC();
1492
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
1504    dpbStatus.m_numPicsInSubDpb[dpbStatus.m_layerIdToSubDpbIdMap[layerId]]--;
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;
1516    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1517    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1518
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}
1536
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;
1545    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1546    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1547
1548    DpbStatus dpbStatus;
1549
1550    // Find the status of the DPB
1551    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus, false);
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{
1565  for(Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++)
1566  {
1567    markAllPicturesAsErased(i);
1568  }
1569}
1570
1571Void TAppDecTop::markAllPicturesAsErased(Int layerIdx)
1572{
1573  TComList<TComPic*>::iterator  iterPic = m_apcTDecTop[layerIdx]->getListPic()->begin();
1574  Int iSize = Int( m_apcTDecTop[layerIdx]->getListPic()->size() );
1575 
1576  for (Int i = 0; i < iSize; i++ )
1577  {
1578    TComPic* pcPic = *(iterPic++);
1579
1580    if( pcPic )
1581    {
1582      pcPic->destroy();
1583
1584      // pcPic is statically created for the external (AVC) base layer, no need to delete it
1585      if( !m_apcTDecTop[layerIdx]->getParameterSetManager()->getActiveVPS()->getNonHEVCBaseLayerFlag() || layerIdx )
1586      {
1587        delete pcPic;
1588        pcPic = NULL;
1589      }
1590    }
1591  }
1592
1593  m_apcTDecTop[layerIdx]->getListPic()->clear();
1594}
1595
1596Void TAppDecTop::checkOutputBeforeDecoding(Int layerIdx)
1597{   
1598  std::vector<Int>  listOfPocs;
1599  std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1600  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1601
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;
1618
1619  Int subDpbIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx() == 0 ? dpbStatus.m_layerIdToSubDpbIdMap[0] : dpbStatus.m_layerIdToSubDpbIdMap[layerIdx];
1620
1621  findDpbParametersFromVps(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, maxDpbLimit);
1622
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;
1633  std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1634  std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1635
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;
1667
1668  for( Int dpbLayerCtr = 0; dpbLayerCtr < dpbStatus.m_numLayers; dpbLayerCtr++)
1669  {
1670    Int layerId  = dpbStatus.m_targetDecLayerIdList[dpbLayerCtr];
1671
1672    // Check if picture with pocValue is present.
1673    it = find( listOfPocsInEachLayer[layerId].begin(), listOfPocsInEachLayer[layerId].end(), pocValue );
1674    if( it != listOfPocsInEachLayer[layerId].end() )  // picture found.
1675    {
1676      Int picPosition = (Int)std::distance( listOfPocsInEachLayer[layerId].begin(), it );
1677      Int j;
1678      for(j = 0, iterPic = m_apcTDecTop[layerId]->getListPic()->begin(); j < listOfPocsPositionInEachLayer[layerId][picPosition]; j++) // Picture to be output
1679      {
1680        iterPic++;
1681      }
1682      TComPic *pic = *iterPic;
1683
1684      xOutputAndMarkPic( pic, m_reconFileName[layerId], layerId, m_aiPOCLastDisplay[layerId], dpbStatus );
1685
1686#if CONFORMANCE_BITSTREAM_MODE
1687      FILE *fptr;
1688      if( m_confModeFlag )
1689      {
1690        if( m_metadataFileRefresh )
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);
1701
1702        TComPictureHash recon_digest;
1703        Int numChar = calcMD5(*pic->getPicYuvRec(), recon_digest, pic->getSlice(0)->getSPS()->getBitDepths());
1704        fprintf(fptr, "%8d%9d    MD5:%s\n", pic->getLayerId(), pic->getSlice(0)->getPOC(), hashToString(recon_digest, numChar).c_str());
1705        fclose(fptr);
1706      }
1707#endif
1708
1709      listOfPocsInEachLayer[layerId].erase( it );
1710      listOfPocsPositionInEachLayer[layerId].erase( listOfPocsPositionInEachLayer[layerId].begin() + picPosition );
1711      dpbStatus.m_numPicsInSubDpb[dpbStatus.m_layerIdToSubDpbIdMap[layerId]]--;
1712    }
1713  }
1714
1715  dpbStatus.m_numAUsNotDisplayed--;
1716
1717#if CONFORMANCE_BITSTREAM_MODE
1718  if( m_confModeFlag )
1719  {
1720    for( Int dpbLayerCtr = 0; dpbLayerCtr < dpbStatus.m_numLayers; dpbLayerCtr++)
1721    {
1722      Int layerId = dpbStatus.m_targetDecLayerIdList[dpbLayerCtr];
1723      // Output all picutres "decoded" in that layer that have POC less than the current picture
1724      std::vector<TComPic> *layerBuffer = m_apcTDecTop[layerId]->getConfListPic();
1725      // Write all pictures to the file.
1726      if( this->getDecodedYuvLayerRefresh(layerId) )
1727      {
1728        char tempFileName[256];
1729        strcpy(tempFileName, this->getDecodedYuvLayerFileName( layerId ).c_str());
1730
1731        const TComSPS *sps = m_apcTDecTop[layerId]->getParameterSetManager()->getActiveSPS();
1732        const BitDepths &bitDpeths = sps->getBitDepths();
1733        Int bitDepth[] = {bitDpeths.recon[CHANNEL_TYPE_LUMA], bitDpeths.recon[CHANNEL_TYPE_CHROMA]};
1734
1735        m_confReconFile[layerId].open(tempFileName, true, bitDepth, bitDepth, bitDepth ); // write mode
1736        this->setDecodedYuvLayerRefresh( layerId, false );
1737      }
1738
1739      std::vector<TComPic>::iterator itPic;
1740      for(itPic = layerBuffer->begin(); itPic != layerBuffer->end(); itPic++)
1741      {
1742        TComPic checkPic = *itPic;
1743        const Window &conf = checkPic.getConformanceWindow();
1744        const Window &defDisp = m_respectDefDispWindow ? checkPic.getDefDisplayWindow() : Window();
1745        Int xScal = 1, yScal = 1;
1746 
1747        UInt chromaFormatIdc = checkPic.getSlice(0)->getSPS()->getChromaFormatIdc();
1748        xScal = TComSPS::getWinUnitX( chromaFormatIdc );
1749        yScal = TComSPS::getWinUnitY( chromaFormatIdc );
1750 
1751        if( checkPic.getPOC() <= pocValue )
1752        {
1753          TComPicYuv* pPicCYuvRec = checkPic.getPicYuvRec();
1754          m_confReconFile[layerId].write( pPicCYuvRec, m_outputColourSpaceConvert,
1755            conf.getWindowLeftOffset()  * xScal + defDisp.getWindowLeftOffset(),
1756            conf.getWindowRightOffset() * xScal + defDisp.getWindowRightOffset(),
1757            conf.getWindowTopOffset()   * yScal + defDisp.getWindowTopOffset(),
1758            conf.getWindowBottomOffset()* yScal + defDisp.getWindowBottomOffset(),
1759            NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
1760
1761          layerBuffer->erase(itPic);
1762          itPic = layerBuffer->begin();  // Ensure doesn't go to infinite loop
1763          if(layerBuffer->size() == 0)
1764          {
1765            break;
1766          }
1767        }
1768      }
1769    }
1770  }
1771#endif
1772
1773  // Remove the picture from the listOfPocs
1774  listOfPocs.erase( listOfPocs.begin() );
1775}
1776
1777const TComVPS *TAppDecTop::findDpbParametersFromVps(std::vector<Int> const &listOfPocs, std::vector<Int> const *listOfPocsInEachLayer, std::vector<Int> const *listOfPocsPositionInEachLayer, DpbStatus &maxDpbLimit)
1778{
1779  Int targetOutputLsIdx = getCommonDecoderParams()->getTargetOutputLayerSetIdx();
1780  const TComVPS *vps = NULL;
1781
1782  if( targetOutputLsIdx == 0 )   // Only base layer is output
1783  {
1784    const TComSPS *sps = NULL;
1785    assert( listOfPocsInEachLayer[0].size() != 0 );
1786    TComList<TComPic*>::iterator iterPic;
1787    Int j;
1788    for(j = 0, iterPic = m_apcTDecTop[0]->getListPic()->begin(); j < listOfPocsPositionInEachLayer[0][0]; j++) // Picture to be output
1789    {
1790      iterPic++;
1791    }
1792    TComPic *pic = *iterPic;
1793    sps = pic->getSlice(0)->getSPS();   assert( sps->getLayerId() == 0 );
1794    vps = pic->getSlice(0)->getVPS();
1795    Int highestTId = sps->getMaxTLayers() - 1;
1796
1797    maxDpbLimit.m_numAUsNotDisplayed = sps->getNumReorderPics( highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1798    maxDpbLimit.m_maxLatencyIncrease = sps->getMaxLatencyIncreasePlus1( highestTId ) > 0;
1799    if( maxDpbLimit.m_maxLatencyIncrease )
1800    {
1801      maxDpbLimit.m_maxLatencyPictures = sps->getMaxLatencyIncreasePlus1( highestTId ) + sps->getNumReorderPics( highestTId ) - 1;
1802    }
1803    maxDpbLimit.m_numPicsInSubDpb[0] = sps->getMaxDecPicBuffering( highestTId );
1804  }
1805  else
1806  {
1807    // -------------------------------------
1808    // Find the VPS used for the pictures
1809    // -------------------------------------
1810    for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1811    {
1812      if( m_apcTDecTop[i]->getListPic()->empty() )
1813      {
1814        assert( listOfPocsInEachLayer[i].size() == 0 );
1815        continue;
1816      }
1817
1818      std::vector<Int>::const_iterator it;
1819      it = find( listOfPocsInEachLayer[i].begin(), listOfPocsInEachLayer[i].end(), listOfPocs[0] );
1820      TComList<TComPic*>::iterator iterPic;
1821
1822      if( it != listOfPocsInEachLayer[i].end() )
1823      {
1824        Int picPosition = (Int)std::distance( listOfPocsInEachLayer[i].begin(), it );
1825        Int j;
1826
1827        // Picture to be output
1828        for( j = 0, iterPic = m_apcTDecTop[i]->getListPic()->begin(); j < listOfPocsPositionInEachLayer[i][picPosition]; j++ )
1829        {
1830          iterPic++;
1831        }
1832
1833        TComPic *pic = *iterPic;
1834        vps = pic->getSlice(0)->getVPS();
1835        break;
1836      }
1837    }
1838
1839    Int targetLsIdx       = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1840    Int highestTId = vps->getMaxTLayers() - 1;
1841
1842    maxDpbLimit.m_numAUsNotDisplayed = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ); // m_numAUsNotDisplayed is only variable name - stores reorderpics
1843    maxDpbLimit.m_maxLatencyIncrease  = vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) > 0;
1844
1845    if( maxDpbLimit.m_maxLatencyIncrease )
1846    {
1847      maxDpbLimit.m_maxLatencyPictures = vps->getMaxVpsNumReorderPics( targetOutputLsIdx, highestTId ) + vps->getMaxVpsLatencyIncreasePlus1(targetOutputLsIdx, highestTId ) - 1;
1848    }
1849
1850    for(Int i = 0; i < vps->getNumLayersInIdList( targetLsIdx ); i++)
1851    {
1852      maxDpbLimit.m_numPicsInSubDpb[i] = vps->getMaxVpsDecPicBufferingMinus1( targetOutputLsIdx, i, highestTId) + 1;
1853    }
1854    // -------------------------------------
1855  }
1856  return vps;
1857}
1858
1859Void TAppDecTop::emptyUnusedPicturesNotNeededForOutput()
1860{
1861  for( Int layerIdx = 0; layerIdx < MAX_VPS_LAYER_IDX_PLUS1; layerIdx++ )
1862  {
1863    TComList <TComPic*> *pcListPic = m_apcTDecTop[layerIdx]->getListPic();
1864    TComList<TComPic*>::iterator iterPic = pcListPic->begin();
1865    while ( iterPic != pcListPic->end() )
1866    {
1867      TComPic *pic = *iterPic;
1868
1869      assert( pic->getPicSym() );
1870
1871      if( !pic->getSlice(0)->isReferenced() && !pic->getOutputMark() )
1872      {
1873        // Emtpy the picture buffer
1874        pic->setReconMark( false );
1875      }
1876      iterPic++;
1877    }
1878  }
1879}
1880
1881Bool TAppDecTop::ifInvokeBumpingBeforeDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit, const Int layerIdx, const Int subDpbIdx )
1882{
1883  Bool retVal = false;
1884  // Number of reorder picutres
1885  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1886
1887  // Number of pictures in each sub-DPB
1888  retVal |= ( dpbStatus.m_numPicsInSubDpb[subDpbIdx] >= dpbLimit.m_numPicsInSubDpb[subDpbIdx] );
1889
1890  return retVal;
1891}
1892
1893Bool TAppDecTop::ifInvokeBumpingAfterDecoding( const DpbStatus &dpbStatus, const DpbStatus &dpbLimit )
1894{
1895  Bool retVal = false;
1896
1897  // Number of reorder picutres
1898  retVal |= ( dpbStatus.m_numAUsNotDisplayed > dpbLimit.m_numAUsNotDisplayed );
1899
1900  return retVal;
1901}
1902
1903Void TAppDecTop::xFindDPBStatus( std::vector<Int> &listOfPocs
1904                            , std::vector<Int> *listOfPocsInEachLayer
1905                            , std::vector<Int> *listOfPocsPositionInEachLayer
1906                            , DpbStatus &dpbStatus
1907                            , Bool notOutputCurrAu
1908                            )
1909{
1910  const TComVPS *vps = NULL;
1911  dpbStatus.init();
1912
1913  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1914  {
1915    if( m_apcTDecTop[i]->getListPic()->empty() )
1916    {
1917      continue;
1918    }
1919   
1920    // To check # AUs that have at least one picture not output,
1921    // For each layer, populate listOfPOcs if not already present
1922    TComList<TComPic*>::iterator iterPic = m_apcTDecTop[i]->getListPic()->begin();
1923    Int picPositionInList = 0;
1924    while (iterPic != m_apcTDecTop[i]->getListPic()->end())
1925    {
1926      TComPic* pic = *(iterPic);
1927      if( pic->getReconMark() )
1928      {
1929        if( vps == NULL )
1930        {
1931          vps = pic->getSlice(0)->getVPS();
1932        }
1933
1934        if( !(pic->isCurrAu() && notOutputCurrAu ) )
1935        {
1936          std::vector<Int>::iterator it;
1937          if( pic->getOutputMark() ) // && pic->getPOC() > m_aiPOCLastDisplay[i])
1938          {
1939            it = find( listOfPocs.begin(), listOfPocs.end(), pic->getPOC() ); // Check if already included
1940
1941            if( it == listOfPocs.end() )  // New POC value - i.e. new AU - add to the list
1942            {
1943              listOfPocs.push_back( pic->getPOC() );
1944            }
1945            listOfPocsInEachLayer         [i].push_back( pic->getPOC()    );    // POC to be output in each layer
1946            listOfPocsPositionInEachLayer [i].push_back( picPositionInList  );  // For ease of access
1947          }
1948
1949          if( pic->getSlice(0)->isReferenced() || pic->getOutputMark() )
1950          {
1951            dpbStatus.m_numPicsInSubDpb[i]++;  // Count pictures that are "used for reference" or "needed for output"
1952          }
1953        }
1954      }
1955
1956      iterPic++;
1957      picPositionInList++;
1958    }
1959  }
1960
1961#if CONFORMANCE_BITSTREAM_FIX
1962  if (!vps) return;
1963#else
1964  assert( vps != NULL );    // No picture in any DPB?
1965#endif
1966  std::sort( listOfPocs.begin(), listOfPocs.end() );    // Sort in increasing order of POC
1967  Int targetLsIdx = vps->getOutputLayerSetIdx( getCommonDecoderParams()->getTargetOutputLayerSetIdx() );
1968
1969  // Update status
1970  dpbStatus.m_numAUsNotDisplayed = (Int)listOfPocs.size();   // Number of AUs not displayed
1971  dpbStatus.m_numLayers = vps->getNumLayersInIdList( targetLsIdx );
1972
1973  for( Int i = 0; i < dpbStatus.m_numLayers; i++ )
1974  {
1975    dpbStatus.m_layerIdToSubDpbIdMap[vps->getLayerSetLayerIdList(targetLsIdx, i)] = i;
1976    dpbStatus.m_targetDecLayerIdList[i] = vps->getLayerSetLayerIdList(targetLsIdx, i);  // Layer Id stored in a particular sub-DPB
1977  }
1978  dpbStatus.m_numSubDpbs = vps->getNumSubDpbs( targetLsIdx ); 
1979
1980  for( Int i = 0; i < MAX_VPS_LAYER_IDX_PLUS1; i++ )
1981  {
1982    dpbStatus.m_numPicsNotDisplayedInLayer[i] = (Int)listOfPocsInEachLayer[i].size();
1983  }
1984  assert( dpbStatus.m_numAUsNotDisplayed != -1 );
1985} 
1986
1987Void TAppDecTop::outputAllPictures(Int layerId, Bool notOutputCurrPic)
1988{
1989  { // All pictures in the DPB in that layer are to be output; this means other pictures would also be output
1990    std::vector<Int>  listOfPocs;
1991    std::vector<Int>  listOfPocsInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1992    std::vector<Int>  listOfPocsPositionInEachLayer[MAX_VPS_LAYER_IDX_PLUS1];
1993
1994    DpbStatus dpbStatus;
1995
1996    // Find the status of the DPB
1997    xFindDPBStatus(listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus, notOutputCurrPic);
1998
1999    if( listOfPocs.size() )
2000    {
2001      while( listOfPocsInEachLayer[layerId].size() )    // As long as there picture in the layer to be output
2002      {
2003        bumpingProcess( listOfPocs, listOfPocsInEachLayer, listOfPocsPositionInEachLayer, dpbStatus );
2004      }
2005    }
2006  }
2007}
2008#endif //ALIGNED_BUMPING
2009
2010//! \}
Note: See TracBrowser for help on using the repository browser.