source: SHVCSoftware/branches/SHM-1.1-dev/source/Lib/TLibDecoder/TDecGop.cpp @ 42

Last change on this file since 42 was 28, checked in by seregin, 12 years ago

Reintegrate SHM-1.0-dev branch

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