diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index b6584f0754dd08616524ea3096dae8904859a3eb..0e4e9c1f519f4ad843059deafa4a3df886d29d4b 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -95,6 +95,18 @@ uint32_t DecApp::decode()
     }
   }
 
+#if JVET_P2008_OUTPUT_LOG
+  if (!m_oplFilename.empty() && m_oplFilename!="-")
+  {
+    m_oplFilename += ".opl";
+    m_oplFileStream.open(m_oplFilename.c_str(), std::ios::out);
+    if (!m_oplFileStream.is_open() || !m_oplFileStream.good())
+    {
+      EXIT( "Unable to open file "<< m_oplFilename.c_str() << " to write an opl-file for conformance testing (see JVET-P2008 for details)");
+    }
+  }
+#endif //JVET_P2008_OUTPUT_LOG
+
   // create & initialize internal classes
   xCreateDecLib();
 
@@ -656,6 +668,21 @@ bool DecApp::isNewAccessUnit( bool newPicture, ifstream *bitstreamFile, class In
   return ret;
 }
 
+#if JVET_P2008_OUTPUT_LOG
+void DecApp::writeLineToOutputLog(Picture * pcPic)
+{
+  if (m_oplFileStream.is_open() && m_oplFileStream.good())
+  {
+    const SPS* sps = pcPic->cs->sps;
+    PictureHash recon_digest;
+    auto numChar = calcMD5(((const Picture*)pcPic)->getRecoBuf(), recon_digest, sps->getBitDepths());
+
+
+    m_oplFileStream << std::setw(8) << pcPic->getPOC() << "," << std::setw(5) << pcPic->Y().width << "," << std::setw(5) << pcPic->Y().height << "," << hashToString(recon_digest, numChar) << "\n";
+  }
+}
+#endif // JVET_P2008_OUTPUT_LOG
+
 // ====================================================================================================================
 // Protected member functions
 // ====================================================================================================================
@@ -802,6 +829,10 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
                                           NUM_CHROMA_FORMAT, isTff );
           }
         }
+#if JVET_P2008_OUTPUT_LOG
+        writeLineToOutputLog(pcPicTop);
+        writeLineToOutputLog(pcPicBottom);
+#endif
 
         // update POC of display order
         m_iPOCLastDisplay = pcPicBottom->getPOC();
@@ -860,6 +891,9 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
                                         NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
             }
         }
+#if JVET_P2008_OUTPUT_LOG
+        writeLineToOutputLog(pcPic);
+#endif
 
 #if HEVC_SEI
         if (m_seiMessageFileStream.is_open())
@@ -929,7 +963,10 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
                                         conf.getWindowBottomOffset() * SPS::getWinUnitY( pcPicTop->cs->sps->getChromaFormatIdc() ),
                                         NUM_CHROMA_FORMAT, isTff );
         }
-
+#if JVET_P2008_OUTPUT_LOG
+        writeLineToOutputLog(pcPicTop);
+        writeLineToOutputLog(pcPicBottom);
+#endif
         // update POC of display order
         m_iPOCLastDisplay = pcPicBottom->getPOC();
 
@@ -997,7 +1034,9 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
                                         NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
             }
         }
-
+#if JVET_P2008_OUTPUT_LOG
+        writeLineToOutputLog(pcPic);
+#endif
 #if HEVC_SEI
         if (m_seiMessageFileStream.is_open())
         {
diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h
index 2d5c0fcdae81b11c04f0ca70ac489f23aac9cc86..b355a04e46f4bf74d118980e1cc7255b20f3fd7e 100644
--- a/source/App/DecoderApp/DecApp.h
+++ b/source/App/DecoderApp/DecApp.h
@@ -66,6 +66,12 @@ private:
   // for output control
   int             m_iPOCLastDisplay;              ///< last POC in display order
   std::ofstream   m_seiMessageFileStream;         ///< Used for outputing SEI messages.
+
+#if JVET_P2008_OUTPUT_LOG
+  std::ofstream   m_oplFileStream;                ///< Used to output log file for confomance testing
+#endif //JVET_P2008_OUTPUT_LOG
+
+
 #if HEVC_SEI
   ColourRemapping m_cColourRemapping;             ///< colour remapping handler
 #endif
@@ -86,6 +92,11 @@ private:
   bool  deriveOutputLayerSet(); ///< derive OLS and layer sets
   bool  isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream);  ///< check if next NAL unit will be the first NAL unit from a new picture
   bool  isNewAccessUnit(bool newPicture, ifstream *bitstreamFile, class InputByteStream *bytestream);  ///< check if next NAL unit will be the first NAL unit from a new access unit
