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

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