source: 3DVCSoftware/trunk/source/App/TAppDecoder/TAppDecTop.cpp @ 1313

Last change on this file since 1313 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

  • Property svn:eol-style set to native
File size: 38.1 KB
RevLine 
[5]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
[1313]4 * granted under this license.
[5]5 *
[1313]6 * Copyright (c) 2010-2015, ITU/ISO/IEC
[5]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.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]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 */
[2]33
34/** \file     TAppDecTop.cpp
35    \brief    Decoder application class
36*/
37
38#include <list>
[56]39#include <vector>
[2]40#include <stdio.h>
41#include <fcntl.h>
42#include <assert.h>
43
44#include "TAppDecTop.h"
[56]45#include "TLibDecoder/AnnexBread.h"
46#include "TLibDecoder/NALread.h"
[1313]47#if RExt__DECODER_DEBUG_BIT_STATISTICS
48#include "TLibCommon/TComCodingStatistics.h"
49#endif
[2]50
[56]51//! \ingroup TAppDecoder
52//! \{
[2]53
54// ====================================================================================================================
55// Constructor / destructor / initialization / destroy
56// ====================================================================================================================
57
58TAppDecTop::TAppDecTop()
[1313]59#if !NH_MV
[608]60: m_iPOCLastDisplay(-MAX_INT)
61#else
62: m_numDecoders( 0 )
63#endif
[2]64{
[1313]65#if NH_MV
[738]66  for (Int i = 0; i < MAX_NUM_LAYER_IDS; i++) 
67  {
68    m_layerIdToDecIdx[i] = -1; 
69    m_layerInitilizedFlags[i] = false; 
70  }
[608]71#endif
[1313]72#if NH_3D
[608]73    m_pScaleOffsetFile  = 0;
74#endif
[964]75
[1313]76#if NH_MV
[964]77    m_markedForOutput = false; 
78#endif
79
[2]80}
81
82Void TAppDecTop::create()
83{
84}
85
86Void TAppDecTop::destroy()
87{
[1313]88#if NH_MV
89  // destroy internal classes
90  xDestroyDecLib();
91#endif
92
[608]93  if (m_pchBitstreamFile)
94  {
95    free (m_pchBitstreamFile);
96    m_pchBitstreamFile = NULL;
97  }
[1313]98#if NH_MV
[608]99  for (Int decIdx = 0; decIdx < m_numDecoders; decIdx++)
100  {
101    if (m_pchReconFiles[decIdx])
102    {
103      free (m_pchReconFiles[decIdx]);
104      m_pchReconFiles[decIdx] = NULL;
105    }
106  }
107#endif
108  if (m_pchReconFile)
109  {
110    free (m_pchReconFile);
111    m_pchReconFile = NULL;
112  }
[1313]113#if NH_3D
[608]114  if (m_pchScaleOffsetFile)
115  {
116    free (m_pchScaleOffsetFile);
117    m_pchScaleOffsetFile = NULL; 
118  }
119#endif
[2]120}
121
122// ====================================================================================================================
123// Public member functions
124// ====================================================================================================================
125
126/**
127 - create internal class
128 - initialize internal class
129 - until the end of the bitstream, call decoding function in TDecTop class
130 - delete allocated buffers
131 - destroy internal class
132 .
133 */
134Void TAppDecTop::decode()
135{
[608]136  Int                 poc;
[1313]137#if NH_MV
[608]138  poc = -1; 
[77]139#endif
[608]140  TComList<TComPic*>* pcListPic = NULL;
[210]141
[56]142  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
143  if (!bitstreamFile)
144  {
145    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
146    exit(EXIT_FAILURE);
147  }
[1313]148#if NH_3D
[56]149  if( m_pchScaleOffsetFile ) 
150  { 
151    m_pScaleOffsetFile = ::fopen( m_pchScaleOffsetFile, "wt" ); 
152    AOF( m_pScaleOffsetFile ); 
153  }
[608]154#endif
[1313]155
[56]156  InputByteStream bytestream(bitstreamFile);
157
[1313]158  if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-")
159  {
160    m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out);
161    if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good())
162    {
163      fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str());
164      exit(EXIT_FAILURE);
165    }
166  }
167
[608]168  // create & initialize internal classes
169  xCreateDecLib();
170  xInitDecLib  ();
[1313]171#if !NH_MV
[608]172  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
173
174  // main decoder loop
[655]175  Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
[608]176#else
[964]177
[608]178  Int  pocCurrPic        = -MAX_INT;     
179  Int  pocLastPic        = -MAX_INT;   
[964]180
181  Int  layerIdLastPic    = -MAX_INT; 
[608]182  Int  layerIdCurrPic    = 0; 
183
184  Int  decIdxLastPic     = 0; 
185  Int  decIdxCurrPic     = 0; 
186
187  Bool firstSlice        = true; 
188#endif
[1313]189  Bool loopFiltered = false;
[872]190
[56]191  while (!!bitstreamFile)
[2]192  {
[56]193    /* location serves to work around a design fault in the decoder, whereby
194     * the process of reading a new slice that is the first slice of a new frame
195     * requires the TDecTop::decode() method to be called again with the same
196     * nal unit. */
[1313]197#if RExt__DECODER_DEBUG_BIT_STATISTICS
198    TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics());
199    streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes());
200#else
[56]201    streampos location = bitstreamFile.tellg();
[1313]202#endif
203#if NH_MV
[608]204#if ENC_DEC_TRACE
205    Int64 symCount = g_nSymbolCounter;
206#endif
207#endif
[56]208    AnnexBStats stats = AnnexBStats();
[1313]209
[56]210    InputNALUnit nalu;
[1313]211    byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
[56]212
213    // call actual decoding function
[608]214    Bool bNewPicture = false;
[1313]215#if NH_MV
[608]216    Bool newSliceDiffPoc   = false;
217    Bool newSliceDiffLayer = false;
[964]218    Bool sliceSkippedFlag  = false; 
[608]219    Bool allLayersDecoded  = false;     
220#endif
[1313]221    if (nalu.getBitstream().getFifo().empty())
[2]222    {
[56]223      /* this can happen if the following occur:
224       *  - empty input file
225       *  - two back-to-back start_code_prefixes
226       *  - start_code_prefix immediately followed by EOF
227       */
228      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
[2]229    }
230    else
231    {
[1313]232      read(nalu);
233#if NH_MV     
[872]234      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) 
235          || !isNaluWithinTargetDecLayerIdSet(&nalu)
[1313]236          || nalu.m_nuhLayerId > MAX_NUM_LAYER_IDS-1
237          || (nalu.m_nalUnitType == NAL_UNIT_VPS && nalu.m_nuhLayerId > 0)           
238          || (nalu.m_nalUnitType == NAL_UNIT_EOB && nalu.m_nuhLayerId > 0)             
[872]239         ) 
[77]240      {
[608]241        bNewPicture = false;
[738]242        if ( !bitstreamFile )
243        {
244          decIdxLastPic     = decIdxCurrPic; 
245        }
[77]246      }
[210]247      else
[608]248      { 
[1313]249        Int decIdx     = xGetDecoderIdx( nalu.m_nuhLayerId , true );     
250        newSliceDiffLayer = nalu.isSlice() && ( nalu.m_nuhLayerId != layerIdCurrPic ) && !firstSlice;
[738]251        newSliceDiffPoc   = m_tDecTop[decIdx]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[decIdx], newSliceDiffLayer, sliceSkippedFlag );
[608]252        // decode function only returns true when all of the following conditions are true
253        // - poc in particular layer changes
254        // - nalu does not belong to first slice in layer
255        // - nalu.isSlice() == true     
256
[1313]257        bNewPicture       = ( newSliceDiffLayer || newSliceDiffPoc ) && !sliceSkippedFlag; 
258        if ( nalu.isSlice() && firstSlice && !sliceSkippedFlag )       
[964]259        {
[1313]260          layerIdCurrPic = nalu.m_nuhLayerId; 
261          pocCurrPic     = m_tDecTop[decIdx]->getCurrPoc(); 
262          decIdxCurrPic  = decIdx; 
263          firstSlice     = false; 
264
265          /// Use VPS activated by the first slice to determine OLS
266          m_vps = m_tDecTop[decIdx]->getActiveVPS( );
[964]267          if ( m_targetDecLayerIdSetFileEmpty )
[1313]268          {           
[1066]269            if ( m_targetOptLayerSetIdx == -1 )
270            {
[1313]271              m_targetOptLayerSetIdx = m_tDecTop[decIdx]->getTargetOlsIdx(); 
[1066]272            }
[1313]273            else
[1066]274            {
[1313]275              assert( m_tDecTop[decIdx]->getTargetOlsIdx() == m_targetOptLayerSetIdx );
[1066]276            }
277
[1313]278            if ( m_targetOptLayerSetIdx < 0 || m_targetOptLayerSetIdx >= m_vps->getNumOutputLayerSets() )
[1066]279            {
[1313]280              fprintf(stderr, "\ntarget output layer set index must be in the range of 0 to %d, inclusive \n", m_vps->getNumOutputLayerSets() - 1 );           
[1066]281              exit(EXIT_FAILURE);
282            }
[1313]283            m_targetDecLayerIdSet = m_vps->getTargetDecLayerIdList( m_targetOptLayerSetIdx ); 
[964]284          }
[1313]285
[1066]286          if (m_outputVpsInfo )
[872]287          {
[1066]288            m_vps->printScalabilityId();
289            m_vps->printLayerDependencies();
290            m_vps->printLayerSets();
291            m_vps->printPTL(); 
[872]292          }
[1313]293        }       
[608]294
[1313]295        if ( bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS )
[608]296        { 
[964]297          layerIdLastPic    = layerIdCurrPic; 
[1313]298          layerIdCurrPic    = nalu.m_nuhLayerId; 
[608]299          pocLastPic        = pocCurrPic; 
300          pocCurrPic        = m_tDecTop[decIdx]->getCurrPoc(); 
301          decIdxLastPic     = decIdxCurrPic; 
302          decIdxCurrPic     = decIdx; 
[1313]303          allLayersDecoded = ( pocCurrPic != pocLastPic ) && ( nalu.m_nalUnitType != NAL_UNIT_EOS );
[210]304        }
305#else
[608]306      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
[210]307      {
[655]308        bNewPicture = false;
[210]309      }
[608]310      else
[2]311      {
[608]312        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
[56]313#endif
[608]314        if (bNewPicture)
[42]315        {
[56]316          bitstreamFile.clear();
317          /* location points to the current nalunit payload[1] due to the
318           * need for the annexB parser to read three extra bytes.
319           * [1] except for the first NAL unit in the file
320           *     (but bNewPicture doesn't happen then) */
[1313]321#if RExt__DECODER_DEBUG_BIT_STATISTICS
322          bitstreamFile.seekg(location);
323          bytestream.reset();
324          TComCodingStatistics::SetStatistics(backupStats);
325#else
[56]326          bitstreamFile.seekg(location-streamoff(3));
327          bytestream.reset();
[1313]328#endif
[872]329#if H_MV_ENC_DEC_TRAC
[608]330#if ENC_DEC_TRACE
331          const Bool resetCounter = false; 
332          if ( resetCounter )
333          {
334            g_nSymbolCounter  = symCount; // Only reset counter SH becomes traced twice
[210]335          }
[608]336          else
337          {
[872]338            g_disableHLSTrace = true;     // Tracing of second parsing of SH is not carried out
339          }     
[210]340#endif
[608]341#endif
[42]342        }
343      }
[56]344    }
[1313]345
346    if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) &&
347#if NH_MV     
348      !m_tDecTop[decIdxLastPic]->getFirstSliceInSequence () )
349#else
350      !m_cTDecTop.getFirstSliceInSequence () )
351#endif
352
[56]353    {
[872]354      if (!loopFiltered || bitstreamFile)
355      {
[1313]356#if NH_MV
[872]357        assert( decIdxLastPic != -1 ); 
358        m_tDecTop[decIdxLastPic]->endPicDecoding(poc, pcListPic, m_targetDecLayerIdSet );
[964]359        xMarkForOutput( allLayersDecoded, poc, layerIdLastPic ); 
[608]360#else
[872]361        m_cTDecTop.executeLoopFilters(poc, pcListPic);
[608]362#endif
[872]363      }
364      loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS);
[1313]365      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
366      {
367#if NH_MV     
368        m_tDecTop[decIdxLastPic]->setFirstSliceInSequence(true);
369#else
370        m_cTDecTop.setFirstSliceInSequence(true);
371#endif
372      }
[56]373    }
[1313]374    else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
375#if NH_MV     
376              m_tDecTop[decIdxLastPic]->getFirstSliceInSequence () ) 
377#else
378              m_cTDecTop.getFirstSliceInSequence () ) 
379#endif
[964]380    {
[1313]381#if NH_MV     
382      m_tDecTop[decIdxLastPic]->setFirstSliceInPicture (true);
383#else
384      m_cTDecTop.setFirstSliceInPicture (true);
385#endif
[964]386    }
[1313]387
388#if NH_3D
[608]389    if ( allLayersDecoded || !bitstreamFile )
[56]390    {
[608]391      for( Int dI = 0; dI < m_numDecoders; dI++ )
392      {
393        TComPic* picLastCoded = m_ivPicLists.getPic( m_tDecTop[dI]->getLayerId(), pocLastPic );
394        assert( picLastCoded != NULL );       
395        picLastCoded->compressMotion(1);
396      }
397    }
398#endif
399
400    if( pcListPic )
401    {
[1313]402#if NH_MV
[608]403      if ( m_pchReconFiles[decIdxLastPic] && !m_reconOpen[decIdxLastPic] )
404#else
[1313]405      if ( m_pchReconFile && !openedReconFile )
[608]406#endif
[2]407      {
[1313]408        const BitDepths &bitDepths=pcListPic->front()->getPicSym()->getSPS().getBitDepths(); // use bit depths of first reconstructed picture.
409        for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
410        {
411          if (m_outputBitDepth[channelType] == 0)
412          {
413            m_outputBitDepth[channelType] = bitDepths.recon[channelType];
414          }
415        }
416#if NH_MV
417        m_tVideoIOYuvReconFile[decIdxLastPic]->open( m_pchReconFiles[decIdxLastPic], true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
[608]418        m_reconOpen[decIdxLastPic] = true;
[2]419      }
[964]420      // write reconstruction to file
421      if( bNewPicture )
422      {
423        // Bumping after picture has been decoded
424#if ENC_DEC_TRACE
425        g_bJustDoIt = true; 
426        writeToTraceFile( "Bumping after decoding \n", g_decTracePicOutput  );         
427        g_bJustDoIt = false; 
428#endif
429        xWriteOutput( pcListPic, decIdxLastPic, nalu.m_temporalId );
430      }
431      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_tDecTop[decIdxLastPic]->getNoOutputPriorPicsFlag() )
432      {
433        m_tDecTop[decIdxLastPic]->checkNoOutputPriorPics( pcListPic );
434        m_tDecTop[decIdxLastPic]->setNoOutputPriorPicsFlag (false);
435      }
[1313]436
[608]437      if ( bNewPicture && newSliceDiffPoc && 
438#else
[1313]439        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
440        openedReconFile = true;
[608]441      }
[964]442      // write reconstruction to file
443      if( bNewPicture )
444      {
445        xWriteOutput( pcListPic, nalu.m_temporalId );
446      }
447      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() )
448      {
449        m_cTDecTop.checkNoOutputPriorPics( pcListPic );
450        m_cTDecTop.setNoOutputPriorPicsFlag (false);
451      }
[1313]452
453      if ( bNewPicture &&
[964]454#endif
[608]455           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
456            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
457            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
458            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
459            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
460      {
[1313]461#if NH_MV
[608]462        xFlushOutput( pcListPic, decIdxLastPic );
463#else
464        xFlushOutput( pcListPic );
465#endif
466      }
[872]467      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
468      {
[1313]469#if NH_MV
470        xWriteOutput( pcListPic, decIdxCurrPic, nalu.m_temporalId );
[964]471#else
[1313]472        xWriteOutput( pcListPic, nalu.m_temporalId );
[964]473#endif
[1313]474#if NH_MV
475        m_tDecTop[decIdxCurrPic]->setFirstSliceInPicture (false);
[872]476#else
[1313]477        m_cTDecTop.setFirstSliceInPicture (false);
[872]478#endif
479      }
[1313]480      // write reconstruction to file -- for additional bumping as defined in C.5.2.3
481#if NH_MV
[964]482      // Above comment seems to be wrong
483#endif
484      if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31)
[2]485      {
[1313]486#if NH_MV       
[964]487        // Bumping after reference picture set has been applied (here after first vcl nalu.
488#if ENC_DEC_TRACE
489        g_bJustDoIt = true; 
490        writeToTraceFile( "Bumping after reference picture set has been applied \n", g_decTracePicOutput  );         
491        g_bJustDoIt = false; 
492#endif
493
494        xWriteOutput( m_tDecTop[decIdxCurrPic]->getListPic(), decIdxCurrPic, nalu.m_temporalId );
495#else
496        xWriteOutput( pcListPic, nalu.m_temporalId );
497#endif
[2]498      }
499    }
[608]500  }
[1313]501#if NH_MV
502#if NH_3D
[57]503  if( m_cCamParsCollector.isInitialized() )
504  {
505    m_cCamParsCollector.setSlice( 0 );
506  }
[608]507#endif
508  for(UInt decIdx = 0; decIdx < m_numDecoders; decIdx++)
[2]509  {
[608]510    xFlushOutput( m_tDecTop[decIdx]->getListPic(), decIdx );
511  }
[964]512#else 
[608]513  xFlushOutput( pcListPic );
514  // delete buffers
515  m_cTDecTop.deletePicBuffer();
516  // destroy internal classes
[2]517  xDestroyDecLib();
[1313]518#endif
[2]519}
520
521// ====================================================================================================================
522// Protected member functions
523// ====================================================================================================================
524
[608]525Void TAppDecTop::xCreateDecLib()
526{
[1313]527#if NH_MV
[608]528  // initialize global variables
529  initROM(); 
[1313]530#if NH_3D_DMM
[608]531  initWedgeLists();
532#endif
533#else
534  // create decoder class
535  m_cTDecTop.create();
536#endif
537}
538
[2]539Void TAppDecTop::xDestroyDecLib()
540{
[1313]541#if NH_MV
[608]542  // destroy ROM
543  destroyROM();
[2]544
[608]545  for(Int decIdx = 0; decIdx < m_numDecoders ; decIdx++)
[2]546  {
[608]547    if( m_tVideoIOYuvReconFile[decIdx] )
[56]548    {
[608]549      m_tVideoIOYuvReconFile[decIdx]->close();
550      delete m_tVideoIOYuvReconFile[decIdx]; 
551      m_tVideoIOYuvReconFile[decIdx] = NULL ;
[56]552    }
[2]553
[608]554    if( m_tDecTop[decIdx] )
[56]555    {
[608]556      m_tDecTop[decIdx]->deletePicBuffer();
557      m_tDecTop[decIdx]->destroy() ;
[56]558    }
[608]559    delete m_tDecTop[decIdx] ; 
560    m_tDecTop[decIdx] = NULL ;
[2]561  }
[608]562#else
563  if ( m_pchReconFile )
564  {
565    m_cTVideoIOYuvReconFile. close();
566  }
[1313]567
[608]568  // destroy decoder class
569  m_cTDecTop.destroy();
570#endif
[1313]571#if NH_3D
[57]572  m_cCamParsCollector.uninit();
573  if( m_pScaleOffsetFile ) 
574  { 
575    ::fclose( m_pScaleOffsetFile ); 
576  }
[608]577#endif
[56]578}
[2]579
[608]580Void TAppDecTop::xInitDecLib()
[56]581{
[1313]582
583#if NH_3D
584  m_cCamParsCollector.setCodeScaleOffsetFile( m_pScaleOffsetFile );
585#endif
586#if !NH_MV
[608]587  // initialize decoder class
588  m_cTDecTop.init();
589  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
[1313]590#if O0043_BEST_EFFORT_DECODING
591  m_cTDecTop.setForceDecodeBitDepth(m_forceDecodeBitDepth);
[608]592#endif
[1313]593  if (!m_outputDecodedSEIMessagesFilename.empty())
594  {
595    std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout;
596    m_cTDecTop.setDecodedSEIMessageOutputStream(&os);
597  }
598#endif
[608]599}
600
601/** \param pcListPic list of pictures to be written to file
[1313]602    \param tId       temporal sub-layer ID
[608]603 */
[1313]604#if NH_MV
[608]605Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int decIdx, Int tId )
606#else
607Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId )
608#endif
609{
[872]610  if (pcListPic->empty())
611  {
612    return;
613  }
614
[56]615  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
[655]616  Int numPicsNotYetDisplayed = 0;
[964]617  Int dpbFullness = 0;
[1313]618  const TComSPS* activeSPS = &(pcListPic->front()->getPicSym()->getSPS());
619
[964]620  UInt numReorderPicsHighestTid;
621  UInt maxDecPicBufferingHighestTid;
622  UInt maxNrSublayers = activeSPS->getMaxTLayers();
623
624  if(m_iMaxTemporalLayer == -1 || m_iMaxTemporalLayer >= maxNrSublayers)
625  {
626    numReorderPicsHighestTid = activeSPS->getNumReorderPics(maxNrSublayers-1);
627    maxDecPicBufferingHighestTid =  activeSPS->getMaxDecPicBuffering(maxNrSublayers-1); 
628  }
629  else
630  {
631    numReorderPicsHighestTid = activeSPS->getNumReorderPics(m_iMaxTemporalLayer);
632    maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(m_iMaxTemporalLayer); 
633  }
[1313]634
[56]635  while (iterPic != pcListPic->end())
[2]636  {
[56]637    TComPic* pcPic = *(iterPic);
[1313]638#if NH_MV
[608]639    if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[decIdx])
640#else
641    if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay)
642#endif
[56]643    {
[1313]644       numPicsNotYetDisplayed++;
[964]645      dpbFullness++;
[56]646    }
[964]647    else if(pcPic->getSlice( 0 )->isReferenced())
648    {
649      dpbFullness++;
650    }
[56]651    iterPic++;
[2]652  }
[1313]653
654  iterPic = pcListPic->begin();
655
[655]656  if (numPicsNotYetDisplayed>2)
657  {
658    iterPic++;
659  }
[1313]660
[655]661  TComPic* pcPic = *(iterPic);
662  if (numPicsNotYetDisplayed>2 && pcPic->isField()) //Field Decoding
[2]663  {
[655]664    TComList<TComPic*>::iterator endPic   = pcListPic->end();
665    endPic--;
666    iterPic   = pcListPic->begin();
667    while (iterPic != endPic)
668    {
669      TComPic* pcPicTop = *(iterPic);
670      iterPic++;
671      TComPic* pcPicBottom = *(iterPic);
[1313]672
673#if NH_MV
674      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() &&
675        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) &&
676        (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) &&
677        (pcPicTop->getPOC() == m_pocLastDisplay[decIdx]+1 || m_pocLastDisplay[decIdx] < 0))
[608]678#else
[964]679      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() &&
680          (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) &&
681          (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) &&
682          (pcPicTop->getPOC() == m_iPOCLastDisplay+1 || m_iPOCLastDisplay < 0))
[608]683#endif
[655]684      {
685        // write to file
686        numPicsNotYetDisplayed = numPicsNotYetDisplayed-2;
[1313]687#if NH_MV
[608]688      if ( m_pchReconFiles[decIdx] )
689#else
[655]690        if ( m_pchReconFile )
[608]691#endif
[655]692        {
693          const Window &conf = pcPicTop->getConformanceWindow();
[1313]694          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
695          const Bool isTff = pcPicTop->isTopField();
[655]696
[1313]697          Bool display = true;
698          if( m_decodedNoDisplaySEIEnabled )
699          {
700            SEIMessages noDisplay = getSeisByType(pcPic->getSEIs(), SEI::NO_DISPLAY );
701            const SEINoDisplay *nd = ( noDisplay.size() > 0 ) ? (SEINoDisplay*) *(noDisplay.begin()) : NULL;
702            if( (nd != NULL) && nd->m_noDisplay )
703            {
704              display = false;
705            }
706          }
707
708          if (display)
709          {
710#if NH_MV
[622]711        assert( conf   .getScaledFlag() );
712        assert( defDisp.getScaledFlag() );
[976]713#if ENC_DEC_TRACE
[964]714        g_bJustDoIt = true; 
715        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
716        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
717        g_bJustDoIt = false; 
718#endif
[655]719        m_tVideoIOYuvReconFile[decIdx]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
720#else
[1313]721        m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
[622]722#endif
[1313]723                                           m_outputColourSpaceConvert,
724                                           conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
725                                           conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
726                                           conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
727#if NH_3D
728                                           conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), m_depth420OutputFlag && pcPicTop->getIsDepth() ? CHROMA_420 : NUM_CHROMA_FORMAT, isTff );
729#else
730                                           conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
731#endif
732          }
[655]733        }
[1313]734
[655]735        // update POC of display order
[1313]736#if NH_MV
[655]737        m_pocLastDisplay[decIdx] = pcPic->getPOC();
[608]738#else
[655]739        m_iPOCLastDisplay = pcPicBottom->getPOC();
[608]740#endif
[1313]741
[655]742        // erase non-referenced picture in the reference picture list after display
743        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
744        {
745          pcPicTop->setReconMark(false);
[1313]746
[655]747          // mark it should be extended later
748          pcPicTop->getPicYuvRec()->setBorderExtension( false );
749        }
750        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
751        {
752          pcPicBottom->setReconMark(false);
[1313]753
[655]754          // mark it should be extended later
755          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
756        }
757        pcPicTop->setOutputMark(false);
758        pcPicBottom->setOutputMark(false);
[56]759      }
[655]760    }
761  }
762  else if (!pcPic->isField()) //Frame Decoding
763  {
764    iterPic = pcListPic->begin();
[1313]765
[655]766    while (iterPic != pcListPic->end())
767    {
768      pcPic = *(iterPic);
769
[1313]770#if NH_MV
[964]771      if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[decIdx] &&
772        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
[655]773#else     
[964]774      if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay &&
775        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
[655]776#endif
777      {
778        // write to file
[1313]779         numPicsNotYetDisplayed--;
[964]780        if(pcPic->getSlice(0)->isReferenced() == false)
781        {
782          dpbFullness--;
783        }
[1313]784#if NH_MV
[655]785      if ( m_pchReconFiles[decIdx] )
[608]786#else
[655]787        if ( m_pchReconFile )
[608]788#endif
[655]789        {
[1313]790          const Window &conf    = pcPic->getConformanceWindow();
791          const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
792#if NH_MV
[655]793        assert( conf   .getScaledFlag() );
794        assert( defDisp.getScaledFlag() );
[964]795#if ENC_DEC_TRACE
796        g_bJustDoIt = true; 
797        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
798        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
799        g_bJustDoIt = false; 
800#endif
[655]801        m_tVideoIOYuvReconFile[decIdx]->write( pcPic->getPicYuvRec(),
802#else
803          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
804#endif
[1313]805                                         m_outputColourSpaceConvert,
806                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
807                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
808                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
809                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), 
810#if NH_3D
811                                          m_depth420OutputFlag && pcPic->getIsDepth() ? CHROMA_420 : NUM_CHROMA_FORMAT,
812#else
813                                          NUM_CHROMA_FORMAT,
814#endif
815           m_bClipOutputVideoToRec709Range   );
[655]816        }
[1313]817
[655]818        // update POC of display order
[1313]819#if NH_MV
[655]820        m_pocLastDisplay[decIdx] = pcPic->getPOC();
821#else
822        m_iPOCLastDisplay = pcPic->getPOC();
823#endif
[1313]824
[655]825        // erase non-referenced picture in the reference picture list after display
826        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
827        {
828          pcPic->setReconMark(false);
[1313]829
[655]830          // mark it should be extended later
831          pcPic->getPicYuvRec()->setBorderExtension( false );
832        }
833        pcPic->setOutputMark(false);
[1313]834#if NH_MV
[964]835        pcPic->setPicOutputFlag(false);
836#endif
[56]837      }
[1313]838
[655]839      iterPic++;
[56]840    }
[2]841  }
842}
[1313]843
[2]844/** \param pcListPic list of pictures to be written to file
845 */
[1313]846#if NH_MV
[608]847Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int decIdx )
848#else
849Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic )
850#endif
[2]851{
[872]852  if(!pcListPic || pcListPic->empty())
[56]853  {
854    return;
[655]855  }
[2]856  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
[1313]857
[56]858  iterPic   = pcListPic->begin();
[655]859  TComPic* pcPic = *(iterPic);
[1313]860
[655]861  if (pcPic->isField()) //Field Decoding
[2]862  {
[655]863    TComList<TComPic*>::iterator endPic   = pcListPic->end();
864    endPic--;
865    TComPic *pcPicTop, *pcPicBottom = NULL;
866    while (iterPic != endPic)
[2]867    {
[655]868      pcPicTop = *(iterPic);
869      iterPic++;
870      pcPicBottom = *(iterPic);
[1313]871
[655]872      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) )
873      {
874        // write to file
[1313]875#if NH_MV
[608]876      if ( m_pchReconFiles[decIdx] )
877#else
[655]878        if ( m_pchReconFile )
[608]879#endif
[655]880        {
881          const Window &conf = pcPicTop->getConformanceWindow();
[1313]882          const Window  defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
[655]883          const Bool isTff = pcPicTop->isTopField();
[1313]884#if NH_MV
[622]885        assert( conf   .getScaledFlag() );
886        assert( defDisp.getScaledFlag() );
[964]887#if ENC_DEC_TRACE
888        g_bJustDoIt = true; 
889        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
890        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
891        g_bJustDoIt = false; 
892#endif
[655]893        m_tVideoIOYuvReconFile[decIdx]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
894#else
895          m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
[622]896#endif
[1313]897                                         m_outputColourSpaceConvert,
898                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
899                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
900                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
901#if NH_3D
902                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), m_depth420OutputFlag && pcPicTop->getIsDepth() ? CHROMA_420 : NUM_CHROMA_FORMAT, isTff );
903#else
904                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff );
905#endif
[655]906        }
[1313]907
[655]908        // update POC of display order
[1313]909#if NH_MV
[655]910      m_pocLastDisplay[decIdx] = pcPic->getPOC();
[608]911#else
[1313]912        m_iPOCLastDisplay = pcPicBottom->getPOC();
[655]913#endif       
914        // erase non-referenced picture in the reference picture list after display
915        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
916        {
917          pcPicTop->setReconMark(false);
[1313]918
[655]919          // mark it should be extended later
920          pcPicTop->getPicYuvRec()->setBorderExtension( false );
921        }
922        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
923        {
924          pcPicBottom->setReconMark(false);
[1313]925
[655]926          // mark it should be extended later
927          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
928        }
929        pcPicTop->setOutputMark(false);
930        pcPicBottom->setOutputMark(false);
[1313]931
[655]932        if(pcPicTop)
933        {
934          pcPicTop->destroy();
935          delete pcPicTop;
936          pcPicTop = NULL;
937        }
[2]938      }
[655]939    }
940    if(pcPicBottom)
941    {
942      pcPicBottom->destroy();
943      delete pcPicBottom;
944      pcPicBottom = NULL;
945    }
946  }
947  else //Frame decoding
948  {
949    while (iterPic != pcListPic->end())
950    {
951      pcPic = *(iterPic);
[1313]952
[655]953      if ( pcPic->getOutputMark() )
954      {
955        // write to file
[1313]956#if NH_MV
[655]957      if ( m_pchReconFiles[decIdx] )
958#else
959        if ( m_pchReconFile )
960#endif
961        {
[1313]962          const Window &conf    = pcPic->getConformanceWindow();
963          const Window  defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
964#if NH_MV
[655]965        assert( conf   .getScaledFlag() );
966        assert( defDisp.getScaledFlag() );
[964]967#if ENC_DEC_TRACE
968        g_bJustDoIt = true; 
969        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
970        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
971        g_bJustDoIt = false; 
972#endif
[655]973        m_tVideoIOYuvReconFile[decIdx]->write( pcPic->getPicYuvRec(),
974#else
975          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
976#endif
[1313]977                                         m_outputColourSpaceConvert,
978                                         conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
979                                         conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
980                                         conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
981                                         conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), 
982#if NH_3D
983                                         m_depth420OutputFlag && pcPic->getIsDepth() ? CHROMA_420 : NUM_CHROMA_FORMAT
984#else
985                                         NUM_CHROMA_FORMAT
986#endif
987                                         , m_bClipOutputVideoToRec709Range);
[655]988        }
[1313]989
[655]990        // update POC of display order
[1313]991#if NH_MV
[608]992      m_pocLastDisplay[decIdx] = pcPic->getPOC();
993#else
[655]994        m_iPOCLastDisplay = pcPic->getPOC();
[608]995#endif
[1313]996
[655]997        // erase non-referenced picture in the reference picture list after display
998        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
999        {
1000          pcPic->setReconMark(false);
[1313]1001
[655]1002          // mark it should be extended later
1003          pcPic->getPicYuvRec()->setBorderExtension( false );
1004        }
1005        pcPic->setOutputMark(false);
[1313]1006#if NH_MV
[964]1007        pcPic->setPicOutputFlag(false);
1008#endif
[2]1009      }
[1313]1010#if !NH_MV
1011      if(pcPic != NULL)
[655]1012      {
1013        pcPic->destroy();
1014        delete pcPic;
1015        pcPic = NULL;
1016      }
1017#endif
1018      iterPic++;
[608]1019    }
[2]1020  }
[1313]1021#if NH_MV
[608]1022  m_pocLastDisplay[decIdx] = -MAX_INT;
1023#else
[56]1024  pcListPic->clear();
[608]1025  m_iPOCLastDisplay = -MAX_INT;
1026#endif
[2]1027}
[608]1028
1029/** \param nalu Input nalu to check whether its LayerId is within targetDecLayerIdSet
1030 */
1031Bool TAppDecTop::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu )
[2]1032{
[608]1033  if ( m_targetDecLayerIdSet.size() == 0 ) // By default, the set is empty, meaning all LayerIds are allowed
[2]1034  {
[608]1035    return true;
[2]1036  }
[608]1037  for (std::vector<Int>::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++)
1038  {
[1313]1039#if NH_MV
1040    if ( nalu->m_nuhLayerId == (*it) )
[81]1041#else
[1313]1042    if ( nalu->m_nuhLayerId == (*it) )
[81]1043#endif
[56]1044    {
[608]1045      return true;
[56]1046    }
1047  }
[608]1048  return false;
[2]1049}
1050
[1313]1051#if NH_MV
[608]1052Int TAppDecTop::xGetDecoderIdx( Int layerId, Bool createFlag /*= false */ )
1053{
1054  Int decIdx = -1; 
[738]1055
1056  if ( layerId > MAX_NUM_LAYER_IDS-1 ) 
1057  {
1058    return decIdx; 
1059  }
1060
[608]1061  if ( m_layerIdToDecIdx[ layerId ] != -1 ) 
1062  {     
1063    decIdx = m_layerIdToDecIdx[ layerId ]; 
[210]1064  }
1065  else
[608]1066  {     
1067    assert ( createFlag ); 
1068    assert( m_numDecoders < MAX_NUM_LAYERS ); 
[210]1069
[608]1070    decIdx = m_numDecoders; 
1071
1072    // Init decoder
1073    m_tDecTop[ decIdx ] =  new TDecTop;
1074    m_tDecTop[ decIdx ]->create();
1075    m_tDecTop[ decIdx ]->init( );
1076    m_tDecTop[ decIdx ]->setLayerId( layerId );
1077    m_tDecTop[ decIdx ]->setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
1078    m_tDecTop[ decIdx ]->setIvPicLists( &m_ivPicLists ); 
[738]1079    m_tDecTop[ decIdx ]->setLayerInitilizedFlags( m_layerInitilizedFlags );
[1313]1080    m_tDecTop[ decIdx ]->setTargetOlsIdx( m_targetOptLayerSetIdx );   
1081#if O0043_BEST_EFFORT_DECODING
1082    m_cTDecTop[ decIdx ]->setForceDecodeBitDepth(m_forceDecodeBitDepth);
[1179]1083#endif
[1313]1084    if (!m_outputDecodedSEIMessagesFilename.empty())
1085    {
1086      std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout;
1087      m_tDecTop[ decIdx ]->setDecodedSEIMessageOutputStream(&os);
1088    }
1089#if NH_3D
[608]1090   m_tDecTop[ decIdx ]->setCamParsCollector( &m_cCamParsCollector );
[210]1091#endif
[2]1092
[608]1093    // append pic list of new decoder to PicLists
1094    assert( m_ivPicLists.size() == m_numDecoders );
1095    m_ivPicLists.push_back( m_tDecTop[ decIdx ]->getListPic() );
[2]1096
[608]1097    // create recon file related stuff     
1098    Char* pchTempFilename = NULL;
1099    if ( m_pchReconFile )
1100    {     
1101      Char buffer[4];     
1102      sprintf(buffer,"_%i", layerId );
1103      assert ( m_pchReconFile ); 
1104      xAppendToFileNameEnd( m_pchReconFile , buffer, pchTempFilename );
1105      assert( m_pchReconFiles.size() == m_numDecoders );
[2]1106    }
[210]1107
[608]1108    m_pchReconFiles.push_back( pchTempFilename );   
[296]1109
[608]1110    m_tVideoIOYuvReconFile[ decIdx ] = new TVideoIOYuv;
1111    m_reconOpen           [ decIdx ] = false;
[443]1112
[608]1113    // set others
1114    m_pocLastDisplay      [ decIdx ] = -MAX_INT;
1115    m_layerIdToDecIdx     [ layerId ] = decIdx; 
[296]1116
[608]1117    m_numDecoders++; 
1118  };
1119  return decIdx;
[964]1120
[296]1121}
[964]1122
1123Void TAppDecTop::xMarkForOutput( Bool allLayersDecoded, Int pocLastPic, Int layerIdLastPic )
1124{ 
1125  vector<Int> targetOptLayerIdList = m_vps->getTargetOptLayerIdList( m_targetOptLayerSetIdx );
1126
1127  if (m_vps->getAltOutputLayerFlagVar( m_targetOptLayerSetIdx ) )
1128  {
1129    assert( targetOptLayerIdList.size() == 1 ); 
1130    Int targetLayerId = targetOptLayerIdList[0];     
1131
1132    TComPic* curPic = m_ivPicLists.getPic( layerIdLastPic, pocLastPic );
1133    assert( curPic != NULL );
1134
1135    if ( layerIdLastPic == targetLayerId )
1136    {
1137      if ( curPic->getPicOutputFlag() )
1138      {
1139        curPic->setOutputMark( true );
1140      }
1141      else
1142      {       
1143        xMarkAltOutPic( targetLayerId, pocLastPic ); 
1144      }
1145      m_markedForOutput = true; 
1146    }
1147    else if ( ( layerIdLastPic > targetLayerId || allLayersDecoded ) && !m_markedForOutput )
1148    {
1149      xMarkAltOutPic( targetLayerId, pocLastPic );
1150    }
1151
1152    if ( allLayersDecoded )
1153    {
1154      m_markedForOutput = false; 
1155    }
1156  }
1157  else
1158  { 
1159    for( Int dI = 0; dI < m_numDecoders; dI++ )
1160    {     
1161      Int layerId = m_tDecTop[dI]->getLayerId(); 
1162      TComPic* curPic = m_ivPicLists.getPic( layerId, pocLastPic );
1163      if ( curPic != NULL )
1164      {
1165        if ( curPic->getReconMark() )
1166        {
1167          Bool isTargetOptLayer = std::find(targetOptLayerIdList.begin(), targetOptLayerIdList.end(), layerId) != targetOptLayerIdList.end();
1168          curPic->setOutputMark( isTargetOptLayer ? curPic->getPicOutputFlag() : false ); 
1169        }
1170      }
1171    }
1172  }
1173}
[976]1174
1175Void TAppDecTop::xMarkAltOutPic( Int targetOutputLayer, Int pocLastPic )
1176{
1177  Int optLayerIdxInVps = m_vps->getLayerIdInNuh( targetOutputLayer ); 
1178  Int highestNuhLayerId = -1; 
1179  TComPic* picWithHighestNuhLayerId = NULL; 
1180  for (Int dIdx = 0; dIdx < m_numDecoders; dIdx++)
1181  {
1182    Int curLayerId = m_tDecTop[dIdx]->getLayerId();
1183    Int curLayerIdxInVps = m_vps->getLayerIdInNuh( curLayerId  ); 
[1066]1184    if ( m_vps->getDependencyFlag(optLayerIdxInVps, curLayerIdxInVps ) )
[976]1185    {
1186      TComPic* curPic = m_ivPicLists.getPic( curLayerId, pocLastPic ); 
1187      if (curPic != NULL)
1188      {
1189        if (curPic->getReconMark() && curPic->getPicOutputFlag() )
1190        {
1191          curPic->setOutputMark   ( false ); 
1192          curPic->setPicOutputFlag( false ); 
1193          if ( curLayerId > highestNuhLayerId)
1194          {
1195            highestNuhLayerId = curLayerId ; 
1196            picWithHighestNuhLayerId = curPic; 
1197          }           
1198        }
1199      }
1200    }
1201  }
1202  if ( picWithHighestNuhLayerId != NULL )
1203  {
1204    picWithHighestNuhLayerId->setPicOutputFlag(true); 
1205    picWithHighestNuhLayerId->setOutputMark   (true); 
1206  }
1207}
1208
[296]1209#endif
[56]1210//! \}
Note: See TracBrowser for help on using the repository browser.