diff --git a/CMakeLists.txt b/CMakeLists.txt
index 574707d8..ca71de16 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -149,6 +149,7 @@ add_subdirectory( "source/Lib/Utilities" )
 add_subdirectory( "source/App/DecoderAnalyserApp" )
 add_subdirectory( "source/App/DecoderApp" )
 add_subdirectory( "source/App/EncoderApp" )
+add_subdirectory( "source/App/utils/testbed" )
 add_subdirectory( "source/App/SEIRemovalApp" )
 add_subdirectory( "source/App/Parcat" )
 add_subdirectory( "source/App/StreamMergeApp" )
diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index 629b2351..9fff62c6 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -296,7 +296,6 @@ void DecApp::xCreateDecLib()
 #endif
   );
   m_cDecLib.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
-
   m_cDecLib.setTargetDecLayer(m_iTargetLayer);
 
   if (!m_outputDecodedSEIMessagesFilename.empty())
diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h
index 774d15da..ab9bd36c 100644
--- a/source/App/DecoderApp/DecAppCfg.h
+++ b/source/App/DecoderApp/DecAppCfg.h
@@ -77,7 +77,6 @@ protected:
   bool          m_mctsCheck;
 
   int          m_upscaledOutput;                     ////< Output upscaled (2), decoded but in full resolution buffer (1) or decoded cropped (0, default) picture for RPR.
-
 public:
   DecAppCfg();
   virtual ~DecAppCfg();
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 3390dc92..9efc1438 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -307,6 +307,9 @@ void EncApp::xInitLibCfg()
       m_cEncLib.setLadfIntervalLowerBound(m_LadfIntervalLowerBound[k], k);
     }
   }
+#endif
+#if JVET_P0300_SIGNALING
+  m_cEncLib.setFastCabacEnabled                                  ( m_FastCabacEnabled );
 #endif
   m_cEncLib.setUseMHIntra                                        ( m_MHIntra );
   m_cEncLib.setUseTriangle                                       ( m_Triangle );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 878c48a9..234f83c0 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -956,6 +956,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("LadfNumIntervals",                                m_LadfNumIntervals,                                   3, "LADF number of intervals (2-5, inclusive)")
   ("LadfQpOffset",                                    cfg_LadfQpOffset,                      cfg_LadfQpOffset, "LADF QP offset")
   ("LadfIntervalLowerBound",                          cfg_LadfIntervalLowerBound,  cfg_LadfIntervalLowerBound, "LADF lower bound for 2nd lowest interval")
+#endif
+#if JVET_P0300_SIGNALING
+  ("FastCabac",                                       m_FastCabacEnabled,                               false, "Fast Cabac Mode")
 #endif
   ("MHIntra",                                         m_MHIntra,                                        false, "Enable MHIntra mode")
   ("Triangle",                                        m_Triangle,                                       false, "Enable triangular shape motion vector prediction (0:off, 1:on)")
@@ -3689,6 +3692,9 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "GBiFast:%d ", m_GBiFast );
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
     msg( VERBOSE, "LADF:%d ", m_LadfEnabed );
+#endif
+#if JVET_P0300_SIGNALING
+    msg( VERBOSE, "FastCabac:%d ", m_FastCabacEnabled);
 #endif
     msg(VERBOSE, "MHIntra:%d ", m_MHIntra);
     msg( VERBOSE, "Triangle:%d ", m_Triangle );
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index a4d392e3..1671569c 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -297,6 +297,9 @@ protected:
   std::vector<int> m_LadfQpOffset;
   int       m_LadfIntervalLowerBound[MAX_LADF_INTERVALS];
 #endif
+#if JVET_P0300_SIGNALING
+  bool      m_FastCabacEnabled;
+#endif
 
   bool      m_MHIntra;
   bool      m_Triangle;
