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

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

Reintegrated branch 4.1-dev0 Rev. 188.

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