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

Last change on this file since 16 was 5, checked in by hhi, 13 years ago

Clean version with cfg-files

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