diff --git a/CMakeLists.txt b/CMakeLists.txt
index 574707d86a77b06cee8e523cf691a8ca388bcb3e..eedbcd95e9624c1c1d6383e577403ecb1ab32541 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -152,6 +152,7 @@ add_subdirectory( "source/App/EncoderApp" )
 add_subdirectory( "source/App/SEIRemovalApp" )
 add_subdirectory( "source/App/Parcat" )
 add_subdirectory( "source/App/StreamMergeApp" )
+add_subdirectory( "source/App/BitstreamExtractorApp" )
 if( EXTENSION_360_VIDEO )
   add_subdirectory( "source/App/utils/360ConvertApp" )
 endif()
diff --git a/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e760fc59d3211145415d953c59ff55d97a6a6d7
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp
@@ -0,0 +1,265 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2020, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <list>
+#include <vector>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "CommonLib/CommonDef.h"
+#include "BitstreamExtractorApp.h"
+#include "DecoderLib/AnnexBread.h"
+#include "DecoderLib/NALread.h"
+#include "EncoderLib/NALwrite.h"
+#include "EncoderLib/VLCWriter.h"
+#include "EncoderLib/AnnexBwrite.h"
+
+BitstreamExtractorApp::BitstreamExtractorApp()
+{
+}
+
+void BitstreamExtractorApp::xPrintVPSInfo (VPS *vps)
+{
+  msg (VERBOSE, "VPS Info: \n");
+  msg (VERBOSE, "  VPS ID         : %d\n", vps->getVPSId());
+  msg (VERBOSE, "  Max layers     : %d\n", vps->getMaxLayers());
+  msg (VERBOSE, "  Max sub-layers : %d\n", vps->getMaxSubLayers());
+  msg (VERBOSE, "  Number of OLS  : %d\n", vps->getNumOutputLayerSets());
+  for (int olsIdx=0; olsIdx < vps->getNumOutputLayerSets(); olsIdx++)
+  {
+    vps->deriveTargetOutputLayerSet(olsIdx);
+    msg (VERBOSE, "    OLS # %d\n", olsIdx);
+    msg (VERBOSE, "      Output layers: ");
+    for( int i = 0; i < vps->m_targetOutputLayerIdSet.size(); i++ )
+    {
+      msg (VERBOSE, "%d  ", vps->m_targetOutputLayerIdSet[i]);
+    }
+    msg (VERBOSE, "\n");
+
+    msg (VERBOSE, "      Target layers: ");
+    for( int i = 0; i < vps->m_targetLayerIdSet.size(); i++ )
+    {
+      msg (VERBOSE, "%d  ", vps->m_targetLayerIdSet[i]);
+    }
+    msg (VERBOSE, "\n");
+  }
+}
+
+void BitstreamExtractorApp::xWriteVPS(VPS *vps, std::ostream& out, int layerId, int temporalId)
+{
+  // create a new NAL unit for output
+  OutputNALUnit naluOut (NAL_UNIT_VPS, layerId, temporalId);
+  CHECK( naluOut.m_temporalId, "The value of TemporalId of VPS NAL units shall be equal to 0" );
+
+  // write the VPS to the newly created NAL unit buffer
+  m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
+  m_hlSyntaxWriter.codeVPS( vps );
+
+  // create a dummy AU
+  AccessUnit tmpAu;
+  // convert to EBSP (this adds emulation prevention!) and add into NAL unit
+  tmpAu.push_back(new NALUnitEBSP(naluOut));
+
+  // write the dummy AU
+  // note: The first NAL unit in an access unit will be written with a 4-byte start code
+  //       Parameter sets are also coded with a 4-byte start code, so writing the dummy
+  //       AU works without chaning the start code length.
+  //       This cannot be done for VLC NAL units!
+  writeAnnexB (out, tmpAu);
+}
+
+void BitstreamExtractorApp::xWriteSPS(SPS *sps, std::ostream& out, int layerId, int temporalId)
+{
+  // create a new NAL unit for output
+  OutputNALUnit naluOut (NAL_UNIT_SPS, layerId, temporalId);
+  CHECK( naluOut.m_temporalId, "The value of TemporalId of SPS NAL units shall be equal to 0" );
+
+  // write the SPS to the newly created NAL unit buffer
+  m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
+  m_hlSyntaxWriter.codeSPS( sps );
+
+  // create a dummy AU
+  AccessUnit tmpAu;
+  // convert to EBSP (this adds emulation prevention!) and add into NAL unit
+  tmpAu.push_back(new NALUnitEBSP(naluOut));
+
+  // write the dummy AU
+  // note: The first NAL unit in an access unit will be written with a 4-byte start code
+  //       Parameter sets are also coded with a 4-byte start code, so writing the dummy
+  //       AU works without chaning the start code length.
+  //       This cannot be done for VLC NAL units!
+  writeAnnexB (out, tmpAu);
+}
+
+void BitstreamExtractorApp::xWritePPS(PPS *pps, std::ostream& out, int layerId, int temporalId)
+{
+  // create a new NAL unit for output
+  OutputNALUnit naluOut (NAL_UNIT_PPS, layerId, temporalId);
+
+  // write the PPS to the newly created NAL unit buffer
+  m_hlSyntaxWriter.setBitstream( &naluOut.m_Bitstream );
+  m_hlSyntaxWriter.codePPS( pps );
+
+  // create a dummy AU
+  AccessUnit tmpAu;
+  // convert to EBSP (this adds emulation prevention!) and add into NAL unit
+  tmpAu.push_back(new NALUnitEBSP(naluOut));
+
+  // write the dummy AU
+  // note: The first NAL unit in an access unit will be written with a 4-byte start code
+  //       Parameter sets are also coded with a 4-byte start code, so writing the dummy
+  //       AU works without chaning the start code length.
+  //       This cannot be done for VLC NAL units!
+  writeAnnexB (out, tmpAu);
+}
+
+
+uint32_t BitstreamExtractorApp::decode()
+{
+  std::ifstream bitstreamFileIn(m_bitstreamFileNameIn.c_str(), std::ifstream::in | std::ifstream::binary);
+  if (!bitstreamFileIn)
+  {
+    EXIT( "failed to open bitstream file " << m_bitstreamFileNameIn.c_str() << " for reading" ) ;
+  }
+
+  std::ofstream bitstreamFileOut(m_bitstreamFileNameOut.c_str(), std::ifstream::out | std::ifstream::binary);
+
+  InputByteStream bytestream(bitstreamFileIn);
+
+  bitstreamFileIn.clear();
+  bitstreamFileIn.seekg( 0, std::ios::beg );
+
+  int unitCnt = 0;
+
+  while (!!bitstreamFileIn)
+  {
+    AnnexBStats stats = AnnexBStats();
+
+    InputNALUnit nalu;
+    byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
+
+    // call actual decoding function
+    if (nalu.getBitstream().getFifo().empty())
+    {
+      /* this can happen if the following occur:
+       *  - empty input file
+       *  - two back-to-back start_code_prefixes
+       *  - start_code_prefix immediately followed by EOF
+       */
+      msg(WARNING, "Warning: Attempt to decode an empty NAL unit" );
+    }
+    else
+    {
+      read(nalu);
+
+      bool writeInpuNalUnitToStream = true;
+
+      // filte temporal layers
+      writeInpuNalUnitToStream &= ( m_maxTemporalLayer < 0  ) || ( nalu.m_temporalId <= m_maxTemporalLayer );
+
+      if( nalu.m_nalUnitType == NAL_UNIT_VPS )
+      {
+        VPS* vps = new VPS();
+        m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
+        m_hlSynaxReader.parseVPS( vps );
+        m_parameterSetManager.storeVPS( vps, nalu.getBitstream().getFifo() );
+        xPrintVPSInfo(vps);
+
+        // example: just write the parsed VPS back to the stream
+        // *** add modifications here ***
+        // only write, if not dropped earlier
+        if (writeInpuNalUnitToStream)
+        {
+          xWriteVPS(vps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
+          writeInpuNalUnitToStream = false;
+        }
+      }
+
+      if( nalu.m_nalUnitType == NAL_UNIT_SPS )
+      {
+        SPS* sps = new SPS();
+        m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
+        m_hlSynaxReader.parseSPS( sps );
+        m_parameterSetManager.storeSPS( sps, nalu.getBitstream().getFifo() );
+
+        msg (VERBOSE, "SPS Info: SPS ID = %d\n", sps->getSPSId());
+        // example: just write the parsed SPS back to the stream
+        // *** add modifications here ***
+        // only write, if not dropped earlier
+        if (writeInpuNalUnitToStream)
+        {
+          xWriteSPS(sps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
+          writeInpuNalUnitToStream = false;
+        }
+      }
+
+      if( nalu.m_nalUnitType == NAL_UNIT_PPS )
+      {
+        PPS* pps = new PPS();
+        m_hlSynaxReader.setBitstream( &nalu.getBitstream() );
+        m_hlSynaxReader.parsePPS( pps );
+        m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() );
+        msg (VERBOSE, "PPS Info: PPS ID = %d\n", pps->getPPSId());
+
+        // example: just write the parsed PPS back to the stream
+        // *** add modifications here ***
+        // only write, if not dropped earlier
+        if (writeInpuNalUnitToStream)
+        {
+          xWritePPS(pps, bitstreamFileOut, nalu.m_nuhLayerId, nalu.m_temporalId);
+          writeInpuNalUnitToStream = false;
+        }
+      }
+
+      unitCnt++;
+
+      if( writeInpuNalUnitToStream )
+      {
+        int numZeros = stats.m_numLeadingZero8BitsBytes + stats.m_numZeroByteBytes + stats.m_numStartCodePrefixBytes -1;
+        // write start code
+        char ch = 0;
+        for( int i = 0 ; i < numZeros; i++ )
+        {
+          bitstreamFileOut.write( &ch, 1 );
+        }
+        ch = 1;
+        bitstreamFileOut.write( &ch, 1 );
+        // write input NAL unit
+        bitstreamFileOut.write( (const char*)nalu.getBitstream().getFifo().data(), nalu.getBitstream().getFifo().size() );
+      }
+    }
+  }
+
+  return 0;
+}
+
diff --git a/source/App/BitstreamExtractorApp/BitstreamExtractorApp.h b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.h
new file mode 100644
index 0000000000000000000000000000000000000000..c753c90330122515e53da672c73c03bac20381e0
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.h
@@ -0,0 +1,74 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2020, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BITSTREAMEXTRACTORAPP__
+#define __BITSTREAMEXTRACTORAPP__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <stdio.h>
+#include <fstream>
+#include <iostream>
+
+#include "CommonLib/CommonDef.h"
+#include "BitstreamExtractorAppCfg.h"
+#include "CommonLib/ParameterSetManager.h"
+#include "DecoderLib/NALread.h"
+#include "VLCReader.h"
+#include "VLCWriter.h"
+
+class BitstreamExtractorApp : public BitstreamExtractorAppCfg
+{
+
+public:
+  BitstreamExtractorApp();
+  virtual ~BitstreamExtractorApp         ()  {}
+
+  uint32_t  decode            (); ///< main decoding function
+  
+protected:
+  void xPrintVPSInfo (VPS *vps);
+
+  void xWriteVPS(VPS *vps, std::ostream& out, int layerId, int temporalId);
+  void xWriteSPS(SPS *sps, std::ostream& out, int layerId, int temporalId);
+  void xWritePPS(PPS *pps, std::ostream& out, int layerId, int temporalId);
+
+  ParameterSetManager   m_parameterSetManager;
+  HLSyntaxReader        m_hlSynaxReader;
+  HLSWriter             m_hlSyntaxWriter;
+};
+
+#endif // __BITSTREAMEXTRACTORAPP__
+
diff --git a/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.cpp b/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0329958730638a756fefcdb95b8448c1b07c60a
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.cpp
@@ -0,0 +1,166 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2020, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include "CommonLib/CommonDef.h"
+#include "BitstreamExtractorApp.h"
+#include "Utilities/program_options_lite.h"
+#if ENABLE_TRACING
+#include "CommonLib/dtrace_next.h"
+#endif
+
+using namespace std;
+namespace po = df::program_options_lite;
+
+
+// ====================================================================================================================
+// Public member functions
+// ====================================================================================================================
+
+// argc number of arguments
+// argv array of arguments
+ bool BitstreamExtractorAppCfg::parseCfg( int argc, char* argv[] )
+{
+#if ENABLE_TRACING
+  bool printTracingChannelsList;
+  std::string tracingFile;
+  std::string tracingRule;
+#endif
+
+  bool printHelp = false;
+  bool warnUnknownParameter = false;
+  int  verbosity;
+
+  po::Options opts;
+  opts.addOptions()
+
+  ("help",                      printHelp,                             false,      "This help text")
+  ("BitstreamFileIn,b",         m_bitstreamFileNameIn,                 string(""), "Bitstream input file name")
+  ("BitstreamFileOut,o",        m_bitstreamFileNameOut,                string(""), "bitstream output file name")
+  ("MaxTemporalLayer,t",        m_maxTemporalLayer,                    -1,         "Maximum Temporal Layer to be decoded. -1 to decode all layers")
+  ("TargetOutputLayerSet,p",    m_targetOlsIdx,                        -1,         "Target output layer set index")
+  ("SubPicId,p",                m_subPicId,                            -1,         "Target subpic ID")
+
+#if ENABLE_TRACING
+  ("TraceChannelsList",         printTracingChannelsList,              false,        "List all available tracing channels" )
+  ("TraceRule",                 tracingRule,                           string( "" ), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")" )
+  ("TraceFile",                 tracingFile,                           string( "" ), "Tracing file" )
+#endif
+
+  ("Verbosity,v",               verbosity,                             (int)VERBOSE, "Specifies the level of the verboseness")
+  ("WarnUnknowParameter,w",     warnUnknownParameter,                  false,        "Warn for unknown configuration parameters instead of failing")
+  ;
+
+  po::setDefaults(opts);
+  po::ErrorReporter err;
+  const list<const char*>& argv_unhandled = po::scanArgv(opts, argc, (const char**) argv, err);
+
+  for (list<const char*>::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++)
+  {
+    std::cerr << "Unhandled argument ignored: "<< *it << std::endl;
+  }
+
+  if (argc == 1 || printHelp)
+  {
+    po::doHelp(cout, opts);
+    return false;
+  }
+
+#if ENABLE_TRACING
+  g_trace_ctx = tracing_init( tracingFile, tracingRule );
+  if( printTracingChannelsList && g_trace_ctx )
+  {
+    std::string channelsList;
+    g_trace_ctx->getChannelsList( channelsList );
+    msg( INFO, "\nAvailable tracing channels:\n\n%s\n", channelsList.c_str() );
+  }
+  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) );
+#endif
+  
+  g_verbosity = MsgLevel( verbosity );
+
+  if (err.is_errored)
+  {
+    if (!warnUnknownParameter)
+    {
+      /* errors have already been reported to stderr */
+      return false;
+    }
+  }
+
+  if (m_targetOlsIdx != -1)
+  {
+    std::cerr << "Extraction by target output layer set index is not implemented yet";
+    return false;
+  }
+
+  if (m_subPicId != -1)
+  {
+    std::cerr << "Extraction by subpicture ID is not implemented yet";
+    return false;
+  }
+
+  if (m_bitstreamFileNameIn.empty())
+  {
+    std::cerr << "No input file specified, aborting" << std::endl;
+    return false;
+  }
+  if (m_bitstreamFileNameOut.empty())
+  {
+    std::cerr << "No output file specified, aborting" << std::endl;
+    return false;
+  }
+
+
+  return true;
+}
+
+BitstreamExtractorAppCfg::BitstreamExtractorAppCfg()
+: m_bitstreamFileNameIn()
+, m_bitstreamFileNameOut()
+, m_maxTemporalLayer( -1 )
+, m_targetOlsIdx( -1 )
+, m_subPicId( -1 )
+{
+}
+
+BitstreamExtractorAppCfg::~BitstreamExtractorAppCfg()
+{
+#if ENABLE_TRACING
+  tracing_uninit( g_trace_ctx );
+#endif
+}
+
diff --git a/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.h b/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.h
new file mode 100644
index 0000000000000000000000000000000000000000..adc182862a3e366f7ee1f3c6345b1d4fe92b0f73
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/BitstreamExtractorAppCfg.h
@@ -0,0 +1,65 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2020, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __BITSTREAMEXTRACTORAPPCFG__
+#define __BITSTREAMEXTRACTORAPPCFG__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "CommonLib/CommonDef.h"
+#include <vector>
+
+// Bitstream Extractor configuration class
+class BitstreamExtractorAppCfg
+{
+protected:
+  std::string   m_bitstreamFileNameIn;                //  output bitstream file name
+  std::string   m_bitstreamFileNameOut;               //  input bitstream file name
+  int           m_maxTemporalLayer;
+  int           m_targetOlsIdx;
+  int           m_subPicId;
+
+public:
+  BitstreamExtractorAppCfg();
+  virtual ~BitstreamExtractorAppCfg();
+
+  bool  parseCfg        ( int argc, char* argv[] );   //  initialize option class from configuration
+};
+
+
+#endif  // __BITSTREAMEXTRACTORAPPCFG__
+
+
diff --git a/source/App/BitstreamExtractorApp/CMakeLists.txt b/source/App/BitstreamExtractorApp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a299cf5cca769c71f83b9c683bcfae461625ee79
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/CMakeLists.txt
@@ -0,0 +1,84 @@
+# executable
+set( EXE_NAME BitstreamExtractorApp )
+
+# get source files
+file( GLOB SRC_FILES "*.cpp" )
+
+# get include files
+file( GLOB INC_FILES "*.h" )
+
+# get additional libs for gcc on Ubuntu systems
+if( CMAKE_SYSTEM_NAME STREQUAL "Linux" )
+  if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
+    if( USE_ADDRESS_SANITIZER )
+      set( ADDITIONAL_LIBS asan )
+    endif()
+  endif()
+endif()
+
+# NATVIS files for Visual Studio
+if( MSVC )
+  file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" )
+endif()
+
+# add executable
+add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} )
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+if( SET_ENABLE_TRACING )
+  if( ENABLE_TRACING )
+    target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=1 )
+  else()
+    target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=0 )
+  endif()
+endif()
+
+if( OpenMP_FOUND )
+  if( SET_ENABLE_SPLIT_PARALLELISM )
+    if( ENABLE_SPLIT_PARALLELISM )
+      target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_SPLIT_PARALLELISM=1 )
+    else()
+      target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_SPLIT_PARALLELISM=0 )
+    endif()
+  endif()
+  if( SET_ENABLE_WPP_PARALLELISM )
+    if( ENABLE_WPP_PARALLELISM )
+      target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_PARALLELISM=1 )
+    else()
+      target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_PARALLELISM=0 )
+    endif()
+  endif()
+else()
+  target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_SPLIT_PARALLELISM=0 )
+  target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_PARALLELISM=0 )
+endif()
+
+if( CMAKE_COMPILER_IS_GNUCC AND BUILD_STATIC )
+  set( ADDITIONAL_LIBS ${ADDITIONAL_LIBS} -static -static-libgcc -static-libstdc++ )
+  target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_STATIC_LINK=1 )
+endif()
+
+target_link_libraries( ${EXE_NAME} CommonLib EncoderLib DecoderLib Utilities Threads::Threads ${ADDITIONAL_LIBS} )
+
+# lldb custom data formatters
+if( XCODE )
+  add_dependencies( ${EXE_NAME} Install${PROJECT_NAME}LldbFiles )
+endif()
+
+if( CMAKE_SYSTEM_NAME STREQUAL "Linux" )
+  add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
+                                                          $<$<CONFIG:Debug>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/BitstreamExtractorApp>
+                                                          $<$<CONFIG:Release>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/BitstreamExtractorApp>
+                                                          $<$<CONFIG:RelWithDebInfo>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/BitstreamExtractorApp>
+                                                          $<$<CONFIG:MinSizeRel>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/BitstreamExtractorApp>
+                                                          $<$<CONFIG:Debug>:${CMAKE_SOURCE_DIR}/bin/BitstreamExtractorAppStaticd>
+                                                          $<$<CONFIG:Release>:${CMAKE_SOURCE_DIR}/bin/BitstreamExtractorAppStatic>
+                                                          $<$<CONFIG:RelWithDebInfo>:${CMAKE_SOURCE_DIR}/bin/BitstreamExtractorAppStaticp>
+                                                          $<$<CONFIG:MinSizeRel>:${CMAKE_SOURCE_DIR}/bin/BitstreamExtractorAppStaticm> )
+endif()
+
+# example: place header files in different folders
+source_group( "Natvis Files" FILES ${NATVIS_FILES} )
+
+# set the folder where to place the projects
+set_target_properties( ${EXE_NAME}         PROPERTIES FOLDER app LINKER_LANGUAGE CXX )
diff --git a/source/App/BitstreamExtractorApp/bitstreamextractormain.cpp b/source/App/BitstreamExtractorApp/bitstreamextractormain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e57f05d414d2133702f2cf367d50a37d4b88857d
--- /dev/null
+++ b/source/App/BitstreamExtractorApp/bitstreamextractormain.cpp
@@ -0,0 +1,112 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2020, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include "CommonLib/CommonDef.h"
+#include "BitstreamExtractorApp.h"
+#include "program_options_lite.h"
+
+// ====================================================================================================================
+// Main function
+// ====================================================================================================================
+
+int main(int argc, char* argv[])
+{
+  int returnCode = EXIT_SUCCESS;
+
+  // print information
+  fprintf( stdout, "\n" );
+  fprintf( stdout, "VVCSoftware: VTM Bitstream Extractor Version %s ", VTM_VERSION );
+  fprintf( stdout, NVM_ONOS );
+  fprintf( stdout, NVM_COMPILEDBY );
+  fprintf( stdout, NVM_BITS );
+#if ENABLE_SIMD_OPT
+  std::string SIMD;
+  df::program_options_lite::Options optsSimd;
+  optsSimd.addOptions()( "SIMD", SIMD, std::string( "" ), "" );
+  df::program_options_lite::SilentReporter err;
+  df::program_options_lite::scanArgv( optsSimd, argc, ( const char** ) argv, err );
+  fprintf( stdout, "[SIMD=%s] ", read_x86_extension( SIMD ) );
+#endif
+#if ENABLE_TRACING
+  fprintf( stdout, "[ENABLE_TRACING] " );
+#endif
+  fprintf( stdout, "\n" );
+
+  BitstreamExtractorApp *extractorApp = new BitstreamExtractorApp;
+  // parse configuration
+  if(!extractorApp->parseCfg( argc, argv ))
+  {
+    returnCode = EXIT_FAILURE;
+    return returnCode;
+  }
+
+  // starting time
+  double timeDifference;
+  clock_t startTime = clock();
+
+  // call decoding function
+#ifndef _DEBUG
+  try
+  {
+#endif // !_DEBUG
+    if( 0 != extractorApp->decode() )
+    {
+      printf( "\n\n***ERROR*** A decoding mismatch occured: signalled md5sum does not match\n" );
+      returnCode = EXIT_FAILURE;
+    }
+#ifndef _DEBUG
+  }
+  catch( Exception &e )
+  {
+    std::cerr << e.what() << std::endl;
+    returnCode = EXIT_FAILURE;
+  }
+  catch( ... )
+  {
+    std::cerr << "Unspecified error occurred" << std::endl;
+    returnCode = EXIT_FAILURE;
+  }
+#endif
+
+  // ending time
+  timeDifference = (double)(clock()-startTime) / CLOCKS_PER_SEC;
+  printf("\n Total Time: %12.3f sec.\n", timeDifference);
+
+  delete extractorApp;
+
+  return returnCode;
+}
+