source: 3DVCSoftware/trunk/source/Lib/TLibDecoder/TDecGop.cpp @ 341

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

Reintegrated branch 5.1-dev0 rev. 295.

  • Property svn:eol-style set to native
File size: 18.4 KB
RevLine 
[5]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
[56]4 * granted under this license. 
[5]5 *
[56]6 * Copyright (c) 2010-2012, ITU/ISO/IEC
[5]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.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]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 */
[2]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"
[56]45#include "libmd5/MD5.h"
46#include "TLibCommon/SEI.h"
[2]47
48#include <time.h>
49
[56]50//! \ingroup TLibDecoder
51//! \{
52
[2]53static void calcAndPrintMD5Status(TComPicYuv& pic, const SEImessages* seis);
54
55// ====================================================================================================================
56// Constructor / destructor / initialization / destroy
57// ====================================================================================================================
58
59TDecGop::TDecGop()
60{
61  m_iGopSize = 0;
62  m_dDecTime = 0;
[56]63  m_pcSbacDecoders = NULL;
64  m_pcBinCABACs = NULL;
65  m_first = true;
[2]66}
67
68TDecGop::~TDecGop()
69{
70 
71}
72
73Void TDecGop::create()
74{
75 
76}
77
78
79Void TDecGop::destroy()
80{
[56]81  m_alfParamSetPilot.releaseALFParam();
[2]82}
83
84Void TDecGop::init( TDecEntropy*            pcEntropyDecoder, 
85                   TDecSbac*               pcSbacDecoder, 
86                   TDecBinCABAC*           pcBinCABAC,
87                   TDecCavlc*              pcCavlcDecoder, 
88                   TDecSlice*              pcSliceDecoder, 
89                   TComLoopFilter*         pcLoopFilter, 
[56]90                   TComAdaptiveLoopFilter* pcAdaptiveLoopFilter
91                   ,TComSampleAdaptiveOffset* pcSAO
[5]92#if DEPTH_MAP_GENERATION
[56]93                   ,TComDepthMapGenerator*  pcDepthMapGenerator
[5]94#endif
[296]95#if H3D_IVRP
[56]96                  ,TComResidualGenerator*  pcResidualGenerator
[5]97#endif
[56]98                   )
[2]99{
100  m_pcEntropyDecoder      = pcEntropyDecoder;
101  m_pcSbacDecoder         = pcSbacDecoder;
102  m_pcBinCABAC            = pcBinCABAC;
103  m_pcCavlcDecoder        = pcCavlcDecoder;
104  m_pcSliceDecoder        = pcSliceDecoder;
105  m_pcLoopFilter          = pcLoopFilter;
106  m_pcAdaptiveLoopFilter  = pcAdaptiveLoopFilter;
107  m_pcSAO  = pcSAO;
[5]108#if DEPTH_MAP_GENERATION
[2]109  m_pcDepthMapGenerator   = pcDepthMapGenerator;
[5]110#endif
[296]111#if H3D_IVRP
[2]112  m_pcResidualGenerator   = pcResidualGenerator;
[5]113#endif
[2]114}
115
[56]116
[2]117// ====================================================================================================================
[56]118// Private member functions
119// ====================================================================================================================
120Void TDecGop::patchAlfLCUParams(ALFParam*** alfLCUParam, AlfParamSet* alfParamSet, Int firstLCUAddr)
121{
122  Int numLCUInWidth = alfParamSet->numLCUInWidth;
123  Int numLCU        = alfParamSet->numLCU;
124
125  Int rx, ry, pos, posUp;
126  std::vector<ALFParam*> storedFilters[NUM_ALF_COMPONENT];
127  storedFilters[ALF_Y].clear();
128  storedFilters[ALF_Cb].clear();
129  storedFilters[ALF_Cr].clear();
130
131  for(Int i=0; i< numLCU; i++)
132  {
133    rx     = (i+ firstLCUAddr)% numLCUInWidth;
134    ry     = (i+ firstLCUAddr)/ numLCUInWidth;
135    pos    = (ry*numLCUInWidth) + rx;
136    posUp  = pos-numLCUInWidth;
137
138    for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
139    {
140      AlfUnitParam& alfUnitParam = alfParamSet->alfUnitParam[compIdx][i];
141      ALFParam&     alfFiltParam = *(alfLCUParam[compIdx][pos]);
142
143      switch( alfUnitParam.mergeType )
144      {
145      case ALF_MERGE_DISABLED:
146        {
147          if(alfUnitParam.isEnabled)
148          {
149            if(alfUnitParam.isNewFilt)
150            {
151              alfFiltParam = *alfUnitParam.alfFiltParam;
152              storedFilters[compIdx].push_back( &alfFiltParam );
153            }
154            else //stored filter
155            {
156              alfFiltParam = *(storedFilters[compIdx][alfUnitParam.storedFiltIdx]);
157              assert(alfFiltParam.alf_flag == 1);
158            }
159          }
160          else
161          {
162            alfFiltParam.alf_flag = 0;
163          }
164        }
165        break;
166      case ALF_MERGE_UP:
167        {
168          assert(posUp >= 0);
169          alfFiltParam = *(alfLCUParam[compIdx][posUp]);
170        }
171        break;
172      case ALF_MERGE_LEFT:
173        {
174          assert(pos-1 >= 0);
175          alfFiltParam = *(alfLCUParam[compIdx][pos-1]);
176        }
177        break;
178      case ALF_MERGE_FIRST:
179        {
180          alfFiltParam = *(alfLCUParam[compIdx][firstLCUAddr]);
181        }
182        break;
183      default:
184        {
185          printf("not a supported ALF merge type\n");
186          assert(0);
187          exit(-1);
188        }
189      }
190    } //compIdx
191  } //i (LCU)
192}
193
194// ====================================================================================================================
[2]195// Public member functions
196// ====================================================================================================================
197
[56]198Void TDecGop::decompressGop(TComInputBitstream* pcBitstream, TComPic*& rpcPic, Bool bExecuteDeblockAndAlf)
[2]199{
200  TComSlice*  pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx());
[56]201  // Table of extracted substreams.
202  // These must be deallocated AND their internal fifos, too.
203  TComInputBitstream **ppcSubstreams = NULL;
[2]204
205  //-- For time output for each slice
206  long iBeforeTime = clock();
207 
208  UInt uiStartCUAddr   = pcSlice->getEntropySliceCurStartCUAddr();
[56]209
[2]210  if (!bExecuteDeblockAndAlf)
211  {
[56]212    if(m_first)
[2]213    {
[56]214      m_uiILSliceCount = 0;
215      m_puiILSliceStartLCU = new UInt[(rpcPic->getNumCUsInFrame()* rpcPic->getNumPartInCU()) +1];
216      m_first = false;
[2]217    }
[56]218
219    UInt uiSliceStartCuAddr = pcSlice->getSliceCurStartCUAddr();
220    if(uiSliceStartCuAddr == uiStartCUAddr)
221    {
222      m_puiILSliceStartLCU[m_uiILSliceCount] = uiSliceStartCuAddr;
223      m_uiILSliceCount++;
224    }
225
226    m_pcSbacDecoder->init( (TDecBinIf*)m_pcBinCABAC );
227    m_pcEntropyDecoder->setEntropyDecoder (m_pcSbacDecoder);
[2]228   
[56]229    UInt uiNumSubstreams = pcSlice->getPPS()->getNumSubstreams();
230
231    //init each couple {EntropyDecoder, Substream}
232    UInt *puiSubstreamSizes = pcSlice->getSubstreamSizes();
233    ppcSubstreams    = new TComInputBitstream*[uiNumSubstreams];
234    m_pcSbacDecoders = new TDecSbac[uiNumSubstreams];
235    m_pcBinCABACs    = new TDecBinCABAC[uiNumSubstreams];
236    UInt uiBitsRead = pcBitstream->getByteLocation()<<3;
237    for ( UInt ui = 0 ; ui < uiNumSubstreams ; ui++ )
[2]238    {
[56]239      m_pcSbacDecoders[ui].init(&m_pcBinCABACs[ui]);
240      UInt uiSubstreamSizeBits = (ui+1 < uiNumSubstreams ? puiSubstreamSizes[ui] : pcBitstream->getNumBitsLeft());
241      ppcSubstreams[ui] = pcBitstream->extractSubstream(ui+1 < uiNumSubstreams ? puiSubstreamSizes[ui] : pcBitstream->getNumBitsLeft());
242      // update location information from where tile markers were extracted
[2]243      {
[56]244        UInt uiDestIdx       = 0;
245        for (UInt uiSrcIdx = 0; uiSrcIdx<pcBitstream->getTileMarkerLocationCount(); uiSrcIdx++)
246        {
247          UInt uiLocation = pcBitstream->getTileMarkerLocation(uiSrcIdx);
248          if ((uiBitsRead>>3)<=uiLocation  &&  uiLocation<((uiBitsRead+uiSubstreamSizeBits)>>3))
249          {
250            ppcSubstreams[ui]->setTileMarkerLocation( uiDestIdx, uiLocation - (uiBitsRead>>3) );
251            ppcSubstreams[ui]->setTileMarkerLocationCount( uiDestIdx+1 );
252            uiDestIdx++;
253          }
254        }
255        ppcSubstreams[ui]->setTileMarkerLocationCount( uiDestIdx );
256        uiBitsRead += uiSubstreamSizeBits;
[2]257      }
258    }
259
[56]260    for ( UInt ui = 0 ; ui+1 < uiNumSubstreams; ui++ )
[2]261    {
[56]262      m_pcEntropyDecoder->setEntropyDecoder ( &m_pcSbacDecoders[uiNumSubstreams - 1 - ui] );
263      m_pcEntropyDecoder->setBitstream      (  ppcSubstreams   [uiNumSubstreams - 1 - ui] );
264      m_pcEntropyDecoder->resetEntropy      (pcSlice);
[2]265    }
[56]266
267    m_pcEntropyDecoder->setEntropyDecoder ( m_pcSbacDecoder  );
268    m_pcEntropyDecoder->setBitstream      ( ppcSubstreams[0] );
[2]269    m_pcEntropyDecoder->resetEntropy      (pcSlice);
[56]270
271    if(uiSliceStartCuAddr == uiStartCUAddr)
[2]272    {
[56]273      if(pcSlice->getSPS()->getUseALF())
274      {
275        if(pcSlice->getAlfEnabledFlag())
276        {
277          if(pcSlice->getSPS()->getUseALFCoefInSlice())
278          {
279            Int numSUinLCU    = 1<< (g_uiMaxCUDepth << 1); 
280            Int firstLCUAddr   = pcSlice->getSliceCurStartCUAddr() / numSUinLCU; 
281            patchAlfLCUParams(m_pcAdaptiveLoopFilter->getAlfLCUParam(), &m_alfParamSetPilot, firstLCUAddr);
282          }
[2]283
[56]284          if( !pcSlice->getSPS()->getUseALFCoefInSlice())
285          {
286          m_vAlfCUCtrlSlices.push_back(m_cAlfCUCtrlOneSlice);
287          }
288        }
[2]289      }
290    }
[56]291
[5]292#if DEPTH_MAP_GENERATION
[2]293    // init view component and predict virtual depth map
294    if( uiStartCUAddr == 0 )
295    {
296      m_pcDepthMapGenerator->initViewComponent( rpcPic );
[296]297#if !H3D_NBDV
[2]298      m_pcDepthMapGenerator->predictDepthMap  ( rpcPic );
[100]299#endif
[296]300#if H3D_IVRP
[2]301      m_pcResidualGenerator->initViewComponent( rpcPic );
[5]302#endif
[2]303    }
[5]304#endif
[2]305
[296]306#if H3D_NBDV
[189]307    if(pcSlice->getViewId() && pcSlice->getSPS()->getMultiviewMvPredMode())
308    {
309      Int iColPoc = pcSlice->getRefPOC(RefPicList(pcSlice->getColDir()), pcSlice->getColRefIdx());
310      rpcPic->setRapbCheck(rpcPic->getDisCandRefPictures(iColPoc));
311    }
312#endif
[56]313
314    m_pcSbacDecoders[0].load(m_pcSbacDecoder);
315    m_pcSliceDecoder->decompressSlice( pcBitstream, ppcSubstreams, rpcPic, m_pcSbacDecoder, m_pcSbacDecoders);
316    m_pcEntropyDecoder->setBitstream(  ppcSubstreams[uiNumSubstreams-1] );
317    if ( uiNumSubstreams > 1 )
318    {
319      // deallocate all created substreams, including internal buffers.
320      for (UInt ui = 0; ui < uiNumSubstreams; ui++)
321      {
322        ppcSubstreams[ui]->deleteFifo();
323        delete ppcSubstreams[ui];
324      }
325      delete[] ppcSubstreams;
326      delete[] m_pcSbacDecoders; m_pcSbacDecoders = NULL;
327      delete[] m_pcBinCABACs; m_pcBinCABACs = NULL;
328    }
[2]329    m_dDecTime += (double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
330  }
331  else
332  {
[296]333#if H3D_IVRP
[2]334    // set residual picture
335    m_pcResidualGenerator->setRecResidualPic( rpcPic );
[5]336#endif
337#if DEPTH_MAP_GENERATION
[296]338#if !H3D_NBDV
[2]339    // update virtual depth map
340    m_pcDepthMapGenerator->updateDepthMap( rpcPic );
[5]341#endif
[100]342#endif
[2]343    // deblocking filter
[56]344    Bool bLFCrossTileBoundary = (pcSlice->getPPS()->getTileBehaviorControlPresentFlag() == 1)?
345                                (pcSlice->getPPS()->getLFCrossTileBoundaryFlag()):(pcSlice->getPPS()->getSPS()->getLFCrossTileBoundaryFlag());
346    if (pcSlice->getPPS()->getDeblockingFilterControlPresent())
347    {
348      if(pcSlice->getSPS()->getUseDF())
349      {
350        if(pcSlice->getInheritDblParamFromAPS())
351        {
352          pcSlice->setLoopFilterDisable(pcSlice->getAPS()->getLoopFilterDisable());
353          if (!pcSlice->getLoopFilterDisable())
354          {
355            pcSlice->setLoopFilterBetaOffset(pcSlice->getAPS()->getLoopFilterBetaOffset());
356            pcSlice->setLoopFilterTcOffset(pcSlice->getAPS()->getLoopFilterTcOffset());
357          }
358        }
359      }
360    }
361    m_pcLoopFilter->setCfg(pcSlice->getPPS()->getDeblockingFilterControlPresent(), pcSlice->getLoopFilterDisable(), pcSlice->getLoopFilterBetaOffset(), pcSlice->getLoopFilterTcOffset(), bLFCrossTileBoundary);
[2]362    m_pcLoopFilter->loopFilterPic( rpcPic );
[56]363
364    pcSlice = rpcPic->getSlice(0);
365    if(pcSlice->getSPS()->getUseSAO() || pcSlice->getSPS()->getUseALF())
[2]366    {
[56]367      Int sliceGranularity = pcSlice->getPPS()->getSliceGranularity();
368      m_puiILSliceStartLCU[m_uiILSliceCount] = rpcPic->getNumCUsInFrame()* rpcPic->getNumPartInCU();
369      rpcPic->createNonDBFilterInfo(m_puiILSliceStartLCU, m_uiILSliceCount,sliceGranularity,pcSlice->getSPS()->getLFCrossSliceBoundaryFlag(),rpcPic->getPicSym()->getNumTiles() ,bLFCrossTileBoundary);
370    }
371
372    if( pcSlice->getSPS()->getUseSAO() )
373    {
374      if(pcSlice->getSaoEnabledFlag())
[2]375      {
[56]376        if (pcSlice->getSaoInterleavingFlag())
377        {
378          pcSlice->getAPS()->setSaoInterleavingFlag(pcSlice->getSaoInterleavingFlag());
379          pcSlice->getAPS()->setSaoEnabled(pcSlice->getSaoEnabledFlag());
380          pcSlice->getAPS()->getSaoParam()->bSaoFlag[0] = pcSlice->getSaoEnabledFlag();
381          pcSlice->getAPS()->getSaoParam()->bSaoFlag[1] = pcSlice->getSaoEnabledFlagCb();
382          pcSlice->getAPS()->getSaoParam()->bSaoFlag[2] = pcSlice->getSaoEnabledFlagCr();
383        }
384        m_pcSAO->setSaoInterleavingFlag(pcSlice->getAPS()->getSaoInterleavingFlag());
385        m_pcSAO->createPicSaoInfo(rpcPic, m_uiILSliceCount);
386        m_pcSAO->SAOProcess(rpcPic, pcSlice->getAPS()->getSaoParam()); 
387        m_pcAdaptiveLoopFilter->PCMLFDisableProcess(rpcPic);
388        m_pcSAO->destroyPicSaoInfo();
[2]389      }
390    }
[56]391
[2]392    // adaptive loop filter
393    if( pcSlice->getSPS()->getUseALF() )
394    {
[56]395      if( (pcSlice->getSPS()->getUseALFCoefInSlice())?(true):(pcSlice->getAlfEnabledFlag()))
[2]396      {
[56]397
398        if(!pcSlice->getSPS()->getUseALFCoefInSlice())
[2]399        {
[56]400          patchAlfLCUParams(m_pcAdaptiveLoopFilter->getAlfLCUParam(), pcSlice->getAPS()->getAlfParam());
[2]401        }
[56]402        m_pcAdaptiveLoopFilter->createPicAlfInfo(rpcPic, m_uiILSliceCount, pcSlice->getSliceQp());
403        m_pcAdaptiveLoopFilter->ALFProcess(rpcPic, m_vAlfCUCtrlSlices, pcSlice->getSPS()->getUseALFCoefInSlice());
404      m_pcAdaptiveLoopFilter->PCMLFDisableProcess(rpcPic);
405      m_pcAdaptiveLoopFilter->destroyPicAlfInfo();
[2]406      }
[56]407      m_pcAdaptiveLoopFilter->resetLCUAlfInfo(); //reset all LCU ALFParam->alf_flag = 0
[2]408    }
409   
[56]410    if(pcSlice->getSPS()->getUseSAO() || pcSlice->getSPS()->getUseALF())
[2]411    {
[56]412      rpcPic->destroyNonDBFilterInfo();
[2]413    }
[56]414
415 //   rpcPic->compressMotion();
416    Char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
417    if (!pcSlice->isReferenced()) c += 32;
[2]418   
[56]419    //-- For time output for each slice
420    printf("\n%s   View %2d POC %4d TId: %1d ( %c-SLICE, QP%3d ) ",
421          pcSlice->getIsDepth() ? "Depth  " : "Texture",
422          pcSlice->getViewId(),
423          pcSlice->getPOC(),
424          pcSlice->getTLayer(),
425          c,
426          pcSlice->getSliceQp() );
427
[2]428    m_dDecTime += (double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
429    printf ("[DT %6.3f] ", m_dDecTime );
430    m_dDecTime  = 0;
431   
432    for (Int iRefList = 0; iRefList < 2; iRefList++)
433    {
434      printf ("[L%d ", iRefList);
435      for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++)
436      {
[56]437        if( pcSlice->getViewId() != pcSlice->getRefViewId( RefPicList(iRefList), iRefIndex ) )
[2]438        {
[56]439          printf( "V%d ", pcSlice->getRefViewId( RefPicList(iRefList), iRefIndex ) );
[2]440        }
441        else
[56]442        {
[2]443          printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex));
[56]444        }
[2]445      }
446      printf ("] ");
447    }
448    if(pcSlice->getNumRefIdx(REF_PIC_LIST_C)>0 && !pcSlice->getNoBackPredFlag())
449    {
450      printf ("[LC ");
451      for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(REF_PIC_LIST_C); iRefIndex++)
452      {
[56]453        if( pcSlice->getViewId() != pcSlice->getRefViewId( (RefPicList)pcSlice->getListIdFromIdxOfLC(iRefIndex), pcSlice->getRefIdxFromIdxOfLC(iRefIndex) ) )
[2]454        {
[56]455          printf( "V%d ", pcSlice->getRefViewId( (RefPicList)pcSlice->getListIdFromIdxOfLC(iRefIndex), pcSlice->getRefIdxFromIdxOfLC(iRefIndex) ) );
[2]456        }
457        else
[56]458        {
[2]459          printf ("%d ", pcSlice->getRefPOC((RefPicList)pcSlice->getListIdFromIdxOfLC(iRefIndex), pcSlice->getRefIdxFromIdxOfLC(iRefIndex)));
[56]460        }
[2]461      }
462      printf ("] ");
463    }
464
[56]465    if (m_pictureDigestEnabled)
466    {
[2]467      calcAndPrintMD5Status(*rpcPic->getPicYuvRec(), rpcPic->getSEIs());
468    }
469
[56]470#if FIXED_ROUNDING_FRAME_MEMORY
471    rpcPic->getPicYuvRec()->xFixedRoundingPic();
472#endif
473
474    rpcPic->setOutputMark(true);
[2]475    rpcPic->setReconMark(true);
[56]476
477    rpcPic->setUsedForTMVP( true );
478
479    m_uiILSliceCount = 0;
480    m_vAlfCUCtrlSlices.clear();
[2]481  }
[296]482  fflush(stdout);
[2]483}
484
485/**
[56]486 * Calculate and print MD5 for pic, compare to picture_digest SEI if
487 * present in seis.  seis may be NULL.  MD5 is printed to stdout, in
[2]488 * a manner suitable for the status line. Theformat is:
489 *  [MD5:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,(yyy)]
490 * Where, x..x is the md5
491 *        yyy has the following meanings:
492 *            OK          - calculated MD5 matches the SEI message
493 *            ***ERROR*** - calculated MD5 does not match the SEI message
494 *            unk         - no SEI message was available for comparison
495 */
496static void calcAndPrintMD5Status(TComPicYuv& pic, const SEImessages* seis)
497{
498  /* calculate MD5sum for entire reconstructed picture */
499  unsigned char recon_digest[16];
500  calcMD5(pic, recon_digest);
501
502  /* compare digest against received version */
503  const char* md5_ok = "(unk)";
504  bool md5_mismatch = false;
505
506  if (seis && seis->picture_digest)
507  {
508    md5_ok = "(OK)";
509    for (unsigned i = 0; i < 16; i++)
510    {
511      if (recon_digest[i] != seis->picture_digest->digest[i])
512      {
513        md5_ok = "(***ERROR***)";
514        md5_mismatch = true;
515      }
516    }
517  }
518
519  printf("[MD5:%s,%s] ", digestToString(recon_digest), md5_ok);
520  if (md5_mismatch)
521  {
522    g_md5_mismatch = true;
523    printf("[rxMD5:%s] ", digestToString(seis->picture_digest->digest));
524  }
525}
[56]526//! \}
Note: See TracBrowser for help on using the repository browser.