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

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

port rev 4257

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