+
+#if JVET_P2008_OUTPUT_LOG 
+  void  writeLineToOutputLog(Picture * pcPic);
+#endif // JVET_P2008_OUTPUT_LOG 
+
 };
 
 //! \}
diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp
index 310251e87e3cfcd792d72cd2cfa9336ff1d7ec72..63808add02c8f034a9c3c645afe4c65742a14cc4 100644
--- a/source/App/DecoderApp/DecAppCfg.cpp
+++ b/source/App/DecoderApp/DecAppCfg.cpp
@@ -77,6 +77,10 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] )
   ("BitstreamFile,b",           m_bitstreamFileName,                   string(""), "bitstream input file name")
   ("ReconFile,o",               m_reconFileName,                       string(""), "reconstructed YUV output file name\n")
 
+#if JVET_P2008_OUTPUT_LOG
+  ("OplFile,-opl",              m_oplFilename ,                        string(""), "opl-file name without extension for conformance testing\n")
+#endif //JVET_P2008_OUTPUT_LOG
+
 #if ENABLE_SIMD_OPT
   ("SIMD",                      ignore,                                string(""), "SIMD extension to use (SCALAR, SSE41, SSE42, AVX, AVX2, AVX512), default: the highest supported extension\n")
 #endif
@@ -223,6 +227,10 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] )
 DecAppCfg::DecAppCfg()
 : m_bitstreamFileName()
 , m_reconFileName()
+#if JVET_P2008_OUTPUT_LOG
+, m_oplFilename()
+#endif //JVET_P2008_OUTPUT_LOG
+
 , m_iSkipFrame(0)
 // m_outputBitDepth array initialised below
 , m_outputColourSpaceConvert(IPCOLOURSPACE_UNCHANGED)
diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h
index cc45bfdd88ffbbf828ae96a755e7a09d9c55b059..1ded0629224d0f5c965ee49206507e8970871885 100644
--- a/source/App/DecoderApp/DecAppCfg.h
+++ b/source/App/DecoderApp/DecAppCfg.h
@@ -69,6 +69,12 @@ protected:
   std::string   m_colourRemapSEIFileName;             ///< output Colour Remapping file name
   std::vector<int> m_targetDecLayerIdSet;             ///< set of LayerIds to be included in the sub-bitstream extraction process.
   std::string   m_outputDecodedSEIMessagesFilename;   ///< filename to output decoded SEI messages to. If '-', then use stdout. If empty, do not output details.
+
+#if JVET_P2008_OUTPUT_LOG
+  std::string   m_oplFilename;                        ///< filename to output conformance log.
+#endif //JVET_P2008_OUTPUT_LOG
+
+
   bool          m_bClipOutputVideoToRec709Range;      ///< If true, clip the output video to the Rec 709 range on saving.
   bool          m_packedYUVMode;                      ///< If true, output 10-bit and 12-bit YUV data as 5-byte and 3-byte (respectively) packed YUV data
   std::string   m_cacheCfgFile;                       ///< Config file of cache model
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 1c259541cde70d2bdf5b85ed760b00cb80b6dc97..aad5a47fc4b1f207ee4eb6919826411eba2fa8b1 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -299,6 +299,10 @@ public:
 
 int calcAndPrintHashStatus(const CPelUnitBuf& pic, const class SEIDecodedPictureHash* pictureHashSEI, const BitDepths &bitDepths, const MsgLevel msgl);
 
+#if JVET_P2008_OUTPUT_LOG
+uint32_t calcMD5(const CPelUnitBuf& pic, PictureHash &digest, const BitDepths &bitDepths);
+std::string hashToString(const PictureHash &digest, int numChar);
+#endif // JVET_P2008_OUTPUT_LOG
 
 typedef std::list<Picture*> PicList;
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 756850b86b059df6a67a94fd810dd00696bd4a68..fefdbfe7a98263909b0154bed9ca34afe2315584 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,7 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_P2008_OUTPUT_LOG                             1 // Output log file for conformance tests
 #define JVET_Q0110_Q0785_CHROMA_BDPCM_420                 1 // JVET-Q0110/Q0785: Enable chroma BDPCM for 420, separate contexts for chroma BDPCM and bug-fixes.
 
 #define JVET_Q0512_ENC_CHROMA_TS_ACT                      1 // JVET-Q0512: encoder-side improvement on enabling chroma transform-skip for ACT