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

Last change on this file since 81 was 81, checked in by tech, 13 years ago

Bug fixes:

  • Residual Prediction
  • VPS
  • VSO
  • Renderer
  • Property svn:eol-style set to native
File size: 16.8 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 *
[56]6 * Copyright (c) 2010-2012, 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()
56{
57  ::memset (m_abDecFlag, 0, sizeof (m_abDecFlag));
[56]58  m_useDepth = false;
[57]59  m_pScaleOffsetFile  = 0;
[2]60}
61
62Void TAppDecTop::create()
63{
64}
65
66Void TAppDecTop::destroy()
67{
68}
69
70// ====================================================================================================================
71// Public member functions
72// ====================================================================================================================
73
74/**
75 - create internal class
76 - initialize internal class
77 - until the end of the bitstream, call decoding function in TDecTop class
78 - delete allocated buffers
79 - destroy internal class
80 .
81 */
82Void TAppDecTop::decode()
83{
[77]84#if VIDYO_VPS_INTEGRATION
85  increaseNumberOfViews( 0, 0, 0 );
86#else
[56]87  increaseNumberOfViews( 1 );
[77]88#endif
89 
[56]90#if SONY_COLPIC_AVAILABILITY
91  m_tDecTop[0]->setViewOrderIdx(0);
[2]92#endif
[56]93  Int                 viewDepthId = 0;
94  Int                 previousViewDepthId  = 0;
95  UInt                uiPOC[MAX_VIEW_NUM*2];
96  TComList<TComPic*>* pcListPic[MAX_VIEW_NUM*2];
97  Bool                newPicture[MAX_VIEW_NUM*2];
98  Bool                previousPictureDecoded = false;
99  for( Int i = 0; i < MAX_VIEW_NUM*2; i++ )
100  {
101    uiPOC[i] = 0;
102    pcListPic[i] = NULL;
103    newPicture[i] = false;
104  }
[2]105
[56]106  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
107  if (!bitstreamFile)
108  {
109    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
110    exit(EXIT_FAILURE);
111  }
[2]112
[56]113  if( m_pchScaleOffsetFile ) 
114  { 
115    m_pScaleOffsetFile = ::fopen( m_pchScaleOffsetFile, "wt" ); 
116    AOF( m_pScaleOffsetFile ); 
117  }
118  m_cCamParsCollector.init( m_pScaleOffsetFile );
119
120  InputByteStream bytestream(bitstreamFile);
121
122  while (!!bitstreamFile)
[2]123  {
[56]124    /* location serves to work around a design fault in the decoder, whereby
125     * the process of reading a new slice that is the first slice of a new frame
126     * requires the TDecTop::decode() method to be called again with the same
127     * nal unit. */
128    streampos location = bitstreamFile.tellg();
129    AnnexBStats stats = AnnexBStats();
130    vector<uint8_t> nalUnit;
131    InputNALUnit nalu;
132    byteStreamNALUnit(bytestream, nalUnit, stats);
133
134    // call actual decoding function
135    if (nalUnit.empty())
[2]136    {
[56]137      /* this can happen if the following occur:
138       *  - empty input file
139       *  - two back-to-back start_code_prefixes
140       *  - start_code_prefix immediately followed by EOF
141       */
142      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
[2]143    }
144    else
145    {
[56]146      read(nalu, nalUnit);
[77]147#if VIDYO_VPS_INTEGRATION
148      Int viewId = 0;
149      Int depth = 0;
150     
151      if(nalu.m_nalUnitType != NAL_UNIT_VPS || nalu.m_layerId)
152      {
153        // code assumes that the first nal unit is VPS
154        // currently, this is a hack that requires non-first VPSs have non-zero layer_id
155        viewId = getVPSAccess()->getActiveVPS()->getViewId(nalu.m_layerId);
156        depth = getVPSAccess()->getActiveVPS()->getDepthFlag(nalu.m_layerId);
157      }
158      viewDepthId = nalu.m_layerId;   // coding order T0D0T1D1T2D2
159#else
[56]160      Int viewId = nalu.m_viewId;
161      Int depth = nalu.m_isDepth ? 1 : 0;
162      viewDepthId = viewId * 2 + depth;   // coding order T0D0T1D1T2D2
[77]163#endif
164     
[56]165      newPicture[viewDepthId] = false;
166      if( viewDepthId >= m_tDecTop.size() )     
[2]167      {
[77]168#if VIDYO_VPS_INTEGRATION
169        increaseNumberOfViews( viewDepthId, viewId, depth );
170#else
[56]171        increaseNumberOfViews( viewDepthId +1 );
[77]172#endif   
[2]173      }
[56]174      if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer)
[2]175      {
[56]176        previousPictureDecoded = false; 
[2]177      }
[56]178      if(m_tDecTop.size() > 1 && (viewDepthId != previousViewDepthId) && previousPictureDecoded )
[42]179      {
[56]180        m_tDecTop[previousViewDepthId]->executeDeblockAndAlf(uiPOC[previousViewDepthId], pcListPic[previousViewDepthId], m_iSkipFrame, m_pocLastDisplay[previousViewDepthId]);
181      } 
182      if( ( viewDepthId == 0 && (viewDepthId != previousViewDepthId) ) || m_tDecTop.size() == 1 )
[42]183      {
[56]184#if HHI_INTER_VIEW_RESIDUAL_PRED
185        for( Int i = 0; i < m_tDecTop.size(); i++ )
[42]186        {
[56]187          m_tDecTop[i]->deleteExtraPicBuffers( uiPOC[i] );
[42]188        }
[56]189#endif
190        for( Int i = 0; i < m_tDecTop.size(); i++ )
[42]191        {
[56]192          m_tDecTop[i]->compressMotion( uiPOC[i] );
[42]193        }
[56]194      }   
195      if( !(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) )
[42]196      {
[56]197        newPicture[viewDepthId] = m_tDecTop[viewDepthId]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[viewDepthId]);
198        if (newPicture[viewDepthId])
[42]199        {
[56]200          bitstreamFile.clear();
201          /* location points to the current nalunit payload[1] due to the
202           * need for the annexB parser to read three extra bytes.
203           * [1] except for the first NAL unit in the file
204           *     (but bNewPicture doesn't happen then) */
205          bitstreamFile.seekg(location-streamoff(3));
206          bytestream.reset();
[42]207        }
[56]208        if( nalu.isSlice() )
[42]209        {
[56]210          previousPictureDecoded = true;
[42]211        }
212      }
[56]213    }
214    if( ( (newPicture[viewDepthId] || !bitstreamFile) && m_tDecTop.size() == 1) || (!bitstreamFile && previousPictureDecoded == true) ) 
215    {
216      m_tDecTop[viewDepthId]->executeDeblockAndAlf(uiPOC[viewDepthId], pcListPic[viewDepthId], m_iSkipFrame, m_pocLastDisplay[viewDepthId]);
217    }
218    if( pcListPic[viewDepthId] )
219    {
220      if( newPicture[viewDepthId] && (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDV && m_tDecTop[viewDepthId]->getNalUnitTypeBaseView() == NAL_UNIT_CODED_SLICE_IDR)) )
[2]221      {
[56]222        xFlushOutput( pcListPic[viewDepthId], viewDepthId );
[2]223      }
[56]224      // write reconstruction to file
225      if(newPicture[viewDepthId])
[2]226      {
[56]227#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
228        xWriteOutput( pcListPic[viewDepthId], viewDepthId, nalu.m_temporalId );
[2]229#else
[56]230        xWriteOutput( pcListPic[viewDepthId], viewDepthId );
[2]231#endif
232      }
233    }
[56]234    previousViewDepthId = viewDepthId;
235  } 
[57]236  if( m_cCamParsCollector.isInitialized() )
237  {
238    m_cCamParsCollector.setSlice( 0 );
239  }
[56]240  // last frame
241  for( Int viewDepthIdx = 0; viewDepthIdx < m_tDecTop.size(); viewDepthIdx++ )
[2]242  {
[56]243    xFlushOutput( pcListPic[viewDepthIdx], viewDepthIdx );
244  } 
[2]245  xDestroyDecLib();
246}
247
248// ====================================================================================================================
249// Protected member functions
250// ====================================================================================================================
251
252Void TAppDecTop::xDestroyDecLib()
253{
254
[56]255  for(Int viewDepthIdx=0; viewDepthIdx<m_tVideoIOYuvReconFile.size() ; viewDepthIdx++)
[2]256  {
[56]257    if( m_tVideoIOYuvReconFile[viewDepthIdx] )
258    {
259      m_tVideoIOYuvReconFile[viewDepthIdx]->close();
260      delete m_tVideoIOYuvReconFile[viewDepthIdx]; 
261      m_tVideoIOYuvReconFile[viewDepthIdx] = NULL ;
262    }
[2]263  }
264
[56]265  for(Int viewDepthIdx=0; viewDepthIdx<m_tDecTop.size() ; viewDepthIdx++)
[2]266  {
[56]267    if( m_tDecTop[viewDepthIdx] )
268    {
269      if( !m_useDepth && (viewDepthIdx % 2 == 1) )
270      {
271      }
272      else
273      {
274        m_tDecTop[viewDepthIdx]->deletePicBuffer();
275        m_tDecTop[viewDepthIdx]->destroy() ;
276      }
277      delete m_tDecTop[viewDepthIdx] ; 
278      m_tDecTop[viewDepthIdx] = NULL ;
279    }
[2]280  }
[57]281
282  m_cCamParsCollector.uninit();
283  if( m_pScaleOffsetFile ) 
284  { 
285    ::fclose( m_pScaleOffsetFile ); 
286  }
[56]287}
[2]288
[56]289#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
290Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int viewDepthId, UInt tId )
291#else
292Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int viewDepthId )
293#endif
294{
295  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
296  Int not_displayed = 0;
297
298  while (iterPic != pcListPic->end())
[2]299  {
[56]300    TComPic* pcPic = *(iterPic);
301    if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[viewDepthId])
302    {
303       not_displayed++;
304    }
305    iterPic++;
[2]306  }
[56]307  iterPic   = pcListPic->begin();
308 
309  while (iterPic != pcListPic->end())
[2]310  {
[56]311    TComPic* pcPic = *(iterPic);
312#if PIC_CROPPING
313    TComSPS *sps = pcPic->getSlice(0)->getSPS();
314#endif
315   
316#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
317    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderPics(tId) && pcPic->getPOC() > m_pocLastDisplay[viewDepthId]))
318#else
319    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderFrames() && pcPic->getPOC() > m_pocLastDisplay[viewDepthId]))
320#endif
321    {
322      // write to file
323       not_displayed--;
324      if ( m_pchReconFile )
325      {
326#if PIC_CROPPING
327        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
328#else
329        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
330#endif
331      }
332     
333      // update POC of display order
334      m_pocLastDisplay[viewDepthId] = pcPic->getPOC();
335     
336      // erase non-referenced picture in the reference picture list after display
337      if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
338      {
339#if !DYN_REF_FREE
340        pcPic->setReconMark(false);
341       
342        // mark it should be extended later
343        pcPic->getPicYuvRec()->setBorderExtension( false );
344       
345#else
346        pcPic->destroy();
347        pcListPic->erase( iterPic );
348        iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
349        continue;
350#endif
351      }
352      pcPic->setOutputMark(false);
353    }
354   
355    iterPic++;
[2]356  }
357}
358
359/** \param pcListPic list of pictures to be written to file
360    \todo            DYN_REF_FREE should be revised
361 */
[56]362Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int viewDepthId )
[2]363{
[56]364  if(!pcListPic)
365  {
366    return;
367  } 
[2]368  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
369
[56]370  iterPic   = pcListPic->begin();
371 
[2]372  while (iterPic != pcListPic->end())
373  {
374    TComPic* pcPic = *(iterPic);
[56]375#if PIC_CROPPING
376    TComSPS *sps = pcPic->getSlice(0)->getSPS();
377#endif
[2]378
[56]379    if ( pcPic->getOutputMark() )
[2]380    {
[56]381      // write to file
382      if ( m_pchReconFile )
[2]383      {
[56]384#if PIC_CROPPING
385        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
386#else
387        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
388#endif
[2]389      }
[56]390     
391      // update POC of display order
392      m_pocLastDisplay[viewDepthId] = pcPic->getPOC();
393     
394      // erase non-referenced picture in the reference picture list after display
395      if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
[2]396      {
[56]397#if !DYN_REF_FREE
398        pcPic->setReconMark(false);
399       
400        // mark it should be extended later
401        pcPic->getPicYuvRec()->setBorderExtension( false );
402       
403#else
404        pcPic->destroy();
405        pcListPic->erase( iterPic );
406        iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
407        continue;
408#endif
[2]409      }
[56]410      pcPic->setOutputMark(false);
411    }
412   
[2]413    iterPic++;
414  }
[56]415  pcListPic->clear();
416  m_pocLastDisplay[viewDepthId] = -MAX_INT;
[2]417}
[77]418#if VIDYO_VPS_INTEGRATION
419Void  TAppDecTop::increaseNumberOfViews  ( UInt layerId, UInt viewId, UInt isDepth )
420#else
[56]421Void  TAppDecTop::increaseNumberOfViews  ( Int newNumberOfViewDepth )
[77]422#endif
[2]423{
[77]424#if VIDYO_VPS_INTEGRATION
425  Int newNumberOfViewDepth = layerId + 1;
426#endif
[56]427  if ( m_outputBitDepth == 0 )
[2]428  {
[56]429    m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
[2]430  }
[77]431#if !VIDYO_VPS_INTEGRATION
[56]432  Int viewId = (newNumberOfViewDepth-1)>>1;   // coding order T0D0T1D1T2D2
433  Bool isDepth = ((newNumberOfViewDepth % 2) == 0);  // coding order T0D0T1D1T2D2
[77]434#endif
[56]435  if( isDepth )
436    m_useDepth = true;
437  while( m_tVideoIOYuvReconFile.size() < newNumberOfViewDepth)
[2]438  {
[56]439    m_tVideoIOYuvReconFile.push_back(new TVideoIOYuv);
440    Char buffer[4];
[81]441#if VIDYO_VPS_INTEGRATION
442    sprintf(buffer,"_%i", viewId );
443#else
[56]444    sprintf(buffer,"_%i", (Int)(m_tVideoIOYuvReconFile.size()-1) / 2 );
[81]445#endif
[56]446    Char* nextFilename = NULL;
[81]447#if VIDYO_VPS_INTEGRATION
448    if( isDepth)
449#else
[56]450    if( (m_tVideoIOYuvReconFile.size() % 2) == 0 )
[81]451#endif
[2]452    {
453      Char* pchTempFilename = NULL;
454      xAppendToFileNameEnd( m_pchReconFile, "_depth", pchTempFilename);
[56]455      xAppendToFileNameEnd( pchTempFilename, buffer, nextFilename);
456      free ( pchTempFilename );
[2]457    }
[56]458    else
[2]459    {
[56]460      xAppendToFileNameEnd( m_pchReconFile, buffer, nextFilename);
[2]461    }
[81]462#if !VIDYO_VPS_INTEGRATION
[56]463    if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
[81]464#endif
[56]465    {
466      m_tVideoIOYuvReconFile.back()->open( nextFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
467    }
468      free ( nextFilename );
[2]469  }
[56]470  while( m_pocLastDisplay.size() < newNumberOfViewDepth )
471  {
472    m_pocLastDisplay.push_back(-MAX_INT+m_iSkipFrame);
473  }
474  while( m_tDecTop.size() < newNumberOfViewDepth)
475  {
476    m_tDecTop.push_back(new TDecTop);
[81]477#if !VIDYO_VPS_INTEGRATION
[56]478    if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
479    {
[81]480#endif
[56]481      m_tDecTop.back()->create();
482      m_tDecTop.back()->init( this, newNumberOfViewDepth == 1);
483      m_tDecTop.back()->setViewId( viewId );
484      m_tDecTop.back()->setIsDepth( isDepth );
485      m_tDecTop.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
[57]486      m_tDecTop.back()->setCamParsCollector( &m_cCamParsCollector );
[81]487#if !VIDYO_VPS_INTEGRATION
[56]488    }
[81]489#endif
[56]490  }
[2]491}
492
[56]493TDecTop* TAppDecTop::getTDecTop( Int viewId, Bool isDepth )
494{ 
495  return m_tDecTop[(isDepth ? 1 : 0) + viewId * 2];  // coding order T0D0T1D1T2D2
496} 
[2]497
[56]498std::vector<TComPic*> TAppDecTop::getInterViewRefPics( Int viewId, Int poc, Bool isDepth, TComSPS* sps )
[2]499{
[56]500  std::vector<TComPic*> apcRefPics( sps->getNumberOfUsableInterViewRefs(), (TComPic*)NULL );
501  for( Int k = 0; k < sps->getNumberOfUsableInterViewRefs(); k++ )
[2]502  {
[56]503    TComPic* pcRefPic = xGetPicFromView( sps->getUsableInterViewRef( k ) + viewId, poc, isDepth );
[2]504    assert( pcRefPic != NULL );
[56]505    apcRefPics[k] = pcRefPic;
[2]506  }
507  return apcRefPics;
508}
509
[56]510TComPic* TAppDecTop::xGetPicFromView( Int viewId, Int poc, Bool isDepth )
[2]511{
[56]512  assert( ( viewId >= 0 ) );
513
514  TComList<TComPic*>* apcListPic = getTDecTop( viewId, isDepth )->getListPic();
515  TComPic* pcPic = NULL;
[2]516  for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ )
517  {
[56]518    if( (*it)->getPOC() == poc )
[2]519    {
[56]520      pcPic = *it;
[2]521      break;
522    }
523  }
[56]524  return pcPic;
[2]525}
[56]526//! \}
Note: See TracBrowser for help on using the repository browser.