source: SHVCSoftware/trunk/source/Lib/TLibDecoder/TDecGop.cpp @ 588

Last change on this file since 588 was 588, checked in by seregin, 11 years ago

merge with SHM-5.0-dev

  • Property svn:eol-style set to native
File size: 12.8 KB
RevLine 
[313]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-2013, 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     TDecGop.cpp
35    \brief    GOP decoder class
36*/
37
38#include "TDecGop.h"
39#include "TDecCAVLC.h"
40#include "TDecSbac.h"
41#include "TDecBinCoder.h"
42#include "TDecBinCoderCABAC.h"
43#include "libmd5/MD5.h"
44#include "TLibCommon/SEI.h"
45#if SVC_EXTENSION
46#include "TDecTop.h"
47#endif
48
49#include <time.h>
50
51extern Bool g_md5_mismatch; ///< top level flag to signal when there is a decode problem
52
53//! \ingroup TLibDecoder
54//! \{
55static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI);
56// ====================================================================================================================
57// Constructor / destructor / initialization / destroy
58// ====================================================================================================================
59
60TDecGop::TDecGop()
61{
62  m_dDecTime = 0;
63  m_pcSbacDecoders = NULL;
64  m_pcBinCABACs = NULL;
65}
66
67TDecGop::~TDecGop()
68{
69 
70}
71
72#if SVC_EXTENSION
73Void TDecGop::create(UInt layerId)
74{
75  m_layerId = layerId;
76}
77#else
78Void TDecGop::create()
79{
80 
81}
82#endif
83
84Void TDecGop::destroy()
85{
86}
87#if SVC_EXTENSION
88Void TDecGop::init(TDecTop**               ppcDecTop,
89                   TDecEntropy*            pcEntropyDecoder,
90#else
91Void TDecGop::init( TDecEntropy*            pcEntropyDecoder, 
92#endif
93                   TDecSbac*               pcSbacDecoder, 
94                   TDecBinCABAC*           pcBinCABAC,
95                   TDecCavlc*              pcCavlcDecoder, 
96                   TDecSlice*              pcSliceDecoder, 
97                   TComLoopFilter*         pcLoopFilter,
98                   TComSampleAdaptiveOffset* pcSAO
99                   )
100{
101  m_pcEntropyDecoder      = pcEntropyDecoder;
102  m_pcSbacDecoder         = pcSbacDecoder;
103  m_pcBinCABAC            = pcBinCABAC;
104  m_pcCavlcDecoder        = pcCavlcDecoder;
105  m_pcSliceDecoder        = pcSliceDecoder;
106  m_pcLoopFilter          = pcLoopFilter;
107  m_pcSAO  = pcSAO;
108#if SVC_EXTENSION   
109  m_ppcTDecTop            = ppcDecTop;
110#endif
111}
112
113
114// ====================================================================================================================
115// Private member functions
116// ====================================================================================================================
117// ====================================================================================================================
118// Public member functions
119// ====================================================================================================================
120
121Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic)
122{
123  TComSlice*  pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx());
124  // Table of extracted substreams.
125  // These must be deallocated AND their internal fifos, too.
126  TComInputBitstream **ppcSubstreams = NULL;
127
128  //-- For time output for each slice
129  long iBeforeTime = clock();
[540]130#if !HM_CLEANUP_SAO
[313]131  UInt uiStartCUAddr   = pcSlice->getSliceSegmentCurStartCUAddr();
132
133  UInt uiSliceStartCuAddr = pcSlice->getSliceCurStartCUAddr();
134  if(uiSliceStartCuAddr == uiStartCUAddr)
135  {
136    m_sliceStartCUAddress.push_back(uiSliceStartCuAddr);
137  }
[540]138#endif
[313]139  m_pcSbacDecoder->init( (TDecBinIf*)m_pcBinCABAC );
140  m_pcEntropyDecoder->setEntropyDecoder (m_pcSbacDecoder);
141
142  UInt uiNumSubstreams = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcSlice->getNumEntryPointOffsets()+1 : pcSlice->getPPS()->getNumSubstreams();
143
144  // init each couple {EntropyDecoder, Substream}
145  UInt *puiSubstreamSizes = pcSlice->getSubstreamSizes();
146  ppcSubstreams    = new TComInputBitstream*[uiNumSubstreams];
147  m_pcSbacDecoders = new TDecSbac[uiNumSubstreams];
148  m_pcBinCABACs    = new TDecBinCABAC[uiNumSubstreams];
149  for ( UInt ui = 0 ; ui < uiNumSubstreams ; ui++ )
150  {
151    m_pcSbacDecoders[ui].init(&m_pcBinCABACs[ui]);
152    ppcSubstreams[ui] = pcBitstream->extractSubstream(ui+1 < uiNumSubstreams ? puiSubstreamSizes[ui] : pcBitstream->getNumBitsLeft());
153  }
154
155  for ( UInt ui = 0 ; ui+1 < uiNumSubstreams; ui++ )
156  {
157    m_pcEntropyDecoder->setEntropyDecoder ( &m_pcSbacDecoders[uiNumSubstreams - 1 - ui] );
158    m_pcEntropyDecoder->setBitstream      (  ppcSubstreams   [uiNumSubstreams - 1 - ui] );
159    m_pcEntropyDecoder->resetEntropy      (pcSlice);
160  }
161
162  m_pcEntropyDecoder->setEntropyDecoder ( m_pcSbacDecoder  );
163  m_pcEntropyDecoder->setBitstream      ( ppcSubstreams[0] );
164  m_pcEntropyDecoder->resetEntropy      (pcSlice);
[540]165#if !HM_CLEANUP_SAO
[313]166  if(uiSliceStartCuAddr == uiStartCUAddr)
167  {
168    m_LFCrossSliceBoundaryFlag.push_back( pcSlice->getLFCrossSliceBoundaryFlag());
169  }
[540]170#endif
[313]171  m_pcSbacDecoders[0].load(m_pcSbacDecoder);
172  m_pcSliceDecoder->decompressSlice( ppcSubstreams, rpcPic, m_pcSbacDecoder, m_pcSbacDecoders);
173  m_pcEntropyDecoder->setBitstream(  ppcSubstreams[uiNumSubstreams-1] );
174  // deallocate all created substreams, including internal buffers.
175  for (UInt ui = 0; ui < uiNumSubstreams; ui++)
176  {
177    ppcSubstreams[ui]->deleteFifo();
178    delete ppcSubstreams[ui];
179  }
180  delete[] ppcSubstreams;
181  delete[] m_pcSbacDecoders; m_pcSbacDecoders = NULL;
182  delete[] m_pcBinCABACs; m_pcBinCABACs = NULL;
183
184  m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
185}
186
187Void TDecGop::filterPicture(TComPic*& rpcPic)
188{
189  TComSlice*  pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx());
190
191  //-- For time output for each slice
192  long iBeforeTime = clock();
193
194  // deblocking filter
195  Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag();
196  m_pcLoopFilter->setCfg(bLFCrossTileBoundary);
197  m_pcLoopFilter->loopFilterPic( rpcPic );
[540]198#if !HM_CLEANUP_SAO
[313]199  if(pcSlice->getSPS()->getUseSAO())
200  {
201    m_sliceStartCUAddress.push_back(rpcPic->getNumCUsInFrame()* rpcPic->getNumPartInCU());
202    rpcPic->createNonDBFilterInfo(m_sliceStartCUAddress, 0, &m_LFCrossSliceBoundaryFlag, rpcPic->getPicSym()->getNumTiles(), bLFCrossTileBoundary);
203  }
[540]204#endif
[313]205  if( pcSlice->getSPS()->getUseSAO() )
206  {
[540]207#if HM_CLEANUP_SAO
208    m_pcSAO->reconstructBlkSAOParams(rpcPic, rpcPic->getPicSym()->getSAOBlkParam());
209    m_pcSAO->SAOProcess(rpcPic);
210    m_pcSAO->PCMLFDisableProcess(rpcPic);
211#else
[313]212    {
213      SAOParam *saoParam = rpcPic->getPicSym()->getSaoParam();
214      saoParam->bSaoFlag[0] = pcSlice->getSaoEnabledFlag();
215      saoParam->bSaoFlag[1] = pcSlice->getSaoEnabledFlagChroma();
216      m_pcSAO->setSaoLcuBasedOptimization(1);
217      m_pcSAO->createPicSaoInfo(rpcPic);
218      m_pcSAO->SAOProcess(saoParam);
219      m_pcSAO->PCMLFDisableProcess(rpcPic);
220      m_pcSAO->destroyPicSaoInfo();
221    }
[540]222#endif
[313]223  }
[540]224#if !HM_CLEANUP_SAO
[313]225  if(pcSlice->getSPS()->getUseSAO())
226  {
227    rpcPic->destroyNonDBFilterInfo();
228  }
[540]229#endif
[313]230  rpcPic->compressMotion(); 
231  Char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
232  if (!pcSlice->isReferenced()) c += 32;
233
234  //-- For time output for each slice
235#if SVC_EXTENSION
[588]236  printf("\nPOC %4d LId: %1d TId: %1d ( %c-SLICE %s, QP%3d ) ", pcSlice->getPOC(),
[313]237                                                    rpcPic->getLayerId(),
238                                                    pcSlice->getTLayer(),
239                                                    c,
[588]240                                                    NaluToStr( pcSlice->getNalUnitType() ).data(),
[313]241                                                    pcSlice->getSliceQp() );
242#else
243  printf("\nPOC %4d TId: %1d ( %c-SLICE, QP%3d ) ", pcSlice->getPOC(),
244                                                    pcSlice->getTLayer(),
245                                                    c,
246                                                    pcSlice->getSliceQp() );
247#endif
248  m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
249  printf ("[DT %6.3f] ", m_dDecTime );
250  m_dDecTime  = 0;
251
252  for (Int iRefList = 0; iRefList < 2; iRefList++)
253  {
254    printf ("[L%d ", iRefList);
255    for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++)
256    {
[442]257#if SVC_EXTENSION
258#if VPS_EXTN_DIRECT_REF_LAYERS
[313]259      if( pcSlice->getRefPic(RefPicList(iRefList), iRefIndex)->isILR( m_layerId ) )
260      {
[442]261        printf( "%d(%d)", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex), pcSlice->getRefPic(RefPicList(iRefList), iRefIndex)->getLayerId() );
[313]262      }
263      else
[442]264      {
265        printf ("%d", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex));
266      }
[313]267#endif
[442]268      if( pcSlice->getEnableTMVPFlag() && iRefList == 1 - pcSlice->getColFromL0Flag() && iRefIndex == pcSlice->getColRefIdx() )
269      {
270        printf( "c" );
271      }
272
273      printf( " " );
274#else
[313]275      printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex));
[442]276#endif
[313]277    }
278    printf ("] ");
279  }
280  if (m_decodedPictureHashSEIEnabled)
281  {
282    SEIMessages pictureHashes = getSeisByType(rpcPic->getSEIs(), SEI::DECODED_PICTURE_HASH );
283    const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL;
284    if (pictureHashes.size() > 1)
285    {
286      printf ("Warning: Got multiple decoded picture hash SEI messages. Using first.");
287    }
288    calcAndPrintHashStatus(*rpcPic->getPicYuvRec(), hash);
289  }
290
291  rpcPic->setOutputMark(true);
292  rpcPic->setReconMark(true);
[540]293#if !HM_CLEANUP_SAO
[313]294  m_sliceStartCUAddress.clear();
295  m_LFCrossSliceBoundaryFlag.clear();
[540]296#endif
[313]297}
298
299/**
300 * Calculate and print hash for pic, compare to picture_digest SEI if
301 * present in seis.  seis may be NULL.  Hash is printed to stdout, in
302 * a manner suitable for the status line. Theformat is:
303 *  [Hash_type:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,(yyy)]
304 * Where, x..x is the hash
305 *        yyy has the following meanings:
306 *            OK          - calculated hash matches the SEI message
307 *            ***ERROR*** - calculated hash does not match the SEI message
308 *            unk         - no SEI message was available for comparison
309 */
310static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI)
311{
312  /* calculate MD5sum for entire reconstructed picture */
313  UChar recon_digest[3][16];
314  Int numChar=0;
315  const Char* hashType = "\0";
316
317  if (pictureHashSEI)
318  {
319    switch (pictureHashSEI->method)
320    {
321    case SEIDecodedPictureHash::MD5:
322      {
323        hashType = "MD5";
324        calcMD5(pic, recon_digest);
325        numChar = 16;
326        break;
327      }
328    case SEIDecodedPictureHash::CRC:
329      {
330        hashType = "CRC";
331        calcCRC(pic, recon_digest);
332        numChar = 2;
333        break;
334      }
335    case SEIDecodedPictureHash::CHECKSUM:
336      {
337        hashType = "Checksum";
338        calcChecksum(pic, recon_digest);
339        numChar = 4;
340        break;
341      }
342    default:
343      {
344        assert (!"unknown hash type");
345      }
346    }
347  }
348
349  /* compare digest against received version */
350  const Char* ok = "(unk)";
351  Bool mismatch = false;
352
353  if (pictureHashSEI)
354  {
355    ok = "(OK)";
356    for(Int yuvIdx = 0; yuvIdx < 3; yuvIdx++)
357    {
358      for (UInt i = 0; i < numChar; i++)
359      {
360        if (recon_digest[yuvIdx][i] != pictureHashSEI->digest[yuvIdx][i])
361        {
362          ok = "(***ERROR***)";
363          mismatch = true;
364        }
365      }
366    }
367  }
368
369  printf("[%s:%s,%s] ", hashType, digestToString(recon_digest, numChar), ok);
370
371  if (mismatch)
372  {
373    g_md5_mismatch = true;
374    printf("[rx%s:%s] ", hashType, digestToString(pictureHashSEI->digest, numChar));
375  }
376}
377//! \}
Note: See TracBrowser for help on using the repository browser.