source: SHVCSoftware/branches/0.1.1-bugfix/source/App/TAppDecoder/TAppDecTop.cpp @ 8

Last change on this file since 8 was 6, checked in by seregin, 12 years ago

Correct IntraBL cost and fix for couple of compiler warnings.

File size: 19.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-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#if SVC_EXTENSION
59  for(UInt layer=0; layer < MAX_LAYERS; layer++)
60  {
61    m_aiPOCLastDisplay[layer]  = -MAX_INT;
62    m_apcTDecTop[layer] = &m_acTDecTop[layer];
63  }
64#else
65  m_iPOCLastDisplay  = -MAX_INT;
66#endif
67
68}
69
70Void TAppDecTop::create()
71{
72}
73
74Void TAppDecTop::destroy()
75{
76  if (m_pchBitstreamFile)
77  {
78    free (m_pchBitstreamFile);
79    m_pchBitstreamFile = NULL;
80  }
81#if SVC_EXTENSION   
82  for( Int i = 0; i < m_tgtLayerId; i++ )
83  {
84    if( m_pchReconFile[i] )
85    {
86      free ( m_pchReconFile[i] );
87      m_pchReconFile[i] = NULL;
88    }
89  } 
90#if AVC_BASE
91  if( m_pchBLReconFile )
92  {
93    free ( m_pchBLReconFile );
94    m_pchBLReconFile = NULL;
95  }
96#endif
97#else
98  if (m_pchReconFile)
99  {
100    free (m_pchReconFile);
101    m_pchReconFile = NULL;
102  }
103#endif
104}
105
106// ====================================================================================================================
107// Public member functions
108// ====================================================================================================================
109
110/**
111 - create internal class
112 - initialize internal class
113 - until the end of the bitstream, call decoding function in TDecTop class
114 - delete allocated buffers
115 - destroy internal class
116 .
117 */
118#if SVC_EXTENSION
119Void TAppDecTop::decode()
120{
121  UInt                uiPOC;
122  TComList<TComPic*>* pcListPic = NULL;
123
124  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
125  if (!bitstreamFile)
126  {
127    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
128    exit(EXIT_FAILURE);
129  }
130
131  InputByteStream bytestream(bitstreamFile);
132
133  // create & initialize internal classes
134  xCreateDecLib();
135  xInitDecLib  ();
136
137  // main decoder loop
138  bool recon_opened[MAX_LAYERS]; // reconstruction file not yet opened. (must be performed after SPS is seen)
139  for(UInt layer=0; layer<=m_tgtLayerId; layer++)
140  {
141    recon_opened[layer] = false;
142    m_aiPOCLastDisplay[layer] += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
143  }
144
145  UInt curLayerId = 0;     // current layer to be reconstructed
146
147#if AVC_BASE
148  TComPic pcBLPic;
149  FILE* pFile = fopen( m_pchBLReconFile, "rb" );
150  if( !pFile )
151  {
152    printf( "BL input reading error\n" );
153    exit(0);
154  }
155  TComList<TComPic*> *cListPic = m_acTDecTop[0].getListPic();
156  m_acTDecTop[0].setBLsize( m_iBLSourceWidth, m_iBLSourceHeight );
157  m_acTDecTop[0].setBLReconFile( pFile );
158  pcBLPic.setLayerId( 0 );
159  cListPic->pushBack( &pcBLPic );
160#endif
161
162  while (!!bitstreamFile)
163  {
164    /* location serves to work around a design fault in the decoder, whereby
165     * the process of reading a new slice that is the first slice of a new frame
166     * requires the TDecTop::decode() method to be called again with the same
167     * nal unit. */
168    streampos location = bitstreamFile.tellg();
169    AnnexBStats stats = AnnexBStats();
170
171    vector<uint8_t> nalUnit;
172    InputNALUnit nalu;
173    byteStreamNALUnit(bytestream, nalUnit, stats);
174
175    // call actual decoding function
176    bool bNewPicture = false;
177    bool bNewPOC = false;
178    if (nalUnit.empty())
179    {
180      /* this can happen if the following occur:
181       *  - empty input file
182       *  - two back-to-back start_code_prefixes
183       *  - start_code_prefix immediately followed by EOF
184       */
185      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
186    }
187    else
188    {
189      read(nalu, nalUnit);
190#if TARGET_DECLAYERID_SET
191      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  ||
192        (nalu.m_layerId > m_tgtLayerId) )
193#else
194      if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer ||
195        (nalu.m_layerId > m_tgtLayerId) )
196#endif
197      {
198        bNewPicture = false;
199      }
200      else
201      {
202        bNewPicture = m_acTDecTop[nalu.m_layerId].decode(nalu, m_iSkipFrame, m_aiPOCLastDisplay[nalu.m_layerId], curLayerId, bNewPOC);
203        if (bNewPicture)
204        {
205          bitstreamFile.clear();
206          /* location points to the current nalunit payload[1] due to the
207           * need for the annexB parser to read three extra bytes.
208           * [1] except for the first NAL unit in the file
209           *     (but bNewPicture doesn't happen then) */
210          bitstreamFile.seekg(location-streamoff(3));
211          bytestream.reset();
212        }
213      }
214    }
215    if (bNewPicture || !bitstreamFile)
216    {
217      m_acTDecTop[curLayerId].executeDeblockAndAlf(uiPOC, pcListPic, m_iSkipFrame, m_aiPOCLastDisplay[curLayerId]);
218    }
219
220    if( pcListPic )
221    {
222      if ( m_pchReconFile[curLayerId] && !recon_opened[curLayerId] )
223      {
224        if ( m_outputBitDepth == 0 )
225        {
226          m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
227        }
228
229        m_acTVideoIOYuvReconFile[curLayerId].open( m_pchReconFile[curLayerId], true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement ); // write mode
230        recon_opened[curLayerId] = true;
231      }
232      if ( bNewPicture && bNewPOC && 
233           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR
234#if SUPPORT_FOR_RAP_N_LP
235            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
236            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
237#endif
238            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLANT
239            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA ) )
240      {
241        xFlushOutput( pcListPic, curLayerId );
242      }
243      // write reconstruction to file
244      if(bNewPicture)
245      {
246        xWriteOutput( pcListPic, curLayerId, nalu.m_temporalId );
247      }
248    }
249  }
250  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
251  {
252    xFlushOutput( m_acTDecTop[layer].getListPic(), layer );
253  }
254  // delete buffers
255#if AVC_BASE
256  if( pFile )
257  {
258    fclose( pFile );
259  }
260  pcBLPic.destroy();
261
262  for(UInt layer = 1; layer <= m_tgtLayerId; layer++)
263#else
264  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
265#endif
266  {
267    m_acTDecTop[layer].deletePicBuffer();
268  }
269 
270  // destroy internal classes
271  xDestroyDecLib();
272}
273#else
274Void TAppDecTop::decode()
275{
276  UInt                uiPOC;
277  TComList<TComPic*>* pcListPic = NULL;
278
279  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
280  if (!bitstreamFile)
281  {
282    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
283    exit(EXIT_FAILURE);
284  }
285
286  InputByteStream bytestream(bitstreamFile);
287
288  // create & initialize internal classes
289  xCreateDecLib();
290  xInitDecLib  ();
291  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
292
293  // main decoder loop
294  bool recon_opened = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
295
296  while (!!bitstreamFile)
297  {
298    /* location serves to work around a design fault in the decoder, whereby
299     * the process of reading a new slice that is the first slice of a new frame
300     * requires the TDecTop::decode() method to be called again with the same
301     * nal unit. */
302    streampos location = bitstreamFile.tellg();
303    AnnexBStats stats = AnnexBStats();
304    bool bPreviousPictureDecoded = false;
305
306    vector<uint8_t> nalUnit;
307    InputNALUnit nalu;
308    byteStreamNALUnit(bytestream, nalUnit, stats);
309
310    // call actual decoding function
311    bool bNewPicture = false;
312    if (nalUnit.empty())
313    {
314      /* this can happen if the following occur:
315       *  - empty input file
316       *  - two back-to-back start_code_prefixes
317       *  - start_code_prefix immediately followed by EOF
318       */
319      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
320    }
321    else
322    {
323      read(nalu, nalUnit);
324#if TARGET_DECLAYERID_SET
325      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
326#else
327      if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer)
328#endif
329      {
330        if(bPreviousPictureDecoded)
331        {
332          bNewPicture = true;
333          bPreviousPictureDecoded = false;
334        }
335        else
336        {
337          bNewPicture = false;
338        }
339      }
340      else
341      {
342        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
343        if (bNewPicture)
344        {
345          bitstreamFile.clear();
346          /* location points to the current nalunit payload[1] due to the
347           * need for the annexB parser to read three extra bytes.
348           * [1] except for the first NAL unit in the file
349           *     (but bNewPicture doesn't happen then) */
350          bitstreamFile.seekg(location-streamoff(3));
351          bytestream.reset();
352        }
353        bPreviousPictureDecoded = true; 
354      }
355    }
356    if (bNewPicture || !bitstreamFile)
357    {
358      m_cTDecTop.executeDeblockAndAlf(uiPOC, pcListPic, m_iSkipFrame, m_iPOCLastDisplay);
359    }
360
361    if( pcListPic )
362    {
363      if ( m_pchReconFile && !recon_opened )
364      {
365        if ( m_outputBitDepth == 0 )
366        {
367          m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement;
368        }
369
370        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement ); // write mode
371        recon_opened = true;
372      }
373      if ( bNewPicture && 
374           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR
375#if SUPPORT_FOR_RAP_N_LP
376            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
377            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
378#endif
379            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLANT
380            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA ) )
381      {
382        xFlushOutput( pcListPic );
383      }
384      // write reconstruction to file
385      if(bNewPicture)
386      {
387        xWriteOutput( pcListPic, nalu.m_temporalId );
388      }
389    }
390  }
391 
392  xFlushOutput( pcListPic );
393  // delete buffers
394  m_cTDecTop.deletePicBuffer();
395 
396  // destroy internal classes
397  xDestroyDecLib();
398}
399#endif
400
401// ====================================================================================================================
402// Protected member functions
403// ====================================================================================================================
404
405Void TAppDecTop::xCreateDecLib()
406{
407#if SVC_EXTENSION
408  // initialize global variables
409  initROM(); 
410
411  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
412  {
413    // set layer ID
414    m_acTDecTop[layer].setLayerId                      ( layer );
415
416    // create decoder class
417    m_acTDecTop[layer].create();
418
419    m_acTDecTop[layer].setLayerDec(m_apcTDecTop);   
420  }
421#else
422  // create decoder class
423  m_cTDecTop.create();
424#endif
425}
426
427Void TAppDecTop::xDestroyDecLib()
428{
429#if SVC_EXTENSION
430  // destroy ROM
431  destroyROM();
432
433  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
434  {
435    if ( m_pchReconFile[layer] )
436    {
437      m_acTVideoIOYuvReconFile[layer]. close();
438    }
439
440    // destroy decoder class
441    m_acTDecTop[layer].destroy();
442  }
443#else
444  if ( m_pchReconFile )
445  {
446    m_cTVideoIOYuvReconFile. close();
447  }
448 
449  // destroy decoder class
450  m_cTDecTop.destroy();
451#endif
452}
453
454Void TAppDecTop::xInitDecLib()
455{
456  // initialize decoder class
457#if SVC_EXTENSION
458  for(UInt layer = 0; layer <= m_tgtLayerId; layer++)
459  {
460    m_acTDecTop[layer].init();
461    m_acTDecTop[layer].setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
462    m_acTDecTop[layer].setNumLayer( m_tgtLayerId + 1 );
463  }
464
465#else
466  m_cTDecTop.init();
467  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
468#endif
469}
470
471/** \param pcListPic list of pictures to be written to file
472    \todo            DYN_REF_FREE should be revised
473 */
474#if SVC_EXTENSION
475Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt layerId, UInt tId )
476#else
477Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId )
478#endif
479{
480  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
481  Int not_displayed = 0;
482
483  while (iterPic != pcListPic->end())
484  {
485    TComPic* pcPic = *(iterPic);
486#if SVC_EXTENSION
487    if(pcPic->getOutputMark() && pcPic->getPOC() > m_aiPOCLastDisplay[layerId])
488#else
489    if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay)
490#endif
491    {
492       not_displayed++;
493    }
494    iterPic++;
495  }
496  iterPic   = pcListPic->begin();
497 
498  while (iterPic != pcListPic->end())
499  {
500    TComPic* pcPic = *(iterPic);
501    TComSPS *sps = pcPic->getSlice(0)->getSPS();
502   
503#if SVC_EXTENSION
504    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderPics(tId) && pcPic->getPOC() > m_aiPOCLastDisplay[layerId]))
505#else
506    if ( pcPic->getOutputMark() && (not_displayed >  pcPic->getSlice(0)->getSPS()->getNumReorderPics(tId) && pcPic->getPOC() > m_iPOCLastDisplay))
507#endif
508    {
509      // write to file
510       not_displayed--;
511#if SVC_EXTENSION
512      if ( m_pchReconFile[layerId] )
513      {
514        m_acTVideoIOYuvReconFile[layerId].write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
515      }
516     
517      // update POC of display order
518      m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
519#else
520      if ( m_pchReconFile )
521      {
522        m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
523      }
524     
525      // update POC of display order
526      m_iPOCLastDisplay = pcPic->getPOC();
527#endif
528     
529      // erase non-referenced picture in the reference picture list after display
530      if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
531      {
532#if !DYN_REF_FREE
533        pcPic->setReconMark(false);
534       
535        // mark it should be extended later
536        pcPic->getPicYuvRec()->setBorderExtension( false );
537       
538#else
539        pcPic->destroy();
540        pcListPic->erase( iterPic );
541        iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
542        continue;
543#endif
544      }
545      pcPic->setOutputMark(false);
546    }
547   
548    iterPic++;
549  }
550}
551
552/** \param pcListPic list of pictures to be written to file
553    \todo            DYN_REF_FREE should be revised
554 */
555#if SVC_EXTENSION
556Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, UInt layerId )
557#else
558Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic )
559#endif
560{
561  if(!pcListPic)
562  {
563    return;
564  } 
565  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
566
567  iterPic   = pcListPic->begin();
568 
569  while (iterPic != pcListPic->end())
570  {
571    TComPic* pcPic = *(iterPic);
572    TComSPS *sps = pcPic->getSlice(0)->getSPS();
573
574    if ( pcPic->getOutputMark() )
575    {
576      // write to file
577#if SVC_EXTENSION
578      if ( m_pchReconFile[layerId] )
579      {
580        m_acTVideoIOYuvReconFile[layerId].write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
581      }
582     
583      // update POC of display order
584      m_aiPOCLastDisplay[layerId] = pcPic->getPOC();
585#else
586      if ( m_pchReconFile )
587      {
588        m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() );
589      }
590     
591      // update POC of display order
592      m_iPOCLastDisplay = pcPic->getPOC();
593#endif
594     
595      // erase non-referenced picture in the reference picture list after display
596      if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
597      {
598#if !DYN_REF_FREE
599        pcPic->setReconMark(false);
600       
601        // mark it should be extended later
602        pcPic->getPicYuvRec()->setBorderExtension( false );
603       
604#else
605        pcPic->destroy();
606        pcListPic->erase( iterPic );
607        iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
608        continue;
609#endif
610      }
611      pcPic->setOutputMark(false);
612    }
613#if !SVC_EXTENSION
614#if !DYN_REF_FREE
615    if(pcPic)
616    {
617      pcPic->destroy();
618      delete pcPic;
619      pcPic = NULL;
620    }
621#endif
622#endif
623    iterPic++;
624  }
625#if SVC_EXTENSION
626  m_aiPOCLastDisplay[layerId] = -MAX_INT;
627#else
628  pcListPic->clear(); //k Cannot be cleared here. Otherwise, pictures will never be destroyed.
629  m_iPOCLastDisplay = -MAX_INT;
630#endif
631}
632
633#if TARGET_DECLAYERID_SET
634/** \param nalu Input nalu to check whether its LayerId is within targetDecLayerIdSet
635 */
636Bool TAppDecTop::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu )
637{
638  if ( m_targetDecLayerIdSet.size() == 0 ) // By default, the set is empty, meaning all LayerIds are allowed
639  {
640    return true;
641  }
642  for (std::vector<Int>::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++)
643  {
644    if ( nalu->m_reservedZero6Bits == (*it) )
645    {
646      return true;
647    }
648  }
649  return false;
650}
651#endif
652
653//! \}
Note: See TracBrowser for help on using the repository browser.