From 049964e0634f291f574583abd0e44f5569bbf350 Mon Sep 17 00:00:00 2001
From: Tobias Hinz <tobias.hinz@hhi.fraunhofer.de>
Date: Wed, 30 Jan 2019 11:08:05 +0100
Subject: [PATCH] merged M0055 changes

---
 source/App/EncoderApp/EncApp.cpp         |  3 ++
 source/App/EncoderApp/EncAppCfg.cpp      |  3 ++
 source/App/EncoderApp/EncAppCfg.h        |  3 ++
 source/Lib/CommonLib/CodingStructure.cpp | 11 ++++++
 source/Lib/CommonLib/TypeDef.h           |  2 ++
 source/Lib/DecoderLib/DecLib.cpp         | 45 ++++++++++++++++++++++++
 source/Lib/DecoderLib/DecLib.h           | 17 +++++++--
 source/Lib/DecoderLib/DecSlice.cpp       | 12 +++++++
 source/Lib/DecoderLib/DecSlice.h         |  4 +++
 source/Lib/EncoderLib/EncCfg.h           |  8 ++++-
 source/Lib/EncoderLib/EncGOP.cpp         | 18 ++++++++++
 source/Lib/EncoderLib/EncSlice.cpp       | 20 ++++++++++-
 12 files changed, 142 insertions(+), 4 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index eee3ac264..a091bd770 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -536,6 +536,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setForceDecodeBitstream1                             ( m_forceDecodeBitstream1 );
   m_cEncLib.setStopAfterFFtoPOC                                  ( m_stopAfterFFtoPOC );
   m_cEncLib.setBs2ModPOCAndType                                  ( m_bs2ModPOCAndType );
+#if JVET_M0055_DEBUG_CTU
+  m_cEncLib.setDebugCTU                                          ( m_debugCTU );
+#endif
 #if ENABLE_SPLIT_PARALLELISM
   m_cEncLib.setNumSplitThreads                                   ( m_numSplitThreads );
   m_cEncLib.setForceSingleSplitThread                            ( m_forceSplitSequential );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index a1709b0d3..a432e0fba 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1289,6 +1289,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("ForceSingleSplitThread",                          m_forceSplitSequential,                   false, "Force single thread execution even if taking the parallelized path")
   ("NumWppThreads",                                   m_numWppThreads,                              1, "Number of threads used to run WPP-style parallelization")
   ("NumWppExtraLines",                                m_numWppExtraLines,                           0, "Number of additional wpp lines to switch when threads are blocked")
+#if JVET_M0055_DEBUG_CTU
+  ("DebugCTU",                                        m_debugCTU,                                  -1, "If DebugBitstream is present, load frames up to this POC from this bitstream. Starting with DebugPOC-frame at CTUline containin debug CTU.")
+#endif
 #if ENABLE_WPP_PARALLELISM
   ("EnsureWppBitEqual",                               m_ensureWppBitEqual,                       true, "Ensure the results are equal to results with WPP-style parallelism, even if WPP is off")
 #else
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index b1910b56b..7bc2e0413 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -526,6 +526,9 @@ protected:
   int         m_verbosity;
 
   std::string m_decodeBitstreams[2];                          ///< filename for decode bitstreams.
+#if JVET_M0055_DEBUG_CTU
+  int         m_debugCTU;
+#endif  
   int         m_switchPOC;                                    ///< dbg poc.
   int         m_switchDQP;                                    ///< switch DQP.
   int         m_fastForwardToPOC;                             ///< get to encoding the specified POC as soon as possible by skipping temporal layers irrelevant for the specified POC
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index 8d5013fcc..759587a55 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -966,6 +966,17 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
 
     // copy data to picture
     picture->getRecoBuf( area ).copyFrom( recoBuf );
