Ticket #1070: lf_fix_2.patch

File lf_fix_2.patch, 15.5 KB (added by pieterkapsenberg, 10 years ago)

modified to handle dependent slices and the case where SEI arrives before the last slice of the picture

  • App/TAppDecoder/TAppDecTop.cpp

     
    126126
    127127    // call actual decoding function
    128128    Bool bNewPicture = false;
     129    Bool bPicComplete = false;
    129130    if (nalUnit.empty())
    130131    {
    131132      /* this can happen if the following occur:
     
    152153      }
    153154      else
    154155      {
    155         bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
     156        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay, bPicComplete);
     157        if(bPicComplete)
     158        {
     159          m_cTDecTop.executeLoopFilters(poc, pcListPic);
     160        }
    156161        if (bNewPicture)
    157162        {
    158163          bitstreamFile.clear();
     
    166171        bPreviousPictureDecoded = true;
    167172      }
    168173    }
    169     if (bNewPicture || !bitstreamFile)
    170     {
    171       m_cTDecTop.executeLoopFilters(poc, pcListPic);
    172     }
    173 
    174174    if( pcListPic )
    175175    {
    176176      if ( m_pchReconFile && !recon_opened )
  • Lib/TLibDecoder/TDecGop.cpp

     
    4040#include "TDecSbac.h"
    4141#include "TDecBinCoder.h"
    4242#include "TDecBinCoderCABAC.h"
    43 #include "libmd5/MD5.h"
    44 #include "TLibCommon/SEI.h"
    4543
    4644#include <time.h>
    4745
    48 extern Bool g_md5_mismatch; ///< top level flag to signal when there is a decode problem
    49 
    5046//! \ingroup TLibDecoder
    5147//! \{
    52 static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI);
     48
    5349// ====================================================================================================================
    5450// Constructor / destructor / initialization / destroy
    5551// ====================================================================================================================
     
    10298// Public member functions
    10399// ====================================================================================================================
    104100
    105 Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic)
     101Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic, Bool& bPicComplete)
    106102{
    107103  TComSlice*  pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx());
    108104  // Table of extracted substreams.
     
    152148    m_LFCrossSliceBoundaryFlag.push_back( pcSlice->getLFCrossSliceBoundaryFlag());
    153149  }
    154150  m_pcSbacDecoders[0].load(m_pcSbacDecoder);
    155   m_pcSliceDecoder->decompressSlice( ppcSubstreams, rpcPic, m_pcSbacDecoder, m_pcSbacDecoders);
     151  m_pcSliceDecoder->decompressSlice( ppcSubstreams, rpcPic, m_pcSbacDecoder, m_pcSbacDecoders, bPicComplete);
    156152  m_pcEntropyDecoder->setBitstream(  ppcSubstreams[uiNumSubstreams-1] );
    157153  // deallocate all created substreams, including internal buffers.
    158154  for (UInt ui = 0; ui < uiNumSubstreams; ui++)
     
    227223    }
    228224    printf ("] ");
    229225  }
    230   if (m_decodedPictureHashSEIEnabled)
    231   {
    232     SEIMessages pictureHashes = getSeisByType(rpcPic->getSEIs(), SEI::DECODED_PICTURE_HASH );
    233     const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL;
    234     if (pictureHashes.size() > 1)
    235     {
    236       printf ("Warning: Got multiple decoded picture hash SEI messages. Using first.");
    237     }
    238     calcAndPrintHashStatus(*rpcPic->getPicYuvRec(), hash);
    239   }
    240226
    241227  rpcPic->setOutputMark(true);
    242228  rpcPic->setReconMark(true);
     
    244230  m_LFCrossSliceBoundaryFlag.clear();
    245231}
    246232
    247 /**
    248  * Calculate and print hash for pic, compare to picture_digest SEI if
    249  * present in seis.  seis may be NULL.  Hash is printed to stdout, in
    250  * a manner suitable for the status line. Theformat is:
    251  *  [Hash_type:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,(yyy)]
    252  * Where, x..x is the hash
    253  *        yyy has the following meanings:
    254  *            OK          - calculated hash matches the SEI message
    255  *            ***ERROR*** - calculated hash does not match the SEI message
    256  *            unk         - no SEI message was available for comparison
    257  */
    258 static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI)
    259 {
    260   /* calculate MD5sum for entire reconstructed picture */
    261   UChar recon_digest[3][16];
    262   Int numChar=0;
    263   const Char* hashType = "\0";
    264233
    265   if (pictureHashSEI)
    266   {
    267     switch (pictureHashSEI->method)
    268     {
    269     case SEIDecodedPictureHash::MD5:
    270       {
    271         hashType = "MD5";
    272         calcMD5(pic, recon_digest);
    273         numChar = 16;
    274         break;
    275       }
    276     case SEIDecodedPictureHash::CRC:
    277       {
    278         hashType = "CRC";
    279         calcCRC(pic, recon_digest);
    280         numChar = 2;
    281         break;
    282       }
    283     case SEIDecodedPictureHash::CHECKSUM:
    284       {
    285         hashType = "Checksum";
    286         calcChecksum(pic, recon_digest);
    287         numChar = 4;
    288         break;
    289       }
    290     default:
    291       {
    292         assert (!"unknown hash type");
    293       }
    294     }
    295   }
    296 
    297   /* compare digest against received version */
    298   const Char* ok = "(unk)";
    299   Bool mismatch = false;
    300 
    301   if (pictureHashSEI)
    302   {
    303     ok = "(OK)";
    304     for(Int yuvIdx = 0; yuvIdx < 3; yuvIdx++)
    305     {
    306       for (UInt i = 0; i < numChar; i++)
    307       {
    308         if (recon_digest[yuvIdx][i] != pictureHashSEI->digest[yuvIdx][i])
    309         {
    310           ok = "(***ERROR***)";
    311           mismatch = true;
    312         }
    313       }
    314     }
    315   }
    316 
    317   printf("[%s:%s,%s] ", hashType, digestToString(recon_digest, numChar), ok);
    318 
    319   if (mismatch)
    320   {
    321     g_md5_mismatch = true;
    322     printf("[rx%s:%s] ", hashType, digestToString(pictureHashSEI->digest, numChar));
    323   }
    324 }
    325234//! \}
  • Lib/TLibDecoder/TDecGop.h

     
    8080 
    8181  TComSampleAdaptiveOffset*     m_pcSAO;
    8282  Double                m_dDecTime;
    83   Int                   m_decodedPictureHashSEIEnabled;  ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message
    8483
    8584  //! list that contains the CU address of each slice plus the end address
    8685  std::vector<Int> m_sliceStartCUAddress;
     
    10099                 );
    101100  Void  create  ();
    102101  Void  destroy ();
    103   Void  decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic );
     102  Void  decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic, Bool &bPicComplete);
    104103  Void  filterPicture  (TComPic*& rpcPic );
    105104
    106   void setDecodedPictureHashSEIEnabled(Int enabled) { m_decodedPictureHashSEIEnabled = enabled; }
    107105
    108106};
    109107
  • Lib/TLibDecoder/TDecSlice.cpp

     
    105105  m_pcCuDecoder       = pcCuDecoder;
    106106}
    107107
    108 Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders)
     108Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders, Bool& bPicComplete)
    109109{
    110110  TComDataCU* pcCU;
    111111  UInt        uiIsLast = 0;
     
    379379         CTXMem[1]->loadContexts( &m_pcBufferSbacDecoders[uiTileCol] );//ctx 2.LCU
    380380       }
    381381      CTXMem[0]->loadContexts( pcSbacDecoder );//ctx end of dep.slice
     382      bPicComplete = iCUAddr == (rpcPic->getNumCUsInFrame()-1);
    382383      return;
    383384    }
     385  bPicComplete = iCUAddr == (rpcPic->getNumCUsInFrame()-1);
    384386  }
    385387}
    386388
  • Lib/TLibDecoder/TDecSlice.h

     
    8080  Void  create            ();
    8181  Void  destroy           ();
    8282 
    83   Void  decompressSlice   ( TComInputBitstream** ppcSubstreams,   TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders );
     83  Void  decompressSlice   ( TComInputBitstream** ppcSubstreams,   TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders, Bool& bPicComplete );
    8484  Void      initCtxMem(  UInt i );
    8585  Void      setCtxMem( TDecSbac* sb, Int b )   { CTXMem[b] = sb; }
    8686};
  • Lib/TLibDecoder/TDecTop.cpp

     
    3737
    3838#include "NALread.h"
    3939#include "TDecTop.h"
     40#include "libmd5/MD5.h"
     41#include "TLibCommon/SEI.h"
    4042
    4143//! \ingroup TLibDecoder
     44extern Bool g_md5_mismatch; ///< top level flag to signal when there is a decode problem
     45
     46static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI);
     47
    4248//! \{
    4349
    4450TDecTop::TDecTop()
     
    5662  m_prevPOC                = MAX_INT;
    5763  m_bFirstSliceInPicture    = true;
    5864  m_bFirstSliceInSequence   = true;
     65  m_digestCanBeChecked      = false;
    5966}
    6067
    6168TDecTop::~TDecTop()
     
    185192  // Execute Deblock + Cleanup
    186193
    187194  m_cGopDecoder.filterPicture(pcPic);
    188 
     195  m_digestCanBeChecked = true;
    189196  TComSlice::sortPicList( m_cListPic ); // sorting for application output
    190197  poc                 = pcPic->getSlice(m_uiSliceIdx-1)->getPOC();
    191198  rpcListPic          = &m_cListPic; 
    192199  m_cCuDecoder.destroy();       
    193200  m_bFirstSliceInPicture  = true;
    194 
     201  if (m_decodedPictureHashSEIEnabled)
     202    {
     203      SEIMessages pictureHashes = getSeisByType(m_pcPic->getSEIs(), SEI::DECODED_PICTURE_HASH );
     204      const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL;
     205      if(pictureHashes.size() == 0)
     206      {
     207        return;
     208      }
     209      // Possible that the SUFFIX SEI was inserted before the last slice (but after the first one)
     210      if (pictureHashes.size() > 1)
     211      {
     212        printf ("Warning: Got multiple decoded picture hash SEI messages. Using first.");
     213      }
     214      calcAndPrintHashStatus(*m_pcPic->getPicYuvRec(), hash);
     215    }
    195216  return;
    196217}
    197218
     
    282303  m_cLoopFilter.        create( g_uiMaxCUDepth );
    283304}
    284305
    285 Bool TDecTop::xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay )
     306Bool TDecTop::xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay, Bool &bPicComplete )
    286307{
    287308  TComPic*&   pcPic         = m_pcPic;
    288309  m_apcSlicePilot->initSlice();
     
    570591  }
    571592
    572593  //  Decode a picture
    573   m_cGopDecoder.decompressSlice(nalu.m_Bitstream, pcPic);
    574 
     594  m_cGopDecoder.decompressSlice(nalu.m_Bitstream, pcPic, bPicComplete);
     595 
    575596  m_bFirstSliceInPicture = false;
     597  m_digestCanBeChecked = false;
    576598  m_uiSliceIdx++;
    577599
    578600  return false;
     
    618640  if(nalUnitType == NAL_UNIT_SEI_SUFFIX)
    619641  {
    620642    m_seiReader.parseSEImessage( bs, m_pcPic->getSEIs(), nalUnitType, m_parameterSetManagerDecoder.getActiveSPS() );
     643    if (m_decodedPictureHashSEIEnabled && m_digestCanBeChecked)
     644    {
     645      SEIMessages pictureHashes = getSeisByType(m_pcPic->getSEIs(), SEI::DECODED_PICTURE_HASH );
     646      const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL;
     647      if (pictureHashes.size() > 1)
     648      {
     649        printf ("Warning: Got multiple decoded picture hash SEI messages. Using first.");
     650      }
     651      calcAndPrintHashStatus(*m_pcPic->getPicYuvRec(), hash);
     652    }
    621653  }
    622654  else
    623655  {
     
    636668  }
    637669}
    638670
    639 Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay)
     671Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay, Bool& bPicComplete)
    640672{
    641673  // Initialize entropy decoder
    642674  m_cEntropyDecoder.setEntropyDecoder (&m_cCavlcDecoder);
     
    677709    case NAL_UNIT_CODED_SLICE_DLP:
    678710    case NAL_UNIT_CODED_SLICE_RASL_N:
    679711    case NAL_UNIT_CODED_SLICE_TFD:
    680       return xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay);
     712      return xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay, bPicComplete);
    681713      break;
    682714    default:
    683715      assert (1);
     
    757789  return false;
    758790}
    759791
     792/**
     793 * Calculate and print hash for pic, compare to picture_digest SEI if
     794 * present in seis.  seis may be NULL.  Hash is printed to stdout, in
     795 * a manner suitable for the status line. Theformat is:
     796 *  [Hash_type:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,(yyy)]
     797 * Where, x..x is the hash
     798 *        yyy has the following meanings:
     799 *            OK          - calculated hash matches the SEI message
     800 *            ***ERROR*** - calculated hash does not match the SEI message
     801 *            unk         - no SEI message was available for comparison
     802 */
     803static void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI)
     804{
     805  /* calculate MD5sum for entire reconstructed picture */
     806  UChar recon_digest[3][16];
     807  Int numChar=0;
     808  const Char* hashType = "\0";
     809
     810  if (pictureHashSEI)
     811  {
     812    switch (pictureHashSEI->method)
     813    {
     814    case SEIDecodedPictureHash::MD5:
     815      {
     816        hashType = "MD5";
     817        calcMD5(pic, recon_digest);
     818        numChar = 16;
     819        break;
     820      }
     821    case SEIDecodedPictureHash::CRC:
     822      {
     823        hashType = "CRC";
     824        calcCRC(pic, recon_digest);
     825        numChar = 2;
     826        break;
     827      }
     828    case SEIDecodedPictureHash::CHECKSUM:
     829      {
     830        hashType = "Checksum";
     831        calcChecksum(pic, recon_digest);
     832        numChar = 4;
     833        break;
     834      }
     835    default:
     836      {
     837        assert (!"unknown hash type");
     838      }
     839    }
     840  }
     841
     842  /* compare digest against received version */
     843  const Char* ok = "(unk)";
     844  Bool mismatch = false;
     845
     846  if (pictureHashSEI)
     847  {
     848    ok = "(OK)";
     849    for(Int yuvIdx = 0; yuvIdx < 3; yuvIdx++)
     850    {
     851      for (UInt i = 0; i < numChar; i++)
     852      {
     853        if (recon_digest[yuvIdx][i] != pictureHashSEI->digest[yuvIdx][i])
     854        {
     855          ok = "(***ERROR***)";
     856          mismatch = true;
     857        }
     858      }
     859    }
     860  }
     861
     862  printf("[%s:%s,%s] ", hashType, digestToString(recon_digest, numChar), ok);
     863
     864  if (mismatch)
     865  {
     866    g_md5_mismatch = true;
     867    printf("[rx%s:%s] ", hashType, digestToString(pictureHashSEI->digest, numChar));
     868  }
     869}
     870
    760871//! \}
  • Lib/TLibDecoder/TDecTop.h

     
    9797  Int                     m_prevPOC;
    9898  Bool                    m_bFirstSliceInPicture;
    9999  Bool                    m_bFirstSliceInSequence;
     100  Int                     m_decodedPictureHashSEIEnabled;  ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message
     101  Bool                    m_digestCanBeChecked;
    100102
    101103public:
    102104  TDecTop();
     
    105107  Void  create  ();
    106108  Void  destroy ();
    107109
    108   void setDecodedPictureHashSEIEnabled(Int enabled) { m_cGopDecoder.setDecodedPictureHashSEIEnabled(enabled); }
     110  void setDecodedPictureHashSEIEnabled(Int enabled) { m_decodedPictureHashSEIEnabled = enabled; }
    109111
    110112  Void  init();
    111   Bool  decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay);
     113  Bool  decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay, Bool &bPicComplete);
    112114 
    113115  Void  deletePicBuffer();
    114116
     
    119121  Void  xCreateLostPicture (Int iLostPOC);
    120122
    121123  Void      xActivateParameterSets();
    122   Bool      xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay);
     124  Bool      xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay, Bool &bPicComplete);
    123125  Void      xDecodeVPS();
    124126  Void      xDecodeSPS();
    125127  Void      xDecodePPS();