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

Last change on this file since 1219 was 1210, checked in by seregin, 10 years ago

macro cleanup: POC_RESET_IDC_DECODER, POC_RESET_IDC

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