source: 3DVCSoftware/branches/0.1-poznan-univ/source/App/TAppDecoder/TAppDecTop.cpp

Last change on this file was 2, checked in by hhi, 13 years ago

inital import

  • Property svn:eol-style set to native
File size: 16.8 KB
Line 
1
2
3/** \file     TAppDecTop.cpp
4    \brief    Decoder application class
5*/
6
7#include <list>
8#include <stdio.h>
9#include <fcntl.h>
10#include <assert.h>
11
12#include "TAppDecTop.h"
13
14// ====================================================================================================================
15// Local constants
16// ====================================================================================================================
17
18/// initial bitstream buffer size
19/// should be large enough for parsing SPS
20/// resized as a function of picture size after parsing SPS
21#define BITS_BUF_SIZE 65536
22
23// ====================================================================================================================
24// Constructor / destructor / initialization / destroy
25// ====================================================================================================================
26
27TAppDecTop::TAppDecTop()
28{
29  ::memset (m_abDecFlag, 0, sizeof (m_abDecFlag));
30  m_bUsingDepth = false;
31//  m_iPOCLastDisplay  = -1;
32  m_pScaleOffsetFile  = 0;
33}
34
35Void TAppDecTop::create()
36{
37  m_apcBitstream  = new TComBitstream;
38 
39  m_apcBitstream->create( BITS_BUF_SIZE );
40}
41
42Void TAppDecTop::destroy()
43{
44  if ( m_apcBitstream )
45  {
46    m_apcBitstream->destroy();
47    delete m_apcBitstream;
48    m_apcBitstream = NULL;
49  }
50#if SB_MEM_FIX
51  if( m_pchBitstreamFile )
52  {
53    free(m_pchBitstreamFile);
54  }
55  if( m_pchReconFile )
56  {
57    free(m_pchReconFile);
58  }
59#endif
60}
61
62// ====================================================================================================================
63// Public member functions
64// ====================================================================================================================
65
66/**
67 - create internal class
68 - initialize internal class
69 - until the end of the bitstream, call decoding function in TDecTop class
70 - delete allocated buffers
71 - destroy internal class
72 .
73 */
74Void TAppDecTop::decode()
75{
76  TComBitstream*      pcBitstream = m_apcBitstream;
77  UInt                uiPOC;
78  TComList<TComPic*>* pcListPic;
79  Bool bFirstSliceDecoded = true;
80
81  // create & initialize internal classes
82  xCreateDecLib();
83  xInitDecLib  ();
84#if DCM_SKIP_DECODING_FRAMES
85//  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
86#endif
87
88  // main decoder loop
89  Bool  bEos        = false;
90  Bool resizedBitstreamBuffer = false;
91 
92  Bool bIsDepth = false;
93  Int iViewIdx = 0;
94  TComSPS cComSPS ;
95  NalUnitType eNalUnitType;
96
97 
98  while ( !bEos )
99  {
100    streampos  lLocation = m_cTVideoIOBitstreamFile.getFileLocation();
101    bEos                 = m_cTVideoIOBitstreamFile.readBits( pcBitstream );
102    if (bEos)
103    {
104      //if (!bFirstSliceDecoded) m_cTDecTop.decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_iPOCLastDisplay);
105      if( bIsDepth )
106      {
107        if (!bFirstSliceDecoded) m_acTDecDepthTopList[iViewIdx]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiDepthPOCLastDisplayList[iViewIdx] );
108        m_acTDecDepthTopList[iViewIdx]->executeDeblockAndAlf( bEos, pcBitstream, uiPOC, pcListPic, m_iSkipFrame, m_aiDepthPOCLastDisplayList[iViewIdx]);
109      }
110      else
111      {
112        if (!bFirstSliceDecoded) m_acTDecTopList[iViewIdx]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiPOCLastDisplayList[iViewIdx] );
113        m_acTDecTopList[iViewIdx]->executeDeblockAndAlf( bEos, pcBitstream, uiPOC, pcListPic, m_iSkipFrame, m_aiPOCLastDisplayList[iViewIdx]);
114      }
115      if( pcListPic )
116      {
117        // write reconstuction to file
118        xWriteOutput( pcListPic );
119      }
120      break;
121    }
122   
123    // call actual decoding function
124#if DCM_SKIP_DECODING_FRAMES
125    Bool bNewPicture;
126    if( bIsDepth )
127      bNewPicture = m_acTDecDepthTopList[iViewIdx]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiDepthPOCLastDisplayList[iViewIdx] );
128    else
129      bNewPicture = m_acTDecTopList[iViewIdx]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiPOCLastDisplayList[iViewIdx] );
130    bFirstSliceDecoded   = true;
131
132    if( eNalUnitType == NAL_UNIT_SPS )
133    {
134      if( cComSPS.isDepth() && (m_bUsingDepth==false) )  // expected not using depth, but bitstream are using depth
135      {                                                     // know from sps
136        assert( cComSPS.getViewId() == 0 && iViewIdx == 0 && !bIsDepth );
137        startUsingDepth() ;
138      }
139      if( cComSPS.isDepth() && !bIsDepth )
140      {
141        assert( cComSPS.getViewId() == iViewIdx );
142        m_acTDecDepthTopList[iViewIdx]->setSPS(cComSPS);
143      }
144      else if( cComSPS.getViewId() >= m_acTVideoIOYuvReconFileList.size() ) // expecting iViewIdx, but got cComSPS.getViewIdx()
145      {
146        assert( cComSPS.getViewId() == m_acTVideoIOYuvReconFileList.size() );
147        assert( !cComSPS.isDepth() );
148        increaseNumberOfViews(cComSPS.getViewId()+1);
149        m_acTDecTopList[cComSPS.getViewId()]->setSPS(cComSPS);
150      }
151      bEos = m_cTVideoIOBitstreamFile.readBits( pcBitstream );
152      assert( !bEos);
153      if( cComSPS.isDepth() )
154        m_acTDecDepthTopList[cComSPS.getViewId()]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiDepthPOCLastDisplayList[cComSPS.getViewId()]); // decode PPS
155      else
156        m_acTDecTopList[cComSPS.getViewId()]->decode( bEos, pcBitstream, uiPOC, pcListPic, eNalUnitType, cComSPS, m_iSkipFrame, m_aiPOCLastDisplayList[cComSPS.getViewId()]); // decode PPS
157      assert( eNalUnitType == NAL_UNIT_PPS );
158    }
159    assert( eNalUnitType != NAL_UNIT_SEI ); // not yet supported for MVC
160    if (bNewPicture)
161    {
162      if( bIsDepth )
163        m_acTDecDepthTopList[iViewIdx]->executeDeblockAndAlf( bEos, pcBitstream, uiPOC, pcListPic, m_iSkipFrame, m_aiDepthPOCLastDisplayList[iViewIdx]);
164      else
165        m_acTDecTopList[iViewIdx]->executeDeblockAndAlf( bEos, pcBitstream, uiPOC, pcListPic, m_iSkipFrame, m_aiPOCLastDisplayList[iViewIdx]);
166      if (!m_cTVideoIOBitstreamFile.good()) m_cTVideoIOBitstreamFile.clear();
167      m_cTVideoIOBitstreamFile.setFileLocation( lLocation );
168      bFirstSliceDecoded = false;
169
170      if( m_bUsingDepth && !bIsDepth )
171      {
172        bIsDepth = true;
173      }
174      else
175      {
176        bIsDepth = false;
177        if( iViewIdx<m_acTDecTopList.size()-1)
178        {
179          iViewIdx++ ;
180        }
181        else
182        {
183          iViewIdx = 0;
184
185          // end of access unit: delete extra pic buffers
186          Int iNumViews = (Int)m_acTVideoIOYuvReconFileList.size();
187          for( Int iVId = 0; iVId < iNumViews; iVId++ )
188          {
189            if( iVId < (Int)m_acTDecTopList.size() &&  m_acTDecTopList[iVId] )
190            {
191              m_acTDecTopList[iVId]->deleteExtraPicBuffers( (Int)uiPOC );
192            }
193            if( iVId < (Int)m_acTDecDepthTopList.size() && m_acTDecDepthTopList[iVId] )
194            {
195              m_acTDecDepthTopList[iVId]->deleteExtraPicBuffers( (Int)uiPOC );
196            }
197          }
198
199#if AMVP_BUFFERCOMPRESS
200          // compress motion for entire access unit
201          for( Int iVId = 0; iVId < iNumViews; iVId++ )
202          {
203            if( iVId < (Int)m_acTDecTopList.size() &&  m_acTDecTopList[iVId] )
204            {
205              m_acTDecTopList[iVId]->compressMotion( (Int)uiPOC );
206            }
207            if( iVId < (Int)m_acTDecDepthTopList.size() && m_acTDecDepthTopList[iVId] )
208            {
209              m_acTDecDepthTopList[iVId]->compressMotion( (Int)uiPOC );
210            }
211          }
212#endif
213        }
214      }
215    }
216#else
217#error
218    m_cTDecTop.decode( bEos, pcBitstream, uiPOC, pcListPic );
219#endif
220
221   
222    if (!resizedBitstreamBuffer)
223    {
224      TComSPS *sps = m_acTDecTopList[0]->getSPS();
225      if (sps)
226      {
227        pcBitstream->destroy();
228        pcBitstream->create(sps->getWidth() * sps->getHeight() * 2);
229        resizedBitstreamBuffer = true;
230      }
231    }
232   
233    if( pcListPic )
234    {
235      // write reconstuction to file
236      xWriteOutput( pcListPic );
237    }
238  }
239 
240  // delete buffers
241  for(Int i=0; i<m_acTDecTopList.size(); i++)
242    m_acTDecTopList[i]->deletePicBuffer();
243
244  if (m_bUsingDepth)
245  {
246    for(Int i=0; i<m_acTDecDepthTopList.size(); i++)
247      m_acTDecDepthTopList[i]->deletePicBuffer();
248  }
249 
250  // destroy internal classes
251  xDestroyDecLib();
252}
253
254// ====================================================================================================================
255// Protected member functions
256// ====================================================================================================================
257
258Void TAppDecTop::xCreateDecLib()
259{
260  // open bitstream file
261  m_cTVideoIOBitstreamFile.openBits( m_pchBitstreamFile, false);  // read mode
262
263  // create decoder class
264//  m_cTDecTop.create();
265  m_acTDecTopList.push_back(new TDecTop) ;// at least one decoder
266  m_acTDecTopList[0]->create() ;
267
268  m_aiPOCLastDisplayList.push_back(-1+m_iSkipFrame) ;
269
270  if( m_pchScaleOffsetFile ) 
271  { 
272    m_pScaleOffsetFile = ::fopen( m_pchScaleOffsetFile, "wt" ); 
273    AOF( m_pScaleOffsetFile ); 
274  }
275  m_cCamParsCollector.init( m_pScaleOffsetFile );
276}
277
278Void TAppDecTop::xDestroyDecLib()
279{
280  // close bitstream file
281  m_cTVideoIOBitstreamFile.closeBits();
282
283  for(Int iViewIdx=0; iViewIdx<m_acTVideoIOYuvReconFileList.size() ; iViewIdx++)
284  {
285    m_acTVideoIOYuvReconFileList[iViewIdx]->close();
286    delete m_acTVideoIOYuvReconFileList[iViewIdx]; m_acTVideoIOYuvReconFileList[iViewIdx] = NULL ;
287  }
288
289  // destroy decoder class
290//  m_cTDecTop.destroy();
291  for(Int iViewIdx=0; iViewIdx<m_acTDecTopList.size() ; iViewIdx++)
292  {
293    m_acTDecTopList[iViewIdx]->destroy() ;
294    delete m_acTDecTopList[iViewIdx] ; m_acTDecTopList[iViewIdx] = NULL ;
295  }
296
297  for(Int iViewIdx=0; iViewIdx<m_acTVideoIOYuvDepthReconFileList.size() ; iViewIdx++)
298  {
299    m_acTVideoIOYuvDepthReconFileList[iViewIdx]->close();
300    delete m_acTVideoIOYuvDepthReconFileList[iViewIdx]; m_acTVideoIOYuvDepthReconFileList[iViewIdx] = NULL ;
301  }
302
303  for(Int iViewIdx=0; iViewIdx<m_acTDecDepthTopList.size() ; iViewIdx++)
304  {
305    m_acTDecDepthTopList[iViewIdx]->destroy() ;
306    delete m_acTDecDepthTopList[iViewIdx] ; m_acTDecDepthTopList[iViewIdx] = NULL ;
307  }
308
309  m_cCamParsCollector.uninit();
310  if( m_pScaleOffsetFile ) 
311  { 
312    ::fclose( m_pScaleOffsetFile ); 
313  }
314}
315
316Void TAppDecTop::xInitDecLib()
317{
318  // initialize decoder class
319  m_acTDecTopList[0]->init( this );
320  m_acTDecTopList[0]->setViewIdx(0);
321  m_acTDecTopList[0]->setPictureDigestEnabled(m_pictureDigestEnabled);
322  m_acTDecTopList[0]->setCamParsCollector( &m_cCamParsCollector );
323}
324
325/** \param pcListPic list of pictures to be written to file
326    \param bFirst    first picture?
327    \todo            DYN_REF_FREE should be revised
328 */
329Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic )
330{
331  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
332
333  while (iterPic != pcListPic->end())
334  {
335    TComPic* pcPic = *(iterPic);
336    Int iViewIdx = pcPic->getViewIdx();
337    Int bIsDepth = pcPic->getSlice(0)->getSPS()->isDepth() ;
338
339    if (!bIsDepth)
340    {
341      if( m_acTVideoIOYuvReconFileList.size() < iViewIdx+1 )
342            increaseNumberOfViews( iViewIdx+1 ) ;
343
344      if ( pcPic->getReconMark() && pcPic->getPOC() == (m_aiPOCLastDisplayList[iViewIdx] + 1) )
345      {
346        // write to file
347        if ( m_pchReconFile )
348        {
349          m_acTVideoIOYuvReconFileList[iViewIdx]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
350        }
351
352        // update POC of display order
353        m_aiPOCLastDisplayList[iViewIdx] = pcPic->getPOC();
354
355        // erase non-referenced picture in the reference picture list after display
356        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
357        {
358  #if !DYN_REF_FREE
359          pcPic->setReconMark(false);
360
361          // mark it should be extended later
362          pcPic->getPicYuvRec()->setBorderExtension( false );
363
364  #else
365          pcPic->destroy();
366          pcListPic->erase( iterPic );
367          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
368          continue;
369  #endif
370        }
371      }
372    } /// end !bIsDepth
373    else
374    {
375      if( m_acTVideoIOYuvDepthReconFileList.size() < iViewIdx+1 )
376             increaseNumberOfViews( iViewIdx+1 ) ;
377
378      if ( pcPic->getReconMark() && pcPic->getPOC() == (m_aiDepthPOCLastDisplayList[iViewIdx] + 1) )
379      {
380        // write to file
381        if ( m_pchReconFile )
382        {
383          m_acTVideoIOYuvDepthReconFileList[iViewIdx]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
384        }
385
386        // update POC of display order
387        m_aiDepthPOCLastDisplayList[iViewIdx] = pcPic->getPOC();
388
389        // erase non-referenced picture in the reference picture list after display
390        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
391        {
392  #if !DYN_REF_FREE
393          pcPic->setReconMark(false);
394
395          // mark it should be extended later
396          pcPic->getPicYuvRec()->setBorderExtension( false );
397
398  #else
399          pcPic->destroy();
400          pcListPic->erase( iterPic );
401          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
402          continue;
403  #endif
404        }
405      }
406    } // end bIsDepth
407
408    iterPic++;
409  }
410}
411
412Void TAppDecTop::startUsingDepth()
413{
414  m_bUsingDepth = true ;
415  increaseNumberOfViews( (Int)m_acTVideoIOYuvReconFileList.size() );
416}
417
418Void  TAppDecTop::increaseNumberOfViews  (Int iNewNumberOfViews)
419{
420  while( m_acTVideoIOYuvReconFileList.size() < iNewNumberOfViews)
421  {
422    m_acTVideoIOYuvReconFileList.push_back(new TVideoIOYuv);
423
424// GT FIX
425    Char cBuffer[4]  ;
426    sprintf(cBuffer,"_%i",(Int)m_acTVideoIOYuvReconFileList.size()-1 );
427    Char* pchNextFilename;
428    xAppendToFileNameEnd( m_pchReconFile, cBuffer, pchNextFilename);
429// GT FIX END
430    if ( m_outputBitDepth == 0 )
431      m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
432    m_acTVideoIOYuvReconFileList.back()->open( pchNextFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
433    free (pchNextFilename);
434  }
435
436  while( m_aiPOCLastDisplayList.size() < iNewNumberOfViews )
437    m_aiPOCLastDisplayList.push_back(-1+m_iSkipFrame) ;
438
439  while( m_acTDecTopList.size() < iNewNumberOfViews)
440  {
441    m_acTDecTopList.push_back(new TDecTop) ;// at least one decoder
442    m_acTDecTopList.back()->create() ;
443    m_acTDecTopList.back()->init( this, false );
444    m_acTDecTopList.back()->setViewIdx((Int)m_acTDecTopList.size()-1);
445    m_acTDecTopList.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
446    m_acTDecTopList.back()->setCamParsCollector( &m_cCamParsCollector );
447  }
448  if( m_bUsingDepth )
449  {
450    while( m_acTVideoIOYuvDepthReconFileList.size() < iNewNumberOfViews  )
451    {
452      m_acTVideoIOYuvDepthReconFileList.push_back(new TVideoIOYuv);
453// GT FIX
454      Char* pchTempFilename = NULL;
455      xAppendToFileNameEnd( m_pchReconFile, "_depth", pchTempFilename);
456      Char cBuffer[4]  ;
457      sprintf(cBuffer,"_%i",(Int)m_acTVideoIOYuvDepthReconFileList.size()-1 );
458      Char* pchDepthFilename = NULL;
459      xAppendToFileNameEnd( pchTempFilename, cBuffer, pchDepthFilename);
460// GT FIX END
461      if ( m_outputBitDepth == 0 )
462        m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
463      m_acTVideoIOYuvDepthReconFileList.back()->open( pchDepthFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
464      free (pchTempFilename);
465      free( pchDepthFilename );
466    }
467    while( m_aiDepthPOCLastDisplayList.size() < iNewNumberOfViews )
468      m_aiDepthPOCLastDisplayList.push_back(-1+m_iSkipFrame) ;
469    while( m_acTDecDepthTopList.size() < iNewNumberOfViews)
470    {
471      m_acTDecDepthTopList.push_back(new TDecTop) ;// at least one decoder
472      m_acTDecDepthTopList.back()->create() ;
473      m_acTDecDepthTopList.back()->init( this, false );
474      m_acTDecDepthTopList.back()->setViewIdx((Int)m_acTDecTopList.size()-1);
475      m_acTDecDepthTopList.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
476      m_acTDecDepthTopList.back()->setToDepth( true );
477      m_acTDecDepthTopList.back()->setCamParsCollector( &m_cCamParsCollector );
478    }
479  }
480}
481
482
483// GT FIX
484std::vector<TComPic*> TAppDecTop::getSpatialRefPics( Int iViewIdx, Int iPoc, Bool bIsDepth ) // only for mvc functionality yet
485{
486  std::vector<TComPic*> apcRefPics( iViewIdx, (TComPic*)NULL );
487  for( int iRefViewIdx = 0; iRefViewIdx < iViewIdx; iRefViewIdx++ )
488  {
489    TComPic* pcRefPic = getPicFromView( iRefViewIdx, iPoc, bIsDepth );
490    assert( pcRefPic != NULL );
491    apcRefPics[iRefViewIdx] = pcRefPic;
492  }
493  return apcRefPics;
494}
495
496TComPic* TAppDecTop::getPicFromView( Int iViewIdx, Int iPoc, bool bIsDepth )
497{
498  TComList<TComPic*>* apcListPic = (bIsDepth ? m_acTDecDepthTopList[iViewIdx] : m_acTDecTopList[iViewIdx])->getListPic();
499  TComPic* pcRefPic = NULL;
500  for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ )
501  {
502    if( (*it)->getPOC() == iPoc )
503    {
504      pcRefPic = *it;
505      break;
506    }
507  }
508  return pcRefPic;
509}
Note: See TracBrowser for help on using the repository browser.