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

Last change on this file since 21 was 21, checked in by hschwarz, 12 years ago

updated with HHI branch (0.2-HHI)

  • Property svn:eol-style set to native
File size: 18.6 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#if SONY_COLPIC_AVAILABILITY
355  m_acTDecTopList[0]->setViewOrderIdx(0);
356#endif
357}
358
359/** \param pcListPic list of pictures to be written to file
360    \param bFirst    first picture?
361    \todo            DYN_REF_FREE should be revised
362 */
363Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic )
364{
365  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
366
367  while (iterPic != pcListPic->end())
368  {
369    TComPic* pcPic = *(iterPic);
370    Int iViewIdx = pcPic->getViewIdx();
371    Int bIsDepth = pcPic->getSlice(0)->getSPS()->isDepth() ;
372
373    if (!bIsDepth)
374    {
375      if( m_acTVideoIOYuvReconFileList.size() < iViewIdx+1 )
376            increaseNumberOfViews( iViewIdx+1 ) ;
377
378      if ( pcPic->getReconMark() && pcPic->getPOC() == (m_aiPOCLastDisplayList[iViewIdx] + 1) )
379      {
380        // write to file
381        if ( m_pchReconFile )
382        {
383          m_acTVideoIOYuvReconFileList[iViewIdx]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
384        }
385
386        // update POC of display order
387        m_aiPOCLastDisplayList[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    else
408    {
409      if( m_acTVideoIOYuvDepthReconFileList.size() < iViewIdx+1 )
410             increaseNumberOfViews( iViewIdx+1 ) ;
411
412      if ( pcPic->getReconMark() && pcPic->getPOC() == (m_aiDepthPOCLastDisplayList[iViewIdx] + 1) )
413      {
414        // write to file
415        if ( m_pchReconFile )
416        {
417          m_acTVideoIOYuvDepthReconFileList[iViewIdx]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
418        }
419
420        // update POC of display order
421        m_aiDepthPOCLastDisplayList[iViewIdx] = pcPic->getPOC();
422
423        // erase non-referenced picture in the reference picture list after display
424        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
425        {
426  #if !DYN_REF_FREE
427          pcPic->setReconMark(false);
428
429          // mark it should be extended later
430          pcPic->getPicYuvRec()->setBorderExtension( false );
431
432  #else
433          pcPic->destroy();
434          pcListPic->erase( iterPic );
435          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
436          continue;
437  #endif
438        }
439      }
440    } // end bIsDepth
441
442    iterPic++;
443  }
444}
445
446Void TAppDecTop::startUsingDepth()
447{
448  m_bUsingDepth = true ;
449  increaseNumberOfViews( (Int)m_acTVideoIOYuvReconFileList.size() );
450}
451
452Void  TAppDecTop::increaseNumberOfViews  (Int iNewNumberOfViews)
453{
454  while( m_acTVideoIOYuvReconFileList.size() < iNewNumberOfViews)
455  {
456    m_acTVideoIOYuvReconFileList.push_back(new TVideoIOYuv);
457
458// GT FIX
459    Char cBuffer[4]  ;
460    sprintf(cBuffer,"_%i",(Int)m_acTVideoIOYuvReconFileList.size()-1 );
461    Char* pchNextFilename;
462    xAppendToFileNameEnd( m_pchReconFile, cBuffer, pchNextFilename);
463// GT FIX END
464    if ( m_outputBitDepth == 0 )
465      m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
466    m_acTVideoIOYuvReconFileList.back()->open( pchNextFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
467    free (pchNextFilename);
468  }
469
470  while( m_aiPOCLastDisplayList.size() < iNewNumberOfViews )
471    m_aiPOCLastDisplayList.push_back(-1+m_iSkipFrame) ;
472
473  while( m_acTDecTopList.size() < iNewNumberOfViews)
474  {
475    m_acTDecTopList.push_back(new TDecTop) ;// at least one decoder
476    m_acTDecTopList.back()->create() ;
477    m_acTDecTopList.back()->init( this, false );
478    m_acTDecTopList.back()->setViewIdx((Int)m_acTDecTopList.size()-1);
479    m_acTDecTopList.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
480    m_acTDecTopList.back()->setCamParsCollector( &m_cCamParsCollector );
481  }
482  if( m_bUsingDepth )
483  {
484    while( m_acTVideoIOYuvDepthReconFileList.size() < iNewNumberOfViews  )
485    {
486      m_acTVideoIOYuvDepthReconFileList.push_back(new TVideoIOYuv);
487// GT FIX
488      Char* pchTempFilename = NULL;
489      xAppendToFileNameEnd( m_pchReconFile, "_depth", pchTempFilename);
490      Char cBuffer[4]  ;
491      sprintf(cBuffer,"_%i",(Int)m_acTVideoIOYuvDepthReconFileList.size()-1 );
492      Char* pchDepthFilename = NULL;
493      xAppendToFileNameEnd( pchTempFilename, cBuffer, pchDepthFilename);
494// GT FIX END
495      if ( m_outputBitDepth == 0 )
496        m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
497      m_acTVideoIOYuvDepthReconFileList.back()->open( pchDepthFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
498      free (pchTempFilename);
499      free( pchDepthFilename );
500    }
501    while( m_aiDepthPOCLastDisplayList.size() < iNewNumberOfViews )
502      m_aiDepthPOCLastDisplayList.push_back(-1+m_iSkipFrame) ;
503    while( m_acTDecDepthTopList.size() < iNewNumberOfViews)
504    {
505      m_acTDecDepthTopList.push_back(new TDecTop) ;// at least one decoder
506      m_acTDecDepthTopList.back()->create() ;
507      m_acTDecDepthTopList.back()->init( this, false );
508      m_acTDecDepthTopList.back()->setViewIdx((Int)m_acTDecTopList.size()-1);
509      m_acTDecDepthTopList.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
510      m_acTDecDepthTopList.back()->setToDepth( true );
511      m_acTDecDepthTopList.back()->setCamParsCollector( &m_cCamParsCollector );
512    }
513  }
514}
515
516
517// GT FIX
518std::vector<TComPic*> TAppDecTop::getSpatialRefPics( Int iViewIdx, Int iPoc, Bool bIsDepth ) // only for mvc functionality yet
519{
520  std::vector<TComPic*> apcRefPics( iViewIdx, (TComPic*)NULL );
521  for( int iRefViewIdx = 0; iRefViewIdx < iViewIdx; iRefViewIdx++ )
522  {
523    TComPic* pcRefPic = getPicFromView( iRefViewIdx, iPoc, bIsDepth );
524    assert( pcRefPic != NULL );
525    apcRefPics[iRefViewIdx] = pcRefPic;
526  }
527  return apcRefPics;
528}
529
530TComPic* TAppDecTop::getPicFromView( Int iViewIdx, Int iPoc, bool bIsDepth )
531{
532  TComList<TComPic*>* apcListPic = (bIsDepth ? m_acTDecDepthTopList[iViewIdx] : m_acTDecTopList[iViewIdx])->getListPic();
533  TComPic* pcRefPic = NULL;
534  for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ )
535  {
536    if( (*it)->getPOC() == iPoc )
537    {
538      pcRefPic = *it;
539      break;
540    }
541  }
542  return pcRefPic;
543}
Note: See TracBrowser for help on using the repository browser.