source: 3DVCSoftware/branches/HTM-3.0-Vidyo/source/App/TAppDecoder/TAppDecTop.cpp @ 353

Last change on this file since 353 was 80, checked in by vidyo, 12 years ago

decoder bug fix - fixing crash when decoding view-only (no depth coding) bitstreams

  • Property svn:eol-style set to native
File size: 16.8 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-2012, ITU/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 ITU/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/** \file     TAppDecTop.cpp
35    \brief    Decoder application class
36*/
37
38#include <list>
39#include <vector>
40#include <stdio.h>
41#include <fcntl.h>
42#include <assert.h>
43
44#include "TAppDecTop.h"
45#include "TLibDecoder/AnnexBread.h"
46#include "TLibDecoder/NALread.h"
47
48//! \ingroup TAppDecoder
49//! \{
50
51// ====================================================================================================================
52// Constructor / destructor / initialization / destroy
53// ====================================================================================================================
54
55TAppDecTop::TAppDecTop()
56{
57  ::memset (m_abDecFlag, 0, sizeof (m_abDecFlag));
58  m_useDepth = false;
59  m_pScaleOffsetFile  = 0;
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{
84#if VIDYO_VPS_INTEGRATION
85  increaseNumberOfViews( 0, 0, 0 );
86#else
87  increaseNumberOfViews( 1 );
88#endif
89 
90#if SONY_COLPIC_AVAILABILITY
91  m_tDecTop[0]->setViewOrderIdx(0);
92#endif
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  }
105
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  }
112
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)
123  {
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())
136    {
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");
143    }
144    else
145    {
146      read(nalu, nalUnit);
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
160      Int viewId = nalu.m_viewId;
161      Int depth = nalu.m_isDepth ? 1 : 0;
162      viewDepthId = viewId * 2 + depth;   // coding order T0D0T1D1T2D2
163#endif
164     
165      newPicture[viewDepthId] = false;
166      if( viewDepthId >= m_tDecTop.size() )     
167      {
168#if VIDYO_VPS_INTEGRATION
169        increaseNumberOfViews( viewDepthId, viewId, depth );
170#else
171        increaseNumberOfViews( viewDepthId +1 );
172#endif   
173      }
174      if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer)
175      {
176        previousPictureDecoded = false; 
177      }
178      if(m_tDecTop.size() > 1 && (viewDepthId != previousViewDepthId) && previousPictureDecoded )
179      {
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 )
183      {
184#if HHI_INTER_VIEW_RESIDUAL_PRED
185        for( Int i = 0; i < m_tDecTop.size(); i++ )
186        {
187          m_tDecTop[i]->deleteExtraPicBuffers( uiPOC[i] );
188        }
189#endif
190        for( Int i = 0; i < m_tDecTop.size(); i++ )
191        {
192          m_tDecTop[i]->compressMotion( uiPOC[i] );
193        }
194      }   
195      if( !(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) )
196      {
197        newPicture[viewDepthId] = m_tDecTop[viewDepthId]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[viewDepthId]);
198        if (newPicture[viewDepthId])
199        {
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();
207        }
208        if( nalu.isSlice() )
209        {
210          previousPictureDecoded = true;
211        }
212      }
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)) )
221      {
222        xFlushOutput( pcListPic[viewDepthId], viewDepthId );
223      }
224      // write reconstruction to file
225      if(newPicture[viewDepthId])
226      {
227#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
228        xWriteOutput( pcListPic[viewDepthId], viewDepthId, nalu.m_temporalId );
229#else
230        xWriteOutput( pcListPic[viewDepthId], viewDepthId );
231#endif
232      }
233    }
234    previousViewDepthId = viewDepthId;
235  } 
236  if( m_cCamParsCollector.isInitialized() )
237  {
238    m_cCamParsCollector.setSlice( 0 );
239  }
240  // last frame
241  for( Int viewDepthIdx = 0; viewDepthIdx < m_tDecTop.size(); viewDepthIdx++ )
242  {
243    xFlushOutput( pcListPic[viewDepthIdx], viewDepthIdx );
244  } 
245  xDestroyDecLib();
246}
247
248// ====================================================================================================================
249// Protected member functions
250// ====================================================================================================================
251
252Void TAppDecTop::xDestroyDecLib()
253{
254
255  for(Int viewDepthIdx=0; viewDepthIdx<m_tVideoIOYuvReconFile.size() ; viewDepthIdx++)
256  {
257    if( m_tVideoIOYuvReconFile[viewDepthIdx] )
258    {
259      m_tVideoIOYuvReconFile[viewDepthIdx]->close();
260      delete m_tVideoIOYuvReconFile[viewDepthIdx]; 
261      m_tVideoIOYuvReconFile[viewDepthIdx] = NULL ;
262    }
263  }
264
265  for(Int viewDepthIdx=0; viewDepthIdx<m_tDecTop.size() ; viewDepthIdx++)
266  {
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    }
280  }
281
282  m_cCamParsCollector.uninit();
283  if( m_pScaleOffsetFile ) 
284  { 
285    ::fclose( m_pScaleOffsetFile ); 
286  }
287}
288
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())
299  {
300    TComPic* pcPic = *(iterPic);
301    if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[viewDepthId])
302    {
303       not_displayed++;
304    }
305    iterPic++;
306  }
307  iterPic   = pcListPic->begin();
308 
309  while (iterPic != pcListPic->end())
310  {
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++;
356  }
357}
358
359/** \param pcListPic list of pictures to be written to file
360    \todo            DYN_REF_FREE should be revised
361 */
362Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int viewDepthId )
363{
364  if(!pcListPic)
365  {
366    return;
367  } 
368  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
369
370  iterPic   = pcListPic->begin();
371 
372  while (iterPic != pcListPic->end())
373  {
374    TComPic* pcPic = *(iterPic);
375#if PIC_CROPPING
376    TComSPS *sps = pcPic->getSlice(0)->getSPS();
377#endif
378
379    if ( pcPic->getOutputMark() )
380    {
381      // write to file
382      if ( m_pchReconFile )
383      {
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
389      }
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 )
396      {
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
409      }
410      pcPic->setOutputMark(false);
411    }
412   
413    iterPic++;
414  }
415  pcListPic->clear();
416  m_pocLastDisplay[viewDepthId] = -MAX_INT;
417}
418#if VIDYO_VPS_INTEGRATION
419Void  TAppDecTop::increaseNumberOfViews  ( UInt layerId, UInt viewId, UInt isDepth )
420#else
421Void  TAppDecTop::increaseNumberOfViews  ( Int newNumberOfViewDepth )
422#endif
423{
424#if VIDYO_VPS_INTEGRATION
425  Int newNumberOfViewDepth = layerId + 1;
426#endif
427  if ( m_outputBitDepth == 0 )
428  {
429    m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
430  }
431#if !VIDYO_VPS_INTEGRATION
432  Int viewId = (newNumberOfViewDepth-1)>>1;   // coding order T0D0T1D1T2D2
433  Bool isDepth = ((newNumberOfViewDepth % 2) == 0);  // coding order T0D0T1D1T2D2
434#endif
435  if( isDepth )
436    m_useDepth = true;
437  while( m_tVideoIOYuvReconFile.size() < newNumberOfViewDepth)
438  {
439    m_tVideoIOYuvReconFile.push_back(new TVideoIOYuv);
440    Char buffer[4];
441#if VIDYO_VPS_INTEGRATION
442    sprintf(buffer,"_%i", viewId );
443#else
444    sprintf(buffer,"_%i", (Int)(m_tVideoIOYuvReconFile.size()-1) / 2 );
445#endif
446    Char* nextFilename = NULL;
447#if VIDYO_VPS_INTEGRATION
448    if( isDepth)
449#else
450    if( (m_tVideoIOYuvReconFile.size() % 2) == 0 )
451#endif
452    {
453      Char* pchTempFilename = NULL;
454      xAppendToFileNameEnd( m_pchReconFile, "_depth", pchTempFilename);
455      xAppendToFileNameEnd( pchTempFilename, buffer, nextFilename);
456      free ( pchTempFilename );
457    }
458    else
459    {
460      xAppendToFileNameEnd( m_pchReconFile, buffer, nextFilename);
461    }
462#if !VIDYO_VPS_INTEGRATION
463    if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
464#endif
465    {
466      m_tVideoIOYuvReconFile.back()->open( nextFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
467    }
468      free ( nextFilename );
469  }
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);
477#if !VIDYO_VPS_INTEGRATION
478    if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
479    {
480#endif
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);
486      m_tDecTop.back()->setCamParsCollector( &m_cCamParsCollector );
487#if !VIDYO_VPS_INTEGRATION
488    }
489#endif
490  }
491}
492
493TDecTop* TAppDecTop::getTDecTop( Int viewId, Bool isDepth )
494{ 
495  return m_tDecTop[(isDepth ? 1 : 0) + viewId * 2];  // coding order T0D0T1D1T2D2
496} 
497
498std::vector<TComPic*> TAppDecTop::getInterViewRefPics( Int viewId, Int poc, Bool isDepth, TComSPS* sps )
499{
500  std::vector<TComPic*> apcRefPics( sps->getNumberOfUsableInterViewRefs(), (TComPic*)NULL );
501  for( Int k = 0; k < sps->getNumberOfUsableInterViewRefs(); k++ )
502  {
503    TComPic* pcRefPic = xGetPicFromView( sps->getUsableInterViewRef( k ) + viewId, poc, isDepth );
504    assert( pcRefPic != NULL );
505    apcRefPics[k] = pcRefPic;
506  }
507  return apcRefPics;
508}
509
510TComPic* TAppDecTop::xGetPicFromView( Int viewId, Int poc, Bool isDepth )
511{
512  assert( ( viewId >= 0 ) );
513
514  TComList<TComPic*>* apcListPic = getTDecTop( viewId, isDepth )->getListPic();
515  TComPic* pcPic = NULL;
516  for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ )
517  {
518    if( (*it)->getPOC() == poc )
519    {
520      pcPic = *it;
521      break;
522    }
523  }
524  return pcPic;
525}
526//! \}
Note: See TracBrowser for help on using the repository browser.