+#if JVET_M0055_DEBUG_CTU
+
+    // required for DebugCTU
+    int numCh = ::getNumberValidChannels( area.chromaFormat );
+    for( int i = 0; i < numCh; i++ )
+    {
+      const size_t _area = unitScale[i].scaleArea( area.blocks[i].area() );
+
+      memcpy( m_isDecomp[i], other.m_isDecomp[i], sizeof( *m_isDecomp[0] ) * _area );
+    }
+#endif
   }
 }
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index cb70e1dce..089b76b31 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_M0055_DEBUG_CTU                              1 // DebugCTU encoder debug option
+
 #define JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET               1 // Only use left neighbor for ATMVP offset derivation, from M0273, M0240, M0116, M0338, M0204
 
 #define JVET_M0063_BDOF_FIX                               1 // BDOF bitdepth bugfix
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 09b493dd5..668ba3d37 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -56,7 +56,11 @@
 #include "CommonLib/CodingStatistics.h"
 #endif
 
+#if JVET_M0055_DEBUG_CTU
+bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound /* = false */, int debugCTU /* = -1*/, int debugPOC /* = -1*/ )
+#else
 bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound /* = false */ )
+#endif
 {
   int      poc;
   PicList* pcListPic = NULL;
@@ -91,6 +95,10 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 #endif
       );
 
+#if JVET_M0055_DEBUG_CTU
+      pcDecLib->setDebugCTU( debugCTU );
+      pcDecLib->setDebugPOC( debugPOC );
+#endif
       pcDecLib->setDecodedPictureHashSEIEnabled( true );
 
       bFirstCall = false;
@@ -156,6 +164,9 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 
                 CHECK( expectedPoc != poc, "mismatch in POC - check encoder configuration" );
 
+#if JVET_M0055_DEBUG_CTU
+                if( debugCTU < 0 || poc != debugPOC )
+#endif
                 for( int i = 0; i < pic->slices.size(); i++ )
                 {
                   if( pcEncPic->slices.size() <= i )
@@ -168,6 +179,29 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 
                 pcEncPic->cs->slice = pcEncPic->slices.back();
 
+#if JVET_M0055_DEBUG_CTU
+                if( debugCTU >= 0 && poc == debugPOC )
+                {
+                  pcEncPic->cs->initStructData();
+
+                  pcEncPic->cs->copyStructure( *pic->cs, CH_L, true, true );
+
+                  if( CS::isDualITree( *pcEncPic->cs ) )
+                  {
+                    pcEncPic->cs->copyStructure( *pic->cs, CH_C, true, true );
+                  }
+
+                  for( auto &cu : pcEncPic->cs->cus )
+                  {
+                    cu->slice = pcEncPic->cs->slice;
+                  }
+#if JVET_L0266_HMVP
+                  pcEncPic->cs->slice->copyMotionLUTs( pic->slices.back()->getMotionLUTs(), pcEncPic->slices.back()->getMotionLUTs());
+#endif
+                }
+                else
+                {
+#endif
                 if ( pic->cs->sps->getSAOEnabledFlag() )
                 {
                   pcEncPic->copySAO( *pic, 0 );
@@ -198,6 +232,9 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
                 {
                   pcEncPic->cs->copyStructure( *pic->cs, CH_C, true, true );
                 }
+#if JVET_M0055_DEBUG_CTU
+                }
+#endif
                 goOn = false; // exit the loop return
                 bRet = true;
                 break;
@@ -370,6 +407,10 @@ DecLib::DecLib()
   , m_numberOfChecksumErrorsDetected(0)
   , m_warningMessageSkipPicture(false)
   , m_prefixSEINALUs()
+#if JVET_M0055_DEBUG_CTU
+  , m_debugPOC( -1 )
+  , m_debugCTU( -1 )
+#endif
 {
 #if ENABLE_SIMD_OPT_BUFFER
   g_pelBufOP.initPelBufOpsX86();
@@ -1235,7 +1276,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
 
   //  Decode a picture
+#if JVET_M0055_DEBUG_CTU
+  m_cSliceDecoder.decompressSlice( pcSlice, &( nalu.getBitstream() ), ( m_pcPic->poc == getDebugPOC() ? getDebugCTU() : -1 ) );
+#else
   m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) );
+#endif
 
   m_bFirstSliceInPicture = false;
   if (pcSlice->getSPS()->getSpsNext().getIBCMode())
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index 687ea822a..c43ae4fcb 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -59,8 +59,11 @@ class InputNALUnit;
 //! \ingroup DecoderLib
 //! \{
 
-bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false );
-// ====================================================================================================================
+#if JVET_M0055_DEBUG_CTU
+bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false, int debugCTU = -1, int debugPOC = -1 );
+#else
+ bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false );
+#endif// ====================================================================================================================
 // Class definition
 // ====================================================================================================================
 