diff --git a/source/App/utils/testbed/CMakeLists.txt b/source/App/utils/testbed/CMakeLists.txt
new file mode 100644
index 00000000..7ebee279
--- /dev/null
+++ b/source/App/utils/testbed/CMakeLists.txt
@@ -0,0 +1,84 @@
+# executable
+set( EXE_NAME testbed )
+
+# 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} )
+
+# 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}/testbed>
+                                                          $<$<CONFIG:Release>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/testbed>
+                                                          $<$<CONFIG:RelWithDebInfo>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/testbed>
+                                                          $<$<CONFIG:MinSizeRel>:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/testbed>
+                                                          $<$<CONFIG:Debug>:${CMAKE_SOURCE_DIR}/bin/testbedd>
+                                                          $<$<CONFIG:Release>:${CMAKE_SOURCE_DIR}/bin/testbedStatic>
+                                                          $<$<CONFIG:RelWithDebInfo>:${CMAKE_SOURCE_DIR}/bin/testbedStaticp>
+                                                          $<$<CONFIG:MinSizeRel>:${CMAKE_SOURCE_DIR}/bin/testbedStaticm> )
+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/utils/testbed/testbed.cpp b/source/App/utils/testbed/testbed.cpp
new file mode 100644
index 00000000..720a09e9
--- /dev/null
+++ b/source/App/utils/testbed/testbed.cpp
@@ -0,0 +1,716 @@
+﻿/* 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) 2018, 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 <cstdint>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <limits>
+#include <random>
+#include <chrono>
+#include <cassert>
+
+// Bin file generation:
+// DecoderApp -b str.bin --TraceFile="bin.txt" --TraceRule="D_CABAC_BINS:poc>=0"
+
+#ifndef ENGINE
+#define ENGINE 2
+//  0: AVC/HEVC
+//  1: VVC
+//  2: JVET-P0300
+#endif
+
+#if WIN32
+inline uint32_t __builtin_clz(uint32_t x)
+{
+  unsigned long position;
+  _BitScanReverse(&position, x);
+  return 31 - position;
+}
+#define NOINLINE __declspec(noinline)
+#else
+#define NOINLINE __attribute__((noinline))
+#endif
+
+#ifndef NOBRANCH_MPS
+#define NOBRANCH_MPS 1
+#endif
+
+#ifndef NOBRANCH
+#define NOBRANCH 0
+#endif
+
+#ifndef USE_RLPS_TABLE
+#define USE_RLPS_TABLE 0
+#endif
+
+#define NCTX 401
+
+
+uint32_t low;
+uint32_t range;
+uint32_t bits_left;
+uint32_t byte_count;
+uint8_t  buffered_byte;
+uint32_t num_buffered_bytes;
+uint8_t *bytes;
+uint32_t value;
+int32_t  bits_needed;
+uint8_t *ptr;
+
+#if NOBRANCH
+#define READ                                                                                                           \
+  range <<= n;                                                                                                         \
+  value <<= n;                                                                                                         \
+  int32_t  _bits_needed = bits_needed + n;                                                                             \
+  uint32_t byte         = *ptr;                                                                                        \
+  byte <<= _bits_needed;                                                                                               \
+  int32_t mask = ~_bits_needed >> 31;                                                                                  \
+  byte &= mask;                                                                                                        \
+  ptr -= mask;                                                                                                         \
+  bits_needed = _bits_needed | -8;                                                                                     \
+  value += byte
+#else
+#define READ                                                                                                           \
+  range <<= n;                                                                                                         \
+  value <<= n;                                                                                                         \
+  bits_needed += n;                                                                                                    \
+  if (bits_needed >= 0)                                                                                                \
+  {                                                                                                                    \
+    value += (*ptr++) << bits_needed;                                                                                  \
+    bits_needed -= 8;                                                                                                  \
+  }
+#endif
+
+void init_enc(uint8_t *buf)
+{
+  low                = 0;
+  range              = 510;
+  bits_left          = 23;
+  byte_count         = 0;
+  num_buffered_bytes = 0;
+  bytes              = buf;
+}
+
+void write_out()
+{
+  uint32_t lead_byte = low >> (24 - bits_left);
+  bits_left += 8;
+  low &= 0xffffffffu >> bits_left;
+  if (lead_byte == 0xff)
+  {
+    num_buffered_bytes++;
+  }
+  else
+  {
+    if (num_buffered_bytes > 0)
+    {
+      uint32_t carry      = lead_byte >> 8;
+      uint8_t  byte       = buffered_byte + carry;
+      buffered_byte       = lead_byte & 0xff;
+      bytes[byte_count++] = byte;
+      byte                = (0xff + carry) & 0xff;
+      while (num_buffered_bytes > 1)
+      {
+        bytes[byte_count++] = byte;
+        num_buffered_bytes--;
+      }
+    }
+    else
+    {
+      num_buffered_bytes = 1;
+      buffered_byte      = lead_byte;
+    }
+  }
+}
+
+uint32_t get_bit_count()
+{
+  return 8 * byte_count + 23 - bits_left;
+}
+
+void terminate_write()
+{
+  for (int i = 0; i < 8; i++)
+  {
+    low <<= 8;
+    bits_left -= 8;
+    if (bits_left < 12)
+      write_out();
+  }
+}
+
+void init_dec(uint8_t *b)
+{
+  bytes       = b;
+  bits_needed = -8;
+
+  range = 510;
+  value = 256 * bytes[0] + bytes[1];
+  ptr   = bytes + 2;
+}
+
+#if ENGINE == 0
+uint8_t state[NCTX];
+void    init();
+
+void init_prob()
+{
+  for (int i = 0; i < NCTX; i++)
+    state[i] = 0;
+}
+
+const uint8_t rps_table[256] = {
+  128, 128, 128, 123, 116, 111, 105, 100, 95,  90,  85,  81, 77, 73, 69, 66, 62,  59,  56,  53,  51,  48,
+  46,  43,  41,  39,  37,  35,  33,  32,  30,  29,  27,  26, 24, 23, 22, 21, 20,  19,  18,  17,  16,  15,
+  14,  14,  13,  12,  12,  11,  11,  10,  10,  9,   9,   8,  8,  7,  7,  7,  6,   6,   6,   2,   176, 167,
+  158, 150, 142, 135, 128, 122, 116, 110, 104, 99,  94,  89, 85, 80, 76, 72, 69,  65,  62,  59,  56,  53,
+  50,  48,  45,  43,  41,  39,  37,  35,  33,  31,  30,  28, 27, 26, 24, 23, 22,  21,  20,  19,  18,  17,
+  16,  15,  14,  14,  13,  12,  12,  11,  11,  10,  9,   9,  9,  8,  8,  7,  7,   2,   208, 197, 187, 178,
+  169, 160, 152, 144, 137, 130, 123, 117, 111, 105, 100, 95, 90, 86, 81, 77, 73,  69,  66,  63,  59,  56,
+  54,  51,  48,  46,  43,  41,  39,  37,  35,  33,  32,  30, 29, 27, 26, 25, 23,  22,  21,  20,  19,  18,
+  17,  16,  15,  15,  14,  13,  12,  12,  11,  11,  10,  10, 9,  9,  8,  2,  240, 227, 216, 205, 195, 185,
+  175, 166, 158, 150, 142, 135, 128, 122, 116, 110, 104, 99, 94, 89, 85, 80, 76,  72,  69,  65,  62,  59,
+  56,  53,  50,  48,  45,  43,  41,  39,  37,  35,  33,  31, 30, 28, 27, 25, 24,  23,  22,  21,  20,  19,
+  18,  17,  16,  15,  14,  14,  13,  12,  12,  11,  11,  10, 9,  2,
+};
+
+const uint8_t next_state[256] = {
+  127, 126, 77,  76,  77,  76,  75,  74,  75,  74,  75,  74,  73,  72,  73,  72,  73,  72,  71,  70,  71,  70,
+  71,  70,  69,  68,  69,  68,  67,  66,  67,  66,  67,  66,  65,  64,  65,  64,  63,  62,  61,  60,  61,  60,
+  61,  60,  59,  58,  59,  58,  57,  56,  55,  54,  55,  54,  53,  52,  53,  52,  51,  50,  49,  48,  49,  48,
+  47,  46,  45,  44,  45,  44,  43,  42,  43,  42,  39,  38,  39,  38,  37,  36,  37,  36,  33,  32,  33,  32,
+  31,  30,  31,  30,  27,  26,  27,  26,  25,  24,  23,  22,  23,  22,  19,  18,  19,  18,  17,  16,  15,  14,
+  13,  12,  11,  10,  9,   8,   9,   8,   5,   4,   5,   4,   3,   2,   1,   0,   0,   1,   2,   3,   4,   5,
+  6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
+  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
+  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,
+  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,
+  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+  116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 124, 125, 126, 127,
+};
+
+void NOINLINE encode(uint32_t val, uint16_t ctx)
+{
+  uint32_t st   = state[ctx];
+  uint32_t mps  = st & 1;
+  uint32_t rlps = rps_table[(st >> 1) + (range & 192)];
+  range -= rlps;
+  if (val == mps)
+  {
+    if (range < 256)
+    {
+      range += range;
+      low += low;
+      bits_left -= 1;
+      if (bits_left < 12)
+        write_out();
+    }
+  }
+  else
+  {
+    uint32_t n = __builtin_clz(rlps) - 23;
+    low += range;
+    range = rlps << n;
+    low <<= n;
+    bits_left -= n;
+    if (bits_left < 12)
+      write_out();
+  }
+
+  state[ctx] = next_state[(st ^ -(val != mps)) + 128];
+}
+
+uint32_t NOINLINE decode(uint16_t ctx)
+{
+  uint32_t st = state[ctx];
+
+  uint32_t rlps = rps_table[(st >> 1) + (range & 192)];
+
+#if NOBRANCH_MPS
+  uint32_t rmps   = range - rlps;
+  int32_t  is_lps = ((int32_t)(rmps + ~(value >> 7))) >> 31;
+  range           = rmps ^ ((rmps ^ rlps) & is_lps);
+  value -= (rmps << 7) & is_lps;
+  st ^= is_lps;
+
+  state[ctx] = next_state[st + 128];
+  uint32_t n = __builtin_clz(range) - 23;
+#else
+  uint32_t n = 0;
+  range -= rlps;
+  uint32_t SR = range << 7;
+
+  if (value < SR)
+  {
+    // MPS path
+    if (range >= 256)
+    {
+      goto done;
+    }
+  }
+  else
+  {
+    st = ~st;
+    // LPS path
+    value = (value - SR);
+    range = rlps;
+  }
+
+  n = __builtin_clz(range) - 23;
+#endif
+  {
+    READ;
+  }
+#if !NOBRANCH_MPS
+done:
+  state[ctx] = next_state[st + 128];
+#endif
+
+  return st & 1;
+}
+#endif
+
+#if ENGINE == 1
+uint32_t state[NCTX];
+
+#if USE_RLPS_TABLE
+const uint8_t rlps_table[256] = {
+  4,   8,   12,  16,  20,  24,  28,  32,  36,  40,  44,  48,  52,  56,  60,  64,  68,  72,  76,  80,  84,  88,
+  92,  96,  100, 104, 108, 112, 116, 120, 124, 128, 4,   8,   13,  17,  22,  26,  31,  35,  40,  44,  49,  53,
+  58,  62,  67,  71,  76,  80,  85,  89,  94,  98,  103, 107, 112, 116, 121, 125, 130, 134, 139, 143, 4,   9,
+  14,  19,  24,  29,  34,  39,  44,  49,  54,  59,  64,  69,  74,  79,  84,  89,  94,  99,  104, 109, 114, 119,
+  124, 129, 134, 139, 144, 149, 154, 159, 4,   9,   15,  20,  26,  31,  37,  42,  48,  53,  59,  64,  70,  75,
+  81,  86,  92,  97,  103, 108, 114, 119, 125, 130, 136, 141, 147, 152, 158, 163, 169, 174, 4,   10,  16,  22,
+  28,  34,  40,  46,  52,  58,  64,  70,  76,  82,  88,  94,  100, 106, 112, 118, 124, 130, 136, 142, 148, 154,
+  160, 166, 172, 178, 184, 190, 4,   10,  17,  23,  30,  36,  43,  49,  56,  62,  69,  75,  82,  88,  95,  101,
+  108, 114, 121, 127, 134, 140, 147, 153, 160, 166, 173, 179, 186, 192, 199, 205, 4,   11,  18,  25,  32,  39,
+  46,  53,  60,  67,  74,  81,  88,  95,  102, 109, 116, 123, 130, 137, 144, 151, 158, 165, 172, 179, 186, 193,
+  200, 207, 214, 221, 4,   11,  19,  26,  34,  41,  49,  56,  64,  71,  79,  86,  94,  101, 109, 116, 124, 131,
+  139, 146, 154, 161, 169, 176, 184, 191, 199, 206, 214, 221, 229, 236
+};
+#endif
+
+
+void init_prob()
+{
+  int a = 8192;
+  int b = 512;
+  for (int i = 0; i < NCTX; i++)
+  {
+    // 15-bit sum, 10-bit prob, 4-bit speed, 3-bit speed
+    state[i] = (a << 17) + (b << 21) + (b << 7) + (7 << 3) + 4;
+  }
+}
+
+void NOINLINE encode(uint32_t val, uint16_t ctx)
+{
+  uint32_t st  = state[ctx];
+  uint32_t mps = (int32_t) st >> 31;
+
+  uint32_t rlps = ((((int32_t) st >> 26) ^ mps) * (range & 0x1e0) >> 6) + 4;
+
+  range -= rlps;
+
+  uint32_t shift0 = st & 7;
+  uint32_t shift1 = (st >> 3) & 15;
+
+#if WIN32
+  int32_t bin = -((int) val & 1);
+#else
+  int32_t bin = -(val & 1);
+#endif
+
+  st -= (st << 14) & 0x7fe00000;
+  st ^= bin;
+  st -= (((st & 0x1ff80) >> shift0) & 0x1ff80) + (((st & 0x7ffe0000) >> shift1) & 0x7ffe0000);
+
+  st ^= bin;
+  st += (st << 14) & 0x7fe00000;
+
+  if (bin == mps)
+  {
+    if (range < 256)
+    {
+      range += range;
+      low += low;
+      bits_left -= 1;
+      if (bits_left < 12)
+        write_out();
+    }
+  }
+  else
+  {
+    uint32_t n = __builtin_clz(rlps) - 23;
+    low += range;
+    range = rlps << n;
+    low <<= n;
+    bits_left -= n;
+    if (bits_left < 12)
+      write_out();
+  }
+
+  state[ctx] = st;
+}
+
+#if NOBRANCH_MPS
+uint32_t NOINLINE decode(uint16_t ctx)
+{
+  uint32_t st = state[ctx];
+
+  uint32_t mps = (int32_t) st >> 31;
+#if USE_RLPS_TABLE
+  uint32_t rlps = rlps_table[(((int32_t) st >> 26) ^ mps) + (range & 0xe0)];
+#else
+  uint32_t rlps = ((((int32_t) st >> 26) ^ mps) * (range & 0x1e0) >> 6) + 4;
+#endif
+
+  uint32_t rmps   = range - rlps;
+  int32_t  is_lps = ((int32_t)(rmps + ~(value >> 7))) >> 31;
+  range           = rmps ^ ((rmps ^ rlps) & is_lps);
+  value -= (rmps << 7) & is_lps;
+
+  uint32_t shift0 = st & 7;
+  uint32_t shift1 = (st >> 3) & 15;
+
+  st -= (st << 14) & 0x7fe00000;
+
+  uint32_t mask0 = (0x1ff80 >> shift0) & 0x1ff80;
+  uint32_t mask1 = (0x7ffe0000 >> shift1) & 0x7ffe0000;
+  st -= ((st >> shift0) & mask0);
+  st -= ((st >> shift1) & mask1);
+
+  int32_t bin = is_lps ^ mps;
+
+  st += (mask0 + mask1) & bin;
+
+  st += (st << 14) & 0x7fe00000;
+
+  state[ctx] = st;
+
+  uint32_t n = __builtin_clz(range) - 23;
+
+  READ;
+
+  return bin & 1;
+}
+#else   // NOBRANCH_MPS
+uint32_t NOINLINE decode(uint16_t ctx)
+{
+  uint32_t st = state[ctx];
+
+  uint32_t mps = (int32_t) st >> 31;
+#if USE_RLPS_TABLE
+  uint32_t rlps   = rlps_table[(((int32_t) st >> 26) ^ mps) + (range & 0xe0)];
+#else
+  uint32_t rlps = ((((int32_t) st >> 26) ^ mps) * (range & 0x1e0) >> 6) + 4;
+#endif
+
+  uint32_t shift0 = st & 7;
+  uint32_t shift1 = (st >> 3) & 15;
+
+  uint32_t mask0 = (0x1ff80 >> shift0) & 0x1ff80;
+  uint32_t mask1 = (0x7ffe0000 >> shift1) & 0x7ffe0000;
+
+  st -= (st << 14) & 0x7fe00000;
+
+  st -= ((st >> shift0) & mask0);
+  st -= ((st >> shift1) & mask1);
+
+  uint32_t n = 0;
+  range -= rlps;
+  uint32_t SR = range << 7;
+  int32_t bin = mps;
+
+  if (value < SR)
+  {
+    // MPS path
+    if (range >= 256)
+    {
+      goto done;
+    }
+  }
+  else
+  {
+    bin = ~bin;
+    // LPS path
+    value = (value - SR);
+    range = rlps;
+  }
+
+  n = __builtin_clz(range) - 23;
+
+  {
+    READ;
+  }
+
+done:
+
+  st += (mask0 + mask1) & bin;
+
+  st += (st << 14) & 0x7fe00000;
+
+  state[ctx] = st;
+
+  return bin & 1;
+}
+#endif   // NOBRANCH_MPS
+#endif
+
+
+#if ENGINE == 2
+uint8_t state[NCTX];
+
+void init_prob( int gb )
+{
+  int shift = 1 + std::abs( gb );
+  int mps = gb >= 0;
+  for (int i = 0; i < NCTX; i++)
+  {
+    // 1-bit mps, 7-bit shift
+    state[i] = (mps << 7) + shift;
+  }
+}
+
+void NOINLINE encode(uint32_t val, const uint8_t state)
+{
+  uint8_t st  = state & 127;
+  uint8_t mps = (uint8_t) state >> 7;
+  uint32_t rlps = range >> st;
+
+  range -= rlps;
+
+  if( val == mps )
+  {
+    if (range < 256)
+    {
+      range += range;
+      low += low;
+      bits_left -= 1;
+      if (bits_left < 12)
+        write_out();
+    }
+  }
+  else
+  {
+    uint32_t n = __builtin_clz(rlps) - 23;
+    low += range;
+    range = rlps << n;
+    low <<= n;
+    bits_left -= n;
+    if (bits_left < 12)
+      write_out();
+  }
+}
+
+
+uint32_t NOINLINE decode(const uint8_t state)
+{
+  uint8_t st  = state & 127;
+  uint8_t mps = (uint8_t) state >> 7;
+  uint32_t rlps = range >> st;
+
+#if NOBRANCH_MPS
+  uint32_t rmps   = range - rlps;
+  int32_t  is_lps = ((int32_t)(rmps + ~(value >> 7))) >> 31;
+  range           = rmps ^ ((rmps ^ rlps) & is_lps);
+  value -= (rmps << 7) & is_lps;
+  int32_t bin = mps ^ is_lps;
+
+  uint32_t n = __builtin_clz(range) - 23;
+#else
+  uint32_t n = 0;
+  range -= rlps;
+  uint32_t SR = range << 7;
+  int32_t bin = mps;
+
+  if (value < SR)
+  {
+    // MPS path
+    if (range >= 256)
+    {
+      goto done;
+    }
+  }
+  else
+  {
+    bin = ~bin;
+    // LPS path
+    value = (value - SR);
+    range = rlps;
+  }
+
+  n = __builtin_clz(range) - 23;
+#endif
+
+  {
+    READ;
+  }
+#if !NOBRANCH_MPS
+done:
+#endif
+  return bin & 1;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+  int period = 50000000;
+
+  uint8_t * bins_in  = new uint8_t[period];
+  uint8_t * bins_out = new uint8_t[period];
+  uint8_t * buf      = new uint8_t[period];
+#if ENGINE == 2
+  uint8_t *next_ctx = new uint8_t[2 * period];
+  const int8_t gbz[] = { -3,-2,-1,-1,0,0,0,1,1,2,3};
+#else
+  uint16_t *next_ctx = new uint16_t[2 * period];
+#endif
+  int       res      = 0;
+
+  int max = 11 + argc - 1;
+  for (int z = 0; z < max; z++)
+  {
+    int sum = 0;
+    double p = -1.0;
+    if (z >= 11)
+    {
+#if ENGINE == 2
+      std::cout << "ENGINE 2 not supported with binfiles." << std::endl;
+      exit(-1);
+#endif
+      FILE *f = fopen(argv[z - 10], "r");
+      for (int i = 0; i < period; i++)
+      {
+        if (feof(f))
+          fseek(f, 0, SEEK_SET);
+
+        int ctx, bin;
+        res |= fscanf(f, "%d %d", &ctx, &bin);
+        bins_in[i] = bin;
+        sum += bins_in[i];
+        if( ctx >= NCTX )
+        {
+          std::cout << "Ctx index in input file too large. Increase NCTX." << std::endl;
+          exit(-1);
+        }
+        next_ctx[2 * i + 0] = ctx;
+        next_ctx[2 * i + 1] = ctx;
+      }
+      fclose(f);
+    }
+    else
+    {
+#if ENGINE == 2
+      init_prob( gbz[z] );
+#endif
+
+      p = z / 10.0;
+      std::mt19937                            generator;
+      std::bernoulli_distribution             distribution(p);
+      std::uniform_int_distribution<unsigned> ctx_dist(0, NCTX-1);
+//      std::uniform_int_distribution<unsigned> ctx_dist(0, 255);
+      for (int i = 0; i < period; i++)
+      {
+        bins_in[i] = distribution(generator);
+        sum += bins_in[i];
+#if ENGINE == 2
+        next_ctx[2 * i + 0] = state[ctx_dist(generator)];
+        next_ctx[2 * i + 1] = state[ctx_dist(generator)];
+#else
+        next_ctx[2 * i + 0] = ctx_dist(generator);
+        next_ctx[2 * i + 1] = ctx_dist(generator);
+#endif
+      }
+    }
+
+
+    std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
+
+    init_enc(buf);
+#if ENGINE != 2
+    init_prob();
+#endif
+    uint8_t prev_bin = 0;
+    for (int i = 0; i < period; i++)
+    {
+      encode(bins_in[i], next_ctx[2 * i + prev_bin]);
+      prev_bin = bins_in[i];
+    }
+
+    terminate_write();
+    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
+
+    init_dec(buf);
+#if ENGINE != 2
+    init_prob();
+#endif
+
+    prev_bin = 0;
+    for (int i = 0; i < period; i++)
+    {
+      bins_out[i]  = decode(next_ctx[2 * i + prev_bin]);
+      prev_bin     = bins_out[i];
+    }
+
+    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
+
+    uint32_t decoded = period;
+    for (int i = 0; i < period; i++)
+    {
+      if (bins_in[i] != bins_out[i])
+      {
+        decoded = i;
+        break;
+      }
+    }
+    int    delta_t  = (int) std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count();
+    int    delta_t2 = (int) std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
+    double entropy  = (period * log(period) - sum * log(sum) - (period - sum) * log(period - sum)) / log(2.0) / period;
+    if( sum == 0 || sum == period )
+    {
+      entropy = 0.0;
+    }
+    std::cout << "p: " << std::setprecision( 3 ) << std::setw( 6 ) << std::fixed << p;
+#if ENGINE == 2
+    std::cout << " gb: " << std::setw( 3 ) << int( gbz[z] );
+#endif
+    std::cout << " " << std::setw(  9 ) << std::setprecision( 6 ) << std::fixed << (get_bit_count() * 1.0 / period / entropy);
+    std::cout << " " << std::setw( 11 ) << std::setprecision( 6 ) << std::fixed << ( period * 1.0 / delta_t );
+    std::cout << " " << std::setw( 11 ) << std::setprecision( 6 ) << std::fixed << ( period * 1.0 / delta_t2 );
+    std::cout << "  " << decoded << std::endl;
+  }
+
+  return res;
+}
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index 3280c087..c477923f 100755
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -40,151 +40,916 @@
 #include <algorithm>
 #include <cstring>
 #include <limits>
+#if JVET_P0300
+#include <cmath>
+#endif
+
+
+const uint8_t ProbModelTables::m_RenormTable_32[32] =
+{
+  6,  5,  4,  4,
+  3,  3,  3,  3,
+  2,  2,  2,  2,
+  2,  2,  2,  2,
+  1,  1,  1,  1,
+  1,  1,  1,  1,
+  1,  1,  1,  1,
+  1,  1,  1,  1
+};
+
+#if JVET_P0300
+const BinFracBits (&getFracBitsGB())[2*FixedProbModel_Est::m_numGB+4]
+{
+  static bool initDone = false;
+  static BinFracBits x[2*FixedProbModel_Est::m_numGB+4];
+  CHECK( initDone, "Called getFracBitsGB() for a second time. This is unexpected." );
+
+
+  for( int i = 0; i < 2*FixedProbModel_Est::m_numGB + 4; ++i )
+  {
+    if( (i >> 1) == 0 )
+    {
+      x[i].intBits[0] = 0; // never used
+      x[i].intBits[1] = 0; // never used
+    }
+    else
+    {
+      double p = 1.0 / (1 << ( i >> 1 ) );
+      if( i & 1 )
+      {
+        p = 1.0 - p;
+      }
+      x[i].intBits[0] = (uint32_t)(-std::log2( 1.0 -  p ) * 32768.0);
+      x[i].intBits[1] = (uint32_t)(-std::log2( p ) * 32768.0);
+    }
+  }
+  initDone = true;
+  return x;
+}
+
+const BinFracBits (&FixedProbModel_Est::m_fracBitsGB)[2*FixedProbModel_Est::m_numGB+4] = getFracBitsGB();
+
+void FixedProbModel_Est::init( int qp, int initId )
+{
+  int slope = (initId >> 3) - 4;
+  int offset = ((initId & 7) * 18) + 1;
+  int inistate = ((slope   * (qp - 16)) >> 1) + offset;
+  int state_clip = inistate < 1 ? 1 : inistate > 127 ? 127 : inistate;
+
+  int lps_state = state_clip;
+  if( state_clip >= 64 )
+  {
+    lps_state = 128 - state_clip;
+  }
+  int initGB = std::min( JVET_P0300_NUM_GB, 6 - floorLog2( lps_state + (lps_state>>2) ) );
+  m_bestGB = state_clip >= 64 ? initGB : -initGB;
+  m_bestGB = 2 + ( (int)(std::abs( m_bestGB )) << 1 ) + ( m_bestGB >= 0 ? 1 : 0 );
+}
+#endif
+
+const BinFracBits ProbModelTables::m_binFracBits[256] = {
+  { { 0x0005c, 0x48000 } }, { { 0x00116, 0x3b520 } }, { { 0x001d0, 0x356cb } }, { { 0x0028b, 0x318a9 } },
+  { { 0x00346, 0x2ea40 } }, { { 0x00403, 0x2c531 } }, { { 0x004c0, 0x2a658 } }, { { 0x0057e, 0x28beb } },
+  { { 0x0063c, 0x274ce } }, { { 0x006fc, 0x26044 } }, { { 0x007bc, 0x24dc9 } }, { { 0x0087d, 0x23cfc } },
+  { { 0x0093f, 0x22d96 } }, { { 0x00a01, 0x21f60 } }, { { 0x00ac4, 0x2122e } }, { { 0x00b89, 0x205dd } },
+  { { 0x00c4e, 0x1fa51 } }, { { 0x00d13, 0x1ef74 } }, { { 0x00dda, 0x1e531 } }, { { 0x00ea2, 0x1db78 } },
+  { { 0x00f6a, 0x1d23c } }, { { 0x01033, 0x1c970 } }, { { 0x010fd, 0x1c10b } }, { { 0x011c8, 0x1b903 } },
+  { { 0x01294, 0x1b151 } }, { { 0x01360, 0x1a9ee } }, { { 0x0142e, 0x1a2d4 } }, { { 0x014fc, 0x19bfc } },
+  { { 0x015cc, 0x19564 } }, { { 0x0169c, 0x18f06 } }, { { 0x0176d, 0x188de } }, { { 0x0183f, 0x182e8 } },
+  { { 0x01912, 0x17d23 } }, { { 0x019e6, 0x1778a } }, { { 0x01abb, 0x1721c } }, { { 0x01b91, 0x16cd5 } },
+  { { 0x01c68, 0x167b4 } }, { { 0x01d40, 0x162b6 } }, { { 0x01e19, 0x15dda } }, { { 0x01ef3, 0x1591e } },
+  { { 0x01fcd, 0x15480 } }, { { 0x020a9, 0x14fff } }, { { 0x02186, 0x14b99 } }, { { 0x02264, 0x1474e } },
+  { { 0x02343, 0x1431b } }, { { 0x02423, 0x13f01 } }, { { 0x02504, 0x13afd } }, { { 0x025e6, 0x1370f } },
+  { { 0x026ca, 0x13336 } }, { { 0x027ae, 0x12f71 } }, { { 0x02894, 0x12bc0 } }, { { 0x0297a, 0x12821 } },
+  { { 0x02a62, 0x12494 } }, { { 0x02b4b, 0x12118 } }, { { 0x02c35, 0x11dac } }, { { 0x02d20, 0x11a51 } },
+  { { 0x02e0c, 0x11704 } }, { { 0x02efa, 0x113c7 } }, { { 0x02fe9, 0x11098 } }, { { 0x030d9, 0x10d77 } },
+  { { 0x031ca, 0x10a63 } }, { { 0x032bc, 0x1075c } }, { { 0x033b0, 0x10461 } }, { { 0x034a5, 0x10173 } },
+  { { 0x0359b, 0x0fe90 } }, { { 0x03693, 0x0fbb9 } }, { { 0x0378c, 0x0f8ed } }, { { 0x03886, 0x0f62b } },
+  { { 0x03981, 0x0f374 } }, { { 0x03a7e, 0x0f0c7 } }, { { 0x03b7c, 0x0ee23 } }, { { 0x03c7c, 0x0eb89 } },
+  { { 0x03d7d, 0x0e8f9 } }, { { 0x03e7f, 0x0e671 } }, { { 0x03f83, 0x0e3f2 } }, { { 0x04088, 0x0e17c } },
+  { { 0x0418e, 0x0df0e } }, { { 0x04297, 0x0dca8 } }, { { 0x043a0, 0x0da4a } }, { { 0x044ab, 0x0d7f3 } },
+  { { 0x045b8, 0x0d5a5 } }, { { 0x046c6, 0x0d35d } }, { { 0x047d6, 0x0d11c } }, { { 0x048e7, 0x0cee3 } },
+  { { 0x049fa, 0x0ccb0 } }, { { 0x04b0e, 0x0ca84 } }, { { 0x04c24, 0x0c85e } }, { { 0x04d3c, 0x0c63f } },
+  { { 0x04e55, 0x0c426 } }, { { 0x04f71, 0x0c212 } }, { { 0x0508d, 0x0c005 } }, { { 0x051ac, 0x0bdfe } },
+  { { 0x052cc, 0x0bbfc } }, { { 0x053ee, 0x0b9ff } }, { { 0x05512, 0x0b808 } }, { { 0x05638, 0x0b617 } },
+  { { 0x0575f, 0x0b42a } }, { { 0x05888, 0x0b243 } }, { { 0x059b4, 0x0b061 } }, { { 0x05ae1, 0x0ae83 } },
+  { { 0x05c10, 0x0acaa } }, { { 0x05d41, 0x0aad6 } }, { { 0x05e74, 0x0a907 } }, { { 0x05fa9, 0x0a73c } },
+  { { 0x060e0, 0x0a575 } }, { { 0x06219, 0x0a3b3 } }, { { 0x06354, 0x0a1f5 } }, { { 0x06491, 0x0a03b } },
+  { { 0x065d1, 0x09e85 } }, { { 0x06712, 0x09cd4 } }, { { 0x06856, 0x09b26 } }, { { 0x0699c, 0x0997c } },
+  { { 0x06ae4, 0x097d6 } }, { { 0x06c2f, 0x09634 } }, { { 0x06d7c, 0x09495 } }, { { 0x06ecb, 0x092fa } },
+  { { 0x0701d, 0x09162 } }, { { 0x07171, 0x08fce } }, { { 0x072c7, 0x08e3e } }, { { 0x07421, 0x08cb0 } },
+  { { 0x0757c, 0x08b26 } }, { { 0x076da, 0x089a0 } }, { { 0x0783b, 0x0881c } }, { { 0x0799f, 0x0869c } },
+  { { 0x07b05, 0x0851f } }, { { 0x07c6e, 0x083a4 } }, { { 0x07dd9, 0x0822d } }, { { 0x07f48, 0x080b9 } },
+  { { 0x080b9, 0x07f48 } }, { { 0x0822d, 0x07dd9 } }, { { 0x083a4, 0x07c6e } }, { { 0x0851f, 0x07b05 } },
+  { { 0x0869c, 0x0799f } }, { { 0x0881c, 0x0783b } }, { { 0x089a0, 0x076da } }, { { 0x08b26, 0x0757c } },
+  { { 0x08cb0, 0x07421 } }, { { 0x08e3e, 0x072c7 } }, { { 0x08fce, 0x07171 } }, { { 0x09162, 0x0701d } },
+  { { 0x092fa, 0x06ecb } }, { { 0x09495, 0x06d7c } }, { { 0x09634, 0x06c2f } }, { { 0x097d6, 0x06ae4 } },
+  { { 0x0997c, 0x0699c } }, { { 0x09b26, 0x06856 } }, { { 0x09cd4, 0x06712 } }, { { 0x09e85, 0x065d1 } },
+  { { 0x0a03b, 0x06491 } }, { { 0x0a1f5, 0x06354 } }, { { 0x0a3b3, 0x06219 } }, { { 0x0a575, 0x060e0 } },
+  { { 0x0a73c, 0x05fa9 } }, { { 0x0a907, 0x05e74 } }, { { 0x0aad6, 0x05d41 } }, { { 0x0acaa, 0x05c10 } },
+  { { 0x0ae83, 0x05ae1 } }, { { 0x0b061, 0x059b4 } }, { { 0x0b243, 0x05888 } }, { { 0x0b42a, 0x0575f } },
+  { { 0x0b617, 0x05638 } }, { { 0x0b808, 0x05512 } }, { { 0x0b9ff, 0x053ee } }, { { 0x0bbfc, 0x052cc } },
+  { { 0x0bdfe, 0x051ac } }, { { 0x0c005, 0x0508d } }, { { 0x0c212, 0x04f71 } }, { { 0x0c426, 0x04e55 } },
+  { { 0x0c63f, 0x04d3c } }, { { 0x0c85e, 0x04c24 } }, { { 0x0ca84, 0x04b0e } }, { { 0x0ccb0, 0x049fa } },
+  { { 0x0cee3, 0x048e7 } }, { { 0x0d11c, 0x047d6 } }, { { 0x0d35d, 0x046c6 } }, { { 0x0d5a5, 0x045b8 } },
+  { { 0x0d7f3, 0x044ab } }, { { 0x0da4a, 0x043a0 } }, { { 0x0dca8, 0x04297 } }, { { 0x0df0e, 0x0418e } },
+  { { 0x0e17c, 0x04088 } }, { { 0x0e3f2, 0x03f83 } }, { { 0x0e671, 0x03e7f } }, { { 0x0e8f9, 0x03d7d } },
+  { { 0x0eb89, 0x03c7c } }, { { 0x0ee23, 0x03b7c } }, { { 0x0f0c7, 0x03a7e } }, { { 0x0f374, 0x03981 } },
+  { { 0x0f62b, 0x03886 } }, { { 0x0f8ed, 0x0378c } }, { { 0x0fbb9, 0x03693 } }, { { 0x0fe90, 0x0359b } },
+  { { 0x10173, 0x034a5 } }, { { 0x10461, 0x033b0 } }, { { 0x1075c, 0x032bc } }, { { 0x10a63, 0x031ca } },
+  { { 0x10d77, 0x030d9 } }, { { 0x11098, 0x02fe9 } }, { { 0x113c7, 0x02efa } }, { { 0x11704, 0x02e0c } },
+  { { 0x11a51, 0x02d20 } }, { { 0x11dac, 0x02c35 } }, { { 0x12118, 0x02b4b } }, { { 0x12494, 0x02a62 } },
+  { { 0x12821, 0x0297a } }, { { 0x12bc0, 0x02894 } }, { { 0x12f71, 0x027ae } }, { { 0x13336, 0x026ca } },
+  { { 0x1370f, 0x025e6 } }, { { 0x13afd, 0x02504 } }, { { 0x13f01, 0x02423 } }, { { 0x1431b, 0x02343 } },
+  { { 0x1474e, 0x02264 } }, { { 0x14b99, 0x02186 } }, { { 0x14fff, 0x020a9 } }, { { 0x15480, 0x01fcd } },
+  { { 0x1591e, 0x01ef3 } }, { { 0x15dda, 0x01e19 } }, { { 0x162b6, 0x01d40 } }, { { 0x167b4, 0x01c68 } },
+  { { 0x16cd5, 0x01b91 } }, { { 0x1721c, 0x01abb } }, { { 0x1778a, 0x019e6 } }, { { 0x17d23, 0x01912 } },
+  { { 0x182e8, 0x0183f } }, { { 0x188de, 0x0176d } }, { { 0x18f06, 0x0169c } }, { { 0x19564, 0x015cc } },
+  { { 0x19bfc, 0x014fc } }, { { 0x1a2d4, 0x0142e } }, { { 0x1a9ee, 0x01360 } }, { { 0x1b151, 0x01294 } },
+  { { 0x1b903, 0x011c8 } }, { { 0x1c10b, 0x010fd } }, { { 0x1c970, 0x01033 } }, { { 0x1d23c, 0x00f6a } },
+  { { 0x1db78, 0x00ea2 } }, { { 0x1e531, 0x00dda } }, { { 0x1ef74, 0x00d13 } }, { { 0x1fa51, 0x00c4e } },
+  { { 0x205dd, 0x00b89 } }, { { 0x2122e, 0x00ac4 } }, { { 0x21f60, 0x00a01 } }, { { 0x22d96, 0x0093f } },
+  { { 0x23cfc, 0x0087d } }, { { 0x24dc9, 0x007bc } }, { { 0x26044, 0x006fc } }, { { 0x274ce, 0x0063c } },
+  { { 0x28beb, 0x0057e } }, { { 0x2a658, 0x004c0 } }, { { 0x2c531, 0x00403 } }, { { 0x2ea40, 0x00346 } },
+  { { 0x318a9, 0x0028b } }, { { 0x356cb, 0x001d0 } }, { { 0x3b520, 0x00116 } }, { { 0x48000, 0x0005c } },
+};
+void BinProbModel_Std::init( int qp, int initId )
+{
+  int slope = (initId >> 3) - 4;
+  int offset = ((initId & 7) * 18) + 1;
+  int inistate = ((slope   * (qp - 16)) >> 1) + offset;
+  int state_clip = inistate < 1 ? 1 : inistate > 127 ? 127 : inistate;
+  const int p1 = (state_clip << 8);
+  m_state[0]   = p1 & MASK_0;
+  m_state[1]   = p1 & MASK_1;
+}
+
+
+
+
+CtxSet::CtxSet( std::initializer_list<CtxSet> ctxSets )
+{
+  uint16_t  minOffset = std::numeric_limits<uint16_t>::max();
+  uint16_t  maxOffset = 0;
+  for( auto iter = ctxSets.begin(); iter != ctxSets.end(); iter++ )
+  {
+    minOffset = std::min<uint16_t>( minOffset, (*iter).Offset              );
+    maxOffset = std::max<uint16_t>( maxOffset, (*iter).Offset+(*iter).Size );
+  }
+  Offset  = minOffset;
+  Size    = maxOffset - minOffset;
+}
+
+
+
+
+
+const std::vector<uint8_t>& ContextSetCfg::getInitTable( unsigned initId )
+{
+  CHECK( initId >= (unsigned)sm_InitTables.size(),
+         "Invalid initId (" << initId << "), only " << sm_InitTables.size() << " tables defined." );
+  return sm_InitTables[initId];
+}
+
+
+CtxSet ContextSetCfg::addCtxSet( std::initializer_list<std::initializer_list<uint8_t>> initSet2d )
+{
+  const std::size_t startIdx  = sm_InitTables[0].size();
+  const std::size_t numValues = ( *initSet2d.begin() ).size();
+        std::size_t setId     = 0;
+  for( auto setIter = initSet2d.begin(); setIter != initSet2d.end() && setId < sm_InitTables.size(); setIter++, setId++ )
+  {
+    const std::initializer_list<uint8_t>& initSet   = *setIter;
+    std::vector<uint8_t>&           initTable = sm_InitTables[setId];
+    CHECK( initSet.size() != numValues,
+           "Number of init values do not match for all sets (" << initSet.size() << " != " << numValues << ")." );
+    initTable.resize( startIdx + numValues );
+    std::size_t elemId = startIdx;
+    for( auto elemIter = ( *setIter ).begin(); elemIter != ( *setIter ).end(); elemIter++, elemId++ )
+    {
+      initTable[elemId] = *elemIter;
+    }
+  }
+  return CtxSet( (uint16_t)startIdx, (uint16_t)numValues );
+}
+
+
+#define CNU 35
+std::vector<std::vector<uint8_t>> ContextSetCfg::sm_InitTables(NUMBER_OF_SLICE_TYPES + 1);
+
+// clang-format off
+
+
+#if JVET_P0300
+
+// inits from LLC, LQP, CTC, and HQP bitstreams; 4 * VTM + 1 * GB3 (INIT_4ALL_VTM_1ALL_GB3)
+
+const CtxSet ContextSetCfg::SplitFlag = ContextSetCfg::addCtxSet
+({
+  {  18,  27,  30,  11,  28,  30,  12,  29,  31, },
+  {  26,  35,  53,  19,  21,  30,   6,  22,  31, },
+  {  19,  28,  38,  12,  21,  30,  20,  30,  31, },
+  {   9,  12,   8,   4,  12,   9,   4,   8,   8, },
+});
+
+const CtxSet ContextSetCfg::SplitQtFlag = ContextSetCfg::addCtxSet
+({
+  {  12,  36,  38,  33,  27,  29, },
+  {  13,  21,  23,  18,  19,  21, },
+  {  12,   6,  15,  25,  27,  29, },
+  {   0,   5,   8,  12,  12,  12, },
+});
+
+const CtxSet ContextSetCfg::SplitHvFlag = ContextSetCfg::addCtxSet
+({
+  {  36,  34,  44,  35,  36, },
+  {  36,  35,  37,  27,  37, },
+  {  36,  35,  44,  35,  44, },
+  {   9,   5,   8,   5,   5, },
+});
+
+const CtxSet ContextSetCfg::Split12Flag = ContextSetCfg::addCtxSet
+({
+  {  35,  29,  28,  29, },
+  {  43,  37,  21,  37, },
+  {  51,  45,  36,  45, },
+  {   8,   9,   9,  12, },
+});
+
+const CtxSet ContextSetCfg::ModeConsFlag = ContextSetCfg::addCtxSet
+({
+  {  25,  28, },
+  {  25,  12, },
+  { CNU, CNU, },
+  {   1,   0, },
+});
+
+const CtxSet ContextSetCfg::SkipFlag = ContextSetCfg::addCtxSet
+({
+  {  49,  59,  53, },
+  {  56,  58,  52, },
+  {  32,  34,  37, },
+  {   5,   4,   4, },
+});
+
+const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet
+({
+  {  28, },
+  {  14, },
+  {  26, },
+  {   4, },
+});
+
+const CtxSet ContextSetCfg::RegularMergeFlag = ContextSetCfg::addCtxSet
+({
+  {  39,  15, },
+  {  38,  14, },
+  { CNU, CNU, },
+  {   5,   4, },
+});
+
+const CtxSet ContextSetCfg::MergeIdx = ContextSetCfg::addCtxSet
+({
+  {  19, },
+  {  35, },
+  {  35, },
+  {   1, },
+});
+
+const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet
+({
+  {  19, },
+  {  19, },
+  { CNU, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
+({
+  {  43, },
+  {  43, },
+  { CNU, },
+  {   9, },
+});
+
+const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
+({
+  {  59, },
+  {  60, },
+  { CNU, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::PredMode = ContextSetCfg::addCtxSet
+({
+  {  40,  35, },
+  {  40,  35, },
+  { CNU, CNU, },
+  {   4,   1, },
+});
+
+const CtxSet ContextSetCfg::MultiRefLineIdx = ContextSetCfg::addCtxSet
+({
+  {  25,  51, },
+  {  25,  43, },
+  {  25,  60, },
+  {   6,   8, },
+});
+
+const CtxSet ContextSetCfg::IntraLumaMpmFlag = ContextSetCfg::addCtxSet
+({
+  {  44, },
+  {  44, },
+  {  52, },
+  {   5, },
+});
+
+const CtxSet ContextSetCfg::IntraLumaPlanarFlag = ContextSetCfg::addCtxSet
+({
+  {  13,  20, },
+  {  12,  20, },
+  {  13,  20, },
+  {   1,   1, },
+});
+
+const CtxSet ContextSetCfg::CclmModeFlag = ContextSetCfg::addCtxSet
+({
+  {  19, },
+  {  34, },
+  {  51, },
+  {   1, },
+});
+
+const CtxSet ContextSetCfg::CclmModeIdx = ContextSetCfg::addCtxSet
+({
+  {  27, },
+  {  27, },
+  {  19, },
+  {   5, },
+});
+
+const CtxSet ContextSetCfg::IntraChromaPredMode = ContextSetCfg::addCtxSet
+({
+  {  10, },
+  {  18, },
+  {  19, },
+  {   4, },
+});
+
+const CtxSet ContextSetCfg::MipFlag = ContextSetCfg::addCtxSet
+({
+  {  41,  42,  43,  33, },
+  {  41,  42,  43,  26, },
+  {  33,  34,  35,  25, },
+  {   8,  10,   9,   6, },
+});
+
+const CtxSet ContextSetCfg::DeltaQP = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { DWS, DWS, },
+});
+
+const CtxSet ContextSetCfg::InterDir = ContextSetCfg::addCtxSet
+({
+  {  21,  19,  12,  18,  10,  33, },
+  {   7,   6,   5,   4,   4,  33, },
+  { CNU, CNU, CNU, CNU, CNU, CNU, },
+  {   0,   0,   0,   0,   0,   0, },
+});
+
+const CtxSet ContextSetCfg::RefPic = ContextSetCfg::addCtxSet
+({
+  {  35,  35, },
+  {  34,  35, },
+  { CNU, CNU, },
+  {   0,   4, },
+});
+
+const CtxSet ContextSetCfg::SubblockMergeFlag = ContextSetCfg::addCtxSet
+({
+  {  33,  51,  52, },
+  {  48,  57,  58, },
+  { CNU, CNU, CNU, },
+  {   0,   4,   4, },
+});
+
+const CtxSet ContextSetCfg::AffineFlag = ContextSetCfg::addCtxSet
+({
+  {  19,   6,   6, },
+  {  12,   5,   6, },
+  { CNU, CNU, CNU, },
+  {   0,   0,   0, },
+});
+
+const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet
+({
+  {  28, },
+  {  35, },
+  { CNU, },
+  {   1, },
+});
+
+const CtxSet ContextSetCfg::AffMergeIdx = ContextSetCfg::addCtxSet
+({
+  {   4, },
+  {   5, },
+  { CNU, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::GBiIdx = ContextSetCfg::addCtxSet
+({
+  {  12, },
+  {   4, },
+  { CNU, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::Mvd = ContextSetCfg::addCtxSet
+({
+  {  37,  37, },
+  {  37,  43, },
+  {  21,  38, },
+  {   9,   4, },
+});
+
+const CtxSet ContextSetCfg::BDPCMMode = ContextSetCfg::addCtxSet
+({
+  {  12,  36, },
+  {  33,  36, },
+  {  35,  35, },
+  {   4,   0, },
+});
+
+const CtxSet ContextSetCfg::QtRootCbf = ContextSetCfg::addCtxSet
+({
+  {  19, },
+  {   5, },
+  {  12, },
+  {   4, },
+});
+
+const CtxSet ContextSetCfg::QtCbf[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  22,  13,  20,  14, },
+    {  23,   5,  13,   7, },
+    {   7,  11,  20,  29, },
+    {   4,   1,   8,   8, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   3, CNU, },
+    {   3, CNU, },
+    {  12, CNU, },
+    {   1, DWS, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   9,  22, CNU, },
+    {  25,  21, CNU, },
+    {  26,  21, CNU, },
+    {   1,   1, DWS, },
+  }),
+};
+
+const CtxSet ContextSetCfg::SigCoeffGroup[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  18,  30, },
+    {  10,  15, },
+    {  11,  31, },
+    {   8,   5, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  16,  30, },
+    {   2,  22, },
+    {   2,  15, },
+    {   1,   8, },
+  }),
+};
+
+const CtxSet ContextSetCfg::SigFlag[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  17,  34,  34,  28,   8,  34,  50,  29,  48,  58,  43,  37, },
+    {  17,  34,  27,  29,  25,  34,  35,  37,  33,  43,  36,  30, },
+    {  17,  34,  35,  29,  25,  35,  28,  30,  19,  37,  37,  38, },
+    {  12,   9,   9,  10,   9,   9,   9,  10,   8,   8,   8,   9, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   0,  42,  35,  37,  40,  51,  44,  45, },
+    {  17,  34,  35,  29,  33,  59,  60,  45, },
+    {  25,  27,  36,  37,  41,  60,  53,  46, },
+    {   9,   9,   9,  12,   4,   5,   8,   9, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  19,  45,  53,  46,  42,  61,  61,  39,  35,  39,  39,  39, },
+    {  19,  45,  38,  31,  27,  54,  54,  39,   6,  39,  39,  39, },
+    {  11,  45,  46,  47,  20,  39,  39,  39,  29,  39,  39,  39, },
+    {   9,  13,   8,   8,   8,   8,   8,   5,   8,   0,   0,   0, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  26,  45,  38,  31,  50,  39,  39,  39, },
+    {  35,  45,  38,  55,  37,  39,  39,  39, },
+    {  19,  53,  38,  39,  45,  39,  39,  39, },
+    {   8,  12,   8,   8,   4,   0,   0,   0, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   5,  55,  39,  39,  43,  39,  39,  39,   8,  39,  39,  39, },
+    {  12,  39,  47,  39,  12,  39,  39,  39,  56,  39,  39,  39, },
+    {   4,  39,  39,  39,  12,  39,  39,  39,  24,  39,  39,  39, },
+    {   8,   8,   8,   8,   8,   0,   4,   4,   0,   0,   0,   0, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  11,  38,  46,  39,  33,  39,  39,  39, },
+    {  27,  38,  55,  39,  19,  39,  39,  39, },
+    {  19,  55,  39,  39,  19,  39,  39,  39, },
+    {   4,   8,   8,   8,   0,   0,   0,   0, },
+  }),
+};
+
+const CtxSet ContextSetCfg::ParFlag[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  26,  40,  25,  26,  26,  34,  25,  33,  26,  34,  35,  25,  34,  42,  42,  35,  26,  27,  35,  42,  35, },
+    {  18,  25,  17,  18,  34,  27,  17,  18,  26,  42,  35,  25,  34,  42,  42,  35,  26,  27,  42,  35,  35, },
+    {  26,  25,  18,  26,  34,  27,  25,  26,  34,  34,  35,  33,  19,  27,  35,  35,  34,  42,  20,  43,  35, },
+    {   8,   9,  12,  12,  13,  13,  10,  12,  13,  13,  13,  13,  13,  13,  13,  13,  10,  13,  13,  13,  13, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  26,  25,  26,  34,  34,  35,  33,  34,  35,  42,  35, },
+    {  25,  25,  26,  26,  34,  35,  33,  42,  50,  35,  35, },
+    {  26,  25,  26,  42,  27,  35,  26,  42,  35,  35,  35, },
+    {   8,  12,  12,  13,  13,  13,  13,  12,  13,  12,  13, },
+  }),
+};
+
+const CtxSet ContextSetCfg::GtxFlag[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  18,  16,  16,   0,  25,  10,  16,   0,  25,  33,  19,  16,  25,  33,  34,  28,  25,  26,  19,  20,  29, },
+    {  17,  16,  16,   8,  25,  10,  16,   8,  25,  33,  19,  16,  25,  18,  26,  35,  25,  18,  19,  27,  21, },
+    {  10,   8,   8,  25,  25,  19,   0,  25,  25,  10,  35,   8,  33,  26,  19,  13,  33,  19,  20,  28,  29, },
+    {   1,   5,   9,   9,   9,   6,   5,   9,   9,   9,   6,   9,   9,   9,   9,   9,   5,   8,   8,   8,   9, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  18,   8,  25,  33,  26,  35,  25,  33,  34,  28,  29, },
+    {  16,  24,  40,  25,  26,  43,  16,  33,  34,  43,  52, },
+    {  26,  16,  25,  18,  18,  35,  25,  26,  35,  28,  37, },
+    {   1,   8,   9,   9,   8,   6,   5,   8,   8,   5,   8, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   0,   8,  26,  34,  35,  28,   8,  34,  35,  36,  29,  33,  34,  28,  36,  30,  34,  36,  44,  45,  38, },
+    {   0,   0,  26,  19,  35,  28,  17,  34,  35,  36,  29,  33,  27,  35,  29,  37,  34,  28,  44,  37,  38, },
+    {   9,   0,  26,  35,  36,  29,  25,  27,  35,  28,  29,  34,  35,  36,  29,  30,  28,  29,  45,  30,  23, },
+    {   9,   8,  10,  13,  13,  10,   9,  10,  12,  12,  12,   8,   9,   9,  10,  12,   8,   9,   9,  10,  13, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  17,  33,  34,  35,  36,  29,  49,  44,  45,  30,  38, },
+    {  16,  25,  34,  35,  36,  29,  42,  44,  37,  45,  31, },
+    {  25,  33,  27,  36,  28,  37,  36,  29,  53,  38,  38, },
+    {   5,   9,  10,  12,  12,   9,   5,   8,   8,   8,   8, },
+  }),
+};
+
+const CtxSet ContextSetCfg::LastX[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  14,  14,  20,   7,   7,  12,   7,   7,   6,   5,  29,   7,   7,  14,  20,  35,  15,  28,  28,  28, },
+    {   6,  13,  20,   6,   6,  12,  14,   7,   6,   5,  22,   7,   6,   6,  13,  36,  22,   6,  28,  27, },
+    {  13,  13,   5,   6,   7,  12,  14,  22,  22,  20,  21,  22,  37,  21,  12,  36,  29,  29,  50,  28, },
+    {   5,   5,   4,   5,   4,   4,   5,   4,   1,   0,   4,   1,   0,   0,   0,   1,   1,   0,   0,   0, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {   5,  30,  37, },
+    {  13,   5,   3, },
+    {  13,  13,  12, },
+    {   1,   1,   2, },
+  }),
+};
+
+const CtxSet ContextSetCfg::LastY[] =
+{
+  ContextSetCfg::addCtxSet
+  ({
+    {  21,  21,  28,   6,   6,  20,  14,   6,  13,  13,  14,   7,   6,  20,  28,  28,  15,   6,  13,  34, },
+    {  13,  13,  20,   6,   6,  12,   6,  14,   6,  12,  14,   7,   6,  13,  28,  35,   7,   6,   5,  50, },
+    {  13,  13,  12,   6,   6,  12,  14,  14,  13,  28,  14,  14,   6,  12,  12,  36,  29,  29,  28,  49, },
+    {   5,   5,   8,   5,   5,   4,   5,   4,   1,   0,   5,   5,   1,   0,   0,   1,   4,   0,   0,   0, },
+  }),
+  ContextSetCfg::addCtxSet
+  ({
+    {  12,  13,  28, },
+    {   4,   5,   3, },
+    {  20,   5,   3, },
+    {   5,   5,   5, },
+  }),
+};
+
+const CtxSet ContextSetCfg::MVPIdx = ContextSetCfg::addCtxSet
+({
+  {  34, },
+  {  34, },
+  {  27, },
+  {  13, },
+});
+
+const CtxSet ContextSetCfg::SmvdFlag = ContextSetCfg::addCtxSet
+({
+  {  36, },
+  {  35, },
+  { CNU, },
+  {   5, },
+});
+
+const CtxSet ContextSetCfg::SaoMergeFlag = ContextSetCfg::addCtxSet
+({
+  {  10, },
+  {  60, },
+  {  60, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::SaoTypeIdx = ContextSetCfg::addCtxSet
+({
+  {  10, },
+  {   4, },
+  {   4, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::TransquantBypassFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
+
+const CtxSet ContextSetCfg::LFNSTIdx = ContextSetCfg::addCtxSet
+({
+  {  52,  37,  34, },
+  {  37,  45,  19, },
+  { CNU,  37,  34, },
+  {   9,   9,   6, },
+});
+
+const CtxSet ContextSetCfg::PLTFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
+
+const CtxSet ContextSetCfg::RotationFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
+
+const CtxSet ContextSetCfg::RunTypeFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
+
+const CtxSet ContextSetCfg::IdxRunModel = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, CNU, CNU, },
+  { CNU, CNU, CNU, CNU, CNU, },
+  { CNU, CNU, CNU, CNU, CNU, },
+  { DWS, DWS, DWS, DWS, DWS, },
+});
+
+const CtxSet ContextSetCfg::CopyRunModel = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { DWS, DWS, DWS, },
+});
+
+const CtxSet ContextSetCfg::RdpcmFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { DWS, DWS, },
+});
+
+const CtxSet ContextSetCfg::RdpcmDir = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { CNU, CNU, },
+  { DWS, DWS, },
+});
 
+const CtxSet ContextSetCfg::MTSIndex = ContextSetCfg::addCtxSet
+({
+  {  37, CNU, CNU, CNU, CNU, CNU,   4,  25,  27,  32, CNU,   3, },
+  {  45, CNU, CNU, CNU, CNU, CNU,  25,  33,  27,  32, CNU,  16, },
+  {  21, CNU, CNU, CNU, CNU, CNU,  11,  32,  35,  32, CNU,  10, },
+  {   8, DWS, DWS, DWS, DWS, DWS,   0,   0,   9,   0, DWS,   0, },
+});
 
-const uint8_t ProbModelTables::m_RenormTable_32[32] =
-{
-  6,  5,  4,  4,
-  3,  3,  3,  3,
-  2,  2,  2,  2,
-  2,  2,  2,  2,
-  1,  1,  1,  1,
-  1,  1,  1,  1,
-  1,  1,  1,  1,
-  1,  1,  1,  1
-};
+const CtxSet ContextSetCfg::ISPMode = ContextSetCfg::addCtxSet
+({
+  {  33,  36, },
+  {  33,  36, },
+  {  33,  36, },
+  {   8,   1, },
+});
 
-const BinFracBits ProbModelTables::m_binFracBits[256] = {
-  { { 0x0005c, 0x48000 } }, { { 0x00116, 0x3b520 } }, { { 0x001d0, 0x356cb } }, { { 0x0028b, 0x318a9 } },
-  { { 0x00346, 0x2ea40 } }, { { 0x00403, 0x2c531 } }, { { 0x004c0, 0x2a658 } }, { { 0x0057e, 0x28beb } },
-  { { 0x0063c, 0x274ce } }, { { 0x006fc, 0x26044 } }, { { 0x007bc, 0x24dc9 } }, { { 0x0087d, 0x23cfc } },
-  { { 0x0093f, 0x22d96 } }, { { 0x00a01, 0x21f60 } }, { { 0x00ac4, 0x2122e } }, { { 0x00b89, 0x205dd } },
-  { { 0x00c4e, 0x1fa51 } }, { { 0x00d13, 0x1ef74 } }, { { 0x00dda, 0x1e531 } }, { { 0x00ea2, 0x1db78 } },
-  { { 0x00f6a, 0x1d23c } }, { { 0x01033, 0x1c970 } }, { { 0x010fd, 0x1c10b } }, { { 0x011c8, 0x1b903 } },
-  { { 0x01294, 0x1b151 } }, { { 0x01360, 0x1a9ee } }, { { 0x0142e, 0x1a2d4 } }, { { 0x014fc, 0x19bfc } },
-  { { 0x015cc, 0x19564 } }, { { 0x0169c, 0x18f06 } }, { { 0x0176d, 0x188de } }, { { 0x0183f, 0x182e8 } },
-  { { 0x01912, 0x17d23 } }, { { 0x019e6, 0x1778a } }, { { 0x01abb, 0x1721c } }, { { 0x01b91, 0x16cd5 } },
-  { { 0x01c68, 0x167b4 } }, { { 0x01d40, 0x162b6 } }, { { 0x01e19, 0x15dda } }, { { 0x01ef3, 0x1591e } },
-  { { 0x01fcd, 0x15480 } }, { { 0x020a9, 0x14fff } }, { { 0x02186, 0x14b99 } }, { { 0x02264, 0x1474e } },
-  { { 0x02343, 0x1431b } }, { { 0x02423, 0x13f01 } }, { { 0x02504, 0x13afd } }, { { 0x025e6, 0x1370f } },
-  { { 0x026ca, 0x13336 } }, { { 0x027ae, 0x12f71 } }, { { 0x02894, 0x12bc0 } }, { { 0x0297a, 0x12821 } },
-  { { 0x02a62, 0x12494 } }, { { 0x02b4b, 0x12118 } }, { { 0x02c35, 0x11dac } }, { { 0x02d20, 0x11a51 } },
-  { { 0x02e0c, 0x11704 } }, { { 0x02efa, 0x113c7 } }, { { 0x02fe9, 0x11098 } }, { { 0x030d9, 0x10d77 } },
-  { { 0x031ca, 0x10a63 } }, { { 0x032bc, 0x1075c } }, { { 0x033b0, 0x10461 } }, { { 0x034a5, 0x10173 } },
-  { { 0x0359b, 0x0fe90 } }, { { 0x03693, 0x0fbb9 } }, { { 0x0378c, 0x0f8ed } }, { { 0x03886, 0x0f62b } },
-  { { 0x03981, 0x0f374 } }, { { 0x03a7e, 0x0f0c7 } }, { { 0x03b7c, 0x0ee23 } }, { { 0x03c7c, 0x0eb89 } },
-  { { 0x03d7d, 0x0e8f9 } }, { { 0x03e7f, 0x0e671 } }, { { 0x03f83, 0x0e3f2 } }, { { 0x04088, 0x0e17c } },
-  { { 0x0418e, 0x0df0e } }, { { 0x04297, 0x0dca8 } }, { { 0x043a0, 0x0da4a } }, { { 0x044ab, 0x0d7f3 } },
-  { { 0x045b8, 0x0d5a5 } }, { { 0x046c6, 0x0d35d } }, { { 0x047d6, 0x0d11c } }, { { 0x048e7, 0x0cee3 } },
-  { { 0x049fa, 0x0ccb0 } }, { { 0x04b0e, 0x0ca84 } }, { { 0x04c24, 0x0c85e } }, { { 0x04d3c, 0x0c63f } },
-  { { 0x04e55, 0x0c426 } }, { { 0x04f71, 0x0c212 } }, { { 0x0508d, 0x0c005 } }, { { 0x051ac, 0x0bdfe } },
-  { { 0x052cc, 0x0bbfc } }, { { 0x053ee, 0x0b9ff } }, { { 0x05512, 0x0b808 } }, { { 0x05638, 0x0b617 } },
-  { { 0x0575f, 0x0b42a } }, { { 0x05888, 0x0b243 } }, { { 0x059b4, 0x0b061 } }, { { 0x05ae1, 0x0ae83 } },
-  { { 0x05c10, 0x0acaa } }, { { 0x05d41, 0x0aad6 } }, { { 0x05e74, 0x0a907 } }, { { 0x05fa9, 0x0a73c } },
-  { { 0x060e0, 0x0a575 } }, { { 0x06219, 0x0a3b3 } }, { { 0x06354, 0x0a1f5 } }, { { 0x06491, 0x0a03b } },
-  { { 0x065d1, 0x09e85 } }, { { 0x06712, 0x09cd4 } }, { { 0x06856, 0x09b26 } }, { { 0x0699c, 0x0997c } },
-  { { 0x06ae4, 0x097d6 } }, { { 0x06c2f, 0x09634 } }, { { 0x06d7c, 0x09495 } }, { { 0x06ecb, 0x092fa } },
-  { { 0x0701d, 0x09162 } }, { { 0x07171, 0x08fce } }, { { 0x072c7, 0x08e3e } }, { { 0x07421, 0x08cb0 } },
-  { { 0x0757c, 0x08b26 } }, { { 0x076da, 0x089a0 } }, { { 0x0783b, 0x0881c } }, { { 0x0799f, 0x0869c } },
-  { { 0x07b05, 0x0851f } }, { { 0x07c6e, 0x083a4 } }, { { 0x07dd9, 0x0822d } }, { { 0x07f48, 0x080b9 } },
-  { { 0x080b9, 0x07f48 } }, { { 0x0822d, 0x07dd9 } }, { { 0x083a4, 0x07c6e } }, { { 0x0851f, 0x07b05 } },
-  { { 0x0869c, 0x0799f } }, { { 0x0881c, 0x0783b } }, { { 0x089a0, 0x076da } }, { { 0x08b26, 0x0757c } },
-  { { 0x08cb0, 0x07421 } }, { { 0x08e3e, 0x072c7 } }, { { 0x08fce, 0x07171 } }, { { 0x09162, 0x0701d } },
-  { { 0x092fa, 0x06ecb } }, { { 0x09495, 0x06d7c } }, { { 0x09634, 0x06c2f } }, { { 0x097d6, 0x06ae4 } },
-  { { 0x0997c, 0x0699c } }, { { 0x09b26, 0x06856 } }, { { 0x09cd4, 0x06712 } }, { { 0x09e85, 0x065d1 } },
-  { { 0x0a03b, 0x06491 } }, { { 0x0a1f5, 0x06354 } }, { { 0x0a3b3, 0x06219 } }, { { 0x0a575, 0x060e0 } },
-  { { 0x0a73c, 0x05fa9 } }, { { 0x0a907, 0x05e74 } }, { { 0x0aad6, 0x05d41 } }, { { 0x0acaa, 0x05c10 } },
-  { { 0x0ae83, 0x05ae1 } }, { { 0x0b061, 0x059b4 } }, { { 0x0b243, 0x05888 } }, { { 0x0b42a, 0x0575f } },
-  { { 0x0b617, 0x05638 } }, { { 0x0b808, 0x05512 } }, { { 0x0b9ff, 0x053ee } }, { { 0x0bbfc, 0x052cc } },
-  { { 0x0bdfe, 0x051ac } }, { { 0x0c005, 0x0508d } }, { { 0x0c212, 0x04f71 } }, { { 0x0c426, 0x04e55 } },
-  { { 0x0c63f, 0x04d3c } }, { { 0x0c85e, 0x04c24 } }, { { 0x0ca84, 0x04b0e } }, { { 0x0ccb0, 0x049fa } },
-  { { 0x0cee3, 0x048e7 } }, { { 0x0d11c, 0x047d6 } }, { { 0x0d35d, 0x046c6 } }, { { 0x0d5a5, 0x045b8 } },
-  { { 0x0d7f3, 0x044ab } }, { { 0x0da4a, 0x043a0 } }, { { 0x0dca8, 0x04297 } }, { { 0x0df0e, 0x0418e } },
-  { { 0x0e17c, 0x04088 } }, { { 0x0e3f2, 0x03f83 } }, { { 0x0e671, 0x03e7f } }, { { 0x0e8f9, 0x03d7d } },
-  { { 0x0eb89, 0x03c7c } }, { { 0x0ee23, 0x03b7c } }, { { 0x0f0c7, 0x03a7e } }, { { 0x0f374, 0x03981 } },
-  { { 0x0f62b, 0x03886 } }, { { 0x0f8ed, 0x0378c } }, { { 0x0fbb9, 0x03693 } }, { { 0x0fe90, 0x0359b } },
-  { { 0x10173, 0x034a5 } }, { { 0x10461, 0x033b0 } }, { { 0x1075c, 0x032bc } }, { { 0x10a63, 0x031ca } },
-  { { 0x10d77, 0x030d9 } }, { { 0x11098, 0x02fe9 } }, { { 0x113c7, 0x02efa } }, { { 0x11704, 0x02e0c } },
-  { { 0x11a51, 0x02d20 } }, { { 0x11dac, 0x02c35 } }, { { 0x12118, 0x02b4b } }, { { 0x12494, 0x02a62 } },
-  { { 0x12821, 0x0297a } }, { { 0x12bc0, 0x02894 } }, { { 0x12f71, 0x027ae } }, { { 0x13336, 0x026ca } },
-  { { 0x1370f, 0x025e6 } }, { { 0x13afd, 0x02504 } }, { { 0x13f01, 0x02423 } }, { { 0x1431b, 0x02343 } },
-  { { 0x1474e, 0x02264 } }, { { 0x14b99, 0x02186 } }, { { 0x14fff, 0x020a9 } }, { { 0x15480, 0x01fcd } },
-  { { 0x1591e, 0x01ef3 } }, { { 0x15dda, 0x01e19 } }, { { 0x162b6, 0x01d40 } }, { { 0x167b4, 0x01c68 } },
-  { { 0x16cd5, 0x01b91 } }, { { 0x1721c, 0x01abb } }, { { 0x1778a, 0x019e6 } }, { { 0x17d23, 0x01912 } },
-  { { 0x182e8, 0x0183f } }, { { 0x188de, 0x0176d } }, { { 0x18f06, 0x0169c } }, { { 0x19564, 0x015cc } },
-  { { 0x19bfc, 0x014fc } }, { { 0x1a2d4, 0x0142e } }, { { 0x1a9ee, 0x01360 } }, { { 0x1b151, 0x01294 } },
-  { { 0x1b903, 0x011c8 } }, { { 0x1c10b, 0x010fd } }, { { 0x1c970, 0x01033 } }, { { 0x1d23c, 0x00f6a } },
-  { { 0x1db78, 0x00ea2 } }, { { 0x1e531, 0x00dda } }, { { 0x1ef74, 0x00d13 } }, { { 0x1fa51, 0x00c4e } },
-  { { 0x205dd, 0x00b89 } }, { { 0x2122e, 0x00ac4 } }, { { 0x21f60, 0x00a01 } }, { { 0x22d96, 0x0093f } },
-  { { 0x23cfc, 0x0087d } }, { { 0x24dc9, 0x007bc } }, { { 0x26044, 0x006fc } }, { { 0x274ce, 0x0063c } },
-  { { 0x28beb, 0x0057e } }, { { 0x2a658, 0x004c0 } }, { { 0x2c531, 0x00403 } }, { { 0x2ea40, 0x00346 } },
-  { { 0x318a9, 0x0028b } }, { { 0x356cb, 0x001d0 } }, { { 0x3b520, 0x00116 } }, { { 0x48000, 0x0005c } },
-};
-void BinProbModel_Std::init( int qp, int initId )
-{
-  int slope = (initId >> 3) - 4;
-  int offset = ((initId & 7) * 18) + 1;
-  int inistate = ((slope   * (qp - 16)) >> 1) + offset;
-  int state_clip = inistate < 1 ? 1 : inistate > 127 ? 127 : inistate;
-  const int p1 = (state_clip << 8);
-  m_state[0]   = p1 & MASK_0;
-  m_state[1]   = p1 & MASK_1;
-}
+const CtxSet ContextSetCfg::SbtFlag = ContextSetCfg::addCtxSet
+({
+  {  41,  49, },
+  {  41,  57, },
+  { CNU, CNU, },
+  {   1,   5, },
+});
 
+const CtxSet ContextSetCfg::SbtQuadFlag = ContextSetCfg::addCtxSet
+({
+  {  42, },
+  {  42, },
+  { CNU, },
+  {   9, },
+});
 
+const CtxSet ContextSetCfg::SbtHorFlag = ContextSetCfg::addCtxSet
+({
+  {  35,  51,  20, },
+  {  20,  43,  12, },
+  { CNU, CNU, CNU, },
+  {   5,   4,   0, },
+});
 
+const CtxSet ContextSetCfg::SbtPosFlag = ContextSetCfg::addCtxSet
+({
+  {  35, },
+  {  28, },
+  { CNU, },
+  {  13, },
+});
 
-CtxSet::CtxSet( std::initializer_list<CtxSet> ctxSets )
-{
-  uint16_t  minOffset = std::numeric_limits<uint16_t>::max();
-  uint16_t  maxOffset = 0;
-  for( auto iter = ctxSets.begin(); iter != ctxSets.end(); iter++ )
-  {
-    minOffset = std::min<uint16_t>( minOffset, (*iter).Offset              );
-    maxOffset = std::max<uint16_t>( maxOffset, (*iter).Offset+(*iter).Size );
-  }
-  Offset  = minOffset;
-  Size    = maxOffset - minOffset;
-}
+const CtxSet ContextSetCfg::CrossCompPred = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
+  { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
+  { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
+  { DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, },
+});
 
+const CtxSet ContextSetCfg::ChromaQpAdjFlag = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
 
+const CtxSet ContextSetCfg::ChromaQpAdjIdc = ContextSetCfg::addCtxSet
+({
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
+});
 
+const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet
+({
+  {  53,  35,  58,  60,  46, },
+  {  59,  56,  58,  60,  60, },
+  { CNU,  42, CNU, CNU, CNU, },
+  {   0,   0,   0,   0,   4, },
+});
 
+const CtxSet ContextSetCfg::ctbAlfFlag = ContextSetCfg::addCtxSet
+({
+  {  33,  52,  46,  25,  61,  54,  25,  61,  54, },
+  {   6,  38,  46,  19,  61,  54,  12,  46,  47, },
+  {  62,  63,  55,  62,  47,  39,  46,  39,  39, },
+  {   0,   0,   0,   4,   0,   0,   4,   0,   0, },
+});
 
-const std::vector<uint8_t>& ContextSetCfg::getInitTable( unsigned initId )
-{
-  CHECK( initId >= (unsigned)sm_InitTables.size(),
-         "Invalid initId (" << initId << "), only " << sm_InitTables.size() << " tables defined." );
-  return sm_InitTables[initId];
-}
+const CtxSet ContextSetCfg::ctbAlfAlternative = ContextSetCfg::addCtxSet
+({
+  {  35,  13, },
+  {  21,  13, },
+  {  21,  21, },
+  {   0,   0, },
+});
 
+const CtxSet ContextSetCfg::AlfUseTemporalFilt = ContextSetCfg::addCtxSet
+({
+  {  46, },
+  {  46, },
+  {  46, },
+  {   0, },
+});
 
-CtxSet ContextSetCfg::addCtxSet( std::initializer_list<std::initializer_list<uint8_t>> initSet2d )
-{
-  const std::size_t startIdx  = sm_InitTables[0].size();
-  const std::size_t numValues = ( *initSet2d.begin() ).size();
-        std::size_t setId     = 0;
-  for( auto setIter = initSet2d.begin(); setIter != initSet2d.end() && setId < sm_InitTables.size(); setIter++, setId++ )
-  {
-    const std::initializer_list<uint8_t>& initSet   = *setIter;
-    std::vector<uint8_t>&           initTable = sm_InitTables[setId];
-    CHECK( initSet.size() != numValues,
-           "Number of init values do not match for all sets (" << initSet.size() << " != " << numValues << ")." );
-    initTable.resize( startIdx + numValues );
-    std::size_t elemId = startIdx;
-    for( auto elemIter = ( *setIter ).begin(); elemIter != ( *setIter ).end(); elemIter++, elemId++ )
-    {
-      initTable[elemId] = *elemIter;
-    }
-  }
-  return CtxSet( (uint16_t)startIdx, (uint16_t)numValues );
-}
+const CtxSet ContextSetCfg::MHIntraFlag = ContextSetCfg::addCtxSet
+({
+  {  51, },
+  {  43, },
+  { CNU, },
+  {   0, },
+});
+
+const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet
+({
+  {  32,  35,  38, },
+  {  32,  35,  37, },
+  {   8,  35,  37, },
+  {   5,   5,   8, },
+});
 
+const CtxSet ContextSetCfg::JointCbCrFlag = ContextSetCfg::addCtxSet
+({
+  {  42,  50,  59, },
+  {  27,  36,  59, },
+  {  35,  36,  58, },
+  {   1,   0,   0, },
+});
 
-#define CNU 35
-std::vector<std::vector<uint8_t>> ContextSetCfg::sm_InitTables(NUMBER_OF_SLICE_TYPES + 1);
+const CtxSet ContextSetCfg::TsSigCoeffGroup = ContextSetCfg::addCtxSet
+({
+  {  19,  21,  30, },
+  {  18,  20,  14, },
+  {  19,  21,  31, },
+  {   5,   5,   1, },
+});
+
+const CtxSet ContextSetCfg::TsSigFlag = ContextSetCfg::addCtxSet
+({
+  {   9,  19,  29, },
+  {  25,  35,  37, },
+  {   9,  28,  38, },
+  {  12,   9,   9, },
+});
+
+const CtxSet ContextSetCfg::TsParFlag = ContextSetCfg::addCtxSet
+({
+  {  26, },
+  {  18, },
+  {  27, },
+  {   9, },
+});
+
+const CtxSet ContextSetCfg::TsGtxFlag = ContextSetCfg::addCtxSet
+({
+  { CNU,  43,  36,  37,  37, },
+  { CNU,   2,  19,  20,  12, },
+  { CNU,  27,  20,  37,  13, },
+  { DWS,   1,   2,   2,   2, },
+});
+
+const CtxSet ContextSetCfg::TsLrg1Flag = ContextSetCfg::addCtxSet
+({
+  {  43,  19,  12,   6, },
+  {  18,  11,  12,  43, },
+  {  19,  19,  12,  29, },
+  {   1,   2,   2,   1, },
+});
+
+const CtxSet ContextSetCfg::TsResidualSign = ContextSetCfg::addCtxSet
+({
+  {  35,  25,  46,  35,  33,  38, },
+  {  35,  10,  53,  35,  25,  46, },
+  {  35,  17,  54,  35,  25,  45, },
+  {   9,   6,   5,   4,   5,   8, },
+});
+
+
+#else
 
-// clang-format off
 #if RETRAIN_CABAC
 const CtxSet ContextSetCfg::SplitFlag = ContextSetCfg::addCtxSet
 ({
@@ -1712,6 +2477,7 @@ const CtxSet ContextSetCfg::TsResidualSign = ContextSetCfg::addCtxSet
   {   1,   4,   4, DWS, DWS, DWS, },
 });
 #endif
+#endif
 // clang-format on
 
 const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size();
@@ -1743,6 +2509,10 @@ template <class BinProbModel>
 CtxStore<BinProbModel>::CtxStore( const CtxStore<BinProbModel>& ctxStore )
   : m_CtxBuffer ( ctxStore.m_CtxBuffer )
   , m_Ctx       ( m_CtxBuffer.data() )
+#if JVET_P0300
+  , m_fixedProbQP( ctxStore.m_fixedProbQP )
+  , m_fixedProbId( ctxStore.m_fixedProbId )
+#endif
 {}
 
 template <class BinProbModel>
@@ -1756,6 +2526,10 @@ void CtxStore<BinProbModel>::init( int qp, int initId )
         "Size of rate init table (" << rateInitTable.size() << ") does not match size of context buffer ("
                                     << m_CtxBuffer.size() << ").");
   int clippedQP = Clip3( 0, MAX_QP, qp );
+#if JVET_P0300
+  m_fixedProbQP = clippedQP;
+  m_fixedProbId = initId;
+#endif
   for( std::size_t k = 0; k < m_CtxBuffer.size(); k++ )
   {
     m_CtxBuffer[k].init( clippedQP, initTable[k] );
@@ -1763,6 +2537,7 @@ void CtxStore<BinProbModel>::init( int qp, int initId )
   }
 }
 
+#if !JVET_P0300
 template <class BinProbModel>
 void CtxStore<BinProbModel>::setWinSizes( const std::vector<uint8_t>& log2WindowSizes )
 {
@@ -1794,10 +2569,12 @@ void CtxStore<BinProbModel>::savePStates( std::vector<uint16_t>& probStates ) co
     probStates[k] = m_CtxBuffer[k].getState();
   }
 }
+#endif
 
-
-
-
+#if JVET_P0300
+template class CtxStore<FixedProbModel_Est>;
+template class CtxStore<FixedProbModel_Enc>;
+#endif
 
 template class CtxStore<BinProbModel_Std>;
 
@@ -1806,10 +2583,18 @@ template class CtxStore<BinProbModel_Std>;
 
 
 Ctx::Ctx()                                  : m_BPMType( BPM_Undefined )                        {}
+#if JVET_P0300
+Ctx::Ctx( const FixedProbModel_Est* dummy ) : m_BPMType( BPM_FixedEst ), m_CtxStore_FixedEst( true )  {}
+Ctx::Ctx( const FixedProbModel_Enc* dummy ) : m_BPMType( BPM_FixedEnc ), m_CtxStore_FixedEnc( true )  {}
+#endif
 Ctx::Ctx( const BinProbModel_Std*   dummy ) : m_BPMType( BPM_Std   ), m_CtxStore_Std  ( true )  {}
 
 Ctx::Ctx( const Ctx& ctx )
   : m_BPMType         ( ctx.m_BPMType )
+#if JVET_P0300
+  , m_CtxStore_FixedEst( ctx.m_CtxStore_FixedEst )
+  , m_CtxStore_FixedEnc( ctx.m_CtxStore_FixedEnc )
+#endif
   , m_CtxStore_Std    ( ctx.m_CtxStore_Std    )
 {
   ::memcpy( m_GRAdaptStats, ctx.m_GRAdaptStats, sizeof( unsigned ) * RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS );
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 519f6ac6..6dd84b8c 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -60,6 +60,10 @@ enum BPMType
 {
   BPM_Undefined = 0,
   BPM_Std,
+#if JVET_P0300
+  BPM_FixedEst,
+  BPM_FixedEnc,
+#endif
   BPM_NUM
 };
 
@@ -154,7 +158,77 @@ private:
   uint8_t  m_rate;
 };
 
+#if JVET_P0300
+class FixedProbModel_Est : public BinProbModelBase
+{
+public:
+  FixedProbModel_Est() {}
+  ~FixedProbModel_Est() {}
 
+  void            init              ( int qp, int initId );
+  void update(unsigned bin) {}
+  void setLog2WindowSize(uint8_t log2WindowSize) {}
+  void estFracBitsUpdate(unsigned bin, uint64_t &b) { b += estFracBits(bin); }
+  uint32_t        estFracBits(unsigned bin) const { return getFracBitsArray().intBits[bin]; }
+  static uint32_t estFracBitsTrm(unsigned bin) { return (bin ? 0x3bfbb : 0x0010c); }
+  BinFracBits     getFracBitsArray() const { return m_fracBitsGB[m_bestGB]; }
+public:
+  uint8_t mps() const { return m_bestGB & 1; }
+  uint8_t getLPS(unsigned range) const
+  {
+    return range >> ( m_bestGB >> 1 );
+  }
+  static uint8_t  getRenormBitsLPS  ( unsigned LPS )                    { return    m_RenormTable_32  [LPS>>3]; }
+  static uint8_t  getRenormBitsRange( unsigned range )                  { return    1; }
+  static const int m_numGB = JVET_P0300_NUM_GB;
+  int8_t getBestGB() const { return m_bestGB; }
+private:
+  static const BinFracBits (&m_fracBitsGB)[2*m_numGB+4];
+  int8_t m_bestGB;
+};
+
+class FixedProbModel_Enc : public FixedProbModel_Est
+{
+public:
+  FixedProbModel_Enc()
+  {
+    m_ones = 0;
+    m_zeros = 0;
+  }
+
+  void  init( int qp, int initId )
+  {
+    FixedProbModel_Est::init( qp, initId );
+    m_ones = 0;
+    m_zeros = 0;
+  }
+
+  void update(unsigned bin)
+  {
+    if( bin )
+    {
+      m_ones++;
+    }
+    else
+    {
+      m_zeros++;
+    }
+  }
+
+  uint64_t estFracExcessBits(const FixedProbModel_Enc &r) const
+  {
+    if( m_ones + m_zeros == 0 )
+    {
+      return 32768; // Equal probability if no bins were encoded
+    }
+    int n = (int)(512 * m_ones / (m_ones + m_zeros));
+    return ((512 - n) * r.estFracBits(0) + n * r.estFracBits(1) + 256) >> 9;
+  }
+private:
+  uint64_t m_ones;
+  uint64_t m_zeros;
+};
+#endif
 
 
 
@@ -306,12 +380,19 @@ public:
   CtxStore( bool dummy );
   CtxStore( const CtxStore<BinProbModel>& ctxStore );
 public:
+#if JVET_P0300
+  template<class T> void copyFrom   ( const CtxStore<T>& src )                        { checkInit(); ::memcpy( m_Ctx,               src.m_Ctx,               sizeof( T ) * ContextSetCfg::NumberOfContexts ); }
+  template<class T> void copyFrom   ( const CtxStore<T>& src, const CtxSet& ctxSet )  { checkInit(); ::memcpy( m_Ctx+ctxSet.Offset, src.m_Ctx+ctxSet.Offset, sizeof( T ) * ctxSet.Size ); }
+#else
   void copyFrom   ( const CtxStore<BinProbModel>& src )                        { checkInit(); ::memcpy( m_Ctx,               src.m_Ctx,               sizeof( BinProbModel ) * ContextSetCfg::NumberOfContexts ); }
   void copyFrom   ( const CtxStore<BinProbModel>& src, const CtxSet& ctxSet )  { checkInit(); ::memcpy( m_Ctx+ctxSet.Offset, src.m_Ctx+ctxSet.Offset, sizeof( BinProbModel ) * ctxSet.Size ); }
+#endif
   void init       ( int qp, int initId );
+#if !JVET_P0300
   void setWinSizes( const std::vector<uint8_t>&   log2WindowSizes );
   void loadPStates( const std::vector<uint16_t>&  probStates );
   void savePStates( std::vector<uint16_t>&        probStates )  const;
+#endif
 
   const BinProbModel& operator[]      ( unsigned  ctxId  )  const { return m_Ctx[ctxId]; }
   BinProbModel&       operator[]      ( unsigned  ctxId  )        { return m_Ctx[ctxId]; }
@@ -325,9 +406,49 @@ private:
 private:
   std::vector<BinProbModel> m_CtxBuffer;
   BinProbModel*             m_Ctx;
+#if JVET_P0300
+  int                      m_fixedProbQP = -1;
+  int                      m_fixedProbId = -1;
+#endif
 };
 
+#if JVET_P0300
+template<>
+template<>
+inline void CtxStore<FixedProbModel_Est>::copyFrom<FixedProbModel_Est>( const CtxStore<FixedProbModel_Est>& src )
+{
+  if( !m_Ctx )
+  {
+    m_CtxBuffer.resize( ContextSetCfg::NumberOfContexts );
+    m_Ctx = m_CtxBuffer.data();
+  }
+  CHECK( src.m_fixedProbQP == -1, "Full copy of partially or uninitialized context." );
 
+  if( m_fixedProbQP != src.m_fixedProbQP || m_fixedProbId != src.m_fixedProbId )
+  {
+    m_fixedProbQP = src.m_fixedProbQP;
+    m_fixedProbId = src.m_fixedProbId;
+    ::memcpy( m_Ctx, src.m_Ctx, sizeof( FixedProbModel_Est ) * ContextSetCfg::NumberOfContexts );
+  }
+}
+
+template<>
+template<>
+inline void CtxStore<FixedProbModel_Est>::copyFrom<FixedProbModel_Est>( const CtxStore<FixedProbModel_Est>& src, const CtxSet& ctxSet )
+{
+  if( !m_Ctx )
+  {
+    m_CtxBuffer.resize( ContextSetCfg::NumberOfContexts );
+    m_Ctx = m_CtxBuffer.data();
+  }
+
+  if( src.m_fixedProbQP == -1 || m_fixedProbQP != src.m_fixedProbQP || m_fixedProbId != src.m_fixedProbId )
+  {
+    ::memcpy( m_Ctx+ctxSet.Offset, src.m_Ctx+ctxSet.Offset, sizeof( FixedProbModel_Est ) * ctxSet.Size );
+  }
+}
+
+#endif
 
 class Ctx;
 class SubCtx
@@ -348,6 +469,10 @@ class Ctx : public ContextSetCfg
 {
 public:
   Ctx();
+#if JVET_P0300
+  Ctx( const FixedProbModel_Est*  dummy );
+  Ctx( const FixedProbModel_Enc*  dummy );
+#endif
   Ctx( const BinProbModel_Std*    dummy );
   Ctx( const Ctx&                 ctx   );
 
@@ -357,6 +482,10 @@ public:
     m_BPMType = ctx.m_BPMType;
     switch( m_BPMType )
     {
+#if JVET_P0300
+    case BPM_FixedEst: m_CtxStore_FixedEst.copyFrom( ctx.m_CtxStore_FixedEst );  break;
+    case BPM_FixedEnc: m_CtxStore_FixedEnc.copyFrom( ctx.m_CtxStore_FixedEnc );  break;
+#endif
     case BPM_Std:   m_CtxStore_Std  .copyFrom( ctx.m_CtxStore_Std   );  break;
     default:        break;
     }
@@ -369,6 +498,10 @@ public:
     m_BPMType = subCtx.m_Ctx.m_BPMType;
     switch( m_BPMType )
     {
+#if JVET_P0300
+    case BPM_FixedEst: m_CtxStore_FixedEst.copyFrom( subCtx.m_Ctx.m_CtxStore_FixedEst, subCtx.m_CtxSet );  break;
+    case BPM_FixedEnc: m_CtxStore_FixedEnc.copyFrom( subCtx.m_Ctx.m_CtxStore_FixedEnc, subCtx.m_CtxSet );  break;
+#endif
     case BPM_Std:   m_CtxStore_Std  .copyFrom( subCtx.m_Ctx.m_CtxStore_Std,   subCtx.m_CtxSet );  break;
     default:        break;
     }
@@ -379,6 +512,10 @@ public:
   {
     switch( m_BPMType )
     {
+#if JVET_P0300
+    case BPM_FixedEst: m_CtxStore_FixedEst.init( qp, initId );  break;
+    case BPM_FixedEnc: m_CtxStore_FixedEnc.init( qp, initId );  break;
+#endif
     case BPM_Std:   m_CtxStore_Std  .init( qp, initId );  break;
     default:        break;
     }
@@ -387,7 +524,7 @@ public:
       m_GRAdaptStats[k] = 0;
     }
   }
-
+#if !JVET_P0300
   void  loadPStates( const std::vector<uint16_t>& probStates )
   {
     switch( m_BPMType )
@@ -418,7 +555,7 @@ public:
       break;
     }
   }
-
+#endif
   const unsigned&     getGRAdaptStats ( unsigned      id )      const { return m_GRAdaptStats[id]; }
   unsigned&           getGRAdaptStats ( unsigned      id )            { return m_GRAdaptStats[id]; }
 
@@ -427,6 +564,12 @@ public:
   const Ctx&          getCtx          ()                        const { return *this; }
   Ctx&                getCtx          ()                              { return *this; }
 
+#if JVET_P0300
+  explicit operator   const CtxStore<FixedProbModel_Est>  &()     const { return m_CtxStore_FixedEst; }
+  explicit operator         CtxStore<FixedProbModel_Est>  &()           { return m_CtxStore_FixedEst; }
+  explicit operator   const CtxStore<FixedProbModel_Enc>  &()     const { return m_CtxStore_FixedEnc; }
+  explicit operator         CtxStore<FixedProbModel_Enc>  &()           { return m_CtxStore_FixedEnc; }
+#endif
   explicit operator   const CtxStore<BinProbModel_Std>  &()     const { return m_CtxStore_Std; }
   explicit operator         CtxStore<BinProbModel_Std>  &()           { return m_CtxStore_Std; }
 
@@ -434,6 +577,10 @@ public:
   {
     switch( m_BPMType )
     {
+#if JVET_P0300
+    case BPM_FixedEst:   return m_CtxStore_FixedEst;
+    case BPM_FixedEnc:   return m_CtxStore_FixedEnc;
+#endif
     case BPM_Std:   return m_CtxStore_Std;
     default:        THROW("BPMType out of range");
     }
@@ -441,6 +588,10 @@ public:
 
 private:
   BPMType                       m_BPMType;
+#if JVET_P0300
+  CtxStore<FixedProbModel_Est>  m_CtxStore_FixedEst;
+  CtxStore<FixedProbModel_Enc>  m_CtxStore_FixedEnc;
+#endif
   CtxStore<BinProbModel_Std>    m_CtxStore_Std;
 protected:
   unsigned                      m_GRAdaptStats[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS];
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index bb648125..b56f7645 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1676,6 +1676,9 @@ SPS::SPS()
 , m_LadfQpOffset              { 0 }
 , m_LadfIntervalLowerBound    { 0 }
 #endif
+#if JVET_P0300_SIGNALING
+, m_FastCabacEnabled          ( false )
+#endif
 , m_MIP                       ( false )
     ,m_GDREnabledFlag         (1)
 , m_SubLayerCbpParametersPresentFlag (1)
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 3baa39d3..4276cf3e 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -946,6 +946,9 @@ private:
   int               m_LadfNumIntervals;
   int               m_LadfQpOffset[MAX_LADF_INTERVALS];
   int               m_LadfIntervalLowerBound[MAX_LADF_INTERVALS];
+#endif
+#if JVET_P0300_SIGNALING
+  bool              m_FastCabacEnabled;
 #endif
   bool              m_MIP;
   ChromaQpMappingTable m_chromaQpMappingTable;
@@ -1178,6 +1181,10 @@ public:
   void      setLadfIntervalLowerBound( int value, int idx )                         { m_LadfIntervalLowerBound[ idx ] = value; }
   int       getLadfIntervalLowerBound( int idx )                          const     { return m_LadfIntervalLowerBound[ idx ]; }
 #endif
+#if JVET_P0300_SIGNALING
+  void      setFastCabacEnabled   ( bool b )                                        { m_FastCabacEnabled = b; }
+  bool      getFastCabacEnabled   ()                                      const     { return m_FastCabacEnabled; }
+#endif
 
   void      setUseMHIntra         ( bool b )                                        { m_MHIntra = b; }
   bool      getUseMHIntra         ()                                      const     { return m_MHIntra; }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 1363c314..9ef0197d 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,14 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_P0300                                        1
+
+
+#if JVET_P0300
+#define JVET_P0300_NUM_GB                                 3
+#define JVET_P0300_SIGNALING                              1
+#endif
+
 #define RETRAIN_CABAC                                     1 // Retrained CABAC probabilities
 
 #define JVET_P01034_PRED_1D_SCALING_LIST                  1 // JVET-P1034: 1D Scaling list index and add predictor mode
diff --git a/source/Lib/DecoderLib/BinDecoder.cpp b/source/Lib/DecoderLib/BinDecoder.cpp
index 63578555..6112e2b0 100644
--- a/source/Lib/DecoderLib/BinDecoder.cpp
+++ b/source/Lib/DecoderLib/BinDecoder.cpp
@@ -350,6 +350,65 @@ TBinDecoder<BinProbModel>::TBinDecoder()
   , m_Ctx         ( static_cast<CtxStore<BinProbModel>&>( *this   ) )
 {}
 
+#if JVET_P0300
+template <>
+unsigned TBinDecoder<FixedProbModel_Est>::decodeBin( unsigned ctxId )
+{
+  FixedProbModel_Est& rcProbModel = m_Ctx[ctxId];
+  if( rcProbModel.getBestGB() < 4 )
+  {
+    return decodeBinEP();
+  }
+  unsigned      bin         = rcProbModel.mps();
+  uint32_t      LPS         = rcProbModel.getLPS( m_Range );
+
+  DTRACE( g_trace_ctx, D_CABAC, "%d" " %d " "%d" "  " "[%d:%d]" "  " "%2d(MPS=%d)"  "  " , DTRACE_GET_COUNTER( g_trace_ctx, D_CABAC ), ctxId, m_Range, m_Range-LPS, LPS, ( unsigned int )( rcProbModel.state() ), m_Value < ( ( m_Range - LPS ) << 7 ) );
+  //DTRACE( g_trace_ctx, D_CABAC, " %d " "%d" "  " "[%d:%d]" "  " "%2d(MPS=%d)"  "  ", DTRACE_GET_COUNTER( g_trace_ctx, D_CABAC ), m_Range, m_Range - LPS, LPS, (unsigned int)( rcProbModel.state() ), m_Value < ( ( m_Range - LPS ) << 7 ) );
+  m_Range   -=  LPS;
+  uint32_t      SR          = m_Range << 7;
+  if( m_Value < SR )
+  {
+#if RExt__DECODER_DEBUG_BIT_STATISTICS
+    CodingStatistics::UpdateCABACStat( *ptype, m_Range+LPS, m_Range, int( bin ) );
+#endif
+    // MPS path
+    if( m_Range < 256 )
+    {
+      int numBits   = rcProbModel.getRenormBitsRange( m_Range );
+      m_Range     <<= numBits;
+      m_Value     <<= numBits;
+      m_bitsNeeded += numBits;
+      if( m_bitsNeeded >= 0 )
+      {
+        m_Value      += m_Bitstream->readByte() << m_bitsNeeded;
+        m_bitsNeeded -= 8;
+      }
+    }
+  }
+  else
+  {
+    bin = 1 - bin;
+#if RExt__DECODER_DEBUG_BIT_STATISTICS
+    CodingStatistics::UpdateCABACStat( *ptype, m_Range+LPS, LPS, int( bin ) );
+#endif
+    // LPS path
+    int numBits = rcProbModel.getBestGB() >> 1;
+    m_Value      -= SR;
+    m_Value       = m_Value << numBits;
+    m_Range       = LPS     << numBits;
+    m_bitsNeeded += numBits;
+    if( m_bitsNeeded >= 0 )
+    {
+      m_Value      += m_Bitstream->readByte() << m_bitsNeeded;
+      m_bitsNeeded -= 8;
+    }
+  }
+  rcProbModel.update( bin );
+  //DTRACE_DECR_COUNTER( g_trace_ctx, D_CABAC );
+  DTRACE_WITHOUT_COUNT( g_trace_ctx, D_CABAC, "  -  " "%d" "\n", bin );
+  return  bin;
+}
+#endif
 
 template <class BinProbModel>
 unsigned TBinDecoder<BinProbModel>::decodeBin( unsigned ctxId )
@@ -407,6 +466,8 @@ unsigned TBinDecoder<BinProbModel>::decodeBin( unsigned ctxId )
 }
 
 
-
+#if JVET_P0300
+template class TBinDecoder<FixedProbModel_Est>;
+#endif
 template class TBinDecoder<BinProbModel_Std>;
 
diff --git a/source/Lib/DecoderLib/BinDecoder.h b/source/Lib/DecoderLib/BinDecoder.h
index d3632726..e7bf8b17 100644
--- a/source/Lib/DecoderLib/BinDecoder.h
+++ b/source/Lib/DecoderLib/BinDecoder.h
@@ -105,7 +105,9 @@ private:
 };
 
 
-
+#if JVET_P0300
+typedef TBinDecoder<FixedProbModel_Est>   BinDecoder_Fixed;
+#endif
 typedef TBinDecoder<BinProbModel_Std>   BinDecoder_Std;
 
 
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index 95bb0abc..137f1438 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -186,14 +186,25 @@ class CABACDecoder
 public:
   CABACDecoder()
     : m_CABACReaderStd  ( m_BinDecoderStd )
+#if JVET_P0300
+    , m_CABACReaderFixed( m_BinDecoderFixed )
+    , m_CABACReader     { &m_CABACReaderStd, &m_CABACReaderFixed }
+#else
     , m_CABACReader     { &m_CABACReaderStd }
+#endif
   {}
 
   CABACReader*                getCABACReader    ( int           id    )       { return m_CABACReader[id]; }
 
 private:
   BinDecoder_Std          m_BinDecoderStd;
+#if JVET_P0300
+  BinDecoder_Fixed        m_BinDecoderFixed;
+#endif
   CABACReader             m_CABACReaderStd;
+#if JVET_P0300
+  CABACReader             m_CABACReaderFixed;
+#endif
   CABACReader*            m_CABACReader[BPM_NUM-1];
 };
 
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 8f99d259..2eb276ff 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1585,7 +1585,6 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
   //  Decode a picture
   m_cSliceDecoder.decompressSlice( pcSlice, &( nalu.getBitstream() ), ( m_pcPic->poc == getDebugPOC() ? getDebugCTU() : -1 ) );
-
   m_bFirstSliceInPicture = false;
   m_uiSliceSegmentIdx++;
 
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index d21981ae..f7b4631c 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -169,7 +169,6 @@ public:
   void setDebugCTU( int debugCTU )        { m_debugCTU = debugCTU; }
   int  getDebugPOC( )               const { return m_debugPOC; };
   void setDebugPOC( int debugPOC )        { m_debugPOC = debugPOC; };
-
 protected:
   void  xUpdateRasInit(Slice* slice);
 
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index b4a5da39..d888fc89 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -78,7 +78,17 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
   const SPS*     sps          = slice->getSPS();
   Picture*       pic          = slice->getPic();
   const BrickMap& tileMap     = *pic->brickMap;
+#if JVET_P0300
+
+#if JVET_P0300_SIGNALING
+  CABACReader&   cabacReader  = *m_CABACDecoder->getCABACReader( sps->getFastCabacEnabled() );
+#else
+  CABACReader&   cabacReader  = *m_CABACDecoder->getCABACReader( 1 );
+#endif
+
+#else
   CABACReader&   cabacReader  = *m_CABACDecoder->getCABACReader( 0 );
+#endif
 
   // setup coding structure
   CodingStructure& cs = *pic->cs;
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index d3b51f0a..5380f499 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1529,6 +1529,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
     }
   }
 #endif
+#if JVET_P0300_SIGNALING
+  READ_FLAG( uiCode, "sps_fast_cabac_enabled_flag" );               pcSPS->setFastCabacEnabled(uiCode != 0);
+#endif
 
   // KJS: reference picture sets to be replaced
 
diff --git a/source/Lib/EncoderLib/BinEncoder.cpp b/source/Lib/EncoderLib/BinEncoder.cpp
index 06500d6f..a2e665a1 100644
--- a/source/Lib/EncoderLib/BinEncoder.cpp
+++ b/source/Lib/EncoderLib/BinEncoder.cpp
@@ -405,6 +405,99 @@ TBinEncoder<BinProbModel>::TBinEncoder()
   , m_Ctx         ( static_cast<CtxStore<BinProbModel>&>( *this   ) )
 {}
 
+#if JVET_P0300
+template <>
+void TBinEncoder<FixedProbModel_Est>::encodeBin( unsigned bin, unsigned ctxId )
+{
+  if( m_Ctx[ctxId].getBestGB() < 4 )
+  {
+    encodeBinEP( bin );
+    return;
+  }
+  BinCounter::addCtx( ctxId );
+  FixedProbModel_Est& rcProbModel = m_Ctx[ctxId];
+  uint32_t      LPS         = rcProbModel.getLPS( m_Range );
+
+  DTRACE( g_trace_ctx, D_CABAC, "%d" " %d " "%d" "  " "[%d:%d]" "  " "%2d(MPS=%d)"  "  " "  -  " "%d" "\n", DTRACE_GET_COUNTER( g_trace_ctx, D_CABAC ), ctxId, m_Range, m_Range - LPS, LPS, ( unsigned int ) ( rcProbModel.state() ), bin == rcProbModel.mps(), bin );
+
+  m_Range   -=  LPS;
+  if( bin != rcProbModel.mps() )
+  {
+    int numBits = rcProbModel.getBestGB() >> 1;
+//    int numBits   = rcProbModel.getRenormBitsLPS( LPS );
+    m_bitsLeft   -= numBits;
+    m_Low        += m_Range;
+    m_Low         = m_Low << numBits;
+    m_Range       = LPS   << numBits;
+    if( m_bitsLeft < 12 )
+    {
+      writeOut();
+    }
+  }
+  else
+  {
+    if( m_Range < 256 )
+    {
+      int numBits   = rcProbModel.getRenormBitsRange( m_Range );
+      m_bitsLeft   -= numBits;
+      m_Low       <<= numBits;
+      m_Range     <<= numBits;
+      if( m_bitsLeft < 12 )
+      {
+        writeOut();
+      }
+    }
+  }
+  rcProbModel.update( bin );
+  BinEncoderBase::m_BinStore.addBin( bin, ctxId );
+}
+template <>
+void TBinEncoder<FixedProbModel_Enc>::encodeBin( unsigned bin, unsigned ctxId )
+{
+  if( m_Ctx[ctxId].getBestGB() < 4 )
+  {
+    encodeBinEP( bin );
+    return;
+  }
+  BinCounter::addCtx( ctxId );
+  FixedProbModel_Enc& rcProbModel = m_Ctx[ctxId];
+  uint32_t      LPS         = rcProbModel.getLPS( m_Range );
+
+  DTRACE( g_trace_ctx, D_CABAC, "%d" " %d " "%d" "  " "[%d:%d]" "  " "%2d(MPS=%d)"  "  " "  -  " "%d" "\n", DTRACE_GET_COUNTER( g_trace_ctx, D_CABAC ), ctxId, m_Range, m_Range - LPS, LPS, ( unsigned int ) ( rcProbModel.state() ), bin == rcProbModel.mps(), bin );
+
+  m_Range   -=  LPS;
+  if( bin != rcProbModel.mps() )
+  {
+    int numBits = rcProbModel.getBestGB() >> 1;
+//    int numBits   = rcProbModel.getRenormBitsLPS( LPS );
+    m_bitsLeft   -= numBits;
+    m_Low        += m_Range;
+    m_Low         = m_Low << numBits;
+    m_Range       = LPS   << numBits;
+    if( m_bitsLeft < 12 )
+    {
+      writeOut();
+    }
+  }
+  else
+  {
+    if( m_Range < 256 )
+    {
+      int numBits   = rcProbModel.getRenormBitsRange( m_Range );
+      m_bitsLeft   -= numBits;
+      m_Low       <<= numBits;
+      m_Range     <<= numBits;
+      if( m_bitsLeft < 12 )
+      {
+        writeOut();
+      }
+    }
+  }
+  rcProbModel.update( bin );
+  BinEncoderBase::m_BinStore.addBin( bin, ctxId );
+}
+#endif
+
 template <class BinProbModel>
 void TBinEncoder<BinProbModel>::encodeBin( unsigned bin, unsigned ctxId )
 {
@@ -562,6 +655,10 @@ TBitEstimator<BinProbModel>::TBitEstimator()
 {}
 
 
+#if JVET_P0300
+template class TBinEncoder<FixedProbModel_Enc>;
+template class TBitEstimator<FixedProbModel_Est>;
+#endif
 
 template class TBinEncoder<BinProbModel_Std>;
 
diff --git a/source/Lib/EncoderLib/BinEncoder.h b/source/Lib/EncoderLib/BinEncoder.h
index 979f2721..4ebc5a48 100644
--- a/source/Lib/EncoderLib/BinEncoder.h
+++ b/source/Lib/EncoderLib/BinEncoder.h
@@ -295,6 +295,10 @@ private:
 };
 
 
+#if JVET_P0300
+typedef TBinEncoder  <FixedProbModel_Enc> BinEncoder_Fixed;
+typedef TBitEstimator<FixedProbModel_Est> BitEstimator_Fixed;
+#endif
 
 typedef TBinEncoder  <BinProbModel_Std>   BinEncoder_Std;
 
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 7c334449..e0a9d09e 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -105,15 +105,22 @@ SliceType xGetCtxInitId( const Slice& slice, const BinEncIf& binEncoder, Ctx& ct
 
 SliceType CABACWriter::getCtxInitId( const Slice& slice )
 {
+#if JVET_P0300
+  m_TestCtx = m_BinEncoder.getCtx();
+#endif
   switch( m_TestCtx.getBPMType() )
   {
+#if JVET_P0300
+  case BPM_FixedEst: CHECK( 1, "Not supported." );
+  case BPM_FixedEnc: return  xGetCtxInitId<FixedProbModel_Enc>   ( slice, m_BinEncoder, m_TestCtx );
+#endif
   case BPM_Std:   return  xGetCtxInitId<BinProbModel_Std>   ( slice, m_BinEncoder, m_TestCtx );
   default:        return  NUMBER_OF_SLICE_TYPES;
   }
 }
 
 
-
+#if !JVET_P0300
 unsigned estBits( BinEncIf& binEnc, const std::vector<bool>& bins, const Ctx& ctx, const int ctxId, const uint8_t winSize )
 {
   binEnc.initCtxAndWinSize( ctxId, ctx, winSize );
@@ -129,8 +136,7 @@ unsigned estBits( BinEncIf& binEnc, const std::vector<bool>& bins, const Ctx& ct
   unsigned codedBits  = endBits - startBits;
   return   codedBits;
 }
-
-
+#endif
 
 
 
diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h
index 7e60fe96..21d2ac92 100644
--- a/source/Lib/EncoderLib/CABACWriter.h
+++ b/source/Lib/EncoderLib/CABACWriter.h
@@ -51,7 +51,11 @@ class EncCu;
 class CABACWriter
 {
 public:
+#if JVET_P0300
+  CABACWriter(BinEncIf& binEncoder)   : m_BinEncoder(binEncoder), m_Bitstream(0) { m_EncCu = NULL; }
+#else
   CABACWriter(BinEncIf& binEncoder)   : m_BinEncoder(binEncoder), m_Bitstream(0) { m_TestCtx = m_BinEncoder.getCtx(); m_EncCu = NULL; }
+#endif
   virtual ~CABACWriter() {}
 
 public:
@@ -210,17 +214,43 @@ public:
   CABACEncoder()
     : m_CABACWriterStd      ( m_BinEncoderStd )
     , m_CABACEstimatorStd   ( m_BitEstimatorStd )
+#if JVET_P0300
+    , m_CABACWriterFixed    ( m_BinEncoderFixed )
+    , m_CABACEstimatorFixed ( m_BitEstimatorFixed )
+    , m_CABACWriter         { &m_CABACWriterStd, &m_CABACWriterFixed  }
+    , m_CABACEstimator      { &m_CABACEstimatorStd, &m_CABACEstimatorFixed }
+#else
     , m_CABACWriter         { &m_CABACWriterStd,   }
     , m_CABACEstimator      { &m_CABACEstimatorStd }
+#endif
   {}
+#if JVET_P0300
 
+#if JVET_P0300_SIGNALING
+  CABACWriter*                getCABACWriter          ( const SPS*   sps   )        { return m_CABACWriter   [sps->getFastCabacEnabled()]; }
+  CABACWriter*                getCABACEstimator       ( const SPS*   sps   )        { return m_CABACEstimator[sps->getFastCabacEnabled()]; }
+#else
+  CABACWriter*                getCABACWriter          ( const SPS*   sps   )        { return m_CABACWriter   [1]; }
+  CABACWriter*                getCABACEstimator       ( const SPS*   sps   )        { return m_CABACEstimator[1]; }
+#endif
+
+#else
   CABACWriter*                getCABACWriter          ( const SPS*   sps   )        { return m_CABACWriter   [0]; }
   CABACWriter*                getCABACEstimator       ( const SPS*   sps   )        { return m_CABACEstimator[0]; }
+#endif
 private:
   BinEncoder_Std      m_BinEncoderStd;
   BitEstimator_Std    m_BitEstimatorStd;
+#if JVET_P0300
+  BinEncoder_Fixed    m_BinEncoderFixed;
+  BitEstimator_Fixed  m_BitEstimatorFixed;
+#endif
   CABACWriter         m_CABACWriterStd;
   CABACWriter         m_CABACEstimatorStd;
+#if JVET_P0300
+  CABACWriter         m_CABACWriterFixed;
+  CABACWriter         m_CABACEstimatorFixed;
+#endif
   CABACWriter*        m_CABACWriter   [BPM_NUM-1];
   CABACWriter*        m_CABACEstimator[BPM_NUM-1];
 };
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index bdb6e92e..57e72b95 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -2522,8 +2522,11 @@ void  EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar
             continue;
           }
         }
-
+#if JVET_P0300
+        m_CABACEstimator->getCtx() = AlfCtx(ctxStart);
+#else
         m_CABACEstimator->getCtx() = ctxStart;
+#endif
         for (int ctbIdx = 0; ctbIdx < m_numCTUsInPic; ctbIdx++)
         {
           double distUnfilterCtb = m_ctbDistortionUnfilter[COMPONENT_Y][ctbIdx];
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 9f7cbf09..2146eaab 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -307,6 +307,9 @@ protected:
   int       m_LadfQpOffset[MAX_LADF_INTERVALS];
   int       m_LadfIntervalLowerBound[MAX_LADF_INTERVALS];
 #endif
+#if JVET_P0300_SIGNALING
+  bool      m_FastCabacEnabled;
+#endif
 
   bool      m_MHIntra;
   bool      m_Triangle;
@@ -933,6 +936,10 @@ public:
   void      setLadfIntervalLowerBound       ( int value, int idx ){ m_LadfIntervalLowerBound[ idx ] = value; }
   int       getLadfIntervalLowerBound       ( int idx ) const { return m_LadfIntervalLowerBound[ idx ]; }
 
+#endif
+#if JVET_P0300_SIGNALING
+  void      setFastCabacEnabled             ( bool b )       { m_FastCabacEnabled = b; }
+  bool      getFastCabacEnabled             ()         const { return m_FastCabacEnabled; }
 #endif
 
   void      setUseMHIntra                   ( bool b )       { m_MHIntra = b; }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index a469d437..dd7b1fdc 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1016,6 +1016,9 @@ void EncLib::xInitSPS(SPS &sps)
     CHECK( m_LadfIntervalLowerBound[0] != 0, "abnormal value set to LadfIntervalLowerBound[0]" );
   }
 #endif
+#if JVET_P0300_SIGNALING
+  sps.setFastCabacEnabled     ( m_FastCabacEnabled );
+#endif
 
   sps.setUseMHIntra            ( m_MHIntra );
   sps.setUseTriangle           ( m_Triangle );
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 00723e7a..a14e3796 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -969,6 +969,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     }
   }
 #endif
+#if JVET_P0300_SIGNALING
+  WRITE_FLAG( pcSPS->getFastCabacEnabled() ? 1 : 0,                                   "sps_fast_cabac_enabled_flag");
+#endif
 
   // KJS: reference picture sets to be replaced
 
