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

Last change on this file since 1327 was 1323, checked in by seregin, 10 years ago

port rev 4401

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