@@ -122,6 +125,10 @@ private:
   bool                    m_warningMessageSkipPicture;
 
   std::list<InputNALUnit*> m_prefixSEINALUs; /// Buffered up prefix SEI NAL Units.
+#if JVET_M0055_DEBUG_CTU
+  int                     m_debugPOC;
+  int                     m_debugCTU;
+#endif
 public:
   DecLib();
   virtual ~DecLib();
@@ -152,6 +159,12 @@ public:
   void  setDecodedSEIMessageOutputStream(std::ostream *pOpStream) { m_pDecodedSEIOutputStream = pOpStream; }
   uint32_t  getNumberOfChecksumErrorsDetected() const { return m_numberOfChecksumErrorsDetected; }
 
+#if JVET_M0055_DEBUG_CTU
+  int  getDebugCTU( )               const { return m_debugCTU; }
+  void setDebugCTU( int debugCTU )        { m_debugCTU = debugCTU; }
+  int  getDebugPOC( )               const { return m_debugPOC; };
+  void setDebugPOC( int debugPOC )        { m_debugPOC = debugPOC; };
+#endif
 protected:
   void  xUpdateRasInit(Slice* slice);
 
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index 9f53af255..13be91a5c 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -70,7 +70,11 @@ void DecSlice::init( CABACDecoder* cabacDecoder, DecCu* pcCuDecoder )
   m_pcCuDecoder     = pcCuDecoder;
 }
 
+#if JVET_M0055_DEBUG_CTU 
+void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int debugCTU )
+#else
 void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream )
+#endif
 {
   //-- For time output for each slice
   slice->startProcessingTimer();
@@ -231,6 +235,14 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream )
       cs.slice->resetMotionLUTs();
     }
 
+#if JVET_M0055_DEBUG_CTU 
+ 
+    if( ctuRsAddr == debugCTU )
+    {
+      isLastCtuOfSliceSegment = true; // get out here
+      break;
+    }
+#endif
     isLastCtuOfSliceSegment = cabacReader.coding_tree_unit( cs, ctuArea, pic->m_prevQP, ctuRsAddr );
 
     m_pcCuDecoder->decompressCtu( cs, ctuArea );
diff --git a/source/Lib/DecoderLib/DecSlice.h b/source/Lib/DecoderLib/DecSlice.h
index 10304cf0e..f4a14e5b7 100644
--- a/source/Lib/DecoderLib/DecSlice.h
+++ b/source/Lib/DecoderLib/DecSlice.h
@@ -77,7 +77,11 @@ public:
   void  create            ();
   void  destroy           ();
 
+#if JVET_M0055_DEBUG_CTU
+  void  decompressSlice   ( Slice* slice, InputBitstream* bitstream, int debugCTU );
+#else
   void  decompressSlice   ( Slice* slice, InputBitstream* bitstream );
+#endif
 };
 
 //! \}
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 24561541a..ce5c46ea5 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -549,6 +549,9 @@ protected:
   int         m_switchDQP;                                    ///< dqp applied to  switchPOC and subsequent pictures.
   int         m_fastForwardToPOC;                             ///<
   bool        m_stopAfterFFtoPOC;                             ///<
+#if JVET_M0055_DEBUG_CTU
+  int         m_debugCTU;                                     ///< dbg ctu
+#endif
   bool        m_bs2ModPOCAndType;
 
 
