source: 3DVCSoftware/branches/HTM-5.0-Qualcomm/source/App/TAppDecoder/TAppDecTop.cpp @ 195

Last change on this file since 195 was 195, checked in by tech, 12 years ago

Changed macro switch names to match conventions.

  • Property svn:eol-style set to native
File size: 18.3 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|QC_MVHEVC_B0046
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 QC_MVHEVC_B0046
148    viewDepthId = nalu.m_layerId;
149    Int depth = 0;
150    Int viewId = viewDepthId;
151#else
152#if VIDYO_VPS_INTEGRATION
153      Int viewId = 0;
154      Int depth = 0;
155     
156      if(nalu.m_nalUnitType != NAL_UNIT_VPS || nalu.m_layerId)
157      {
158        // code assumes that the first nal unit is VPS
159        // currently, this is a hack that requires non-first VPSs have non-zero layer_id
160        viewId = getVPSAccess()->getActiveVPS()->getViewId(nalu.m_layerId);
161        depth = getVPSAccess()->getActiveVPS()->getDepthFlag(nalu.m_layerId);
162      }
163      viewDepthId = nalu.m_layerId;   // coding order T0D0T1D1T2D2
164#else
165      Int viewId = nalu.m_viewId;
166      Int depth = nalu.m_isDepth ? 1 : 0;
167      viewDepthId = viewId * 2 + depth;   // coding order T0D0T1D1T2D2
168#endif
169#endif     
170      newPicture[viewDepthId] = false;
171      if( viewDepthId >= m_tDecTop.size() )     
172      {
173#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
174        increaseNumberOfViews( viewDepthId, viewId, depth );
175#else
176        increaseNumberOfViews( viewDepthId +1 );
177#endif   
178      }
179      if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer)
180      {
181        previousPictureDecoded = false; 
182      }
183      if(m_tDecTop.size() > 1 && (viewDepthId != previousViewDepthId) && previousPictureDecoded )
184      {
185        m_tDecTop[previousViewDepthId]->executeDeblockAndAlf(uiPOC[previousViewDepthId], pcListPic[previousViewDepthId], m_iSkipFrame, m_pocLastDisplay[previousViewDepthId]);
186      } 
187      if( ( viewDepthId == 0 && (viewDepthId != previousViewDepthId) ) || m_tDecTop.size() == 1 )
188      {
189#if HHI_INTER_VIEW_RESIDUAL_PRED
190        for( Int i = 0; i < m_tDecTop.size(); i++ )
191        {
192          m_tDecTop[i]->deleteExtraPicBuffers( uiPOC[i] );
193        }
194#endif
195        for( Int i = 0; i < m_tDecTop.size(); i++ )
196        {
197          m_tDecTop[i]->compressMotion( uiPOC[i] );
198        }
199      }   
200      if( !(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) )
201      {
202#if QC_MVHEVC_B0046
203        if(viewDepthId && m_tDecTop[viewDepthId]->m_bFirstNal== false)
204        {
205          m_tDecTop[viewDepthId]->m_bFirstNal = true;
206          ParameterSetManagerDecoder* pDecV0 = m_tDecTop[0]->xGetParaSetDec();
207          m_tDecTop[viewDepthId]->xCopyVPS(pDecV0->getPrefetchedVPS(0));
208          m_tDecTop[viewDepthId]->xCopySPS(pDecV0->getPrefetchedSPS(0));
209          m_tDecTop[viewDepthId]->xCopyPPS(pDecV0->getPrefetchedPPS(0));
210        }
211#endif
212        newPicture[viewDepthId] = m_tDecTop[viewDepthId]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[viewDepthId]);
213        if (newPicture[viewDepthId])
214        {
215          bitstreamFile.clear();
216          /* location points to the current nalunit payload[1] due to the
217           * need for the annexB parser to read three extra bytes.
218           * [1] except for the first NAL unit in the file
219           *     (but bNewPicture doesn't happen then) */
220          bitstreamFile.seekg(location-streamoff(3));
221          bytestream.reset();
222        }
223        if( nalu.isSlice() )
224        {
225          previousPictureDecoded = true;
226        }
227      }
228    }
229    if( ( (newPicture[viewDepthId] || !bitstreamFile) && m_tDecTop.size() == 1) || (!bitstreamFile && previousPictureDecoded == true) ) 
230    {
231      m_tDecTop[viewDepthId]->executeDeblockAndAlf(uiPOC[viewDepthId], pcListPic[viewDepthId], m_iSkipFrame, m_pocLastDisplay[viewDepthId]);
232    }
233    if( pcListPic[viewDepthId] )
234    {
235#if QC_REM_IDV_B0046
236      Int iviewId = m_tDecTop[viewDepthId]->getViewId();
237      if( newPicture[viewDepthId] && (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR || ((nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR && iviewId) && m_tDecTop[viewDepthId]->getNalUnitTypeBaseView() == NAL_UNIT_CODED_SLICE_IDR)) )
238#else
239      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)) )
240#endif
241      {
242        xFlushOutput( pcListPic[viewDepthId], viewDepthId );
243      }
244      // write reconstruction to file
245      if(newPicture[viewDepthId])
246      {
247#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
248        xWriteOutput( pcListPic[viewDepthId], viewDepthId, nalu.m_temporalId );
249#else
250        xWriteOutput( pcListPic[viewDepthId], viewDepthId );
251#endif
252      }
253    }
254    previousViewDepthId = viewDepthId;
255  } 
256  if( m_cCamParsCollector.isInitialized() )
257  {
258    m_cCamParsCollector.setSlice( 0 );
259  }
260  // last frame
261  for( Int viewDepthIdx = 0; viewDepthIdx < m_tDecTop.size(); viewDepthIdx++ )
262  {
263    xFlushOutput( pcListPic[viewDepthIdx], viewDepthIdx );
264  } 
265  xDestroyDecLib();
266}
267
268// ====================================================================================================================
269// Protected member functions
270// ====================================================================================================================
271
272Void TAppDecTop::xDestroyDecLib()
273{
274
275  for(Int viewDepthIdx=0; viewDepthIdx<m_tVideoIOYuvReconFile.size() ; viewDepthIdx++)
276  {
277    if( m_tVideoIOYuvReconFile[viewDepthIdx] )
278    {
279      m_tVideoIOYuvReconFile[viewDepthIdx]->close();
280      delete m_tVideoIOYuvReconFile[viewDepthIdx]; 
281      m_tVideoIOYuvReconFile[viewDepthIdx] = NULL ;
282    }
283  }
284
285  for(Int viewDepthIdx=0; viewDepthIdx<m_tDecTop.size() ; viewDepthIdx++)
286  {
287    if( m_tDecTop[viewDepthIdx] )
288    {
289      if( !m_useDepth && (viewDepthIdx % 2 == 1) )
290      {
291      }
292      else
293      {
294        m_tDecTop[viewDepthIdx]->deletePicBuffer();
295        m_tDecTop[viewDepthIdx]->destroy() ;
296      }
297#if QC_MVHEVC_B0046
298      if(viewDepthIdx)
299      {
300         //Call clear function to remove the record, which has been freed during viewDepthIdx = 0 case.
301        m_tDecTop[viewDepthIdx]->xGetParaSetDec()->clearSPS();
302        m_tDecTop[viewDepthIdx]->xGetParaSetDec()->clearVPS();
303        m_tDecTop[viewDepthIdx]->xGetParaSetDec()->clearPPS();
304      }
305#endif
306      delete m_tDecTop[viewDepthIdx] ; 
307      m_tDecTop[viewDepthIdx] = NULL ;
308    }
309  }
310
311  m_cCamParsCollector.uninit();
312  if( m_pScaleOffsetFile ) 
313  { 
314    ::fclose( m_pScaleOffsetFile ); 
315  }
316}
317
318#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
319Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int viewDepthId, UInt tId )
320#else
321Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int viewDepthId )
322#endif
323{
324  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
325  Int not_displayed = 0;
326
327  while (iterPic != pcListPic->end())
328  {
329    TComPic* pcPic = *(iterPic);
330    if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[viewDepthId])
331    {
332       not_displayed++;
333    }
334    iterPic++;
335  }
336  iterPic   = pcListPic->begin();
337 
338  while (iterPic != pcListPic->end())
339  {
340    TComPic* pcPic = *(iterPic);
341#if PIC_CROPPING
342    TComSPS *sps = pcPic->getSlice(0)->getSPS();
343#endif
344   
345#if H0567_DPB_PARAMETERS_PER_TEMPORAL_LAYER
346    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderPics(tId) && pcPic->getPOC() > m_pocLastDisplay[viewDepthId]))
347#else
348    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderFrames() && pcPic->getPOC() > m_pocLastDisplay[viewDepthId]))
349#endif
350    {
351      // write to file
352       not_displayed--;
353      if ( m_pchReconFile )
354      {
355#if PIC_CROPPING
356        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
357#else
358        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
359#endif
360      }
361     
362      // update POC of display order
363      m_pocLastDisplay[viewDepthId] = pcPic->getPOC();
364     
365      // erase non-referenced picture in the reference picture list after display
366      if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
367      {
368#if !DYN_REF_FREE
369        pcPic->setReconMark(false);
370       
371        // mark it should be extended later
372        pcPic->getPicYuvRec()->setBorderExtension( false );
373       
374#else
375        pcPic->destroy();
376        pcListPic->erase( iterPic );
377        iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
378        continue;
379#endif
380      }
381      pcPic->setOutputMark(false);
382    }
383   
384    iterPic++;
385  }
386}
387
388/** \param pcListPic list of pictures to be written to file
389    \todo            DYN_REF_FREE should be revised
390 */
391Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int viewDepthId )
392{
393  if(!pcListPic)
394  {
395    return;
396  } 
397  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
398
399  iterPic   = pcListPic->begin();
400 
401  while (iterPic != pcListPic->end())
402  {
403    TComPic* pcPic = *(iterPic);
404#if PIC_CROPPING
405    TComSPS *sps = pcPic->getSlice(0)->getSPS();
406#endif
407
408    if ( pcPic->getOutputMark() )
409    {
410      // write to file
411      if ( m_pchReconFile )
412      {
413#if PIC_CROPPING
414        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
415#else
416        m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), pcPic->getSlice(0)->getSPS()->getPad() );
417#endif
418      }
419     
420      // update POC of display order
421      m_pocLastDisplay[viewDepthId] = 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      pcPic->setOutputMark(false);
440    }
441   
442    iterPic++;
443  }
444  pcListPic->clear();
445  m_pocLastDisplay[viewDepthId] = -MAX_INT;
446}
447#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
448Void  TAppDecTop::increaseNumberOfViews  ( UInt layerId, UInt viewId, UInt isDepth )
449#else
450Void  TAppDecTop::increaseNumberOfViews  ( Int newNumberOfViewDepth )
451#endif
452{
453#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
454  Int newNumberOfViewDepth = layerId + 1;
455#endif
456  if ( m_outputBitDepth == 0 )
457  {
458    m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
459  }
460#if !VIDYO_VPS_INTEGRATION&!QC_MVHEVC_B0046
461  Int viewId = (newNumberOfViewDepth-1)>>1;   // coding order T0D0T1D1T2D2
462  Bool isDepth = ((newNumberOfViewDepth % 2) == 0);  // coding order T0D0T1D1T2D2
463#endif
464  if( isDepth )
465    m_useDepth = true;
466
467  if ( m_pchReconFile )
468  { 
469    while( m_tVideoIOYuvReconFile.size() < newNumberOfViewDepth)
470    {
471      m_tVideoIOYuvReconFile.push_back(new TVideoIOYuv);
472      Char buffer[4];
473#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
474      sprintf(buffer,"_%i", viewId );
475#else
476      sprintf(buffer,"_%i", (Int)(m_tVideoIOYuvReconFile.size()-1) / 2 );
477#endif
478      Char* nextFilename = NULL;
479#if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046
480      if( isDepth)
481#else
482      if( (m_tVideoIOYuvReconFile.size() % 2) == 0 )
483#endif
484      {
485        Char* pchTempFilename = NULL;
486        xAppendToFileNameEnd( m_pchReconFile, "_depth", pchTempFilename);
487        xAppendToFileNameEnd( pchTempFilename, buffer, nextFilename);
488        free ( pchTempFilename );
489      }
490      else
491      {
492        xAppendToFileNameEnd( m_pchReconFile, buffer, nextFilename);
493      }
494#if !VIDYO_VPS_INTEGRATION&!QC_MVHEVC_B0046
495      if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
496#endif
497      {
498        m_tVideoIOYuvReconFile.back()->open( nextFilename, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement );
499      }
500      free ( nextFilename );
501    }
502  }
503
504  while( m_pocLastDisplay.size() < newNumberOfViewDepth )
505  {
506    m_pocLastDisplay.push_back(-MAX_INT+m_iSkipFrame);
507  }
508  while( m_tDecTop.size() < newNumberOfViewDepth)
509  {
510    m_tDecTop.push_back(new TDecTop);
511#if !VIDYO_VPS_INTEGRATION&!QC_MVHEVC_B0046
512    if( isDepth || ( !isDepth && (m_tVideoIOYuvReconFile.size() % 2) == 1 ) )
513    {
514#endif
515      m_tDecTop.back()->create();
516      m_tDecTop.back()->init( this, newNumberOfViewDepth == 1);
517      m_tDecTop.back()->setViewId( viewId );
518      m_tDecTop.back()->setIsDepth( isDepth );
519      m_tDecTop.back()->setPictureDigestEnabled(m_pictureDigestEnabled);
520      m_tDecTop.back()->setCamParsCollector( &m_cCamParsCollector );
521#if !VIDYO_VPS_INTEGRATION&!QC_MVHEVC_B0046
522    }
523#endif
524  }
525}
526
527TDecTop* TAppDecTop::getTDecTop( Int viewId, Bool isDepth )
528{ 
529  return m_tDecTop[(isDepth ? 1 : 0) + viewId * 2];  // coding order T0D0T1D1T2D2
530} 
531
532std::vector<TComPic*> TAppDecTop::getInterViewRefPics( Int viewId, Int poc, Bool isDepth, TComSPS* sps )
533{
534  std::vector<TComPic*> apcRefPics( sps->getNumberOfUsableInterViewRefs(), (TComPic*)NULL );
535  for( Int k = 0; k < sps->getNumberOfUsableInterViewRefs(); k++ )
536  {
537    TComPic* pcRefPic = xGetPicFromView( sps->getUsableInterViewRef( k ) + viewId, poc, isDepth );
538    assert( pcRefPic != NULL );
539    apcRefPics[k] = pcRefPic;
540  }
541  return apcRefPics;
542}
543
544TComPic* TAppDecTop::xGetPicFromView( Int viewId, Int poc, Bool isDepth )
545{
546  assert( ( viewId >= 0 ) );
547
548  TComList<TComPic*>* apcListPic = getTDecTop( viewId, isDepth )->getListPic();
549  TComPic* pcPic = NULL;
550  for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ )
551  {
552    if( (*it)->getPOC() == poc )
553    {
554      pcPic = *it;
555      break;
556    }
557  }
558  return pcPic;
559}
560//! \}
Note: See TracBrowser for help on using the repository browser.