@@ -1425,7 +1428,10 @@ public:
   bool         getStopAfterFFtoPOC()                           const { return m_stopAfterFFtoPOC; }
   void         setBs2ModPOCAndType( bool b )                         { m_bs2ModPOCAndType = b; }
   bool         getBs2ModPOCAndType()                           const { return m_bs2ModPOCAndType; }
-
+#if JVET_M0055_DEBUG_CTU
+  void         setDebugCTU( int i )                                  { m_debugCTU = i; }
+  int          getDebugCTU()                                   const { return m_debugCTU; }
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
   void         setNumSplitThreads( int n )                           { m_numSplitThreads = n; }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index bc863bb6c..6ab53a217 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -1207,11 +1207,29 @@ void trySkipOrDecodePicture( bool& decPic, bool& encPic, const EncCfg& cfg, Pict
       else
       {
         // update decode decision
+#if JVET_M0055_DEBUG_CTU
+        bool dbgCTU = cfg.getDebugCTU() != -1 && cfg.getSwitchPOC() == pcPic->getPOC();
+
+        if( ( bDecode1stPart = ( cfg.getSwitchPOC() != pcPic->getPOC() ) || dbgCTU ) && ( bDecode1stPart = tryDecodePicture( pcPic, pcPic->getPOC(), cfg.getDecodeBitstream( 0 ), false, cfg.getDebugCTU(), cfg.getSwitchPOC() ) ) )
+        {
+          if( dbgCTU )
+          {
+            encPic = true;
+            decPic = false;
+            bDecode1stPart = false;
+
+            return;
+          }
+          decPic = bDecode1stPart;
+          return;
+        }
+#else
         if( ( bDecode1stPart = ( cfg.getSwitchPOC() != pcPic->getPOC() )) && ( bDecode1stPart = tryDecodePicture( pcPic, pcPic->getPOC(), cfg.getDecodeBitstream( 0 ), false ) ) )
         {
           decPic = bDecode1stPart;
           return;
         }
+#endif
         else if( pcPic->getPOC() )
         {
           // reset decoder if used and not required any further
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 44bca844f..ee2a8453f 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1255,7 +1255,11 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
 
   cs.slice = pcSlice;
 
-  if (startCtuTsAddr == 0)
+#if JVET_M0055_DEBUG_CTU
+  if( startCtuTsAddr == 0 && ( pcSlice->getPOC() != m_pcCfg->getSwitchPOC() || -1 == m_pcCfg->getDebugCTU() ) )
+#else
+  if( startCtuTsAddr == 0 )
+#endif
   {
     cs.initStructData (pcSlice->getSliceQp(), pcSlice->getPPS()->getTransquantBypassEnabledFlag());
   }
@@ -1490,11 +1494,19 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
   // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment)
   for( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
   {
+#if JVET_M0055_DEBUG_CTU
+ #if HEVC_TILES_WPP
+    const int32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap( ctuTsAddr );
+ #else
+    const int32_t ctuRsAddr = ctuTsAddr;
+#endif
+#else
 #if HEVC_TILES_WPP
     const uint32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap(ctuTsAddr);
 #else
     const uint32_t ctuRsAddr = ctuTsAddr;
 #endif
+#endif
 
 #if HEVC_TILES_WPP
     // update CABAC state
@@ -1508,6 +1520,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUWidth, pcv.maxCUHeight ) );
     DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
 
+#if JVET_M0055_DEBUG_CTU
+    if( pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU() )
+#endif
     if ( pcSlice->getSliceType() != I_SLICE && ctuXPosInCtus == 0)
     {
       pcSlice->resetMotionLUTs();
@@ -1613,6 +1628,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       m_pcInterSearch->initWeightIdxBits();
     }
 
+#if JVET_M0055_DEBUG_CTU
+    if( pCfg->getSwitchPOC() != pcPic->poc || ctuRsAddr >= pCfg->getDebugCTU() )
+#endif
 #if ENABLE_WPP_PARALLELISM
     pEncLib->getCuEncoder( dataId )->compressCtu( cs, ctuArea, ctuRsAddr, prevQP, currQP );
 #else
-- 
GitLab