diff --git a/COPYING b/COPYING
index a9d8844e42393a8ca9b79fb1cc81aa983b916cc3..0227899c94523ffb16b26e6a85ff55add99123e4 100644
--- a/COPYING
+++ b/COPYING
@@ -3,7 +3,7 @@ License, included below. This software may be subject to other third party
 and contributor rights, including patent rights, and no such rights are
 granted under this license.   
 
-Copyright (c) 2010-2017, ITU/ISO/IEC
+Copyright (c) 2010-2019, ITU/ISO/IEC
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Makefile b/Makefile
index d737cd85630e7d19638cf0f2324ca23b86571eb6..d61744bed9a7926118b9107c9e59384d12a3126d 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,8 @@ else
   UNAME_S := $(shell uname -s)
   BUILD_CMD := $(BUILD_SCRIPT)
   ifeq ($(UNAME_S),Linux)
+    # for Jenkins: run trace build only on Linux
+    LINUXBUILD := TRUE
   endif
   ifeq ($(UNAME_S),Darwin)
     # MAC
@@ -127,6 +129,12 @@ clean-p:
 configure:
 	$(BUILD_CMD) $(CONFIG_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo
 
+linuxbuild:
+ifeq ($(LINUXBUILD),TRUE)
+	# option for automated jenkins build
+	$(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug
+endif
+
 #
 # project specific targets
 #
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b695964769c896c17c0b5f6690e79da19d7c0ca3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,97 @@
+How to build VTM
+================
+
+The software uses CMake to create platform-specific build files. 
+
+Build instructions for plain CMake (suggested)
+----------------------------------------------
+
+**Note:** A working CMake installation is required for building the software.
+
+CMake generates configuration files for the compiler environment/development environment on each platform. 
+The following is a list of examples for Windows (MS Visual Studio), macOS (Xcode) and Linux (make).
+
+Open a command prompt on your system and change into the root directory of this project.
+
+Create a build directory in the root directory:
+```bash
+mkdir build 
+```
+
+Use one of the following CMake commands, based on your platform. Feel free to change the commands to satisfy
+your needs.
+
+**Windows Visual Studio 2015 64 Bit:**
+```bash
+cd build
+cmake .. -G "Visual Studio 14 2015 Win64"
+```
+Then open the generated solution file in MS Visual Studio.
+
+**macOS Xcode:**
+```bash
+cd build
+cmake .. -G "Xcode"
+```
+Then open the generated work space in Xcode.
+
+**Linux**
+
+For generating Linux Release Makefile:
+```bash
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release
+```
+For generating Linux Debug Makefile:
+```bash
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Debug
+```
+
+Then type
+```bash
+make -j
+```
+
+For more details, refer to the CMake documentation: https://cmake.org/cmake/help/latest/
+
+Build instructions for make
+---------------------------
+
+**Note:** The build instructions in this section require the make tool and Python to be installed, which are
+part of usual Linux and macOS environments. See below for installation instruction for Python and GnuWin32 
+on Windows.
+
+Open a command prompt on your system and change into the root directory of this project.
+
+To use the default system compiler simply call:
+```bash
+make all
+```
+For MSYS2 and MinGW: Open an MSYS MinGW 64-Bit terminal and change into the root directory of this project.
+
+Call:
+```bash
+make all toolset=gcc
+```
+
+
+Tool Installation on Windows
+----------------------------
+Download CMake: http://www.cmake.org/ and install it.
+
+Python and GnuWin32 are not mandatory, but they simplify the build process for the user.
+
+python:    https://www.python.org/downloads/release/python-371/
+
+gnuwin32:  https://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/0.6.30/GetGnuWin32-0.6.3.exe/download
+
+To use MinGW, install MSYS2: http://repo.msys2.org/distrib/msys2-x86_64-latest.exe
+
+Installation instructions: https://www.msys2.org/
+
+Install the needed toolchains:
+```bash
+pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain git subversion mingw-w64-i686-cmake mingw-w64-x86_64-cmake
+```
+
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 8c8f02715a0dac363cb2721636ae51c789eb3184..0000000000000000000000000000000000000000
--- a/README.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-NextSoftware/VVCSoftware_VTM build howto:
-
-The software uses cmake to create the needed build files. 
-Download cmake: http://www.cmake.org/ and install it.
-
-=================== Windows only =======================
-Python and gnuwin32 are not mandatory, but they simplifiy the build process for the user.
-python:    https://www.python.org/downloads/release/python-371/
-gnuwin32:  https://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/0.6.30/GetGnuWin32-0.6.3.exe/download
-
-To use MinGW, install MSYS2:
-http://repo.msys2.org/distrib/msys2-x86_64-latest.exe
-
-Installation instructions:
-https://www.msys2.org/
-
-and install the needed toolchains.
-pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain git subversion mingw-w64-i686-cmake mingw-w64-x86_64-cmake
-========================================================
-
-========= Build instructions for plain cmake ===========
-Open a command prompt on your system and change into the root directory
-of this project (location of README.txt).
-
-Create a build directory in the root directory:
-mkdir build 
-
-After that use one of the following cmake commands. Feel free to change the 
-commands to satisfy your needs.
-
-Windows sample for Visual Studio 2015 64 Bit:
-cd build
-cmake .. -G "Visual Studio 14 2015 Win64"
-
-Linux Release Makefile sample:
-cd build
-cmake .. -DCMAKE_BUILD_TYPE=Release
-
-Linux Debug Makefile sample:
-cd build
-cmake .. -DCMAKE_BUILD_TYPE=Debug
-
-MACOSX Xcode sample:
-cd build
-cmake .. -G "Xcode"
-========================================================
-
-============= Build instructions for make ==============
-remark:
-If you installed python and gnuwin32 on Windows operating systems, 
-you will be able to use make.
-
-Open a command prompt on your system and change into the root directory
-of this project (location of README.txt).
-
-to use the default system compiler simply call:
-make all
-
-Using MSYS2 and MinGW:
-Open an MSYS MinGW 64-Bit terminal and change into the root directory
-of this project (location of README.txt).
-
-Call:
-make all toolset=gcc
-========================================================
diff --git a/cfg/encoder_intra_vtm.cfg b/cfg/encoder_intra_vtm.cfg
index 814bf20d9368cd7c9a6675e9840f2ec1ae4c2e13..c758b49907e00fbea3c9d07cab18b6637904f63e 100644
--- a/cfg/encoder_intra_vtm.cfg
+++ b/cfg/encoder_intra_vtm.cfg
@@ -87,7 +87,6 @@ TemporalSubsampleRatio              : 8
 #============ NEXT ====================
 
 # General
-LargeCTU                     : 1      # Large CTU
 CTUSize                      : 128
 LCTUFast                     : 1
 QuadtreeTULog2MaxSize        : 6
@@ -99,25 +98,31 @@ MinQTNonISlice               : 8
 MaxBTDepth                   : 3
 MaxBTDepthISliceL            : 3
 MaxBTDepthISliceC            : 3
-MTT                          : 1
 
 MTS                          : 1
 MTSIntraMaxCand              : 3
 MTSInterMaxCand              : 4
+SBT                          : 1
 Affine                       : 1
 SubPuMvp                     : 1
 MaxNumMergeCand              : 6
 LMChroma                     : 1      # use CCLM only
 DepQuant                     : 1
-IMV                          : 2
+IMV                          : 1
 ALF                          : 1
 IBC                          : 0      # turned off in CTC 
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 0
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
 
 # Fast tools
 PBIntraFast                  : 1
 FastMrg                      : 1
 AMaxBT                       : 1
 
+# Encoder optimization tools
+AffineAmvrEncOpt             : 0
+
 ### DO NOT ADD ANYTHING BELOW THIS LINE ###
 ### DO NOT DELETE THE EMPTY LINE BELOW ###
 
diff --git a/cfg/encoder_lowdelay_P_vtm.cfg b/cfg/encoder_lowdelay_P_vtm.cfg
index 132d9db5c55967284a1d2ee5497da6c44ee39ed5..9673ad33a33e36952002e4ac6fab81aed4f4f8b3 100644
--- a/cfg/encoder_lowdelay_P_vtm.cfg
+++ b/cfg/encoder_lowdelay_P_vtm.cfg
@@ -103,7 +103,6 @@ CrQpOffset                          : 1
 #============ NEXT ====================
 
 # General
-LargeCTU                     : 1      # Large CTU
 CTUSize                      : 128
 LCTUFast                     : 1
 QuadtreeTULog2MaxSize        : 6
@@ -115,26 +114,32 @@ MinQTNonISlice               : 8
 MaxBTDepth                   : 3
 MaxBTDepthISliceL            : 3
 MaxBTDepthISliceC            : 3
-MTT                          : 1
 
 MTS                          : 1
 MTSIntraMaxCand              : 3
 MTSInterMaxCand              : 4
+SBT                          : 1
 Affine                       : 1
 SubPuMvp                     : 1
 MaxNumMergeCand              : 6
 LMChroma                     : 1      # use CCLM only
 DepQuant                     : 1
-IMV                          : 2
+IMV                          : 1
 ALF                          : 1
 MHIntra                      : 1
 IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 0
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
 
 # Fast tools
 PBIntraFast                  : 1
 FastMrg                      : 1
 AMaxBT                       : 1
 
+# Encoder optimization tools
+AffineAmvrEncOpt             : 0
+
 ### DO NOT ADD ANYTHING BELOW THIS LINE ###
 ### DO NOT DELETE THE EMPTY LINE BELOW ###
 
diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg
index 7d8350f9257c2d87be841e0083792ada75bc11b3..81bcc515518a7547262b08e271397e46fccde8ae 100644
--- a/cfg/encoder_lowdelay_vtm.cfg
+++ b/cfg/encoder_lowdelay_vtm.cfg
@@ -103,7 +103,6 @@ CrQpOffset                          : 1
 #============ NEXT ====================
 
 # General
-LargeCTU                     : 1      # Large CTU
 CTUSize                      : 128
 LCTUFast                     : 1
 QuadtreeTULog2MaxSize        : 6
@@ -115,29 +114,35 @@ MinQTNonISlice               : 8
 MaxBTDepth                   : 3
 MaxBTDepthISliceL            : 3
 MaxBTDepthISliceC            : 3
-MTT                          : 1
 
 MTS                          : 1
 MTSIntraMaxCand              : 3
 MTSInterMaxCand              : 4
+SBT                          : 1
 Affine                       : 1
 SubPuMvp                     : 1
 MaxNumMergeCand              : 6
 LMChroma                     : 1      # use CCLM only
 DepQuant                     : 1
-IMV                          : 2
+IMV                          : 1
 ALF                          : 1
 GBi                          : 1 
 GBiFast                      : 1 
 MHIntra                      : 1
 Triangle                     : 1
 IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 0
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
 
 # Fast tools
 PBIntraFast                  : 1
 FastMrg                      : 1
 AMaxBT                       : 1
 
+# Encoder optimization tools
+AffineAmvrEncOpt             : 0
+
 ### DO NOT ADD ANYTHING BELOW THIS LINE ###
 ### DO NOT DELETE THE EMPTY LINE BELOW ###
 
diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg
index f3404e3f2b958461236f98e56e0387d315808658..b15a43887296c87133f8a27371943a48d8aaeea7 100644
--- a/cfg/encoder_randomaccess_vtm.cfg
+++ b/cfg/encoder_randomaccess_vtm.cfg
@@ -117,7 +117,6 @@ CrQpOffset                          : 1
 #============ NEXT ====================
 
 # General
-LargeCTU                     : 1      # Large CTU
 CTUSize                      : 128
 LCTUFast                     : 1
 QuadtreeTULog2MaxSize        : 6
@@ -129,17 +128,17 @@ MinQTNonISlice               : 8
 MaxBTDepth                   : 3
 MaxBTDepthISliceL            : 3
 MaxBTDepthISliceC            : 3
-MTT                          : 1
 
 MTS                          : 1
 MTSIntraMaxCand              : 3
 MTSInterMaxCand              : 4
+SBT                          : 1
 Affine                       : 1
 SubPuMvp                     : 1
 MaxNumMergeCand              : 6
 LMChroma                     : 1      # use CCLM only
 DepQuant                     : 1
-IMV                          : 2
+IMV                          : 1
 ALF                          : 1
 GBi                          : 1 
 GBiFast                      : 1
@@ -147,12 +146,19 @@ BIO                          : 1
 MHIntra                      : 1
 Triangle                     : 1
 IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 1
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
+DMVR                         : 1
 
 # Fast tools
 PBIntraFast                  : 1
 FastMrg                      : 1
 AMaxBT                       : 1
 
+# Encoder optimization tools
+AffineAmvrEncOpt             : 1
+
 ### DO NOT ADD ANYTHING BELOW THIS LINE ###
 ### DO NOT DELETE THE EMPTY LINE BELOW ###
 
diff --git a/cfg/per-class/classF.cfg b/cfg/per-class/classF.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..52ae3dfa2c608bae4325b0c19695db04bd0ce589
--- /dev/null
+++ b/cfg/per-class/classF.cfg
@@ -0,0 +1,3 @@
+IBC : 1
+HashME : 1
+
diff --git a/doc/Makefile b/doc/Makefile
index 084c4f3fdd34c793dea857b04f054dae1638cf10..c1f5a58b96c11088f7c284b98d9ab58f46b1444d 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -6,8 +6,13 @@ LATEX:=$(shell which xelatex || which pdflatex || which latex)
 BIBTOOL:=$(shell which bibtool || echo \\\# skipping bibtool )
 BIBTOOL_DB=~/mpeg/doc/bib/jctvc.bib
 
+LATEXFLAGS:="-shell-escape"
+
 all: $(DOCNUM).pdf
 
+clean:
+	rm -fr _minted-software-manual software-manual.bbl software-manual.blg software-manual.lot software-manual.out software-manual.log software-manual.toc software-manual.aux software-manual.pdf
+
 %.aux: %.tex
 	$(LATEX) $(LATEXFLAGS) $<
 
diff --git a/doc/figures/YUView.png b/doc/figures/YUView.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b6b81f0954adc8df0fa95e4b10f78c337e2667c
Binary files /dev/null and b/doc/figures/YUView.png differ
diff --git a/doc/gop-structure-example.pdf b/doc/figures/gop-structure-example.pdf
similarity index 100%
rename from doc/gop-structure-example.pdf
rename to doc/figures/gop-structure-example.pdf
diff --git a/doc/figures/raceHorsesShot2MotionVectors.png b/doc/figures/raceHorsesShot2MotionVectors.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a35a3928103d6ac5f052bbd5fdacb2ed283b084
Binary files /dev/null and b/doc/figures/raceHorsesShot2MotionVectors.png differ
diff --git a/doc/figures/raceHorsesShot3SkipFlag.png b/doc/figures/raceHorsesShot3SkipFlag.png
new file mode 100644
index 0000000000000000000000000000000000000000..b4b50ee752d19b94ad1620c5174521e528850785
Binary files /dev/null and b/doc/figures/raceHorsesShot3SkipFlag.png differ
diff --git a/doc/jvetdoc.cls b/doc/jvetdoc.cls
new file mode 100644
index 0000000000000000000000000000000000000000..bdc22890e30fb89bfc9ac4a60b0b17d920c2af7b
--- /dev/null
+++ b/doc/jvetdoc.cls
@@ -0,0 +1,148 @@
+%%
+%% jvetdoc: Copyright (c) 2011 BBC Research & Development
+%% All rights reserved.
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% Neither the names of the BBC, 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.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesClass{jvetdoc}[2019/01/31 JVET document class]
+
+\LoadClassWithOptions{article}
+
+% typeset using Times New Roman
+\RequirePackage{ifxetex}
+\ifxetex
+  % use the correct fonts when using XeTeX
+  \RequirePackage{fontspec}
+  \defaultfontfeatures{Mapping=tex-text}
+  \setmainfont{Times New Roman}
+\else
+  \RequirePackage{times}
+\fi
+
+% expand the margins
+\RequirePackage{geometry}
+\geometry{tmargin=1.6cm,lmargin=1in,rmargin=2.5cm,bmargin=1in,nohead}
+
+% require graphicx for loading the logos in the header
+\RequirePackage{graphicx}
+
+% don't number the abstract
+\renewenvironment{abstract}{\section*{Abstract}}{}
+
+% format the date in iso style
+\RequirePackage{datetime}
+\renewcommand{\dateseparator}{-}
+\newdateformat{JVET@yyyymmdddate}{%
+	\THEYEAR\dateseparator\twodigit{\THEMONTH}\dateseparator\twodigit{\THEDAY}}
+
+% all pages only have a footer
+\RequirePackage{fancyhdr}
+\pagestyle{fancy}
+\renewcommand{\headrulewidth}{0pt}
+\fancyhead{}
+\cfoot{\thepage}
+\rfoot{Date saved: \JVET@yyyymmdddate\today}
+
+% macros for document metadata
+\RequirePackage[normalem]{ulem}
+\def\@jvetdocnum{\uline{xxx}}
+\def\@jvetdocstatus{\uline{TODO: Add \texttt{\textbackslash{}jvetdocstatus}}}
+\def\@jvetdocpurpose{\uline{TODO: Add \texttt{\textbackslash{}jvetdocpurpose}}}
+\def\@jvetdocsource{\uline{TODO: Add \texttt{\textbackslash{}jvetdocsource}}}
+\def\@jvetmeeting{\uline{TODO: Add \texttt{\textbackslash{}jvetmeeting}}}
+\newcommand{\jvetdocnum}[1]{\def\@jvetdocnum{\mbox{#1}}}
+\newcommand{\jvetdocstatus}[1]{\def\@jvetdocstatus{\mbox{#1}}}
+\newcommand{\jvetdocpurpose}[1]{\def\@jvetdocpurpose{\mbox{#1}}}
+\newcommand{\jvetdocsource}[1]{\def\@jvetdocsource{\mbox{#1}}}
+\newcommand{\jvetmeeting}[1]{\def\@jvetmeeting{\mbox{#1}}}
+
+% affiliation block in the author list
+\newenvironment{affiliation}{%
+	\begin{tabular}[t]{@{}>{\renewcommand{\\}{, }}l@{}}%
+}{%
+	\end{tabular}%
+}
+
+\RequirePackage{array}
+
+\RequirePackage{ifthen}
+\newcounter{jvet@author@column}
+\newcommand{\@jvet@switch@author@column}{%
+	\ifthenelse{\value{jvet@author@column} = 1}{%
+		% do nothing
+	}{%
+		\addtocounter{jvet@author@column}{1}%
+		&
+	}%
+}
+
+\newcommand*{\email}[1]{\@jvet@switch@author@column\textit{#1}}
+\newcommand*{\tel}[1]{\@jvet@switch@author@column\textrm{#1}}
+
+% Make a title at the top of the current page.
+\renewcommand\maketitle{%
+	% none of the title is put in the header (it is too difficult to
+	% make the page match the word style in this case)
+	\vspace*{-1.7cm}
+	\begin{raggedright}
+	\rule{0pt}{0.74cm}% strut incase images aren't loaded
+	\IfFileExists{logos/itu}{\includegraphics[height=0.74cm]{logos/itu}}{}
+	\IfFileExists{logos/iso}{\includegraphics[height=0.74cm]{logos/iso}}{}
+	\IfFileExists{logos/iec}{\includegraphics[height=0.74cm]{logos/iec}}{}
+	\\
+	\textbf{Joint Video Experts Team (JVET)}\\[0ex]
+	\textbf{of ITU-T SG16 WP3 and ISO/IEC JTC1/SC29/WG11}
+		\hfill Document: JVET-\@jvetdocnum\\[0ex]
+	\@jvetmeeting
+
+	\vspace{0.5\baselineskip}
+
+	\newcommand{\@strutb}{\rule{0pt}{2.5ex}}
+	\begin{tabular}{lp{0.78\textwidth}}
+	\@strutb \it Title: & \@title \\
+	\@strutb \it Status: & \@jvetdocstatus \\
+	\@strutb \it Purpose: & \@jvetdocpurpose \\
+	\@strutb \it Author(s): & %
+		\setcounter{jvet@author@column}{0}
+		\let\@and\\
+		\renewcommand{\and}{\@and\setcounter{jvet@author@column}{0}}
+		\newcommand{\@NLtoPAR}{\renewcommand{\\}{\par}}
+		\begin{tabular}[t]{@{}>{\@NLtoPAR}p{3in}|>{\@NLtoPAR}p{2in}@{}}%
+			\@author
+		\end{tabular}\\
+	\@strutb \it Source: & \@jvetdocsource \\
+	\end{tabular}
+	\end{raggedright}
+
+	% draw a short horizontal line to delimit the title from body
+	{\center\rule{0.35\textwidth}{1pt}\\}
+}
+
+%
+\RequirePackage{parskip}
+\RequirePackage[compact]{titlesec}
+%\titlespacing{\section}{0pt}{*0}{*0}
+%\titlespacing{\subsection}{0pt}{*0}{*0}
+%\titlespacing{\subsubsection}{0pt}{*0}{*0}
+
+\titlespacing*{\section}
+{0pt}{5ex}{2ex}
+\titlespacing*{\subsection}
+{0pt}{5ex}{2ex}
+\titlespacing*{\subsection}
+{0pt}{5ex}{2ex}
diff --git a/doc/mainpage.h b/doc/mainpage.h
index 4a55ec87e5cc1595a4ecaae6d5fa5e40e18d7d0d..efe90264a414e5bca1df89df715511d12fd8c854 100644
--- a/doc/mainpage.h
+++ b/doc/mainpage.h
@@ -7,8 +7,8 @@
  *
  * \section Introduction
  *
- *  This is the doxygen generated documentation of the HEVC HM reference software. 
- *     
+ *  This is the doxygen generated documentation of the HEVC HM reference software.
+ *
  *  For detailed information see the sub-pages of this site.
  *
  *  For information on the <b>subversion repositories</b> and the <b>software manual</b> see
@@ -22,7 +22,7 @@
  * 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.  
+ * granted under this license.
  *
  * Copyright (c) 2010-2019, ITU/ISO/IEC
  * All rights reserved.
diff --git a/doc/software-manual.pdf b/doc/software-manual.pdf
index 0b4925cf32a94097c096cdc47707a5dbbebe3637..34b144cc8b9a980a393cc3c1a4a8bba40a247126 100644
Binary files a/doc/software-manual.pdf and b/doc/software-manual.pdf differ
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 0cd31316c6225c0c1924a52b909b8e5b26588341..e816dbe34f6722ddf22932558b173a04cfbcabca 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -1,4 +1,4 @@
-\documentclass[a4paper,11pt]{jctvcdoc}
+\documentclass[a4paper,11pt]{jvetdoc}
 
 \usepackage{geometry}[2010/02/12]
 
@@ -22,6 +22,18 @@
 \usepackage{algorithm2e}
 \usepackage{amsmath}
 
+\urlstyle{same}
+
+% code highlighting
+\usepackage{minted,xcolor}
+\definecolor{bggray}{gray}{0.95}
+\setminted{
+bgcolor=bggray,
+xleftmargin=3ex,
+breaklines=true,
+fontsize=\footnotesize}
+
+
 \usepackage[strings]{underscore}
 \usepackage{csquotes}
 \MakeOuterQuote{"}
@@ -72,7 +84,7 @@
 }
 
 \newenvironment{OptionTableNoShorthand}[2]{%
-	\footnotesize
+	\scriptsize
 	\def\arraystretch{1.8}
 	\clearOptions
 	\begin{longtable}{l<{\makecell[tl]{\optOption}}%
@@ -105,7 +117,7 @@
 }
 
 \newenvironment{SEIListTable}[1]{%
-	\footnotesize
+	\scriptsize
 	\def\arraystretch{1.8}
 	\clearOptions
 	\begin{longtable}{c<{\makecell[tl]{\optOption}}%
@@ -138,7 +150,7 @@
 }
 
 \newenvironment{MacroTable}[1]{%
-	\footnotesize
+	\scriptsize
 	\def\arraystretch{1.3}
 	\clearOptions
 	\begin{longtable}{lcp{0.5\textwidth}}
@@ -166,7 +178,7 @@
 	\end{longtable}
 }
 
-\title{HM Software Manual}
+\title{VTM Software Manual}
 \author{%
 	Frank Bossen
 	\email{frank@bossentech.com}
@@ -174,36 +186,37 @@
 	David Flynn
 	\email{dflynn@blackberry.com}
 	\and
-  Karl Sharman
+	Xiang Li
+	\email{xlxiangli@tencent.com}
+	\and
+	Karl Sharman
 	\email{karl.sharman@eu.sony.com}
 	\and
 	Karsten S\"uhring
 	\email{karsten.suehring@hhi.fraunhofer.de}
 }
 
-\jctvcmeeting{}
-\jctvcdocnum{Software Manual}
-\jctvcdocstatus{Software AHG working document}
-\jctvcdocpurpose{Information}
-\jctvcdocsource{AHG chairs}
+\jvetmeeting{}
+\jvetdocnum{Software Manual}
+\jvetdocstatus{Software AHG working document}
+\jvetdocpurpose{Information}
+\jvetdocsource{AHG chairs}
 
 \begin{document}
 \maketitle
 \begin{abstract}
-This document is a user manual describing usage of reference software
-for the HEVC project. It applies to version 16.13
-of the software.
+This document is a user manual describing usage of the VTM reference software
+for the VVC project. It applies to version 4.0 of the software.
 \end{abstract}
 
 \tableofcontents
 \listoftables
 
 
-
 \section{General Information}
 Reference software is being made available to provide a reference
-implementation of the HEVC standard being developed by the Joint
-Collaborative Team on Video Coding (JCT-VC) regrouping experts from
+implementation of the HEVC standard being developed by the Joint 
+Video Experts Team (JVET) regrouping experts from
 ITU-T SG 16 and ISO/IEC SC29 WG11. One of the main goals of the
 reference software is to provide a basis upon which to conduct
 experiments in order to determine which coding tools provide desired
@@ -211,61 +224,165 @@ coding performance. It is not meant to be a particularly efficient
 implementation of anything, and one may notice its apparent
 unsuitability for a particular use. It should not be construed to be a
 reflection of how complex a production-quality implementation of a
-future HEVC standard would be.
+future VVC standard would be.
 
 This document aims to provide guidance on the usage of the reference
 software. It is widely suspected to be incomplete and suggestions for
 improvements are welcome. Such suggestions and general inquiries may be
-sent to the general JCT-VC email reflector on
-\url{jct-vc@lists.rwth-aachen.de} (registration required).
+sent to the general JVET email reflector on
+\url{https://lists.rwth-aachen.de/postorius/lists/jvet.lists.rwth-aachen.de/} 
+(registration required).
 
 \subsection*{Bug reporting}
-Bugs should be reported on the issue tracker set up at
-\url{http://hevc.kw.bbc.co.uk/trac/}
+Bugs should be reported on the issue tracker set up at:
+
+\url{https://jvet.hhi.fraunhofer.de/trac/vvc/}
 
 \section{Installation and compilation}
-The software may be retrieved from one of the following SVN servers
-(mirrored):
-\begin{itemize}
-\item \url{https://hevc.hhi.fraunhofer.de/svn/svn_HEVCSoftware/}
-\item \url{svn://hevc.kw.bbc.co.uk/svn/jctvc-hm/}
-\end{itemize}
+The software may be retrieved from the GitLab server located at:
 
-Table~\ref{tab:project-files} enumerates various project files that are
-provided for development environments.
+\url{https://vcgit.hhi.fraunhofer.de/jvet/VVCSoftware_VTM}
+
+Table~\ref{tab:project-files} lists the compiler environments and versions 
+for which building the software is tested.
+
+Note that the software makes use of C++11 language features, which may not
+be available in older compilers.
 
 \begin{table}[ht]
-\footnotesize
-\caption{Available project files}
+\caption{Supported compilers}
 \label{tab:project-files}
 \centering
 \begin{tabular}{ll}
 \hline
- \thead{Environment} &
- \thead{Location of project file} \\
-% Environment          & Location of project file \\
+ \thead{Compiler environment} &
+ \thead{Versions} \\
 \hline
-MS Visual Studio 2008 (VC9)   & build/HM_vc9.sln \\
-MS Visual Studio 2010 (VC10)  & build/HM_vc2010.sln \\
-MS Visual Studio 2012 (VC11)  & build/HM_vc2012.sln \\
-MS Visual Studio 2013 (VC12)  & build/HM_vc2013.sln \\
-Xcode                         & HM.xcodeproj \\
-Eclipse                       & .project .cproject \\
-make/gcc (e.g. Linux)         & build/linux/makefile \\
+MS Visual Studio  & 2015 and 2017 \\
+GCC               & 5.4 and 7.3 \\
+Xcode/clang       & latest \\
 \hline
 \end{tabular}
 \end{table}
 
-For encoding large picture sizes (like UHDTV) it is strongly advised to build 64-bit
-binaries and to use a 64-bit OS. This will allow the software to use more than 2GB of RAM.
+By default the software is built as 64-bit binaries to be used on a 64-bit OS. 
+This allows the software to use more than 2GB of RAM.
+
+The software uses CMake to create platform-specific build files. 
+
+\subsection {Build instructions for plain CMake (suggested)}
+
+\textbf{Note:} A working CMake installation is required for building the software.
+
+CMake generates configuration files for the compiler environment/development
+environment on each platform. The following is a list of examples for Windows
+(MS Visual Studio), macOS (Xcode) and Linux (make).
+
+Open a command prompt on your system and change into the root directory
+of this project.
+
+Create a build directory in the root directory:
+\begin{minted}{bash}
+mkdir build 
+\end{minted}
+Use one of the following CMake commands, based on your platform. Feel free to change the 
+commands to satisfy your needs.
+
+\textbf{Windows Visual Studio 2015 64 Bit:}
+\begin{minted}{bash}
+cd build
+cmake .. -G "Visual Studio 14 2015 Win64"
+\end{minted}
+Then open the generated solution file in MS Visual Studio.
+
+\textbf{macOS Xcode:}
+\begin{minted}{bash}
+cd build
+cmake .. -G "Xcode"
+\end{minted}
+Then open the generated work space in Xcode.
+
+\textbf{Linux}
+
+For generating Linux Release Makefile:
+\begin{minted}{bash}
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release
+\end{minted}
+For generating Linux Debug Makefile:
+\begin{minted}{bash}
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Debug
+\end{minted}
+Then type
+\begin{minted}{bash}
+make -j
+\end{minted}
+to build the software.
+
+For more details, refer to the CMake documentation: \url{https://cmake.org/cmake/help/latest/}
+
+\subsection {Build instructions for make}
+
+\textbf{Note:}
+The build instructions in this section require the make tool and Python
+to be installed, which are part of usual Linux and macOS environments. 
+See section \ref{windowsinstall} for installation instruction for Python 
+and GnuWin32 on Windows.
+
+Open a command prompt on your system and change into the root directory
+of this project.
+
+To use the default system compiler simply call:
+\begin{minted}{bash}
+make all
+\end{minted}
+For MSYS2 and MinGW:
+Open an MSYS MinGW 64-Bit terminal and change into the root directory
+of this project.
+
+Call:
+\begin{minted}{bash}
+make all toolset=gcc
+\end{minted}
+
+\subsection{Tool Installation on Windows}
+\label{windowsinstall}
+
+Download CMake: \url{http://www.cmake.org/} and install it.
+
+Python and GnuWin32 are not mandatory, but they simplify the build process for the user.
+
+\begin{table}[ht]
+\footnotesize
+\centering
+\begin{tabular}{ll}
+\hline
+Python     &    \url{https://www.python.org/downloads/release/python-371/} \\
+GnuWin32   &    \url{https://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/0.6.30/GetGnuWin32-0.6.3.exe/download} \\
+\hline
+\end{tabular}
+\end{table}
+
+To use MinGW, install MSYS2:
+\url{http://repo.msys2.org/distrib/msys2-x86_64-latest.exe}
+
+Installation instructions:
+\url{https://www.msys2.org/}
+
+Install the needed toolchains:
+\begin{minted}{bash}
+pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain git subversion mingw-w64-i686-cmake mingw-w64-x86_64-cmake
+\end{minted}
 
 %%%%
 %%%%
 %%%%
 \section{Using the encoder}
-\begin{verbatim}
+
+\begin{minted}{bash}
 TAppEncoder 	[--help] [-c config.cfg] [--parameter=value]
-\end{verbatim}
+\end{minted}
 
 \begin{table}[ht]
 \footnotesize
@@ -417,7 +534,7 @@ its list of reference pictures is \verb|-1 1|.
 \caption{A GOP structure}
 \label{fig:gop-example}
 \centering
-\includegraphics[width=0.7\textwidth]{gop-structure-example}
+\includegraphics[width=0.7\textwidth]{figures/gop-structure-example}
 \end{figure}
 
 Inter RPS prediction may be used for Frame2, Frame3 and Frame4, hence
@@ -1914,6 +2031,63 @@ RCInitialCpbFullness should be smaller than or equal to 1.
 \\
 \end{OptionTableNoShorthand}
 
+
+
+%%
+%% Encoder debug parameters
+%%
+\begin{OptionTableNoShorthand}{Encoder debug parameters}{tab:encoder-debugging}
+
+\Option{DebugBitstream/DecodeBitstream1} &
+%\ShortOption{\None} &
+\Default{} &
+Specifies the first bit stream to be read until a pre-defined switch point is encountered.
+\\
+
+\Option{DecodeBitstream2} &
+%\ShortOption{\None} &
+\Default{} &
+Specifies the second bit stream, to be read after the first random access point after a QP switch point (specified using SwitchPOC and SwitchQP).
+\\
+
+\Option{DebugPOC} &
+%\ShortOption{\None} &
+\Default{-1} &
+Specifies a POC, at which a bit stream specified using DebugBitstream or DecodeBitstream1 is no longer read, but rather normal encoding is started.
+\\
+
+\Option{DebugCTU} &
+%\ShortOption{\None} &
+\Default{-1} &
+When the POC is encountered at which normal encoding is to be resumed, if set, this option specifies that CTUs up to the specified CTU(in raster scan addressing order are to be read from the specified bit stream, after which normal encoding is started the specified CTU.
+\\
+
+\Option{SwitchPOC} &
+%\ShortOption{\None} &
+\Default{-1} &
+Specifies a POC, at which the specified bit stream is no longer read, but rather normal encoding is started.
+\\
+
+\Option{SwitchDQP} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies a QP offset to be applied when normal encoding is started as specified by SwitchPOC.
+\\
+
+\Option{FastForwardToPOC} &
+%\ShortOption{\None} &
+\Default{0} &
+When encoding a bit streams, all frames that are not references including transitive references to the specified POC are skipped.
+\\
+\Option{StopAfterFFtoPOC} &
+%\ShortOption{\None} &
+\Default{false} &
+If enabled, causes the encoder to not encode any frame after the frame specified by FastForwardToPOC option, in encoding order.
+\\
+\end{OptionTableNoShorthand}
+
+
+
 %%
 %% VUI parameters
 %%
@@ -2879,9 +3053,9 @@ Numerous constants that guard individual adoptions are defined within
 \clearpage
 \section{Using the decoder}
 \subsection{General}
-\begin{verbatim}
+\begin{minted}{bash}
 TAppDecoder -b str.bin -o dec.yuv [options]
-\end{verbatim}
+\end{minted}
 
 \begin{OptionTableNoShorthand}{Decoder options}{tab:decoder-options}
 \Option{(--help)} &
@@ -3032,7 +3206,7 @@ way, which in turn can be loaded into a suitable YUV player for overlay of the
 reconstructed YUV sequence, or can be used for statistical analysis at a
 selectable scope (e.g. block/picture/sequence level). An example implementation
 for such visualization is available with the open-source YUView player
-(https://github.com/IENT/YUView). 
+(\url{https://github.com/IENT/YUView}). 
 
 
 \subsection{Usage}
@@ -3070,7 +3244,7 @@ Specifies which traces should be saved, and for which POCs.
 \end{OptionTableNoShorthand}
 
 Concrete examples of calls for  generating a block statistics file are:
-\begin{verbatim}
+\begin{minted}{bash}
 bin/DecoderAppStatic -b str/BasketballDrive_1920x1080_QP37.vvc \
     --TraceFile="stats/BasketballDrive_1920x1080_QP37_coded.vtmbmsstats" \
     --TraceRule="D_BLOCK_STATISTICS_CODED:poc>=0"
@@ -3078,7 +3252,7 @@ bin/DecoderAppStatic -b str/BasketballDrive_1920x1080_QP37.vvc \
 bin/DecoderAppStatic -b str/BasketballDrive_1920x1080_QP37.vvc \
     --TraceFile="stats/BasketballDrive_1920x1080_QP37_all.vtmbmsstats" \
     --TraceRule="D_BLOCK_STATISTICS_ALL:poc>=0"   
-\end{verbatim}
+\end{minted}
 
 
 \subsection{Block statistics file formats}
@@ -3187,16 +3361,16 @@ In order to add further block statistics, do the following:
 \begin{description}
 \item[source/Lib/CommonLib/dtrace_blockstatistics.h]
   Add your statistic to the BlockStatistic enum:	
-\begin{verbatim}
+\begin{minted}{c++}
 enum class BlockStatistic {
   // general
   PredMode,
   PartSize,
   Depth,
-\end{verbatim}
+\end{minted}
   
 Further, add your statistic to the map blockstatistic2description:
-\begin{verbatim}
+\begin{minted}{c++}
 static const std::map<BlockStatistic, 
   std::tuple<std::string, BlockStatisticType, std::string>> 
   blockstatistic2description =
@@ -3211,7 +3385,7 @@ static const std::map<BlockStatistic,
     std::tuple<std::string, BlockStatisticType, std::string>
     {"MVL0", BlockStatisticType::Vector, "Scale: 4"}},
   YOURS
-\end{verbatim}
+\end{minted}
 
 
 \item[source/Lib/CommonLib/dtrace_blockstatistics.cpp] All code for
@@ -3219,28 +3393,28 @@ static const std::map<BlockStatistic,
   getAndStoreBlockStatistics. This function is called once for each
   CTU, after it has been en/decoded. The following macros have been
   defined to facilitate writing of block statistics:
-\begin{verbatim}
+\begin{minted}{c++}
 DTRACE_BLOCK_SCALAR(ctx,channel,cs_cu_pu,stat_type,val)   
 DTRACE_BLOCK_SCALAR_CHROMA(ctx,channel,cs_cu_pu,stat_type,val)
 DTRACE_BLOCK_VECTOR(ctx,channel,cu_pu,stat_type,v_x,v_y)    
 DTRACE_BLOCK_AFFINETF(ctx,channel,pu,stat_type,v_x0,v_y0,v_x1,v_y1,v_x2,v_y2) 
-\end{verbatim}
+\end{minted}
 
 An example:
-\begin{verbatim}
+\begin{minted}{c++}
 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, 
   cu, GetBlockStatisticName(BlockStatistic::PredMode), cu.predMode);
-\end{verbatim}
+\end{minted}
 
 
 \item[Block statistics for debugging] The statistics can also be used
   to write out other data, not just syntax elements. Add your
   statistics to dtrace_blockstatistics.h. Where it should be used the
   following headers have to be included:
-\begin{verbatim}
+\begin{minted}{c++}
 #include "dtrace_next.h"
 #include "dtrace_blockstatistics.h"
-\end{verbatim}
+\end{minted}
 \end{description}
 
 \end{document}
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 6afd8db7333f1376da1346246b9cd70f6ae5befa..26753f9411d84dc9fa783fe02ec8c699d18b9206 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -215,20 +215,14 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setMinQTSizes                                        ( m_uiMinQT );
   m_cEncLib.setMaxBTDepth                                        ( m_uiMaxBTDepth, m_uiMaxBTDepthI, m_uiMaxBTDepthIChroma );
   m_cEncLib.setDualITree                                         ( m_dualTree );
-  m_cEncLib.setLargeCTU                                          ( m_LargeCTU );
   m_cEncLib.setSubPuMvpMode                                      ( m_SubPuMvpMode );
   m_cEncLib.setAffine                                            ( m_Affine );
   m_cEncLib.setAffineType                                        ( m_AffineType );
   m_cEncLib.setBIO                                               (m_BIO);
-  m_cEncLib.setDisableMotionCompression                          ( m_DisableMotionCompression );
-  m_cEncLib.setMTTMode                                           ( m_MTT );
   m_cEncLib.setUseLMChroma                                       ( m_LMChroma );
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
   m_cEncLib.setCclmCollocatedChromaFlag                          ( m_cclmCollocatedChromaFlag );
 #endif
-#if ENABLE_WPP_PARALLELISM
-  m_cEncLib.setUseAltDQPCoding                                   ( m_AltDQPCoding );
-#endif
 #if JVET_M0464_UNI_MTS
   m_cEncLib.setIntraMTS                                          ( m_MTS & 1 );
   m_cEncLib.setIntraMTSMaxCand                                   ( m_MTSIntraMaxCand );
@@ -239,6 +233,12 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setFastIntraEMT                                      ( m_FastEMT & m_EMT & 1 );
   m_cEncLib.setInterEMT                                          ( ( m_EMT >> 1 ) & 1 );
   m_cEncLib.setFastInterEMT                                      ( ( m_FastEMT >> 1 ) & ( m_EMT >> 1 ) & 1 );
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  m_cEncLib.setImplicitMTS                                       ( m_MTSImplicit );
+#endif
+#if JVET_M0140_SBT
+  m_cEncLib.setUseSBT                                            ( m_SBT );
 #endif
   m_cEncLib.setUseCompositeRef                                   ( m_compositeRefEnabled );
   m_cEncLib.setUseGBi                                            ( m_GBi );
@@ -254,10 +254,25 @@ void EncApp::xInitLibCfg()
       m_cEncLib.setLadfIntervalLowerBound(m_LadfIntervalLowerBound[k], k);
     }
   }
-#endif  
+#endif
   m_cEncLib.setUseMHIntra                                        ( m_MHIntra );
   m_cEncLib.setUseTriangle                                       ( m_Triangle );
+#if JVET_M0253_HASH_ME
+  m_cEncLib.setUseHashME                                         ( m_HashME );
+#endif
 
+#if JVET_M0255_FRACMMVD_SWITCH
+  m_cEncLib.setAllowDisFracMMVD                                  ( m_allowDisFracMMVD );
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  m_cEncLib.setUseAffineAmvr                                     ( m_AffineAmvr );
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  m_cEncLib.setUseAffineAmvrEncOpt                               ( m_AffineAmvrEncOpt );
+#endif
+#if JVET_M0147_DMVR
+  m_cEncLib.setDMVR                                              ( m_DMVR );
+#endif
   m_cEncLib.setIBCMode                                           ( m_IBCMode );
   m_cEncLib.setIBCLocalSearchRangeX                              ( m_IBCLocalSearchRangeX );
   m_cEncLib.setIBCLocalSearchRangeY                              ( m_IBCLocalSearchRangeY );
@@ -534,6 +549,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setForceDecodeBitstream1                             ( m_forceDecodeBitstream1 );
   m_cEncLib.setStopAfterFFtoPOC                                  ( m_stopAfterFFtoPOC );
   m_cEncLib.setBs2ModPOCAndType                                  ( m_bs2ModPOCAndType );
+#if JVET_M0055_DEBUG_CTU
+  m_cEncLib.setDebugCTU                                          ( m_debugCTU );
+#endif
 #if ENABLE_SPLIT_PARALLELISM
   m_cEncLib.setNumSplitThreads                                   ( m_numSplitThreads );
   m_cEncLib.setForceSingleSplitThread                            ( m_forceSplitSequential );
@@ -545,6 +563,12 @@ void EncApp::xInitLibCfg()
 
 #endif
   m_cEncLib.setUseALF                                            ( m_alf );
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cEncLib.setReshaper                                          ( m_lumaReshapeEnable );
+  m_cEncLib.setReshapeSignalType                                 ( m_reshapeSignalType );
+  m_cEncLib.setReshapeIntraCMD                                   ( m_intraCMD );
+  m_cEncLib.setReshapeCW                                         ( m_reshapeCW );
+#endif
 }
 
 void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 10241f5caae994d3e4c68d692541232a9ccedee5..c3c44085eabd364146d58f33b8c248b232570210 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -799,7 +799,6 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("InterlacedSource",                                m_interlacedSourceFlag,                           false, "Indicate that source is interlaced")
   ("NonPackedSource",                                 m_nonPackedConstraintFlag,                        false, "Indicate that source does not contain frame packing")
   ("FrameOnly",                                       m_frameOnlyConstraintFlag,                        false, "Indicate that the bitstream contains only frames")
-  ("MTT",                                             m_MTT,                                               0u, "Multi type tree type (0: off, 1:QTBT + triple split) [default: 0]")
   ("CTUSize",                                         m_uiCTUSize,                                       128u, "CTUSize (specifies the CTU size if QTBT is on) [default: 128]")
   ("EnablePartitionConstraintsOverride",              m_SplitConsOverrideEnabledFlag,                    true, "Enable partition constraints override")
   ("MinQTISlice",                                     m_uiMinQT[0],                                        8u, "MinQTISlice")
@@ -811,20 +810,14 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("MaxBTDepthISliceL",                               m_uiMaxBTDepthI,                                     3u, "MaxBTDepthISliceL")
   ("MaxBTDepthISliceC",                               m_uiMaxBTDepthIChroma,                               3u, "MaxBTDepthISliceC")
   ("DualITree",                                       m_dualTree,                                       false, "Use separate QTBT trees for intra slice luma and chroma channel types")
-  ("LargeCTU",                                        m_LargeCTU,                                       false, "Enable large CTU (0:off, 1:on)  [default: off]")
   ("SubPuMvp",                                       m_SubPuMvpMode,                                       0, "Enable Sub-PU temporal motion vector prediction (0:off, 1:ATMVP, 2:STMVP, 3:ATMVP+STMVP)  [default: off]")
   ("Affine",                                         m_Affine,                                         false, "Enable affine prediction (0:off, 1:on)  [default: off]")
   ("AffineType",                                     m_AffineType,                                     true,  "Enable affine type prediction (0:off, 1:on)  [default: on]" )
   ("BIO",                                            m_BIO,                                             false, "Enable bi-directional optical flow")
-  ("DisableMotCompression",                           m_DisableMotionCompression,                       false, "Disable motion data compression for all modes")
-  ("IMV",                                             m_ImvMode,                                            2, "Adaptive MV precision Mode (IMV)\n"
-                                                                                                               "\t0: disabled IMV\n"
-                                                                                                               "\t1: IMV default (Full-Pel)\n"
-                                                                                                               "\t2: IMV Full-Pel and 4-PEL\n")
+  ("IMV",                                             m_ImvMode,                                            1, "Adaptive MV precision Mode (IMV)\n"
+                                                                                                               "\t0: disabled\n"
+                                                                                                               "\t1: enabled (Full-Pel and 4-PEL)\n")
   ("IMV4PelFast",                                     m_Imv4PelFast,                                        1, "Fast 4-Pel Adaptive MV precision Mode 0:disabled, 1:enabled)  [default: 1]")
-#if ENABLE_WPP_PARALLELISM
-  ("AltDQPCoding",                                    m_AltDQPCoding,                                   false, "Improved predictive delta-QP coding (0:off, 1:on)  [default: off]")
-#endif
   ("LMChroma",                                        m_LMChroma,                                           1, " LMChroma prediction "
                                                                                                                "\t0:  Disable LMChroma\n"
                                                                                                                "\t1:  Enable LMChroma\n")
@@ -852,6 +845,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     "\t1:  Enable fast methods only for Intra EMT\n"
     "\t2:  Enable fast methods only for Inter EMT\n"
     "\t3:  Enable fast methods for both Intra & Inter EMT\n")
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  ("MTSImplicit",                                     m_MTSImplicit,                                        0, "Enable implicit MTS (when explicit MTS is off)\n")
+#endif
+#if JVET_M0140_SBT
+  ( "SBT",                                            m_SBT,                                            false, "Enable Sub-Block Transform for inter blocks\n" )
 #endif
   ("CompositeLTReference",                            m_compositeRefEnabled,                            false, "Enable Composite Long Term Reference Frame")
   ("GBi",                                             m_GBi,                                            false, "Enable Generalized Bi-prediction(GBi)")
@@ -864,7 +863,22 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif
   ("MHIntra",                                         m_MHIntra,                                        false, "Enable MHIntra mode")
   ("Triangle",                                        m_Triangle,                                       false, "Enable triangular shape motion vector prediction (0:off, 1:on)")
+#if JVET_M0253_HASH_ME
+  ("HashME",                                          m_HashME,                                         false, "Enable hash motion estimation (0:off, 1:on)")
+#endif
 
+#if JVET_M0255_FRACMMVD_SWITCH
+  ("AllowDisFracMMVD",                                m_allowDisFracMMVD,                               false, "Disable fractional MVD in MMVD mode adaptively")
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  ("AffineAmvr",                                      m_AffineAmvr,                                     false, "Eanble AMVR for affine inter mode")
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  ("AffineAmvrEncOpt",                                m_AffineAmvrEncOpt,                               false, "Enable encoder optimization of affine AMVR")
+#endif
+#if JVET_M0147_DMVR
+  ("DMVR",                                            m_DMVR,                                           false, "Decoder-side Motion Vector Refinement")
+#endif
   ( "IBC",                                            m_IBCMode,                                           0u, "IBCMode (0x1:enabled, 0x0:disabled)  [default: disabled]")
   ( "IBCLocalSearchRangeX",                           m_IBCLocalSearchRangeX,                            128u, "Search range of IBC local search in x direction")
   ( "IBCLocalSearchRangeY",                           m_IBCLocalSearchRangeY,                            128u, "Search range of IBC local search in y direction")
@@ -877,7 +891,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("WrapAroundOffset",                                m_wrapAroundOffset,                                  0u, "Offset in luma samples used for computing the horizontal wrap-around position")
 
   // ADD_NEW_TOOL : (encoder app) add parsing parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  ("LumaReshapeEnable",                               m_lumaReshapeEnable,                              false, "Enable Reshaping for Luma Channel")
+  ("ReshapeSignalType",                               m_reshapeSignalType,                                 0u, "Input signal type: 0: SDR, 1:PQ, 2:HLG")
+  ("IntraCMD",                                        m_intraCMD,                                          0u, "IntraChroma MD: 0: none, 1:fixed to default wPSNR weight")
+#endif
   ("LCTUFast",                                        m_useFastLCTU,                                    false, "Fast methods for large CTU")
   ("FastMrg",                                         m_useFastMrg,                                     false, "Fast methods for inter merge")
   ("PBIntraFast",                                     m_usePbIntraFast,                                 false, "Fast assertion if the intra mode is probable")
@@ -1287,6 +1305,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("ForceSingleSplitThread",                          m_forceSplitSequential,                   false, "Force single thread execution even if taking the parallelized path")
   ("NumWppThreads",                                   m_numWppThreads,                              1, "Number of threads used to run WPP-style parallelization")
   ("NumWppExtraLines",                                m_numWppExtraLines,                           0, "Number of additional wpp lines to switch when threads are blocked")
+#if JVET_M0055_DEBUG_CTU
+  ("DebugCTU",                                        m_debugCTU,                                  -1, "If DebugBitstream is present, load frames up to this POC from this bitstream. Starting with DebugPOC-frame at CTUline containin debug CTU.")
+#endif
 #if ENABLE_WPP_PARALLELISM
   ("EnsureWppBitEqual",                               m_ensureWppBitEqual,                       true, "Ensure the results are equal to results with WPP-style parallelism, even if WPP is off")
 #else
@@ -1310,13 +1331,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   po::ErrorReporter err;
   const list<const char*>& argv_unhandled = po::scanArgv(opts, argc, (const char**) argv, err);
 
-  if (m_compositeRefEnabled) 
+  if (m_compositeRefEnabled)
   {
-    for (int i = 0; i < m_iGOPSize; i++) 
+    for (int i = 0; i < m_iGOPSize; i++)
     {
       m_GOPList[i].m_POC *= 2;
       m_GOPList[i].m_deltaRPS *= 2;
-      for (int j = 0; j < m_GOPList[i].m_numRefPics; j++) 
+      for (int j = 0; j < m_GOPList[i].m_numRefPics; j++)
       {
         m_GOPList[i].m_referencePics[j] *= 2;
       }
@@ -1831,6 +1852,14 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     }
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  m_reshapeCW.binCW.resize(3);
+  m_reshapeCW.rspFps = m_iFrameRate;
+  m_reshapeCW.rspIntraPeriod = m_iIntraPeriod;
+  m_reshapeCW.rspPicSize = m_iSourceWidth*m_iSourceHeight;
+  m_reshapeCW.rspFpsToIp = std::max(16, 16 * (int)(round((double)m_iFrameRate /16.0)));
+  m_reshapeCW.rspBaseQP = m_iQP;
+#endif
 #if ENABLE_TRACING
   g_trace_ctx = tracing_init(sTracingFile, sTracingRule);
   if( bTracingChannelsList && g_trace_ctx )
@@ -1861,9 +1890,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   }
 #else
  #if QP_SWITCHING_FOR_PARALLEL
-  if( m_LargeCTU && ( m_iQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
+  if( ( m_iQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
  #else
-  if( m_LargeCTU && ( ( int ) m_fQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
+  if( ( ( int ) m_fQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
  #endif
   {
     msg( WARNING, "*************************************************************************\n" );
@@ -1940,11 +1969,11 @@ bool EncAppCfg::xCheckParameter()
     xConfirmPara( m_numWppThreads > 1, "WPP-style parallelization only supported with NEXT profile" );
 #endif
     xConfirmPara( m_LMChroma, "LMChroma only allowed with NEXT profile" );
-    xConfirmPara( m_LargeCTU, "Large CTU is only allowed with NEXT profile" );
-    xConfirmPara( m_DisableMotionCompression, "Disable motion data compression only allowed with NEXT profile" );
-    xConfirmPara( m_MTT, "Multi type tree is only allowed with NEXT profile" );
     xConfirmPara( m_ImvMode, "IMV is only allowed with NEXT profile" );
     xConfirmPara(m_IBCMode, "IBC Mode only allowed with NEXT profile");
+#if JVET_M0253_HASH_ME
+    xConfirmPara( m_HashME, "Hash motion estimation only allowed with NEXT profile" );
+#endif
     xConfirmPara( m_useFastLCTU, "Fast large CTU can only be applied when encoding with NEXT profile" );
 #if JVET_M0464_UNI_MTS
     xConfirmPara( m_MTS, "MTS only allowed with NEXT profile" );
@@ -1958,13 +1987,13 @@ bool EncAppCfg::xCheckParameter()
     xConfirmPara( m_GBi, "GBi is only allowed with NEXT profile" );
     xConfirmPara( m_GBiFast, "GBiFast is only allowed with NEXT profile" );
     xConfirmPara( m_Triangle, "Triangle is only allowed with NEXT profile" );
+#if JVET_M0147_DMVR
+    xConfirmPara(m_DMVR, "DMVR only allowed with NEXT profile");
+#endif
     // ADD_NEW_TOOL : (parameter check) add a check for next tools here
   }
   else
   {
-#if ENABLE_WPP_PARALLELISM
-    xConfirmPara( !m_AltDQPCoding && ( m_numWppThreads + m_numWppExtraLines ) > 1, "Wavefront parallel encoding only supported with AltDQPCoding" );
-#endif
     if( m_depQuantEnabledFlag )
     {
       xConfirmPara( !m_useRDOQ || !m_useRDOQTS, "RDOQ and RDOQTS must be equal to 1 if dependent quantization is enabled" );
@@ -2021,8 +2050,8 @@ bool EncAppCfg::xCheckParameter()
 
 
   xConfirmPara( m_useAMaxBT && !m_SplitConsOverrideEnabledFlag, "AMaxBt can only be used with PartitionConstriantsOverride enabled" );
- 
-  
+
+
   xConfirmPara(m_bitstreamFileName.empty(), "A bitstream file name must be specified (BitstreamFile)");
   const uint32_t maxBitDepth=(m_chromaFormatIDC==CHROMA_400) ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]);
   xConfirmPara(m_bitDepthConstraint<maxBitDepth, "The internalBitDepth must not be greater than the bitDepthConstraint value");
@@ -2224,6 +2253,30 @@ bool EncAppCfg::xCheckParameter()
 #if SHARP_LUMA_DELTA_QP
   xConfirmPara( m_lumaLevelToDeltaQPMapping.mode && m_uiDeltaQpRD > 0,                      "Luma-level-based Delta QP cannot be used together with slice level multiple-QP optimization\n" );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_lumaLevelToDeltaQPMapping.mode && m_lumaReshapeEnable)
+  {
+    msg(WARNING, "For HDR-PQ, reshaper should be used mutual-exclusively with Luma-level-based Delta QP. If use luma DQP, turn reshaper off.\n");
+    m_lumaReshapeEnable = false;
+  }
+  if (!m_lumaReshapeEnable)
+  {
+    m_reshapeSignalType = RESHAPE_SIGNAL_NULL;
+    m_intraCMD = 0;
+  }
+  if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_PQ)
+  {
+    m_intraCMD = 1;
+  }
+  else if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_SDR)
+  {
+    m_intraCMD = 0;
+  }
+  else
+  {
+    m_lumaReshapeEnable = false;
+  }
+#endif
 
   xConfirmPara( m_cbQpOffset < -12,   "Min. Chroma Cb QP Offset is -12" );
   xConfirmPara( m_cbQpOffset >  12,   "Max. Chroma Cb QP Offset is  12" );
@@ -2262,13 +2315,6 @@ bool EncAppCfg::xCheckParameter()
 
   xConfirmPara( m_quadtreeTULog2MinSize < 2,                                        "QuadtreeTULog2MinSize must be 2 or greater." );
 
-  if( !m_LargeCTU )
-  {
-    xConfirmPara( m_uiMaxCUHeight > 64, "CTU bigger than 64 only allowed with large CTU." );
-    xConfirmPara( m_uiMaxCUWidth  > 64, "CTU bigger than 64 only allowed with large CTU." );
-    xConfirmPara( m_uiCTUSize > 64, "CTU bigger than 64 only allowed with large CTU." );
-  }
-
   if( m_profile == Profile::NEXT )
   {
     xConfirmPara( m_quadtreeTULog2MaxSize > 7,                                      "QuadtreeTULog2MaxSize must be 7 or smaller." );
@@ -2301,9 +2347,15 @@ bool EncAppCfg::xCheckParameter()
   xConfirmPara( m_MTS < 0 || m_MTS > 3, "MTS must be greater than 0 smaller than 4" );
   xConfirmPara( m_MTSIntraMaxCand < 0 || m_MTSIntraMaxCand > 5, "m_MTSIntraMaxCand must be greater than 0 and smaller than 6" );
   xConfirmPara( m_MTSInterMaxCand < 0 || m_MTSInterMaxCand > 5, "m_MTSInterMaxCand must be greater than 0 and smaller than 6" );
+#if JVET_M0303_IMPLICIT_MTS
+  xConfirmPara( m_MTS != 0 && m_MTSImplicit != 0, "Both explicit and implicit MTS cannot be enabled at the same time" );
+#endif
 #else
   xConfirmPara( m_EMT < 0 || m_EMT >3, "EMT must be 0, 1, 2 or 3" );
   xConfirmPara( m_FastEMT < 0 || m_FastEMT >3, "FEMT must be 0, 1, 2 or 3" );
+#if JVET_M0303_IMPLICIT_MTS
+  xConfirmPara( m_EMT != 0 && m_MTSImplicit != 0, "Both explicit and implicit MTS cannot be enabled at the same time" );
+#endif
 #endif
   if( m_usePCM)
   {
@@ -2887,7 +2939,7 @@ bool EncAppCfg::xCheckParameter()
 #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI
   xConfirmPara(m_preferredTransferCharacteristics > 255, "transfer_characteristics_idc should not be greater than 255.");
 #endif
-  xConfirmPara( unsigned(m_ImvMode) > 2, "ImvMode exceeds range (0 to 2)" );
+  xConfirmPara( unsigned(m_ImvMode) > 1, "ImvMode exceeds range (0 to 1)" );
   xConfirmPara( m_decodeBitstreams[0] == m_bitstreamFileName, "Debug bitstream and the output bitstream cannot be equal.\n" );
   xConfirmPara( m_decodeBitstreams[1] == m_bitstreamFileName, "Decode2 bitstream and the output bitstream cannot be equal.\n" );
   xConfirmPara(unsigned(m_LMChroma) > 1, "LMMode exceeds range (0 to 1)");
@@ -3127,14 +3179,8 @@ void EncAppCfg::xPrintParameter()
     }
     msg(VERBOSE, "SubPuMvp:%d+%d ", m_SubPuMvpMode & 1, (m_SubPuMvpMode & 2) == 2);
     msg( VERBOSE, "DualITree:%d ", m_dualTree );
-    msg( VERBOSE, "LargeCTU:%d ", m_LargeCTU );
     msg( VERBOSE, "IMV:%d ", m_ImvMode );
     msg( VERBOSE, "BIO:%d ", m_BIO );
-    msg( VERBOSE, "DisMDC:%d ", m_DisableMotionCompression );
-    msg( VERBOSE, "MTT:%d ", m_MTT );
-#if ENABLE_WPP_PARALLELISM
-    msg( VERBOSE, "AltDQPCoding:%d ", m_AltDQPCoding );
-#endif
     msg( VERBOSE, "LMChroma:%d ", m_LMChroma );
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
     if( m_LMChroma && m_chromaFormatIDC == CHROMA_420 )
@@ -3146,6 +3192,9 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "MTS: %1d(intra) %1d(inter) ", m_MTS & 1, ( m_MTS >> 1 ) & 1 );
 #else
     msg( VERBOSE, "EMT: %1d(intra) %1d(inter) ", m_EMT & 1, ( m_EMT >> 1 ) & 1 );
+#endif
+#if JVET_M0140_SBT
+    msg( VERBOSE, "SBT:%d ", m_SBT );
 #endif
     msg( VERBOSE, "CompositeLTReference:%d ", m_compositeRefEnabled);
     msg( VERBOSE, "GBi:%d ", m_GBi );
@@ -3155,23 +3204,43 @@ void EncAppCfg::xPrintParameter()
 #endif
     msg(VERBOSE, "MHIntra:%d ", m_MHIntra);
     msg( VERBOSE, "Triangle:%d ", m_Triangle );
+#if JVET_M0255_FRACMMVD_SWITCH
+    msg( VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD );
+#endif
+#if JVET_M0246_AFFINE_AMVR
+    msg( VERBOSE, "AffineAmvr:%d ", m_AffineAmvr );
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    m_AffineAmvrEncOpt = m_AffineAmvr ? m_AffineAmvrEncOpt : false;
+    msg( VERBOSE, "AffineAmvrEncOpt:%d ", m_AffineAmvrEncOpt );
+#endif
+#if JVET_M0147_DMVR
+    msg(VERBOSE, "DMVR:%d ", m_DMVR);
+#endif
   }
     msg(VERBOSE, "IBC:%d ", m_IBCMode);
+#if JVET_M0253_HASH_ME
+  msg( VERBOSE, "HashME:%d ", m_HashME );
+#endif
   msg( VERBOSE, "WrapAround:%d ", m_wrapAround);
   if( m_wrapAround )
   {
     msg( VERBOSE, "WrapAroundOffset:%d ", m_wrapAroundOffset );
   }
   // ADD_NEW_TOOL (add some output indicating the usage of tools)
-
+#if JVET_M0427_INLOOP_RESHAPER
+    msg(VERBOSE, "Reshape:%d ", m_lumaReshapeEnable);
+    if (m_lumaReshapeEnable)
+    {
+      msg(VERBOSE, "(Sigal:%s ", m_reshapeSignalType==0? "SDR" : "HDR-PQ");
+      msg(VERBOSE, ") ");
+    }
+#endif
   msg( VERBOSE, "\nFAST TOOL CFG: " );
-  if( m_LargeCTU )
-  {
-    msg( VERBOSE, "LCTUFast:%d ", m_useFastLCTU );
-  }
+  msg( VERBOSE, "LCTUFast:%d ", m_useFastLCTU );
   msg( VERBOSE, "FastMrg:%d ", m_useFastMrg );
   msg( VERBOSE, "PBIntraFast:%d ", m_usePbIntraFast );
-  if( m_ImvMode == 2 ) msg( VERBOSE, "IMV4PelFast:%d ", m_Imv4PelFast );
+  if( m_ImvMode ) msg( VERBOSE, "IMV4PelFast:%d ", m_Imv4PelFast );
 #if JVET_M0464_UNI_MTS
   if( m_MTS ) msg( VERBOSE, "MTSMaxCand: %1d(intra) %1d(inter) ", m_MTSIntraMaxCand, m_MTSInterMaxCand );
 #else
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 8b67d948decc874a2639cc402a27ee0d900cf67b..45895dc47bbd603185c179c09503a9bdb18003c6 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -202,16 +202,10 @@ protected:
   unsigned  m_uiMaxBTDepthI;
   unsigned  m_uiMaxBTDepthIChroma;
   bool      m_dualTree;
-  bool      m_LargeCTU;
   int       m_SubPuMvpMode;
   bool      m_Affine;
   bool      m_AffineType;
   bool      m_BIO;
-  bool      m_DisableMotionCompression;
-  unsigned  m_MTT;
-#if ENABLE_WPP_PARALLELISM
-  bool      m_AltDQPCoding;
-#endif
   int       m_LMChroma;
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
   bool      m_cclmCollocatedChromaFlag;
@@ -224,6 +218,12 @@ protected:
   int       m_EMT;                                            ///< XZ: Enhanced Multiple Transform
   int       m_FastEMT;                                        ///< XZ: Fast Methods of Enhanced Multiple Transform
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  int       m_MTSImplicit;
+#endif
+#if JVET_M0140_SBT
+  bool      m_SBT;                                            ///< Sub-Block Transform for inter blocks
+#endif
 
   bool      m_compositeRefEnabled;
   bool      m_GBi;
@@ -237,7 +237,21 @@ protected:
 
   bool      m_MHIntra;
   bool      m_Triangle;
-
+#if JVET_M0253_HASH_ME
+  bool      m_HashME;
+#endif
+#if JVET_M0255_FRACMMVD_SWITCH
+  bool      m_allowDisFracMMVD;
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  bool      m_AffineAmvr;
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  bool      m_AffineAmvrEncOpt;
+#endif
+#if JVET_M0147_DMVR
+  bool      m_DMVR;
+#endif
 
   unsigned  m_IBCMode;
   unsigned  m_IBCLocalSearchRangeX;
@@ -246,12 +260,17 @@ protected:
   unsigned  m_IBCHashSearchMaxCand;
   unsigned  m_IBCHashSearchRange4SmallBlk;
   unsigned  m_IBCFastMethod;
-  
+
   bool      m_wrapAround;
   unsigned  m_wrapAroundOffset;
 
   // ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  bool      m_lumaReshapeEnable;
+  uint32_t  m_reshapeSignalType;
+  uint32_t  m_intraCMD;
+  ReshapeCW m_reshapeCW;
+#endif
   unsigned  m_uiMaxCUWidth;                                   ///< max. CU width in pixel
   unsigned  m_uiMaxCUHeight;                                  ///< max. CU height in pixel
   unsigned  m_uiMaxCUDepth;                                   ///< max. CU depth (as specified by command line)
@@ -524,6 +543,9 @@ protected:
   int         m_verbosity;
 
   std::string m_decodeBitstreams[2];                          ///< filename for decode bitstreams.
+#if JVET_M0055_DEBUG_CTU
+  int         m_debugCTU;
+#endif  
   int         m_switchPOC;                                    ///< dbg poc.
   int         m_switchDQP;                                    ///< switch DQP.
   int         m_fastForwardToPOC;                             ///< get to encoding the specified POC as soon as possible by skipping temporal layers irrelevant for the specified POC
diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp
index 81872abd5fb67b1bcdce84a68959119640944178..e6443eaf190ba9614243af216fa32a4572162f77 100644
--- a/source/App/Parcat/parcat.cpp
+++ b/source/App/Parcat/parcat.cpp
@@ -314,11 +314,11 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int
       int byte_offset2 = offset / 8;
       int hi_bits2 = offset % 8;
       uint16_t data2 = (nalu[byte_offset2] << 8) | nalu[byte_offset2 + 1];
-      int low_bits2 = 16 - hi_bits2 - 1;      
+      int low_bits2 = 16 - hi_bits2 - 1;
       if(((data2 >> low_bits2) % 2))
-        offset += 1; // PPSId=0 
+        offset += 1; // PPSId=0
       else
-        offset += 3; // PPSId=1 
+        offset += 3; // PPSId=1
       offset += 1; // slice_type TODO: ue(v)
       // separate_colour_plane_flag is not supported in JEM1.0
       if (nalu_type == CRA)
diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
index ed573e04cd87e3bd859bc1068f9e0dce791251e7..b234f00997f747b2d3e886b2b86c9055a6180ab0 100644
--- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
+++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
@@ -135,7 +135,7 @@ void AdaptiveLoopFilter::reconstructCoeff( AlfSliceParam& alfSliceParam, Channel
   int numFilters = isLuma( channel ) ? alfSliceParam.numLumaFilters : 1;
   short* coeff = isLuma( channel ) ? alfSliceParam.lumaCoeff : alfSliceParam.chromaCoeff;
 
-  if( alfSliceParam.coeffDeltaPredModeFlag && isLuma( channel ) )
+  if( alfSliceParam.alfLumaCoeffDeltaPredictionFlag && isLuma( channel ) )
   {
     for( int i = 1; i < numFilters; i++ )
     {
@@ -167,7 +167,7 @@ void AdaptiveLoopFilter::reconstructCoeff( AlfSliceParam& alfSliceParam, Channel
     memcpy( m_coeffFinal + classIdx * MAX_NUM_ALF_LUMA_COEFF, coeff + filterIdx * MAX_NUM_ALF_LUMA_COEFF, sizeof( int16_t ) * numCoeff );
   }
 
-  if( bRedo && alfSliceParam.coeffDeltaPredModeFlag )
+  if( bRedo && alfSliceParam.alfLumaCoeffDeltaPredictionFlag )
   {
     for( int i = numFilters - 1; i > 0; i-- )
     {
diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index 07ffa9a94ab29b9ce80e49aae1e75bbeb025c6c5..84f83324ea8b668a3d6c0dfd8bcc0225a98baa2b 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -91,18 +91,30 @@ void addBIOAvgCore(const Pel* src0, int src0Stride, const Pel* src1, int src1Str
   }
 }
 
+#if JVET_M0063_BDOF_FIX
+void gradFilterCore(Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, const int bitDepth)
+#else
 void gradFilterCore(Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY)
+#endif
 {
   Pel* srcTmp = pSrc + srcStride + 1;
   Pel* gradXTmp = gradX + gradStride + 1;
   Pel* gradYTmp = gradY + gradStride + 1;
+#if JVET_M0063_BDOF_FIX
+  int  shift1 = std::max<int>(2, (IF_INTERNAL_PREC - bitDepth));
+#endif
 
   for (int y = 0; y < (height - 2 * BIO_EXTEND_SIZE); y++)
   {
     for (int x = 0; x < (width - 2 * BIO_EXTEND_SIZE); x++)
     {
+#if JVET_M0063_BDOF_FIX
+      gradYTmp[x] = (srcTmp[x + srcStride] - srcTmp[x - srcStride]) >> shift1;
+      gradXTmp[x] = (srcTmp[x + 1] - srcTmp[x - 1]) >> shift1;
+#else
       gradYTmp[x] = (srcTmp[x + srcStride] - srcTmp[x - srcStride]) >> 4;
       gradXTmp[x] = (srcTmp[x + 1] - srcTmp[x - 1]) >> 4;
+#endif
     }
     gradXTmp += gradStride;
     gradYTmp += gradStride;
@@ -130,15 +142,29 @@ void gradFilterCore(Pel* pSrc, int srcStride, int width, int height, int gradStr
   ::memcpy(gradYTmp + (height - 2 * BIO_EXTEND_SIZE)*gradStride, gradYTmp + (height - 2 * BIO_EXTEND_SIZE - 1)*gradStride, sizeof(Pel)*(width));
 }
 
+#if JVET_M0063_BDOF_FIX
+void calcBIOParCore(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, const int bitDepth)
+#else
 void calcBIOParCore(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG)
+#endif
 {
+#if JVET_M0063_BDOF_FIX
+  int shift4 = std::min<int>(8, (bitDepth - 4));
+  int shift5 = std::min<int>(5, (bitDepth - 7));
+#endif
   for (int y = 0; y < heightG; y++)
   {
     for (int x = 0; x < widthG; x++)
     {
+#if JVET_M0063_BDOF_FIX
+      int temp = (srcY0Temp[x] >> shift4) - (srcY1Temp[x] >> shift4);
+      int tempX = (gradX0[x] + gradX1[x]) >> shift5;
+      int tempY = (gradY0[x] + gradY1[x]) >> shift5;
+#else
       int temp = (srcY0Temp[x] >> 6) - (srcY1Temp[x] >> 6);
       int tempX = (gradX0[x] + gradX1[x]) >> 3;
       int tempY = (gradY0[x] + gradY1[x]) >> 3;
+#endif
       dotProductTemp1[x] = tempX * tempX;
       dotProductTemp2[x] = tempX * tempY;
       dotProductTemp3[x] = -tempX * temp;
@@ -273,6 +299,10 @@ PelBufferOps::PelBufferOps()
   calcBIOPar      = calcBIOParCore;
   calcBlkGradient = calcBlkGradientCore;
 
+#if JVET_M0147_DMVR
+  copyBuffer = copyBufferCore;
+  padding = paddingCore;
+#endif
 #if ENABLE_SIMD_OPT_GBI
   removeWeightHighFreq8 = removeWeightHighFreq;
   removeWeightHighFreq4 = removeWeightHighFreq;
@@ -287,6 +317,42 @@ PelBufferOps g_pelBufOP = PelBufferOps();
 #endif
 #endif
 
+#if JVET_M0147_DMVR
+void copyBufferCore(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height)
+{
+  int numBytes = width * sizeof(Pel);
+  for (int i = 0; i < height; i++)
+  {
+    memcpy(dst + i * dstStride, src + i * srcStride, numBytes);
+  }
+}
+
+void paddingCore(Pel *ptr, int stride, int width, int height, int padSize)
+{
+  /*left and right padding*/
+  Pel *ptrTemp1 = ptr;
+  Pel *ptrTemp2 = ptr + (width - 1);
+  int offset = 0;
+  for (int i = 0; i < height; i++)
+  {
+    offset = stride * i;
+    for (int j = 1; j <= padSize; j++)
+    {
+      *(ptrTemp1 - j + offset) = *(ptrTemp1 + offset);
+      *(ptrTemp2 + j + offset) = *(ptrTemp2 + offset);
+    }
+  }
+  /*Top and Bottom padding*/
+  int numBytes = (width + padSize + padSize) * sizeof(Pel);
+  ptrTemp1 = (ptr - padSize);
+  ptrTemp2 = (ptr + (stride * (height - 1)) - padSize);
+  for (int i = 1; i <= padSize; i++)
+  {
+    memcpy(ptrTemp1 - (i * stride), (ptrTemp1), numBytes);
+    memcpy(ptrTemp2 + (i * stride), (ptrTemp2), numBytes);
+  }
+}
+#endif
 template<>
 void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng, const int8_t gbiIdx)
 {
@@ -317,6 +383,80 @@ void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel> &other1, const AreaBu
 #undef ADD_AVG_INC
 }
 
+#if JVET_M0427_INLOOP_RESHAPER
+template<>
+void AreaBuf<Pel>::rspSignal(std::vector<Pel>& pLUT)
+{
+  Pel* dst = buf;
+  Pel* src = buf;
+#if !JVET_M0102_INTRA_SUBPARTITIONS
+  if (width == 1)
+  {
+    THROW("Blocks of width = 1 not supported");
+  }
+  else
+  {
+#endif
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        dst[x] = pLUT[src[x]];
+      }
+      dst += stride;
+      src += stride;
+    }
+#if !JVET_M0102_INTRA_SUBPARTITIONS
+  }
+#endif
+}
+
+template<>
+void AreaBuf<Pel>::scaleSignal(const int scale, const bool dir, const ClpRng& clpRng)
+{
+  Pel* dst = buf;
+  Pel* src = buf;
+  int sign, absval;
+  int maxAbsclipBD = (1<<clpRng.bd) - 1;
+
+  if (dir) // forward
+  {
+    if (width == 1)
+    {
+      THROW("Blocks of width = 1 not supported");
+    }
+    else
+    {
+      for (unsigned y = 0; y < height; y++)
+      {
+        for (unsigned x = 0; x < width; x++)
+        {
+          sign = src[x] >= 0 ? 1 : -1;
+          absval = sign * src[x];
+          dst[x] = (Pel)Clip3(-maxAbsclipBD, maxAbsclipBD, sign * (((absval << CSCALE_FP_PREC) + (scale >> 1)) / scale));
+        }
+        dst += stride;
+        src += stride;
+      }
+    }
+  }
+  else // inverse
+  {
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        sign = src[x] >= 0 ? 1 : -1;
+        absval = sign * src[x];
+        dst[x] = sign * ((absval * scale + (1 << (CSCALE_FP_PREC - 1))) >> CSCALE_FP_PREC);
+      }
+      dst += stride;
+      src += stride;
+    }
+  }
+}
+#endif
+
 template<>
 void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng)
 {
diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h
index 116f5c69fac4469eb69e6ec8ba755d133060ecdd..21584dde076f5c2056803e680d6bd1d285ac65a4 100644
--- a/source/Lib/CommonLib/Buffer.h
+++ b/source/Lib/CommonLib/Buffer.h
@@ -69,9 +69,18 @@ struct PelBufferOps
   void ( *linTf4 )        ( const Pel* src0, int src0Stride,                                  Pel *dst, int dstStride, int width, int height, int scale, int shift, int offset, const ClpRng& clpRng, bool bClip );
   void ( *linTf8 )        ( const Pel* src0, int src0Stride,                                  Pel *dst, int dstStride, int width, int height, int scale, int shift, int offset, const ClpRng& clpRng, bool bClip );
   void(*addBIOAvg4)    (const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel*gradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng);
+#if JVET_M0063_BDOF_FIX
+  void(*bioGradFilter) (Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, const int bitDepth);
+  void(*calcBIOPar)    (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, const int bitDepth);
+#else
   void(*bioGradFilter) (Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY);
   void(*calcBIOPar)    (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG);
+#endif
   void(*calcBlkGradient)(int sx, int sy, int    *arraysGx2, int     *arraysGxGy, int     *arraysGxdI, int     *arraysGy2, int     *arraysGydI, int     &sGx2, int     &sGy2, int     &sGxGy, int     &sGxdI, int     &sGydI, int width, int height, int unitSize);
+#if JVET_M0147_DMVR
+  void(*copyBuffer)(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height);
+  void(*padding)(Pel *dst, int stride, int width, int height, int padSize);
+#endif
 #if ENABLE_SIMD_OPT_GBI
   void ( *removeWeightHighFreq8)  ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int gbiWeight);
   void ( *removeWeightHighFreq4)  ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int gbiWeight);
@@ -85,6 +94,12 @@ extern PelBufferOps g_pelBufOP;
 #endif
 #endif
 
+
+#if JVET_M0147_DMVR
+void paddingCore(Pel *ptr, int stride, int width, int height, int padSize);
+void copyBufferCore(Pel *src, int srcStride, Pel *Dst, int dstStride, int width, int height);
+#endif
+
 template<typename T>
 struct AreaBuf : public Size
 {
@@ -118,7 +133,6 @@ struct AreaBuf : public Size
   void removeHighFreq       ( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng);
   void updateHistogram      ( std::vector<int32_t>& hist ) const;
 
-  T    mean                 () const;
   T    meanDiff             ( const AreaBuf<const T> &other ) const;
   void subtract             ( const T val );
 
@@ -128,6 +142,12 @@ struct AreaBuf : public Size
 
   void toLast               ( const ClpRng& clpRng );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  void rspSignal            ( std::vector<Pel>& pLUT );
+  void scaleSignal          ( const int scale, const bool dir , const ClpRng& clpRng);
+#endif
+  T    computeAvg           ( ) const;
+
         T& at( const int &x, const int &y )          { return buf[y * stride + x]; }
   const T& at( const int &x, const int &y ) const    { return buf[y * stride + x]; }
 
@@ -548,26 +568,6 @@ void AreaBuf<T>::extendBorderPel( unsigned margin )
   }
 }
 
-template<typename T>
-T AreaBuf<T>::mean() const
-{
-  int64_t  sum = 0;
-
-  CHECK (area() == 0, "size of area is zero");
-
-  const T* src = buf;
-
-#define MEAN_INC      src += stride
-#define MEAN_OP(ADDR) sum += src[ADDR]
-
-  SIZE_AWARE_PER_EL_OP(MEAN_OP, MEAN_INC);
-
-#undef MEAN_INC
-#undef MEAN_OP
-
-  return T ((sum + (area() >> 1)) / area());
-}
-
 template<typename T>
 T AreaBuf<T>::meanDiff( const AreaBuf<const T> &other ) const
 {
@@ -631,6 +631,33 @@ void AreaBuf<T>::transposedFrom( const AreaBuf<const T> &other )
   }
 }
 
+template<typename T>
+T AreaBuf <T> ::computeAvg() const
+{
+#if !JVET_M0102_INTRA_SUBPARTITIONS
+  if (width == 1)
+  {
+    THROW("Blocks of width = 1 not supported");
+  }
+  else
+  {
+#endif
+    const T* src = buf;
+#if ENABLE_QPA
+    int64_t  acc = 0; // for picture-wise use in getGlaringColorQPOffset() and applyQPAdaptationChroma()
+#else
+    int32_t  acc = 0;
+#endif
+#define AVG_INC      src += stride
+#define AVG_OP(ADDR) acc += src[ADDR]
+    SIZE_AWARE_PER_EL_OP(AVG_OP, AVG_INC);
+#undef AVG_INC
+#undef AVG_OP
+    return T ((acc + (area() >> 1)) / area());
+#if !JVET_M0102_INTRA_SUBPARTITIONS
+  }
+#endif
+}
 
 #ifndef DONT_UNDEF_SIZE_AWARE_PER_EL_OP
 #undef SIZE_AWARE_PER_EL_OP
diff --git a/source/Lib/CommonLib/CodingStatistics.h b/source/Lib/CommonLib/CodingStatistics.h
index 748138fdf7a5339d69a21cab167088f17ac5e40c..b35013ca264fc26fa1d29d526bea4048c2ebd919 100644
--- a/source/Lib/CommonLib/CodingStatistics.h
+++ b/source/Lib/CommonLib/CodingStatistics.h
@@ -68,13 +68,21 @@ enum CodingStatisticsType
   STATS__CABAC_BITS__MVD_EP,
   STATS__CABAC_BITS__AFFINE_FLAG,
   STATS__CABAC_BITS__AFFINE_TYPE,
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  STATS__CABAC_BITS__ISP_MODE_FLAG,
+  STATS__CABAC_BITS__ISP_SPLIT_FLAG,
+#endif
   STATS__CABAC_BITS__TRANSFORM_SUBDIV_FLAG,
   STATS__CABAC_BITS__QT_ROOT_CBF,
   STATS__CABAC_BITS__DELTA_QP_EP,
   STATS__CABAC_BITS__CHROMA_QP_ADJUSTMENT,
   STATS__CABAC_BITS__QT_CBF,
   STATS__CABAC_BITS__CROSS_COMPONENT_PREDICTION,
+#if JVET_M0464_UNI_MTS
+  STATS__CABAC_BITS__MTS_FLAGS,
+#else
   STATS__CABAC_BITS__TRANSFORM_SKIP_FLAGS,
+#endif
   STATS__CABAC_BITS__LAST_SIG_X_Y,
   STATS__CABAC_BITS__SIG_COEFF_GROUP_FLAG,
   STATS__CABAC_BITS__SIG_COEFF_MAP_FLAG,
@@ -99,18 +107,23 @@ enum CodingStatisticsType
   STATS__CABAC_BITS__INVALID,
   STATS__CABAC_BITS__IMV_FLAG,
   STATS__CABAC_BITS__GBI_IDX,
+#if !JVET_M0464_UNI_MTS
   STATS__CABAC_BITS__EMT_CU_FLAG,
   STATS__CABAC_BITS__EMT_TU_INDEX,
+#endif
+#if JVET_M0140_SBT
+  STATS__CABAC_BITS__SBT_MODE,
+#endif
   STATS__CABAC_BITS__MH_INTRA_FLAG,
   STATS__CABAC_BITS__TRIANGLE_FLAG,
   STATS__CABAC_BITS__TRIANGLE_INDEX,
   STATS__CABAC_BITS__MULTI_REF_LINE,
-  STATS__TOOL_TOTAL_FRAME,// This is a special case and is not included in the report.
-  STATS__TOOL_AFF,
-  STATS__TOOL_EMT,
 #if JVET_M0444_SMVD
   STATS__CABAC_BITS__SYMMVD_FLAG,
 #endif
+  STATS__TOOL_TOTAL_FRAME,// This is a special case and is not included in the report.
+  STATS__TOOL_AFF,
+  STATS__TOOL_EMT,
   STATS__TOOL_TOTAL,
   STATS__NUM_STATS
 };
@@ -150,13 +163,21 @@ static inline const char* getName(CodingStatisticsType name)
     "CABAC_BITS__MVD_EP",
     "CABAC_BITS__AFFINE_FLAG",
     "CABAC_BITS__AFFINE_TYPE",
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    "CABAC_BITS__ISP_MODE_FLAG",
+    "CABAC_BITS__ISP_SPLIT_FLAG",
+#endif
     "CABAC_BITS__TRANSFORM_SUBDIV_FLAG",
     "CABAC_BITS__QT_ROOT_CBF",
     "CABAC_BITS__DELTA_QP_EP",
     "CABAC_BITS__CHROMA_QP_ADJUSTMENT",
     "CABAC_BITS__QT_CBF",
     "CABAC_BITS__CROSS_COMPONENT_PREDICTION",
+#if JVET_M0464_UNI_MTS
+    "CABAC_BITS__MTS_FLAGS",
+#else
     "CABAC_BITS__TRANSFORM_SKIP_FLAGS",
+#endif
     "CABAC_BITS__LAST_SIG_X_Y",
     "CABAC_BITS__SIG_COEFF_GROUP_FLAG",
     "CABAC_BITS__SIG_COEFF_MAP_FLAG",
@@ -181,8 +202,13 @@ static inline const char* getName(CodingStatisticsType name)
     "CABAC_BITS__INVALID",
     "CABAC_BITS__IMV_FLAG",
     "CABAC_BITS__GBI_IDX",
+#if !JVET_M0464_UNI_MTS
     "CABAC_BITS__EMT_CU_FLAG",
     "CABAC_BITS__EMT_TU_INDX",
+#endif
+#if JVET_M0140_SBT
+    "CABAC_BITS__SBT_MODE",
+#endif
     "CABAC_BITS__MH_INTRA_FLAG",
     "CABAC_BITS__TRIANGLE_FLAG",
     "CABAC_BITS__TRIANGLE_INDEX",
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index 8d5013fcc154824f7131c04f8dc76f23b3576441..f52f4205834c8bfafe0841b22e45451cb4462b16 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -62,6 +62,9 @@ CodingStructure::CodingStructure(CUCache& cuCache, PUCache& puCache, TUCache& tu
   : area      ()
   , picture   ( nullptr )
   , parent    ( nullptr )
+#if JVET_M0246_AFFINE_AMVR
+  , bestCS    ( nullptr )
+#endif
   , m_isTuEnc ( false )
   , m_cuCache ( cuCache )
   , m_puCache ( puCache )
@@ -256,7 +259,11 @@ const PredictionUnit * CodingStructure::getPU( const Position &pos, const Channe
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+TransformUnit* CodingStructure::getTU( const Position &pos, const ChannelType effChType, const int subTuIdx )
+#else
 TransformUnit* CodingStructure::getTU( const Position &pos, const ChannelType effChType )
+#endif
 {
   const CompArea &_blk = area.blocks[effChType];
 
@@ -269,13 +276,45 @@ TransformUnit* CodingStructure::getTU( const Position &pos, const ChannelType ef
   {
     const unsigned idx = m_tuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( idx != 0 )
+    {
+      unsigned extraIdx = 0;
+      if( isLuma( effChType ) )
+      {
+        const TransformUnit& tu = *tus[idx - 1];
+
+        if( tu.cu->ispMode ) // Intra SubPartitions mode
+        {
+          //we obtain the offset to index the corresponding sub-partition
+          if( subTuIdx != -1 )
+          {
+            extraIdx = subTuIdx;
+          }
+          else
+          {
+            while( pos != tus[idx - 1 + extraIdx]->blocks[getFirstComponentOfChannel( effChType )].pos() )
+            {
+              extraIdx++;
+            }
+          }
+        }
+      }
+      return tus[idx - 1 + extraIdx];
+    }
+#else
     if( idx != 0 )       return tus[ idx - 1 ];
+#endif
     else if( m_isTuEnc ) return parent->getTU( pos, effChType );
     else                 return nullptr;
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+const TransformUnit * CodingStructure::getTU( const Position &pos, const ChannelType effChType, const int subTuIdx ) const
+#else
 const TransformUnit * CodingStructure::getTU( const Position &pos, const ChannelType effChType ) const
+#endif
 {
   const CompArea &_blk = area.blocks[effChType];
 
@@ -287,8 +326,34 @@ const TransformUnit * CodingStructure::getTU( const Position &pos, const Channel
   else
   {
     const unsigned idx = m_tuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( idx != 0 )
+    {
+      unsigned extraIdx = 0;
+      if( isLuma( effChType ) )
+      {
+        const TransformUnit& tu = *tus[idx - 1];
+        if( tu.cu->ispMode ) // Intra SubPartitions mode
+        {
+          //we obtain the offset to index the corresponding sub-partition
+          if( subTuIdx != -1 )
+          {
+            extraIdx = subTuIdx;
+          }
+          else
+          {
+            while( pos != tus[idx - 1 + extraIdx]->blocks[effChType].pos() )
+            {
+              extraIdx++;
+            }
+          }
+        }
+      }
+      return tus[idx - 1 + extraIdx];
+    }
+#else
     if( idx != 0 )       return tus[idx - 1];
+#endif
     else if( m_isTuEnc ) return parent->getTU( pos, effChType );
     else                 return nullptr;
   }
@@ -415,6 +480,9 @@ TransformUnit& CodingStructure::addTU( const UnitArea &unit, const ChannelType c
   tu->UnitArea::operator=( unit );
   tu->initData();
   tu->next   = nullptr;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  tu->prev   = nullptr;
+#endif
   tu->cs     = this;
   tu->cu     = m_isTuEnc ? cus[0] : getCU( unit.blocks[chType].pos(), chType );
   tu->chType = chType;
@@ -430,6 +498,9 @@ TransformUnit& CodingStructure::addTU( const UnitArea &unit, const ChannelType c
   if( prevTU && prevTU->cu == tu->cu )
   {
     prevTU->next = tu;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    tu->prev     = prevTU;
+#endif
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
 
     CHECK( prevTU->cacheId != tu->cacheId, "Inconsintent cacheId between previous and current TU" );
@@ -467,11 +538,25 @@ TransformUnit& CodingStructure::addTU( const UnitArea &unit, const ChannelType c
       const CompArea &_selfBlk = area.blocks[i];
       const CompArea     &_blk = tu-> blocks[i];
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      bool isIspTu = tu->cu != nullptr && tu->cu->ispMode && isLuma( _blk.compID );
+
+      bool isFirstIspTu = false;
+      if( isIspTu )
+      {
+        isFirstIspTu = CU::isISPFirst( *tu->cu, _blk, getFirstComponentOfChannel( ChannelType( i ) ) );
+      }
+      if( !isIspTu || isFirstIspTu )
+#endif
       {
         const UnitScale& scale = unitScale[_blk.compID];
 
         const Area scaledSelf  = scale.scale( _selfBlk );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        const Area scaledBlk   = isIspTu ? scale.scale( tu->cu->blocks[i] ) : scale.scale( _blk );
+#else
         const Area scaledBlk   = scale.scale(     _blk );
+#endif
         unsigned *idxPtr       = m_tuIdx[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
         CHECK( *idxPtr, "Overwriting a pre-existing value, should be '0'!" );
         AreaBuf<uint32_t>( idxPtr, scaledSelf.width, scaledBlk.size() ).fill( idx );
@@ -746,7 +831,11 @@ void CodingStructure::useSubStructure( const CodingStructure& subStruct, const C
   if( cpyResi ) picture->getResiBuf( clippedArea ).copyFrom( subResiBuf );
   if( cpyReco ) picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
 
+#if JVET_M0483_IBC
+  if (!subStruct.m_isTuEnc && ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && subStruct.chType != CHANNEL_TYPE_CHROMA))
+#else
   if (!subStruct.m_isTuEnc && (!slice->isIntra() && subStruct.chType != CHANNEL_TYPE_CHROMA))
+#endif
   {
     // copy motion buffer
     MotionBuf ownMB  = getMotionBuf          ( clippedArea );
@@ -926,7 +1015,11 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
     pu = *ppu;
   }
 
+#if JVET_M0483_IBC
+  if (!other.slice->isIntra() || other.slice->getSPS()->getIBCFlag())
+#else
   if( !other.slice->isIntra() )
+#endif
   {
     // copy motion buffer
     MotionBuf  ownMB = getMotionBuf();
@@ -966,6 +1059,28 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
 
     // copy data to picture
     picture->getRecoBuf( area ).copyFrom( recoBuf );
+#if JVET_M0427_INLOOP_RESHAPER
+    if (other.pcv->isEncoder)
+    {
+      CPelUnitBuf predBuf = other.getPredBuf(area);
+      if (parent)
+      {
+        getPredBuf(area).copyFrom(predBuf);
+      }
+      picture->getPredBuf(area).copyFrom(predBuf);
+    }
+#endif
+#if JVET_M0055_DEBUG_CTU
+
+    // required for DebugCTU
+    int numCh = ::getNumberValidChannels( area.chromaFormat );
+    for( int i = 0; i < numCh; i++ )
+    {
+      const size_t _area = unitScale[i].scaleArea( area.blocks[i].area() );
+
+      memcpy( m_isDecomp[i], other.m_isDecomp[i], sizeof( *m_isDecomp[0] ) * _area );
+    }
+#endif
   }
 }
 
@@ -981,7 +1096,11 @@ void CodingStructure::initStructData( const int &QP, const bool &_isLosses, cons
     isLossless            = _isLosses;
   }
 
+#if JVET_M0483_IBC
+  if (!skipMotBuf && (!parent || ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && !m_isTuEnc)))
+#else
   if( !skipMotBuf && ( !parent || ( ( slice->getSliceType() != I_SLICE ) && !m_isTuEnc ) ) )
+#endif
   {
     getMotionBuf()      .memset( 0 );
   }
@@ -989,6 +1108,9 @@ void CodingStructure::initStructData( const int &QP, const bool &_isLosses, cons
   fracBits = 0;
   dist     = 0;
   cost     = MAX_DOUBLE;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  lumaCost = MAX_DOUBLE;
+#endif
   interHad = std::numeric_limits<Distortion>::max();
 }
 
@@ -1004,7 +1126,7 @@ void CodingStructure::clearTUs()
     memset( m_tuIdx   [i],     0, sizeof( *m_tuIdx   [0] ) * _area );
   }
 
-  numCh = getNumberValidComponents( area.chromaFormat ); 
+  numCh = getNumberValidComponents( area.chromaFormat );
   for( int i = 0; i < numCh; i++ )
   {
     m_offsets[i] = 0;
diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h
index 3727cc1fd33e8af22c8d7a44362b79ba00a14524..f28500a798c9a02ea29c2f58e19501540d80f94a 100644
--- a/source/Lib/CommonLib/CodingStructure.h
+++ b/source/Lib/CommonLib/CodingStructure.h
@@ -53,6 +53,9 @@ enum PictureType
 {
   PIC_RECONSTRUCTION = 0,
   PIC_ORIGINAL,
+#if JVET_M0427_INLOOP_RESHAPER
+  PIC_TRUE_ORIGINAL,
+#endif
   PIC_PREDICTION,
   PIC_RESIDUAL,
   PIC_ORG_RESI,
@@ -79,7 +82,9 @@ public:
 
   Picture         *picture;
   CodingStructure *parent;
-
+#if JVET_M0246_AFFINE_AMVR
+  CodingStructure *bestCS;
+#endif
   Slice           *slice;
 
   UnitScale        unitScale[MAX_NUM_COMPONENT];
@@ -124,11 +129,19 @@ public:
 
   const CodingUnit     *getCU(const Position &pos, const ChannelType _chType) const;
   const PredictionUnit *getPU(const Position &pos, const ChannelType _chType) const;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const TransformUnit  *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1) const;
+#else
   const TransformUnit  *getTU(const Position &pos, const ChannelType _chType) const;
+#endif
 
   CodingUnit     *getCU(const Position &pos, const ChannelType _chType);
   PredictionUnit *getPU(const Position &pos, const ChannelType _chType);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  TransformUnit  *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1);
+#else
   TransformUnit  *getTU(const Position &pos, const ChannelType _chType);
+#endif
 
   const CodingUnit     *getCU(const ChannelType &_chType) const { return getCU(area.blocks[_chType].pos(), _chType); }
   const PredictionUnit *getPU(const ChannelType &_chType) const { return getPU(area.blocks[_chType].pos(), _chType); }
@@ -166,6 +179,9 @@ public:
   static_vector<double, NUM_ENC_FEATURES> features;
 
   double      cost;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  double      lumaCost;
+#endif
   uint64_t      fracBits;
   Distortion  dist;
   Distortion  interHad;
diff --git a/source/Lib/CommonLib/Common.h b/source/Lib/CommonLib/Common.h
index 24746baad3be0895fd1ae962155c4fdbc17bccc4..81c92278b2bd60a59c558424bcdbedf0f1defb5b 100644
--- a/source/Lib/CommonLib/Common.h
+++ b/source/Lib/CommonLib/Common.h
@@ -72,6 +72,9 @@ struct Size
   bool operator!=(const Size &other)      const { return (width != other.width) || (height != other.height); }
   bool operator==(const Size &other)      const { return (width == other.width) && (height == other.height); }
   uint32_t area()                             const { return (uint32_t) width * (uint32_t) height; }
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  void resizeTo(const Size newSize)             { width = newSize.width; height = newSize.height; }
+#endif
 };
 
 struct Area : public Position, public Size
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 27d76437a551bb84a7d284e129c8d27423cb3d9c..6d09dc35f650e11d42a96fe0daf219da1381a6e5 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -53,9 +53,10 @@
 #include "TypeDef.h"
 #include "version.h"
 
+// MS Visual Studio before 2014 does not support required C++11 features
 #ifdef _MSC_VER
-#if _MSC_VER <= 1500
-inline int64_t abs (int64_t x) { return _abs64(x); };
+#if _MSC_VER < 1900
+#error "MS Visual Studio version not supported. Please upgrade to Visual Studio 2015 or higher (or use other compilers)"
 #endif
 #endif
 
@@ -66,7 +67,14 @@ inline int64_t abs (int64_t x) { return _abs64(x); };
 // Platform information
 // ====================================================================================================================
 
-#ifdef __GNUC__
+#ifdef __clang__
+#define NVM_COMPILEDBY  "[clang %d.%d.%d]", __clang_major__, __clang_minor__, __clang_patchlevel__
+#ifdef __IA64__
+#define NVM_ONARCH    "[on 64-bit] "
+#else
+#define NVM_ONARCH    "[on 32-bit] "
+#endif
+#elif __GNUC__
 #define NVM_COMPILEDBY  "[GCC %d.%d.%d]", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
 #ifdef __IA64__
 #define NVM_ONARCH    "[on 64-bit] "
@@ -117,7 +125,7 @@ static const double AFFINE_ME_LIST_MVP_TH =                        1.0;
 // ====================================================================================================================
 // Common constants
 // ====================================================================================================================
-
+static const uint64_t   MAX_UINT64 =                  0xFFFFFFFFFFFFFFFFU;
 static const uint32_t   MAX_UINT =                            0xFFFFFFFFU; ///< max. value of unsigned 32-bit integer
 static const int    MAX_INT =                              2147483647; ///< max. value of signed 32-bit integer
 static const uint8_t  MAX_UCHAR =                                   255;
@@ -162,9 +170,11 @@ static const int MAXIMUM_INTRA_FILTERED_HEIGHT =                   16;
 
 static const int MAX_CPB_CNT =                                     32; ///< Upper bound of (cpb_cnt_minus1 + 1)
 static const int MAX_NUM_LAYER_IDS =                               64;
-
+#if JVET_M0470
+static const int COEF_REMAIN_BIN_REDUCTION =                        5; ///< indicates the level at which the VLC transitions from Golomb-Rice to TU+EG(k)
+#else
 static const int COEF_REMAIN_BIN_REDUCTION =                        3; ///< indicates the level at which the VLC transitions from Golomb-Rice to TU+EG(k)
-
+#endif
 static const int CU_DQP_TU_CMAX =                                   5; ///< max number bins for truncated unary
 static const int CU_DQP_EG_k =                                      0; ///< expgolomb order
 
@@ -316,7 +326,7 @@ static const int BIO_TEMP_BUFFER_SIZE         =                     (MAX_CU_SIZE
 static const int GBI_NUM =                                          5; ///< the number of weight options
 static const int GBI_DEFAULT =                                      ((uint8_t)(GBI_NUM >> 1)); ///< Default weighting index representing for w=0.5
 static const int GBI_SIZE_CONSTRAINT =                            256; ///< disabling GBi if cu size is smaller than 256
-static const int MAX_NUM_HMVP_CANDS =                              6; ///< maximum number of HMVP candidates to be stored and used in merge list
+static const int MAX_NUM_HMVP_CANDS =                              5; ///< maximum number of HMVP candidates to be stored and used in merge list
 static const int MAX_NUM_HMVP_AVMPCANDS =                          4; ///< maximum number of HMVP candidates to be used in AMVP list
 
 #if W0038_DB_OPT
@@ -330,6 +340,14 @@ static const uint32_t LUMA_LEVEL_TO_DQP_LUT_MAXSIZE =                1024; ///<
 #if !JVET_M0464_UNI_MTS
 static const int NUM_EMT_CU_FLAG_CTX =                              6;      ///< number of context models for EMT CU-level flag
 #endif
+#if JVET_M0147_DMVR
+static const int DMVR_SUBCU_WIDTH = 16;
+static const int DMVR_SUBCU_HEIGHT = 16;
+static const int DMVR_SUBCU_WIDTH_LOG2 = 4;
+static const int DMVR_SUBCU_HEIGHT_LOG2 = 4;
+static const int MAX_NUM_SUBCU_DMVR = ((MAX_CU_SIZE * MAX_CU_SIZE) >> (DMVR_SUBCU_WIDTH_LOG2 + DMVR_SUBCU_HEIGHT_LOG2));
+static const int DMVR_NUM_ITERATION = 2;
+#endif
 
 //QTBT high level parameters
 //for I slice luma CTB configuration para.
@@ -365,7 +383,7 @@ static const int    FAST_SKIP_DEPTH =                               2;
 static const double PBINTRA_RATIO     =                             1.1;
 static const int    NUM_MRG_SATD_CAND =                             4;
 static const double MRG_FAST_RATIO    =                             1.25;
-static const int    NUM_AFF_MRG_SATD_CAND =                         1;
+static const int    NUM_AFF_MRG_SATD_CAND =                         2;
 
 static const double AMAXBT_TH32 =                                  15.0;
 static const double AMAXBT_TH64 =                                  30.0;
@@ -396,13 +414,31 @@ static const int TRIANGLE_MAX_NUM_CANDS =                          40;
 static const int TRIANGLE_MAX_NUM_SATD_CANDS =                      3;
 static const int TRIANGLE_MIN_SIZE =                            8 * 8;
 
+#if JVET_M0140_SBT
+static const int SBT_MAX_SIZE =                                    64; ///< maximum CU size for using SBT
+static const int SBT_NUM_SL =                                      10; ///< maximum number of historical PU decision saved for a CU
+static const int SBT_NUM_RDO =                                      2; ///< maximum number of SBT mode tried for a PU
+#endif
+
 static const int IBC_MAX_CAND_SIZE = 16; // max block size for ibc search
 static const int IBC_NUM_CANDIDATES = 64; ///< Maximum number of candidates to store/test
 static const int CHROMA_REFINEMENT_CANDIDATES = 8; /// 8 candidates BV to choose from
 static const int IBC_FAST_METHOD_NOINTRA_IBCCBF0 = 0x01;
 static const int IBC_FAST_METHOD_BUFFERBV = 0X02;
 static const int IBC_FAST_METHOD_ADAPTIVE_SEARCHRANGE = 0X04;
-
+#if JVET_M0512_MOTION_BUFFER_COMPRESSION
+static constexpr int MV_EXPONENT_BITCOUNT    = 4;
+static constexpr int MV_MANTISSA_BITCOUNT    = 6;
+static constexpr int MV_MANTISSA_UPPER_LIMIT = ((1 << (MV_MANTISSA_BITCOUNT - 1)) - 1);
+static constexpr int MV_MANTISSA_LIMIT       = (1 << (MV_MANTISSA_BITCOUNT - 1));
+static constexpr int MV_EXPONENT_MASK        = ((1 << MV_EXPONENT_BITCOUNT) - 1);
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+static const int PIC_ANALYZE_CW_BINS =                           32;
+static const int PIC_CODE_CW_BINS =                              16;
+static const int FP_PREC =                                       14;
+static const int CSCALE_FP_PREC =                                11;
+#endif
 // ====================================================================================================================
 // Macro functions
 // ====================================================================================================================
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index d52ea51e00383a3719d16ecc733dd3f968afda60..b90718f94d61afd495af74edd8faa6ea59070b9e 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -50,11 +50,21 @@ CoeffCodingContext::CoeffCodingContext(const TransformUnit& tu, ComponentID comp
   , m_chType                    (toChannelType(m_compID))
   , m_width                     (tu.block(m_compID).width)
   , m_height                    (tu.block(m_compID).height)
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  , m_log2CGWidth               ( g_log2SbbSize[m_chType][ g_aucLog2[m_width] ][ g_aucLog2[m_height] ][0] )
+  , m_log2CGHeight              ( g_log2SbbSize[m_chType][ g_aucLog2[m_width] ][ g_aucLog2[m_height] ][1] )
+#else
   , m_log2CGWidth               ((m_width & 3) || (m_height & 3) ? 1 : 2)
   , m_log2CGHeight              ((m_width & 3) || (m_height & 3) ? 1 : 2)
+#endif
   , m_log2CGSize                (m_log2CGWidth + m_log2CGHeight)
-  , m_widthInGroups             (m_width  >> m_log2CGWidth)
-  , m_heightInGroups            (m_height >> m_log2CGHeight)
+#if JVET_M0257
+  , m_widthInGroups(std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, m_width) >> m_log2CGWidth)
+  , m_heightInGroups(std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, m_height) >> m_log2CGHeight)
+#else
+  , m_widthInGroups(m_width >> m_log2CGWidth)
+  , m_heightInGroups(m_height >> m_log2CGHeight)
+#endif
   , m_log2BlockWidth            (g_aucLog2[m_width])
   , m_log2BlockHeight           (g_aucLog2[m_height])
   , m_log2BlockSize             ((m_log2BlockWidth + m_log2BlockHeight)>>1)
@@ -69,14 +79,22 @@ CoeffCodingContext::CoeffCodingContext(const TransformUnit& tu, ComponentID comp
 #else
   , m_scanType                  (SCAN_DIAG)
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  , m_scan                      (g_scanOrder     [m_chType][SCAN_GROUPED_4x4][m_scanType][gp_sizeIdxInfo->idxFrom(m_width        )][gp_sizeIdxInfo->idxFrom(m_height        )])
+  , m_scanCG                    (g_scanOrder     [m_chType][SCAN_UNGROUPED  ][m_scanType][gp_sizeIdxInfo->idxFrom(m_widthInGroups)][gp_sizeIdxInfo->idxFrom(m_heightInGroups)])
+#else
   , m_scan                      (g_scanOrder     [SCAN_GROUPED_4x4][m_scanType][gp_sizeIdxInfo->idxFrom(m_width        )][gp_sizeIdxInfo->idxFrom(m_height        )])
-  , m_scanPosX                  (g_scanOrderPosXY[SCAN_GROUPED_4x4][m_scanType][gp_sizeIdxInfo->idxFrom(m_width        )][gp_sizeIdxInfo->idxFrom(m_height        )][0])
-  , m_scanPosY                  (g_scanOrderPosXY[SCAN_GROUPED_4x4][m_scanType][gp_sizeIdxInfo->idxFrom(m_width        )][gp_sizeIdxInfo->idxFrom(m_height        )][1])
   , m_scanCG                    (g_scanOrder[SCAN_UNGROUPED  ][m_scanType][gp_sizeIdxInfo->idxFrom(m_widthInGroups)][gp_sizeIdxInfo->idxFrom(m_heightInGroups)])
+#endif
   , m_CtxSetLastX               (Ctx::LastX[m_chType])
   , m_CtxSetLastY               (Ctx::LastY[m_chType])
-  , m_maxLastPosX               (g_uiGroupIdx[m_width - 1])
-  , m_maxLastPosY               (g_uiGroupIdx[m_height - 1])
+#if JVET_M0257
+  , m_maxLastPosX(g_uiGroupIdx[std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, m_width) - 1])
+  , m_maxLastPosY(g_uiGroupIdx[std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, m_height) - 1])
+#else
+  , m_maxLastPosX(g_uiGroupIdx[m_width - 1])
+  , m_maxLastPosY(g_uiGroupIdx[m_height - 1])
+#endif
   , m_lastOffsetX               (0)
   , m_lastOffsetY               (0)
   , m_lastShiftX                (0)
@@ -137,7 +155,7 @@ CoeffCodingContext::CoeffCodingContext(const TransformUnit& tu, ComponentID comp
 void CoeffCodingContext::initSubblock( int SubsetId, bool sigGroupFlag )
 {
   m_subSetId                = SubsetId;
-  m_subSetPos               = m_scanCG[ m_subSetId ];
+  m_subSetPos               = m_scanCG[m_subSetId].idx;
   m_subSetPosY              = m_subSetPos / m_widthInGroups;
   m_subSetPosX              = m_subSetPos - ( m_subSetPosY * m_widthInGroups );
   m_minSubPos               = m_subSetId << m_log2CGSize;
@@ -262,8 +280,8 @@ void DeriveCtx::CtxSplit( const CodingStructure& cs, Partitioner& partitioner, u
   //////////////////////////
   // CTX is h/v bt (0-3)
   //////////////////////////
-  ctxHorBt = ( partitioner.currBtDepth >= 2 ? 1 : 0 );
-  ctxVerBt = ( partitioner.currBtDepth >= 2 ? 3 : 2 );
+  ctxHorBt = ( partitioner.currMtDepth <= 1 ? 1 : 0 );
+  ctxVerBt = ( partitioner.currMtDepth <= 1 ? 3 : 2 );
 }
 #else
 unsigned DeriveCtx::CtxCUsplit( const CodingStructure& cs, Partitioner& partitioner )
@@ -304,8 +322,17 @@ unsigned DeriveCtx::CtxCUsplit( const CodingStructure& cs, Partitioner& partitio
 }
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+unsigned DeriveCtx::CtxQtCbf( const ComponentID compID, const unsigned trDepth, const bool prevCbCbf, const int ispIdx )
+{
+  if( ispIdx && isLuma( compID ) )
+  {
+    return 2 + (int)prevCbCbf;
+  }
+#else
 unsigned DeriveCtx::CtxQtCbf( const ComponentID compID, const unsigned trDepth, const bool prevCbCbf )
 {
+#endif
   if( compID == COMPONENT_Cr )
   {
     return ( prevCbCbf ? 1 : 0 );
@@ -322,11 +349,7 @@ unsigned DeriveCtx::CtxQtCbf( const ComponentID compID, const unsigned trDepth,
 
 unsigned DeriveCtx::CtxInterDir( const PredictionUnit& pu )
 {
-  if( pu.cs->sps->getSpsNext().getUseLargeCTU() )
-  {
-    return Clip3( 0, 3, 7 - ( ( g_aucLog2[pu.lumaSize().width] + g_aucLog2[pu.lumaSize().height] + 1 ) >> 1 ) );    // VG-ASYMM DONE
-  }
-  return pu.cu->qtDepth;
+  return Clip3( 0, 3, 7 - ( ( g_aucLog2[pu.lumaSize().width] + g_aucLog2[pu.lumaSize().height] + 1 ) >> 1 ) );    // VG-ASYMM DONE
 }
 
 unsigned DeriveCtx::CtxAffineFlag( const CodingUnit& cu )
@@ -451,6 +474,20 @@ unsigned DeriveCtx::CtxPredModeFlag( const CodingUnit& cu )
 }
 #endif
 
+#if JVET_M0483_IBC
+unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu)
+{
+  const CodingStructure *cs = cu.cs;
+  unsigned ctxId = 0;
+  const CodingUnit *cuLeft = cs->getCURestricted(cu.lumaPos().offset(-1, 0), cu, CH_L);
+  ctxId += (cuLeft && CU::isIBC(*cuLeft)) ? 1 : 0;
+
+  const CodingUnit *cuAbove = cs->getCURestricted(cu.lumaPos().offset(0, -1), cu, CH_L);
+  ctxId += (cuAbove && CU::isIBC(*cuAbove)) ? 1 : 0;
+  return ctxId;
+}
+#endif
+
 void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
 {
   CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" );
@@ -470,17 +507,28 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
   pu.mvpIdx [REF_PIC_LIST_1] = NOT_VALID;
   pu.mvpNum [REF_PIC_LIST_0] = NOT_VALID;
   pu.mvpNum [REF_PIC_LIST_1] = NOT_VALID;
+#if JVET_M0483_IBC
+  if (CU::isIBC(*pu.cu))
+  {
+    pu.bv = pu.mv[REF_PIC_LIST_0];
+    pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution
+  }
+#else
   if (interDirNeighbours[candIdx] == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, mvFieldNeighbours[candIdx << 1].refIdx)->getPOC() == pu.cs->slice->getPOC())
   {
     pu.cu->ibc = true;
     pu.bv = pu.mv[REF_PIC_LIST_0];
     pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution
   }
+#endif
   pu.cu->GBiIdx = ( interDirNeighbours[candIdx] == 3 ) ? GBiIdx[candIdx] : GBI_DEFAULT;
 
 #if JVET_M0068_M0171_MMVD_CLEANUP
   PU::restrictBiPredMergeCandsOne(pu);
 #endif
+#if JVET_M0823_MMVD_ENCOPT
+  pu.mmvdEncOptMode = 0;
+#endif
 }
 void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
 {
@@ -501,8 +549,15 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   tempIdx = tempIdx - fPosBaseIdx * (MMVD_MAX_REFINE_NUM);
   fPosStep = tempIdx / 4;
   fPosPosition = tempIdx - fPosStep * (4);
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  int offset = refMvdCands[fPosStep];
+  if ( pu.cu->slice->getDisFracMMVD() )
+  {
+    offset <<= 2;
+  }
+#else
   const int offset = refMvdCands[fPosStep];
+#endif
   const int refList0 = mmvdBaseMv[fPosBaseIdx][0].refIdx;
   const int refList1 = mmvdBaseMv[fPosBaseIdx][1].refIdx;
 
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index 4f2c0d90327606deffffdf26773083927762a763..5e6b2db73a4ee36c8b5738c6055c26ca065df37d 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -70,6 +70,10 @@ public:
   int             cgPosX          ()                        const { return m_subSetPosX; }
   unsigned        width           ()                        const { return m_width; }
   unsigned        height          ()                        const { return m_height; }
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  unsigned        log2CGWidth     ()                        const { return m_log2CGWidth; }
+  unsigned        log2CGHeight    ()                        const { return m_log2CGHeight; }
+#endif
   unsigned        log2CGSize      ()                        const { return m_log2CGSize; }
   unsigned        log2BlockWidth  ()                        const { return m_log2BlockWidth; }
   unsigned        log2BlockHeight ()                        const { return m_log2BlockHeight; }
@@ -82,7 +86,7 @@ public:
   int             maxSubPos       ()                        const { return m_maxSubPos; }
   bool            isLast          ()                        const { return ( ( m_scanPosLast >> m_log2CGSize ) == m_subSetId ); }
   bool            isNotFirst      ()                        const { return ( m_subSetId != 0 ); }
-  bool            isSigGroup      ( int       scanPosCG )   const { return m_sigCoeffGroupFlag[ m_scanCG[ scanPosCG ] ]; }
+  bool            isSigGroup(int scanPosCG) const { return m_sigCoeffGroupFlag[m_scanCG[scanPosCG].idx]; }
   bool            isSigGroup      ()                        const { return m_sigCoeffGroupFlag[ m_subSetPos ]; }
 #if HEVC_USE_SIGN_HIDING
   bool            signHiding      ()                        const { return m_signHiding; }
@@ -90,9 +94,9 @@ public:
                                     int       posLast   )   const { return ( m_signHiding && ( posLast - posFirst >= SBH_THRESHOLD ) ); }
 #endif
   CoeffScanType   scanType        ()                        const { return m_scanType; }
-  unsigned        blockPos        ( int       scanPos   )   const { return m_scan[ scanPos ]; }
-  unsigned        posX            ( int       scanPos   )   const { return m_scanPosX[ scanPos ]; }
-  unsigned        posY            ( int       scanPos   )   const { return m_scanPosY[ scanPos ]; }
+  unsigned        blockPos(int scanPos) const { return m_scan[scanPos].idx; }
+  unsigned        posX(int scanPos) const { return m_scan[scanPos].x; }
+  unsigned        posY(int scanPos) const { return m_scan[scanPos].y; }
   unsigned        maxLastPosX     ()                        const { return m_maxLastPosX; }
   unsigned        maxLastPosY     ()                        const { return m_maxLastPosY; }
   unsigned        lastXCtxId      ( unsigned  posLastX  )   const { return m_CtxSetLastX( m_lastOffsetX + ( posLastX >> m_lastShiftX ) ); }
@@ -101,8 +105,8 @@ public:
 
   unsigned sigCtxIdAbs( int scanPos, const TCoeff* coeff, const int state )
   {
-    const uint32_t    posY      = m_scanPosY[ scanPos ];
-    const uint32_t    posX      = m_scanPosX[ scanPos ];
+    const uint32_t posY      = m_scan[scanPos].y;
+    const uint32_t posX      = m_scan[scanPos].x;
     const TCoeff* pData     = coeff + posX + posY * m_width;
     const int     diag      = posX + posY;
     int           numPos    = 0;
@@ -160,8 +164,8 @@ public:
 
   unsigned templateAbsSum( int scanPos, const TCoeff* coeff )
   {
-    const uint32_t  posY  = m_scanPosY[scanPos];
-    const uint32_t  posX  = m_scanPosX[scanPos];
+    const uint32_t  posY  = m_scan[scanPos].y;
+    const uint32_t  posX  = m_scan[scanPos].x;
     const TCoeff*   pData = coeff + posX + posY * m_width;
     int             sum   = 0;
     if (posX < m_width - 1)
@@ -213,10 +217,8 @@ private:
   const bool                m_extendedPrecision;
   const int                 m_maxLog2TrDynamicRange;
   CoeffScanType             m_scanType;
-  const unsigned*           m_scan;
-  const unsigned*           m_scanPosX;
-  const unsigned*           m_scanPosY;
-  const unsigned*           m_scanCG;
+  const ScanElement *       m_scan;
+  const ScanElement *       m_scanCG;
   const CtxSet              m_CtxSetLastX;
   const CtxSet              m_CtxSetLastY;
   const unsigned            m_maxLastPosX;
@@ -308,7 +310,11 @@ void     CtxSplit     ( const CodingStructure& cs, Partitioner& partitioner, uns
 unsigned CtxCUsplit   ( const CodingStructure& cs, Partitioner& partitioner );
 unsigned CtxBTsplit   ( const CodingStructure& cs, Partitioner& partitioner );
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+unsigned CtxQtCbf     ( const ComponentID compID, const unsigned trDepth, const bool prevCbCbf = false, const int ispIdx = 0 );
+#else
 unsigned CtxQtCbf     ( const ComponentID compID, const unsigned trDepth, const bool prevCbCbf );
+#endif
 unsigned CtxInterDir  ( const PredictionUnit& pu );
 unsigned CtxSkipFlag  ( const CodingUnit& cu );
 unsigned CtxIMVFlag   ( const CodingUnit& cu );
@@ -317,6 +323,9 @@ unsigned CtxTriangleFlag( const CodingUnit& cu );
 #if JVET_M0502_PRED_MODE_CTX
 unsigned CtxPredModeFlag( const CodingUnit& cu );
 #endif
+#if JVET_M0483_IBC
+unsigned CtxIBCFlag(const CodingUnit& cu);
+#endif
 }
 
 #endif // __CONTEXTMODELLING__
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index cbc516d354ffa006e10826ec03b36f8bb78fb434..566a85793a3ac598ed6de281b603288309d75662 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -350,12 +350,12 @@ std::vector<std::vector<uint8_t>> ContextSetCfg::sm_InitTables( NUMBER_OF_SLICE_
 const CtxSet ContextSetCfg::SplitFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0421_SPLIT_SIG
-  // |-------- do split ctx -------------------| 
-  {  93, 124, 141, 123, 125, 141, 139, 126, 157, },
-  { 108, 139, 156, 138, 140, 141, 139, 141, 143, },
-  { 153, 154, 172, 153, 140, 156, 154, 127, 159, },
+  // |-------- do split ctx -------------------|
+  { 122, 124, 141, 108, 125, 156, 138, 126, 143, },
+  { 93, 139, 171, 124, 125, 141, 139, 141, 158, },
+  { 138, 154, 172, 124, 140, 142, 154, 127, 175, },
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, },
+  { 9, 13, 8, 8, 13, 12, 5, 10, 12, },
 #endif
 #else
 #if JVET_M0453_CABAC_ENGINE
@@ -374,31 +374,31 @@ const CtxSet ContextSetCfg::SplitFlag = ContextSetCfg::addCtxSet
 #if JVET_M0421_SPLIT_SIG
 const CtxSet ContextSetCfg::SplitQtFlag = ContextSetCfg::addCtxSet
 ({
-  { 153, 126, 142, 137, 109, 155, },
-  { 153, 126, 157, 122, 138, 140, },
-  { 153, 125, 127, 137, 153, 155, },
+  { 138, 140, 142, 136, 138, 140, },
+  { 139, 126, 142, 107, 138, 125, },
+  { 139, 125, 127, 136, 153, 126, },
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, DWS, DWS, DWS, DWS, DWS, },
+  { 0, 8, 8, 12, 12, 8, },
 #endif
 });
 
 const CtxSet ContextSetCfg::SplitHvFlag = ContextSetCfg::addCtxSet
 ({
-  { 154, 168, 155, 153, 155, },
-  { 154, 168, 170, 153, 170, },
-  { 154, 153, 140, 153, 154, },
+  { 154, 168, 155, 139, 155, },
+  { 169, 168, 170, 153, 170, },
+  { 154, 168, 140, 153, 169, },
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, DWS, DWS, DWS, DWS, },
+  { 10, 9, 9, 8, 8, },
 #endif
 });
 
 const CtxSet ContextSetCfg::Split12Flag = ContextSetCfg::addCtxSet
 ({
-  { 140, 154, 140, 154, },
-  { 155, 169, 140, 154, },
-  { 155, 154, 155, 154, },
+  { 154, 140, 154, 140, },
+  { 169, 155, 154, 140, },
+  { 154, 170, 154, 170, },
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, DWS, DWS, DWS, },
+  { 12, 12, 12, 12, },
 #endif
 });
 #else
@@ -421,10 +421,10 @@ const CtxSet ContextSetCfg::BTSplitFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::SkipFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  197, 214, 230,},
-  {  197, 184, 200,},
-  {  CNU, CNU, CNU,},
-  {    5,   8,   8,},
+  { 197, 214, 216, },
+  { 197, 198, 185, },
+  { 40, 138, 154, },
+  { 5, 8, 8, },
 #else
   { 183, 185, 186, },
   { 168, 199, 200, },
@@ -435,10 +435,10 @@ const CtxSet ContextSetCfg::SkipFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  125,},
-  {  110,},
-  {  CNU,},
-  {    5,},
+  { 111, },
+  { 111, },
+  { 153, },
+  { 5, },
 #else
   { 125, },
   { 110, },
@@ -449,10 +449,10 @@ const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MergeIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
+  { 138, },
+  { 154, },
   { 153, },
-  {  154,},
-  { CNU, },
-  {    8,},
+  { 8, },
 #else
   { 167, },
   { 138, },
@@ -463,10 +463,10 @@ const CtxSet ContextSetCfg::MergeIdx = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  135,},
-  {  122,},
-  {  CNU,},
-  {    9,},
+  { 120, },
+  { 122, },
+  { CNU, },
+  { 8, },
 #else
   { 136, },
   { 167, },
@@ -480,7 +480,7 @@ const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
   { 154, },
   { 154, },
   { CNU, },
-  {   10,},
+  { 10, },
 #else
   { 154, },
   { 154, },
@@ -491,10 +491,10 @@ const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  { 228, },
-  {  245,},
+  { 213, },
+  { 244, },
   { CNU, },
-  {    1,},
+  { 1, },
 #else
   { 213, },
   { 169, },
@@ -520,10 +520,10 @@ const CtxSet ContextSetCfg::PredMode = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
 #if JVET_M0502_PRED_MODE_CTX
-  { 193, 193, },
-  { 151, 151, },
+  { 192, 168, },
+  { 165, 139, },
   { CNU, CNU, },
-  {   1,   1, },
+  { 5, 2, },
 #else
   {  193,},
   {  151,},
@@ -546,10 +546,10 @@ const CtxSet ContextSetCfg::PredMode = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MultiRefLineIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {   90, 212, CNU,},
-  {  118, 212, CNU,},
-  {  134, 184, CNU,},
-  {    8,   8, DWS,},
+  { 90, 212, CNU, },
+  { 118, 212, CNU, },
+  { 119, 169, CNU, },
+  { 8, 8, DWS, },
 #else
   { 151, 183, CNU, },
   { 165, 183, CNU, },
@@ -557,43 +557,31 @@ const CtxSet ContextSetCfg::MultiRefLineIdx = ContextSetCfg::addCtxSet
 #endif
 });
 
-const CtxSet ContextSetCfg::IPredMode[] =
-{
-  ContextSetCfg::addCtxSet
-  ({
+const CtxSet ContextSetCfg::IntraLumaMpmFlag = ContextSetCfg::addCtxSet
+({
 #if JVET_M0453_CABAC_ENGINE
-    {  169,},
-    {  169,},
-    {  156,},
-    {    1,},
+  { 154, },
+  { 154, },
+  { 170, },
+  { 6, },
 #else
     { 183, },
     { 154, },
     { 156, },
 #endif
-  }),
-  ContextSetCfg::addCtxSet
-  ({
-#if JVET_M0453_CABAC_ENGINE
-    {  CNU, 137, 139, 140, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU,},
-    {  CNU, 138, 139, 169, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU,},
-    {  CNU, 154, 139, 154, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU,},
-    {  DWS,   5,   8,   9, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS,  },
-#else
-    { CNU, 152, 139, 154, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
-    { CNU, 138, 139, 169, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
-    { CNU, 109, 139, 154, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
-#endif
-  }),
-};
+});
 
-const CtxSet ContextSetCfg::PdpcFlag = ContextSetCfg::addCtxSet
+const CtxSet ContextSetCfg::IntraChromaPredMode = ContextSetCfg::addCtxSet
 ({
-  {  107,},
-  {  107,},
-  {  139,},
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, }
+  {  137, 139, 140,},
+  {  138, 139, 169,},
+  {  154, 139, 154,},
+  {    5,   8,   9,},
+#else
+  { 152, 139, 154,},
+  { 138, 139, 169,},
+  { 109, 139, 154,},
 #endif
 });
 
@@ -610,10 +598,10 @@ const CtxSet ContextSetCfg::DeltaQP = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::InterDir = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  126, 125, 110,  79, 208,},
-  {  126, 111, 110,  79, 224,},
-  {  CNU, CNU, CNU, CNU, CNU,},
-  {    0,   1,   4,   5,   0,},
+  { 111, 125, 110, 94, 192, },
+  { 126, 111, 110, 94, 208, },
+  { CNU, CNU, CNU, CNU, CNU, },
+  { 0, 0, 4, 5, 0, },
 #else
   { 111, 110, 95, 78, 193, },
   { 126, 111, 95, 93, 194, },
@@ -624,10 +612,10 @@ const CtxSet ContextSetCfg::InterDir = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::RefPic = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  110, 139,},
-  {  108, 168,},
-  {  CNU, CNU,},
-  {    4,   5,},
+  { 125, 139, },
+  { 138, 168, },
+  { CNU, CNU, },
+  { 4, 5, },
 #else
   { 139, 139, },
   { 138, 168, },
@@ -638,10 +626,10 @@ const CtxSet ContextSetCfg::RefPic = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::AffineFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  194, 169, 156,},
-  {  180, 182, 155,},
-  {  CNU, CNU, CNU,},
-  {    8,   5,   4,},
+  { 179, 169, 171, },
+  { 180, 168, 155, },
+  { CNU, CNU, CNU, },
+  { 8, 5, 4, },
 #else
   { 196, 184, 171, },
   { 181, 169, 185, },
@@ -653,9 +641,9 @@ const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
   { 138, },
-  { 138, },
+  { 153, },
   { CNU, },
-  {    4,},
+  { 4, },
 #else
   { 123, },
   { 138, },
@@ -666,25 +654,38 @@ const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::AffMergeIdx = ContextSetCfg::addCtxSet
 ( {
 #if JVET_M0453_CABAC_ENGINE
+#if JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
+  { 109, },
+  { 95, },
+  { CNU, },
+  { 0, },
+#else
   {  109, 168, 168, 153, CNU,},
   {   95, 154, 139, 153, CNU,},
   {  CNU, CNU, CNU, CNU, CNU,},
   {    0,   5,   9,   8, DWS,},
+#endif
+#else
+#if JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
+  { 123, },
+  { 109, },
+  { CNU, },
 #else
   { 123, 154, 154, 168, CNU, },
   { 109, 154, 139, 168, CNU, },
   { CNU, CNU, CNU, CNU, CNU, },
 #endif
+#endif
 } );
 
 const CtxSet ContextSetCfg::GBiIdx = ContextSetCfg::addCtxSet
 ({
   // 4 ctx for 1st bin; 1 ctx for each of rest bins
 #if JVET_M0453_CABAC_ENGINE
-  {  228, CNU, CNU, CNU, 154, 170, 143,},
-  {  242, CNU, CNU, CNU, 154, 185, 175,},
-  {  CNU, CNU, CNU, CNU, CNU, CNU, CNU,},
-  {    4, DWS, DWS, DWS,   4,   0,   0,},
+  { 228, CNU, CNU, CNU, 125, 155, 175, },
+  { 242, CNU, CNU, CNU, 154, 170, 237, },
+  { CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
+  { 4, DWS, DWS, DWS, 4, 0, 0, },
 #else
   { 199, CNU, CNU, CNU, 124, 169, 127, },
   { 154, CNU, CNU, CNU, 124, 185, 143, },
@@ -696,9 +697,9 @@ const CtxSet ContextSetCfg::Mvd = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
   { 169, 183, },
-  {  155, 154,},
-  { CNU, CNU, },
-  {    9,   5,},
+  { 155, 154, },
+  { 141, 156, },
+  { 9, 5, },
 #else
   { 169, 183, },
   { 155, 198, },
@@ -706,23 +707,13 @@ const CtxSet ContextSetCfg::Mvd = ContextSetCfg::addCtxSet
 #endif
 });
 
-const CtxSet ContextSetCfg::TransSubdivFlag = ContextSetCfg::addCtxSet
-({
-  {  224, 167, 122, 122, 122},
-  {  124, 138,  94,  94,  94},
-  {  153, 138, 138, 138, 138},
-#if JVET_M0453_CABAC_ENGINE
-  { DWS, DWS, DWS, DWS, DWS, }
-#endif
-});
-
 const CtxSet ContextSetCfg::QtRootCbf = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {   94,},
-  {   94,},
-  {  CNU,},
-  {    4,},
+  { 109, },
+  { 95, },
+  { 110, },
+  { 4, },
 #else
   { 94, },
   { 95, },
@@ -732,6 +723,24 @@ const CtxSet ContextSetCfg::QtRootCbf = ContextSetCfg::addCtxSet
 
 const CtxSet ContextSetCfg::QtCbf[] =
 {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+#if JVET_M0453_CABAC_ENGINE
+  ContextSetCfg::addCtxSet
+  ({
+    { 141, 127, 139, 140, },
+    { 142, 127, 139, 140, },
+    { CNU, 111, 124, 111, },
+    { 1, 5, 9, 8, },
+  }),
+#else
+  ContextSetCfg::addCtxSet
+  ({
+    { 140, 141, CNU, CNU},
+    { 155, 127, CNU, CNU},
+    { CNU, 126, CNU, CNU},
+  }),
+#endif
+#else
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
@@ -745,13 +754,14 @@ const CtxSet ContextSetCfg::QtCbf[] =
     { CNU, 126, },
 #endif
   }),
+#endif
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  178, 154, CNU, CNU, CNU,},
-    {  164, 154, CNU, CNU, CNU,},
-    {  109, CNU, CNU, CNU, CNU,},
-    {    5,   4, DWS, DWS, DWS,  },
+    { 163, 154, CNU, CNU, CNU, },
+    { 164, 154, CNU, CNU, CNU, },
+    { 109, CNU, CNU, CNU, CNU, },
+    { 5, 8, DWS, DWS, DWS, },
 #else
     { 149, 168, CNU, CNU, CNU, },
     { 164, 154, CNU, CNU, CNU, },
@@ -761,10 +771,10 @@ const CtxSet ContextSetCfg::QtCbf[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  162, 154,},
-    {  192, 154,},
-    {  151, 155,},
-    {    5,   4,  },
+    { 161, 154, },
+    { 192, 154, },
+    { 151, 155, },
+    { 5, 5, },
 #else
     { 192, 153, },
     { 178, 139, },
@@ -778,10 +788,10 @@ const CtxSet ContextSetCfg::SigCoeffGroup[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  120, 185,},
-    {  106, 171,},
-    {  107, 159,},
-    {    8,   5,  },
+    { 105, 155, },
+    { 106, 156, },
+    { 107, 158, },
+    { 8, 5, },
 #else
     { 106, 170, },
     { 121, 141, },
@@ -791,10 +801,10 @@ const CtxSet ContextSetCfg::SigCoeffGroup[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {   91, 141,},
-    {   90, 156,},
-    {   76, 127,},
-    {    8,   8,  },
+    { 91, 155, },
+    { 90, 141, },
+    { 76, 127, },
+    { 5, 8, },
 #else
     { 91, 140, },
     { 105, 155, },
@@ -803,18 +813,18 @@ const CtxSet ContextSetCfg::SigCoeffGroup[] =
   }),
   ContextSetCfg::addCtxSet
   ({
-    {  122, 143,  },
-    {   78, 111,  },
-    {  135, 155,  },
+    { CNU, CNU, },
+    { CNU, CNU, },
+    { CNU, CNU, },
 #if JVET_M0453_CABAC_ENGINE
     { DWS, DWS, }
 #endif
   }),
   ContextSetCfg::addCtxSet
   ({
-    {   91, 141,  },
-    {   60, 140,  },
-    {  104, 139,  },
+    { CNU, CNU, },
+    { CNU, CNU, },
+    { CNU, CNU, },
 #if JVET_M0453_CABAC_ENGINE
     { DWS, DWS, }
 #endif
@@ -826,10 +836,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  104, 137, 152, 182, 168, 169, 161, 167, 182, 168, 183, 170, 208, 213, 183, 183, 169, 185,},
-    {  133, 152, 167, 168, 183, 140, 163, 182, 168, 183, 169, 170, 166, 213, 183, 169, 184, 156,},
-    {  104, 138, 153, 139, 125, 111, 134, 139, 139, 140, 155, 127, 137, 185, 169, 185, 156, 143,},
-    {   12,   9,   9,   9,   9,  10,   9,   9,   9,   9,   9,   9,   8,   8,   8,   8,   8,   9,  },
+    { 88, 166, 152, 182, 168, 154, 0, 167, 182, 168, 183, 155, 193, 213, 183, 183, 169, 185, },
+    { 132, 152, 167, 168, 183, 140, 177, 182, 168, 154, 169, 155, 180, 213, 183, 169, 184, 156, },
+    { 89, 138, 153, 139, 154, 140, 134, 139, 139, 140, 140, 141, 137, 170, 169, 170, 141, 157, },
+    { 12, 9, 9, 9, 9, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, },
 #else
     { 105, 152, 167, 153, 168, 169, 104, 167, 182, 183, 183, 170, 209, 213, 183, 183, 169, 185, },
     { 119, 152, 167, 168, 183, 140, 134, 182, 168, 183, 169, 185, 166, 228, 183, 198, 184, 156, },
@@ -839,10 +849,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  133, 167, 153, 168, 154, 155, 151, 199, 183, 199, 199, 157,},
-    {  104, 138, 153, 139, 154, 155, 181, 229, 169, 229, 170, 157,},
-    {   74, 153, 168, 169, 140, 141, 152, 215, 155, 172, 171, 143,},
-    {    9,   9,  12,   9,   9,  13,   8,   5,   8,   8,   8,   9,  },
+    { 72, 167, 153, 168, 154, 155, 180, 199, 183, 199, 199, 186, },
+    { 133, 138, 153, 139, 154, 140, 181, 229, 169, 229, 170, 157, },
+    { 43, 153, 168, 169, 154, 155, 152, 215, 155, 201, 171, 143, },
+    { 9, 9, 12, 9, 13, 13, 5, 5, 8, 8, 8, 9, },
 #else
     { 148, 167, 153, 168, 154, 140, 166, 199, 183, 199, 199, 172, },
     { 134, 168, 168, 169, 169, 170, 196, 244, 184, 244, 200, 172, },
@@ -852,10 +862,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  152, 127, 187, 201, 172, 173, 197, 248, 188, 232, 188, 205, 182, 223, 223, 223, 223, 223,},
-    {  123, 142, 172, 172, 172, 218, 138, 248, 248, 248, 248, 223, 139, 223, 223, 223, 223, 223,},
-    {   93, 157, 143, 158, 203, 190, 123, 223, 175, 253, 253, 223, 124, 223, 223, 223, 223, 223,},
-    {    9,  12,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   0,   0,   0,   0,   0,  },
+    { 152, 156, 201, 186, 186, 187, 182, 248, 188, 232, 188, 205, 182, 223, 223, 223, 223, 223, },
+    { 123, 142, 157, 172, 172, 218, 138, 249, 248, 248, 219, 223, 139, 223, 223, 223, 223, 223, },
+    { 93, 142, 157, 143, 188, 175, 138, 238, 205, 238, 253, 237, 139, 223, 223, 223, 223, 253, },
+    { 9, 12, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 8, 0, 0, 0, 0, 0, },
 #else
     { 152, 127, 173, 201, 187, 173, 197, 203, 188, 217, 188, 189, 182, 223, 223, 223, 223, 223, },
     { 123, 142, 202, 172, 172, 203, 138, 188, 233, 203, 203, 191, 139, 223, 223, 223, 223, 223, },
@@ -865,10 +875,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  182, 171, 143, 158, 172, 189, 183, 223, 223, 223, 223, 223,},
-    {  168, 156, 173, 201, 172, 204, 169, 223, 223, 223, 223, 223,},
-    {  152, 173, 157, 187, 189, 252, 170, 223, 223, 223, 223, 223,},
-    {    8,   9,  12,   8,   8,   8,   4,   0,   0,   0,   0,   0,  },
+    { 182, 171, 143, 158, 172, 189, 183, 223, 223, 223, 223, 223, },
+    { 168, 156, 173, 216, 172, 219, 169, 223, 223, 223, 223, 223, },
+    { 152, 173, 157, 187, 204, 253, 170, 223, 223, 223, 223, 223, },
+    { 8, 9, 12, 8, 8, 8, 4, 0, 2, 2, 2, 2, },
 #else
     { 182, 171, 143, 158, 172, 202, 168, 223, 223, 223, 223, 223, },
     { 168, 156, 173, 201, 157, 203, 198, 223, 223, 223, 223, 223, },
@@ -878,10 +888,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  123, 158, 223, 175, 217, 205, 212, 223, 223, 220, 205, 223, 208, 223, 223, 223, 223, 223,},
-    {  123, 174, 223, 189, 203, 221, 138, 223, 223, 223, 190, 223, 196, 223, 223, 223, 223, 223,},
-    {  107, 159, 223, 191, 205, 253,  63, 223, 223, 223, 223, 223,  14, 223, 223, 223, 223, 223,},
-    {    8,   8,   4,   8,   8,   8,   8,   0,   0,   4,   8,   8,   4,   0,   0,   0,   0,   0,  },
+    { 123, 173, 223, 191, 232, 251, 212, 223, 223, 236, 206, 223, 192, 223, 223, 223, 223, 223, },
+    { 123, 175, 223, 175, 218, 223, 138, 223, 223, 223, 222, 223, 196, 223, 223, 223, 223, 223, },
+    { 107, 174, 223, 238, 251, 223, 63, 223, 223, 238, 223, 238, 12, 223, 223, 223, 223, 223, },
+    { 8, 8, 4, 8, 8, 8, 8, 0, 0, 4, 8, 5, 4, 2, 2, 2, 2, 1, },
 #else
     { 137, 142, 190, 188, 202, 189, 241, 191, 191, 189, 189, 190, 195, 223, 223, 223, 223, 223, },
     { 123, 187, 191, 173, 173, 248, 138, 191, 191, 191, 203, 191, 196, 223, 223, 223, 223, 223, },
@@ -891,10 +901,10 @@ const CtxSet ContextSetCfg::SigFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  167, 201, 223, 233, 189, 223, 181, 223, 223, 223, 223, 223,},
-    {  167, 171, 223, 174, 233, 223, 152, 223, 223, 223, 223, 223,},
-    {  166, 219, 223, 235, 233, 252, 123, 223, 223, 223, 223, 223,},
-    {    8,   8,   8,   8,   8,   8,   8,   0,   0,   0,   0,   0,  },
+    { 167, 201, 223, 248, 219, 223, 181, 223, 223, 223, 223, 223, },
+    { 167, 171, 223, 175, 248, 223, 152, 223, 223, 223, 223, 223, },
+    { 166, 234, 223, 236, 248, 223, 108, 223, 223, 223, 223, 223, },
+    { 8, 8, 5, 8, 8, 8, 5, 1, 2, 2, 2, 2, },
 #else
     { 167, 200, 175, 188, 174, 175, 196, 223, 223, 223, 223, 223, },
     { 167, 156, 237, 158, 188, 205, 182, 223, 223, 223, 223, 223, },
@@ -909,10 +919,10 @@ const CtxSet ContextSetCfg::ParFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  121, 119, 121, 137, 138, 153,  90, 122, 167, 153, 168, 121, 152, 153, 168, 139, 151, 153, 139, 168, 154,},
-    {  121, 119, 136, 152, 138, 153, 119, 122, 138, 153, 139, 121, 138, 153, 168, 139, 137, 153, 168, 139, 139,},
-    {  121, 135, 137, 152, 138, 153,  91, 137, 138, 153, 139, 151, 138, 153, 139, 139, 138, 168, 139, 154, 139,},
-    {    8,   9,  12,  13,  13,  13,  10,  13,  13,  13,  13,  10,  13,  13,  13,  13,  10,  10,  13,  13,  13,  },
+    { 121, 105, 136, 152, 138, 183, 90, 122, 167, 153, 168, 135, 152, 153, 168, 139, 151, 153, 139, 168, 154, },
+    { 121, 119, 136, 137, 138, 153, 104, 122, 138, 153, 139, 106, 138, 153, 168, 139, 137, 153, 168, 139, 139, },
+    { 121, 135, 137, 152, 138, 153, 91, 137, 138, 153, 139, 151, 138, 153, 139, 139, 138, 168, 139, 154, 139, },
+    { 8, 9, 12, 13, 13, 13, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 13, 13, 13, 13, },
 #else
     { 91, 104, 136, 152, 153, 153, 105, 137, 167, 153, 168, 121, 167, 153, 168, 139, 151, 153, 139, 168, 154, },
     { 106, 134, 151, 152, 138, 168, 120, 137, 138, 153, 139, 136, 138, 153, 168, 139, 137, 153, 168, 139, 139, },
@@ -922,10 +932,10 @@ const CtxSet ContextSetCfg::ParFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  136, 120, 152, 138, 138, 153, 136, 168, 154, 168, 139,},
-    {  135, 120, 137, 138, 138, 153, 136, 153, 168, 139, 154,},
-    {  136, 135, 152, 153, 138, 153, 136, 168, 154, 139, 154,},
-    {    8,  10,  12,  12,  13,  13,  10,  10,  10,  12,  13,  },
+    { 151, 120, 152, 138, 153, 153, 136, 168, 154, 168, 154, },
+    { 135, 120, 137, 138, 138, 153, 136, 153, 168, 139, 154, },
+    { 136, 135, 152, 153, 138, 153, 136, 168, 154, 139, 154, },
+    { 8, 10, 12, 12, 13, 13, 10, 10, 13, 13, 13, },
 #else
     { 135, 135, 152, 138, 153, 124, 151, 168, 169, 153, 139, },
     { 120, 150, 152, 153, 153, 153, 166, 168, 168, 139, 154, },
@@ -939,10 +949,10 @@ const CtxSet ContextSetCfg::GtxFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {   60,   0, 102, 119, 150, 137,  42,  44, 120, 136, 123,  86, 119, 151, 152, 153, 104, 136, 138, 153, 125,},
-    {   44,   0,  41, 119, 135, 137,   0,  88, 135, 151, 138, 116, 105, 122, 167, 153, 119, 107, 123, 153, 154,},
-    {   75,  86, 148, 150, 151, 138,  43,  75,  77, 137, 109,  58, 106, 108, 109, 124, 121, 138, 139, 154, 140,},
-    {    4,   5,   9,   9,   9,   6,   5,   9,   8,   9,   9,   9,   9,   8,   8,   8,   9,   8,   8,   8,   8,  },
+    { 31, 73, 118, 75, 152, 109, 42, 44, 105, 107, 109, 0, 119, 136, 152, 124, 118, 136, 138, 153, 140, },
+    { 14, 116, 86, 119, 106, 152, 0, 72, 120, 151, 138, 116, 90, 107, 152, 153, 104, 107, 123, 153, 154, },
+    { 90, 72, 119, 135, 137, 138, 43, 60, 106, 137, 109, 58, 106, 108, 109, 124, 121, 138, 139, 154, 155, },
+    { 4, 1, 8, 8, 4, 2, 5, 9, 9, 8, 9, 9, 9, 9, 8, 9, 9, 8, 9, 8, 8, },
 #else
     { 30, 0, 102, 104, 106, 152, 57, 44, 120, 136, 123, 87, 134, 151, 152, 153, 89, 121, 152, 153, 125, },
     { 88, 0, 102, 149, 150, 152, 101, 103, 150, 151, 138, 102, 105, 122, 167, 153, 90, 107, 123, 153, 154, },
@@ -952,10 +962,10 @@ const CtxSet ContextSetCfg::GtxFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  119,  11, 105, 107, 107, 108, 104, 122, 124, 140, 140,},
-    {  117, 101,  90, 106,  92,  78,  88, 136, 138, 154, 125,},
-    {  194,  56, 105, 122, 122, 123, 118, 106, 153, 154, 140,},
-    {    2,   5,   8,   8,   8,   8,   6,   9,   8,   8,   9,  },
+    { 119, 101, 134, 151, 107, 123, 118, 122, 124, 140, 155, },
+    { 117, 0, 90, 106, 92, 93, 147, 136, 138, 154, 140, },
+    { 194, 40, 120, 122, 122, 138, 103, 121, 153, 154, 155, },
+    { 2, 5, 8, 8, 8, 6, 6, 8, 8, 8, 7, },
 #else
     { 102, 101, 90, 107, 122, 93, 118, 121, 153, 125, 140, },
     { 0, 0, 105, 151, 107, 93, 103, 136, 138, 154, 125, },
@@ -965,10 +975,10 @@ const CtxSet ContextSetCfg::GtxFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {   88, 147, 151, 138, 139, 140, 133, 167, 124, 154, 155, 164, 153, 154, 169, 155, 166, 183, 169, 185, 186,},
-    {  101, 133, 137, 153, 139, 140, 134, 138, 139, 169, 155, 121, 153, 154, 140, 170, 152, 154, 155, 170, 186,},
-    {  119, 120, 123, 153, 139, 140, 121, 153, 139, 125, 126, 152, 154, 140, 155, 141, 139, 140, 185, 171, 157,},
-    {    8,   5,  10,  12,  13,  10,   9,   9,  10,  12,  10,   9,   9,   9,   9,   9,   8,   8,   8,   8,   9,  },
+    { 43, 177, 181, 168, 154, 170, 133, 167, 139, 154, 155, 164, 153, 154, 169, 155, 181, 183, 169, 185, 186, },
+    { 101, 133, 137, 153, 139, 140, 134, 138, 139, 154, 155, 136, 153, 154, 140, 170, 138, 154, 155, 170, 186, },
+    { 134, 120, 123, 153, 139, 140, 92, 124, 154, 125, 111, 138, 154, 140, 155, 141, 154, 140, 185, 171, 143, },
+    { 8, 5, 9, 9, 12, 9, 9, 10, 13, 12, 10, 9, 10, 10, 10, 10, 8, 9, 8, 8, 10, },
 #else
     { 89, 132, 151, 138, 124, 125, 119, 152, 153, 154, 140, 135, 153, 139, 169, 155, 151, 168, 169, 170, 171, },
     { 118, 101, 137, 138, 139, 140, 149, 138, 139, 154, 155, 136, 153, 154, 140, 170, 152, 139, 140, 155, 186, },
@@ -978,10 +988,10 @@ const CtxSet ContextSetCfg::GtxFlag[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  116, 164, 153, 154, 140, 140, 196, 170, 171, 157, 158,},
-    {  117, 150, 153, 139, 125, 140, 167, 155, 156, 142, 173,},
-    {  134, 136, 153, 154, 125, 111, 168, 170, 201, 172, 173,},
-    {    6,   9,  10,  12,  12,   9,   8,   9,   8,   8,   9,  },
+    { 0, 178, 153, 154, 140, 140, 196, 170, 186, 157, 188, },
+    { 0, 135, 153, 139, 125, 140, 182, 155, 156, 142, 159, },
+    { 163, 136, 153, 154, 125, 140, 183, 170, 201, 187, 174, },
+    { 6, 9, 10, 12, 12, 10, 5, 9, 8, 8, 9, },
 #else
     { 102, 164, 138, 139, 154, 140, 181, 155, 171, 157, 143, },
     { 132, 136, 153, 154, 140, 155, 167, 155, 156, 142, 173, },
@@ -995,10 +1005,10 @@ const CtxSet ContextSetCfg::LastX[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  111, 111, 110, 111, 111, 124, 111, 111, 111,  95, 126, 126, 111, 111, 169, 154, 111, 110, 110, 123, CNU, CNU, CNU, CNU, CNU,},
-    {  125, 110, 109, 111, 125, 123, 111, 111,  95, 108, 126, 126, 110,  95, 183, 154, 140, 110, 124, 137, CNU, CNU, CNU, CNU, CNU,},
-    {  140, 140, 124, 111, 126, 109, 111, 126, 125, 123, 126, 127, 111, 110,  93, 141, 157, 126, 125, 182, CNU, CNU, CNU, CNU, CNU,},
-    {    8,   8,   5,   5,   4,   4,   5,   4,   4,   0,   5,   4,   0,   0,   0,   1,   1,   1,   0,   8, DWS, DWS, DWS, DWS, DWS,  },
+    { 111, 111, 110, 111, 111, 139, 111, 126, 111, 139, 126, 126, 111, 111, 169, 154, 111, 110, 110, 139, CNU, CNU, CNU, CNU, CNU, },
+    { 125, 110, 109, 125, 125, 123, 111, 111, 95, 123, 126, 111, 110, 95, 169, 154, 140, 139, 139, 138, CNU, CNU, CNU, CNU, CNU, },
+    { 125, 140, 124, 111, 111, 109, 111, 126, 125, 123, 111, 141, 111, 125, 79, 155, 142, 170, 140, 183, CNU, CNU, CNU, CNU, CNU, },
+    { 8, 5, 5, 5, 4, 4, 5, 4, 4, 0, 5, 1, 0, 0, 0, 1, 1, 0, 0, 0, DWS, DWS, DWS, DWS, DWS, },
 #else
     { 111, 125, 124, 111, 111, 109, 111, 111, 125, 109, 140, 126, 111, 111, 139, 140, 111, 125, 95, 138, CNU, CNU, CNU, CNU, CNU, },
     { 125, 110, 109, 111, 125, 123, 111, 111, 95, 123, 140, 126, 125, 95, 169, 125, 140, 110, 124, 152, CNU, CNU, CNU, CNU, CNU, },
@@ -1008,10 +1018,10 @@ const CtxSet ContextSetCfg::LastX[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  137, 109,  62, CNU,},
-    {  138, 123,  92, CNU,},
-    {  138, 108,  61, CNU,},
-    {    2,   4,   4, DWS,  },
+    { 122, 124, 63, CNU, },
+    { 138, 123, 92, CNU, },
+    { 138, 108, 47, CNU, },
+    { 2, 1, 1, DWS, },
 #else
     { 123, 109, 63, CNU, },
     { 138, 123, 92, CNU, },
@@ -1025,10 +1035,10 @@ const CtxSet ContextSetCfg::LastY[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  125, 125, 139, 111, 111, 124, 111, 111, 110, 110, 140, 126, 110,  95, 155, 154, 111, 110, 124, 180, CNU, CNU, CNU, CNU, CNU,},
-    {  110,  95, 109, 125, 110,  93, 125, 111, 124, 108, 140, 111,  95, 109, 153, 125, 126, 110, 109, 181, CNU, CNU, CNU, CNU, CNU,},
-    {  110, 110, 109, 125, 111, 108, 111, 126,  95,  93, 111, 127, 111,  95,  47, 155, 158, 156, 140, 137, CNU, CNU, CNU, CNU, CNU,},
-    {    8,   5,   8,   5,   5,   4,   5,   5,   4,   0,   5,   5,   1,   0,   0,   1,   4,   1,   0,   8, DWS, DWS, DWS, DWS, DWS,  },
+    { 125, 125, 139, 125, 111, 139, 111, 111, 110, 110, 140, 126, 125, 125, 140, 139, 111, 110, 124, 181, CNU, CNU, CNU, CNU, CNU, },
+    { 95, 95, 109, 110, 110, 108, 125, 111, 124, 123, 140, 111, 110, 124, 139, 125, 126, 110, 124, 182, CNU, CNU, CNU, CNU, CNU, },
+    { 110, 110, 109, 125, 111, 123, 111, 126, 95, 108, 111, 127, 111, 95, 78, 169, 157, 141, 125, 138, CNU, CNU, CNU, CNU, CNU, },
+    { 8, 5, 8, 5, 5, 4, 5, 5, 4, 0, 5, 5, 1, 0, 0, 1, 4, 1, 0, 0, DWS, DWS, DWS, DWS, DWS, },
 #else
     { 125, 110, 139, 125, 125, 109, 111, 111, 110, 109, 140, 126, 110, 110, 154, 140, 111, 125, 109, 181, CNU, CNU, CNU, CNU, CNU, },
     { 110, 95, 94, 125, 110, 123, 140, 111, 95, 123, 125, 111, 110, 95, 154, 125, 111, 95, 94, 137, CNU, CNU, CNU, CNU, CNU, },
@@ -1038,10 +1048,10 @@ const CtxSet ContextSetCfg::LastY[] =
   ContextSetCfg::addCtxSet
   ({
 #if JVET_M0453_CABAC_ENGINE
-    {  137, 109, 122, CNU,},
-    {  108, 108, 136, CNU,},
-    {  123, 123,  91, CNU,},
-    {    2,   5,   5, DWS,  },
+    { 122, 124, 123, CNU, },
+    { 108, 123, 121, CNU, },
+    { 123, 123, 91, CNU, },
+    { 2, 2, 2, DWS, },
 #else
     { 108, 94, 122, CNU, },
     { 108, 93, 92, CNU, },
@@ -1054,10 +1064,10 @@ const CtxSet ContextSetCfg::LastY[] =
 const CtxSet ContextSetCfg::MVPIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  153,},
+  { 153, },
   { 168, },
-  { CNU, },
-  {   10,},
+  { 168, },
+  { 10, },
 #else
   { 168, },
   { 168, },
@@ -1069,10 +1079,10 @@ const CtxSet ContextSetCfg::MVPIdx = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::SmvdFlag = ContextSetCfg::addCtxSet
 ( {
   { 154, },
-  { 110, },
+  { 125, },
   { CNU, },
 #if JVET_M0453_CABAC_ENGINE
-  { DWS, }
+  { 8, },
 #endif
 } );
 #endif
@@ -1080,10 +1090,10 @@ const CtxSet ContextSetCfg::SmvdFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::SaoMergeFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {   63,},
-  {  244,},
-  {  199,},
-  {    0,},
+  { 47, },
+  { 244, },
+  { 199, },
+  { 0, },
 #else
   { 92, },
   { 214, },
@@ -1094,10 +1104,10 @@ const CtxSet ContextSetCfg::SaoMergeFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::SaoTypeIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {   63,},
-  {   95,},
-  {  110,},
-  {    0,},
+  { 47, },
+  { 95, },
+  { 95, },
+  { 0, },
 #else
   { 77, },
   { 111, },
@@ -1155,10 +1165,10 @@ const CtxSet ContextSetCfg::RdpcmDir = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MTSIndex = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  { 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, CNU, CNU, CNU, },
-  { DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, },
+  { CNU, 155, 155, 140, 140, CNU, 216, 153, 153, 0, CNU, },
+  { CNU, 155, 155, 140, 140, CNU, 233, 167, 153, 0, CNU, },
+  { CNU, CNU, 140, 140, 140, CNU, 219, 138, 153, 0, CNU, },
+  { DWS, 8, 8, 8, 8, DWS, 4, 8, 9, 3, DWS, },
 #else
   { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
   { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
@@ -1195,6 +1205,60 @@ const CtxSet ContextSetCfg::EMTCuFlag = ContextSetCfg::addCtxSet
 });
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+const CtxSet ContextSetCfg::ISPMode = ContextSetCfg::addCtxSet
+({
+  { 152, 154, },
+  { 166, 154, },
+  { 152, 154, },
+#if JVET_M0453_CABAC_ENGINE
+  { 8, 5, },
+#endif
+});
+#endif
+
+#if JVET_M0140_SBT
+const CtxSet ContextSetCfg::SbtFlag = ContextSetCfg::addCtxSet
+( {
+  { 168, 183, },
+  { 197, 183, },
+  { CNU, CNU, },
+#if JVET_M0453_CABAC_ENGINE
+  { 4, 8, },
+#endif
+} );
+
+const CtxSet ContextSetCfg::SbtQuadFlag = ContextSetCfg::addCtxSet
+( {
+  { 168, },
+  { 168, },
+  { CNU, },
+#if JVET_M0453_CABAC_ENGINE
+  { 9, },
+#endif
+} );
+
+const CtxSet ContextSetCfg::SbtHorFlag = ContextSetCfg::addCtxSet
+( {
+  { 139, 154, 139, },
+  { 139, 154, 139, },
+  { CNU, CNU, CNU, },
+#if JVET_M0453_CABAC_ENGINE
+  { 8, 5, 4, },
+#endif
+} );
+
+const CtxSet ContextSetCfg::SbtPosFlag = ContextSetCfg::addCtxSet
+( {
+  { 154, },
+  { 154, },
+  { CNU, },
+#if JVET_M0453_CABAC_ENGINE
+  { 13, },
+#endif
+} );
+#endif
+
 const CtxSet ContextSetCfg::CrossCompPred = ContextSetCfg::addCtxSet
 ({
   {  154, 154, 154, 154, 154, 154, 154, 154, 154, 154,},
@@ -1228,15 +1292,28 @@ const CtxSet ContextSetCfg::ChromaQpAdjIdc = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
+#if JVET_M0246_AFFINE_AMVR
+  { 212, 199, 215, 180, 183, 242, },
+  { 213, 229, 244, 166, 198, 244, },
+  { CNU, CNU, CNU, 152, CNU, CNU, },
+  { 1, 4, 4, 5, 1, 0, },
+#else
   {  227, 214, 230, 195,},
   {  213, 229, 230, 166,},
   {  CNU, CNU, CNU, CNU,},
   {    1,   4,   4,   5,},
+#endif
+#else
+#if JVET_M0246_AFFINE_AMVR
+  { 212, 214, 230, 182, 212, 214 },
+  { 212, 214, 230, 182, 212, 214 },
+  { CNU, CNU, CNU, CNU, CNU, CNU },
 #else
   { 212, 214, 230, 182, },
   { 212, 214, 230, 182, },
   { CNU, CNU, CNU, CNU, },
 #endif
+#endif
 });
 
 const CtxSet ContextSetCfg::ctbAlfFlag =
@@ -1244,10 +1321,10 @@ const CtxSet ContextSetCfg::ctbAlfFlag =
   ContextSetCfg::addCtxSet
   ( {
 #if JVET_M0453_CABAC_ENGINE
-    {  154, 201, 203, 168, 247, 249, 168, 248, 235,},
-    {  139, 186, 203, 168, 247, 249, 168, 247, 234,},
-    {  219, 237, 253, 187, 234, 235, 216, 219, 250,},
-    {    0,   0,   4,   0,   0,   0,   0,   0,   0,  },
+    { 154, 186, 174, 183, 233, 250, 168, 248, 250, },
+    { 139, 186, 203, 183, 247, 249, 183, 232, 249, },
+    { 219, 236, 238, 232, 249, 235, 246, 234, 251, },
+    { 0, 0, 4, 0, 0, 1, 0, 0, 1, },
 #else
     { 138, 141, 173, 122, 170, 203, 151, 170, 203, },
     { 153, 156, 188, 137, 185, 218, 152, 185, 218, },
@@ -1259,10 +1336,10 @@ const CtxSet ContextSetCfg::ctbAlfFlag =
 const CtxSet ContextSetCfg::MHIntraFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  240,},
-  {  197,},
-  {  CNU,},
-  {    1,},
+  { 225, },
+  { 197, },
+  { CNU, },
+  { 1, },
 #else
   { 226, },
   { 227, },
@@ -1273,10 +1350,10 @@ const CtxSet ContextSetCfg::MHIntraFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MHIntraPredMode = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  156, CNU, CNU, CNU,},
-  {  156, CNU, CNU, CNU,},
-  {  CNU, CNU, CNU, CNU,},
-  {    9, DWS, DWS, DWS,},
+  { 156, CNU, CNU, CNU, },
+  { 156, CNU, CNU, CNU, },
+  { CNU, CNU, CNU, CNU, },
+  { 9, DWS, DWS, DWS, },
 #else
   { 155, CNU, CNU, CNU, },
   { 141, CNU, CNU, CNU, },
@@ -1287,10 +1364,10 @@ const CtxSet ContextSetCfg::MHIntraPredMode = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::TriangleFlag = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  149, 137, 137,},
-  {  165, 151, 137,},
-  {  CNU, CNU, CNU,},
-  {    9,  13,  10,},
+  { 149, 123, 123, },
+  { 151, 152, 138, },
+  { CNU, CNU, CNU, },
+  { 8, 12, 9, },
 #else
   { 165, 137, 153, },
   { 106, 122, 138, },
@@ -1301,10 +1378,10 @@ const CtxSet ContextSetCfg::TriangleFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::TriangleIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_M0453_CABAC_ENGINE
-  {  141,},
-  {  141,},
-  {  CNU,},
-  {    8,},
+  { CNU, },
+  { CNU, },
+  { CNU, },
+  { DWS, },
 #else
   { 155, },
   { 126, },
@@ -1313,6 +1390,22 @@ const CtxSet ContextSetCfg::TriangleIdx = ContextSetCfg::addCtxSet
 });
 // clang-format on
 
+#if JVET_M0483_IBC
+const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet
+({
+#if JVET_M0453_CABAC_ENGINE
+  { 0, 154, 141, },
+  { 0, 153, 140, },
+  { 132, 153, 125, },
+  { 5, 5, 8, },
+#else
+  { 165, 137, 153, },
+  { 106, 122, 138, },
+  { CNU, CNU, CNU, },
+#endif
+});
+#endif
+
 const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size();
 
 
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index fcc59f0152a14eddf03460f23822adff43834592..79bfc51f179f0abd347614993a7c6d096a82e796 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -258,8 +258,8 @@ public:
   static const CtxSet   PartSize;
   static const CtxSet   PredMode;
   static const CtxSet   MultiRefLineIdx;
-  static const CtxSet   IPredMode       [2];    // [ ChannelType ]
-  static const CtxSet   PdpcFlag;
+  static const CtxSet   IntraLumaMpmFlag;
+  static const CtxSet   IntraChromaPredMode;
   static const CtxSet   DeltaQP;
   static const CtxSet   InterDir;
   static const CtxSet   RefPic;
@@ -270,7 +270,6 @@ public:
   static const CtxSet   AffineType;
   static const CtxSet   AffMergeIdx;
   static const CtxSet   Mvd;
-  static const CtxSet   TransSubdivFlag;
   static const CtxSet   QtRootCbf;
   static const CtxSet   QtCbf           [3];    // [ channel ]
   static const CtxSet   SigCoeffGroup   [4];    // [ ChannelType ]
@@ -293,6 +292,12 @@ public:
 #if !JVET_M0464_UNI_MTS
   static const CtxSet   EMTTuIndex;
   static const CtxSet   EMTCuFlag;
+#endif
+#if JVET_M0140_SBT
+  static const CtxSet   SbtFlag;
+  static const CtxSet   SbtQuadFlag;
+  static const CtxSet   SbtHorFlag;
+  static const CtxSet   SbtPosFlag;
 #endif
   static const CtxSet   CrossCompPred;
   static const CtxSet   ChromaQpAdjFlag;
@@ -306,6 +311,12 @@ public:
   static const CtxSet   TriangleIdx;
 #if JVET_M0444_SMVD
   static const CtxSet   SmvdFlag;
+#endif
+#if JVET_M0483_IBC
+  static const CtxSet   IBCFlag;
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  static const CtxSet   ISPMode;
 #endif
   static const unsigned NumberOfContexts;
 
diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp
index 820920082c726b577d39675070e5048683ce6888..e318345f2149e2d9184dd63a27153fdf0e3b2226 100644
--- a/source/Lib/CommonLib/DepQuant.cpp
+++ b/source/Lib/CommonLib/DepQuant.cpp
@@ -87,6 +87,10 @@ namespace DQIntern
     NbInfoSbb     nextNbInfoSbb;
     int           nextSbbRight;
     int           nextSbbBelow;
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    int           posX;
+    int           posY;
+#endif
   };
 
   class Rom;
@@ -111,10 +115,8 @@ namespace DQIntern
     unsigned          m_widthInSbb;
     unsigned          m_heightInSbb;
     CoeffScanType     m_scanType;
-    const unsigned*   m_scanSbbId2SbbPos;
-    const unsigned*   m_scanId2BlkPos;
-    const unsigned*   m_scanId2PosX;
-    const unsigned*   m_scanId2PosY;
+    const ScanElement *m_scanSbbId2SbbPos;
+    const ScanElement *m_scanId2BlkPos;
     const NbInfoSbb*  m_scanId2NbInfoSbb;
     const NbInfoOut*  m_scanId2NbInfoOut;
     ScanInfo*         m_scanInfo;
@@ -128,8 +130,13 @@ namespace DQIntern
     Rom() : m_scansInitialized(false) {}
     ~Rom() { xUninitScanArrays(); }
     void                init        ()                       { xInitScanArrays(); }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    const NbInfoSbb*    getNbInfoSbb( int hd, int vd, int ch ) const { return m_scanId2NbInfoSbbArray[hd][vd][ch]; }
+    const NbInfoOut*    getNbInfoOut( int hd, int vd, int ch ) const { return m_scanId2NbInfoOutArray[hd][vd][ch]; }
+#else
     const NbInfoSbb*    getNbInfoSbb( int hd, int vd ) const { return m_scanId2NbInfoSbbArray[hd][vd]; }
     const NbInfoOut*    getNbInfoOut( int hd, int vd ) const { return m_scanId2NbInfoOutArray[hd][vd]; }
+#endif
     const TUParameters* getTUPars   ( const CompArea& area, const ComponentID compID ) const
     {
       return m_tuParameters[g_aucLog2[area.width]][g_aucLog2[area.height]][toChannelType(compID)];
@@ -139,8 +146,13 @@ namespace DQIntern
     void  xUninitScanArrays ();
   private:
     bool          m_scansInitialized;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    NbInfoSbb*    m_scanId2NbInfoSbbArray[ MAX_CU_DEPTH+1 ][ MAX_CU_DEPTH+1 ][ MAX_NUM_CHANNEL_TYPE ];
+    NbInfoOut*    m_scanId2NbInfoOutArray[ MAX_CU_DEPTH+1 ][ MAX_CU_DEPTH+1 ][ MAX_NUM_CHANNEL_TYPE ];
+#else
     NbInfoSbb*    m_scanId2NbInfoSbbArray[ MAX_CU_DEPTH+1 ][ MAX_CU_DEPTH+1 ];
     NbInfoOut*    m_scanId2NbInfoOutArray[ MAX_CU_DEPTH+1 ][ MAX_CU_DEPTH+1 ];
+#endif
     TUParameters* m_tuParameters         [ MAX_CU_DEPTH+1 ][ MAX_CU_DEPTH+1 ][ MAX_NUM_CHANNEL_TYPE ];
   };
 
@@ -155,51 +167,84 @@ namespace DQIntern
     ::memset( m_tuParameters,          0, sizeof(m_tuParameters) );
 
     uint32_t raster2id[ MAX_CU_SIZE * MAX_CU_SIZE ];
+    ::memset(raster2id, 0, sizeof(raster2id));
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    for( int ch = 0; ch < MAX_NUM_CHANNEL_TYPE; ch++ )
+    {
+    for( int hd = 0; hd <= MAX_CU_DEPTH; hd++ )
+    {
+      for( int vd = 0; vd <= MAX_CU_DEPTH; vd++ )
+      {
+        if( (hd == 0 && vd <= 1) || (hd <= 1 && vd == 0) )
+        {
+          continue;
+        }
+#else
     for( int hd = 1; hd <= MAX_CU_DEPTH; hd++ )
     {
       for( int vd = 1; vd <= MAX_CU_DEPTH; vd++ )
       {
+#endif
         const uint32_t      blockWidth    = (1 << hd);
         const uint32_t      blockHeight   = (1 << vd);
-        const uint32_t      totalValues   = blockWidth * blockHeight;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        const uint32_t      log2CGWidth   = g_log2SbbSize[ch][hd][vd][0];
+        const uint32_t      log2CGHeight  = g_log2SbbSize[ch][hd][vd][1];
+#else
         const uint32_t      log2CGWidth   = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
         const uint32_t      log2CGHeight  = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
+#endif
         const uint32_t      groupWidth    = 1 << log2CGWidth;
         const uint32_t      groupHeight   = 1 << log2CGHeight;
         const uint32_t      groupSize     = groupWidth * groupHeight;
         const CoeffScanType scanType      = SCAN_DIAG;
         const SizeType      blkWidthIdx   = gp_sizeIdxInfo->idxFrom( blockWidth  );
         const SizeType      blkHeightIdx  = gp_sizeIdxInfo->idxFrom( blockHeight );
-        const uint32_t*     scanId2RP     = g_scanOrder     [SCAN_GROUPED_4x4][scanType][blkWidthIdx][blkHeightIdx];
-        const uint32_t*     scanId2X      = g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blkWidthIdx][blkHeightIdx][0];
-        const uint32_t*     scanId2Y      = g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blkWidthIdx][blkHeightIdx][1];
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        const ScanElement * scanId2RP     = g_scanOrder[ch][SCAN_GROUPED_4x4][scanType][blkWidthIdx][blkHeightIdx];
+        NbInfoSbb*&         sId2NbSbb     = m_scanId2NbInfoSbbArray[hd][vd][ch];
+        NbInfoOut*&         sId2NbOut     = m_scanId2NbInfoOutArray[hd][vd][ch];
+#else
+        const ScanElement * scanId2RP     = g_scanOrder[SCAN_GROUPED_4x4][scanType][blkWidthIdx][blkHeightIdx];
         NbInfoSbb*&         sId2NbSbb     = m_scanId2NbInfoSbbArray[hd][vd];
         NbInfoOut*&         sId2NbOut     = m_scanId2NbInfoOutArray[hd][vd];
+#endif
+        // consider only non-zero-out region
+#if JVET_M0257
+        const uint32_t      blkWidthNZOut = std::min<unsigned>( JVET_C0024_ZERO_OUT_TH, blockWidth  );
+        const uint32_t      blkHeightNZOut= std::min<unsigned>( JVET_C0024_ZERO_OUT_TH, blockHeight );
+#else
+        const uint32_t      blkWidthNZOut = blockWidth;
+        const uint32_t      blkHeightNZOut= blockHeight;
+#endif
+        const uint32_t      totalValues   = blkWidthNZOut * blkHeightNZOut;
 
         sId2NbSbb = new NbInfoSbb[ totalValues ];
         sId2NbOut = new NbInfoOut[ totalValues ];
 
         for( uint32_t scanId = 0; scanId < totalValues; scanId++ )
         {
-          raster2id[ scanId2RP[ scanId ] ] = scanId;
+          raster2id[scanId2RP[scanId].idx] = scanId;
         }
 
         for( unsigned scanId = 0; scanId < totalValues; scanId++ )
         {
-          const int posX = scanId2X [ scanId ];
-          const int posY = scanId2Y [ scanId ];
-          const int rpos = scanId2RP[ scanId ];
+          const int posX = scanId2RP[scanId].x;
+          const int posY = scanId2RP[scanId].y;
+          const int rpos = scanId2RP[scanId].idx;
           {
             //===== inside subband neighbours =====
             NbInfoSbb&     nbSbb  = sId2NbSbb[ scanId ];
             const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
             int            cpos[5];
-            cpos[0] = ( posX < blockWidth -1                         ? ( raster2id[rpos+1           ] - begSbb < groupSize ? raster2id[rpos+1           ] - begSbb : 0 ) : 0 );
-            cpos[1] = ( posX < blockWidth -2                         ? ( raster2id[rpos+2           ] - begSbb < groupSize ? raster2id[rpos+2           ] - begSbb : 0 ) : 0 );
-            cpos[2] = ( posX < blockWidth -1 && posY < blockHeight-1 ? ( raster2id[rpos+1+blockWidth] - begSbb < groupSize ? raster2id[rpos+1+blockWidth] - begSbb : 0 ) : 0 );
-            cpos[3] = ( posY < blockHeight-1                         ? ( raster2id[rpos+  blockWidth] - begSbb < groupSize ? raster2id[rpos+  blockWidth] - begSbb : 0 ) : 0 );
-            cpos[4] = ( posY < blockHeight-2                         ? ( raster2id[rpos+2*blockWidth] - begSbb < groupSize ? raster2id[rpos+2*blockWidth] - begSbb : 0 ) : 0 );
+
+            cpos[0] = ( posX + 1 < blkWidthNZOut                              ? ( raster2id[rpos+1           ] < groupSize + begSbb ? raster2id[rpos+1           ] - begSbb : 0 ) : 0 );
+            cpos[1] = ( posX + 2 < blkWidthNZOut                              ? ( raster2id[rpos+2           ] < groupSize + begSbb ? raster2id[rpos+2           ] - begSbb : 0 ) : 0 );
+            cpos[2] = ( posX + 1 < blkWidthNZOut && posY + 1 < blkHeightNZOut ? ( raster2id[rpos+1+blockWidth] < groupSize + begSbb ? raster2id[rpos+1+blockWidth] - begSbb : 0 ) : 0 );
+            cpos[3] = ( posY + 1 < blkHeightNZOut                             ? ( raster2id[rpos+  blockWidth] < groupSize + begSbb ? raster2id[rpos+  blockWidth] - begSbb : 0 ) : 0 );
+            cpos[4] = ( posY + 2 < blkHeightNZOut                             ? ( raster2id[rpos+2*blockWidth] < groupSize + begSbb ? raster2id[rpos+2*blockWidth] - begSbb : 0 ) : 0 );
+
             for( nbSbb.num = 0; true; )
             {
               int nk = -1;
@@ -227,11 +272,13 @@ namespace DQIntern
             NbInfoOut&     nbOut  = sId2NbOut[ scanId ];
             const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
             int            cpos[5];
-            cpos[0] = ( posX < blockWidth -1                         ? ( raster2id[rpos+1           ] - begSbb >= groupSize ? raster2id[rpos+1           ] : 0 ) : 0 );
-            cpos[1] = ( posX < blockWidth -2                         ? ( raster2id[rpos+2           ] - begSbb >= groupSize ? raster2id[rpos+2           ] : 0 ) : 0 );
-            cpos[2] = ( posX < blockWidth -1 && posY < blockHeight-1 ? ( raster2id[rpos+1+blockWidth] - begSbb >= groupSize ? raster2id[rpos+1+blockWidth] : 0 ) : 0 );
-            cpos[3] = ( posY < blockHeight-1                         ? ( raster2id[rpos+  blockWidth] - begSbb >= groupSize ? raster2id[rpos+  blockWidth] : 0 ) : 0 );
-            cpos[4] = ( posY < blockHeight-2                         ? ( raster2id[rpos+2*blockWidth] - begSbb >= groupSize ? raster2id[rpos+2*blockWidth] : 0 ) : 0 );
+
+            cpos[0] = ( posX + 1 < blkWidthNZOut                              ? ( raster2id[rpos+1           ] >= groupSize + begSbb ? raster2id[rpos+1           ] : 0 ) : 0 );
+            cpos[1] = ( posX + 2 < blkWidthNZOut                              ? ( raster2id[rpos+2           ] >= groupSize + begSbb ? raster2id[rpos+2           ] : 0 ) : 0 );
+            cpos[2] = ( posX + 1 < blkWidthNZOut && posY + 1 < blkHeightNZOut ? ( raster2id[rpos+1+blockWidth] >= groupSize + begSbb ? raster2id[rpos+1+blockWidth] : 0 ) : 0 );
+            cpos[3] = ( posY + 1 < blkHeightNZOut                             ? ( raster2id[rpos+  blockWidth] >= groupSize + begSbb ? raster2id[rpos+  blockWidth] : 0 ) : 0 );
+            cpos[4] = ( posY + 2 < blkHeightNZOut                             ? ( raster2id[rpos+2*blockWidth] >= groupSize + begSbb ? raster2id[rpos+2*blockWidth] : 0 ) : 0 );
+
             for( nbOut.num = 0; true; )
             {
               int nk = -1;
@@ -271,17 +318,25 @@ namespace DQIntern
           const int  begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
           for( int k = 0; k < nbOut.num; k++ )
           {
+            CHECK(begSbb > nbOut.outPos[k], "Position must be past sub block begin");
             nbOut.outPos[k] -= begSbb;
           }
           nbOut.maxDist -= scanId;
         }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        m_tuParameters[hd][vd][ch] = new TUParameters( *this, blockWidth, blockHeight, ChannelType(ch) );
+#else
         for( int chId = 0; chId < MAX_NUM_CHANNEL_TYPE; chId++ )
         {
           m_tuParameters[hd][vd][chId] = new TUParameters( *this, blockWidth, blockHeight, ChannelType(chId) );
         }
+#endif
       }
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    }
+#endif
     m_scansInitialized = true;
   }
 
@@ -291,6 +346,32 @@ namespace DQIntern
     {
       return;
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    for( int hd = 0; hd <= MAX_CU_DEPTH; hd++ )
+    {
+      for( int vd = 0; vd <= MAX_CU_DEPTH; vd++ )
+      {
+        for( int ch = 0; ch < 2; ch++ )
+        {
+          NbInfoSbb*&     sId2NbSbb = m_scanId2NbInfoSbbArray[hd][vd][ch];
+          NbInfoOut*&     sId2NbOut = m_scanId2NbInfoOutArray[hd][vd][ch];
+          TUParameters*&  tuPars    = m_tuParameters         [hd][vd][ch];
+          if( sId2NbSbb )
+          {
+            delete [] sId2NbSbb;
+          }
+          if( sId2NbOut )
+          {
+            delete [] sId2NbOut;
+          }
+          if( tuPars )
+          {
+            delete tuPars;
+          }
+        }
+      }
+    }
+#else
     for( int hd = 0; hd <= MAX_CU_DEPTH; hd++ )
     {
       for( int vd = 0; vd <= MAX_CU_DEPTH; vd++ )
@@ -315,6 +396,7 @@ namespace DQIntern
         }
       }
     }
+#endif
     m_scansInitialized = false;
   }
 
@@ -327,15 +409,31 @@ namespace DQIntern
     m_chType              = chType;
     m_width               = width;
     m_height              = height;
+#if JVET_M0257
+    const uint32_t nonzeroWidth  = std::min<uint32_t>(JVET_C0024_ZERO_OUT_TH, m_width);
+    const uint32_t nonzeroHeight = std::min<uint32_t>(JVET_C0024_ZERO_OUT_TH, m_height);
+    m_numCoeff                   = nonzeroWidth * nonzeroHeight;
+#else
     m_numCoeff            = m_width * m_height;
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    m_log2SbbWidth        = g_log2SbbSize[m_chType][ g_aucLog2[m_width] ][ g_aucLog2[m_height] ][0];
+    m_log2SbbHeight       = g_log2SbbSize[m_chType][ g_aucLog2[m_width] ][ g_aucLog2[m_height] ][1];
+#else
     const bool      no4x4 = ( ( m_width & 3 ) != 0 || ( m_height & 3 ) != 0 );
     m_log2SbbWidth        = ( no4x4 ? 1 : 2 );
     m_log2SbbHeight       = ( no4x4 ? 1 : 2 );
+#endif
     m_log2SbbSize         = m_log2SbbWidth + m_log2SbbHeight;
     m_sbbSize             = ( 1 << m_log2SbbSize );
     m_sbbMask             = m_sbbSize - 1;
+#if JVET_M0257
+    m_widthInSbb  = nonzeroWidth >> m_log2SbbWidth;
+    m_heightInSbb = nonzeroHeight >> m_log2SbbHeight;
+#else
     m_widthInSbb          = m_width  >> m_log2SbbWidth;
     m_heightInSbb         = m_height >> m_log2SbbHeight;
+#endif
     m_numSbb              = m_widthInSbb * m_heightInSbb;
 #if HEVC_USE_MDCS
 #error "MDCS is not supported" // use different function...
@@ -347,14 +445,21 @@ namespace DQIntern
     SizeType        vsbb  = gp_sizeIdxInfo->idxFrom( m_heightInSbb );
     SizeType        hsId  = gp_sizeIdxInfo->idxFrom( m_width  );
     SizeType        vsId  = gp_sizeIdxInfo->idxFrom( m_height );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    m_scanSbbId2SbbPos    = g_scanOrder     [ chType ][ SCAN_UNGROUPED   ][ m_scanType ][ hsbb ][ vsbb ];
+    m_scanId2BlkPos       = g_scanOrder     [ chType ][ SCAN_GROUPED_4x4 ][ m_scanType ][ hsId ][ vsId ];
+    int log2W             = g_aucLog2[ m_width  ];
+    int log2H             = g_aucLog2[ m_height ];
+    m_scanId2NbInfoSbb    = rom.getNbInfoSbb( log2W, log2H, chType );
+    m_scanId2NbInfoOut    = rom.getNbInfoOut( log2W, log2H, chType );
+#else
     m_scanSbbId2SbbPos    = g_scanOrder     [ SCAN_UNGROUPED   ][ m_scanType ][ hsbb ][ vsbb ];
     m_scanId2BlkPos       = g_scanOrder     [ SCAN_GROUPED_4x4 ][ m_scanType ][ hsId ][ vsId ];
-    m_scanId2PosX         = g_scanOrderPosXY[ SCAN_GROUPED_4x4 ][ m_scanType ][ hsId ][ vsId ][ 0 ];
-    m_scanId2PosY         = g_scanOrderPosXY[ SCAN_GROUPED_4x4 ][ m_scanType ][ hsId ][ vsId ][ 1 ];
     int log2W             = g_aucLog2[ m_width  ];
     int log2H             = g_aucLog2[ m_height ];
     m_scanId2NbInfoSbb    = rom.getNbInfoSbb( log2W, log2H );
     m_scanId2NbInfoOut    = rom.getNbInfoOut( log2W, log2H );
+#endif
     m_scanInfo            = new ScanInfo[ m_numCoeff ];
     for( int scanIdx = 0; scanIdx < m_numCoeff; scanIdx++ )
     {
@@ -368,8 +473,8 @@ namespace DQIntern
     scanInfo.sbbSize    = m_sbbSize;
     scanInfo.numSbb     = m_numSbb;
     scanInfo.scanIdx    = scanIdx;
-    scanInfo.rasterPos  = m_scanId2BlkPos[ scanIdx ];
-    scanInfo.sbbPos     = m_scanSbbId2SbbPos[ scanIdx >> m_log2SbbSize ];
+    scanInfo.rasterPos  = m_scanId2BlkPos[scanIdx].idx;
+    scanInfo.sbbPos     = m_scanSbbId2SbbPos[scanIdx >> m_log2SbbSize].idx;
     scanInfo.insidePos  = scanIdx & m_sbbMask;
     scanInfo.eosbb      = ( scanInfo.insidePos == 0 );
     scanInfo.spt        = SCAN_ISCSBB;
@@ -377,10 +482,14 @@ namespace DQIntern
       scanInfo.spt      = SCAN_SOCSBB;
     else if( scanInfo.eosbb && scanIdx > 0 && scanIdx < m_numCoeff - m_sbbSize )
       scanInfo.spt      = SCAN_EOCSBB;
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    scanInfo.posX = m_scanId2BlkPos[scanIdx].x;
+    scanInfo.posY = m_scanId2BlkPos[scanIdx].y;
+#endif
     if( scanIdx )
     {
       const int nextScanIdx = scanIdx - 1;
-      const int diag        = m_scanId2PosX[ nextScanIdx ] + m_scanId2PosY[ nextScanIdx ];
+      const int diag        = m_scanId2BlkPos[nextScanIdx].x + m_scanId2BlkPos[nextScanIdx].y;
       if( m_chType == CHANNEL_TYPE_LUMA )
       {
         scanInfo.sigCtxOffsetNext = ( diag < 2 ? 12 : diag < 5 ?  6 : 0 );
@@ -395,7 +504,7 @@ namespace DQIntern
       scanInfo.nextNbInfoSbb      = m_scanId2NbInfoSbb[ nextScanIdx ];
       if( scanInfo.eosbb )
       {
-        const int nextSbbPos  = m_scanSbbId2SbbPos[ nextScanIdx >> m_log2SbbSize ];
+        const int nextSbbPos  = m_scanSbbId2SbbPos[nextScanIdx >> m_log2SbbSize].idx;
         const int nextSbbPosY = nextSbbPos               / m_widthInSbb;
         const int nextSbbPosX = nextSbbPos - nextSbbPosY * m_widthInSbb;
         scanInfo.nextSbbRight = ( nextSbbPosX < m_widthInSbb  - 1 ? nextSbbPos + 1            : 0 );
@@ -421,7 +530,7 @@ namespace DQIntern
     inline const CoeffFracBits *gtxFracBits(unsigned stateId) const { return m_gtxFracBits; }
     inline int32_t              lastOffset(unsigned scanIdx) const
     {
-      return m_lastBitsX[m_scanId2PosX[scanIdx]] + m_lastBitsY[m_scanId2PosY[scanIdx]];
+      return m_lastBitsX[m_scanId2Pos[scanIdx].x] + m_lastBitsY[m_scanId2Pos[scanIdx].y];
     }
 
   private:
@@ -438,8 +547,7 @@ namespace DQIntern
     static const unsigned sm_maxNumGtxCtx     = 21;
 
   private:
-    const unsigned*     m_scanId2PosX;
-    const unsigned*     m_scanId2PosY;
+    const ScanElement * m_scanId2Pos;
     int32_t             m_lastBitsX      [ MAX_TU_SIZE ];
     int32_t             m_lastBitsY      [ MAX_TU_SIZE ];
     BinFracBits         m_sigSbbFracBits [ sm_maxNumSigSbbCtx ];
@@ -449,8 +557,7 @@ namespace DQIntern
 
   void RateEstimator::initCtx( const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID, const FracBitsAccess& fracBitsAccess )
   {
-    m_scanId2PosX       = tuPars.m_scanId2PosX;
-    m_scanId2PosY       = tuPars.m_scanId2PosY;
+    m_scanId2Pos = tuPars.m_scanId2BlkPos;
     xSetSigSbbFracBits  ( fracBitsAccess, tuPars.m_chType );
     xSetSigFlagBits     ( fracBitsAccess, tuPars.m_chType );
     xSetGtxFlagBits     ( fracBitsAccess, tuPars.m_chType );
@@ -468,8 +575,44 @@ namespace DQIntern
     }
     else
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      BinFracBits bits;
+      bool prevLumaCbf           = false;
+      bool lastCbfIsInferred     = false;
+      bool useIntraSubPartitions = tu.cu->ispMode && isLuma(chType);
+      if( useIntraSubPartitions )
+      {
+        bool rootCbfSoFar = false;
+        bool isLastSubPartition = CU::isISPLast(*tu.cu, tu.Y(), compID);
+        uint32_t nTus = tu.cu->ispMode == HOR_INTRA_SUBPARTITIONS ? tu.cu->lheight() >> g_aucLog2[tu.lheight()] : tu.cu->lwidth() >> g_aucLog2[tu.lwidth()];
+        if( isLastSubPartition )
+        {
+          TransformUnit* tuPointer = tu.cu->firstTU;
+          for( int tuIdx = 0; tuIdx < nTus - 1; tuIdx++ )
+          {
+            rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMPONENT_Y, tu.depth);
+            tuPointer     = tuPointer->next;
+          }
+          if( !rootCbfSoFar )
+          {
+            lastCbfIsInferred = true;
+          }
+        }
+        if( !lastCbfIsInferred )
+        {
+          prevLumaCbf = TU::getPrevTuCbfAtDepth(tu, compID, tu.depth);
+        }
+        bits = fracBitsAccess.getFracBitsArray(Ctx::QtCbf[compID](DeriveCtx::CtxQtCbf(compID, tu.depth, prevLumaCbf, true)));
+      }
+      else
+      {
+        bits = fracBitsAccess.getFracBitsArray(Ctx::QtCbf[compID](DeriveCtx::CtxQtCbf(compID, tu.depth, tu.cbf[COMPONENT_Cb])));
+      }
+      cbfDeltaBits = lastCbfIsInferred ? 0 : int32_t(bits.intBits[1]) - int32_t(bits.intBits[0]);
+#else
       BinFracBits bits = fracBitsAccess.getFracBitsArray( Ctx::QtCbf[compID]( DeriveCtx::CtxQtCbf( compID, tu.depth, tu.cbf[COMPONENT_Cb] ) ) );
       cbfDeltaBits = int32_t( bits.intBits[1] ) - int32_t( bits.intBits[0] );
+#endif
     }
 
     static const unsigned prefixCtx[] = { 0, 0, 0, 3, 6, 10, 15, 21 };
@@ -489,7 +632,11 @@ namespace DQIntern
       const unsigned      lastShift   = ( compID == COMPONENT_Y ? (log2Size+1)>>2 : Clip3<unsigned>(0,2,size>>3) );
       const unsigned      lastOffset  = ( compID == COMPONENT_Y ? ( prefixCtx[log2Size] ) : 0 );
       uint32_t            sumFBits    = 0;
+#if JVET_M0257
+      unsigned            maxCtxId    = g_uiGroupIdx[std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, size) - 1];
+#else
       unsigned            maxCtxId    = g_uiGroupIdx[ size - 1 ];
+#endif
       for( unsigned ctxId = 0; ctxId < maxCtxId; ctxId++ )
       {
         const BinFracBits bits  = fracBitsAccess.getFracBitsArray( ctxSetLast( lastOffset + ( ctxId >> lastShift ) ) );
@@ -497,7 +644,11 @@ namespace DQIntern
         sumFBits               +=            bits.intBits[1];
       }
       ctxBits  [ maxCtxId ]     = sumFBits + ( maxCtxId>3 ? ((maxCtxId-2)>>1)<<SCALE_BITS : 0 ) + bitOffset;
+#if JVET_M0257
+      for (unsigned pos = 0; pos < std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, size); pos++)
+#else
       for( unsigned pos = 0; pos < size; pos++ )
+#endif
       {
         lastBits[ pos ]         = ctxBits[ g_uiGroupIdx[ pos ] ];
       }
@@ -653,8 +804,13 @@ namespace DQIntern
     m_QShift                    = QUANT_SHIFT  - 1 + qpPer + transformShift;
     m_QAdd                      = -( ( 3 << m_QShift ) >> 1 );
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+    Intermediate_Int  invShift  = IQUANT_SHIFT + 1 - qpPer - transformShift + ( TU::needsBlockSizeTrafoScale( tu, compID ) ? ADJ_DEQUANT_SHIFT : 0 );
+    m_QScale                    = ( TU::needsSqrt2Scale( tu, compID ) ? ( g_quantScales[ qpRem ] * 181 ) >> 7 : g_quantScales[ qpRem ] );
+#else
     Intermediate_Int  invShift  = IQUANT_SHIFT + 1 - qpPer - transformShift + ( TU::needsBlockSizeTrafoScale( area ) ? ADJ_DEQUANT_SHIFT : 0 );
     m_QScale                    = ( TU::needsSqrt2Scale( area ) ? ( g_quantScales[ qpRem ] * 181 ) >> 7 : g_quantScales[ qpRem ] );
+#endif
 #else
     Intermediate_Int  invShift  = IQUANT_SHIFT + 1 - qpPer - transformShift;
     m_QScale                    = g_quantScales   [ qpRem ];
@@ -699,7 +855,11 @@ namespace DQIntern
 #else
     const CoeffScanType scanType  = SCAN_DIAG;
 #endif
-    const unsigned*     scan      = g_scanOrder[ SCAN_GROUPED_4x4 ][ scanType ][ hsId ][ vsId ];
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    const ScanElement *scan = g_scanOrder[toChannelType(compID)][SCAN_GROUPED_4x4][scanType][hsId][vsId];
+#else
+    const ScanElement * scan      = g_scanOrder[SCAN_GROUPED_4x4][scanType][hsId][vsId];
+#endif
     const TCoeff*       qCoeff    = tu.getCoeffs( compID ).buf;
           TCoeff*       tCoeff    = recCoeff.buf;
 
@@ -708,7 +868,7 @@ namespace DQIntern
     int lastScanIdx = -1;
     for( int scanIdx = numCoeff - 1; scanIdx >= 0; scanIdx-- )
     {
-      if( qCoeff[ scan[ scanIdx ] ] )
+      if (qCoeff[scan[scanIdx].idx])
       {
         lastScanIdx = scanIdx;
         break;
@@ -737,8 +897,13 @@ namespace DQIntern
 #endif
     const int         transformShift        = ( clipTransformShift ? std::max<int>( 0, nomTransformShift ) : nomTransformShift );
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+    Intermediate_Int  shift                 = IQUANT_SHIFT + 1 - qpPer - transformShift + ( TU::needsBlockSizeTrafoScale( tu, compID ) ? ADJ_DEQUANT_SHIFT : 0 );
+    Intermediate_Int  invQScale             = g_invQuantScales[ qpRem ] * ( TU::needsSqrt2Scale( tu, compID ) ? 181 : 1 );
+#else
     Intermediate_Int  shift                 = IQUANT_SHIFT + 1 - qpPer - transformShift + ( TU::needsBlockSizeTrafoScale( area ) ? ADJ_DEQUANT_SHIFT : 0 );
     Intermediate_Int  invQScale             = g_invQuantScales[ qpRem ] * ( TU::needsSqrt2Scale( area ) ? 181 : 1 );
+#endif
 #else
     Intermediate_Int  shift                 = IQUANT_SHIFT + 1 - qpPer - transformShift;
     Intermediate_Int  invQScale             = g_invQuantScales[ qpRem ];
@@ -753,7 +918,7 @@ namespace DQIntern
     //----- dequant coefficients -----
     for( int state = 0, scanIdx = lastScanIdx; scanIdx >= 0; scanIdx-- )
     {
-      const unsigned  rasterPos = scan  [ scanIdx   ];
+      const unsigned  rasterPos = scan[scanIdx].idx;
       const TCoeff&   level     = qCoeff[ rasterPos ];
       if( level )
       {
@@ -840,6 +1005,15 @@ namespace DQIntern
   };
 
 #define RICEMAX 32
+#if JVET_M0470
+  const int32_t g_goRiceBits[4][RICEMAX] =
+  {
+      { 32768,	65536,	98304,	131072,	163840,	196608,	262144,	262144,	327680,	327680,	327680,	327680,	393216,	393216,	393216,	393216,	393216,	393216,	393216,	393216,	458752,	458752,	458752,	458752,	458752,	458752,	458752,	458752,	458752,	458752,	458752,	458752},
+      { 65536,	65536,	98304,	98304,	131072,	131072,	163840,	163840,	196608,	196608,	229376,	229376,	294912,	294912,	294912,	294912,	360448,	360448,	360448,	360448,	360448,	360448,	360448,	360448,	425984,	425984,	425984,	425984,	425984,	425984,	425984,	425984},
+      { 98304,	98304,	98304,	98304,	131072,	131072,	131072,	131072,	163840,	163840,	163840,	163840,	196608,	196608,	196608,	196608,	229376,	229376,	229376,	229376,	262144,	262144,	262144,	262144,	327680,	327680,	327680,	327680,	327680,	327680,	327680,	327680},
+      { 131072,	131072,	131072,	131072,	131072,	131072,	131072,	131072,	163840,	163840,	163840,	163840,	163840,	163840,	163840,	163840,	196608,	196608,	196608,	196608,	196608,	196608,	196608,	196608,	229376,	229376,	229376,	229376,	229376,	229376,	229376,	229376}
+  };
+#else
   const int32_t g_goRiceBits[4][RICEMAX] =
   {
     {  32768,  65536,  98304, 131072, 163840, 196608, 229376, 294912, 294912, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520 },
@@ -847,6 +1021,7 @@ namespace DQIntern
     {  98304,  98304,  98304,  98304, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448 },
     { 131072, 131072, 131072, 131072, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376 }
   };
+#endif
 
   class State
   {
@@ -981,6 +1156,16 @@ namespace DQIntern
       }
     }
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    inline void checkRdCostSkipSbbZeroOut(Decision &decision) const
+    {
+      int64_t rdCost = m_rdCost + m_sbbFracBits.intBits[0];
+      decision.rdCost = rdCost;
+      decision.absLevel = 0;
+      decision.prevId = 4 + m_stateId;
+    }
+#endif
+
   private:
     int64_t                   m_rdCost;
     uint16_t                  m_absLevelsAndCtxInit[24];  // 16x8bit for abs levels + 16x16bit for ctx init id
@@ -1168,10 +1353,17 @@ namespace DQIntern
     if( decision.prevId > -2 )
     {
       const State* prvState = 0;
-      if( decision.prevId  >= 0 )
+      if( decision.prevId  >= 4 )
+      {
+        CHECK( decision.absLevel != 0, "cannot happen" );
+        prvState    = skipStates + ( decision.prevId - 4 );
+        m_numSigSbb = 0;
+        ::memset( m_absLevelsAndCtxInit, 0, 16*sizeof(uint8_t) );
+      }
+      else if( decision.prevId  >= 0 )
       {
-        prvState    = ( decision.prevId < 4 ? prevStates : skipStates - 4 ) +   decision.prevId;
-        m_numSigSbb = prvState->m_numSigSbb                                 + !!decision.absLevel;
+        prvState    = prevStates            +   decision.prevId;
+        m_numSigSbb = prvState->m_numSigSbb + !!decision.absLevel;
         ::memcpy( m_absLevelsAndCtxInit, prvState->m_absLevelsAndCtxInit, 16*sizeof(uint8_t) );
       }
       else
@@ -1291,8 +1483,13 @@ namespace DQIntern
     void    dequant ( const TransformUnit& tu,  CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP )  const;
 
   private:
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    void    xDecideAndUpdate  ( const TCoeff absCoeff, const ScanInfo& scanInfo, bool zeroOut );
+    void    xDecide           ( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions, bool zeroOut );
+#else
     void    xDecideAndUpdate  ( const TCoeff absCoeff, const ScanInfo& scanInfo );
     void    xDecide           ( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions );
+#endif
 
   private:
     CommonCtx   m_commonCtx;
@@ -1330,10 +1527,28 @@ namespace DQIntern
 #undef  DINIT
 
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  void DepQuant::xDecide( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions, bool zeroOut)
+#else
   void DepQuant::xDecide( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions)
+#endif
   {
     ::memcpy( decisions, startDec, 8*sizeof(Decision) );
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    if( zeroOut )
+    {
+      if( spt==SCAN_EOCSBB )
+      {
+        m_skipStates[0].checkRdCostSkipSbbZeroOut( decisions[0] );
+        m_skipStates[1].checkRdCostSkipSbbZeroOut( decisions[1] );
+        m_skipStates[2].checkRdCostSkipSbbZeroOut( decisions[2] );
+        m_skipStates[3].checkRdCostSkipSbbZeroOut( decisions[3] );
+      }
+      return;
+    }
+#endif
+
     PQData  pqData[4];
     m_quant.preQuantCoeff( absCoeff, pqData );
     m_prevStates[0].checkRdCosts( spt, pqData[0], pqData[2], decisions[0], decisions[2]);
@@ -1351,13 +1566,21 @@ namespace DQIntern
     m_startState.checkRdCostStart( lastOffset, pqData[2], decisions[2] );
   }
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  void DepQuant::xDecideAndUpdate( const TCoeff absCoeff, const ScanInfo& scanInfo, bool zeroOut )
+#else
   void DepQuant::xDecideAndUpdate( const TCoeff absCoeff, const ScanInfo& scanInfo )
+#endif
   {
     Decision* decisions = m_trellis[ scanInfo.scanIdx ];
 
     std::swap( m_prevStates, m_currStates );
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    xDecide( scanInfo.spt, absCoeff, lastOffset(scanInfo.scanIdx), decisions, zeroOut );
+#else
     xDecide( scanInfo.spt, absCoeff, lastOffset(scanInfo.scanIdx), decisions);
+#endif
 
     if( scanInfo.scanIdx )
     {
@@ -1370,7 +1593,11 @@ namespace DQIntern
         m_currStates[3].updateStateEOS( scanInfo, m_prevStates, m_skipStates, decisions[3] );
         ::memcpy( decisions+4, decisions, 4*sizeof(Decision) );
       }
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+      else if( !zeroOut )
+#else
       else
+#endif
       {
         switch( scanInfo.nextNbInfoSbb.num )
         {
@@ -1438,7 +1665,7 @@ namespace DQIntern
     const TCoeff thres = m_quant.getLastThreshold();
     for( ; firstTestPos >= 0; firstTestPos-- )
     {
-      if( abs( tCoeff[ tuPars.m_scanId2BlkPos[firstTestPos] ] ) > thres )
+      if (abs(tCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx]) > thres)
       {
         break;
       }
@@ -1457,12 +1684,38 @@ namespace DQIntern
     }
     m_startState.init();
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+    int effWidth = tuPars.m_width, effHeight = tuPars.m_height;
+    bool zeroOut = false;
+#if JVET_M0140_SBT
+#if JVET_M0464_UNI_MTS
+    if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tuPars.m_height <= 32 && tuPars.m_width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+    if( ( ( tu.cu->emtFlag && !tu.transformSkip[ compID ] ) || ( tu.cu->sbtInfo != 0 && tuPars.m_height <= 32 && tuPars.m_width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#else
+#if JVET_M0464_UNI_MTS
+    if( tu.mtsIdx > 1 && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+    if( tu.cu->emtFlag && !tu.transformSkip[compID] && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#endif
+    {
+      effHeight = ( tuPars.m_height == 32 ) ? 16 : tuPars.m_height;
+      effWidth = ( tuPars.m_width == 32 ) ? 16 : tuPars.m_width;
+      zeroOut  = ( effHeight < tuPars.m_height || effWidth < tuPars.m_width );
+    }
+#endif
 
     //===== populate trellis =====
     for( int scanIdx = firstTestPos; scanIdx >= 0; scanIdx-- )
     {
       const ScanInfo& scanInfo = tuPars.m_scanInfo[ scanIdx ];
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+      xDecideAndUpdate( abs( tCoeff[ scanInfo.rasterPos ] ), scanInfo, zeroOut && ( scanInfo.posX >= effWidth || scanInfo.posY >= effHeight ) );
+#else
       xDecideAndUpdate( abs( tCoeff[ scanInfo.rasterPos ] ), scanInfo );
+#endif
     }
 
     //===== find best path =====
@@ -1483,7 +1736,7 @@ namespace DQIntern
     for( ; decision.prevId >= 0; scanIdx++ )
     {
       decision          = m_trellis[ scanIdx ][ decision.prevId ];
-      int32_t blkpos    = tuPars.m_scanId2BlkPos[ scanIdx ];
+      int32_t blkpos    = tuPars.m_scanId2BlkPos[scanIdx].idx;
       qCoeff[ blkpos ]  = ( tCoeff[ blkpos ] < 0 ? -decision.absLevel : decision.absLevel );
       absSum           += decision.absLevel;
     }
diff --git a/source/Lib/CommonLib/Hash.cpp b/source/Lib/CommonLib/Hash.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2301f6845b148de9e435cb6f72cbd4dbcb0fddfc
--- /dev/null
+++ b/source/Lib/CommonLib/Hash.cpp
@@ -0,0 +1,732 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2019, 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.
+ */
+
+ /** \file     TEncHash.cpp
+     \brief    hash encoder class
+ */
+#include "CommonLib/dtrace_codingstruct.h"
+#include "CommonLib/Picture.h"
+#include "CommonLib/UnitTools.h"
+#include "Hash.h"
+
+
+
+ // ====================================================================================================================
+ // Constructor / destructor / create / destroy
+ // ====================================================================================================================
+
+int TComHash::m_blockSizeToIndex[65][65];
+TCRCCalculatorLight TComHash::m_crcCalculator1(24, 0x5D6DCB);
+TCRCCalculatorLight TComHash::m_crcCalculator2(24, 0x864CFB);
+
+TCRCCalculatorLight::TCRCCalculatorLight(uint32_t bits, uint32_t truncPoly)
+{
+  m_remainder = 0;
+  m_bits = bits;
+  m_truncPoly = truncPoly;
+  m_finalResultMask = (1 << bits) - 1;
+
+  xInitTable();
+}
+
+TCRCCalculatorLight::~TCRCCalculatorLight()
+{
+
+}
+
+void TCRCCalculatorLight::xInitTable()
+{
+  const uint32_t highBit = 1 << (m_bits - 1);
+  const uint32_t byteHighBit = 1 << (8 - 1);
+
+  for (uint32_t value = 0; value < 256; value++)
+  {
+    uint32_t remainder = 0;
+    for (unsigned char mask = byteHighBit; mask != 0; mask >>= 1)
+    {
+      if (value & mask)
+      {
+        remainder ^= highBit;
+      }
+
+      if (remainder & highBit)
+      {
+        remainder <<= 1;
+        remainder ^= m_truncPoly;
+      }
+      else
+      {
+        remainder <<= 1;
+      }
+    }
+
+    m_table[value] = remainder;
+  }
+}
+
+void TCRCCalculatorLight::processData(unsigned char* curData, uint32_t dataLength)
+{
+  for (uint32_t i = 0; i < dataLength; i++)
+  {
+    unsigned char index = (m_remainder >> (m_bits - 8)) ^ curData[i];
+    m_remainder <<= 8;
+    m_remainder ^= m_table[index];
+  }
+}
+
+
+TComHash::TComHash()
+{
+  m_lookupTable = NULL;
+  tableHasContent = false;
+}
+
+TComHash::~TComHash()
+{
+  clearAll();
+  if (m_lookupTable != NULL)
+  {
+    delete[] m_lookupTable;
+    m_lookupTable = NULL;
+  }
+}
+
+void TComHash::create()
+{
+  if (m_lookupTable != NULL)
+  {
+    clearAll();
+    return;
+  }
+  int maxAddr = 1 << (m_CRCBits + m_blockSizeBits);
+  m_lookupTable = new std::vector<BlockHash>*[maxAddr];
+  memset(m_lookupTable, 0, sizeof(std::vector<BlockHash>*) * maxAddr);
+  tableHasContent = false;
+}
+
+void TComHash::clearAll()
+{
+  tableHasContent = false;
+  if (m_lookupTable == NULL)
+  {
+    return;
+  }
+  int maxAddr = 1 << (m_CRCBits + m_blockSizeBits);
+  for (int i = 0; i < maxAddr; i++)
+  {
+    if (m_lookupTable[i] != NULL)
+    {
+      delete m_lookupTable[i];
+      m_lookupTable[i] = NULL;
+    }
+  }
+}
+
+void TComHash::addToTable(uint32_t hashValue, const BlockHash& blockHash)
+{
+  if (m_lookupTable[hashValue] == NULL)
+  {
+    m_lookupTable[hashValue] = new std::vector<BlockHash>;
+    m_lookupTable[hashValue]->push_back(blockHash);
+  }
+  else
+  {
+    m_lookupTable[hashValue]->push_back(blockHash);
+  }
+}
+
+int TComHash::count(uint32_t hashValue)
+{
+  if (m_lookupTable[hashValue] == NULL)
+  {
+    return 0;
+  }
+  else
+  {
+    return static_cast<int>(m_lookupTable[hashValue]->size());
+  }
+}
+
+int TComHash::count(uint32_t hashValue) const
+{
+  if (m_lookupTable[hashValue] == NULL)
+  {
+    return 0;
+  }
+  else
+  {
+    return static_cast<int>(m_lookupTable[hashValue]->size());
+  }
+}
+
+MapIterator TComHash::getFirstIterator(uint32_t hashValue)
+{
+  return m_lookupTable[hashValue]->begin();
+}
+
+const MapIterator TComHash::getFirstIterator(uint32_t hashValue) const
+{
+  return m_lookupTable[hashValue]->begin();
+}
+
+bool TComHash::hasExactMatch(uint32_t hashValue1, uint32_t hashValue2)
+{
+  if (m_lookupTable[hashValue1] == NULL)
+  {
+    return false;
+  }
+  std::vector<BlockHash>::iterator it;
+  for (it = m_lookupTable[hashValue1]->begin(); it != m_lookupTable[hashValue1]->end(); it++)
+  {
+    if ((*it).hashValue2 == hashValue2)
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+void TComHash::generateBlock2x2HashValue(const PelUnitBuf &curPicBuf, int picWidth, int picHeight, const BitDepths bitDepths, uint32_t* picBlockHash[2], bool* picBlockSameInfo[3])
+{
+  const int width = 2;
+  const int height = 2;
+  int xEnd = picWidth - width + 1;
+  int yEnd = picHeight - height + 1;
+
+  int length = width * 2;
+  bool includeChroma = false;
+  if ((curPicBuf).chromaFormat == CHROMA_444)
+  {
+    length *= 3;
+    includeChroma = true;
+  }
+  unsigned char* p = new unsigned char[length];
+
+  int pos = 0;
+  for (int yPos = 0; yPos < yEnd; yPos++)
+  {
+    for (int xPos = 0; xPos < xEnd; xPos++)
+    {
+      TComHash::getPixelsIn1DCharArrayByBlock2x2(curPicBuf, p, xPos, yPos, bitDepths, includeChroma);
+      picBlockSameInfo[0][pos] = isBlock2x2RowSameValue(p, includeChroma);
+      picBlockSameInfo[1][pos] = isBlock2x2ColSameValue(p, includeChroma);
+
+      picBlockHash[0][pos] = TComHash::getCRCValue1(p, length * sizeof(unsigned char));
+      picBlockHash[1][pos] = TComHash::getCRCValue2(p, length * sizeof(unsigned char));
+
+      pos++;
+    }
+    pos += width - 1;
+  }
+
+  delete[] p;
+}
+void TComHash::generateRectangleHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3])
+{
+  //at present, only support 1:2(2:1) retangle hash value
+  CHECK(width != (height << 1) && (width << 1) != height, "Wrong")
+  bool isHorizontal = width == (height << 1) ? true : false;
+
+  int xEnd = picWidth - width + 1;
+  int yEnd = picHeight - height + 1;
+
+  int srcWidth = width >> 1;
+  int quadWidth = width >> 2;
+  int srcHeight = height >> 1;
+  int quadHeight = height >> 2;
+
+  int length = 2 * sizeof(uint32_t);
+  uint32_t* p = new uint32_t[2];
+  int pos = 0;
+  if (isHorizontal)
+  {
+    for (int yPos = 0; yPos < yEnd; yPos++)
+    {
+      for (int xPos = 0; xPos < xEnd; xPos++)
+      {
+        p[0] = srcPicBlockHash[0][pos];
+        p[1] = srcPicBlockHash[0][pos + srcWidth];
+        dstPicBlockHash[0][pos] = TComHash::getCRCValue1((unsigned char*)p, length);
+
+        p[0] = srcPicBlockHash[1][pos];
+        p[1] = srcPicBlockHash[1][pos + srcWidth];
+        dstPicBlockHash[1][pos] = TComHash::getCRCValue2((unsigned char*)p, length);
+
+        dstPicBlockSameInfo[0][pos] = srcPicBlockSameInfo[0][pos] && srcPicBlockSameInfo[0][pos + quadWidth] && srcPicBlockSameInfo[0][pos + srcWidth];
+        dstPicBlockSameInfo[1][pos] = srcPicBlockSameInfo[1][pos] && srcPicBlockSameInfo[1][pos + srcWidth];
+        pos++;
+      }
+      pos += width - 1;
+    }
+  }
+  else
+  {
+    for (int yPos = 0; yPos < yEnd; yPos++)
+    {
+      for (int xPos = 0; xPos < xEnd; xPos++)
+      {
+        p[0] = srcPicBlockHash[0][pos];
+        p[1] = srcPicBlockHash[0][pos + srcHeight * picWidth];
+        dstPicBlockHash[0][pos] = TComHash::getCRCValue1((unsigned char*)p, length);
+
+        p[0] = srcPicBlockHash[1][pos];
+        p[1] = srcPicBlockHash[1][pos + srcHeight * picWidth];
+        dstPicBlockHash[1][pos] = TComHash::getCRCValue2((unsigned char*)p, length);
+
+        dstPicBlockSameInfo[0][pos] = srcPicBlockSameInfo[0][pos] && srcPicBlockSameInfo[0][pos + srcHeight * picWidth];
+        dstPicBlockSameInfo[1][pos] = srcPicBlockSameInfo[1][pos] && srcPicBlockSameInfo[1][pos + quadHeight * picWidth] && srcPicBlockSameInfo[1][pos + srcHeight * picWidth];
+
+        pos++;
+      }
+      pos += width - 1;
+    }
+  }
+
+  int widthMinus1 = width - 1;
+  int heightMinus1 = height - 1;
+  pos = 0;
+
+  for (int yPos = 0; yPos < yEnd; yPos++)
+  {
+    for (int xPos = 0; xPos < xEnd; xPos++)
+    {
+      dstPicBlockSameInfo[2][pos] = (!dstPicBlockSameInfo[0][pos] && !dstPicBlockSameInfo[1][pos]) || (((xPos & widthMinus1) == 0) && ((yPos & heightMinus1) == 0));
+      pos++;
+    }
+    pos += width - 1;
+  }
+
+  delete[] p;
+}
+
+void TComHash::generateBlockHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3])
+{
+  int xEnd = picWidth - width + 1;
+  int yEnd = picHeight - height + 1;
+
+  int srcWidth = width >> 1;
+  int quadWidth = width >> 2;
+  int srcHeight = height >> 1;
+  int quadHeight = height >> 2;
+
+  int length = 4 * sizeof(uint32_t);
+
+  uint32_t* p = new uint32_t[4];
+  int pos = 0;
+  for (int yPos = 0; yPos < yEnd; yPos++)
+  {
+    for (int xPos = 0; xPos < xEnd; xPos++)
+    {
+      p[0] = srcPicBlockHash[0][pos];
+      p[1] = srcPicBlockHash[0][pos + srcWidth];
+      p[2] = srcPicBlockHash[0][pos + srcHeight * picWidth];
+      p[3] = srcPicBlockHash[0][pos + srcHeight * picWidth + srcWidth];
+      dstPicBlockHash[0][pos] = TComHash::getCRCValue1((unsigned char*)p, length);
+
+      p[0] = srcPicBlockHash[1][pos];
+      p[1] = srcPicBlockHash[1][pos + srcWidth];
+      p[2] = srcPicBlockHash[1][pos + srcHeight * picWidth];
+      p[3] = srcPicBlockHash[1][pos + srcHeight * picWidth + srcWidth];
+      dstPicBlockHash[1][pos] = TComHash::getCRCValue2((unsigned char*)p, length);
+
+      dstPicBlockSameInfo[0][pos] = srcPicBlockSameInfo[0][pos] && srcPicBlockSameInfo[0][pos + quadWidth] && srcPicBlockSameInfo[0][pos + srcWidth]
+        && srcPicBlockSameInfo[0][pos + srcHeight * picWidth] && srcPicBlockSameInfo[0][pos + srcHeight * picWidth + quadWidth] && srcPicBlockSameInfo[0][pos + srcHeight * picWidth + srcWidth];
+
+      dstPicBlockSameInfo[1][pos] = srcPicBlockSameInfo[1][pos] && srcPicBlockSameInfo[1][pos + srcWidth] && srcPicBlockSameInfo[1][pos + quadHeight * picWidth]
+        && srcPicBlockSameInfo[1][pos + quadHeight * picWidth + srcWidth] && srcPicBlockSameInfo[1][pos + srcHeight * picWidth] && srcPicBlockSameInfo[1][pos + srcHeight * picWidth + srcWidth];
+
+      pos++;
+    }
+    pos += width - 1;
+  }
+
+  if (width >= 4)
+  {
+    int widthMinus1 = width - 1;
+    int heightMinus1 = height - 1;
+    pos = 0;
+
+    for (int yPos = 0; yPos < yEnd; yPos++)
+    {
+      for (int xPos = 0; xPos < xEnd; xPos++)
+      {
+        dstPicBlockSameInfo[2][pos] = (!dstPicBlockSameInfo[0][pos] && !dstPicBlockSameInfo[1][pos]) || (((xPos & widthMinus1) == 0) && ((yPos & heightMinus1) == 0));
+        pos++;
+      }
+      pos += width - 1;
+    }
+  }
+
+  delete[] p;
+
+}
+
+void TComHash::addToHashMapByRowWithPrecalData(uint32_t* picHash[2], bool* picIsSame, int picWidth, int picHeight, int width, int height)
+{
+  int xEnd = picWidth - width + 1;
+  int yEnd = picHeight - height + 1;
+
+  bool* srcIsAdded = picIsSame;
+  uint32_t* srcHash[2] = { picHash[0], picHash[1] };
+
+  int addValue = m_blockSizeToIndex[width][height];
+  CHECK(addValue < 0, "Wrong")
+  addValue <<= m_CRCBits;
+  int crcMask = 1 << m_CRCBits;
+  crcMask -= 1;
+
+  for (int xPos = 0; xPos < xEnd; xPos++)
+  {
+    for (int yPos = 0; yPos < yEnd; yPos++)
+    {
+      int pos = yPos * picWidth + xPos;
+      //valid data
+      if (srcIsAdded[pos])
+      {
+        BlockHash blockHash;
+        blockHash.x = xPos;
+        blockHash.y = yPos;
+
+        uint32_t hashValue1 = (srcHash[0][pos] & crcMask) + addValue;
+        blockHash.hashValue2 = srcHash[1][pos];
+
+        addToTable(hashValue1, blockHash);
+      }
+    }
+  }
+}
+
+void TComHash::getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, unsigned char* pixelsIn1D, int xStart, int yStart, const BitDepths& bitDepths, bool includeAllComponent)
+{
+  ChromaFormat fmt = (curPicBuf).chromaFormat;
+  if (fmt != CHROMA_444)
+  {
+    includeAllComponent = false;
+  }
+
+  if (bitDepths.recon[CHANNEL_TYPE_LUMA] == 8 && bitDepths.recon[CHANNEL_TYPE_CHROMA] == 8)
+  {
+    Pel* curPel[3];
+    int stride[3];
+    for (int id = 0; id < 3; id++)
+    {
+      ComponentID compID = ComponentID(id);
+      stride[id] = (curPicBuf).get(compID).stride;
+      curPel[id] = (curPicBuf).get(compID).buf;
+      curPel[id] += (yStart >> getComponentScaleY(compID, fmt)) * stride[id] + (xStart >> getComponentScaleX(compID, fmt));
+    }
+
+    int index = 0;
+    for (int i = 0; i < 2; i++)
+    {
+      for (int j = 0; j < 2; j++)
+      {
+        pixelsIn1D[index++] = static_cast<unsigned char>(curPel[0][j]);
+        if (includeAllComponent)
+        {
+          pixelsIn1D[index++] = static_cast<unsigned char>(curPel[1][j]);
+          pixelsIn1D[index++] = static_cast<unsigned char>(curPel[2][j]);
+        }
+      }
+      curPel[0] += stride[0];
+      if (includeAllComponent)
+      {
+        curPel[1] += stride[1];
+        curPel[2] += stride[2];
+      }
+    }
+  }
+  else
+  {
+    int shift = bitDepths.recon[CHANNEL_TYPE_LUMA] - 8;
+    int shiftc = bitDepths.recon[CHANNEL_TYPE_CHROMA] - 8;
+    Pel* curPel[3];
+    int stride[3];
+    for (int id = 0; id < 3; id++)
+    {
+      ComponentID compID = ComponentID(id);
+      stride[id] = (curPicBuf).get(compID).stride;
+      curPel[id] = (curPicBuf).get(compID).buf;
+      curPel[id] += (yStart >> getComponentScaleY(compID, fmt)) * stride[id] + (xStart >> getComponentScaleX(compID, fmt));
+    }
+
+    int index = 0;
+    for (int i = 0; i < 2; i++)
+    {
+      for (int j = 0; j < 2; j++)
+      {
+        pixelsIn1D[index++] = static_cast<unsigned char>(curPel[0][j] >> shift);
+        if (includeAllComponent)
+        {
+          pixelsIn1D[index++] = static_cast<unsigned char>(curPel[1][j] >> shiftc);
+          pixelsIn1D[index++] = static_cast<unsigned char>(curPel[2][j] >> shiftc);
+        }
+      }
+      curPel[0] += stride[0];
+      if (includeAllComponent)
+      {
+        curPel[1] += stride[1];
+        curPel[2] += stride[2];
+      }
+    }
+  }
+}
+
+bool TComHash::isBlock2x2RowSameValue(unsigned char* p, bool includeAllComponent)
+{
+  if (includeAllComponent)
+  {
+    if (p[0] != p[3] || p[6] != p[9])
+    {
+      return false;
+    }
+    if (p[1] != p[4] || p[7] != p[10])
+    {
+      return false;
+    }
+    if (p[2] != p[5] || p[8] != p[11])
+    {
+      return false;
+    }
+  }
+  else
+  {
+    if (p[0] != p[1] || p[2] != p[3])
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool TComHash::isBlock2x2ColSameValue(unsigned char* p, bool includeAllComponent)
+{
+  if (includeAllComponent)
+  {
+    if (p[0] != p[6] || p[3] != p[9])
+    {
+      return false;
+    }
+    if (p[1] != p[7] || p[4] != p[10])
+    {
+      return false;
+    }
+    if (p[2] != p[8] || p[5] != p[11])
+    {
+      return false;
+    }
+  }
+  else
+  {
+    if ((p[0] != p[2]) || (p[1] != p[3]))
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool TComHash::getBlockHashValue(const PelUnitBuf &curPicBuf, int width, int height, int xStart, int yStart, const BitDepths bitDepths, uint32_t& hashValue1, uint32_t& hashValue2)
+{
+  int addValue = m_blockSizeToIndex[width][height];
+
+  CHECK(addValue < 0, "Wrong")
+  addValue <<= m_CRCBits;
+  int crcMask = 1 << m_CRCBits;
+  crcMask -= 1;
+  int length = 4;
+  bool includeChroma = false;
+  if ((curPicBuf).chromaFormat == CHROMA_444)
+  {
+    length *= 3;
+    includeChroma = true;
+  }
+
+  unsigned char* p = new unsigned char[length];
+  uint32_t* toHash = new uint32_t[4];
+
+  int block2x2Num = (width*height) >> 2;
+
+  uint32_t* hashValueBuffer[2][2];
+  for (int i = 0; i < 2; i++)
+  {
+    for (int j = 0; j < 2; j++)
+    {
+      hashValueBuffer[i][j] = new uint32_t[block2x2Num];
+    }
+  }
+
+  //2x2 subblock hash values in current CU
+  int subBlockInWidth = (width >> 1);
+  int subBlockInHeight = (height >> 1);
+  for (int yPos = 0; yPos < height; yPos += 2)
+  {
+    for (int xPos = 0; xPos < width; xPos += 2)
+    {
+      int pos = (yPos >> 1)*subBlockInWidth + (xPos >> 1);
+      TComHash::getPixelsIn1DCharArrayByBlock2x2(curPicBuf, p, xStart + xPos, yStart + yPos, bitDepths, includeChroma);
+
+      hashValueBuffer[0][0][pos] = TComHash::getCRCValue1(p, length * sizeof(unsigned char));
+      hashValueBuffer[1][0][pos] = TComHash::getCRCValue2(p, length * sizeof(unsigned char));
+    }
+  }
+
+  int srcSubBlockInWidth = subBlockInWidth;
+  subBlockInWidth >>= 1;
+  subBlockInHeight >>= 1;
+  length = 4 * sizeof(uint32_t);
+
+  int srcIdx = 1;
+  int dstIdx = 0;
+
+  //4x4 subblock hash values to current block hash values
+  int minSize = std::min(height, width);
+  for (int subWidth = 4; subWidth <= minSize; subWidth *= 2)
+  {
+    srcIdx = 1 - srcIdx;
+    dstIdx = 1 - dstIdx;
+
+    int dstPos = 0;
+    for (int yPos = 0; yPos < subBlockInHeight; yPos++)
+    {
+      for (int xPos = 0; xPos < subBlockInWidth; xPos++)
+      {
+        int srcPos = (yPos << 1)*srcSubBlockInWidth + (xPos << 1);
+
+        toHash[0] = hashValueBuffer[0][srcIdx][srcPos];
+        toHash[1] = hashValueBuffer[0][srcIdx][srcPos + 1];
+        toHash[2] = hashValueBuffer[0][srcIdx][srcPos + srcSubBlockInWidth];
+        toHash[3] = hashValueBuffer[0][srcIdx][srcPos + srcSubBlockInWidth + 1];
+
+        hashValueBuffer[0][dstIdx][dstPos] = TComHash::getCRCValue1((unsigned char*)toHash, length);
+
+        toHash[0] = hashValueBuffer[1][srcIdx][srcPos];
+        toHash[1] = hashValueBuffer[1][srcIdx][srcPos + 1];
+        toHash[2] = hashValueBuffer[1][srcIdx][srcPos + srcSubBlockInWidth];
+        toHash[3] = hashValueBuffer[1][srcIdx][srcPos + srcSubBlockInWidth + 1];
+        hashValueBuffer[1][dstIdx][dstPos] = TComHash::getCRCValue2((unsigned char*)toHash, length);
+
+        dstPos++;
+      }
+    }
+
+    srcSubBlockInWidth = subBlockInWidth;
+    subBlockInWidth >>= 1;
+    subBlockInHeight >>= 1;
+  }
+
+  if (width != height)//currently support 1:2 or 2:1 block size
+  {
+    CHECK(width != (height << 1) && (width << 1) != height, "Wrong")
+    bool isHorizontal = width == (height << 1) ? true : false;
+    length = 2 * sizeof(uint32_t);
+    srcIdx = 1 - srcIdx;
+    dstIdx = 1 - dstIdx;
+    if (isHorizontal)
+    {
+      toHash[0] = hashValueBuffer[0][srcIdx][0];
+      toHash[1] = hashValueBuffer[0][srcIdx][1];
+
+      hashValueBuffer[0][dstIdx][0] = TComHash::getCRCValue1((unsigned char*)toHash, length);
+
+      toHash[0] = hashValueBuffer[1][srcIdx][0];
+      toHash[1] = hashValueBuffer[1][srcIdx][1];
+      hashValueBuffer[1][dstIdx][0] = TComHash::getCRCValue2((unsigned char*)toHash, length);
+    }
+    else
+    {
+      CHECK(srcSubBlockInWidth != 1, "Wrong")
+      toHash[0] = hashValueBuffer[0][srcIdx][0];
+      toHash[1] = hashValueBuffer[0][srcIdx][srcSubBlockInWidth];
+
+      hashValueBuffer[0][dstIdx][0] = TComHash::getCRCValue1((unsigned char*)toHash, length);
+
+      toHash[0] = hashValueBuffer[1][srcIdx][0];
+      toHash[1] = hashValueBuffer[1][srcIdx][srcSubBlockInWidth];
+      hashValueBuffer[1][dstIdx][0] = TComHash::getCRCValue2((unsigned char*)toHash, length);
+    }
+  }
+
+  hashValue1 = (hashValueBuffer[0][dstIdx][0] & crcMask) + addValue;
+  hashValue2 = hashValueBuffer[1][dstIdx][0];
+
+  delete[] toHash;
+
+  for (int i = 0; i < 2; i++)
+  {
+    for (int j = 0; j < 2; j++)
+    {
+      delete[] hashValueBuffer[i][j];
+    }
+  }
+
+  delete[] p;
+
+  return true;
+}
+
+void TComHash::initBlockSizeToIndex()
+{
+  for (int i = 0; i < 65; i++)
+  {
+    for (int j = 0; j < 65; j++)
+    {
+      m_blockSizeToIndex[i][j] = -1;
+    }
+  }
+
+  m_blockSizeToIndex[8][8] = 0;
+  m_blockSizeToIndex[16][16] = 1;
+  m_blockSizeToIndex[32][32] = 2;
+  m_blockSizeToIndex[64][64] = 3;
+  m_blockSizeToIndex[4][4] = 4;
+  m_blockSizeToIndex[4][8] = 5;
+  m_blockSizeToIndex[8][4] = 6;
+}
+
+uint32_t TComHash::getCRCValue1(unsigned char* p, int length)
+{
+  m_crcCalculator1.reset();
+  m_crcCalculator1.processData(p, length);
+  return m_crcCalculator1.getCRC();
+}
+
+uint32_t TComHash::getCRCValue2(unsigned char* p, int length)
+{
+  m_crcCalculator2.reset();
+  m_crcCalculator2.processData(p, length);
+  return m_crcCalculator2.getCRC();
+}
+//! \}
diff --git a/source/Lib/CommonLib/Hash.h b/source/Lib/CommonLib/Hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..d69787cfc70eb38306153b2fc0e913793098fa66
--- /dev/null
+++ b/source/Lib/CommonLib/Hash.h
@@ -0,0 +1,134 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2019, 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.
+ */
+
+ /** \file     Hash.h
+     \brief    Hash class (header)
+ */
+
+
+#ifndef __HASH__
+#define __HASH__
+
+ // Include files
+
+#include "CommonLib/Buffer.h"
+#include "CommonLib/CommonDef.h"
+#include "CommonLib/TrQuant.h"
+#include "CommonLib/Unit.h"
+#include "CommonLib/UnitPartitioner.h"
+#include <vector>
+
+
+struct BlockHash
+{
+  short x;
+  short y;
+  uint32_t hashValue2;
+};
+
+typedef std::vector<BlockHash>::iterator MapIterator;
+
+// ====================================================================================================================
+// Class definitions
+// ====================================================================================================================
+
+
+struct TCRCCalculatorLight
+{
+public:
+  TCRCCalculatorLight(uint32_t bits, uint32_t truncPoly);
+  ~TCRCCalculatorLight();
+
+public:
+  void processData(unsigned char* curData, uint32_t dataLength);
+  void reset() { m_remainder = 0; }
+  uint32_t getCRC() { return m_remainder & m_finalResultMask; }
+
+private:
+  void xInitTable();
+
+private:
+  uint32_t m_remainder;
+  uint32_t m_truncPoly;
+  uint32_t m_bits;
+  uint32_t m_table[256];
+  uint32_t m_finalResultMask;
+};
+
+
+struct TComHash
+{
+public:
+  TComHash();
+  ~TComHash();
+  void create();
+  void clearAll();
+  void addToTable(uint32_t hashValue, const BlockHash& blockHash);
+  int count(uint32_t hashValue);
+  int count(uint32_t hashValue) const;
+  MapIterator getFirstIterator(uint32_t hashValue);
+  const MapIterator getFirstIterator(uint32_t hashValue) const;
+  bool hasExactMatch(uint32_t hashValue1, uint32_t hashValue2);
+
+  void generateBlock2x2HashValue(const PelUnitBuf &curPicBuf, int picWidth, int picHeight, const BitDepths bitDepths, uint32_t* picBlockHash[2], bool* picBlockSameInfo[3]);
+  void generateBlockHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3]);
+  void generateRectangleHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3]);
+  void addToHashMapByRowWithPrecalData(uint32_t* srcHash[2], bool* srcIsSame, int picWidth, int picHeight, int width, int height);
+  bool isInitial() { return tableHasContent; }
+  void setInitial() { tableHasContent = true; }
+
+
+
+public:
+  static uint32_t getCRCValue1(unsigned char* p, int length);
+  static uint32_t getCRCValue2(unsigned char* p, int length);
+  static void getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, unsigned char* pixelsIn1D, int xStart, int yStart, const BitDepths& bitDepths, bool includeAllComponent = true);
+  static bool isBlock2x2RowSameValue(unsigned char* p, bool includeAllComponent = true);
+  static bool isBlock2x2ColSameValue(unsigned char* p, bool includeAllComponent = true);
+  static bool getBlockHashValue(const PelUnitBuf &curPicBuf, int width, int height, int xStart, int yStart, const BitDepths bitDepths, uint32_t& hashValue1, uint32_t& hashValue2);
+  static void initBlockSizeToIndex();
+
+private:
+  std::vector<BlockHash>** m_lookupTable;
+  bool tableHasContent;
+
+private:
+  static const int m_CRCBits = 16;
+  static const int m_blockSizeBits = 3;
+  static int m_blockSizeToIndex[65][65];
+
+  static TCRCCalculatorLight m_crcCalculator1;
+  static TCRCCalculatorLight m_crcCalculator2;
+};
+
+#endif // __HASH__
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 205d74394e0cf0adc52f44834c3280f42728888d..473d844c98a0b024bc37dab51e6684a192f0233e 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -82,7 +82,15 @@ InterPrediction::InterPrediction()
       m_filteredBlockTmp[i][c] = nullptr;
     }
   }
-
+#if JVET_M0147_DMVR
+  m_cYuvPredTempDMVRL1 = nullptr;
+  m_cYuvPredTempDMVRL0 = nullptr;
+  for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
+  {
+    m_cRefSamplesDMVRL0[ch] = nullptr;
+    m_cRefSamplesDMVRL1[ch] = nullptr;
+  }
+#endif
 }
 
 InterPrediction::~InterPrediction()
@@ -128,6 +136,19 @@ void InterPrediction::destroy()
   xFree(m_gradY0);   m_gradY0 = nullptr;
   xFree(m_gradX1);   m_gradX1 = nullptr;
   xFree(m_gradY1);   m_gradY1 = nullptr;
+#if JVET_M0147_DMVR
+  xFree(m_cYuvPredTempDMVRL0);
+  m_cYuvPredTempDMVRL0 = nullptr;
+  xFree(m_cYuvPredTempDMVRL1);
+  m_cYuvPredTempDMVRL1 = nullptr;
+  for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
+  {
+    xFree(m_cRefSamplesDMVRL0[ch]);
+    m_cRefSamplesDMVRL0[ch] = nullptr;
+    xFree(m_cRefSamplesDMVRL1[ch]);
+    m_cRefSamplesDMVRL1[ch] = nullptr;
+  }
+#endif
 }
 
 void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC )
@@ -148,6 +169,10 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC )
     {
       int extWidth = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 16;
       int extHeight = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 1;
+#if JVET_M0147_DMVR
+      extWidth = extWidth > (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 16) ? extWidth : MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 16;
+      extHeight = extHeight > (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 1) ? extHeight : MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 1;
+#endif
       for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; i++ )
       {
         m_filteredBlockTmp[i][c] = ( Pel* ) xMalloc( Pel, ( extWidth + 4 ) * ( extHeight + 7 + 4 ) );
@@ -168,13 +193,22 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC )
     m_triangleBuf.create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
 
     m_iRefListIdx = -1;
-  
+
     m_gradX0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
     m_gradY0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
     m_gradX1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
     m_gradY1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
   }
 
+#if JVET_M0147_DMVR
+  m_cYuvPredTempDMVRL0 = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)));
+  m_cYuvPredTempDMVRL1 = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)));
+  for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
+  {
+    m_cRefSamplesDMVRL0[ch] = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA));
+    m_cRefSamplesDMVRL1[ch] = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA));
+  }
+#endif
 #if !JVET_J0090_MEMORY_BANDWITH_MEASURE
   m_if.initInterpolationFilter( true );
 #endif
@@ -326,7 +360,12 @@ void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const R
       subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
       subPu = curMi;
       PelUnitBuf subPredBuf = predBuf.subBuf(UnitAreaRelative(pu, subPu));
-
+#if JVET_M0823_MMVD_ENCOPT
+      subPu.mmvdEncOptMode = 0;
+#endif
+#if JVET_M0147_DMVR
+      subPu.mvRefine = false;
+#endif
       motionCompensation(subPu, subPredBuf, eRefPicList);
       secDim = later - secStep;
     }
@@ -365,8 +404,8 @@ void InterPrediction::xChromaMC(PredictionUnit &pu, PelUnitBuf& pcYuvPred)
 }
 
 
-void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi 
-                                   , const bool& bioApplied 
+void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi
+                                   , const bool& bioApplied
                                    , const bool luma, const bool chroma
 )
 {
@@ -375,7 +414,11 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList&
   int iRefIdx = pu.refIdx[eRefPicList];
   Mv mv[3];
   bool isIBC = false;
+#if JVET_M0483_IBC
+  if (CU::isIBC(*pu.cu))
+#else
   if (pu.cs->slice->getRefPic(eRefPicList, iRefIdx)->getPOC() == pu.cs->slice->getPOC())
+#endif
   {
     isIBC = true;
   }
@@ -396,7 +439,6 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList&
          pu.cu->lumaSize(),
          sps);
 
-
   for( uint32_t comp = COMPONENT_Y; comp < pcYuvPred.bufs.size() && comp <= m_maxCompIDToPred; comp++ )
   {
     const ComponentID compID = ComponentID( comp );
@@ -411,11 +453,27 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList&
     }
     else
     {
+#if JVET_M0483_IBC
+      if (isIBC)
+      {
+        xPredInterBlk(compID, pu, pu.cu->slice->getPic(), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID)
+          , bioApplied
+          , isIBC
+        );
+      }
+      else
+      {
+        xPredInterBlk(compID, pu, pu.cu->slice->getRefPic(eRefPicList, iRefIdx), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID)
+          , bioApplied
+          , isIBC
+        );
+      }
+#else
       xPredInterBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx ), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng( compID )
                     , bioApplied
                     , isIBC
                     );
-
+#endif
     }
   }
 }
@@ -453,12 +511,20 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
     }
 #endif
 
-    if (pu.cu->cs->sps->getSpsNext().getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
+    if (pu.cu->cs->sps->getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
     {
       bioApplied = false;
     }
   }
-
+#if JVET_M0823_MMVD_ENCOPT
+  if (pu.mmvdEncOptMode == 2 && pu.mmvdMergeFlag) {
+    bioApplied = false;
+  }
+#endif
+#if JVET_M0147_DMVR
+  bool dmvrApplied = false;
+  dmvrApplied = (pu.mvRefine) && PU::checkDMVRCondition(pu);
+#endif
   for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
   {
     if( pu.refIdx[refList] < 0)
@@ -468,7 +534,13 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
 
     RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
 
+#if JVET_M0483_IBC
+    CHECK(CU::isIBC(*pu.cu) && eRefPicList != REF_PIC_LIST_0, "Invalid interdir for ibc mode");
+    CHECK(CU::isIBC(*pu.cu) && pu.refIdx[refList] != MAX_NUM_REF, "Invalid reference index for ibc mode");
+    CHECK((CU::isInter(*pu.cu) && pu.refIdx[refList] >= slice.getNumRefIdx(eRefPicList)), "Invalid reference index");
+#else
     CHECK( pu.refIdx[refList] >= slice.getNumRefIdx( eRefPicList ), "Invalid reference index" );
+#endif
     m_iRefListIdx = refList;
 
     PelUnitBuf pcMbBuf = ( pu.chromaFormat == CHROMA_400 ?
@@ -477,6 +549,10 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
 
     if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
     {
+#if JVET_M0147_DMVR
+      if (dmvrApplied)
+        continue; // mc will happen in processDMVR
+#endif
       xPredInterUni ( pu, eRefPicList, pcMbBuf, true
         , bioApplied
         , true, true
@@ -486,20 +562,26 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
     {
       if( ( (pps.getUseWP() && slice.getSliceType() == P_SLICE) || (pps.getWPBiPred() && slice.getSliceType() == B_SLICE) ) )
       {
-        xPredInterUni ( pu, eRefPicList, pcMbBuf, true 
+        xPredInterUni ( pu, eRefPicList, pcMbBuf, true
           , bioApplied
           , true, true
         );
       }
       else
       {
-        xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle 
+        xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle
           , bioApplied
           , true, true
         );
       }
     }
   }
+#if JVET_M0147_DMVR
+  if (dmvrApplied)
+  {
+    xProcessDMVR(pu, pcYuvPred, slice.clpRngs(), bioApplied);
+  }
+#endif
 
 
   CPelUnitBuf srcPred0 = ( pu.chromaFormat == CHROMA_400 ?
@@ -518,14 +600,33 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
   }
   else
   {
+#if JVET_M0147_DMVR
+    if (dmvrApplied == false)
+    {
+#endif
     xWeightedAverage( pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied );
+#if JVET_M0147_DMVR
+    }
+#endif
   }
 }
 
+#if JVET_M0147_DMVR
+void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
+                                     , const bool& bioApplied
+                                     , bool isIBC
+                                     , SizeType dmvrWidth
+                                     , SizeType dmvrHeight
+                                     , bool bilinearMC
+                                     , Pel *srcPadBuf
+                                     , int32_t srcPadStride
+                                    )
+#else
 void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
                                      , const bool& bioApplied
                                      , bool isIBC
                                     )
+#endif
 {
   JVET_J0090_SET_REF_PICTURE( refPic, compID );
   const ChromaFormat  chFmt = pu.chromaFormat;
@@ -549,9 +650,28 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
   CPelBuf refBuf;
   {
     Position offset = pu.blocks[compID].pos().offset( _mv.getHor() >> shiftHor, _mv.getVer() >> shiftVer );
+#if JVET_M0147_DMVR
+    if (dmvrWidth)
+    {
+      refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(dmvrWidth, dmvrHeight)));
+    }
+    else
+#endif
     refBuf = refPic->getRecoBuf( CompArea( compID, chFmt, offset, pu.blocks[compID].size() ) );
   }
 
+#if JVET_M0147_DMVR
+  if (NULL != srcPadBuf)
+  {
+    refBuf.buf = srcPadBuf;
+    refBuf.stride = srcPadStride;
+  }
+  if (dmvrWidth)
+  {
+    width = dmvrWidth;
+    height = dmvrHeight;
+  }
+#endif
   // backup data
   int backupWidth = width;
   int backupHeight = height;
@@ -570,21 +690,49 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
 
   if( yFrac == 0 )
   {
+#if JVET_M0147_DMVR
+    m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
+#else
     m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng);
+#endif
   }
   else if( xFrac == 0 )
   {
+#if JVET_M0147_DMVR
+    m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
+#else
     m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng);
+#endif
   }
   else
   {
+#if JVET_M0147_DMVR
+    PelBuf tmpBuf = dmvrWidth ? PelBuf(m_filteredBlockTmp[0][compID], Size(dmvrWidth, dmvrHeight)) : PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
+    if (dmvrWidth == 0)
+      tmpBuf.stride = dstBuf.stride;
+#else
     PelBuf tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
     tmpBuf.stride = dstBuf.stride;
+#endif
 
     int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA;
+#if JVET_M0147_DMVR
+    if (bilinearMC)
+    {
+      vFilterSize = NTAPS_BILINEAR;
+    }
+#endif
+#if JVET_M0147_DMVR
+    m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, bilinearMC, bilinearMC);
+#else
     m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng);
+#endif
     JVET_J0090_SET_CACHE_ENABLE( false );
+#if JVET_M0147_DMVR
+    m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
+#else
     m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng);
+#endif
   }
   JVET_J0090_SET_CACHE_ENABLE( true );
   if (bioApplied && compID == COMPONENT_Y)
@@ -622,11 +770,18 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
     }
 #else
     refBuf.buf = refBuf.buf - refBuf.stride - 1;
+#if JVET_M0147_DMVR
+    if (srcPadBuf)
+    {
+      refBuf.buf = srcPadBuf - srcPadStride - 1;
+      refBuf.stride = srcPadStride;
+    }
+#endif
     dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + dstBuf.stride + 1;
     bioSampleExtendBilinearFilter(refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, width - 2, height - 2, 1, xFrac, yFrac, rndRes, chFmt, clpRng);
 #endif
 
-    // restore data 
+    // restore data
     width = backupWidth;
     height = backupHeight;
     dstBuf.buf = backupDstBufPtr;
@@ -724,6 +879,12 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio
         iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h);
         iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h);
         roundAffineMv(iMvScaleTmpHor, iMvScaleTmpVer, shift);
+#if JVET_M0145_AFFINE_MV_CLIP
+        Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer);
+        tmpMv.clipToStorageBitDepth();
+        iMvScaleTmpHor = tmpMv.getHor();
+        iMvScaleTmpVer = tmpMv.getVer();
+#endif
 
         // clip and scale
         if (sps.getWrapAroundEnabledFlag())
@@ -736,24 +897,55 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio
         }
         else
         {
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+          m_storedMv[h / AFFINE_MIN_BLOCK_SIZE * MVBUFFER_SIZE + w / AFFINE_MIN_BLOCK_SIZE].set(iMvScaleTmpHor, iMvScaleTmpVer);
+#endif
           iMvScaleTmpHor = std::min<int>(iHorMax, std::max<int>(iHorMin, iMvScaleTmpHor));
           iMvScaleTmpVer = std::min<int>(iVerMax, std::max<int>(iVerMin, iMvScaleTmpVer));
-
+#if !JVET_M0265_MV_ROUNDING_CLEANUP
           m_storedMv[h / AFFINE_MIN_BLOCK_SIZE * MVBUFFER_SIZE + w / AFFINE_MIN_BLOCK_SIZE].set(iMvScaleTmpHor, iMvScaleTmpVer);
+#endif
         }
       }
       else
       {
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+#if JVET_M0192_AFF_CHROMA_SIMPL
+        Mv curMv = m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE) * MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
+          m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)];
+        roundAffineMv(curMv.hor, curMv.ver, 1);
+#else
+        Mv curMv = m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE) * MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
+          m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
+          m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)] +
+          m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)];
+        roundAffineMv(curMv.hor, curMv.ver, 2);
+#endif
+#else
+#if JVET_M0192_AFF_CHROMA_SIMPL
+        Mv curMv = m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE) * MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
+          m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)];
+        roundAffineMv(curMv.hor, curMv.ver, 1);
+#else
         Mv curMv = (m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE) * MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
           m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
           m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)] +
           m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)] +
           Mv(2, 2));
-        curMv.set(curMv.getHor() >> 2, curMv.getVer() >> 2);     
+        curMv.set(curMv.getHor() >> 2, curMv.getVer() >> 2);
+#endif
+#endif
         if (sps.getWrapAroundEnabledFlag())
         {
           clipMv(curMv, Position(pu.Y().x + (w << iScaleX), pu.Y().y + (h << iScaleY)), Size(blockWidth << iScaleX, blockHeight << iScaleY), sps);
         }
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+        else
+        {
+          curMv.hor = std::min<int>(iHorMax, std::max<int>(iHorMin, curMv.hor));
+          curMv.ver = std::min<int>(iVerMax, std::max<int>(iVerMin, curMv.ver));
+        }
+#endif
         iMvScaleTmpHor = curMv.hor;
         iMvScaleTmpVer = curMv.ver;
       }
@@ -850,7 +1042,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
     Pel* gradY = (refList == 0) ? m_gradY0 : m_gradY1;
     Pel* gradX = (refList == 0) ? m_gradX0 : m_gradX1;
 
+#if JVET_M0063_BDOF_FIX
+    xBioGradFilter(dstTempPtr, stridePredMC, widthG, heightG, widthG, gradX, gradY, clipBitDepths.recon[toChannelType(COMPONENT_Y)]);
+#else
     xBioGradFilter(dstTempPtr, stridePredMC, widthG, heightG, widthG, gradX, gradY);
+#endif
     Pel* padStr = m_filteredBlockTmp[2 + refList][COMPONENT_Y] + 2 * stridePredMC + 2;
     for (int y = 0; y< height; y++)
     {
@@ -868,7 +1064,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
   const int   bitDepth = clipBitDepths.recon[toChannelType(COMPONENT_Y)];
   const int   shiftNum = IF_INTERNAL_PREC + 1 - bitDepth;
   const int   offset = (1 << (shiftNum - 1)) + 2 * IF_INTERNAL_OFFS;
+#if JVET_M0063_BDOF_FIX
+  const int   limit = (bitDepth>12)? 2 : ((int)1 << (4 + IF_INTERNAL_PREC - bitDepth - 5));
+#else
   const int   limit = ((int)1 << (4 + IF_INTERNAL_PREC - bitDepth - 5));
+#endif
 
   int*     dotProductTemp1 = m_dotProduct1;
   int*     dotProductTemp2 = m_dotProduct2;
@@ -876,7 +1076,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
   int*     dotProductTemp5 = m_dotProduct5;
   int*     dotProductTemp6 = m_dotProduct6;
 
+#if JVET_M0063_BDOF_FIX
+  xCalcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, widthG, widthG, heightG, bitDepth);
+#else
   xCalcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, widthG, widthG, heightG);
+#endif
 
   int xUnit = (width >> 2);
   int yUnit = (height >> 2);
@@ -1041,6 +1245,17 @@ void InterPrediction::xAddBIOAvg4(const Pel* src0, int src0Stride, const Pel* sr
   g_pelBufOP.addBIOAvg4(src0, src0Stride, src1, src1Stride, dst, dstStride, gradX0, gradX1, gradY0, gradY1, gradStride, width, height, tmpx, tmpy, shift, offset, clpRng);
 }
 
+#if JVET_M0063_BDOF_FIX
+void InterPrediction::xBioGradFilter(Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, int bitDepth)
+{
+  g_pelBufOP.bioGradFilter(pSrc, srcStride, width, height, gradStride, gradX, gradY, bitDepth);
+}
+
+void InterPrediction::xCalcBIOPar(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, int bitDepth)
+{
+  g_pelBufOP.calcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, gradStride, widthG, heightG, bitDepth);
+}
+#else
 void InterPrediction::xBioGradFilter(Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY)
 {
   g_pelBufOP.bioGradFilter(pSrc, srcStride, width, height, gradStride, gradX, gradY);
@@ -1050,6 +1265,7 @@ void InterPrediction::xCalcBIOPar(const Pel* srcY0Temp, const Pel* srcY1Temp, co
 {
   g_pelBufOP.calcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, gradStride, widthG, heightG);
 }
+#endif
 
 void InterPrediction::xCalcBlkGradient(int sx, int sy, int    *arraysGx2, int     *arraysGxGy, int     *arraysGxdI, int     *arraysGy2, int     *arraysGydI, int     &sGx2, int     &sGy2, int     &sGxGy, int     &sGxdI, int     &sGydI, int width, int height, int unitSize)
 {
@@ -1108,12 +1324,12 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB
   }
 }
 
-void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBuf, const RefPicList &eRefPicList 
+void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBuf, const RefPicList &eRefPicList
   , const bool luma, const bool chroma
 )
 {
   // dual tree handling for IBC as the only ref
-  if (!luma || !chroma)
+  if ((!luma || !chroma) && eRefPicList == REF_PIC_LIST_0)
   {
     if (!luma && chroma)
     {
@@ -1137,7 +1353,7 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
   {
     if( ( ( sliceType == P_SLICE && pps.getUseWP() ) || ( sliceType == B_SLICE && pps.getWPBiPred() ) ) )
     {
-      xPredInterUni         ( pu,          eRefPicList, predBuf, true 
+      xPredInterUni         ( pu,          eRefPicList, predBuf, true
         , false
         , true, true
       );
@@ -1145,7 +1361,7 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
     }
     else
     {
-      xPredInterUni( pu, eRefPicList, predBuf, false 
+      xPredInterUni( pu, eRefPicList, predBuf, false
         , false
         , true, true
       );
@@ -1159,7 +1375,7 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
     }
     else if( xCheckIdenticalMotion( pu ) )
     {
-      xPredInterUni( pu, REF_PIC_LIST_0, predBuf, false 
+      xPredInterUni( pu, REF_PIC_LIST_0, predBuf, false
         , false
         , true, true
       );
@@ -1172,25 +1388,31 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
   return;
 }
 
-void InterPrediction::motionCompensation( CodingUnit &cu, const RefPicList &eRefPicList 
+void InterPrediction::motionCompensation( CodingUnit &cu, const RefPicList &eRefPicList
   , const bool luma, const bool chroma
 )
 {
   for( auto &pu : CU::traversePUs( cu ) )
   {
     PelUnitBuf predBuf = cu.cs->getPredBuf( pu );
-    motionCompensation( pu, predBuf, eRefPicList 
+#if JVET_M0147_DMVR
+    pu.mvRefine = true;
+#endif
+    motionCompensation( pu, predBuf, eRefPicList
       , luma, chroma
     );
+#if JVET_M0147_DMVR
+    pu.mvRefine = false;
+#endif
   }
 }
 
-void InterPrediction::motionCompensation( PredictionUnit &pu, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/ 
+void InterPrediction::motionCompensation( PredictionUnit &pu, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/
   , const bool luma, const bool chroma
 )
 {
   PelUnitBuf predBuf = pu.cs->getPredBuf( pu );
-  motionCompensation( pu, predBuf, eRefPicList 
+  motionCompensation( pu, predBuf, eRefPicList
     , luma, chroma
   );
 }
@@ -1220,21 +1442,46 @@ void InterPrediction::motionCompensation4Triangle( CodingUnit &cu, MergeCtx &tri
     const UnitArea localUnitArea( cu.cs->area.chromaFormat, Area( 0, 0, pu.lwidth(), pu.lheight() ) );
     PelUnitBuf tmpTriangleBuf = m_triangleBuf.getBuf( localUnitArea );
     PelUnitBuf predBuf        = cu.cs->getPredBuf( pu );
-     
+
     triangleMrgCtx.setMergeInfo( pu, candIdx0 );
     PU::spanMotionInfo( pu );
     motionCompensation( pu, tmpTriangleBuf );
-   
+
     triangleMrgCtx.setMergeInfo( pu, candIdx1 );
     PU::spanMotionInfo( pu );
     motionCompensation( pu, predBuf );
 
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+    weightedTriangleBlk( pu, splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, tmpTriangleBuf, predBuf );
+#else
     weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, tmpTriangleBuf, predBuf );
+#endif
   }
 }
 
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
+#else
 void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, bool weights, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
+#endif
 {
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+  if( channel == CHANNEL_TYPE_LUMA )
+  {
+    xWeightedTriangleBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 );
+  }
+  else if( channel == CHANNEL_TYPE_CHROMA )
+  {
+    xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
+    xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
+  }
+  else
+  {
+    xWeightedTriangleBlk( pu, pu.lumaSize().width,   pu.lumaSize().height,   COMPONENT_Y,  splitDir, predDst, predSrc0, predSrc1 );
+    xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
+    xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
+  }
+#else
   if( channel == CHANNEL_TYPE_LUMA )
   {
     xWeightedTriangleBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, weights, predDst, predSrc0, predSrc1 );
@@ -1250,9 +1497,14 @@ void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, bool weights, con
     xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, weights, predDst, predSrc0, predSrc1 );
     xWeightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, weights, predDst, predSrc0, predSrc1 );
   }
+#endif
 }
 
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+void InterPrediction::xWeightedTriangleBlk( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
+#else
 void InterPrediction::xWeightedTriangleBlk( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, const bool weights, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
+#endif
 {
   Pel*    dst        = predDst .get(compIdx).buf;
   Pel*    src0       = predSrc0.get(compIdx).buf;
@@ -1268,18 +1520,28 @@ void InterPrediction::xWeightedTriangleBlk( const PredictionUnit &pu, const uint
   const int32_t offsetDefault     = (1<<(shiftDefault-1)) + IF_INTERNAL_OFFS;
   const int32_t shiftWeighted     = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + log2WeightBase;
   const int32_t offsetWeighted    = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase);
-                                  
+
   const int32_t ratioWH           = (width > height) ? (width / height) : 1;
   const int32_t ratioHW           = (width > height) ? 1 : (height / width);
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+  const bool    longWeight        = (compIdx == COMPONENT_Y) || ( predDst.chromaFormat == CHROMA_444 );
+  const int32_t weightedLength    = longWeight ? 7 : 3;
+#else
   const Pel*    pelWeighted       = (compIdx == COMPONENT_Y) ? g_trianglePelWeightedLuma[splitDir][weights] : g_trianglePelWeightedChroma[predDst.chromaFormat == CHROMA_444 ? 0 : 1][splitDir][weights];
   const int32_t weightedLength    = (compIdx == COMPONENT_Y) ? g_triangleWeightLengthLuma[weights] : g_triangleWeightLengthChroma[predDst.chromaFormat == CHROMA_444 ? 0 : 1][weights];
+#endif
         int32_t weightedStartPos  = ( splitDir == 0 ) ? ( 0 - (weightedLength >> 1) * ratioWH ) : ( width - ((weightedLength + 1) >> 1) * ratioWH );
         int32_t weightedEndPos    = weightedStartPos + weightedLength * ratioWH - 1;
         int32_t weightedPosoffset =( splitDir == 0 ) ? ratioWH : -ratioWH;
-  
+
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+        Pel     tmpPelWeighted;
+        int32_t weightIdx;
+#else
   const Pel*    tmpPelWeighted;
+#endif
         int32_t x, y, tmpX, tmpY, tmpWeightedStart, tmpWeightedEnd;
-  
+
   for( y = 0; y < height; y+= ratioHW )
   {
     for( tmpY = ratioHW; tmpY > 0; tmpY-- )
@@ -1293,18 +1555,36 @@ void InterPrediction::xWeightedTriangleBlk( const PredictionUnit &pu, const uint
 
       tmpWeightedStart = std::max((int32_t)0, weightedStartPos);
       tmpWeightedEnd   = std::min(weightedEndPos, (int32_t)(width - 1));
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+      weightIdx        = 1;
+#else
       tmpPelWeighted   = pelWeighted;
+#endif
       if( weightedStartPos < 0 )
       {
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+        weightIdx     += abs(weightedStartPos) / ratioWH;
+#else
         tmpPelWeighted += abs(weightedStartPos) / ratioWH;
+#endif
       }
       for( x = tmpWeightedStart; x <= tmpWeightedEnd; x+= ratioWH )
       {
         for( tmpX = ratioWH; tmpX > 0; tmpX-- )
         {
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+          tmpPelWeighted = Clip3( 1, 7, longWeight ? weightIdx : (weightIdx * 2));
+          tmpPelWeighted = splitDir ? ( 8 - tmpPelWeighted ) : tmpPelWeighted;
+          *dst++         = ClipPel( rightShift( (tmpPelWeighted*(*src0++) + ((8 - tmpPelWeighted) * (*src1++)) + offsetWeighted), shiftWeighted ), clipRng );
+#else
           *dst++ = ClipPel( rightShift( ((*tmpPelWeighted)*(*src0++) + ((8 - (*tmpPelWeighted)) * (*src1++)) + offsetWeighted), shiftWeighted ), clipRng );
+#endif
         }
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+        weightIdx ++;
+#else
         tmpPelWeighted++;
+#endif
       }
 
       for( x = weightedEndPos + 1; x < width; x++ )
@@ -1323,6 +1603,445 @@ void InterPrediction::xWeightedTriangleBlk( const PredictionUnit &pu, const uint
   }
 }
 
+#if JVET_M0147_DMVR
+void InterPrediction::xPrefetchPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId)
+{
+  int offset, width, height;
+  int padsize;
+  Mv cMv;
+  const Picture* refPic = pu.cu->slice->getRefPic(refId, pu.refIdx[refId]);
+  int mvShift = (MV_FRACTIONAL_BITS_INTERNAL);
+  for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+  {
+    cMv = Mv(pu.mv[refId].getHor(), pu.mv[refId].getVer());
+    pcPad.bufs[compID].stride = (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA);
+    int filtersize = (compID == (COMPONENT_Y)) ? NTAPS_LUMA : NTAPS_CHROMA;
+    width = pcPad.bufs[compID].width;
+    height = pcPad.bufs[compID].height;
+    offset = (DMVR_NUM_ITERATION) * (pcPad.bufs[compID].stride + 1);
+    padsize = (DMVR_NUM_ITERATION) >> getComponentScaleX((ComponentID)compID, pu.chromaFormat);
+    int mvshiftTemp = mvShift + getComponentScaleX((ComponentID)compID, pu.chromaFormat);
+    width += (filtersize - 1);
+    height += (filtersize - 1);
+    cMv += Mv(-(((filtersize >> 1) - 1) << mvshiftTemp),
+      -(((filtersize >> 1) - 1) << mvshiftTemp));
+    clipMv(cMv, pu.lumaPos(), pu.lumaSize(),*pu.cs->sps);
+    /* Pre-fetch similar to HEVC*/
+    {
+      CPelBuf refBuf;
+      Position Rec_offset = pu.blocks[compID].pos().offset(cMv.getHor() >> mvshiftTemp, cMv.getVer() >> mvshiftTemp);
+      refBuf = refPic->getRecoBuf(CompArea((ComponentID)compID, pu.chromaFormat, Rec_offset, pu.blocks[compID].size()));
+      PelBuf &dstBuf = pcPad.bufs[compID];
+      g_pelBufOP.copyBuffer((Pel *)refBuf.buf, refBuf.stride, ((Pel *)dstBuf.buf) + offset, dstBuf.stride, width, height);
+    }
+    /*padding on all side of size DMVR_PAD_LENGTH*/
+    {
+      g_pelBufOP.padding(pcPad.bufs[compID].buf + offset, pcPad.bufs[compID].stride, width, height, padsize);
+    }
+  }
+}
+inline int32_t div_for_maxq7(int64_t N, int64_t D)
+{
+  int32_t sign, q;
+  sign = 0;
+  if (N < 0)
+  {
+    sign = 1;
+    N = -N;
+  }
+
+  q = 0;
+  D = (D << 3);
+  if (N >= D)
+  {
+    N -= D;
+    q++;
+  }
+  q = (q << 1);
+
+  D = (D >> 1);
+  if (N >= D)
+  {
+    N -= D;
+    q++;
+  }
+  q = (q << 1);
+
+  if (N >= (D >> 1))
+    q++;
+
+  if (sign)
+    return (-q);
+  return(q);
+}
+
+void xSubPelErrorSrfc(uint64_t *sadBuffer, int32_t *deltaMv)
+{
+  int64_t numerator, denominator;
+  int32_t mvDeltaSubPel;
+  int32_t mvSubPelLvl = 4;/*1: half pel, 2: Qpel, 3:1/8, 4: 1/16*/
+                                                        /*horizontal*/
+    numerator = (int64_t)((sadBuffer[1] - sadBuffer[3]) << mvSubPelLvl);
+    denominator = (int64_t)((sadBuffer[1] + sadBuffer[3] - (sadBuffer[0] << 1)));
+
+    if (0 != denominator)
+    {
+      if ((sadBuffer[1] != sadBuffer[0]) && (sadBuffer[3] != sadBuffer[0]))
+      {
+        mvDeltaSubPel = div_for_maxq7(numerator, denominator);
+        deltaMv[0] = (mvDeltaSubPel);
+      }
+      else
+      {
+        if (sadBuffer[1] == sadBuffer[0])
+        {
+          deltaMv[0] = -8;// half pel
+        }
+        else
+        {
+          deltaMv[0] = 8;// half pel
+        }
+      }
+    }
+
+    /*vertical*/
+    numerator = (int64_t)((sadBuffer[2] - sadBuffer[4]) << mvSubPelLvl);
+    denominator = (int64_t)((sadBuffer[2] + sadBuffer[4] - (sadBuffer[0] << 1)));
+    if (0 != denominator)
+    {
+      if ((sadBuffer[2] != sadBuffer[0]) && (sadBuffer[4] != sadBuffer[0]))
+      {
+        mvDeltaSubPel = div_for_maxq7(numerator, denominator);
+        deltaMv[1] = (mvDeltaSubPel);
+      }
+      else
+      {
+        if (sadBuffer[2] == sadBuffer[0])
+        {
+          deltaMv[1] = -8;// half pel
+        }
+        else
+        {
+          deltaMv[1] = 8;// half pel
+        }
+      }
+    }
+  return;
+}
+
+void InterPrediction::xBIPMVRefine(int bd, Pel *pRefL0, Pel *pRefL1, uint64_t& minCost, int16_t *deltaMV, uint64_t *pSADsArray, int width, int height)
+{
+  const int32_t refStrideL0 = m_biLinearBufStride;
+  const int32_t refStrideL1 = m_biLinearBufStride;
+  Pel *pRefL0Orig = pRefL0;
+  Pel *pRefL1Orig = pRefL1;
+  for (int nIdx = SAD_BOTTOM; nIdx <= SAD_TOP_LEFT; ++nIdx)
+  {
+    int32_t sadOffset = ((m_pSearchOffset[nIdx].getVer() * ((2 * DMVR_NUM_ITERATION) + 1)) + m_pSearchOffset[nIdx].getHor());
+    pRefL0 = pRefL0Orig + m_pSearchOffset[nIdx].hor + (m_pSearchOffset[nIdx].ver * refStrideL0);
+    pRefL1 = pRefL1Orig - m_pSearchOffset[nIdx].hor - (m_pSearchOffset[nIdx].ver * refStrideL1);
+    if (*(pSADsArray + sadOffset) == MAX_UINT64)
+    {
+      const uint64_t cost = xDMVRCost(bd, pRefL0, refStrideL0, pRefL1, refStrideL1, width, height);
+      *(pSADsArray + sadOffset) = cost;
+    }
+    if (nIdx == SAD_LEFT)
+    {
+      int32_t down = -1, right = -1;
+      if (pSADsArray[(((2 * DMVR_NUM_ITERATION) + 1))] < pSADsArray[-(((2 * DMVR_NUM_ITERATION) + 1))])
+      {
+        down = 1;
+      }
+      if (pSADsArray[1] < pSADsArray[-1])
+      {
+        right = 1;
+      }
+      m_pSearchOffset[SAD_TOP_LEFT].set(right, down);
+    }
+    if (*(pSADsArray + sadOffset) < minCost)
+    {
+      minCost = *(pSADsArray + sadOffset);
+      deltaMV[0] = m_pSearchOffset[nIdx].getHor();
+      deltaMV[1] = m_pSearchOffset[nIdx].getVer();
+    }
+  }
+}
+
+void InterPrediction::xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvSrc0, PelUnitBuf &pcYuvSrc1, PelUnitBuf &pcPad0, PelUnitBuf &pcPad1, const bool bioApplied
+  , const Mv mergeMV[NUM_REF_PIC_LIST_01]
+)
+{
+  int offset, deltaIntMvX, deltaIntMvY;
+
+  PelUnitBuf pcYUVTemp = pcYuvSrc0;
+  PelUnitBuf pcPadTemp = pcPad0;
+  /*always high precision MVs are used*/
+  int mvShift = MV_FRACTIONAL_BITS_INTERNAL;
+
+  for (int k = 0; k < NUM_REF_PIC_LIST_01; k++)
+  {
+    RefPicList refId = (RefPicList)k;
+    Mv cMv = pu.mv[refId];
+    m_iRefListIdx = refId;
+    const Picture* refPic = pu.cu->slice->getRefPic(refId, pu.refIdx[refId]);
+    clipMv(cMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps);
+
+    Mv startMv = mergeMV[refId];
+    clipMv(startMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps);
+
+    for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+    {
+      int mvshiftTemp = mvShift + getComponentScaleX((ComponentID)compID, pu.chromaFormat);
+      int leftPixelExtra;
+      if (compID == COMPONENT_Y)
+      {
+        leftPixelExtra = (NTAPS_LUMA >> 1) - 1;
+      }
+      else
+      {
+        leftPixelExtra = (NTAPS_CHROMA >> 1) - 1;
+      }
+
+      deltaIntMvX = (cMv.getHor() >> mvshiftTemp) -
+        (startMv.getHor() >> mvshiftTemp);
+      deltaIntMvY = (cMv.getVer() >> mvshiftTemp) -
+        (startMv.getVer() >> mvshiftTemp);
+
+      CHECK((abs(deltaIntMvX) > DMVR_NUM_ITERATION) || (abs(deltaIntMvY) > DMVR_NUM_ITERATION), "not expected DMVR movement");
+
+      offset = (DMVR_NUM_ITERATION + leftPixelExtra) * (pcPadTemp.bufs[compID].stride + 1);
+      offset += (deltaIntMvY)* pcPadTemp.bufs[compID].stride;
+      offset += (deltaIntMvX);
+      PelBuf &srcBuf = pcPadTemp.bufs[compID];
+      xPredInterBlk((ComponentID)compID, pu, refPic, cMv, pcYUVTemp, true, pu.cs->slice->getClpRngs().comp[compID],
+        bioApplied, false, 0, 0, 0, (srcBuf.buf + offset), pcPadTemp.bufs[compID].stride);
+    }
+    pcYUVTemp = pcYuvSrc1;
+    pcPadTemp = pcPad1;
+  }
+}
+
+uint64_t InterPrediction::xDMVRCost(int bitDepth, Pel* pOrg, uint32_t refStride, const Pel* pRef, uint32_t orgStride, int width, int height)
+{
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+  cDistParam.useMR = false;
+  m_pcRdCost->setDistParam(cDistParam, pOrg, pRef, orgStride, refStride, bitDepth, COMPONENT_Y, width, height, 1);
+  uint64_t uiCost = cDistParam.distFunc(cDistParam);
+  return uiCost;
+}
+
+void xDMVRSubPixelErrorSurface(bool notZeroCost, int16_t *totalDeltaMV, int16_t *deltaMV, uint64_t *pSADsArray)
+{
+
+  int sadStride = (((2 * DMVR_NUM_ITERATION) + 1));
+  uint64_t sadbuffer[5];
+  if (notZeroCost && deltaMV[0] == 0 && deltaMV[1] == 0)
+  {
+    int32_t tempDeltaMv[2] = { 0,0 };
+    sadbuffer[0] = pSADsArray[0];
+    sadbuffer[1] = pSADsArray[-1];
+    sadbuffer[2] = pSADsArray[-sadStride];
+    sadbuffer[3] = pSADsArray[1];
+    sadbuffer[4] = pSADsArray[sadStride];
+    xSubPelErrorSrfc(sadbuffer, tempDeltaMv);
+    totalDeltaMV[0] += tempDeltaMv[0];
+    totalDeltaMV[1] += tempDeltaMv[1];
+  }
+}
+
+void InterPrediction::xinitMC(PredictionUnit& pu, const ClpRngs &clpRngs)
+{
+  const int refIdx0 = pu.refIdx[0];
+  const int refIdx1 = pu.refIdx[1];
+  /*use merge MV as starting MV*/
+  Mv mergeMVL0(pu.mv[REF_PIC_LIST_0]);
+  Mv mergeMVL1(pu.mv[REF_PIC_LIST_1]);
+
+  /*Clip the starting MVs*/
+  clipMv(mergeMVL0, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps);
+  clipMv(mergeMVL1, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps);
+
+  /*L0 MC for refinement*/
+  {
+    int offset;
+    int leftPixelExtra = (NTAPS_LUMA >> 1) - 1;
+    offset = (DMVR_NUM_ITERATION + leftPixelExtra) * (m_cYuvRefBuffDMVRL0.bufs[COMPONENT_Y].stride + 1);
+    offset += (-(int)DMVR_NUM_ITERATION)* (int)m_cYuvRefBuffDMVRL0.bufs[COMPONENT_Y].stride;
+    offset += (-(int)DMVR_NUM_ITERATION);
+    PelBuf srcBuf = m_cYuvRefBuffDMVRL0.bufs[COMPONENT_Y];
+    PelUnitBuf yuvPredTempL0 = PelUnitBuf(pu.chromaFormat, PelBuf(m_cYuvPredTempDMVRL0,
+      (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)), pu.lwidth() + (2 * DMVR_NUM_ITERATION), pu.lheight() + (2 * DMVR_NUM_ITERATION)));
+
+    xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, refIdx0), mergeMVL0, yuvPredTempL0, true, clpRngs.comp[COMPONENT_Y],
+      false, false, pu.lwidth() + (2 * DMVR_NUM_ITERATION), pu.lheight() + (2 * DMVR_NUM_ITERATION), true, ((Pel *)srcBuf.buf) + offset, srcBuf.stride
+    );
+  }
+
+  /*L1 MC for refinement*/
+  {
+    int offset;
+    int leftPixelExtra = (NTAPS_LUMA >> 1) - 1;
+    offset = (DMVR_NUM_ITERATION + leftPixelExtra) * (m_cYuvRefBuffDMVRL1.bufs[COMPONENT_Y].stride + 1);
+    offset += (-(int)DMVR_NUM_ITERATION)* (int)m_cYuvRefBuffDMVRL1.bufs[COMPONENT_Y].stride;
+    offset += (-(int)DMVR_NUM_ITERATION);
+    PelBuf srcBuf = m_cYuvRefBuffDMVRL1.bufs[COMPONENT_Y];
+    PelUnitBuf yuvPredTempL1 = PelUnitBuf(pu.chromaFormat, PelBuf(m_cYuvPredTempDMVRL1,
+      (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)), pu.lwidth() + (2 * DMVR_NUM_ITERATION), pu.lheight() + (2 * DMVR_NUM_ITERATION)));
+
+    xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_1, refIdx1), mergeMVL1, yuvPredTempL1, true, clpRngs.comp[COMPONENT_Y],
+      false, false, pu.lwidth() + (2 * DMVR_NUM_ITERATION), pu.lheight() + (2 * DMVR_NUM_ITERATION), true, ((Pel *)srcBuf.buf) + offset, srcBuf.stride
+    );
+  }
+}
+
+void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, const ClpRngs &clpRngs, const bool bioApplied)
+{
+  int iterationCount = DMVR_NUM_ITERATION;
+  /*Always High Precision*/
+  int mvShift = MV_FRACTIONAL_BITS_INTERNAL;
+
+  /*use merge MV as starting MV*/
+  Mv mergeMv[] = { pu.mv[REF_PIC_LIST_0] , pu.mv[REF_PIC_LIST_1] };
+
+  m_biLinearBufStride = (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION));
+
+  int dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT);
+  int dx = std::min<int>(pu.lumaSize().width,  DMVR_SUBCU_WIDTH);
+  /*L0 Padding*/
+  m_cYuvRefBuffDMVRL0 = (pu.chromaFormat == CHROMA_400 ?
+    PelUnitBuf(pu.chromaFormat, PelBuf(m_cRefSamplesDMVRL0[0], pcYuvDst.Y())) :
+    PelUnitBuf(pu.chromaFormat, PelBuf(m_cRefSamplesDMVRL0[0], pcYuvDst.Y()),
+      PelBuf(m_cRefSamplesDMVRL0[1], pcYuvDst.Cb()), PelBuf(m_cRefSamplesDMVRL0[2], pcYuvDst.Cr())));
+
+  xPrefetchPad(pu, m_cYuvRefBuffDMVRL0, REF_PIC_LIST_0);
+
+  /*L1 Padding*/
+  m_cYuvRefBuffDMVRL1 = (pu.chromaFormat == CHROMA_400 ?
+    PelUnitBuf(pu.chromaFormat, PelBuf(m_cRefSamplesDMVRL1[0], pcYuvDst.Y())) :
+    PelUnitBuf(pu.chromaFormat, PelBuf(m_cRefSamplesDMVRL1[0], pcYuvDst.Y()), PelBuf(m_cRefSamplesDMVRL1[1], pcYuvDst.Cb()),
+      PelBuf(m_cRefSamplesDMVRL1[2], pcYuvDst.Cr())));
+
+  xPrefetchPad(pu, m_cYuvRefBuffDMVRL1, REF_PIC_LIST_1);
+
+  xinitMC(pu, clpRngs);
+
+  // point mc buffer to cetre point to avoid multiplication to reach each iteration to the begining
+  Pel *biLinearPredL0 = m_cYuvPredTempDMVRL0 + (iterationCount * m_biLinearBufStride) + iterationCount;
+  Pel *biLinearPredL1 = m_cYuvPredTempDMVRL1 + (iterationCount * m_biLinearBufStride) + iterationCount;
+
+  Position puPos = pu.lumaPos();
+
+  int bd = pu.cs->slice->getClpRngs().comp[COMPONENT_Y].bd;
+
+  {
+    int num = 0;
+
+    int yStart = 0;
+    for (int y = puPos.y; y < (puPos.y + pu.lumaSize().height); y = y + dy, yStart = yStart + dy)
+    {
+      for (int x = puPos.x, xStart = 0; x < (puPos.x + pu.lumaSize().width); x = x + dx, xStart = xStart + dx)
+      {
+        uint64_t minCost = MAX_UINT64;
+        bool notZeroCost = true;
+        int16_t totalDeltaMV[2] = { 0,0 };
+        int16_t deltaMV[2] = { 0, 0 };
+        uint64_t  *pSADsArray;
+        for (int i = 0; i < (((2 * DMVR_NUM_ITERATION) + 1) * ((2 * DMVR_NUM_ITERATION) + 1)); i++)
+        {
+          m_SADsArray[i] = MAX_UINT64;
+        }
+        pSADsArray = &m_SADsArray[(((2 * DMVR_NUM_ITERATION) + 1) * ((2 * DMVR_NUM_ITERATION) + 1)) >> 1];
+
+        Pel *addrL0Centre = biLinearPredL0 + yStart * m_biLinearBufStride + xStart;
+        Pel *addrL1Centre = biLinearPredL1 + yStart * m_biLinearBufStride + xStart;
+        for (int i = 0; i < iterationCount; i++)
+        {
+          deltaMV[0] = 0;
+          deltaMV[1] = 0;
+          Pel *addrL0 = addrL0Centre + totalDeltaMV[0] + (totalDeltaMV[1] * m_biLinearBufStride);
+          Pel *addrL1 = addrL1Centre - totalDeltaMV[0] - (totalDeltaMV[1] * m_biLinearBufStride);
+          if (i == 0)
+          {
+            minCost = xDMVRCost(clpRngs.comp[COMPONENT_Y].bd, addrL0, m_biLinearBufStride, addrL1, m_biLinearBufStride, dx, dy);
+            if (minCost < ((4 * dx * (dy >> 1/*for alternate line*/))))
+            {
+              notZeroCost = false;
+              break;
+            }
+            pSADsArray[0] = minCost;
+          }
+          if (!minCost)
+          {
+            notZeroCost = false;
+            break;
+          }
+
+          xBIPMVRefine(bd, addrL0, addrL1, minCost, deltaMV, pSADsArray, dx, dy);
+
+          if (deltaMV[0] == 0 && deltaMV[1] == 0)
+          {
+            break;
+          }
+          totalDeltaMV[0] += deltaMV[0];
+          totalDeltaMV[1] += deltaMV[1];
+          pSADsArray += ((deltaMV[1] * (((2 * DMVR_NUM_ITERATION) + 1))) + deltaMV[0]);
+        }
+
+        totalDeltaMV[0] = (totalDeltaMV[0] << mvShift);
+        totalDeltaMV[1] = (totalDeltaMV[1] << mvShift);
+        xDMVRSubPixelErrorSurface(notZeroCost, totalDeltaMV, deltaMV, pSADsArray);
+
+        pu.mvdL0SubPu[num] = Mv(totalDeltaMV[0], totalDeltaMV[1]);
+
+        num++;
+      }
+    }
+  }
+
+  {
+    PredictionUnit subPu = pu;
+    subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(puPos.x, puPos.y, dx, dy)));
+    PelUnitBuf           m_cYuvRefBuffSubCuDMVRL0;
+    PelUnitBuf           m_cYuvRefBuffSubCuDMVRL1;
+    PelUnitBuf srcPred0 = (pu.chromaFormat == CHROMA_400 ?
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvDst.Y())) :
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvDst.Y()), PelBuf(m_acYuvPred[0][1], pcYuvDst.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvDst.Cr())));
+    PelUnitBuf srcPred1 = (pu.chromaFormat == CHROMA_400 ?
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvDst.Y())) :
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvDst.Y()), PelBuf(m_acYuvPred[1][1], pcYuvDst.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvDst.Cr())));
+
+    srcPred0 = srcPred0.subBuf(UnitAreaRelative(pu, subPu));
+    srcPred1 = srcPred1.subBuf(UnitAreaRelative(pu, subPu));
+    PelUnitBuf subPredBuf = pcYuvDst.subBuf(UnitAreaRelative(pu, subPu));
+
+    int x = 0, y = 0;
+    int xStart = 0, yStart = 0;
+    int num = 0;
+
+    int dstStride[MAX_NUM_COMPONENT] = { pcYuvDst.bufs[COMPONENT_Y].stride, pcYuvDst.bufs[COMPONENT_Cb].stride, pcYuvDst.bufs[COMPONENT_Cr].stride };
+    for (y = puPos.y; y < (puPos.y + pu.lumaSize().height); y = y + dy, yStart = yStart + dy)
+    {
+      for (x = puPos.x, xStart = 0; x < (puPos.x + pu.lumaSize().width); x = x + dx, xStart = xStart + dx)
+      {
+        subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
+
+        subPu.mv[0] = mergeMv[REF_PIC_LIST_0] + pu.mvdL0SubPu[num];
+        subPu.mv[1] = mergeMv[REF_PIC_LIST_1] - pu.mvdL0SubPu[num];
+        m_cYuvRefBuffSubCuDMVRL0 = m_cYuvRefBuffDMVRL0.subBuf(UnitAreaRelative(pu, subPu));
+        m_cYuvRefBuffSubCuDMVRL1 = m_cYuvRefBuffDMVRL1.subBuf(UnitAreaRelative(pu, subPu));
+        xFinalPaddedMCForDMVR(subPu, srcPred0, srcPred1, m_cYuvRefBuffSubCuDMVRL0, m_cYuvRefBuffSubCuDMVRL1, bioApplied, mergeMv);
+
+        subPredBuf.bufs[COMPONENT_Y].buf  = pcYuvDst.bufs[COMPONENT_Y].buf + xStart + yStart * dstStride[COMPONENT_Y];
+        subPredBuf.bufs[COMPONENT_Cb].buf = pcYuvDst.bufs[COMPONENT_Cb].buf + (xStart >> 1) + ((yStart >> 1) * dstStride[COMPONENT_Cb]);
+        subPredBuf.bufs[COMPONENT_Cr].buf = pcYuvDst.bufs[COMPONENT_Cr].buf + (xStart >> 1) + ((yStart >> 1) * dstStride[COMPONENT_Cr]);
+        xWeightedAverage(subPu, srcPred0, srcPred1, subPredBuf, subPu.cu->slice->getSPS()->getBitDepths(), subPu.cu->slice->clpRngs(), bioApplied);
+        num++;
+      }
+    }
+  }
+}
+#endif
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
 void InterPrediction::cacheAssign( CacheModel *cache )
 {
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index 145431e2777417e854efa484d18fe1fba7418ad4..5c0b4b9ab02652d33724e9b8ecabdcaaccd28dce 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -94,7 +94,34 @@ protected:
   int                  m_iRefListIdx;
   PelStorage           m_triangleBuf;
   Mv*                  m_storedMv;
- 
+#if JVET_M0147_DMVR
+ /*buffers for bilinear Filter data for DMVR refinement*/
+  Pel*                 m_cYuvPredTempDMVRL0;
+  Pel*                 m_cYuvPredTempDMVRL1;
+  int                  m_biLinearBufStride;
+  /*buffers for padded data*/
+  PelUnitBuf           m_cYuvRefBuffDMVRL0;
+  PelUnitBuf           m_cYuvRefBuffDMVRL1;
+  Pel*                 m_cRefSamplesDMVRL0[MAX_NUM_COMPONENT];
+  Pel*                 m_cRefSamplesDMVRL1[MAX_NUM_COMPONENT];
+  enum SAD_POINT_INDEX
+  {
+    NOT_AVAILABLE = -1,
+    SAD_BOTTOM = 0,
+    SAD_TOP,
+    SAD_RIGHT,
+    SAD_LEFT,
+    SAD_TOP_LEFT,
+    SAD_TOP_RIGHT,
+    SAD_BOTTOM_LEFT,
+    SAD_BOTTOM_RIGHT,
+    SAD_CENTER,
+    SAD_COUNT
+  };
+  Mv m_pSearchOffset[5] = { Mv(0, 1), Mv(0, -1), Mv(1, 0), Mv(-1, 0), Mv(0, 0) };
+  uint64_t m_SADsArray[((2 * DMVR_NUM_ITERATION) + 1) * ((2 * DMVR_NUM_ITERATION) + 1)];
+#endif
+
   Pel*                 m_gradX0;
   Pel*                 m_gradY0;
   Pel*                 m_gradX1;
@@ -107,24 +134,45 @@ protected:
 #if !JVET_M0487_INT_EXTEND
   void            bioSampleExtendBilinearFilter(Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int dim, int fracX, int fracY, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng);
 #endif
-  void xPredInterUni            ( const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi 
-                                  , const bool& bioApplied 
+  void xPredInterUni            ( const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi
+                                  , const bool& bioApplied
                                   , const bool luma, const bool chroma
   );
   void xPredInterBi             ( PredictionUnit& pu, PelUnitBuf &pcYuvPred );
+#if JVET_M0147_DMVR
+  void xPredInterBlk            ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
+                                 , const bool& bioApplied
+                                 , bool isIBC
+                                 , SizeType dmvrWidth = 0
+                                 , SizeType dmvrHeight = 0
+                                 , bool bilinearMC = false
+                                 , Pel *srcPadBuf = NULL
+                                 , int32_t srcPadStride = 0
+                                 );
+#else
   void xPredInterBlk            ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
                                  , const bool& bioApplied
                                  , bool isIBC
                                  );
+#endif
 
   void xAddBIOAvg4              (const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel*gradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng);
+#if JVET_M0063_BDOF_FIX
+  void xBioGradFilter           (Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, int bitDepth);
+  void xCalcBIOPar              (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, int bitDepth);
+#else
   void xBioGradFilter           (Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY);
   void xCalcBIOPar              (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG);
+#endif
   void xCalcBlkGradient         (int sx, int sy, int    *arraysGx2, int     *arraysGxGy, int     *arraysGxdI, int     *arraysGy2, int     *arraysGydI, int     &sGx2, int     &sGy2, int     &sGxGy, int     &sGxdI, int     &sGydI, int width, int height, int unitSize);
   void xWeightedAverage         ( const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs, const bool& bioApplied );
   void xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng );
 
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+  void xWeightedTriangleBlk     ( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 );
+#else
   void xWeightedTriangleBlk     ( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, const bool weights, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 );
+#endif
 
   static bool xCheckIdenticalMotion( const PredictionUnit& pu );
 
@@ -155,7 +203,21 @@ public:
   );
 
   void    motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 );
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+  void    weightedTriangleBlk        ( PredictionUnit &pu, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 );
+#else
   void    weightedTriangleBlk        ( PredictionUnit &pu, bool weights, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 );
+#endif
+#if JVET_M0147_DMVR
+  void xPrefetchPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId);
+  void xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvSrc0, PelUnitBuf &pcYuvSrc1, PelUnitBuf &pcPad0, PelUnitBuf &pcPad1, const bool bioApplied
+    , const Mv startMV[NUM_REF_PIC_LIST_01]
+  );
+  void xBIPMVRefine(int bd, Pel *pRefL0, Pel *pRefL1, uint64_t& minCost, int16_t *deltaMV, uint64_t *pSADsArray, int width, int height);
+  uint64_t xDMVRCost(int bitDepth, Pel* pRef, uint32_t refStride, const Pel* pOrg, uint32_t orgStride, int width, int height);
+  void xinitMC(PredictionUnit& pu, const ClpRngs &clpRngs);
+  void xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, const ClpRngs &clpRngs, const bool bioApplied );
+#endif
 
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
   void    cacheAssign( CacheModel *cache );
diff --git a/source/Lib/CommonLib/InterpolationFilter.cpp b/source/Lib/CommonLib/InterpolationFilter.cpp
index 4daa5056e7e2a603f5773e009e481101d6bde309..845cb3dcee14f227fa9e5b0b751c675ebe011547 100644
--- a/source/Lib/CommonLib/InterpolationFilter.cpp
+++ b/source/Lib/CommonLib/InterpolationFilter.cpp
@@ -131,6 +131,27 @@ const TFilterCoeff InterpolationFilter::m_bilinearFilter[LUMA_INTERPOLATION_FILT
   { 4, 60, },
 };
 
+#if JVET_M0147_DMVR
+const TFilterCoeff InterpolationFilter::m_bilinearFilterPrec4[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_BILINEAR] =
+{
+  { 16,  0, },
+  { 15,  1, },
+  { 14,  2, },
+  { 13, 3, },
+  { 12, 4, },
+  { 11, 5, },
+  { 10, 6, },
+  { 9, 7, },
+  { 8, 8, },
+  { 7, 9, },
+  { 6, 10, },
+  { 5, 11, },
+  { 4, 12, },
+  { 3, 13, },
+  { 2, 14, },
+  { 1, 15, }
+};
+#endif
 // ====================================================================================================================
 // Private member functions
 // ====================================================================================================================
@@ -197,7 +218,11 @@ InterpolationFilter::InterpolationFilter()
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 template<bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+void InterpolationFilter::filterCopy( const ClpRng& clpRng, const Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool biMCForDMVR)
+#else
 void InterpolationFilter::filterCopy( const ClpRng& clpRng, const Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height )
+#endif
 {
   int row, col;
 
@@ -223,6 +248,40 @@ void InterpolationFilter::filterCopy( const ClpRng& clpRng, const Pel *src, int
   {
     const int shift = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd));
 
+#if JVET_M0147_DMVR
+    if (biMCForDMVR)
+    {
+      int shift10BitOut, offset;
+      if ((clpRng.bd - IF_INTERNAL_PREC_BILINEAR) > 0)
+      {
+        shift10BitOut = (clpRng.bd - IF_INTERNAL_PREC_BILINEAR);
+        offset = (1 << (shift10BitOut - 1));
+        for (row = 0; row < height; row++)
+        {
+          for (col = 0; col < width; col++)
+          {
+            dst[col] = (src[col] + offset) >> shift10BitOut;
+          }
+          src += srcStride;
+          dst += dstStride;
+        }
+      }
+      else
+      {
+        shift10BitOut = (IF_INTERNAL_PREC_BILINEAR - clpRng.bd);
+        for (row = 0; row < height; row++)
+        {
+          for (col = 0; col < width; col++)
+          {
+            dst[col] = src[col] << shift10BitOut;
+          }
+          src += srcStride;
+          dst += dstStride;
+        }
+      }
+    }
+    else
+#endif
     for (row = 0; row < height; row++)
     {
       for (col = 0; col < width; col++)
@@ -240,6 +299,40 @@ void InterpolationFilter::filterCopy( const ClpRng& clpRng, const Pel *src, int
   {
     const int shift = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd));
 
+#if JVET_M0147_DMVR
+    if (biMCForDMVR)
+    {
+      int shift10BitOut, offset;
+      if ((clpRng.bd - IF_INTERNAL_PREC_BILINEAR) > 0)
+      {
+        shift10BitOut = (clpRng.bd - IF_INTERNAL_PREC_BILINEAR);
+        offset = (1 << (shift10BitOut - 1));
+        for (row = 0; row < height; row++)
+        {
+          for (col = 0; col < width; col++)
+          {
+            dst[col] = (src[col] + offset) >> shift10BitOut;
+          }
+          src += srcStride;
+          dst += dstStride;
+        }
+      }
+      else
+      {
+        shift10BitOut = (IF_INTERNAL_PREC_BILINEAR - clpRng.bd);
+        for (row = 0; row < height; row++)
+        {
+          for (col = 0; col < width; col++)
+          {
+            dst[col] = src[col] << shift10BitOut;
+          }
+          src += srcStride;
+          dst += dstStride;
+        }
+      }
+    }
+    else
+#endif
     for (row = 0; row < height; row++)
     {
       for (col = 0; col < width; col++)
@@ -282,7 +375,11 @@ void InterpolationFilter::filterCopy( const ClpRng& clpRng, const Pel *src, int
 //
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 template<int N, bool isVertical, bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+void InterpolationFilter::filter(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR)
+#else
 void InterpolationFilter::filter(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff)
+#endif
 {
   int row, col;
 
@@ -327,6 +424,13 @@ void InterpolationFilter::filter(const ClpRng& clpRng, Pel const *src, int srcSt
     offset = (isFirst) ? -IF_INTERNAL_OFFS << shift : 0;
   }
 
+#if JVET_M0147_DMVR
+  if (biMCForDMVR)
+  {
+    shift = IF_FILTER_PREC_BILINEAR - (IF_INTERNAL_PREC_BILINEAR - clpRng.bd);
+    offset = 1 << (shift - 1);
+  }
+#endif
   for (row = 0; row < height; row++)
   {
     for (col = 0; col < width; col++)
@@ -387,20 +491,36 @@ void InterpolationFilter::filter(const ClpRng& clpRng, Pel const *src, int srcSt
  * \param  coeff      Pointer to filter taps
  */
 template<int N>
+#if JVET_M0147_DMVR
+void InterpolationFilter::filterHor(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR)
+#else
 void InterpolationFilter::filterHor(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isLast, TFilterCoeff const *coeff)
+#endif
 {
 //#if ENABLE_SIMD_OPT_MCIF
   if( N == 8 )
   {
+#if JVET_M0147_DMVR
+    m_filterHor[0][1][isLast](clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterHor[0][1][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else if( N == 4 )
   {
+#if JVET_M0147_DMVR
+    m_filterHor[1][1][isLast](clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterHor[1][1][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else if( N == 2 )
   {
+#if JVET_M0147_DMVR
+    m_filterHor[2][1][isLast](clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterHor[2][1][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else
   {
@@ -424,20 +544,36 @@ void InterpolationFilter::filterHor(const ClpRng& clpRng, Pel const *src, int sr
  * \param  coeff      Pointer to filter taps
  */
 template<int N>
+#if JVET_M0147_DMVR
+void InterpolationFilter::filterVer(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR)
+#else
 void InterpolationFilter::filterVer(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff)
+#endif
 {
 //#if ENABLE_SIMD_OPT_MCIF
   if( N == 8 )
   {
+#if JVET_M0147_DMVR
+    m_filterVer[0][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterVer[0][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else if( N == 4 )
   {
+#if JVET_M0147_DMVR
+    m_filterVer[1][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterVer[1][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else if( N == 2 )
   {
+#if JVET_M0147_DMVR
+    m_filterVer[2][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff, biMCForDMVR);
+#else
     m_filterVer[2][isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height, coeff );
+#endif
   }
   else{
     THROW( "Invalid tap number" );
@@ -463,29 +599,49 @@ void InterpolationFilter::filterVer(const ClpRng& clpRng, Pel const *src, int sr
  * \param  fmt        Chroma format
  * \param  bitDepth   Bit depth
  */
+#if JVET_M0147_DMVR
+void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR)
+#else
 void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx )
+#endif
 {
   if( frac == 0 )
   {
+#if JVET_M0147_DMVR
+    m_filterCopy[true][isLast](clpRng, src, srcStride, dst, dstStride, width, height, biMCForDMVR);
+#else
     m_filterCopy[true][isLast]( clpRng, src, srcStride, dst, dstStride, width, height );
+#endif
   }
   else if( isLuma( compID ) )
   {
     CHECK( frac < 0 || frac >= LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS, "Invalid fraction" );
     if( nFilterIdx == 1 )
     {
+#if JVET_M0147_DMVR
+      filterHor<NTAPS_BILINEAR>(clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_bilinearFilterPrec4[frac], biMCForDMVR);
+#else
       filterHor<NTAPS_BILINEAR>(clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_bilinearFilter[frac]);
+#endif
     }
     else
     {
+#if JVET_M0147_DMVR
+      filterHor<NTAPS_LUMA>( clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_lumaFilter[frac], biMCForDMVR);
+#else
       filterHor<NTAPS_LUMA>( clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_lumaFilter[frac] );
+#endif
     }
   }
   else
   {
     const uint32_t csx = getComponentScaleX( compID, fmt );
     CHECK( frac < 0 || csx >= 2 || ( frac << ( 1 - csx ) ) >= CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS, "Invalid fraction" );
+#if JVET_M0147_DMVR
+    filterHor<NTAPS_CHROMA>( clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_chromaFilter[frac << ( 1 - csx )], biMCForDMVR);
+#else
     filterHor<NTAPS_CHROMA>( clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_chromaFilter[frac << ( 1 - csx )] );
+#endif
   }
 }
 
@@ -506,29 +662,49 @@ void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, i
  * \param  fmt        Chroma format
  * \param  bitDepth   Bit depth
  */
+#if JVET_M0147_DMVR
+void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR)
+#else
 void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx)
+#endif
 {
   if( frac == 0 )
   {
+#if JVET_M0147_DMVR
+    m_filterCopy[isFirst][isLast](clpRng, src, srcStride, dst, dstStride, width, height, biMCForDMVR);
+#else
     m_filterCopy[isFirst][isLast]( clpRng, src, srcStride, dst, dstStride, width, height );
+#endif
   }
   else if( isLuma( compID ) )
   {
     CHECK( frac < 0 || frac >= LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS, "Invalid fraction" );
     if (nFilterIdx == 1)
     {
+#if JVET_M0147_DMVR
+      filterVer<NTAPS_BILINEAR>(clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_bilinearFilterPrec4[frac], biMCForDMVR);
+#else
       filterVer<NTAPS_BILINEAR>(clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_bilinearFilter[frac]);
+#endif
     }
     else
     {
+#if JVET_M0147_DMVR
+      filterVer<NTAPS_LUMA>( clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter[frac], biMCForDMVR);
+#else
       filterVer<NTAPS_LUMA>( clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter[frac] );
+#endif
     }
   }
   else
   {
     const uint32_t csy = getComponentScaleY( compID, fmt );
     CHECK( frac < 0 || csy >= 2 || ( frac << ( 1 - csy ) ) >= CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS, "Invalid fraction" );
+#if JVET_M0147_DMVR
+    filterVer<NTAPS_CHROMA>(clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_chromaFilter[frac << (1 - csy)], biMCForDMVR);
+#else
     filterVer<NTAPS_CHROMA>( clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_chromaFilter[frac << ( 1 - csy )] );
+#endif
   }
 }
 
diff --git a/source/Lib/CommonLib/InterpolationFilter.h b/source/Lib/CommonLib/InterpolationFilter.h
index e4ca95491de7a1f841fb35aed7a2ebf7b2053036..be366a5477bc1ad7a38ee3bcf092684a93f93407 100644
--- a/source/Lib/CommonLib/InterpolationFilter.h
+++ b/source/Lib/CommonLib/InterpolationFilter.h
@@ -48,7 +48,10 @@
 #define IF_INTERNAL_PREC 14 ///< Number of bits for internal precision
 #define IF_FILTER_PREC    6 ///< Log2 of sum of filter taps
 #define IF_INTERNAL_OFFS (1<<(IF_INTERNAL_PREC-1)) ///< Offset used internally
-
+#if JVET_M0147_DMVR
+#define IF_INTERNAL_PREC_BILINEAR 10 ///< Number of bits for internal precision
+#define IF_FILTER_PREC_BILINEAR   4  ///< Bilinear filter coeff precision so that intermediate value will not exceed 16 bit for SIMD - bit exact
+#endif
 /**
  * \brief Interpolation filter class
  */
@@ -57,17 +60,36 @@ class InterpolationFilter
   static const TFilterCoeff m_lumaFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_LUMA]; ///< Luma filter taps
   static const TFilterCoeff m_chromaFilter[CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_CHROMA]; ///< Chroma filter taps
   static const TFilterCoeff m_bilinearFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_BILINEAR]; ///< bilinear filter taps
+#if JVET_M0147_DMVR
+  static const TFilterCoeff m_bilinearFilterPrec4[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_BILINEAR]; ///< bilinear filter taps
+#endif
 public:
   template<bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+  static void filterCopy( const ClpRng& clpRng, const Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool biMCForDMVR);
+#else
   static void filterCopy( const ClpRng& clpRng, const Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height );
+#endif
 
   template<int N, bool isVertical, bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+  static void filter(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR);
+#else
   static void filter(const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff);
-
+#endif
   template<int N>
+#if JVET_M0147_DMVR
+  void filterHor(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR);
+#else
   void filterHor(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height,               bool isLast, TFilterCoeff const *coeff);
+#endif
+
   template<int N>
+#if JVET_M0147_DMVR
+  void filterVer(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR);
+#else
   void filterVer(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff);
+#endif
 
 protected:
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
@@ -76,10 +98,21 @@ protected:
 public:
   InterpolationFilter();
   ~InterpolationFilter() {}
-
+#if JVET_M0147_DMVR
+  void( *m_filterHor[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR);
+#else
   void( *m_filterHor[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff );
+#endif
+#if JVET_M0147_DMVR
+  void( *m_filterVer[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR);
+#else
   void( *m_filterVer[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff );
+#endif
+#if JVET_M0147_DMVR
+  void( *m_filterCopy[2][2] )  ( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool biMCForDMVR);
+#else
   void( *m_filterCopy[2][2] )  ( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height );
+#endif
 
   void initInterpolationFilter( bool enable );
 #ifdef TARGET_SIMD_X86
@@ -87,9 +120,16 @@ public:
   template <X86_VEXT vext>
   void _initInterpolationFilterX86();
 #endif
-
+#if JVET_M0147_DMVR
+  void filterHor(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac,               bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false);
+#else
   void filterHor(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac,               bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0);
+#endif
+#if JVET_M0147_DMVR
+  void filterVer(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false);
+#else
   void filterVer(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0);
+#endif
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
   void cacheAssign( CacheModel *cache ) { m_cacheModel = cache; }
 #endif
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index e49e92eceee0a95924f7d469f72ff4934e80877e..da5a61234c02c36857d8b889deff44a74c0ed80d 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -212,11 +212,6 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth
     }
   }
 
-  int shift = bitDepthY + 4;
-  for (int i = 32; i < 64; i++)
-  {
-    m_auShiftLM[i - 32] = ((1 << shift) + i / 2) / i;
-  }
   if (m_piTemp == nullptr)
   {
     m_piTemp = new Pel[(MAX_CU_SIZE + 1) * (MAX_CU_SIZE + 1)];
@@ -299,6 +294,9 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
   const ChannelType    channelType  = toChannelType( compID );
   const int            iWidth       = piPred.width;
   const int            iHeight      = piPred.height;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const Size           cuSize       = Size( pu.cu->blocks[compId].width, pu.cu->blocks[compId].height );
+#endif
   const uint32_t           uiDirMode    = PU::getFinalIntraMode( pu, channelType );
 
 
@@ -306,8 +304,14 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
   CHECK( g_aucLog2[iWidth] > 7, "Size not allowed" );
 
   const int  multiRefIdx = (compID == COMPONENT_Y) ? pu.multiRefIdx : 0;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const bool useISP = pu.cu->ispMode && isLuma( compID );
+  const int whRatio = useISP ? std::max( unsigned( 1 ), cuSize.width / cuSize.height ) : std::max( 1, iWidth / iHeight );
+  const int hwRatio = useISP ? std::max( unsigned( 1 ), cuSize.height / cuSize.width ) : std::max( 1, iHeight / iWidth );
+#else
   int whRatio           = std::max(1, iWidth / iHeight);
   int hwRatio           = std::max(1, iHeight / iWidth);
+#endif
   const int  srcStride  = m_topRefLength  + 1 + (whRatio + 1) * multiRefIdx;
   const int  srcHStride = m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx;
 
@@ -321,20 +325,34 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
     case(2):
     case(DIA_IDX):
     case(VDIA_IDX):
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if (getWideAngle(useISP ? cuSize.width : iWidth, useISP ? cuSize.height : iHeight, uiDirMode) == static_cast<int>(uiDirMode)) // check if uiDirMode is not wide-angle
+      {
+        xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps, multiRefIdx, useFilteredPredSamples, useISP, cuSize );
+#else
       if (getWideAngle(iWidth, iHeight, uiDirMode) == static_cast<int>(uiDirMode)) // check if uiDirMode is not wide-angle
       {
         xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps
           , multiRefIdx
           , useFilteredPredSamples);
+#endif
         break;
       }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    default:          xPredIntraAng(CPelBuf(getPredictorPtr(compID, false), srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps, multiRefIdx, useFilteredPredSamples, useISP, cuSize); break;
+#else
     default:          xPredIntraAng(CPelBuf(getPredictorPtr(compID, false), srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps
       , multiRefIdx
       , useFilteredPredSamples); break;
+#endif
   }
 
   bool pdpcCondition = (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX || uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( pdpcCondition && multiRefIdx == 0 && !useISP )
+#else
   if (pdpcCondition && multiRefIdx == 0)
+#endif
   {
     const CPelBuf srcBuf = CPelBuf(ptrSrc, srcStride, srcStride);
     PelBuf dstBuf = piPred;
@@ -445,11 +463,20 @@ void IntraPrediction::xPredIntraPlanar( const CPelBuf &pSrc, PelBuf &pDst, const
 {
   const uint32_t width  = pDst.width;
   const uint32_t height = pDst.height;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const uint32_t log2W  = g_aucLog2[width  < 2 ? 2 : width];
+  const uint32_t log2H  = g_aucLog2[height < 2 ? 2 : height];
+#else
   const uint32_t log2W  = g_aucLog2[ width ];
   const uint32_t log2H  = g_aucLog2[ height ];
+#endif
 
   int leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const uint32_t offset = 1 << (log2W + log2H);
+#else
   const uint32_t offset = width * height;
+#endif
 
   // Get left and above reference column and row
   for( int k = 0; k < width + 1; k++ )
@@ -561,17 +588,28 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
   , int multiRefIdx
   , const bool enableBoundaryFilter )
 #else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps,
+                                           int      multiRefIdx,
+                                     const bool     useFilteredPredSamples ,
+                                     const bool     useISP,
+                                     const Size     cuSize )
+#else
 void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps
   , int multiRefIdx
   , const bool useFilteredPredSamples )
 #endif
+#endif
 {
   int width =int(pDst.width);
   int height=int(pDst.height);
 
   CHECK( !( dirMode > DC_IDX && dirMode < NUM_LUMA_MODE ), "Invalid intra dir" );
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  int              predMode           = useISP ? getWideAngle( cuSize.width, cuSize.height, dirMode ) : getWideAngle( width, height, dirMode );
+#else
   int              predMode           = getWideAngle(width, height, dirMode);
+#endif
   const bool       bIsModeVer         = predMode >= DIA_IDX;
   const int        intraPredAngleMode = (bIsModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);
   const int        absAngMode         = abs(intraPredAngleMode);
@@ -582,8 +620,8 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
 
   // Set bitshifts and scale the angle parameter to block size
 
-  static const int angTable[32]    = { 0,    1,    2,    3,    4,    6,     8,   10,   12,   14,   16,   18,   20,   23,   26,   29,   32,   35,   39,  45,  51,  57,  64,  73,  85, 102, 128, 171, 256, 341, 512, 1024 };
-  static const int invAngTable[32] = { 0, 8192, 4096, 2731, 2048, 1365,  1024,  819,  683,  585,  512,  455,  410,  356,  315,  282,  256,  234,  210, 182, 160, 144, 128, 112,  96,  80,  64,  48,  32,  24,  16,    8 }; // (256 * 32) / Angle
+  static const int angTable[32]    = { 0,    1,    2,    3,    4,    6,     8,   10,   12,   14,   16,   18,   20,   23,   26,   29,   32,   35,   39,  45,  51,  57,  64,  73,  86, 102, 128, 171, 256, 341, 512, 1024 };
+  static const int invAngTable[32] = { 0, 8192, 4096, 2731, 2048, 1365,  1024,  819,  683,  585,  512,  455,  410,  356,  315,  282,  256,  234,  210, 182, 160, 144, 128, 112,  95,  80,  64,  48,  32,  24,  16,    8 }; // (256 * 32) / Angle
 
   int invAngle                    = invAngTable[absAngMode];
   int absAng                      = angTable   [absAngMode];
@@ -595,8 +633,13 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
   Pel  refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
   Pel  refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const int whRatio = useISP ? std::max( unsigned( 1 ), cuSize.width / cuSize.height ) : std::max( 1, width / height );
+  const int hwRatio = useISP ? std::max( unsigned( 1 ), cuSize.height / cuSize.width ) : std::max( 1, height / width );
+#else
   int whRatio = std::max(1, width / height);
   int hwRatio = std::max(1, height / width);
+#endif
 
   // Initialize the Main and Left reference array.
   if (intraPredAngle < 0)
@@ -691,7 +734,11 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
         if( isLuma(channelType) )
         {
           Pel                        p[4];
+#if JVET_M0102_INTRA_SUBPARTITIONS
+          const bool                 useCubicFilter = useISP ? ( width <= 8 ) : ( !useFilteredPredSamples || multiRefIdx > 0 );
+#else
           const bool                 useCubicFilter = !useFilteredPredSamples || multiRefIdx > 0;
+#endif
           TFilterCoeff const * const f              = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract];
 
           int         refMainIndex   = deltaInt + 1;
@@ -735,6 +782,10 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
       const int numModes = 8;
       const int scale = ((g_aucLog2[width] - 2 + g_aucLog2[height] - 2 + 2) >> 2);
       CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( !useISP )
+      {
+#endif
       if ((predMode == 2 || predMode == VDIA_IDX) && multiRefIdx == 0)
       {
         int wT = 16 >> std::min(31, ((y << 1) >> scale));
@@ -770,10 +821,17 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
           if (wL == 0) break;
           Pel *p = refSide + deltay;
 
+#if JVET_M0238_PDPC_NO_INTERPOLATION
+          Pel left = p[deltaFrac0 >> 5];
+#else
           Pel left = (((64 - deltaFrac0) * p[0] + deltaFrac0 * p[1] + 32) >> 6);
+#endif
           pDsty[x] = ClipPel((wL * left + (64 - wL) * pDsty[x] + 32) >> 6, clpRng);
         }
       }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      }
+#endif
     }
 #if HEVC_USE_HOR_VER_PREDFILTERING
     if( edgeFilter && absAng <= 1 )
@@ -941,7 +999,11 @@ void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompAre
   Pel *refBufUnfiltered   = m_piYuvExt[area.compID][PRED_BUF_UNFILTERED];
   Pel *refBufFiltered     = m_piYuvExt[area.compID][PRED_BUF_FILTERED];
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  setReferenceArrayLengths( cu.ispMode && isLuma( area.compID ) ? cu.blocks[area.compID] : area );
+#else
   setReferenceArrayLengths(area);
+#endif
 
   // ----- Step 1: unfiltered reference samples -----
   xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, cu );
@@ -967,13 +1029,25 @@ void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBuf
   const int  tuHeight           = area.height;
   const int  predSize           = m_topRefLength;
   const int  predHSize          = m_leftRefLength;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const int  cuWidth            = cu.blocks[area.compID].width;
+  const int  cuHeight           = cu.blocks[area.compID].height;
+  const int  whRatio            = cu.ispMode && isLuma(area.compID) ? std::max(1, cuWidth / cuHeight) : std::max(1, tuWidth / tuHeight);
+  const int  hwRatio            = cu.ispMode && isLuma(area.compID) ? std::max(1, cuHeight / cuWidth) : std::max(1, tuHeight / tuWidth);
+#else
   int whRatio                   = std::max(1, tuWidth / tuHeight);
   int hwRatio                   = std::max(1, tuHeight / tuWidth);
+#endif
   const int  predStride         = predSize + 1 + (whRatio + 1) * multiRefIdx;
 
   const bool noShift            = pcv.noChroma2x2 && area.width == 4; // don't shift on the lowest level (chroma not-split)
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const int  unitWidth          = tuWidth  <= 2 && cu.ispMode && isLuma(area.compID) ? tuWidth  : pcv.minCUWidth  >> (noShift ? 0 : getComponentScaleX(area.compID, sps.getChromaFormatIdc()));
+  const int  unitHeight         = tuHeight <= 2 && cu.ispMode && isLuma(area.compID) ? tuHeight : pcv.minCUHeight >> (noShift ? 0 : getComponentScaleY(area.compID, sps.getChromaFormatIdc()));
+#else
   const int  unitWidth          = pcv.minCUWidth  >> (noShift ? 0 : getComponentScaleX( area.compID, sps.getChromaFormatIdc() ));
   const int  unitHeight         = pcv.minCUHeight >> (noShift ? 0 : getComponentScaleY( area.compID, sps.getChromaFormatIdc() ));
+#endif
 
   const int  totalAboveUnits    = (predSize + (unitWidth - 1)) / unitWidth;
   const int  totalLeftUnits     = (predHSize + (unitHeight - 1)) / unitHeight;
@@ -1289,6 +1363,9 @@ bool IntraPrediction::useFilteredIntraRefSamples( const ComponentID &compID, con
   if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag() )                                       { return false; }
   if( !isLuma( chType ) && pu.chromaFormat != CHROMA_444 )                                               { return false; }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( pu.cu->ispMode && isLuma(compID) )                                                                 { return false; }
+#endif
 
   if( !modeSpecific )                                                                                    { return true; }
 
@@ -1564,7 +1641,7 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom
         }
       }
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
-      else if( pu.cs->sps->getSpsNext().getCclmCollocatedChromaFlag() )
+      else if( pu.cs->sps->getCclmCollocatedChromaFlag() )
       {
         piSrc = pRecSrc0 - iRecStride2;
 
@@ -1611,7 +1688,7 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom
     for (int j = 0; j < uiCHeight + addedLeftBelow; j++)
     {
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
-      if( pu.cs->sps->getSpsNext().getCclmCollocatedChromaFlag() )
+      if( pu.cs->sps->getCclmCollocatedChromaFlag() )
       {
         if( j == 0 && !bAboveAvaillable )
         {
@@ -1647,7 +1724,7 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom
     for( int i = 0; i < uiCWidth; i++ )
     {
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
-      if( pu.cs->sps->getSpsNext().getCclmCollocatedChromaFlag() )
+      if( pu.cs->sps->getCclmCollocatedChromaFlag() )
       {
         if( i == 0 && !bLeftAvaillable )
         {
diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h
index 7a1995ed2e030f4570228fd40b8aa77c483134b9..63c36a9a91fd63fbc74ad81104eaa133ceaba08e 100644
--- a/source/Lib/CommonLib/IntraPrediction.h
+++ b/source/Lib/CommonLib/IntraPrediction.h
@@ -74,8 +74,6 @@ private:
 
   static const uint8_t m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS];
 
-  unsigned m_auShiftLM[32]; // Table for substituting division operation by multiplication
-
   Pel* m_piTemp;
   Pel* m_pMdlmTemp; // for MDLM mode
 protected:
@@ -91,15 +89,23 @@ protected:
   void xPredIntraAng              ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const bool bEnableEdgeFilters, const SPS& sps
     , int multiRefIdx
     , const bool enableBoundaryFilter = true );
+#else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void xPredIntraAng              ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps,
+                                          int  multiRefIdx,
+                                    const bool useFilteredPredSamples,
+                                    const bool useISP = false,
+                                    const Size cuSize = Size( 0, 0 ) );
 #else
   void xPredIntraAng              ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps
     , int multiRefIdx
     , const bool useFilteredPredSamples );
+#endif
 #endif
   Pel  xGetPredValDc              ( const CPelBuf &pSrc, const Size &dstSize );
 
   void xFillReferenceSamples      ( const CPelBuf &recoBuf,      Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu );
-  void xFilterReferenceSamples    ( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps 
+  void xFilterReferenceSamples    ( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps
     , int multiRefIdx
   );
 
diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp
index f8543f5bc8a63203456999609cfe618e55c3a381..b3362a350a49a9171e438ec58b791a79356ab8a6 100644
--- a/source/Lib/CommonLib/LoopFilter.cpp
+++ b/source/Lib/CommonLib/LoopFilter.cpp
@@ -242,10 +242,24 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir )
   const Area area          = cu.Y().valid() ? cu.Y() : Area( recalcPosition( cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].pos() ), recalcSize( cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].size() ) );
 
   xSetLoopfilterParam( cu );
-
+#if  JVET_M0471_LONG_DEBLOCKING_FILTERS
+  bool implicitTU = false;
+#endif
   for( auto &currTU : CU::traverseTUs( cu ) )
   {
     const Area& areaTu    = cu.Y().valid() ? currTU.block( COMPONENT_Y ) : area;
+#if  JVET_M0471_LONG_DEBLOCKING_FILTERS
+    const bool xOff = currTU.blocks[cu.chType].x != cu.blocks[cu.chType].x;
+    const bool yOff = currTU.blocks[cu.chType].y != cu.blocks[cu.chType].y;
+    if ((yOff != 0) && (edgeDir == EDGE_HOR))
+    {
+      implicitTU = true;
+    }
+    if ((xOff != 0) && (edgeDir == EDGE_VER))
+    {
+      implicitTU = true;
+    }
+#endif
     xSetEdgefilterMultiple( cu, EDGE_VER, areaTu, m_stLFCUParam.internalEdge );
     xSetEdgefilterMultiple( cu, EDGE_HOR, areaTu, m_stLFCUParam.internalEdge );
   }
@@ -282,6 +296,32 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir )
       }
     }
   }
+#if JVET_M0908_CIIP_DB
+  if (cu.firstPU->mhIntraFlag)
+  {
+    const uint32_t dirMode = PU::getFinalIntraMode(*(cu.firstPU), cu.chType);
+    if (edgeDir == EDGE_VER && dirMode == HOR_IDX)
+    {
+      mvSubBlocks = true;
+      subBlockSize = std::max(8u, (area.width >> 2));
+      for (uint32_t off = subBlockSize; off < area.width; off += subBlockSize)
+      {
+        const Area mvBlockV(cu.Y().x + off, cu.Y().y, pcv.minCUWidth, cu.Y().height);
+        xSetEdgefilterMultiple(cu, EDGE_VER, mvBlockV, m_stLFCUParam.internalEdge, 1);
+      }
+    }
+    else if (edgeDir == EDGE_HOR && dirMode == VER_IDX)
+    {
+      mvSubBlocks = true;
+      subBlockSize = std::max(8u, (area.height >> 2));
+      for (uint32_t off = subBlockSize; off < area.height; off += subBlockSize)
+      {
+        const Area mvBlockH(cu.Y().x, cu.Y().y + off, cu.Y().width, pcv.minCUHeight);
+        xSetEdgefilterMultiple(cu, EDGE_HOR, mvBlockH, m_stLFCUParam.internalEdge, 1);
+      }
+    }
+  }
+#endif
 
   const unsigned uiPelsInPart = pcv.minCUWidth;
 
@@ -313,14 +353,50 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir )
 
   unsigned int orthogonalLength = 1;
   unsigned int orthogonalIncrement = 1;
-
+#if FIX_DB_MAX_TRANSFORM_SIZE
+  int maxTsize = 64;
+  maxTsize = 1 << cu.slice->getSPS()->getQuadtreeTULog2MaxSize();
+#endif
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+#if FIX_DB_MAX_TRANSFORM_SIZE
+  int maxFilterLengthQ = 7;
+  int maxFilterLengthP = 7;
+  if (implicitTU && maxTsize < 32)
+  {
+    maxFilterLengthQ = 3;
+    maxFilterLengthP = 3;
+  }
+#else
+  int maxFilterLength = 7;
+#endif
+#endif
   if (cu.blocks[COMPONENT_Y].valid())
   {
     if (mvSubBlocks)
     {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+#if FIX_DB_MAX_TRANSFORM_SIZE
+      maxFilterLengthQ = std::min(maxFilterLengthQ, 5);
+#else
+      maxFilterLength = 5;
+#endif
+#endif
       orthogonalIncrement = subBlockSize / 4;
       orthogonalLength = (edgeDir == EDGE_HOR) ? cu.blocks[COMPONENT_Y].height / 4 : cu.blocks[COMPONENT_Y].width / 4;
     }
+#if FIX_DB_MAX_TRANSFORM_SIZE
+    if ((cu.blocks[COMPONENT_Y].height > maxTsize) && (edgeDir == EDGE_HOR) && !mvSubBlocks)
+    {
+      orthogonalIncrement = maxTsize / 4;
+      orthogonalLength = cu.blocks[COMPONENT_Y].height / 4;
+    }
+    if ((cu.blocks[COMPONENT_Y].width > maxTsize) && (edgeDir == EDGE_VER) && !mvSubBlocks)
+    {
+      orthogonalIncrement = maxTsize / 4;
+      orthogonalLength = cu.blocks[COMPONENT_Y].width / 4;
+
+    }
+#else
     if ((cu.blocks[COMPONENT_Y].height > 64) && (edgeDir == EDGE_HOR) && !mvSubBlocks)
     {
       orthogonalIncrement = 64 / 4;
@@ -332,12 +408,52 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir )
       orthogonalLength = cu.blocks[COMPONENT_Y].width / 4;
 
     }
+#endif
   }
+
   for (int edge = 0; edge < orthogonalLength; edge += orthogonalIncrement)
   {
     if (cu.blocks[COMPONENT_Y].valid())
     {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+      if (edge == 0)
+      {
+#if FIX_DB_MAX_TRANSFORM_SIZE
+        xEdgeFilterLuma(cu, edgeDir, edge, maxFilterLengthP, maxFilterLengthQ);
+#else
+        xEdgeFilterLuma(cu, edgeDir, edge, 7, maxFilterLength);
+#endif
+      }
+      else
+      {
+#if FIX_DB_MAX_TRANSFORM_SIZE
+        if (implicitTU && ((edge % (maxTsize / 4)) == 0))
+#else
+        if ( implicitTU && (edge == (64 / 4)) )
+#endif
+        {
+#if FIX_DB_MAX_TRANSFORM_SIZE
+          xEdgeFilterLuma(cu, edgeDir, edge, maxFilterLengthQ, maxFilterLengthQ);
+#else
+          xEdgeFilterLuma(cu, edgeDir, edge, maxFilterLength, maxFilterLength);
+#endif
+        }
+#if FIX_DB_MAX_TRANSFORM_SIZE
+        else if ((edge == 2 || edge == (orthogonalLength - 2)) || (implicitTU && (((edge - 2) % ((maxTsize) / 4) == 0) || ((edge + 2) % ((maxTsize) / 4) == 0))))
+#else
+        else if ( (edge == 2 || edge == (orthogonalLength - 2)) || (implicitTU && (edge == (56 / 4) || edge == (72 / 4))) )
+#endif
+        {
+          xEdgeFilterLuma(cu, edgeDir, edge, 2, 2);
+        }
+        else
+        {
+          xEdgeFilterLuma(cu, edgeDir, edge, 3, 3);
+        }
+      }
+#else
       xEdgeFilterLuma(cu, edgeDir, edge);
+#endif
     }
     if (cu.blocks[COMPONENT_Cb].valid() && pcv.chrFormat != CHROMA_400)
     {
@@ -392,52 +508,115 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu )
   m_stLFCUParam.leftEdge     = ( 0 < pos.x ) && isAvailable ( cu, *cu.cs->getCU( pos.offset( -1,  0 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag());
   m_stLFCUParam.topEdge      = ( 0 < pos.y ) && isAvailable ( cu, *cu.cs->getCU( pos.offset(  0, -1 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag());
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  m_stLFCUParam.internalEdge &= !cu.ispMode;
+#endif
 }
 
 unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const Position& localPos ) const
 {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  // The boundary strength that is output by the function xGetBoundaryStrengthSingle is a multi component boundary strength that contains boundary strength for luma (bits 0 to 1), cb (bits 2 to 3) and cr (bits 4 to 5).
+#endif
+
   const Slice& sliceQ = *cu.slice;
 
-  const Position& cuPosLuma = cu.lumaPos();
   int shiftHor = cu.Y().valid() ? 0 : ::getComponentScaleX(COMPONENT_Cb, cu.firstPU->chromaFormat);
   int shiftVer = cu.Y().valid() ? 0 : ::getComponentScaleY(COMPONENT_Cb, cu.firstPU->chromaFormat);
   const Position& posQ = Position{ localPos.x >> shiftHor,  localPos.y >> shiftVer };
   const Position  posP  = ( edgeDir == EDGE_VER ) ? posQ.offset( -1, 0 ) : posQ.offset( 0, -1 );
 
-  const bool sameCU     = posP.x >= cuPosLuma.x && posP.y >= cuPosLuma.y;
-
   const CodingUnit& cuQ = cu;
-  const CodingUnit& cuP = sameCU ? cu : *cu.cs->getCU( posP, cu.chType );
+  const CodingUnit& cuP = *cu.cs->getCU( posP, cu.chType );
 
   //-- Set BS for Intra MB : BS = 4 or 3
   if( ( MODE_INTRA == cuP.predMode ) || ( MODE_INTRA == cuQ.predMode ) )
   {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    return (BsSet(2, COMPONENT_Y) + BsSet(2, COMPONENT_Cb) + BsSet(2, COMPONENT_Cr));
+#else
     return 2;
+#endif
   }
 
-  const TransformUnit& tuQ = posQ == cuQ.lumaPos() ? *cuQ.firstTU : *cuQ.cs->getTU(posQ, cuQ.chType);
-  const TransformUnit& tuP = posP == cuP.lumaPos() ? *cuP.firstTU : *cuP.cs->getTU(posP, cuP.chType);
+  const TransformUnit& tuQ = *cuQ.cs->getTU(posQ, cuQ.chType);
+  const TransformUnit& tuP = *cuP.cs->getTU(posP, cuP.chType);
   const PreCalcValues& pcv = *cu.cs->pcv;
   const unsigned rasterIdx = getRasterIdx( posQ, pcv );
+#if JVET_M0908_CIIP_DB
+  if (m_aapucBS[edgeDir][rasterIdx] && (cuP.firstPU->mhIntraFlag || cuQ.firstPU->mhIntraFlag))
+  {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+     return (BsSet(2, COMPONENT_Y) + BsSet(2, COMPONENT_Cb) + BsSet(2, COMPONENT_Cr));
+#else
+     return 2;
+#endif
+  }
+#endif
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  unsigned tmpBs = 0;
+  //-- Set BS for not Intra MB : BS = 2 or 1 or 0
+  // Y
+  if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Y) || TU::getCbf(tuP, COMPONENT_Y)))
+  {
+    tmpBs += BsSet(1, COMPONENT_Y);
+  }
+  // U
+  if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Cb) || TU::getCbf(tuP, COMPONENT_Cb)))
+  {
+    tmpBs += BsSet(1, COMPONENT_Cb);
+  }
+  // V
+  if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Cr) || TU::getCbf(tuP, COMPONENT_Cr)))
+  {
+    tmpBs += BsSet(1, COMPONENT_Cr);
+  }
+  if (BsGet(tmpBs, COMPONENT_Y) == 1)
+  {
+    return tmpBs;
+  }
+#else
   //-- Set BS for not Intra MB : BS = 2 or 1 or 0
   if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Y) || TU::getCbf(tuP, COMPONENT_Y)))
   {
     return 1;
   }
+#endif
+#if JVET_M0908_CIIP_DB
+  if ((cuP.firstPU->mhIntraFlag || cuQ.firstPU->mhIntraFlag))
+  {
+    return 1;
+  }
+#endif
+
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  if ( !cu.Y().valid() )
+  {
+    return tmpBs;
+  }
+#endif
 
   // and now the pred
-  const MotionInfo&     miQ = cuQ.cs->getMotionInfo( posQ );
-  const MotionInfo&     miP = cuP.cs->getMotionInfo( posP );
+  const Position& lumaPosQ  = Position{ localPos.x,  localPos.y };
+  const Position  lumaPosP  = ( edgeDir == EDGE_VER ) ? lumaPosQ.offset( -1, 0 ) : lumaPosQ.offset( 0, -1 );
+  const MotionInfo&     miQ = cuQ.cs->getMotionInfo( lumaPosQ );
+  const MotionInfo&     miP = cuP.cs->getMotionInfo( lumaPosP );
   const Slice&       sliceP = *cuP.slice;
 
   if (sliceQ.isInterB() || sliceP.isInterB())
   {
+#if JVET_M0483_IBC
+    const Picture *piRefP0 = (CU::isIBC(cuP) ? sliceP.getPic() : ((0 > miP.refIdx[0]) ? NULL : sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0])));
+    const Picture *piRefP1 = (CU::isIBC(cuP) ? NULL            : ((0 > miP.refIdx[1]) ? NULL : sliceP.getRefPic(REF_PIC_LIST_1, miP.refIdx[1])));
+    const Picture *piRefQ0 = (CU::isIBC(cuQ) ? sliceQ.getPic() : ((0 > miQ.refIdx[0]) ? NULL : sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0])));
+    const Picture *piRefQ1 = (CU::isIBC(cuQ) ? NULL            : ((0 > miQ.refIdx[1]) ? NULL : sliceQ.getRefPic(REF_PIC_LIST_1, miQ.refIdx[1])));
+#else
     const Picture *piRefP0 = ( 0 > miP.refIdx[0] ) ? NULL : sliceP.getRefPic( REF_PIC_LIST_0, miP.refIdx[0] );
     const Picture *piRefP1 = ( 0 > miP.refIdx[1] ) ? NULL : sliceP.getRefPic( REF_PIC_LIST_1, miP.refIdx[1] );
     const Picture *piRefQ0 = ( 0 > miQ.refIdx[0] ) ? NULL : sliceQ.getRefPic( REF_PIC_LIST_0, miQ.refIdx[0] );
     const Picture *piRefQ1 = ( 0 > miQ.refIdx[1] ) ? NULL : sliceQ.getRefPic( REF_PIC_LIST_1, miQ.refIdx[1] );
-
+#endif
     Mv mvP0, mvP1, mvQ0, mvQ1;
 
     if( 0 <= miP.refIdx[0] ) { mvP0 = miP.mv[0]; }
@@ -480,33 +659,51 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De
     {
       uiBs = 1;
     }
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    return uiBs + tmpBs;
+#else
     return uiBs;
+#endif
   }
 
 
   // pcSlice->isInterP()
+#if JVET_M0483_IBC
+  CHECK(CU::isInter(cuP) && 0 > miP.refIdx[0], "Invalid reference picture list index");
+  CHECK(CU::isInter(cuP) && 0 > miQ.refIdx[0], "Invalid reference picture list index");
+  const Picture *piRefP0 = (CU::isIBC(cuP) ? sliceP.getPic() : sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0]));
+  const Picture *piRefQ0 = (CU::isIBC(cuQ) ? sliceQ.getPic() : sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0]));
+#else
   CHECK(0 > miP.refIdx[0], "Invalid reference picture list index");
   CHECK(0 > miQ.refIdx[0], "Invalid reference picture list index");
   const Picture *piRefP0 = sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0]);
   const Picture *piRefQ0 = sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0]);
-
+#endif
   if (piRefP0 != piRefQ0)
   {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    return tmpBs + 1;
+#else
     return 1;
+#endif
   }
 
   Mv mvP0 = miP.mv[0];
   Mv mvQ0 = miQ.mv[0];
 
   int nThreshold = 1 << MV_FRACTIONAL_BITS_INTERNAL;
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  return ( ( abs( mvQ0.getHor() - mvP0.getHor() ) >= nThreshold ) || ( abs( mvQ0.getVer() - mvP0.getVer() ) >= nThreshold ) ) ? (tmpBs + 1) : tmpBs;
+#else
   return ( ( abs( mvQ0.getHor() - mvP0.getHor() ) >= nThreshold ) || ( abs( mvQ0.getVer() - mvP0.getVer() ) >= nThreshold ) ) ? 1 : 0;
+#endif
 }
 
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
 void LoopFilter::deriveLADFShift( const Pel* src, const int stride, int& shift, const DeblockEdgeDir edgeDir, const SPS sps )
 {
   uint32_t lumaLevel = 0;
-  shift = sps.getSpsNext().getLadfQpOffset(0);
+  shift = sps.getLadfQpOffset(0);
 
   if (edgeDir == EDGE_VER)
   {
@@ -517,12 +714,12 @@ void LoopFilter::deriveLADFShift( const Pel* src, const int stride, int& shift,
     lumaLevel = (src[0] + src[3] + src[-stride] + src[-stride + 3]) >> 2;
   }
 
-  for ( int k = 1; k < sps.getSpsNext().getLadfNumIntervals(); k++ )
+  for ( int k = 1; k < sps.getLadfNumIntervals(); k++ )
   {
-    const int th = sps.getSpsNext().getLadfIntervalLowerBound( k );
+    const int th = sps.getLadfIntervalLowerBound( k );
     if ( lumaLevel > th )
     {
-      shift = sps.getSpsNext().getLadfQpOffset( k );
+      shift = sps.getLadfQpOffset( k );
     }
     else
     {
@@ -532,7 +729,11 @@ void LoopFilter::deriveLADFShift( const Pel* src, const int stride, int& shift,
 }
 #endif
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge, const int initialMaxFilterLengthP, const int initialMaxFilterLengthQ)
+#else
 void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge)
+#endif
 {
   const CompArea&  lumaArea = cu.block(COMPONENT_Y);
   const PreCalcValues& pcv = *cu.cs->pcv;
@@ -591,7 +792,11 @@ void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edge
     pos.y += yoffset;
 
     uiBsAbsIdx = getRasterIdx( pos, pcv );
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    uiBs = BsGet(m_aapucBS[edgeDir][uiBsAbsIdx], COMPONENT_Y);
+#else
     uiBs       = m_aapucBS[edgeDir][uiBsAbsIdx];
+#endif
 
     if( uiBs )
     {
@@ -618,13 +823,54 @@ void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edge
       iQP = (cuP.qp + cuQ.qp + 1) >> 1;
 
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-      if ( sps.getSpsNext().getLadfEnabled() )
+      if ( sps.getLadfEnabled() )
       {
         int iShift = 0;
         deriveLADFShift( piTmpSrc + iSrcStep * (iIdx*pelsInPart), iStride, iShift, edgeDir, sps );
         iQP += iShift;
       }
 #endif
+
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+      bool sidePisLarge   = false;
+      bool sideQisLarge   = false;
+      int maxFilterLengthP = initialMaxFilterLengthP;
+      int maxFilterLengthQ = initialMaxFilterLengthQ;
+      if (maxFilterLengthP > 3)
+      {
+        sidePisLarge = (edgeDir == EDGE_VER && cuP.block(COMPONENT_Y).width >= 32)
+          || (edgeDir == EDGE_HOR && cuP.block(COMPONENT_Y).height >= 32);
+
+        if (sidePisLarge && maxFilterLengthP > 5)
+        {
+          // restrict filter length if sub-blocks are used (e.g affine or ATMVP)
+#if JVET_M0908_CIIP_DB
+          bool ciipSubBlock = false;
+          if (cuP.firstPU->mhIntraFlag)
+          {
+            const uint32_t dirMode = PU::getFinalIntraMode(*(cuP.firstPU), cuP.chType);
+            ciipSubBlock = edgeDir == EDGE_HOR ? dirMode == VER_IDX : dirMode == HOR_IDX;
+          }
+          if (cuP.affine || ciipSubBlock)
+#else
+          if (cuP.affine)
+#endif
+          {
+            maxFilterLengthP = std::min(maxFilterLengthP, 5);
+          }
+        }
+      }
+      if (maxFilterLengthQ > 3)
+      {
+        sideQisLarge = (edgeDir == EDGE_VER && cuQ.block(COMPONENT_Y).width >= 32)
+          || (edgeDir == EDGE_HOR && cuQ.block(COMPONENT_Y).height >= 32);
+      }
+
+      if (edgeDir == EDGE_HOR && pos.y % slice.getSPS()->getCTUSize() == 0)
+      {
+        sidePisLarge = false;
+      }
+#endif
       const int iIndexTC  = Clip3(0, MAX_QP + DEFAULT_INTRA_TC_OFFSET, int(iQP + DEFAULT_INTRA_TC_OFFSET*(uiBs - 1) + (tcOffsetDiv2 << 1)));
       const int iIndexB   = Clip3(0, MAX_QP, iQP + (betaOffsetDiv2 << 1));
 
@@ -641,6 +887,72 @@ void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edge
         const int dq0 = xCalcDQ(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 0), iOffset);
         const int dp3 = xCalcDP(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 3), iOffset);
         const int dq3 = xCalcDQ(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 3), iOffset);
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        int dp0L = dp0;
+        int dq0L = dq0;
+        int dp3L = dp3;
+        int dq3L = dq3;
+
+        if (sidePisLarge)
+        {
+          dp0L = (dp0L + xCalcDP(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 0) - 3 * iOffset, iOffset) + 1) >> 1;
+          dp3L = (dp3L + xCalcDP(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 3) - 3 * iOffset, iOffset) + 1) >> 1;
+        }
+        if (sideQisLarge)
+        {
+          dq0L = (dq0L + xCalcDQ(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 0) + 3 * iOffset, iOffset) + 1) >> 1;
+          dq3L = (dq3L + xCalcDQ(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + 3) + 3 * iOffset, iOffset) + 1) >> 1;
+        }
+        bool useLongtapFilter = false;
+        if (sidePisLarge || sideQisLarge)
+        {
+          int d0L = dp0L + dq0L;
+          int d3L = dp3L + dq3L;
+
+          int dpL = dp0L + dp3L;
+          int dqL = dq0L + dq3L;
+
+          int dL = d0L + d3L;
+
+          bPartPNoFilter = bPartQNoFilter = false;
+          if (bPCMFilter)
+          {
+            // Check if each of PUs is I_PCM with LF disabling
+            bPartPNoFilter = cuP.ipcm;
+            bPartQNoFilter = cuQ.ipcm;
+          }
+          if (ppsTransquantBypassEnabledFlag)
+          {
+            // check if each of PUs is lossless coded
+            bPartPNoFilter = bPartPNoFilter || cuP.transQuantBypass;
+            bPartQNoFilter = bPartQNoFilter || cuQ.transQuantBypass;
+          }
+
+          if (dL < iBeta)
+          {
+            const bool filterP = (dpL < iSideThreshold);
+            const bool filterQ = (dqL < iSideThreshold);
+
+            Pel* src0 = piTmpSrc + iSrcStep * (iIdx*pelsInPart + iBlkIdx * 4 + 0);
+            Pel* src3 = piTmpSrc + iSrcStep * (iIdx*pelsInPart + iBlkIdx * 4 + 3);
+
+            // adjust decision so that it is not read beyond p5 is maxFilterLengthP is 5 and q5 if maxFilterLengthQ is 5
+            const bool swL = xUseStrongFiltering(src0, iOffset, 2 * d0L, iBeta, iTc, sidePisLarge, sideQisLarge, maxFilterLengthP, maxFilterLengthQ)
+              && xUseStrongFiltering(src3, iOffset, 2 * d3L, iBeta, iTc, sidePisLarge, sideQisLarge, maxFilterLengthP, maxFilterLengthQ);
+            if (swL)
+            {
+              useLongtapFilter = true;
+              for (int i = 0; i < DEBLOCK_SMALLEST_BLOCK / 2; i++)
+              {
+                xPelFilterLuma(piTmpSrc + iSrcStep*(iIdx*pelsInPart + iBlkIdx * 4 + i), iOffset, iTc, swL, bPartPNoFilter, bPartQNoFilter, iThrCut, filterP, filterQ, clpRng, sidePisLarge, sideQisLarge, maxFilterLengthP, maxFilterLengthQ);
+              }
+            }
+
+          }
+        }
+        if (!useLongtapFilter)
+        {
+#endif
         const int d0 = dp0 + dq0;
         const int d3 = dp3 + dq3;
 
@@ -666,15 +978,25 @@ void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edge
         {
           const bool bFilterP = (dp < iSideThreshold);
           const bool bFilterQ = (dq < iSideThreshold);
-
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+          bool sw = false;
+          if (maxFilterLengthP > 2 && maxFilterLengthQ > 2)
+          {
+            sw = xUseStrongFiltering(piTmpSrc + iSrcStep * (iIdx*pelsInPart + iBlkIdx * 4 + 0), iOffset, 2 * d0, iBeta, iTc)
+              && xUseStrongFiltering(piTmpSrc + iSrcStep * (iIdx*pelsInPart + iBlkIdx * 4 + 3), iOffset, 2 * d3, iBeta, iTc);
+          }
+#else
           const bool sw = xUseStrongFiltering( piTmpSrc + iSrcStep * ( iIdx*pelsInPart + iBlkIdx * 4 + 0 ), iOffset, 2 * d0, iBeta, iTc )
                        && xUseStrongFiltering( piTmpSrc + iSrcStep * ( iIdx*pelsInPart + iBlkIdx * 4 + 3 ), iOffset, 2 * d3, iBeta, iTc );
-
+#endif
           for( int i = 0; i < DEBLOCK_SMALLEST_BLOCK / 2; i++ )
           {
             xPelFilterLuma( piTmpSrc + iSrcStep*( iIdx*pelsInPart + iBlkIdx * 4 + i ), iOffset, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ, clpRng );
           }
         }
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        }
+#endif
       }
     }
   }
@@ -708,6 +1030,9 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
   bool      bPartPNoFilter  = false;
   bool      bPartQNoFilter  = false;
   const int tcOffsetDiv2    = slice.getDeblockingFilterTcOffsetDiv2();
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  const int betaOffsetDiv2  = slice.getDeblockingFilterBetaOffsetDiv2();
+#endif
 
   // Vertical Position
   unsigned uiEdgeNumInCtuVert = rasterIdx % pcv.partsInCtuWidth + iEdge;
@@ -726,7 +1051,11 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
   unsigned uiNumParts =  ( edgeDir == EDGE_VER ) ? lumaSize.height / pcv.minCUHeight : lumaSize.width / pcv.minCUWidth ;
   int   uiNumPelsLuma = pcv.minCUWidth;
   unsigned uiBsAbsIdx;
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  unsigned bS[2];
+#else
   unsigned ucBs;
+#endif
 
   Pel* piTmpSrcCb = piSrcCb;
   Pel* piTmpSrcCr = piSrcCr;
@@ -764,9 +1093,21 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
     pos.y += yoffset;
 
     uiBsAbsIdx = getRasterIdx( pos, pcv );
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    unsigned tmpBs = m_aapucBS[edgeDir][uiBsAbsIdx];
+
+    tmpBs = m_aapucBS[edgeDir][uiBsAbsIdx];
+    bS[0] = BsGet(tmpBs, COMPONENT_Cb);
+    bS[1] = BsGet(tmpBs, COMPONENT_Cr);
+#else
     ucBs       = m_aapucBS[edgeDir][uiBsAbsIdx];
+#endif
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (bS[0] > 0 || bS[1] > 0)
+#else
     if (ucBs > 1)
+#endif
     {
       const CodingUnit& cuQ =  cu;
       const CodingUnit& cuP = *cu.cs->getCU( recalcPosition( cu.chromaFormat, CHANNEL_TYPE_LUMA, cu.chType, pos.offset( xoffset - uiNumPelsLuma, yoffset - uiNumPelsLuma ) ), cu.chType );
@@ -802,8 +1143,26 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
         bPartQNoFilter = bPartQNoFilter || cuQ.transQuantBypass;
       }
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+      const unsigned cuPWidth  = cuP.block(COMPONENT_Cb).width;
+      const unsigned cuPHeight = cuP.block(COMPONENT_Cb).height;
+      const unsigned cuQWidth  = cuQ.block(COMPONENT_Cb).width;
+      const unsigned cuQHeight = cuQ.block(COMPONENT_Cb).height;
+
+      bool largeBoundary = ((edgeDir == EDGE_VER && cuPWidth >= 8 && cuQWidth >= 8) || (edgeDir == EDGE_HOR && cuPHeight >= 8 && cuQHeight >= 8));
+
+      if (edgeDir == EDGE_HOR && pos.y % cuP.slice->getSPS()->getCTUSize() == 0)
+      {
+        largeBoundary = false;
+      }
+
+#endif
       for( int chromaIdx = 0; chromaIdx < 2; chromaIdx++ )
       {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        if ((bS[chromaIdx] == 2) || (largeBoundary && (bS[chromaIdx] == 1)))
+        {
+#endif
         const ClpRng& clpRng( cu.cs->slice->clpRng( ComponentID( chromaIdx + 1 )) );
         const int chromaQPOffset = pps.getQpOffset( ComponentID( chromaIdx + 1 ) );
         Pel* piTmpSrcChroma = (chromaIdx == 0) ? piTmpSrcCb : piTmpSrcCr;
@@ -825,13 +1184,57 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
           iQP = getScaledChromaQP(iQP, sps.getChromaFormatIdc());
         }
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        const int iIndexTC = Clip3<int>(0, MAX_QP + DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET * (bS[chromaIdx] - 1) + (tcOffsetDiv2 << 1));
+#else
         const int iIndexTC = Clip3<int>( 0, MAX_QP + DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET*( ucBs - 1 ) + ( tcOffsetDiv2 << 1 ) );
+#endif
         const int iTc      = sm_tcTable[iIndexTC] * iBitdepthScale;
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        bool useLongFilter = false;
+        if (largeBoundary)
+        {
+        const int indexB = Clip3<int>(0, MAX_QP, iQP + (betaOffsetDiv2 << 1));
+        const int beta = sm_betaTable[indexB] * iBitdepthScale;
+
+        const int dp0 = xCalcDP(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 0), iOffset);
+        const int dq0 = xCalcDQ(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 0), iOffset);
+        const int dp1 = xCalcDP(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 1), iOffset);
+        const int dq1 = xCalcDQ(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 1), iOffset);
+
+        const int d0 = dp0 + dq0;
+        const int d1 = dp1 + dq1;
+        const int d = d0 + d1;
+
+          if (d < beta)
+          {
+            useLongFilter = true;
+            const bool sw = xUseStrongFiltering(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 0), iOffset, 2 * d0, beta, iTc)
+                && xUseStrongFiltering(piTmpSrcChroma + iSrcStep*(iIdx*uiLoopLength + 1), iOffset, 2 * d1, beta, iTc);
+
+            for (unsigned step = 0; step < uiLoopLength; step++)
+            {
+              xPelFilterChroma(piTmpSrcChroma + iSrcStep*(step + iIdx*uiLoopLength), iOffset, iTc, sw, bPartPNoFilter, bPartQNoFilter, clpRng, largeBoundary);
+            }
+          }
+        }
+        if ( !useLongFilter )
+        {
+          for (unsigned step = 0; step < uiLoopLength; step++)
+          {
+            xPelFilterChroma(piTmpSrcChroma + iSrcStep*(step + iIdx*uiLoopLength), iOffset, iTc, false, bPartPNoFilter, bPartQNoFilter, clpRng, largeBoundary);
+          }
+        }
+#else
         for( unsigned uiStep = 0; uiStep < uiLoopLength; uiStep++ )
         {
           xPelFilterChroma( piTmpSrcChroma + iSrcStep*( uiStep + iIdx*uiLoopLength ), iOffset, iTc, bPartPNoFilter, bPartQNoFilter, clpRng );
         }
+#endif
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+        }
+#endif
       }
     }
   }
@@ -853,7 +1256,106 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
  \param bFilterSecondQ  decision weak filter/no filter for partQ
  \param bitDepthLuma    luma bit depth
 */
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+inline void LoopFilter::xBilinearFilter(Pel* srcP, Pel* srcQ, int offset, int refMiddle, int refP, int refQ, int numberPSide, int numberQSide, const int* dbCoeffsP, const int* dbCoeffsQ, int tc) const
+{
+    int src;
+    const char tc7[7] = { 6, 5, 4, 3, 2, 1, 1};
+    const char tc3[3] = { 6, 4, 2 };
+    const char *tcP  = (numberPSide == 3) ? tc3 : tc7;
+    const char *tcQ  = (numberQSide == 3) ? tc3 : tc7;
+    for (int pos = 0; pos < numberPSide; pos++)
+    {
+      src = srcP[-offset*pos];
+      int cvalue = (tc * tcP[pos]) >>1;
+      srcP[-offset * pos] = Clip3(src - cvalue, src + cvalue, ((refMiddle*dbCoeffsP[pos] + refP * (64 - dbCoeffsP[pos]) + 32) >> 6));
+    }
+    for (int pos = 0; pos < numberQSide; pos++)
+    {
+      src = srcQ[offset*pos];
+      int cvalue = (tc * tcQ[pos]) >> 1;
+      srcQ[offset*pos] = Clip3(src - cvalue, src + cvalue, ((refMiddle*dbCoeffsQ[pos] + refQ * (64 - dbCoeffsQ[pos]) + 32) >> 6));
+    }
+}
+
+inline void LoopFilter::xFilteringPandQ(Pel* src, int offset, int numberPSide, int numberQSide, int tc) const
+{
+  CHECK(numberPSide <= 3 && numberQSide <= 3, "Short filtering in long filtering function");
+  Pel* srcP = src-offset;
+  Pel* srcQ = src;
+
+  int refP = 0;
+  int refQ = 0;
+  int refMiddle = 0;
+
+  const int dbCoeffs7[7] = { 59, 50, 41,32,23,14,5 };
+  const int dbCoeffs3[3] = { 53, 32, 11 };
+  const int dbCoeffs5[5] = { 58, 45, 32,19,6};
+  const int* dbCoeffsP   = numberPSide == 7 ? dbCoeffs7 : (numberPSide==5) ? dbCoeffs5 : dbCoeffs3;
+  const int* dbCoeffsQ   = numberQSide == 7 ? dbCoeffs7 : (numberQSide==5) ? dbCoeffs5 : dbCoeffs3;
+
+  switch (numberPSide)
+  {
+    case 7: refP = (srcP[-6*offset]   + srcP[-7 * offset] + 1) >> 1; break;
+    case 3: refP = (srcP[-2 * offset] + srcP[-3 * offset] + 1) >> 1; break;
+    case 5: refP = (srcP[-4 * offset] + srcP[-5 * offset] + 1) >> 1; break;
+  }
+
+  switch (numberQSide)
+  {
+    case 7: refQ = (srcQ[6 * offset] + srcQ[7 * offset] + 1) >> 1; break;
+    case 3: refQ = (srcQ[2 * offset] + srcQ[3 * offset] + 1) >> 1; break;
+    case 5: refQ = (srcQ[4 * offset] + srcQ[5 * offset] + 1) >> 1; break;
+  }
+
+  if (numberPSide == numberQSide)
+  {
+    if (numberPSide == 5)
+    {
+      refMiddle = (2 * (srcP[0] + srcQ[0] + srcP[-offset] + srcQ[offset] + srcP[-2 * offset] + srcQ[2 * offset]) + srcP[-3 * offset] + srcQ[3 * offset] + srcP[-4 * offset] + srcQ[4 * offset] + 8) >> 4;
+    }
+    else
+    {
+      refMiddle = (2 * (srcP[0] + srcQ[0]) + srcP[-offset] + srcQ[offset] + srcP[-2 * offset] + srcQ[2 * offset] + srcP[-3 * offset] + srcQ[3 * offset] + srcP[-4 * offset] + srcQ[4 * offset] + srcP[-5 * offset] + srcQ[5 * offset] + +srcP[-6 * offset] + srcQ[6 * offset] + 8) >> 4;
+    }
+  }
+  else
+  {
+    Pel* srcPt = srcP;
+    Pel* srcQt = srcQ;
+    int offsetP = -offset;
+    int offsetQ = offset;
+
+    int newNumberQSide = numberQSide;
+    int newNumberPSide = numberPSide;
+    if (numberQSide > numberPSide)
+    {
+      std::swap(srcPt, srcQt);
+      std::swap(offsetP, offsetQ);
+      newNumberQSide = numberPSide;
+      newNumberPSide = numberQSide;
+    }
+
+    if (newNumberPSide == 7 && newNumberQSide == 5)
+    {
+      refMiddle = (2 * (srcP[0] + srcQ[0] + srcP[-offset] + srcQ[offset]) + srcP[-2 * offset] + srcQ[2 * offset] + srcP[-3 * offset] + srcQ[3 * offset] + srcP[-4 * offset] + srcQ[4 * offset] + srcP[-5 * offset] + srcQ[5 * offset] + 8) >> 4;
+    }
+    else if (newNumberPSide == 7 && newNumberQSide == 3)
+    {
+      refMiddle = (2 * (srcPt[0] + srcQt[0]) + srcQt[0] + 2 * (srcQt[offsetQ] + srcQt[2 * offsetQ]) + srcPt[offsetP] + srcQt[offsetQ] + srcPt[2 * offsetP] + srcPt[3 * offsetP] + srcPt[4 * offsetP] + srcPt[5 * offsetP] + srcPt[6 * offsetP] + 8) >> 4;
+    }
+    else //if (newNumberPSide == 5 && newNumberQSide == 3)
+    {
+      refMiddle = (srcP[0] + srcQ[0] + srcP[-offset] + srcQ[offset] + srcP[-2 * offset] + srcQ[2 * offset] + srcP[-3 * offset] + srcQ[3 * offset] + 4) >> 3;
+    }
+  }
+  xBilinearFilter(srcP,srcQ,offset,refMiddle,refP,refQ,numberPSide,numberQSide,dbCoeffsP,dbCoeffsQ,tc);
+}
+
+inline void LoopFilter::xPelFilterLuma(Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const int iThrCut, const bool bFilterSecondP, const bool bFilterSecondQ, const ClpRng& clpRng, bool sidePisLarge, bool sideQisLarge, int maxFilterLengthP, int maxFilterLengthQ) const
+#else
 inline void LoopFilter::xPelFilterLuma( Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const int iThrCut, const bool bFilterSecondP, const bool bFilterSecondQ, const ClpRng& clpRng ) const
+#endif
 {
   int delta;
 
@@ -866,14 +1368,39 @@ inline void LoopFilter::xPelFilterLuma( Pel* piSrc, const int iOffset, const int
   const Pel m7  = piSrc[ iOffset * 3];
   const Pel m0  = piSrc[-iOffset * 4];
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  const Pel mP1 = piSrc[-iOffset * 5];
+  const Pel mP2 = piSrc[-iOffset * 6];
+  const Pel mP3 = piSrc[-iOffset * 7];
+  const Pel m8  = piSrc[ iOffset * 4];
+  const Pel m9  = piSrc[ iOffset * 5];
+  const Pel m10 = piSrc[ iOffset * 6];
+  const char tc3[3] = { 3, 2, 1};
+#endif
   if (sw)
   {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (sidePisLarge || sideQisLarge)
+    {
+      xFilteringPandQ(piSrc, iOffset, sidePisLarge ? maxFilterLengthP : 3, sideQisLarge ? maxFilterLengthQ : 3, tc);
+    }
+    else
+    {
+      piSrc[-iOffset]     = Clip3(m3 - tc3[0] * tc, m3 + tc3[0] * tc, ((m1 + 2 * m2 + 2 * m3 + 2 * m4 + m5 + 4) >> 3));
+      piSrc[0]            = Clip3(m4 - tc3[0] * tc, m4 + tc3[0] * tc, ((m2 + 2 * m3 + 2 * m4 + 2 * m5 + m6 + 4) >> 3));
+      piSrc[-iOffset * 2] = Clip3(m2 - tc3[1] * tc, m2 + tc3[1] * tc, ((m1 + m2 + m3 + m4 + 2) >> 2));
+      piSrc[iOffset]      = Clip3(m5 - tc3[1] * tc, m5 + tc3[1] * tc, ((m3 + m4 + m5 + m6 + 2) >> 2));
+      piSrc[-iOffset * 3] = Clip3(m1 - tc3[2] * tc, m1 + tc3[2] * tc, ((2 * m0 + 3 * m1 + m2 + m3 + m4 + 4) >> 3));
+      piSrc[iOffset * 2]  = Clip3(m6 - tc3[2] * tc, m6 + tc3[2] * tc, ((m3 + m4 + m5 + 3 * m6 + 2 * m7 + 4) >> 3));
+    }
+#else
     piSrc[-iOffset]     = Clip3( m3 - 2 * tc, m3 + 2 * tc, ( (     m1 + 2 * m2 + 2 * m3 + 2 * m4 +     m5 + 4 ) >> 3 ) );
     piSrc[ 0]           = Clip3( m4 - 2 * tc, m4 + 2 * tc, ( (     m2 + 2 * m3 + 2 * m4 + 2 * m5 +     m6 + 4 ) >> 3 ) );
     piSrc[-iOffset * 2] = Clip3( m2 - 2 * tc, m2 + 2 * tc, ( (     m1 +     m2 +     m3 +     m4 +          2 ) >> 2 ) );
     piSrc[ iOffset]     = Clip3( m5 - 2 * tc, m5 + 2 * tc, ( (     m3 +     m4 +     m5 +     m6 +          2 ) >> 2 ) );
     piSrc[-iOffset * 3] = Clip3( m1 - 2 * tc, m1 + 2 * tc, ( ( 2 * m0 + 3 * m1 +     m2 +     m3 +     m4 + 4 ) >> 3 ) );
     piSrc[ iOffset * 2] = Clip3( m6 - 2 * tc, m6 + 2 * tc, ( (     m3 +     m4 +     m5 + 3 * m6 + 2 * m7 + 4 ) >> 3 ) );
+#endif
   }
   else
   {
@@ -905,6 +1432,15 @@ inline void LoopFilter::xPelFilterLuma( Pel* piSrc, const int iOffset, const int
     piSrc[-iOffset    ] = m3;
     piSrc[-iOffset * 2] = m2;
     piSrc[-iOffset * 3] = m1;
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (sidePisLarge)
+    {
+      piSrc[-iOffset * 4] = m0;
+      piSrc[-iOffset * 5] = mP1;
+      piSrc[-iOffset * 6] = mP2;
+      piSrc[-iOffset * 7] = mP3;
+    }
+#endif
   }
 
   if(bPartQNoFilter)
@@ -912,6 +1448,15 @@ inline void LoopFilter::xPelFilterLuma( Pel* piSrc, const int iOffset, const int
     piSrc[ 0          ] = m4;
     piSrc[ iOffset    ] = m5;
     piSrc[ iOffset * 2] = m6;
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (sideQisLarge)
+    {
+      piSrc[iOffset * 3] = m7;
+      piSrc[iOffset * 4] = m8;
+      piSrc[iOffset * 5] = m9;
+      piSrc[iOffset * 6] = m10;
+    }
+#endif
   }
 }
 
@@ -925,10 +1470,41 @@ inline void LoopFilter::xPelFilterLuma( Pel* piSrc, const int iOffset, const int
  \param bPartQNoFilter  indicator to disable filtering on partQ
  \param bitDepthChroma  chroma bit depth
  */
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+inline void LoopFilter::xPelFilterChroma( Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const ClpRng& clpRng, const bool largeBoundary ) const
+#else
 inline void LoopFilter::xPelFilterChroma( Pel* piSrc, const int iOffset, const int tc, const bool bPartPNoFilter, const bool bPartQNoFilter, const ClpRng& clpRng ) const
+#endif
 {
   int delta;
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  const Pel m0 = piSrc[-iOffset * 4];
+  const Pel m1 = piSrc[-iOffset * 3];
+  const Pel m2 = piSrc[-iOffset * 2];
+  const Pel m3 = piSrc[-iOffset];
+  const Pel m4 = piSrc[0];
+  const Pel m5 = piSrc[iOffset];
+  const Pel m6 = piSrc[iOffset * 2];
+  const Pel m7 = piSrc[iOffset * 3];
+
+  if (sw)
+  {
+      piSrc[-iOffset * 3] = Clip3(m1 - tc, m1 + tc, ((3 * m0 + 2 * m1 + m2 + m3 + m4 + 4) >> 3));       // p2
+      piSrc[-iOffset * 2] = Clip3(m2 - tc, m2 + tc, ((2 * m0 + m1 + 2 * m2 + m3 + m4 + m5 + 4) >> 3));  // p1
+      piSrc[-iOffset * 1] = Clip3(m3 - tc, m3 + tc, ((m0 + m1 + m2 + 2 * m3 + m4 + m5 + m6 + 4) >> 3)); // p0
+      piSrc[0]            = Clip3(m4 - tc, m4 + tc, ((m1 + m2 + m3 + 2 * m4 + m5 + m6 + m7 + 4) >> 3)); // q0
+      piSrc[iOffset * 1]  = Clip3(m5 - tc, m5 + tc, ((m2 + m3 + m4 + 2 * m5 + m6 + 2 * m7 + 4) >> 3));  // q1
+      piSrc[iOffset * 2]  = Clip3(m6 - tc, m6 + tc, ((m3 + m4 + m5 + 2 * m6 + 3 * m7 + 4) >> 3));       // q2
+  }
+  else
+  {
+      delta = Clip3(-tc, tc, ((((m4 - m3) << 2) + m2 - m5 + 4) >> 3));
+      piSrc[-iOffset] = ClipPel(m3 + delta, clpRng);
+      piSrc[0] = ClipPel(m4 - delta, clpRng);
+  }
+
+#else
   const Pel m4  = piSrc[ 0          ];
   const Pel m3  = piSrc[-iOffset    ];
   const Pel m5  = piSrc[ iOffset    ];
@@ -937,13 +1513,28 @@ inline void LoopFilter::xPelFilterChroma( Pel* piSrc, const int iOffset, const i
   delta           = Clip3( -tc, tc, ( ( ( ( m4 - m3 ) << 2 ) + m2 - m5 + 4 ) >> 3 ) );
   piSrc[-iOffset] = ClipPel( m3 + delta, clpRng );
   piSrc[ 0      ] = ClipPel( m4 - delta, clpRng );
+#endif
 
   if( bPartPNoFilter )
   {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (largeBoundary)
+    {
+      piSrc[-iOffset * 3] = m1; // p2
+      piSrc[-iOffset * 2] = m2; // p1
+    }
+#endif
     piSrc[-iOffset] = m3;
   }
   if( bPartQNoFilter )
   {
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+    if (largeBoundary)
+    {
+      piSrc[iOffset * 1] = m5; // q1
+      piSrc[iOffset * 2] = m6; // q2
+    }
+#endif
     piSrc[ 0      ] = m4;
   }
 }
@@ -957,15 +1548,58 @@ inline void LoopFilter::xPelFilterChroma( Pel* piSrc, const int iOffset, const i
  \param tc              tc value
  \param piSrc           pointer to picture data
  */
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+inline bool LoopFilter::xUseStrongFiltering( Pel* piSrc, const int iOffset, const int d, const int beta, const int tc, bool sidePisLarge, bool sideQisLarge, int maxFilterLengthP, int maxFilterLengthQ ) const
+#else
 inline bool LoopFilter::xUseStrongFiltering( Pel* piSrc, const int iOffset, const int d, const int beta, const int tc ) const
+#endif
 {
   const Pel m4 = piSrc[ 0          ];
   const Pel m3 = piSrc[-iOffset    ];
   const Pel m7 = piSrc[ iOffset * 3];
   const Pel m0 = piSrc[-iOffset * 4];
-
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  int       sp3      = abs(m0 - m3);
+  int       sq3      = abs(m7 - m4);
+  const int d_strong = sp3 + sq3;
+#else
   const int d_strong = abs( m0 - m3 ) + abs( m7 - m4 );
+#endif
+
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  if (sidePisLarge || sideQisLarge)
+  {
+    Pel mP4;
+    Pel m11;
+    if (maxFilterLengthP == 5)
+    {
+      mP4 = piSrc[-iOffset * 6];
+    }
+    else
+    {
+      mP4 = piSrc[-iOffset * 8];
+    }
+    if (maxFilterLengthQ == 5)
+    {
+      m11 = piSrc[iOffset * 5];
+    }
+    else
+    {
+      m11 = piSrc[iOffset * 7];
+    }
 
+    if (sidePisLarge)
+    {
+      sp3 = (sp3 + abs(m0 - mP4) + 1) >> 1;
+    }
+    if (sideQisLarge)
+    {
+      sq3 = (sq3 + abs(m11 - m7) + 1) >> 1;
+    }
+    return ((sp3 + sq3) < (beta*3 >> 5)) && (d < (beta >> 2)) && (abs(m3 - m4) < ((tc * 5 + 1) >> 1));
+  }
+  else
+#endif
   return ( ( d_strong < ( beta >> 3 ) ) && ( d < ( beta >> 2 ) ) && ( abs( m3 - m4 ) < ( ( tc * 5 + 1 ) >> 1 ) ) );
 }
 
@@ -979,4 +1613,9 @@ inline int LoopFilter::xCalcDQ( Pel* piSrc, const int iOffset ) const
   return abs( piSrc[0] - 2 * piSrc[iOffset] + piSrc[iOffset * 2] );
 }
 
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+inline unsigned LoopFilter::BsSet(unsigned val, const ComponentID compIdx) const { return (val << (compIdx << 1)); }
+inline unsigned LoopFilter::BsGet(unsigned val, const ComponentID compIdx) const { return ((val >> (compIdx << 1)) & 3); }
+#endif
+
 //! \}
diff --git a/source/Lib/CommonLib/LoopFilter.h b/source/Lib/CommonLib/LoopFilter.h
index 0f4a71379ff89a104c7824a6fffe82103ce16ed8..5f2b0bafb0a13b0e004bed96061e9e07790e7529 100644
--- a/source/Lib/CommonLib/LoopFilter.h
+++ b/source/Lib/CommonLib/LoopFilter.h
@@ -62,7 +62,7 @@ private:
 private:
   /// CU-level deblocking function
   void xDeblockCU                 (       CodingUnit& cu, const DeblockEdgeDir edgeDir );
-  
+
   // set / get functions
   void xSetLoopfilterParam        ( const CodingUnit& cu );
 
@@ -75,17 +75,32 @@ private:
                                     const Area&           area,
                                     const bool            bValue,
                                     const bool            EdgeIdx = false );
-
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  void xEdgeFilterLuma            ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge, const int initialMaxFilterLengthP, const int initialMaxFilterLengthQ );
+#else
   void xEdgeFilterLuma            ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge );
-  void xEdgeFilterChroma          ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge );
+#endif
+  void xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir edgeDir, const int iEdge);
 
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
   void deriveLADFShift( const Pel* src, const int stride, int& shift, const DeblockEdgeDir edgeDir, const SPS sps );
 #endif
+
+#if JVET_M0471_LONG_DEBLOCKING_FILTERS
+  inline void xBilinearFilter     ( Pel* srcP, Pel* srcQ, int offset, int refMiddle, int refP, int refQ, int numberPSide, int numberQSide, const int* dbCoeffsP, const int* dbCoeffsQ, int tc ) const;
+  inline void xFilteringPandQ     ( Pel* src, int offset, int numberPSide, int numberQSide, int tc ) const;
+  inline void xPelFilterLuma      ( Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const int iThrCut, const bool bFilterSecondP, const bool bFilterSecondQ, const ClpRng& clpRng, bool sidePisLarge = false, bool sideQisLarge = false, int maxFilterLengthP = 7, int maxFilterLengthQ = 7 ) const;
+  inline void xPelFilterChroma    ( Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const ClpRng& clpRng, const bool largeBoundary ) const;
+  inline bool xUseStrongFiltering ( Pel* piSrc, const int iOffset, const int d, const int beta, const int tc, bool sidePisLarge = false, bool sideQisLarge = false, int maxFilterLengthP = 7, int maxFilterLengthQ = 7 ) const;//move the computation outside the function
+  inline unsigned BsSet(unsigned val, const ComponentID compIdx) const;
+  inline unsigned BsGet(unsigned val, const ComponentID compIdx) const;
+#else
   inline void xPelFilterLuma      ( Pel* piSrc, const int iOffset, const int tc, const bool sw, const bool bPartPNoFilter, const bool bPartQNoFilter, const int iThrCut, const bool bFilterSecondP, const bool bFilterSecondQ, const ClpRng& clpRng ) const;
   inline void xPelFilterChroma    ( Pel* piSrc, const int iOffset, const int tc,                const bool bPartPNoFilter, const bool bPartQNoFilter,                                                                          const ClpRng& clpRng ) const;
 
   inline bool xUseStrongFiltering ( Pel* piSrc, const int iOffset, const int d, const int beta, const int tc ) const;
+#endif
+
   inline int xCalcDP              ( Pel* piSrc, const int iOffset ) const;
   inline int xCalcDQ              ( Pel* piSrc, const int iOffset ) const;
   static const uint8_t sm_tcTable[MAX_QP + 3];
diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h
index 20788929749731d6f462f7a30cf56e456680c453..2bc0f935d5e2d8bf49adb725e4c51a4092a060d7 100644
--- a/source/Lib/CommonLib/MotionInfo.h
+++ b/source/Lib/CommonLib/MotionInfo.h
@@ -101,19 +101,49 @@ struct MvField
 struct MotionInfo
 {
   bool     isInter;
+#if JVET_M0483_IBC
+  bool     isIBCmot;
+#endif
   char     interDir;
   uint16_t   sliceIdx;
-
   Mv      mv     [ NUM_REF_PIC_LIST_01 ];
   int16_t   refIdx [ NUM_REF_PIC_LIST_01 ];
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  uint8_t         GBiIdx;
+#endif
   Mv      bv;
-  MotionInfo()        : isInter(  false ), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID } { }
+#if JVET_M0483_IBC
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { }
+#else
+  MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID } { }
+#endif
+  // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything else
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ 0,         0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); }
+#else
+  MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ 0,         0 } { CHECKD(i != 0, "The argument for this constructor has to be '0'"); }
+#endif
+#else
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  MotionInfo() : isInter(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { }
+#else
+  MotionInfo() : isInter(false), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID } { }
+#endif
   // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything else
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  MotionInfo(int i) : isInter(i != 0), interDir(0), sliceIdx(0), refIdx{ 0,         0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); }
+#else
   MotionInfo( int i ) : isInter( i != 0 ), interDir( 0 ), sliceIdx( 0 ), refIdx{         0,         0 } { CHECKD( i != 0, "The argument for this constructor has to be '0'" ); }
+#endif
+#endif
 
   bool operator==( const MotionInfo& mi ) const
   {
     if( isInter != mi.isInter  ) return false;
+#if JVET_M0483_IBC
+    if (isIBCmot != mi.isIBCmot) return false;
+#endif
     if( isInter )
     {
       if( sliceIdx != mi.sliceIdx ) return false;
@@ -150,6 +180,9 @@ class GBiMotionParam
   bool       m_readOnlyAffine[2][2][33];
   Mv         m_mvAffine[2][2][33][3];
   Distortion m_distAffine[2][2][33];
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  int        m_mvpIdx[2][2][33];
+#endif
 
 public:
 
@@ -171,6 +204,9 @@ public:
     memset(m_dist, -1, 2 * 33 * sizeof(Distortion));
     memset(m_readOnlyAffine, false, 2 * 2 * 33 * sizeof(bool));
     memset(m_distAffine, -1, 2 * 2 * 33 * sizeof(Distortion));
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    memset( m_mvpIdx, 0, 2 * 2 * 33 * sizeof( int ) );
+#endif
   }
 
   void setReadMode(bool b, uint32_t uiRefList, uint32_t uiRefIdx) { m_readOnly[uiRefList][uiRefIdx] = b; }
@@ -195,21 +231,38 @@ public:
 
   Mv& getAffineMv(uint32_t uiRefList, uint32_t uiRefIdx, uint32_t uiAffineMvIdx, int bP4) { return m_mvAffine[bP4][uiRefList][uiRefIdx][uiAffineMvIdx]; }
 
-  void copyAffineMvFrom(Mv(&racAffineMvs)[3], Distortion uiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4)
+  void copyAffineMvFrom(Mv(&racAffineMvs)[3], Distortion uiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                        , const int mvpIdx
+#endif
+  )
   {
     memcpy(m_mvAffine[bP4][uiRefList][uiRefIdx], racAffineMvs, 3 * sizeof(Mv));
     m_distAffine[bP4][uiRefList][uiRefIdx] = uiDist;
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    m_mvpIdx[bP4][uiRefList][uiRefIdx]     = mvpIdx;
+#endif
   }
 
-  void copyAffineMvTo(Mv acAffineMvs[3], Distortion& ruiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4)
+  void copyAffineMvTo(Mv acAffineMvs[3], Distortion& ruiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                      , int& mvpIdx
+#endif
+  )
   {
     memcpy(acAffineMvs, m_mvAffine[bP4][uiRefList][uiRefIdx], 3 * sizeof(Mv));
     ruiDist = m_distAffine[bP4][uiRefList][uiRefIdx];
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    mvpIdx  = m_mvpIdx[bP4][uiRefList][uiRefIdx];
+#endif
   }
 };
 struct LutMotionCand
 {
   MotionInfo*   motionCand;
   int  currCnt;
+#if JVET_M0483_IBC
+  int  currCntIBC;
+#endif
 };
 #endif // __MOTIONINFO__
diff --git a/source/Lib/CommonLib/Mv.cpp b/source/Lib/CommonLib/Mv.cpp
index 7edfa2c56903738f79ce174ae35d224d855d16b3..732e756b5ff21ed995286ef3344c52670bdc348a 100644
--- a/source/Lib/CommonLib/Mv.cpp
+++ b/source/Lib/CommonLib/Mv.cpp
@@ -65,7 +65,14 @@ void clipMv( Mv& rcMv, const Position& pos,
   {
     int iHorMax = ( sps.getPicWidthInLumaSamples() + sps.getMaxCUWidth() - size.width + iOffset - ( int ) pos.x - 1 ) << iMvShift;
     int iHorMin = ( -( int ) sps.getMaxCUWidth()                                      - iOffset - ( int ) pos.x + 1 ) << iMvShift;
-    rcMv.setHor( std::min( iHorMax, std::max( iHorMin, rcMv.getHor() ) ) );
+    int mvX = rcMv.getHor();
+    while( mvX > iHorMax ) {
+      mvX -= ( sps.getWrapAroundOffset() << iMvShift );
+    }
+    while( mvX < iHorMin ) {
+      mvX += ( sps.getWrapAroundOffset() << iMvShift );
+    }
+    rcMv.setHor( mvX );
     rcMv.setVer( std::min( iVerMax, std::max( iVerMin, rcMv.getVer() ) ) );
     return;
   }
diff --git a/source/Lib/CommonLib/Mv.h b/source/Lib/CommonLib/Mv.h
index 56287bec0b64953893c6313ce5b7d1ae3349c595..c703fe6cb16446c4bdf596dcb89e1ea0d6c79418 100644
--- a/source/Lib/CommonLib/Mv.h
+++ b/source/Lib/CommonLib/Mv.h
@@ -51,6 +51,9 @@ enum MvPrecision
 {
   MV_PRECISION_4PEL     = 0,      // 4-pel
   MV_PRECISION_INT      = 2,      // 1-pel, shift 2 bits from 4-pel
+#if JVET_M0246_AFFINE_AMVR
+  MV_PRECISION_HALF     = 3,      // 1/2-pel
+#endif
   MV_PRECISION_QUARTER  = 4,      // 1/4-pel (the precision of regular MV difference signaling), shift 4 bits from 4-pel
   MV_PRECISION_INTERNAL = 6,      // 1/16-pel (the precision of internal MV), shift 6 bits from 4-pel
 };
@@ -213,6 +216,14 @@ public:
     return Mv(tarMvPred.hor - hor + curMvPred.hor, tarMvPred.ver - ver + curMvPred.ver);
   }
 #endif
+
+#if JVET_M0145_AFFINE_MV_CLIP
+  void clipToStorageBitDepth()
+  {
+    hor = Clip3( -(1 << 17), (1 << 17) - 1, hor );
+    ver = Clip3( -(1 << 17), (1 << 17) - 1, ver );
+  }
+#endif
 };// END CLASS DEFINITION MV
 
 namespace std
@@ -226,7 +237,7 @@ namespace std
     }
   };
 };
-void clipMv ( Mv& rcMv, const struct Position& pos, 
+void clipMv ( Mv& rcMv, const struct Position& pos,
               const struct Size& size,
               const class SPS& sps );
 
diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index 4c96307cb2196d52f9886c1189987f91d09c69c8..2b8f46593b255789956d72dac002c75ba4d659a0 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -742,11 +742,17 @@ void Picture::create(const ChromaFormat &_chromaFormat, const Size &size, const
   if( !_decoder )
   {
     M_BUFS( 0, PIC_ORIGINAL ).    create( _chromaFormat, a );
+#if JVET_M0427_INLOOP_RESHAPER
+    M_BUFS( 0, PIC_TRUE_ORIGINAL ). create( _chromaFormat, a );
+#endif
   }
 #if !KEEP_PRED_AND_RESI_SIGNALS
 
   m_ctuArea = UnitArea( _chromaFormat, Area( Position{ 0, 0 }, Size( _maxCUSize, _maxCUSize ) ) );
 #endif
+#if JVET_M0253_HASH_ME
+  m_hashMap.clearAll();
+#endif
 }
 
 void Picture::destroy()
@@ -762,7 +768,9 @@ void Picture::destroy()
   {
     M_BUFS( jId, t ).destroy();
   }
-
+#if JVET_M0253_HASH_ME
+  m_hashMap.clearAll();
+#endif
   if( cs )
   {
     cs->destroy();
@@ -846,6 +854,14 @@ const CPelUnitBuf Picture::getOrigBuf(const UnitArea &unit) const { return getBu
        PelUnitBuf Picture::getOrigBuf()                           { return M_BUFS(0,    PIC_ORIGINAL); }
 const CPelUnitBuf Picture::getOrigBuf()                     const { return M_BUFS(0,    PIC_ORIGINAL); }
 
+#if JVET_M0427_INLOOP_RESHAPER
+       PelBuf     Picture::getOrigBuf(const ComponentID compID)       { return getBuf(compID, PIC_ORIGINAL); }
+const CPelBuf     Picture::getOrigBuf(const ComponentID compID) const { return getBuf(compID, PIC_ORIGINAL); }
+       PelUnitBuf Picture::getTrueOrigBuf()                           { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
+const CPelUnitBuf Picture::getTrueOrigBuf()                     const { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
+       PelBuf     Picture::getTrueOrigBuf(const CompArea &blk)        { return getBuf(blk, PIC_TRUE_ORIGINAL); }
+const CPelBuf     Picture::getTrueOrigBuf(const CompArea &blk)  const { return getBuf(blk, PIC_TRUE_ORIGINAL); }
+#endif
        PelBuf     Picture::getPredBuf(const CompArea &blk)        { return getBuf(blk,  PIC_PREDICTION); }
 const CPelBuf     Picture::getPredBuf(const CompArea &blk)  const { return getBuf(blk,  PIC_PREDICTION); }
        PelUnitBuf Picture::getPredBuf(const UnitArea &unit)       { return getBuf(unit, PIC_PREDICTION); }
@@ -1011,7 +1027,7 @@ void Picture::extendPicBorder()
       {
         for (int x = 0; x < xmargin; x++ )
         {
-          pi[ -xmargin + x ] = pi[ -xmargin + x + xoffset ];
+          pi[ -x - 1       ] = pi[ -x - 1       + xoffset ];
           pi[  p.width + x ] = pi[  p.width + x - xoffset ];
         }
         pi += p.stride;
@@ -1162,3 +1178,64 @@ bool Picture::getSpliceFull()
     return false;
   return true;
 }
+
+#if JVET_M0253_HASH_ME
+void Picture::addPictureToHashMapForInter()
+{
+  int picWidth = slices[0]->getSPS()->getPicWidthInLumaSamples();
+  int picHeight = slices[0]->getSPS()->getPicHeightInLumaSamples();
+  uint32_t* blockHashValues[2][2];
+  bool* bIsBlockSame[2][3];
+
+  for (int i = 0; i < 2; i++)
+  {
+    for (int j = 0; j < 2; j++)
+    {
+      blockHashValues[i][j] = new uint32_t[picWidth*picHeight];
+    }
+
+    for (int j = 0; j < 3; j++)
+    {
+      bIsBlockSame[i][j] = new bool[picWidth*picHeight];
+    }
+  }
+
+  m_hashMap.create();
+  m_hashMap.generateBlock2x2HashValue(getOrigBuf(), picWidth, picHeight, slices[0]->getSPS()->getBitDepths(), blockHashValues[0], bIsBlockSame[0]);//2x2
+  m_hashMap.generateBlockHashValue(picWidth, picHeight, 4, 4, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//4x4
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 4, 4);
+
+  m_hashMap.generateRectangleHashValue(picWidth, picHeight, 8, 4, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x4
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 4);
+
+  m_hashMap.generateRectangleHashValue(picWidth, picHeight, 4, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//4x8
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 4, 8);
+
+  m_hashMap.generateBlockHashValue(picWidth, picHeight, 8, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x8
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 8);
+
+  m_hashMap.generateBlockHashValue(picWidth, picHeight, 16, 16, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//16x16
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 16, 16);
+
+  m_hashMap.generateBlockHashValue(picWidth, picHeight, 32, 32, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//32x32
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 32, 32);
+
+  m_hashMap.generateBlockHashValue(picWidth, picHeight, 64, 64, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//64x64
+  m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 64, 64);
+
+  m_hashMap.setInitial();
+
+  for (int i = 0; i < 2; i++)
+  {
+    for (int j = 0; j < 2; j++)
+    {
+      delete[] blockHashValues[i][j];
+    }
+
+    for (int j = 0; j < 3; j++)
+    {
+      delete[] bIsBlockSame[i][j];
+    }
+  }
+}
+#endif
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 55756cdbed31462ec6fae7c98e966efb9c0b34b1..d939de1ac90e6847606f4c733dcfaba38e3cd3fc 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -46,7 +46,9 @@
 #include "Unit.h"
 #include "Slice.h"
 #include "CodingStructure.h"
-
+#if JVET_M0253_HASH_ME
+#include "Hash.h"
+#endif
 #include <deque>
 
 #if ENABLE_WPP_PARALLELISM || ENABLE_SPLIT_PARALLELISM
@@ -192,6 +194,14 @@ struct Picture : public UnitArea
   const CPelUnitBuf getOrigBuf(const UnitArea &unit) const;
          PelUnitBuf getOrigBuf();
   const CPelUnitBuf getOrigBuf() const;
+#if JVET_M0427_INLOOP_RESHAPER
+         PelBuf     getOrigBuf(const ComponentID compID);
+  const CPelBuf     getOrigBuf(const ComponentID compID) const;
+         PelUnitBuf getTrueOrigBuf();
+  const CPelUnitBuf getTrueOrigBuf() const;
+        PelBuf      getTrueOrigBuf(const CompArea &blk);
+  const CPelBuf     getTrueOrigBuf(const CompArea &blk) const;
+#endif
 
          PelBuf     getPredBuf(const CompArea &blk);
   const CPelBuf     getPredBuf(const CompArea &blk) const;
@@ -259,6 +269,13 @@ public:
   PelStorage m_bufs[NUM_PIC_TYPES];
 #endif
 
+#if JVET_M0253_HASH_ME
+  TComHash           m_hashMap;
+  TComHash*          getHashMap() { return &m_hashMap; }
+  const TComHash*    getHashMap() const { return &m_hashMap; }
+  void               addPictureToHashMapForInter();
+#endif
+
   CodingStructure*   cs;
   std::deque<Slice*> slices;
   SEIMessages        SEIs;
diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp
index ca477139b28c97e7342b3cae0b7c14d1494355ac..5829874da0427ff5d161ab7062b18d7b193aeabb 100644
--- a/source/Lib/CommonLib/Quant.cpp
+++ b/source/Lib/CommonLib/Quant.cpp
@@ -313,8 +313,13 @@ void Quant::dequant(const TransformUnit &tu,
   const int QP_rem = cQP.rem;
 
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  const bool needsScalingCorrection = TU::needsBlockSizeTrafoScale( tu, compID );
+  const int  NEScale    = TU::needsSqrt2Scale( tu, compID ) ? 181 : 1;
+#else
   const bool needsScalingCorrection = TU::needsBlockSizeTrafoScale( tu.block( compID ) );
   const int  NEScale    = TU::needsSqrt2Scale( tu.blocks[compID] ) ? 181 : 1;
+#endif
 #if HEVC_USE_SCALING_LISTS
   const int  rightShift = (needsScalingCorrection ?   8 : 0 ) + (IQUANT_SHIFT - (iTransformShift + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0);
 #else
@@ -767,7 +772,11 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf
 
     int iWHScale = 1;
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+    if( TU::needsBlockSizeTrafoScale( tu, compID ) )
+#else
     if( TU::needsBlockSizeTrafoScale( rect ) )
+#endif
     {
       iTransformShift += ADJ_QUANT_SHIFT;
       iWHScale = 181;
@@ -863,7 +872,11 @@ bool Quant::xNeedRDOQ(TransformUnit &tu, const ComponentID &compID, const CCoeff
 
   int iWHScale = 1;
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  if( TU::needsBlockSizeTrafoScale( tu, compID ) )
+#else
   if( TU::needsBlockSizeTrafoScale( rect ) )
+#endif
   {
     iTransformShift += ADJ_QUANT_SHIFT;
     iWHScale = 181;
diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp
index bcf25fe5fd2006cf085f2430ca6b3add0080e613..2682f558a107fa6ee7aa9a3f62208548c35a9521 100644
--- a/source/Lib/CommonLib/QuantRDOQ.cpp
+++ b/source/Lib/CommonLib/QuantRDOQ.cpp
@@ -149,7 +149,12 @@ inline uint32_t QuantRDOQ::xGetCodedLevel( double&            rd64CodedCost,
   for( int uiAbsLevel  = uiMaxAbsLevel; uiAbsLevel >= uiMinAbsLevel ; uiAbsLevel-- )
   {
     double dErr         = double( lLevelDouble  - ( Intermediate_Int(uiAbsLevel) << iQBits ) );
+
+#if JVET_M0470
+    double dCurrCost    = dErr * dErr * errorScale + xGetICost( xGetICRate( uiAbsLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, ui16AbsGoRice, true, maxLog2TrDynamicRange ) );
+#else
     double dCurrCost    = dErr * dErr * errorScale + xGetICost( xGetICRate( uiAbsLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, ui16AbsGoRice, useLimitedPrefixLength, maxLog2TrDynamicRange ) );
+#endif
     dCurrCost          += dCurrCostSig;
 
     if( dCurrCost < rd64CodedCost )
@@ -194,7 +199,11 @@ inline int QuantRDOQ::xGetICRate( const uint32_t         uiAbsLevel,
     int       iRate   = int( xGetIEPRate() ); // cost of sign bit
     uint32_t  symbol  = ( uiAbsLevel == 0 ? goRiceZero : uiAbsLevel <= goRiceZero ? uiAbsLevel-1 : uiAbsLevel );
     uint32_t  length;
+#if JVET_M0470
+    const int threshold = COEF_REMAIN_BIN_REDUCTION;
+#else
     const int threshold = g_auiGoRiceRange[ui16AbsGoRice];
+#endif
     if( symbol < ( threshold << ui16AbsGoRice ) )
     {
       length = symbol >> ui16AbsGoRice;
@@ -239,7 +248,11 @@ inline int QuantRDOQ::xGetICRate( const uint32_t         uiAbsLevel,
   {
     uint32_t symbol = ( uiAbsLevel - cthres ) >> 1;
     uint32_t length;
+#if JVET_M0470
+    const int threshold = COEF_REMAIN_BIN_REDUCTION;
+#else
     const int threshold = g_auiGoRiceRange[ui16AbsGoRice];
+#endif
     if( symbol < ( threshold << ui16AbsGoRice ) )
     {
       length = symbol >> ui16AbsGoRice;
@@ -395,15 +408,21 @@ void QuantRDOQ::setScalingList(ScalingList *scalingList, const int maxLog2TrDyna
 #endif
 #else
 
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+double QuantRDOQ::xGetErrScaleCoeff( const bool needsSqrt2, SizeType width, SizeType height, int qp, const int maxLog2TrDynamicRange, const int channelBitDepth )
+#else
 double QuantRDOQ::xGetErrScaleCoeff( SizeType width, SizeType height, int qp, const int maxLog2TrDynamicRange, const int channelBitDepth )
+#endif
 {
   const int iTransformShift = getTransformShift(channelBitDepth, Size(width, height), maxLog2TrDynamicRange);
 #if HM_QTBT_AS_IN_JEM_QUANT
   double    dErrScale       = (double)( 1 << SCALE_BITS );                                // Compensate for scaling of bitcount in Lagrange cost function
-  bool      needsSrqt2      = TU::needsBlockSizeTrafoScale( Size(width, height) );// ( ( (sizeX+sizeY) & 1 ) !=0 );
-  double    dTransShift     = (double)iTransformShift + ( needsSrqt2 ? -0.5 : 0.0 );
+#if !JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  bool      needsSqrt2      = TU::needsBlockSizeTrafoScale( Size(width, height) );// ( ( (sizeX+sizeY) & 1 ) !=0 );
+#endif
+  double    dTransShift     = (double)iTransformShift + ( needsSqrt2 ? -0.5 : 0.0 );
   dErrScale                 = dErrScale*pow( 2.0, ( -2.0*dTransShift ) );                     // Compensate for scaling through forward transform
-  int       QStep           = ( needsSrqt2 ? ( ( g_quantScales[qp] * 181 ) >> 7 ) : g_quantScales[qp] );
+  int       QStep           = ( needsSqrt2 ? ( ( g_quantScales[qp] * 181 ) >> 7 ) : g_quantScales[qp] );
   double    finalErrScale = dErrScale / QStep / QStep / (1 << (DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth) << 1));
 #else
   int errShift = SCALE_BITS - ((iTransformShift + DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth)) << 1);
@@ -441,8 +460,8 @@ void QuantRDOQ::xSetErrScaleCoeff( uint32_t list, uint32_t sizeX, uint32_t sizeY
 #if HM_QTBT_AS_IN_JEM_QUANT
   double dErrScale = (double)( 1 << SCALE_BITS );                                // Compensate for scaling of bitcount in Lagrange cost function
 
-  bool   needsSrqt2 = TU::needsBlockSizeTrafoScale( Size( g_scalingListSizeX[sizeX], g_scalingListSizeX[sizeY] ) );// ( ( (sizeX+sizeY) & 1 ) !=0 );
-  double dTransShift = (double)iTransformShift + ( needsSrqt2 ? -0.5 : 0.0 );
+  bool   needsSqrt2 = TU::needsBlockSizeTrafoScale( Size( g_scalingListSizeX[sizeX], g_scalingListSizeX[sizeY] ) );// ( ( (sizeX+sizeY) & 1 ) !=0 );
+  double dTransShift = (double)iTransformShift + ( needsSqrt2 ? -0.5 : 0.0 );
   dErrScale = dErrScale*pow( 2.0, ( -2.0*dTransShift ) );                     // Compensate for scaling through forward transform
 
   for( i = 0; i < uiMaxNumCoeff; i++ )
@@ -451,7 +470,7 @@ void QuantRDOQ::xSetErrScaleCoeff( uint32_t list, uint32_t sizeX, uint32_t sizeY
                     / (1 << (DISTORTION_PRECISION_ADJUSTMENT(bitDepths.recon[channelType]) << 1));
   }
 
-  int QStep = ( needsSrqt2 ? ( ( g_quantScales[qp] * 181 ) >> 7 ) : g_quantScales[qp] );
+  int QStep = ( needsSqrt2 ? ( ( g_quantScales[qp] * 181 ) >> 7 ) : g_quantScales[qp] );
 
   xGetErrScaleCoeffNoScalingList(list, sizeX, sizeY, qp) =
     dErrScale / QStep / QStep / (1 << (DISTORTION_PRECISION_ADJUSTMENT(bitDepths.recon[channelType]) << 1));
@@ -562,6 +581,9 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff
 
   bool useRDOQ = useTransformSkip ? m_useRDOQTS : m_useRDOQ;
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( !tu.cu->ispMode || !isLuma(compID) )
+#endif
   {
     useRDOQ &= uiWidth > 2;
     useRDOQ &= uiHeight > 2;
@@ -605,6 +627,9 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
   const bool extendedPrecision     = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
   const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(chType);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const bool useIntraSubPartitions = tu.cu->ispMode && isLuma(compID);
+#endif
   /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be
   * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the
   * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller)
@@ -669,8 +694,13 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
 
   const bool   enableScalingLists             = getUseScalingList(uiWidth, uiHeight, tu.transformSkip[compID]);
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  const int    defaultQuantisationCoefficient = ( TU::needsSqrt2Scale( rect, tu.transformSkip[compID] ) ? ( g_quantScales[cQP.rem] * 181 ) >> 7 : g_quantScales[cQP.rem] );
+  const double defaultErrorScale              = xGetErrScaleCoeffNoScalingList(scalingListType, (uiLog2BlockWidth-1), (uiLog2BlockHeight-1), cQP.rem);
+#else
   const int    defaultQuantisationCoefficient = ( TU::needsSqrt2Scale( rect ) ? ( g_quantScales[cQP.rem] * 181 ) >> 7 : g_quantScales[cQP.rem] );
   const double defaultErrorScale              = xGetErrScaleCoeffNoScalingList(scalingListType, (uiLog2BlockWidth-1), (uiLog2BlockHeight-1), cQP.rem);
+#endif
 #else
   const double blkErrScale                    = ( TU::needsQP3Offset( tu, compID ) ? 2.0 : 1.0 );
   const int    defaultQuantisationCoefficient = g_quantScales[cQP.rem];
@@ -678,8 +708,13 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
 #endif
 #else //HEVC_USE_SCALING_LISTS
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  const int    quantisationCoefficient = ( TU::needsSqrt2Scale( tu, compID ) ? ( g_quantScales[cQP.rem] * 181 ) >> 7 : g_quantScales[cQP.rem] );
+  const double errorScale              = xGetErrScaleCoeff( TU::needsSqrt2Scale( tu, compID ), uiWidth, uiHeight, cQP.rem, maxLog2TrDynamicRange, channelBitDepth );
+#else
   const int    quantisationCoefficient = ( TU::needsSqrt2Scale( rect ) ? ( g_quantScales[cQP.rem] * 181 ) >> 7 : g_quantScales[cQP.rem] );
   const double errorScale              = xGetErrScaleCoeff( uiWidth, uiHeight, cQP.rem, maxLog2TrDynamicRange, channelBitDepth );
+#endif
 #else
   const double blkErrScale             = ( TU::needsQP3Offset( tu, compID ) ? 2.0 : 1.0 );
   const int    quantisationCoefficient = g_quantScales[cQP.rem];
@@ -715,8 +750,11 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
 
   double *pdCostCoeffGroupSig = m_pdCostCoeffGroupSig;
   memset( pdCostCoeffGroupSig, 0, ( uiMaxNumCoeff >> cctx.log2CGSize() ) * sizeof( double ) );
-
+#if JVET_M0257
+  const int iCGNum = std::min<int>(JVET_C0024_ZERO_OUT_TH, uiWidth) * std::min<int>(JVET_C0024_ZERO_OUT_TH, uiHeight) >> cctx.log2CGSize();
+#else
   const int iCGNum  = uiWidth * uiHeight >> cctx.log2CGSize();
+#endif
   int iScanPos;
   coeffGroupRDStats rdStats;
 
@@ -998,10 +1036,49 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
   }
   else
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    bool previousCbf       = tu.cbf[COMPONENT_Cb];
+    bool lastCbfIsInferred = false;
+    if( useIntraSubPartitions )
+    {
+      bool rootCbfSoFar       = false;
+      bool isLastSubPartition = CU::isISPLast(*tu.cu, tu.Y(), compID);
+      uint32_t nTus = tu.cu->ispMode == HOR_INTRA_SUBPARTITIONS ? tu.cu->lheight() >> g_aucLog2[tu.lheight()] : tu.cu->lwidth() >> g_aucLog2[tu.lwidth()];
+      if( isLastSubPartition )
+      {
+        TransformUnit* tuPointer = tu.cu->firstTU;
+        for( int tuIdx = 0; tuIdx < nTus - 1; tuIdx++ )
+        {
+          rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMPONENT_Y, tu.depth);
+          tuPointer     = tuPointer->next;
+        }
+        if( !rootCbfSoFar )
+        {
+          lastCbfIsInferred = true;
+        }
+      }
+      if( !lastCbfIsInferred )
+      {
+        previousCbf = TU::getPrevTuCbfAtDepth(tu, compID, tu.depth);
+      }
+    }
+    BinFracBits fracBitsQtCbf = fracBits.getFracBitsArray( Ctx::QtCbf[compID]( DeriveCtx::CtxQtCbf( rect.compID, tu.depth, previousCbf, useIntraSubPartitions ) ) );
+
+    if( !lastCbfIsInferred )
+    {
+      d64BestCost  = d64BlockUncodedCost + xGetICost(fracBitsQtCbf.intBits[0]);
+      d64BaseCost += xGetICost(fracBitsQtCbf.intBits[1]);
+    }
+    else
+    {
+      d64BestCost  = d64BlockUncodedCost;
+    }
+#else
     BinFracBits fracBitsQtCbf = fracBits.getFracBitsArray( Ctx::QtCbf[compID]( DeriveCtx::CtxQtCbf( rect.compID, tu.depth, tu.cbf[COMPONENT_Cb] ) ) );
 
     d64BestCost  = d64BlockUncodedCost + xGetICost( fracBitsQtCbf.intBits[0] );
     d64BaseCost += xGetICost( fracBitsQtCbf.intBits[1] );
+#endif
   }
 
   int lastBitsX[LAST_SIGNIFICANT_GROUPS] = { 0 };
@@ -1010,9 +1087,14 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
 #if HEVC_USE_MDCS
     int dim1  = ( cctx.scanType() == SCAN_VER ? uiHeight : uiWidth  );
     int dim2  = ( cctx.scanType() == SCAN_VER ? uiWidth  : uiHeight );
+#else
+#if JVET_M0257
+    int dim1 = std::min<int>(JVET_C0024_ZERO_OUT_TH, uiWidth);
+    int dim2 = std::min<int>(JVET_C0024_ZERO_OUT_TH, uiHeight);
 #else
     int dim1  = uiWidth;
     int dim2  = uiHeight;
+#endif
 #endif
     int bitsX = 0;
     int bitsY = 0;
@@ -1123,8 +1205,11 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
     int lastCG = -1;
     int absSum = 0 ;
     int n ;
-
+#if JVET_M0257
+    for (int subSet = iCGNum - 1; subSet >= 0; subSet--)
+#else
     for( int subSet = (uiWidth*uiHeight-1) >> cctx.log2CGSize(); subSet >= 0; subSet-- )
+#endif
     {
       int  subPos         = subSet << cctx.log2CGSize();
       int  firstNZPosInCG = iCGSizeM1 + 1, lastNZPosInCG = -1;
diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h
index c29ab0eca4792cd0bd3c13723977a52eb201a6b1..037fab4d7d5ec44646ebca62be1b018f5bef5bb0 100644
--- a/source/Lib/CommonLib/QuantRDOQ.h
+++ b/source/Lib/CommonLib/QuantRDOQ.h
@@ -75,8 +75,12 @@ private:
   void    xInitScalingList               ( const QuantRDOQ* other );
   void    xDestroyScalingList            ();
   void    xSetErrScaleCoeff              ( uint32_t list, uint32_t sizeX, uint32_t sizeY, int qp, const int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths );
+#else
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  double  xGetErrScaleCoeff              ( const bool needsSqrt2, SizeType width, SizeType height, int qp, const int maxLog2TrDynamicRange, const int channelBitDepth);
 #else
   double  xGetErrScaleCoeff              ( SizeType width, SizeType height, int qp, const int maxLog2TrDynamicRange, const int channelBitDepth);
+#endif
 #endif
 
   // RDOQ functions
diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp
index 78fbcf0f3d0550abd734db1e1347cdc3a14e8b4d..8bbf4b992a25e657ddc653132bee431cfeb63b42 100644
--- a/source/Lib/CommonLib/RdCost.cpp
+++ b/source/Lib/CommonLib/RdCost.cpp
@@ -152,7 +152,7 @@ void RdCost::init()
   m_afpDistortFunc[DF_SAD_FULL_NBIT32 ] = RdCost::xGetSAD_full;
   m_afpDistortFunc[DF_SAD_FULL_NBIT64 ] = RdCost::xGetSAD_full;
   m_afpDistortFunc[DF_SAD_FULL_NBIT16N] = RdCost::xGetSAD_full;
-  
+
 #if WCG_EXT
   m_afpDistortFunc[DF_SSE_WTD   ] = RdCost::xGetSSE_WTD;
   m_afpDistortFunc[DF_SSE2_WTD  ] = RdCost::xGetSSE2_WTD;
@@ -176,6 +176,11 @@ void RdCost::init()
 
   m_motionLambda               = 0;
   m_iCostScale                 = 0;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_signalType                 = RESHAPE_SIGNAL_NULL;
+  m_chromaWeight               = 1.0;
+  m_lumaBD                     = 10;
+#endif
 }
 
 
@@ -331,12 +336,16 @@ void RdCost::setDistParam( DistParam &rcDP, const Pel* pOrg, const Pel* piRefY,
   rcDP.cur.stride = iRefStride;
   rcDP.cur.width  = width;
   rcDP.cur.height = height;
-
+#if JVET_M0147_DMVR
+  rcDP.subShift = subShiftMode;
+#endif
   rcDP.step       = step;
   rcDP.maximumDistortionForEarlyExit = std::numeric_limits<Distortion>::max();
-
+#if JVET_M0147_DMVR
+  CHECK( useHadamard || rcDP.useMR, "only used in xDMVRCost with these default parameters (so far...)" );
+#else
   CHECK( useHadamard || rcDP.useMR || subShiftMode > 0, "only used in xDirectMCCost with these default parameters (so far...)" );
-
+#endif
   if ( bioApplied )
   {
     rcDP.distFunc = m_afpDistortFunc[ DF_SAD_INTERMEDIATE_BITDEPTH ];
@@ -2858,7 +2867,15 @@ Distortion RdCost::xGetHADs( const DistParam &rcDtParam )
 
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+uint32_t   RdCost::m_signalType;
+double     RdCost::m_chromaWeight;
+int        RdCost::m_lumaBD;
+std::vector<double> RdCost::m_reshapeLumaLevelToWeightPLUT;
+std::vector<double> RdCost::m_lumaLevelToWeightPLUT;
+#else
 double RdCost::m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+#endif
 
 void RdCost::saveUnadjustedLambda()
 {
@@ -2883,15 +2900,97 @@ void RdCost::initLumaLevelToWeightTable()
     else
 */
     { // set SDR weight table
-      y = 0.015*x - 1.5 - 6;   // this is the Equation used to derive the luma qp LUT for HDR in MPEG HDR anchor3.2 (JCTCX-X1020) 
+      y = 0.015*x - 1.5 - 6;   // this is the Equation used to derive the luma qp LUT for HDR in MPEG HDR anchor3.2 (JCTCX-X1020)
       y = y<-3 ? -3 : (y>6 ? 6 : y);
     }
-    
-    m_lumaLevelToWeightPLUT[i] = pow(2.0, y / 3.0);      // or power(10, dQp/10)      they are almost equal       
+
+    m_lumaLevelToWeightPLUT[i] = pow(2.0, y / 3.0);      // or power(10, dQp/10)      they are almost equal
+  }
+}
+
+#if JVET_M0427_INLOOP_RESHAPER
+void RdCost::initLumaLevelToWeightTableReshape()
+{
+  int lutSize = 1 << m_lumaBD;
+  if (m_reshapeLumaLevelToWeightPLUT.empty())
+    m_reshapeLumaLevelToWeightPLUT.resize(lutSize, 1.0);
+  if (m_lumaLevelToWeightPLUT.empty())
+    m_lumaLevelToWeightPLUT.resize(lutSize, 1.0);
+  if (m_signalType == RESHAPE_SIGNAL_PQ)
+  {
+    for (int i = 0; i < (1 << m_lumaBD); i++)
+    {
+      double x = m_lumaBD < 10 ? i << (10 - m_lumaBD) : m_lumaBD > 10 ? i >> (m_lumaBD - 10) : i;
+      double y;
+      y = 0.015*x - 1.5 - 6;
+      y = y < -3 ? -3 : (y > 6 ? 6 : y);
+      m_reshapeLumaLevelToWeightPLUT[i] = pow(2.0, y / 3.0);
+      m_lumaLevelToWeightPLUT[i] = m_reshapeLumaLevelToWeightPLUT[i];
+    }
+  }
+}
+
+void RdCost::updateReshapeLumaLevelToWeightTableChromaMD(std::vector<Pel>& ILUT)
+{
+  for (int i = 0; i < (1 << m_lumaBD); i++)
+  {
+    m_reshapeLumaLevelToWeightPLUT[i] = m_lumaLevelToWeightPLUT[ILUT[i]];
+  }
+}
+
+void RdCost::restoreReshapeLumaLevelToWeightTable()
+{
+  for (int i = 0; i < (1 << m_lumaBD); i++)
+  {
+    m_reshapeLumaLevelToWeightPLUT.at(i) = m_lumaLevelToWeightPLUT.at(i);
   }
 }
 
-Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, const uint32_t uiShift, const Pel orgLuma) 
+void RdCost::updateReshapeLumaLevelToWeightTable(SliceReshapeInfo &sliceReshape, Pel *wtTable, double cwt)
+{
+  if (m_signalType == RESHAPE_SIGNAL_SDR)
+  {
+    if (sliceReshape.getSliceReshapeModelPresentFlag())
+    {
+      double wBin = 1.0;
+      double weight = 1.0;
+      int histLens = (1 << m_lumaBD) / PIC_CODE_CW_BINS;
+
+      for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+      {
+        if ((i < sliceReshape.reshaperModelMinBinIdx) || (i > sliceReshape.reshaperModelMaxBinIdx))
+          weight = 1.0;
+        else
+        {
+          if (sliceReshape.reshaperModelBinCWDelta[i] == 1 || (sliceReshape.reshaperModelBinCWDelta[i] == -1 * histLens))
+            weight = wBin;
+          else
+          {
+            weight = (double)wtTable[i] / (double)histLens;
+            weight = weight*weight;
+          }
+        }
+        for (int j = 0; j < histLens; j++)
+        {
+          int ii = i*histLens + j;
+          m_reshapeLumaLevelToWeightPLUT[ii] = weight;
+        }
+      }
+      m_chromaWeight = cwt;
+    }
+    else
+    {
+      THROW("updateReshapeLumaLevelToWeightTable ERROR!!");
+    }
+  }
+  else
+  {
+    THROW("updateReshapeLumaLevelToWeightTable not support other signal types!!");
+  }
+}
+#endif
+
+Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, const uint32_t uiShift, const Pel orgLuma)
 {
   Distortion distortionVal = 0;
   Intermediate_Int iTemp = org - cur;
@@ -2902,8 +3001,32 @@ Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, con
      CHECK(org!=orgLuma, "");
   }
   // use luma to get weight
+#if JVET_M0427_INLOOP_RESHAPER
+  double weight = 1.0;
+  if (m_signalType == RESHAPE_SIGNAL_SDR)
+  {
+    if (compIdx == COMPONENT_Y)
+    {
+      weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
+    }
+    else
+    {
+      weight = m_chromaWeight;
+    }
+  }
+  else
+  {
+    weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
+  }
+#else
   double weight = m_lumaLevelToWeightPLUT[orgLuma];
+#endif
+#if JVET_M0427_INLOOP_RESHAPER // FIXED_PT_WD_CALCULATION
+  int64_t fixedPTweight = (int64_t)(weight * (double)(1 << 16));
+  Intermediate_Int mse = Intermediate_Int((fixedPTweight*(iTemp*iTemp) + (1 << 15)) >> 16);
+#else
   Intermediate_Int mse = Intermediate_Int(weight*(double)iTemp*(double)iTemp+0.5);
+#endif
   distortionVal = Distortion( mse >> uiShift);
   return distortionVal;
 }
@@ -2930,7 +3053,7 @@ Distortion RdCost::xGetSSE_WTD( const DistParam &rcDtParam )
   {
     for (int n = 0; n < iCols; n++ )
     {
-      uiSum += getWeightedMSE(rcDtParam.compID, piOrg[n  ], piCur[n  ], uiShift, piOrgLuma[n<<cShift]); 
+      uiSum += getWeightedMSE(rcDtParam.compID, piOrg[n  ], piCur[n  ], uiShift, piOrgLuma[n<<cShift]);
     }
     piOrg += iStrideOrg;
     piCur += iStrideCur;
@@ -2946,7 +3069,7 @@ Distortion RdCost::xGetSSE2_WTD( const DistParam &rcDtParam )
     CHECK( rcDtParam.org.width != 2, "" );
     return RdCostWeightPrediction::xGetSSEw( rcDtParam ); // ignore it for now
   }
-  
+
   int  iRows = rcDtParam.org.height;
   const Pel* piOrg = rcDtParam.org.buf;
   const Pel* piCur = rcDtParam.cur.buf;
@@ -3015,7 +3138,7 @@ Distortion RdCost::xGetSSE8_WTD( const DistParam &rcDtParam )
   const Pel* piOrgLuma        = rcDtParam.orgLuma.buf;
   const size_t  iStrideOrgLuma   = rcDtParam.orgLuma.stride;
   const size_t  cShift           = (rcDtParam.compID==COMPONENT_Y) ? 0 : 1; // assume 420, could use getComponentScaleX, getComponentScaleY
- 
+
   Distortion uiSum   = 0;
   uint32_t uiShift = DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth) << 1;
   for( ; iRows != 0; iRows-- )
@@ -3050,7 +3173,7 @@ Distortion RdCost::xGetSSE16_WTD( const DistParam &rcDtParam )
   const Pel* piOrgLuma        = rcDtParam.orgLuma.buf;
   const size_t  iStrideOrgLuma   = rcDtParam.orgLuma.stride;
   const size_t  cShift           = (rcDtParam.compID==COMPONENT_Y) ? 0 : 1; // assume 420, could use getComponentScaleX, getComponentScaleY
-  
+
   Distortion uiSum   = 0;
   uint32_t uiShift = DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth) << 1;
   for( ; iRows != 0; iRows-- )
@@ -3138,7 +3261,7 @@ Distortion RdCost::xGetSSE32_WTD( const DistParam &rcDtParam )
   const Pel* piOrgLuma        = rcDtParam.orgLuma.buf;
   const size_t  iStrideOrgLuma   = rcDtParam.orgLuma.stride;
   const size_t  cShift           = (rcDtParam.compID==COMPONENT_Y) ? 0 : 1; // assume 420, could use getComponentScaleX, getComponentScaleY
-  
+
   Distortion uiSum   = 0;
   uint32_t uiShift = DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth) << 1;
   for( ; iRows != 0; iRows-- )
@@ -3197,7 +3320,7 @@ Distortion RdCost::xGetSSE64_WTD( const DistParam &rcDtParam )
   const Pel* piOrgLuma        = rcDtParam.orgLuma.buf;
   const size_t iStrideOrgLuma   = rcDtParam.orgLuma.stride;
   const size_t cShift           = (rcDtParam.compID==COMPONENT_Y) ? 0 : 1; // assume 420, could use getComponentScaleX, getComponentScaleY
- 
+
   Distortion uiSum   = 0;
   uint32_t uiShift = DISTORTION_PRECISION_ADJUSTMENT((rcDtParam.bitDepth)) << 1;
   for( ; iRows != 0; iRows-- )
diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h
index ead8fd5cb20aa52963c84a7c55dc6f1f34f1b880..28c75f6fa3d31700bba2fc0c5dc9828778158a37 100644
--- a/source/Lib/CommonLib/RdCost.h
+++ b/source/Lib/CommonLib/RdCost.h
@@ -107,7 +107,15 @@ private:
 #if WCG_EXT
   double                  m_dLambda_unadjusted; // TODO: check is necessary
   double                  m_DistScaleUnadjusted;
+#if JVET_M0427_INLOOP_RESHAPER
+  static std::vector<double> m_reshapeLumaLevelToWeightPLUT;
+  static std::vector<double> m_lumaLevelToWeightPLUT;
+  static uint32_t         m_signalType;
+  static double           m_chromaWeight;
+  static int              m_lumaBD;
+#else
   static double           m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+#endif
 #endif
   double                  m_DistScale;
   double                  m_dLambdaMotionSAD[2 /* 0=standard, 1=for transquant bypass when mixed-lossless cost evaluation enabled*/];
@@ -290,6 +298,15 @@ public:
          void    saveUnadjustedLambda       ();
          void    initLumaLevelToWeightTable ();
   inline double  getWPSNRLumaLevelWeight    (int val) { return m_lumaLevelToWeightPLUT[val]; }
+#if JVET_M0427_INLOOP_RESHAPER
+  void           initLumaLevelToWeightTableReshape();
+  void           updateReshapeLumaLevelToWeightTableChromaMD (std::vector<Pel>& ILUT);
+  void           restoreReshapeLumaLevelToWeightTable        ();
+  inline double  getWPSNRReshapeLumaLevelWeight              (int val)                   { return m_reshapeLumaLevelToWeightPLUT[val]; }
+  void           setReshapeInfo                              (uint32_t type, int lumaBD) { m_signalType = type; m_lumaBD = lumaBD; }
+  void           updateReshapeLumaLevelToWeightTable         (SliceReshapeInfo &sliceReshape, Pel *wtTable, double cwt);
+  inline std::vector<double>& getLumaLevelWeightTable        ()                   { return m_lumaLevelToWeightPLUT; }
+#endif
 #endif
 
 private:
diff --git a/source/Lib/CommonLib/Reshape.cpp b/source/Lib/CommonLib/Reshape.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31ecca8b14b72d205614072509df2d0857c204e0
--- /dev/null
+++ b/source/Lib/CommonLib/Reshape.cpp
@@ -0,0 +1,235 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, 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.
+*/
+
+/** \file     Reshape.cpp
+    \brief    common reshaper class
+*/
+#include "Reshape.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#if JVET_M0427_INLOOP_RESHAPER
+ //! \ingroup CommonLib
+ //! \{
+
+ // ====================================================================================================================
+ // Constructor / destructor / create / destroy
+ // ====================================================================================================================
+
+Reshape::Reshape()
+{
+  m_CTUFlag = false;
+  m_recReshaped = false;
+  m_reshape = true;
+}
+
+Reshape::~Reshape()
+{
+}
+
+void  Reshape::createDec(int bitDepth)
+{
+  m_lumaBD = bitDepth;
+  m_reshapeLUTSize = 1 << m_lumaBD;
+  m_initCW = m_reshapeLUTSize / PIC_CODE_CW_BINS;
+  if (m_fwdLUT.empty())
+    m_fwdLUT.resize(m_reshapeLUTSize, 0);
+  if (m_invLUT.empty())
+    m_invLUT.resize(m_reshapeLUTSize, 0);
+  if (m_binCW.empty())
+    m_binCW.resize(PIC_CODE_CW_BINS, 0);
+  if (m_reshapePivot.empty())
+    m_reshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (m_chromaAdjHelpLUT.empty())
+    m_chromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 1<<CSCALE_FP_PREC);
+}
+
+void  Reshape::destroy()
+{
+}
+
+/**
+-Perform inverse of a one dimension LUT
+\param   InputLUT  describing the input LUT
+\retval  OutputLUT describing the inversed LUT of InputLUT
+\param   lut_size  size of LUT in number of samples
+*/
+void Reshape::reverseLUT(std::vector<Pel>& inputLUT, std::vector<Pel>& outputLUT, uint16_t lutSize)
+{
+  int i, j;
+  outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]] = m_sliceReshapeInfo.reshaperModelMinBinIdx*m_initCW;
+  for (i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
+  {
+    int16_t X1 = m_reshapePivot[i];
+    int16_t X2 = m_reshapePivot[i + 1];
+    outputLUT[X2] = (i + 1)*m_initCW;
+    int16_t Y1 = outputLUT[X1];
+    int16_t Y2 = outputLUT[X2];
+
+    if (X2 !=X1)
+    {
+      int32_t scale = (int32_t)(Y2 - Y1) * (1 << FP_PREC) / (int32_t)(X2 - X1);
+      for (j = X1 + 1; j < X2; j++)
+      {
+        outputLUT[j] = (Pel)((scale*(int32_t)(j - X1) + (1 << (FP_PREC - 1))) >> FP_PREC) + Y1;
+      }
+    }
+  }
+
+  for (i = 0; i < m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]; i++)
+    outputLUT[i] = outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]];
+  for (i = m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1]; i < m_reshapeLUTSize; i++)
+    outputLUT[i] = outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1]];
+
+  bool clipRange = ((m_sliceReshapeInfo.reshaperModelMinBinIdx > 0) && (m_sliceReshapeInfo.reshaperModelMaxBinIdx < (PIC_CODE_CW_BINS - 1)));
+  for (i = 0; i < lutSize; i++)
+  {
+    if (clipRange) outputLUT[i] = Clip3((Pel)(16<<(m_lumaBD-8)), (Pel)(235<<(m_lumaBD-8)), outputLUT[i]);
+    else           outputLUT[i] = Clip3((Pel)0, (Pel)((1<<m_lumaBD)-1), outputLUT[i]);
+  }
+}
+
+
+/** compute chroma residuce scale for TU
+* \param average luma pred of TU
+* \return chroma residue scale
+*/
+int  Reshape::calculateChromaAdj(Pel avgLuma)
+{
+  int lumaIdx = Clip3<int>(0, (1<<m_lumaBD) - 1, avgLuma);
+  int iAdj = m_chromaAdjHelpLUT[getPWLIdxInv(lumaIdx)];
+  return(iAdj);
+}
+
+
+/** find inx of PWL for inverse mapping
+* \param average luma pred of TU
+* \return idx of PWL for inverse mapping
+*/
+int Reshape::getPWLIdxInv(int lumaVal)
+{
+  int idxS = 0;
+  if (lumaVal < m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx + 1])
+    return m_sliceReshapeInfo.reshaperModelMinBinIdx;
+  else if (lumaVal >= m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx])
+    return m_sliceReshapeInfo.reshaperModelMaxBinIdx;
+  else
+  {
+    for (idxS = m_sliceReshapeInfo.reshaperModelMinBinIdx; (idxS < m_sliceReshapeInfo.reshaperModelMaxBinIdx); idxS++)
+    {
+      if (lumaVal < m_reshapePivot[idxS + 1])     break;
+    }
+    return idxS;
+  }
+}
+
+/**
+-copy Slice reshaper info structure
+\param   tInfo describing the target Slice reshaper info structure
+\param   sInfo describing the source Slice reshaper info structure
+*/
+void Reshape::copySliceReshaperInfo(SliceReshapeInfo& tInfo, SliceReshapeInfo& sInfo)
+{
+  tInfo.sliceReshaperModelPresentFlag = sInfo.sliceReshaperModelPresentFlag;
+  if (sInfo.sliceReshaperModelPresentFlag)
+  {
+    tInfo.reshaperModelMaxBinIdx = sInfo.reshaperModelMaxBinIdx;
+    tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx;
+    memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS));
+    tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW;
+  }
+  tInfo.sliceReshaperEnableFlag = sInfo.sliceReshaperEnableFlag;
+  if (sInfo.sliceReshaperEnableFlag)
+    tInfo.enableChromaAdj = sInfo.enableChromaAdj;
+  else
+    tInfo.enableChromaAdj = 0;
+}
+
+/** Construct reshaper from syntax
+* \param void
+* \return void
+*/
+void Reshape::constructReshaper()
+{
+  int pwlFwdLUTsize = PIC_CODE_CW_BINS;
+  int pwlFwdBinLen = m_reshapeLUTSize / PIC_CODE_CW_BINS;
+
+  for (int i = 0; i < m_sliceReshapeInfo.reshaperModelMinBinIdx; i++)
+    m_binCW[i] = 0;
+  for (int i = m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1; i < PIC_CODE_CW_BINS; i++)
+    m_binCW[i] = 0;
+  for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
+    m_binCW[i] = (uint16_t)(m_sliceReshapeInfo.reshaperModelBinCWDelta[i] + (int)m_initCW);
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_reshapePivot[i + 1] = m_reshapePivot[i] + m_binCW[i];
+    int16_t Y1 = m_reshapePivot[i];
+    int16_t Y2 = m_reshapePivot[i + 1];
+
+    m_fwdLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
+
+    int log2PwlFwdBinLen = g_aucLog2[pwlFwdBinLen];
+
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2PwlFwdBinLen - 1))) >> (log2PwlFwdBinLen);
+    for (int j = 1; j < pwlFwdBinLen; j++)
+    {
+      int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      m_fwdLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)tempVal);
+    }
+  }
+  reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
+  updateChromaScaleLUT();
+}
+
+/** generate chroma residue scaling LUT
+* \param void
+* \return void
+*/
+void Reshape::updateChromaScaleLUT()
+{
+  const int16_t  CW_bin_SC_LUT[2 * PIC_ANALYZE_CW_BINS] = { 16384, 16384, 16384, 16384, 16384, 16384, 16384, 8192, 8192, 8192, 8192, 5461, 5461, 5461, 5461, 4096, 4096, 4096, 4096, 3277, 3277, 3277, 3277, 2731, 2731, 2731, 2731, 2341, 2341, 2341, 2048, 2048, 2048, 1820, 1820, 1820, 1638, 1638, 1638, 1638, 1489, 1489, 1489, 1489, 1365, 1365, 1365, 1365, 1260, 1260, 1260, 1260, 1170, 1170, 1170, 1170, 1092, 1092, 1092, 1092, 1024, 1024, 1024, 1024 }; //p=11
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    uint16_t binCW = m_lumaBD > 10 ? (m_binCW[i] >> (m_lumaBD - 10)) : m_lumaBD < 10 ? (m_binCW[i] << (10 -m_lumaBD)): m_binCW[i];
+    if ((i < m_sliceReshapeInfo.reshaperModelMinBinIdx) || (i > m_sliceReshapeInfo.reshaperModelMaxBinIdx))
+      m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
+    else
+      m_chromaAdjHelpLUT[i] = CW_bin_SC_LUT[Clip3((uint16_t)1, (uint16_t)64, (uint16_t)(binCW >> 1)) - 1];
+  }
+}
+#endif
+
+
+//
+//! \}
diff --git a/source/Lib/CommonLib/Reshape.h b/source/Lib/CommonLib/Reshape.h
new file mode 100644
index 0000000000000000000000000000000000000000..64aa62f391ff3e385860c0809d1b125351681086
--- /dev/null
+++ b/source/Lib/CommonLib/Reshape.h
@@ -0,0 +1,102 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, 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.
+*/
+
+ /** \file     Reshape.h
+     \brief    reshaping header and class (header)
+ */
+
+#ifndef __RESHAPE__
+#define __RESHAPE__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "CommonDef.h"
+#include "Rom.h"
+#include "CommonLib/Picture.h"
+#if JVET_M0427_INLOOP_RESHAPER
+//! \ingroup CommonLib
+//! \{
+// ====================================================================================================================
+// Class definition
+// ====================================================================================================================
+
+class Reshape
+{
+protected:
+  SliceReshapeInfo        m_sliceReshapeInfo;
+  bool                    m_CTUFlag;
+  bool                    m_recReshaped;
+  std::vector<Pel>        m_invLUT;
+  std::vector<Pel>        m_fwdLUT;
+  std::vector<int>        m_chromaAdjHelpLUT;
+  std::vector<uint16_t>   m_binCW;
+  uint16_t                m_initCW;
+  bool                    m_reshape;
+  std::vector<Pel>        m_reshapePivot;
+  int                     m_lumaBD;
+  int                     m_reshapeLUTSize;
+public:
+  Reshape();
+  ~Reshape();
+
+  void createDec(int bitDepth);
+  void destroy();
+
+  void reverseLUT(std::vector<Pel>& inputLUT, std::vector<Pel>& outputLUT, uint16_t lutSize);
+  std::vector<Pel>&  getFwdLUT() { return m_fwdLUT; }
+  std::vector<Pel>&  getInvLUT() { return m_invLUT; }
+  std::vector<int>&  getChromaAdjHelpLUT() { return m_chromaAdjHelpLUT; }
+
+  bool getCTUFlag()              { return m_CTUFlag; }
+  void setCTUFlag(bool b       ) { m_CTUFlag = b; }
+
+  bool getRecReshaped()          { return m_recReshaped; }
+  void setRecReshaped(bool b)    { m_recReshaped = b; }
+  int  calculateChromaAdj(Pel avgLuma);
+  int  getPWLIdxInv(int lumaVal);
+  SliceReshapeInfo& getSliceReshaperInfo() { return m_sliceReshapeInfo; }
+  void copySliceReshaperInfo(SliceReshapeInfo& tInfo, SliceReshapeInfo& sInfo);
+
+  void constructReshaper();
+  void updateChromaScaleLUT();
+  bool getReshapeFlag() { return m_reshape; }
+  void setReshapeFlag(bool b) { m_reshape = b; }
+};// END CLASS DEFINITION Reshape
+
+//! \}
+#endif //
+#endif // __RESHAPE__
+
+
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index a485d9fadf0a04f6d7a1aa3e0a9cc7ae868502a9..d2e45089664850f87bf095c792926f52eb326c4b 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -310,6 +310,33 @@ uint32_t deriveWeightIdxBits(uint8_t gbiIdx) // Note: align this with TEncSbac::
   return numBits;
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS // define the sbb sizes
+uint32_t g_log2SbbSize[2][MAX_CU_DEPTH+1][MAX_CU_DEPTH+1][2] =
+{
+  //===== luma =====
+  {
+    { {0,0}, {0,1}, {0,2}, {0,3}, {0,4}, {0,4}, {0,4}, {0,4} },
+    { {1,0}, {1,1}, {1,2}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3} },
+    { {2,0}, {2,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {3,0}, {3,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {4,0}, {3,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {4,0}, {3,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {4,0}, {3,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {4,0}, {3,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} }
+  },
+  //===== chroma =====
+  {
+    { {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} },
+    { {0,0}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1}, {1,1} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} },
+    { {0,0}, {1,1}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2}, {2,2} }
+  },
+};
+#endif
 // initialize ROM variables
 void initROM()
 {
@@ -341,10 +368,6 @@ void initROM()
   }
 #endif
 
-
-
-
-
   // g_aucConvertToBit[ x ]: log2(x/4), if x=4 -> 0, x=8 -> 1, x=16 -> 2, ...
   // g_aucLog2[ x ]: log2(x), if x=1 -> 0, x=2 -> 1, x=4 -> 2, x=8 -> 3, x=16 -> 4, ...
   ::memset(g_aucLog2, 0, sizeof(g_aucLog2));
@@ -373,6 +396,10 @@ void initROM()
   SizeIndexInfoLog2 sizeInfo;
   sizeInfo.init(MAX_CU_SIZE);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  for( int ch = 0; ch < MAX_NUM_CHANNEL_TYPE; ch++ )
+  {
+#endif
   // initialize scan orders
   for (uint32_t blockHeightIdx = 0; blockHeightIdx < sizeInfo.numAllHeights(); blockHeightIdx++)
   {
@@ -389,10 +416,23 @@ void initROM()
       for (uint32_t scanTypeIndex = 0; scanTypeIndex < SCAN_NUMBER_OF_TYPES; scanTypeIndex++)
       {
         const CoeffScanType scanType = CoeffScanType(scanTypeIndex);
+        ScanElement *       scan     = nullptr;
+
+        if (blockWidthIdx < sizeInfo.numWidths() && blockHeightIdx < sizeInfo.numHeights())
+        {
+          scan = new ScanElement[totalValues];
+        }
 
-        g_scanOrder     [SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx]    = new uint32_t[totalValues];
-        g_scanOrderPosXY[SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx][0] = new uint32_t[totalValues];
-        g_scanOrderPosXY[SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx][1] = new uint32_t[totalValues];
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        g_scanOrder[ch][SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx] = scan;
+#else
+        g_scanOrder[SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx] = scan;
+#endif
+
+        if (scan == nullptr)
+        {
+          continue;
+        }
 
         ScanGenerator fullBlockScan(blockWidth, blockHeight, blockWidth, scanType);
 
@@ -401,36 +441,34 @@ void initROM()
           const int rasterPos = fullBlockScan.GetNextIndex( 0, 0 );
           const int posY      = rasterPos / blockWidth;
           const int posX      = rasterPos - ( posY * blockWidth );
-          g_scanOrder     [SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx]   [scanPosition] = rasterPos;
-          g_scanOrderPosXY[SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx][0][scanPosition] = posX;
-          g_scanOrderPosXY[SCAN_UNGROUPED][scanType][blockWidthIdx][blockHeightIdx][1][scanPosition] = posY;
-        }
-      }
-
-      if( blockWidthIdx >= sizeInfo.numWidths() || blockHeightIdx >= sizeInfo.numHeights() )
-      {
-        // size indizes greater than numIdxs are sizes than are only used when grouping - they will never come up as a block size - thus they can be skipped at this point
-        for( uint32_t scanTypeIndex = 0; scanTypeIndex < SCAN_NUMBER_OF_TYPES; scanTypeIndex++ )
-        {
-          g_scanOrder     [SCAN_GROUPED_4x4][scanTypeIndex][blockWidthIdx][blockHeightIdx]    = nullptr;
-          g_scanOrderPosXY[SCAN_GROUPED_4x4][scanTypeIndex][blockWidthIdx][blockHeightIdx][0] = nullptr;
-          g_scanOrderPosXY[SCAN_GROUPED_4x4][scanTypeIndex][blockWidthIdx][blockHeightIdx][1] = nullptr;
 
+          scan[scanPosition].idx = rasterPos;
+          scan[scanPosition].x   = posX;
+          scan[scanPosition].y   = posY;
         }
-
-        continue;
       }
 
       //--------------------------------------------------------------------------------------------------
 
       //grouped scan orders
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      const uint32_t* log2Sbb        = g_log2SbbSize[ch][ g_aucLog2[blockWidth] ][ g_aucLog2[blockHeight] ];
+      const uint32_t  log2CGWidth    = log2Sbb[0];
+      const uint32_t  log2CGHeight   = log2Sbb[1];
+#else
       const uint32_t  log2CGWidth    = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
       const uint32_t  log2CGHeight   = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
+#endif
 
       const uint32_t  groupWidth     = 1 << log2CGWidth;
       const uint32_t  groupHeight    = 1 << log2CGHeight;
+#if JVET_M0257
+      const uint32_t  widthInGroups = std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, blockWidth) >> log2CGWidth;
+      const uint32_t  heightInGroups = std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, blockHeight) >> log2CGHeight;
+#else
       const uint32_t  widthInGroups  = blockWidth >> log2CGWidth;
       const uint32_t  heightInGroups = blockHeight >> log2CGHeight;
+#endif
 
       const uint32_t  groupSize      = groupWidth    * groupHeight;
       const uint32_t  totalGroups    = widthInGroups * heightInGroups;
@@ -439,10 +477,25 @@ void initROM()
       {
         const CoeffScanType scanType = CoeffScanType(scanTypeIndex);
 
-        g_scanOrder     [SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx]    = new uint32_t[totalValues];
-        g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][0] = new uint32_t[totalValues];
-        g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][1] = new uint32_t[totalValues];
+        ScanElement *scan = new ScanElement[totalValues];
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        g_scanOrder[ch][SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx] = scan;
+#else
+        g_scanOrder[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx] = scan;
+#endif
+
+#if JVET_M0257
+        if ( blockWidth > JVET_C0024_ZERO_OUT_TH || blockHeight > JVET_C0024_ZERO_OUT_TH )
+        {
+          for (uint32_t i = 0; i < totalValues; i++)
+          {
+            scan[i].idx = totalValues - 1;
+            scan[i].x   = blockWidth - 1;
+            scan[i].y   = blockHeight - 1;
+          }
+        }
+#endif
 
         ScanGenerator fullBlockScan(widthInGroups, heightInGroups, groupWidth, scanType);
 
@@ -462,9 +515,9 @@ void initROM()
             const int posY      = rasterPos / blockWidth;
             const int posX      = rasterPos - ( posY * blockWidth );
 
-            g_scanOrder     [SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx]   [groupOffsetScan + scanPosition] = rasterPos;
-            g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][0][groupOffsetScan + scanPosition] = posX;
-            g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][1][groupOffsetScan + scanPosition] = posY;
+            scan[groupOffsetScan + scanPosition].idx = rasterPos;
+            scan[groupOffsetScan + scanPosition].x   = posX;
+            scan[groupOffsetScan + scanPosition].y   = posY;
           }
 
           fullBlockScan.GetNextIndex(0, 0);
@@ -474,6 +527,9 @@ void initROM()
       //--------------------------------------------------------------------------------------------------
     }
   }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  }
+#endif
 
   for( int idxH = MAX_CU_DEPTH - MIN_CU_LOG2; idxH >= 0; --idxH )
   {
@@ -503,6 +559,25 @@ void destroyROM()
   unsigned numWidths = gp_sizeIdxInfo->numAllWidths();
   unsigned numHeights = gp_sizeIdxInfo->numAllHeights();
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  for( uint32_t ch = 0; ch < MAX_NUM_CHANNEL_TYPE; ch++ )
+  {
+    for( uint32_t groupTypeIndex = 0; groupTypeIndex < SCAN_NUMBER_OF_GROUP_TYPES; groupTypeIndex++ )
+    {
+      for( uint32_t scanOrderIndex = 0; scanOrderIndex < SCAN_NUMBER_OF_TYPES; scanOrderIndex++ )
+      {
+        for( uint32_t blockWidthIdx = 0; blockWidthIdx <= numWidths; blockWidthIdx++ )
+        {
+          for( uint32_t blockHeightIdx = 0; blockHeightIdx <= numHeights; blockHeightIdx++ )
+          {
+            delete[] g_scanOrder[ch][groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx];
+            g_scanOrder[ch][groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx] = nullptr;
+          }
+        }
+      }
+    }
+  }
+#else
   for (uint32_t groupTypeIndex = 0; groupTypeIndex < SCAN_NUMBER_OF_GROUP_TYPES; groupTypeIndex++)
   {
     for (uint32_t scanOrderIndex = 0; scanOrderIndex < SCAN_NUMBER_OF_TYPES; scanOrderIndex++)
@@ -513,17 +588,11 @@ void destroyROM()
         {
           delete[] g_scanOrder[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx];
           g_scanOrder[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx] = nullptr;
-
-          delete[] g_scanOrderPosXY[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx][0];
-          g_scanOrderPosXY[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx][0] = nullptr;
-
-          delete[] g_scanOrderPosXY[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx][1];
-          g_scanOrderPosXY[groupTypeIndex][scanOrderIndex][blockWidthIdx][blockHeightIdx][1] = nullptr;
-
         }
       }
     }
   }
+#endif
 
   delete gp_sizeIdxInfo;
   gp_sizeIdxInfo = nullptr;
@@ -563,10 +632,6 @@ const int g_invQuantScales[SCALING_LIST_REM_NUM] =
 
 //--------------------------------------------------------------------------------------------------
 //structures
-
-//EMT threshold
-
-
 //--------------------------------------------------------------------------------------------------
 //coefficients
 //--------------------------------------------------------------------------------------------------
@@ -657,17 +722,11 @@ UnitScale g_miScaling( MIN_CU_LOG2, MIN_CU_LOG2 );
 // ====================================================================================================================
 
 // scanning order table
-uint32_t* g_scanOrder     [SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
-uint32_t* g_scanOrderPosXY[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1][2];
-
-const uint32_t ctxIndMap4x4[4 * 4] =
-{
-  0, 1, 4, 5,
-  2, 3, 4, 5,
-  6, 6, 8, 8,
-  7, 7, 8, 8
-};
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+ScanElement *g_scanOrder[2][SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
+#else
+ScanElement *g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
+#endif
 
 const uint32_t g_uiMinInGroup[LAST_SIGNIFICANT_GROUPS] = { 0,1,2,3,4,6,8,12,16,24,32,48,64,96 };
 const uint32_t g_uiGroupIdx[MAX_TU_SIZE] = { 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
@@ -683,10 +742,12 @@ const uint32_t g_auiGoRicePosCoeff0[3][32] =
   {1, 1, 1, 1, 2, 3, 4,    4, 4, 6, 6, 6, 8, 8,    8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16,    16, 16, 16, 16},
   {1, 1, 2, 2, 2, 3, 4,    4, 4, 6, 6, 6, 8, 8,    8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16,    16, 16, 16, 16}
 };
+#if !JVET_M0470
 const uint32_t g_auiGoRiceRange[MAX_GR_ORDER_RESIDUAL] =
 {
   6, 5, 6, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION
 };
+#endif
 
 #if HEVC_USE_SCALING_LISTS
 const char *MatrixType[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM] =
@@ -795,19 +856,9 @@ const uint32_t g_scalingListSize [SCALING_LIST_SIZE_NUM] = { 4, 16, 64, 256, 102
 const uint32_t g_scalingListSizeX[SCALING_LIST_SIZE_NUM] = { 2,  4,  8,  16,   32,   64,   128 };
 #endif
 
-const uint8_t g_NonMPM[257] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8 };
-
+#if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
 const Pel g_trianglePelWeightedLuma[TRIANGLE_DIR_NUM][2][7] =
-{ 
+{
   { // TRIANGLE_DIR_135
     { 1, 2, 4, 6, 7, 0, 0 },
     { 1, 2, 3, 4, 5, 6, 7 }
@@ -843,19 +894,21 @@ const Pel g_trianglePelWeightedChroma[2][TRIANGLE_DIR_NUM][2][7] =
 
 const uint8_t g_triangleWeightLengthLuma[2] = { 5, 7 };
 const uint8_t g_triangleWeightLengthChroma[2][2] = { { 5, 7 }, { 3, 3 } };
+#endif
 
-      uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
+uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
 
+#if !JVET_M0883_TRIANGLE_SIGNALING
 const uint8_t g_triangleCombination[TRIANGLE_MAX_NUM_CANDS][3] =
 {
-  { 0, 1, 0 }, { 1, 0, 1 }, { 1, 0, 2 }, { 0, 0, 1 }, { 0, 2, 0 }, 
-  { 1, 0, 3 }, { 1, 0, 4 }, { 1, 1, 0 }, { 0, 3, 0 }, { 0, 4, 0 }, 
-  { 0, 0, 2 }, { 0, 1, 2 }, { 1, 1, 2 }, { 0, 0, 4 }, { 0, 0, 3 }, 
-  { 0, 1, 3 }, { 0, 1, 4 }, { 1, 1, 4 }, { 1, 1, 3 }, { 1, 2, 1 }, 
-  { 1, 2, 0 }, { 0, 2, 1 }, { 0, 4, 3 }, { 1, 3, 0 }, { 1, 3, 2 }, 
-  { 1, 3, 4 }, { 1, 4, 0 }, { 1, 3, 1 }, { 1, 2, 3 }, { 1, 4, 1 }, 
-  { 0, 4, 1 }, { 0, 2, 3 }, { 1, 4, 2 }, { 0, 3, 2 }, { 1, 4, 3 }, 
-  { 0, 3, 1 }, { 0, 2, 4 }, { 1, 2, 4 }, { 0, 4, 2 }, { 0, 3, 4 }, 
+  { 0, 1, 0 }, { 1, 0, 1 }, { 1, 0, 2 }, { 0, 0, 1 }, { 0, 2, 0 },
+  { 1, 0, 3 }, { 1, 0, 4 }, { 1, 1, 0 }, { 0, 3, 0 }, { 0, 4, 0 },
+  { 0, 0, 2 }, { 0, 1, 2 }, { 1, 1, 2 }, { 0, 0, 4 }, { 0, 0, 3 },
+  { 0, 1, 3 }, { 0, 1, 4 }, { 1, 1, 4 }, { 1, 1, 3 }, { 1, 2, 1 },
+  { 1, 2, 0 }, { 0, 2, 1 }, { 0, 4, 3 }, { 1, 3, 0 }, { 1, 3, 2 },
+  { 1, 3, 4 }, { 1, 4, 0 }, { 1, 3, 1 }, { 1, 2, 3 }, { 1, 4, 1 },
+  { 0, 4, 1 }, { 0, 2, 3 }, { 1, 4, 2 }, { 0, 3, 2 }, { 1, 4, 3 },
+  { 0, 3, 1 }, { 0, 2, 4 }, { 1, 2, 4 }, { 0, 4, 2 }, { 0, 3, 4 },
 };
 
 const uint8_t g_triangleIdxBins[TRIANGLE_MAX_NUM_CANDS] =
@@ -865,4 +918,5 @@ const uint8_t g_triangleIdxBins[TRIANGLE_MAX_NUM_CANDS] =
    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
   10, 10, 10, 10, 10, 10, 10, 10, 10, 10
 };
+#endif
 //! \}
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index 2a856a448d8bd7b4f06454e42cbf9806a8022191..f7b795621be0edde887cd2700663a8f2a8a2a60b 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -64,8 +64,21 @@ void         generateTrafoBlockSizeScaling( SizeIndexInfo& sizeIdxInfo );
 // ====================================================================================================================
 
 // flexible conversion from relative to absolute index
-extern       uint32_t*  g_scanOrder     [SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
-extern       uint32_t*  g_scanOrderPosXY[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1][2];
+struct ScanElement
+{
+  uint32_t idx;
+  uint16_t x;
+  uint16_t y;
+};
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+extern       uint32_t   g_log2SbbSize   [2][MAX_CU_DEPTH+1][MAX_CU_DEPTH+1][2];
+extern ScanElement
+  *g_scanOrder[2][SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
+#else
+extern ScanElement
+  *g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
+#endif
 
 extern const int g_quantScales   [SCALING_LIST_REM_NUM];          // Q(QP%6)
 extern const int g_invQuantScales[SCALING_LIST_REM_NUM];          // IQ(QP%6)
@@ -86,8 +99,6 @@ extern const uint8_t  g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSi
 // Scanning order & context mapping table
 // ====================================================================================================================
 
-extern const uint32_t   ctxIndMap4x4[4*4];
-
 extern const uint32_t   g_uiGroupIdx[ MAX_TU_SIZE ];
 extern const uint32_t   g_uiMinInGroup[ LAST_SIGNIFICANT_GROUPS ];
 extern const uint32_t   g_auiGoRiceParsCoeff     [ 32 ];
@@ -109,10 +120,6 @@ extern const uint8_t  g_chroma422IntraAngleMappingTable[NUM_INTRA_MODE];
 // Mode-Dependent DST Matrices
 // ====================================================================================================================
 
-#if HEVC_USE_4x4_DSTVII
-extern const TMatrixCoeff g_as_DST_MAT_4 [TRANSFORM_NUMBER_OF_DIRECTIONS][4][4];
-#endif
-
 #if !JVET_M0464_UNI_MTS
 extern const uint32_t g_EmtSigNumThr;
 #endif
@@ -168,7 +175,6 @@ extern int            g_BlockSizeTrafoScale           [MAX_CU_SIZE + 1][MAX_CU_S
 extern int8_t          g_aucLog2                       [MAX_CU_SIZE + 1];
 extern int8_t          g_aucNextLog2        [MAX_CU_SIZE + 1];
 extern int8_t          g_aucPrevLog2        [MAX_CU_SIZE + 1];
-extern const int8_t    i2Log2Tab[257];
 
 inline bool is34( const SizeType& size )
 {
@@ -219,8 +225,6 @@ extern int g_aiLMDivTableLow[];
 extern int g_aiLMDivTableHigh[];
 #endif
 
-extern const int g_aiNonLMPosThrs[];
-
 extern const int8_t g_GbiLog2WeightBase;
 extern const int8_t g_GbiWeightBase;
 extern const int8_t g_GbiWeights[GBI_NUM];
@@ -246,13 +250,17 @@ constexpr uint8_t g_tbMax[257] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
 
 //! \}
 
+#if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
 extern const Pel     g_trianglePelWeightedLuma[TRIANGLE_DIR_NUM][2][7];
 extern const Pel     g_trianglePelWeightedChroma[2][TRIANGLE_DIR_NUM][2][7];
 extern const uint8_t g_triangleWeightLengthLuma[2];
 extern const uint8_t g_triangleWeightLengthChroma[2][2];
+#endif
 extern       uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
+#if !JVET_M0883_TRIANGLE_SIGNALING
 extern const uint8_t g_triangleCombination[TRIANGLE_MAX_NUM_CANDS][3];
 extern const uint8_t g_triangleIdxBins[TRIANGLE_MAX_NUM_CANDS];
+#endif
 
 #endif  //__TCOMROM__
 
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 00f16676bcbef8eece7b89a92ad3b667df5a08cc..8c14b97ab9edeb273605390eed1177e4571dbf6e 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -92,6 +92,9 @@ Slice::Slice()
 , m_colRefIdx                     ( 0 )
 , m_maxNumMergeCand               ( 0 )
 , m_maxNumAffineMergeCand         ( 0 )
+#if JVET_M0255_FRACMMVD_SWITCH
+, m_disFracMMVD                   ( false )
+#endif
 , m_uiTLayer                      ( 0 )
 , m_bTLayerSwitchingFlag          ( false )
 , m_sliceMode                     ( NO_SLICES )
@@ -177,6 +180,15 @@ Slice::Slice()
   }
 
   initMotionLUTs();
+
+#if JVET_M0427_INLOOP_RESHAPER
+  m_sliceReshapeInfo.setUseSliceReshaper(false);
+  m_sliceReshapeInfo.setSliceReshapeModelPresentFlag(false);
+  m_sliceReshapeInfo.setSliceReshapeChromaAdj(0);
+  m_sliceReshapeInfo.reshaperModelMinBinIdx = 0;
+  m_sliceReshapeInfo.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1;
+  memset(m_sliceReshapeInfo.reshaperModelBinCWDelta, 0, PIC_CODE_CW_BINS * sizeof(int));
+#endif
 }
 
 Slice::~Slice()
@@ -214,6 +226,9 @@ void Slice::initSlice()
 
   m_bFinalized=false;
 
+#if JVET_M0255_FRACMMVD_SWITCH
+  m_disFracMMVD          = false;
+#endif
   m_substreamSizes.clear();
   m_cabacInitFlag        = false;
   m_cabacWinUpdateMode   = 0;
@@ -435,13 +450,15 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b
       pcRefPic = xGetLongTermRefPic(rcListPic, m_pRPS->getPOC(i), m_pRPS->getCheckLTMSBPresent(i));
     }
   }
-  if (getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+  if (getSPS()->getIBCMode())
   {
     RefPicSetLtCurr[NumPicLtCurr] = getPic();
     //getPic()->setIsLongTerm(true);
     getPic()->longTerm = true;
     NumPicLtCurr++;
   }
+#endif
   // ref_pic_list_init
   Picture*  rpsCurrList0[MAX_NUM_REF+1];
   Picture*  rpsCurrList1[MAX_NUM_REF+1];
@@ -454,11 +471,13 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b
     // - Otherwise, when the current picture contains a P or B slice, the value of NumPocTotalCurr shall not be equal to 0.
     if (getRapPicFlag())
     {
-      if (getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+      if (getSPS()->getIBCMode())
       {
         CHECK(numPicTotalCurr != 1, "Invalid state");
       }
       else
+#endif
         CHECK(numPicTotalCurr != 0, "Invalid state");
     }
 
@@ -529,11 +548,13 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b
       m_bIsUsedAsLongTerm[REF_PIC_LIST_1][rIdx] = ( cIdx >= NumPicStCurr0 + NumPicStCurr1 );
     }
   }
-  if (getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+  if (getSPS()->getIBCMode())
   {
     m_apcRefPicList[REF_PIC_LIST_0][m_aiNumRefIdx[REF_PIC_LIST_0] - 1] = getPic();
     m_bIsUsedAsLongTerm[REF_PIC_LIST_0][m_aiNumRefIdx[REF_PIC_LIST_0] - 1] = true;
   }
+#endif
     // For generalized B
   // note: maybe not existed case (always L0 is copied to L1 if L1 is empty)
   if( bCopyL0toL1ErrorCase && isInterB() && getNumRefIdx(REF_PIC_LIST_1) == 0)
@@ -564,11 +585,13 @@ int Slice::getNumRpsCurrTempList() const
       numRpsCurrTempList++;
     }
   }
-  if (getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+  if (getSPS()->getIBCMode())
   {
     return numRpsCurrTempList + 1;
   }
   else
+#endif
     return numRpsCurrTempList;
 }
 
@@ -689,6 +712,9 @@ void Slice::decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList&
       if (rpcPic->getPOC() != pocCurr)
       {
         rpcPic->referenced = false;
+#if JVET_M0253_HASH_ME
+        rpcPic->getHashMap()->clearAll();
+#endif
       }
       iterPic++;
     }
@@ -716,6 +742,9 @@ void Slice::decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList&
           if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != m_iLastIDR)
           {
             rpcPic->referenced = false;
+#if JVET_M0253_HASH_ME
+            rpcPic->getHashMap()->clearAll();
+#endif
           }
           iterPic++;
         }
@@ -733,6 +762,9 @@ void Slice::decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList&
           if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != pocCRA)
           {
             rpcPic->referenced = false;
+#if JVET_M0253_HASH_ME
+            rpcPic->getHashMap()->clearAll();
+#endif
           }
           iterPic++;
         }
@@ -864,6 +896,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_enableTMVPFlag                = pSrc->m_enableTMVPFlag;
   m_maxNumMergeCand               = pSrc->m_maxNumMergeCand;
   m_maxNumAffineMergeCand         = pSrc->m_maxNumAffineMergeCand;
+#if JVET_M0255_FRACMMVD_SWITCH
+  m_disFracMMVD                   = pSrc->m_disFracMMVD;
+#endif
   if( cpyAlmostAll ) m_encCABACTableIdx  = pSrc->m_encCABACTableIdx;
   m_splitConsOverrideFlag         = pSrc->m_splitConsOverrideFlag;
   m_uiMinQTSize                   = pSrc->m_uiMinQTSize;
@@ -1141,6 +1176,9 @@ void Slice::applyReferencePictureSet( PicList& rcListPic, const ReferencePicture
       pcPic->referenced = false;
       pcPic->usedByCurr = false;
       pcPic->longTerm   = false;
+#if JVET_M0253_HASH_ME
+      pcPic->getHashMap()->clearAll();
+#endif
     }
 
     // sanity checks
@@ -1612,14 +1650,28 @@ void Slice::initMotionLUTs()
 {
   m_MotionCandLut = new LutMotionCand;
   m_MotionCandLut->currCnt = 0;
+#if JVET_M0483_IBC
+  m_MotionCandLut->currCntIBC = 0;
+#endif
   m_MotionCandLut->motionCand = nullptr;
+#if JVET_M0483_IBC
+  m_MotionCandLut->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2];
+#else
   m_MotionCandLut->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS];
+#endif
 #if  JVET_M0170_MRG_SHARELIST
   m_MotionCandLuTsBkup = new LutMotionCand;
   m_MotionCandLuTsBkup->currCnt = 0;
+#if JVET_M0483_IBC
+  m_MotionCandLuTsBkup->currCntIBC = 0;
+#endif
   m_MotionCandLuTsBkup->motionCand = nullptr;
+#if JVET_M0483_IBC
+  m_MotionCandLuTsBkup->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2];
+#else
   m_MotionCandLuTsBkup->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS];
 #endif
+#endif
 }
 void Slice::destroyMotionLUTs()
 {
@@ -1637,8 +1689,14 @@ void Slice::destroyMotionLUTs()
 void Slice::resetMotionLUTs()
 {
   m_MotionCandLut->currCnt = 0;
+#if JVET_M0483_IBC
+  m_MotionCandLut->currCntIBC = 0;
+#endif
 #if  JVET_M0170_MRG_SHARELIST
   m_MotionCandLuTsBkup->currCnt = 0;
+#if JVET_M0483_IBC
+  m_MotionCandLuTsBkup->currCntIBC = 0;
+#endif
 #endif
 }
 
@@ -1653,8 +1711,46 @@ MotionInfo Slice::getMotionInfoFromLUTBkup(int MotCandIdx) const
 }
 #endif
 
+#if JVET_M0483_IBC
+void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi, bool ibcflag)
+#else
 void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi)
+#endif
 {
+#if JVET_M0483_IBC
+  int currCntIBC = ibcflag ? lutMC->currCntIBC : lutMC->currCnt;
+  int offset = ibcflag ? MAX_NUM_HMVP_CANDS : 0;
+  bool pruned = false;
+  int  sameCandIdx = 0;
+  for (int idx = 0; idx < currCntIBC; idx++)
+  {
+    if (lutMC->motionCand[idx + offset] == newMi)
+    {
+      sameCandIdx = idx;
+      pruned = true;
+      break;
+    }
+  }
+  if (pruned || currCntIBC == MAX_NUM_HMVP_CANDS)
+  {
+    memmove(&lutMC->motionCand[sameCandIdx + offset], &lutMC->motionCand[sameCandIdx + offset + 1],
+      sizeof(MotionInfo) * (currCntIBC - sameCandIdx - 1));
+    memcpy(&lutMC->motionCand[currCntIBC + offset - 1], &newMi, sizeof(MotionInfo));
+  }
+  else
+  {
+    if (ibcflag)
+    {
+      memcpy(&lutMC->motionCand[currCntIBC + offset], &newMi, sizeof(MotionInfo));
+      lutMC->currCntIBC++;
+    }
+    else
+    {
+      memcpy(&lutMC->motionCand[currCntIBC], &newMi, sizeof(MotionInfo));
+      lutMC->currCnt++;
+    }
+  }
+#else
   int currCnt = lutMC->currCnt ;
 
   bool pruned = false;
@@ -1678,6 +1774,7 @@ void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi)
   {
     memcpy(&lutMC->motionCand[lutMC->currCnt++], &newMi, sizeof(MotionInfo));
   }
+#endif
 }
 
 void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu)
@@ -1686,19 +1783,37 @@ void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu)
   if (cu.affine) { return; }
   if (cu.triangle) { return; }
 
-  MotionInfo newMi = selectedPU->getMotionInfo(); 
+  MotionInfo newMi = selectedPU->getMotionInfo();
+#if JVET_M0264_HMVP_WITH_GBIIDX
+  newMi.GBiIdx = (newMi.interDir == 3) ? cu.GBiIdx : GBI_DEFAULT;
+#endif
+#if JVET_M0483_IBC
+  addMotionInfoToLUTs(lutMC, newMi, CU::isIBC(cu));
+#else
   addMotionInfoToLUTs(lutMC, newMi);
+#endif
 }
 
 void Slice::copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst)
 {
    memcpy(Dst->motionCand, Src->motionCand, sizeof(MotionInfo)*(std::min(Src->currCnt, MAX_NUM_HMVP_CANDS)));
    Dst->currCnt = Src->currCnt;
+#if JVET_M0483_IBC
+   memcpy(Dst->motionCand + MAX_NUM_HMVP_CANDS, Src->motionCand + MAX_NUM_HMVP_CANDS, sizeof(MotionInfo)*(std::min(Src->currCntIBC, MAX_NUM_HMVP_CANDS)));
+   Dst->currCntIBC = Src->currCntIBC;
+#endif
 }
 
 unsigned Slice::getMinPictureDistance() const
 {
   int minPicDist = MAX_INT;
+#if JVET_M0483_IBC
+  if (getSPS()->getIBCFlag())
+  {
+    minPicDist = 0;
+  }
+  else
+#endif
   if( ! isIntra() )
   {
     const int currPOC  = getPOC();
@@ -1766,49 +1881,6 @@ SPSRExt::SPSRExt()
 }
 
 
-SPSNext::SPSNext( SPS& sps )
-  : m_SPS                       ( sps )
-  , m_NextEnabled               ( false )
-  // disable all tool enabling flags by default
-  , m_LargeCTU                  ( false )
-  , m_IMV                       ( false )
-  , m_DisableMotionCompression  ( false )
-  , m_LMChroma                  ( false )
-#if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  , m_cclmCollocatedChromaFlag  ( false )
-#endif
-#if JVET_M0464_UNI_MTS
-  , m_IntraMTS                  ( false )
-  , m_InterMTS                  ( false )
-#else
-  , m_IntraEMT                  ( false )
-  , m_InterEMT                  ( false )
-#endif
-  , m_Affine                    ( false )
-  , m_AffineType                ( false )
-  , m_MTTEnabled                ( false )
-  , m_MHIntra                   ( false )
-  , m_Triangle                  ( false )
-#if ENABLE_WPP_PARALLELISM
-  , m_NextDQP                   ( false )
-#endif
-#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  , m_LadfEnabled               ( false )
-  , m_LadfNumIntervals          ( 0 )
-  , m_LadfQpOffset              { 0 }
-  , m_LadfIntervalLowerBound    { 0 }
-#endif
-
-  // default values for additional parameters
-  , m_ImvMode                   ( IMV_OFF )
-  , m_MTTMode                   ( 0 )
-    , m_compositeRefEnabled     ( false )
-  , m_IBCMode                   ( 0 )
-  // ADD_NEW_TOOL : (sps extension) add tool enabling flags here (with "false" as default values)
-{
-}
-
-
 SPS::SPS()
 : m_SPSId                     (  0)
 , m_bIntraOnlyConstraintFlag  (false)
@@ -1828,6 +1900,16 @@ SPS::SPS()
 , m_bNoLadfConstraintFlag     (false)
 , m_bNoDepQuantConstraintFlag (false)
 , m_bNoSignDataHidingConstraintFlag(false)
+#if JVET_M0246_AFFINE_AMVR
+, m_affineAmvrEnabledFlag     ( false )
+#endif
+#if JVET_M0147_DMVR
+, m_DMVR                      ( false )
+#endif
+#if JVET_M0140_SBT
+, m_SBT                       ( false )
+, m_MaxSbtSize                ( 32 )
+#endif
 #if HEVC_VPS
 , m_VPSId                     (  0)
 #endif
@@ -1858,6 +1940,9 @@ SPS::SPS()
 , m_bPCMFilterDisableFlag     (false)
 , m_sbtmvpEnabledFlag         (false)
 , m_bdofEnabledFlag           (false)
+#if JVET_M0255_FRACMMVD_SWITCH
+, m_disFracMmvdEnabledFlag    ( false )
+#endif
 , m_uiBitsForPOC              (  8)
 , m_numLongTermRefPicSPS      (  0)
 , m_uiMaxTrSize               ( 32)
@@ -1871,9 +1956,42 @@ SPS::SPS()
 #endif
 , m_vuiParametersPresentFlag  (false)
 , m_vuiParameters             ()
-, m_spsNextExtension          (*this)
 , m_wrapAroundEnabledFlag     (false)
 , m_wrapAroundOffset          (  0)
+#if JVET_M0483_IBC
+, m_IBCFlag                   (  0)
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+, m_lumaReshapeEnable         (false)
+#endif
+// KJS: BEGIN former SPSNext parameters
+, m_AMVREnabledFlag                       ( false )
+, m_LMChroma                  ( false )
+#if JVET_M0142_CCLM_COLLOCATED_CHROMA
+, m_cclmCollocatedChromaFlag  ( false )
+#endif
+#if JVET_M0464_UNI_MTS
+, m_IntraMTS                  ( false )
+, m_InterMTS                  ( false )
+#else
+, m_IntraEMT                  ( false )
+, m_InterEMT                  ( false )
+#endif
+, m_Affine                    ( false )
+, m_AffineType                ( false )
+, m_MHIntra                   ( false )
+, m_Triangle                  ( false )
+#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
+, m_LadfEnabled               ( false )
+, m_LadfNumIntervals          ( 0 )
+, m_LadfQpOffset              { 0 }
+, m_LadfIntervalLowerBound    { 0 }
+#endif
+, m_compositeRefEnabled     ( false )
+#if !JVET_M0483_IBC
+, m_IBCMode                   ( 0 )
+#endif
+// KJS: END former SPSNext parameters
 {
   for(int ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
   {
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 05b8ea8f046b66ed3bc1e72b0d4288b506ea31dd..11a7d8728f542e0e5b1610eaa89673dcbca242b9 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -291,6 +291,38 @@ struct HrdSubLayerInfo
   uint32_t duBitRateValue    [MAX_CPB_CNT][2];
 };
 
+#if JVET_M0427_INLOOP_RESHAPER
+class SliceReshapeInfo
+{
+public:
+  bool      sliceReshaperEnableFlag;
+  bool      sliceReshaperModelPresentFlag;
+  unsigned  enableChromaAdj;
+  uint32_t  reshaperModelMinBinIdx;
+  uint32_t  reshaperModelMaxBinIdx;
+  int       reshaperModelBinCWDelta[PIC_CODE_CW_BINS];
+  int       maxNbitsNeededDeltaCW;
+  void      setUseSliceReshaper(bool b)                                { sliceReshaperEnableFlag = b;            }
+  bool      getUseSliceReshaper() const                                { return sliceReshaperEnableFlag;         }
+  void      setSliceReshapeModelPresentFlag(bool b)                    { sliceReshaperModelPresentFlag = b;      }
+  bool      getSliceReshapeModelPresentFlag() const                    { return   sliceReshaperModelPresentFlag; }
+  void      setSliceReshapeChromaAdj(unsigned adj)                     { enableChromaAdj = adj;                  }
+  unsigned  getSliceReshapeChromaAdj() const                           { return enableChromaAdj;                 }
+};
+
+struct ReshapeCW
+{
+  std::vector<uint32_t> binCW;
+  int rspPicSize;
+  int rspIntraPeriod;
+  int rspFps;
+  int rspBaseQP;
+  int rspTid;
+  int rspSliceQP;
+  int rspFpsToIp;
+};
+#endif
+
 class HRD
 {
 private:
@@ -790,135 +822,6 @@ public:
 };
 
 
-class SPS;
-
-// Deprecated: SPSNext is going to be removed! Do not add any parameters to SPSNext
-class SPSNext
-{
-private:
-  SPS&  m_SPS;
-
-  bool              m_NextEnabled;
-  //=====  tool enabling flags (4 bytes - NOTE: last flag must be used for new extensions) =====
-  bool              m_LargeCTU;                   // 5
-  bool              m_IMV;                        // 9
-  bool              m_DisableMotionCompression;   // 13
-  bool              m_LMChroma;                   // 17
-#if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  bool              m_cclmCollocatedChromaFlag;
-#endif
-#if JVET_M0464_UNI_MTS
-  bool              m_IntraMTS;                   // 18
-  bool              m_InterMTS;                   // 19
-#else
-  bool              m_IntraEMT;                   // 18
-  bool              m_InterEMT;                   // 19
-#endif
-  bool              m_Affine;
-  bool              m_AffineType;
-  bool              m_GBi;                        //
-  bool              m_MTTEnabled;                 //
-  bool              m_MHIntra;
-  bool              m_Triangle;
-#if ENABLE_WPP_PARALLELISM
-  bool              m_NextDQP;
-#endif
-#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  bool              m_LadfEnabled;
-  int               m_LadfNumIntervals;
-  int               m_LadfQpOffset[MAX_LADF_INTERVALS];
-  int               m_LadfIntervalLowerBound[MAX_LADF_INTERVALS];
-#endif
-
-public:
-  const static int  NumReservedFlags = 32 - 27; /* current number of tool enabling flags */
-
-private:
-  //=====  additional parameters  =====
-  // qtbt
-  //imv
-  ImvMode     m_ImvMode;
-  // multi type tree (QTBT + triple split)
-  unsigned    m_MTTMode;
-
-  bool        m_compositeRefEnabled;        //composite longterm reference
-  unsigned    m_IBCMode;
-
-public:
-  SPSNext( SPS& sps );
-
-  const SPS&  getSPS              () const                                          { return m_SPS; }
-  SPS&        getSPS              ()                                                { return m_SPS; }
-  bool        nextToolsEnabled    () const                                          { return m_NextEnabled; }
-  void        setNextToolsEnabled ( bool next )                                     { m_NextEnabled = next; }
-
-  //=====  tool enabling flags and extension bit  =====
-  void      setUseLargeCTU        ( bool b )                                        { m_LargeCTU = b; }
-  bool      getUseLargeCTU        ()                                      const     { return m_LargeCTU; }
-  void      setUseIMV             ( bool b )                                        { m_IMV = b; }
-  bool      getUseIMV             ()                                      const     { return m_IMV; }
-  void      setUseAffine          ( bool b )                                        { m_Affine = b; }
-  bool      getUseAffine          ()                                      const     { return m_Affine; }
-  void      setUseAffineType      ( bool b )                                        { m_AffineType = b; }
-  bool      getUseAffineType      ()                                      const     { return m_AffineType; }
-  void      setDisableMotCompress ( bool b )                                        { m_DisableMotionCompression = b; }
-  bool      getDisableMotCompress ()                                      const     { return m_DisableMotionCompression; }
-  bool      getMTTEnabled         ()                                      const     { return m_MTTEnabled; }
-#if ENABLE_WPP_PARALLELISM
-  void      setUseNextDQP         ( bool b )                                        { m_NextDQP = b; }
-  bool      getUseNextDQP         ()                                      const     { return m_NextDQP; }
-#endif
-  void      setUseLMChroma        ( bool b )                                        { m_LMChroma = b; }
-  bool      getUseLMChroma        ()                                      const     { return m_LMChroma; }
-#if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  void      setCclmCollocatedChromaFlag( bool b )                                   { m_cclmCollocatedChromaFlag = b; }
-  bool      getCclmCollocatedChromaFlag()                                 const     { return m_cclmCollocatedChromaFlag; }
-#endif
-#if JVET_M0464_UNI_MTS
-  void      setUseIntraMTS        ( bool b )                                        { m_IntraMTS = b; }
-  bool      getUseIntraMTS        ()                                      const     { return m_IntraMTS; }
-  void      setUseInterMTS        ( bool b )                                        { m_InterMTS = b; }
-  bool      getUseInterMTS        ()                                      const     { return m_InterMTS; }
-#else
-  void      setUseIntraEMT        ( bool b )                                        { m_IntraEMT = b; }
-  bool      getUseIntraEMT        ()                                      const     { return m_IntraEMT; }
-  void      setUseInterEMT        ( bool b )                                        { m_InterEMT = b; }
-  bool      getUseInterEMT        ()                                      const     { return m_InterEMT; }
-#endif
-  void      setUseGBi             ( bool b )                                        { m_GBi = b; }
-  bool      getUseGBi             ()                                      const     { return m_GBi; }
-#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  void      setLadfEnabled        ( bool b )                                        { m_LadfEnabled = b; }
-  bool      getLadfEnabled        ()                                      const     { return m_LadfEnabled; }
-  void      setLadfNumIntervals   ( int i )                                         { m_LadfNumIntervals = i; }
-  int       getLadfNumIntervals   ()                                      const     { return m_LadfNumIntervals; }
-  void      setLadfQpOffset       ( int value, int idx )                            { m_LadfQpOffset[ idx ] = value; }
-  int       getLadfQpOffset       ( int idx )                             const     { return m_LadfQpOffset[ idx ]; }
-  void      setLadfIntervalLowerBound( int value, int idx )                         { m_LadfIntervalLowerBound[ idx ] = value; }
-  int       getLadfIntervalLowerBound( int idx )                          const     { return m_LadfIntervalLowerBound[ idx ]; }
-#endif
-  //=====  additional parameters  =====
-  // qtbt
-  // sub pu tmvp
-  void      setImvMode(ImvMode m) { m_ImvMode = m; m_IMV = m != 0;  }
-  ImvMode   getImvMode            ()                                      const     { return m_ImvMode; }
-
-  // multi type tree
-  unsigned  getMTTMode            ()                                      const     { return m_MTTMode; }
-  void      setMTTMode            ( unsigned    mode )                              { m_MTTMode = mode; m_MTTEnabled = ( m_MTTMode != 0 ); }
-
-  void      setUseCompositeRef(bool b) { m_compositeRefEnabled = b; }
-  bool      getUseCompositeRef()                                      const { return m_compositeRefEnabled; }
-
-  void      setUseMHIntra         ( bool b )                                        { m_MHIntra = b; }
-  bool      getUseMHIntra         ()                                      const     { return m_MHIntra; }
-  void      setUseTriangle        ( bool b )                                        { m_Triangle = b; }
-  bool      getUseTriangle        ()                                      const     { return m_Triangle; }
-  void      setIBCMode            (unsigned IBCMode)                                { m_IBCMode = IBCMode; }
-  unsigned  getIBCMode            ()                                      const     { return m_IBCMode; }
-};
-
-
 /// SPS class
 class SPS
 {
@@ -942,6 +845,16 @@ private:
   bool              m_bNoDepQuantConstraintFlag;
   bool              m_bNoSignDataHidingConstraintFlag;
 
+#if JVET_M0246_AFFINE_AMVR
+  bool              m_affineAmvrEnabledFlag;
+#endif
+#if JVET_M0147_DMVR
+  bool              m_DMVR;
+#endif
+#if JVET_M0140_SBT
+  bool              m_SBT;
+  uint8_t           m_MaxSbtSize;
+#endif
 #if HEVC_VPS
   int               m_VPSId;
 #endif
@@ -990,7 +903,9 @@ private:
 
   bool              m_sbtmvpEnabledFlag;
   bool              m_bdofEnabledFlag;
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  bool              m_disFracMmvdEnabledFlag;
+#endif
   uint32_t              m_uiBitsForPOC;
   uint32_t              m_numLongTermRefPicSPS;
   uint32_t              m_ltRefPicPocLsbSps[MAX_NUM_LONG_TERM_REF_PICS];
@@ -1018,7 +933,6 @@ private:
   VUI               m_vuiParameters;
 
   SPSRExt           m_spsRangeExtension;
-  SPSNext           m_spsNextExtension;
 
   static const int  m_winUnitX[NUM_CHROMA_FORMAT];
   static const int  m_winUnitY[NUM_CHROMA_FORMAT];
@@ -1028,6 +942,47 @@ private:
 
   bool              m_wrapAroundEnabledFlag;
   unsigned          m_wrapAroundOffset;
+#if JVET_M0483_IBC
+  unsigned          m_IBCFlag;
+#endif
+
+#if JVET_M0427_INLOOP_RESHAPER
+  bool              m_lumaReshapeEnable;
+#endif
+  // KJS: BEGIN former SPSNext parameters
+  bool              m_AMVREnabledFlag;
+  bool              m_LMChroma;                   // 17
+#if JVET_M0142_CCLM_COLLOCATED_CHROMA
+  bool              m_cclmCollocatedChromaFlag;
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  bool              m_MTS;
+#endif
+#if JVET_M0464_UNI_MTS
+  bool              m_IntraMTS;                   // 18
+  bool              m_InterMTS;                   // 19
+#else
+  bool              m_IntraEMT;                   // 18
+  bool              m_InterEMT;                   // 19
+#endif
+  bool              m_Affine;
+  bool              m_AffineType;
+  bool              m_GBi;                        //
+  bool              m_MHIntra;
+  bool              m_Triangle;
+#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
+  bool              m_LadfEnabled;
+  int               m_LadfNumIntervals;
+  int               m_LadfQpOffset[MAX_LADF_INTERVALS];
+  int               m_LadfIntervalLowerBound[MAX_LADF_INTERVALS];
+#endif
+  
+  bool        m_compositeRefEnabled;        //composite longterm reference
+#if !JVET_M0483_IBC
+  unsigned    m_IBCMode;
+#endif
+  // KJS: END former SPSNext parameters
+
 
 public:
 
@@ -1120,7 +1075,7 @@ public:
   unsigned                getMaxBTDepthIChroma()                                                    const { return m_maxBTDepth[2]; }
   void                    setMaxBTSize(unsigned    maxBTSize,
                                        unsigned    maxBTSizeI,
-                                       unsigned    maxBTSizeC) 
+                                       unsigned    maxBTSizeC)
                                                                                                           { m_maxBTSize[1] = maxBTSize; m_maxBTSize[0] = maxBTSizeI; m_maxBTSize[2] = maxBTSizeC; }
   unsigned                getMaxBTSize()                                                            const { return m_maxBTSize[1]; }
   unsigned                getMaxBTSizeI()                                                           const { return m_maxBTSize[0]; }
@@ -1189,10 +1144,18 @@ public:
 
   bool                    getSBTMVPEnabledFlag() const                                                    { return m_sbtmvpEnabledFlag; }
   void                    setSBTMVPEnabledFlag(bool b)                                                    { m_sbtmvpEnabledFlag = b; }
-  
+
   void                    setBDOFEnabledFlag(bool b)                                                      { m_bdofEnabledFlag = b; }
   bool                    getBDOFEnabledFlag() const                                                      { return m_bdofEnabledFlag; }
 
+#if JVET_M0255_FRACMMVD_SWITCH
+  bool                    getDisFracMmvdEnabledFlag() const                                               { return m_disFracMmvdEnabledFlag; }
+  void                    setDisFracMmvdEnabledFlag( bool b )                                             { m_disFracMmvdEnabledFlag = b;    }
+#endif
+#if JVET_M0147_DMVR
+  bool                    getUseDMVR()const                                                               { return m_DMVR; }
+  void                    setUseDMVR(bool b)                                                              { m_DMVR = b;    }
+#endif
   uint32_t                getMaxTLayers() const                                                           { return m_uiMaxTLayers; }
   void                    setMaxTLayers( uint32_t uiMaxTLayers )                                          { CHECK( uiMaxTLayers > MAX_TLAYER, "Invalid number T-layers" ); m_uiMaxTLayers = uiMaxTLayers; }
 
@@ -1220,6 +1183,10 @@ public:
   void                    setUseStrongIntraSmoothing(bool bVal)                                           { m_useStrongIntraSmoothing = bVal;                                    }
   bool                    getUseStrongIntraSmoothing() const                                              { return m_useStrongIntraSmoothing;                                    }
 
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  void                    setAffineAmvrEnabledFlag( bool val )                                            { m_affineAmvrEnabledFlag = val;                                       }
+  bool                    getAffineAmvrEnabledFlag() const                                                { return m_affineAmvrEnabledFlag;                                      }
 #endif
   bool                    getVuiParametersPresentFlag() const                                             { return m_vuiParametersPresentFlag;                                   }
   void                    setVuiParametersPresentFlag(bool b)                                             { m_vuiParametersPresentFlag = b;                                      }
@@ -1231,13 +1198,83 @@ public:
   const SPSRExt&          getSpsRangeExtension() const                                                    { return m_spsRangeExtension;                                          }
   SPSRExt&                getSpsRangeExtension()                                                          { return m_spsRangeExtension;                                          }
 
-  const SPSNext&          getSpsNext() const                                                              { return m_spsNextExtension;                                           }
-  SPSNext&                getSpsNext()                                                                    { return m_spsNextExtension;                                           }
-
   void                    setWrapAroundEnabledFlag(bool b)                                                { m_wrapAroundEnabledFlag = b;                                         }
   bool                    getWrapAroundEnabledFlag() const                                                { return m_wrapAroundEnabledFlag;                                      }
   void                    setWrapAroundOffset(unsigned offset)                                            { m_wrapAroundOffset = offset;                                         }
   unsigned                getWrapAroundOffset() const                                                     { return m_wrapAroundOffset;                                           }
+#if JVET_M0427_INLOOP_RESHAPER
+  void                    setUseReshaper(bool b)                                                          { m_lumaReshapeEnable = b;                                                   }
+  bool                    getUseReshaper() const                                                          { return m_lumaReshapeEnable;                                                }
+#endif
+#if JVET_M0483_IBC
+  void                    setIBCFlag(unsigned IBCFlag)                                                    { m_IBCFlag = IBCFlag; }
+  unsigned                getIBCFlag() const                                                              { return m_IBCFlag; }
+#endif
+#if JVET_M0140_SBT
+  void                    setUseSBT( bool b )                                                             { m_SBT = b; }
+  bool                    getUseSBT() const                                                               { return m_SBT; }
+  void                    setMaxSbtSize( uint8_t val )                                                    { m_MaxSbtSize = val; }
+  uint8_t                 getMaxSbtSize() const                                                           { return m_MaxSbtSize; }
+#endif
+  
+  // KJS: BEGIN former SPSNext parameters
+  void      setAMVREnabledFlag    ( bool b )                                        { m_AMVREnabledFlag = b; }
+  bool      getAMVREnabledFlag    ()                                      const     { return m_AMVREnabledFlag; }
+  void      setUseAffine          ( bool b )                                        { m_Affine = b; }
+  bool      getUseAffine          ()                                      const     { return m_Affine; }
+  void      setUseAffineType      ( bool b )                                        { m_AffineType = b; }
+  bool      getUseAffineType      ()                                      const     { return m_AffineType; }
+  void      setUseLMChroma        ( bool b )                                        { m_LMChroma = b; }
+  bool      getUseLMChroma        ()                                      const     { return m_LMChroma; }
+#if JVET_M0142_CCLM_COLLOCATED_CHROMA
+  void      setCclmCollocatedChromaFlag( bool b )                                   { m_cclmCollocatedChromaFlag = b; }
+  bool      getCclmCollocatedChromaFlag()                                 const     { return m_cclmCollocatedChromaFlag; }
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  void      setUseMTS             ( bool b )                                        { m_MTS = b; }
+  bool      getUseMTS             ()                                      const     { return m_MTS; }
+#if JVET_M0464_UNI_MTS
+  bool      getUseImplicitMTS     ()                                      const     { return m_MTS && !m_IntraMTS && !m_InterMTS; }
+#else
+  bool      getUseImplicitMTS     ()                                      const     { return m_MTS && !m_IntraEMT && !m_InterEMT; }
+#endif
+#endif
+#if JVET_M0464_UNI_MTS
+  void      setUseIntraMTS        ( bool b )                                        { m_IntraMTS = b; }
+  bool      getUseIntraMTS        ()                                      const     { return m_IntraMTS; }
+  void      setUseInterMTS        ( bool b )                                        { m_InterMTS = b; }
+  bool      getUseInterMTS        ()                                      const     { return m_InterMTS; }
+#else
+  void      setUseIntraEMT        ( bool b )                                        { m_IntraEMT = b; }
+  bool      getUseIntraEMT        ()                                      const     { return m_IntraEMT; }
+  void      setUseInterEMT        ( bool b )                                        { m_InterEMT = b; }
+  bool      getUseInterEMT        ()                                      const     { return m_InterEMT; }
+#endif
+  void      setUseGBi             ( bool b )                                        { m_GBi = b; }
+  bool      getUseGBi             ()                                      const     { return m_GBi; }
+#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
+  void      setLadfEnabled        ( bool b )                                        { m_LadfEnabled = b; }
+  bool      getLadfEnabled        ()                                      const     { return m_LadfEnabled; }
+  void      setLadfNumIntervals   ( int i )                                         { m_LadfNumIntervals = i; }
+  int       getLadfNumIntervals   ()                                      const     { return m_LadfNumIntervals; }
+  void      setLadfQpOffset       ( int value, int idx )                            { m_LadfQpOffset[ idx ] = value; }
+  int       getLadfQpOffset       ( int idx )                             const     { return m_LadfQpOffset[ idx ]; }
+  void      setLadfIntervalLowerBound( int value, int idx )                         { m_LadfIntervalLowerBound[ idx ] = value; }
+  int       getLadfIntervalLowerBound( int idx )                          const     { return m_LadfIntervalLowerBound[ idx ]; }
+#endif
+  // KJS: this is encoder only, right?  
+  void      setUseCompositeRef(bool b) { m_compositeRefEnabled = b; }
+  bool      getUseCompositeRef()                                      const { return m_compositeRefEnabled; }
+  
+  void      setUseMHIntra         ( bool b )                                        { m_MHIntra = b; }
+  bool      getUseMHIntra         ()                                      const     { return m_MHIntra; }
+  void      setUseTriangle        ( bool b )                                        { m_Triangle = b; }
+  bool      getUseTriangle        ()                                      const     { return m_Triangle; }
+#if !JVET_M0483_IBC
+  void      setIBCMode            (unsigned IBCMode)                                { m_IBCMode = IBCMode; }
+  unsigned  getIBCMode            ()                                      const     { return m_IBCMode; }
+#endif
+  // KJS: END former SPSNext parameters
 };
 
 
@@ -1602,7 +1639,9 @@ private:
   uint32_t                       m_colRefIdx;
   uint32_t                       m_maxNumMergeCand;
   uint32_t                   m_maxNumAffineMergeCand;
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  bool                       m_disFracMMVD;
+#endif
   double                     m_lambdas[MAX_NUM_COMPONENT];
 
   bool                       m_abEqualRef  [NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_REF];
@@ -1665,6 +1704,9 @@ private:
 
   AlfSliceParam              m_alfSliceParam;
   LutMotionCand*             m_MotionCandLut;
+#if JVET_M0427_INLOOP_RESHAPER
+  SliceReshapeInfo           m_sliceReshapeInfo;
+#endif
 #if JVET_M0170_MRG_SHARELIST
 public:
   LutMotionCand*             m_MotionCandLuTsBkup;
@@ -1846,7 +1888,10 @@ public:
   uint32_t                    getMaxNumMergeCand() const                             { return m_maxNumMergeCand;                                     }
   void                        setMaxNumAffineMergeCand( uint32_t val )               { m_maxNumAffineMergeCand = val;  }
   uint32_t                    getMaxNumAffineMergeCand() const                       { return m_maxNumAffineMergeCand; }
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  void                        setDisFracMMVD( bool val )                             { m_disFracMMVD = val;                                          }
+  bool                        getDisFracMMVD() const                                 { return m_disFracMMVD;                                         }
+#endif
   void                        setNoOutputPriorPicsFlag( bool val )                   { m_noOutputPriorPicsFlag = val;                                }
   bool                        getNoOutputPriorPicsFlag() const                       { return m_noOutputPriorPicsFlag;                               }
 
@@ -1949,6 +1994,9 @@ public:
   void                        initMotionLUTs       ();
   void                        destroyMotionLUTs    ();
   void                        resetMotionLUTs();
+#if JVET_M0483_IBC
+  int                         getAvailableLUTIBCMrgNum() const { return m_MotionCandLut->currCntIBC; }
+#endif
   int                         getAvailableLUTMrgNum() const  { return m_MotionCandLut->currCnt; }
 #if JVET_M0170_MRG_SHARELIST
   int                         getAvailableLUTBkupMrgNum() const  { return m_MotionCandLuTsBkup->currCnt; }
@@ -1957,12 +2005,18 @@ public:
   MotionInfo                  getMotionInfoFromLUTs(int MotCandIdx) const;
   LutMotionCand*              getMotionLUTs() { return m_MotionCandLut; }
 
-
+#if JVET_M0483_IBC
+  void                        addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi, bool ibcflag);
+#else
   void                        addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi);
+#endif
 
   void                        updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu);
   void                        copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst);
-
+#if JVET_M0427_INLOOP_RESHAPER
+  const SliceReshapeInfo&     getReshapeInfo() const { return m_sliceReshapeInfo; }
+        SliceReshapeInfo&     getReshapeInfo()       { return m_sliceReshapeInfo; }
+#endif
 protected:
   Picture*              xGetRefPic        (PicList& rcListPic, int poc);
   Picture*              xGetLongTermRefPic(PicList& rcListPic, int poc, bool pocHasMsb);
@@ -2178,7 +2232,6 @@ public:
   PreCalcValues( const SPS& sps, const PPS& pps, bool _isEncoder )
     : chrFormat           ( sps.getChromaFormatIdc() )
     , multiBlock422       ( false )
-    , noMotComp           ( sps.getSpsNext().getDisableMotCompress() )
     , maxCUWidth          ( sps.getMaxCUWidth() )
     , maxCUHeight         ( sps.getMaxCUHeight() )
     , maxCUWidthMask      ( maxCUWidth  - 1 )
@@ -2211,7 +2264,6 @@ public:
 
   const ChromaFormat chrFormat;
   const bool         multiBlock422;
-  const bool         noMotComp;
   const unsigned     maxCUWidth;
   const unsigned     maxCUHeight;
   // to get CTU position, use (x & maxCUWidthMask) rather than (x % maxCUWidth)
diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp
index f2afd109dbc34b8db435b25fb24882642c21634b..44ed81e06ca1d2ef668e3ea296060cecbf6328a4 100644
--- a/source/Lib/CommonLib/TrQuant.cpp
+++ b/source/Lib/CommonLib/TrQuant.cpp
@@ -122,6 +122,7 @@ TrQuant::~TrQuant()
       xFree( m_mtsCoeffs[i] );
       m_mtsCoeffs[i] = nullptr;
     }
+    delete[] m_mtsCoeffs;
     m_mtsCoeffs = nullptr;
   }
 #endif
@@ -205,7 +206,7 @@ void TrQuant::invTransformNxN( TransformUnit &tu, const ComponentID &compID, Pel
     DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
 
 #if JVET_M0464_UNI_MTS
-    if( tu.mtsIdx == 1 )
+    if( isLuma(compID) && tu.mtsIdx == 1 )
 #else
     if( tu.transformSkip[compID] )
 #endif
@@ -292,14 +293,61 @@ void TrQuant::invRdpcmNxN(TransformUnit& tu, const ComponentID &compID, PelBuf &
 void TrQuant::getTrTypes ( TransformUnit tu, const ComponentID compID, int &trTypeHor, int &trTypeVer )
 {
 #if JVET_M0464_UNI_MTS
-  bool mtsActivated = CU::isIntra( *tu.cu ) ? tu.cs->sps->getSpsNext().getUseIntraMTS() : tu.cs->sps->getSpsNext().getUseInterMTS();
+  bool mtsActivated = CU::isIntra( *tu.cu ) ? tu.cs->sps->getUseIntraMTS() : tu.cs->sps->getUseInterMTS();
 #else
-  bool emtActivated = CU::isIntra( *tu.cu ) ? tu.cs->sps->getSpsNext().getUseIntraEMT() : tu.cs->sps->getSpsNext().getUseInterEMT();
+  bool emtActivated = CU::isIntra( *tu.cu ) ? tu.cs->sps->getUseIntraEMT() : tu.cs->sps->getUseInterEMT();
 #endif
-  
+
+#if JVET_M0303_IMPLICIT_MTS
+  bool mtsImplicit  = CU::isIntra( *tu.cu ) && tu.cs->sps->getUseImplicitMTS() && compID == COMPONENT_Y;
+#endif
+
   trTypeHor = DCT2;
   trTypeVer = DCT2;
-  
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if (tu.cu->ispMode && isLuma(compID))
+  {
+    TU::getTransformTypeISP(tu, compID, trTypeHor, trTypeVer);
+    return;
+}
+#endif
+#if JVET_M0140_SBT
+  if( tu.cu->sbtInfo && compID == COMPONENT_Y )
+  {
+    uint8_t sbtIdx = tu.cu->getSbtIdx();
+    uint8_t sbtPos = tu.cu->getSbtPos();
+
+    if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD )
+    {
+      assert( tu.lwidth() <= MTS_INTER_MAX_CU_SIZE );
+      if( tu.lheight() > MTS_INTER_MAX_CU_SIZE )
+      {
+        trTypeHor = trTypeVer = DCT2;
+      }
+      else
+      {
+        if( sbtPos == SBT_POS0 )  { trTypeHor = DCT8;  trTypeVer = DST7; }
+        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
+      }
+    }
+    else
+    {
+      assert( tu.lheight() <= MTS_INTER_MAX_CU_SIZE );
+      if( tu.lwidth() > MTS_INTER_MAX_CU_SIZE )
+      {
+        trTypeHor = trTypeVer = DCT2;
+      }
+      else
+      {
+        if( sbtPos == SBT_POS0 )  { trTypeHor = DST7;  trTypeVer = DCT8; }
+        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
+      }
+    }
+    return;
+  }
+#endif
+
 #if JVET_M0464_UNI_MTS
   if ( mtsActivated )
 #else
@@ -319,12 +367,28 @@ void TrQuant::getTrTypes ( TransformUnit tu, const ComponentID compID, int &trTy
         int indHor = tu.emtIdx &  1;
         int indVer = tu.emtIdx >> 1;
 #endif
-        
+
         trTypeHor = indHor ? DCT8 : DST7;
         trTypeVer = indVer ? DCT8 : DST7;
       }
     }
   }
+#if JVET_M0303_IMPLICIT_MTS
+  else if ( mtsImplicit )
+  {
+    int  width       = tu.blocks[compID].width;
+    int  height      = tu.blocks[compID].height;
+    bool widthDstOk  = width  >= 4 && width  <= 16;
+    bool heightDstOk = height >= 4 && height <= 16;
+
+    if ( width < height && widthDstOk )
+      trTypeHor = DST7;
+    else if ( height < width && heightDstOk )
+      trTypeVer = DST7;
+    else if ( width == height && widthDstOk )
+      trTypeHor = trTypeVer = DST7;
+  }
+#endif
 }
 
 void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPelBuf &resi, CoeffBuf &dstCoeff, const int width, const int height )
@@ -332,33 +396,44 @@ void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPel
   const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
   const unsigned bitDepth               = tu.cs->sps->getBitDepth(              toChannelType( compID ) );
   const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD];
+#if !JVET_M0102_INTRA_SUBPARTITIONS
   const int      shift_1st              = ((g_aucLog2[width ]) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange + COM16_C806_TRANS_PREC;
   const int      shift_2nd              =  (g_aucLog2[height])            + TRANSFORM_MATRIX_SHIFT                          + COM16_C806_TRANS_PREC;
+#endif
   const uint32_t transformWidthIndex    = g_aucLog2[width ] - 1;  // nLog2WidthMinus1, since transform start from 2-point
   const uint32_t transformHeightIndex   = g_aucLog2[height] - 1;  // nLog2HeightMinus1, since transform start from 2-point
+#if !JVET_M0297_32PT_MTS_ZERO_OUT
   const int      skipWidth              = width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
   const int      skipHeight             = height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
-  
+#endif
+
+#if !JVET_M0102_INTRA_SUBPARTITIONS
   CHECK( shift_1st < 0, "Negative shift" );
   CHECK( shift_2nd < 0, "Negative shift" );
-  
+#endif
+
   int trTypeHor = DCT2;
   int trTypeVer = DCT2;
-  
+
   getTrTypes ( tu, compID, trTypeHor, trTypeVer );
-  
+
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  const int      skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
+  const int      skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
+#endif
+
 #if RExt__DECODER_DEBUG_TOOL_STATISTICS
   if ( trTypeHor != DCT2 )
   {
     CodingStatistics::IncrementStatisticTool( CodingStatisticsClassType{ STATS__TOOL_EMT, uint32_t( width ), uint32_t( height ), compID } );
   }
 #endif
-  
+
   ALIGN_DATA( MEMORY_ALIGN_DEF_SIZE, TCoeff block[MAX_TU_SIZE * MAX_TU_SIZE] );
-  
+
   const Pel *resiBuf    = resi.buf;
   const int  resiStride = resi.stride;
-  
+
   for( int y = 0; y < height; y++ )
   {
     for( int x = 0; x < width; x++ )
@@ -366,11 +441,36 @@ void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPel
       block[( y * width ) + x] = resiBuf[( y * resiStride ) + x];
     }
   }
-  
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( width > 1 && height > 1 ) // 2-D transform
+  {
+    const int      shift_1st              = ((g_aucLog2[width ]) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange + COM16_C806_TRANS_PREC;
+    const int      shift_2nd              =  (g_aucLog2[height])            + TRANSFORM_MATRIX_SHIFT                          + COM16_C806_TRANS_PREC;
+    CHECK( shift_1st < 0, "Negative shift" );
+    CHECK( shift_2nd < 0, "Negative shift" );
+#endif
   TCoeff *tmp = ( TCoeff * ) alloca( width * height * sizeof( TCoeff ) );
-  
+
   fastFwdTrans[trTypeHor][transformWidthIndex ](block,        tmp, shift_1st, height,        0, skipWidth);
   fastFwdTrans[trTypeVer][transformHeightIndex](tmp, dstCoeff.buf, shift_2nd, width, skipWidth, skipHeight);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  }
+  else if( height == 1 ) //1-D horizontal transform
+  {
+    const int      shift              = ((g_aucLog2[width ]) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange + COM16_C806_TRANS_PREC;
+    CHECK( shift < 0, "Negative shift" );
+    CHECKD( ( transformWidthIndex < 0 ), "There is a problem with the width." );
+    fastFwdTrans[trTypeHor][transformWidthIndex]( block, dstCoeff.buf, shift, 1, 0, skipWidth );
+  }
+  else //if (iWidth == 1) //1-D vertical transform
+  {
+    int shift = ( ( g_aucLog2[height] ) + bitDepth + TRANSFORM_MATRIX_SHIFT ) - maxLog2TrDynamicRange + COM16_C806_TRANS_PREC;
+    CHECK( shift < 0, "Negative shift" );
+    CHECKD( ( transformHeightIndex < 0 ), "There is a problem with the height." );
+    fastFwdTrans[trTypeVer][transformHeightIndex]( block, dstCoeff.buf, shift, 1, 0, skipHeight );
+  }
+#endif
 }
 
 void TrQuant::xIT( const TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pCoeff, PelBuf &pResidual )
@@ -382,30 +482,69 @@ void TrQuant::xIT( const TransformUnit &tu, const ComponentID &compID, const CCo
   const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE];
   const TCoeff   clipMinimum            = -( 1 << maxLog2TrDynamicRange );
   const TCoeff   clipMaximum            =  ( 1 << maxLog2TrDynamicRange ) - 1;
+#if !JVET_M0102_INTRA_SUBPARTITIONS
   const int      shift_1st              =   TRANSFORM_MATRIX_SHIFT + 1 + COM16_C806_TRANS_PREC; // 1 has been added to shift_1st at the expense of shift_2nd
   const int      shift_2nd              = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
+#endif
   const uint32_t transformWidthIndex    = g_aucLog2[width ] - 1;                                // nLog2WidthMinus1, since transform start from 2-point
   const uint32_t transformHeightIndex   = g_aucLog2[height] - 1;                                // nLog2HeightMinus1, since transform start from 2-point
+#if !JVET_M0297_32PT_MTS_ZERO_OUT
   const int      skipWidth              = width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
   const int      skipHeight             = height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
-  
+#endif
+
+#if !JVET_M0102_INTRA_SUBPARTITIONS
   CHECK( shift_1st < 0, "Negative shift" );
   CHECK( shift_2nd < 0, "Negative shift" );
-  
+#endif
+
   int trTypeHor = DCT2;
   int trTypeVer = DCT2;
-  
+
   getTrTypes ( tu, compID, trTypeHor, trTypeVer );
-  
+
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  const int      skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
+  const int      skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
+#endif
+
+#if !JVET_M0102_INTRA_SUBPARTITIONS
   TCoeff *tmp   = ( TCoeff * ) alloca( width * height * sizeof( TCoeff ) );
+#endif
   TCoeff *block = ( TCoeff * ) alloca( width * height * sizeof( TCoeff ) );
-  
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( width > 1 && height > 1 ) //2-D transform
+  {
+    const int      shift_1st              =   TRANSFORM_MATRIX_SHIFT + 1 + COM16_C806_TRANS_PREC; // 1 has been added to shift_1st at the expense of shift_2nd
+    const int      shift_2nd              = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
+    CHECK( shift_1st < 0, "Negative shift" );
+    CHECK( shift_2nd < 0, "Negative shift" );
+    TCoeff *tmp = ( TCoeff * ) alloca( width * height * sizeof( TCoeff ) );
+#endif
   fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, tmp, shift_1st, width, skipWidth, skipHeight, clipMinimum, clipMaximum);
   fastInvTrans[trTypeHor][transformWidthIndex] (tmp,      block, shift_2nd, height,         0, skipWidth, clipMinimum, clipMaximum);
-  
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  }
+  else if( width == 1 ) //1-D vertical transform
+  {
+    int shift = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
+    CHECK( shift < 0, "Negative shift" );
+    CHECK( ( transformHeightIndex < 0 ), "There is a problem with the height." );
+    fastInvTrans[trTypeVer][transformHeightIndex]( pCoeff.buf, block, shift + 1, 1, 0, skipHeight, clipMinimum, clipMaximum );
+  }
+  else //if(iHeight == 1) //1-D horizontal transform
+  {
+    const int      shift              = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
+    CHECK( shift < 0, "Negative shift" );
+    CHECK( ( transformWidthIndex < 0 ), "There is a problem with the width." );
+    fastInvTrans[trTypeHor][transformWidthIndex]( pCoeff.buf, block, shift + 1, 1, 0, skipWidth, clipMinimum, clipMaximum );
+  }
+#endif
+
   Pel *resiBuf    = pResidual.buf;
   int  resiStride = pResidual.stride;
-  
+
   for( int y = 0; y < height; y++ )
   {
     for( int x = 0; x < width; x++ )
@@ -435,7 +574,7 @@ void TrQuant::xITransformSkip(const CCoeffBuf     &pCoeff,
   }
 
   int iWHScale = 1;
-#if HM_QTBT_AS_IN_JEM_QUANT
+#if HM_QTBT_AS_IN_JEM_QUANT && !JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
   if( TU::needsBlockSizeTrafoScale( area ) )
   {
     iTransformShift += ADJ_QUANT_SHIFT;
@@ -477,7 +616,11 @@ void TrQuant::xQuant(TransformUnit &tu, const ComponentID &compID, const CCoeffB
 }
 
 #if JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand, double* diagRatio, double* horVerRatio )
+#else
 void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand)
+#endif
 {
         CodingStructure &cs = *tu.cs;
   const SPS &sps            = *cs.sps;
@@ -497,8 +640,17 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
   {
     tu.mtsIdx = it->first;
     CoeffBuf tempCoeff( m_mtsCoeffs[tu.mtsIdx], rect );
+#if JVET_M0140_SBT
+    if( tu.noResidual )
+    {
+      int sumAbs = 0;
+      trCosts.push_back( TrCost( sumAbs, pos++ ) );
+      it++;
+      continue;
+    }
+#endif
 
-    if( tu.mtsIdx == 1 )
+    if( isLuma(compID) && tu.mtsIdx == 1 )
     {
       xTransformSkip( tu, compID, resiBuf, tempCoeff.buf );
     }
@@ -513,10 +665,24 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
       sumAbs += abs( tempCoeff.buf[pos] );
     }
 
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+    double scaleSAD=1.0;
+    if (isLuma(compID) && tu.mtsIdx==1 && ((g_aucLog2[width] + g_aucLog2[height]) & 1) == 1 )
+    {
+      scaleSAD=1.0/1.414213562; // compensate for not scaling transform skip coefficients by 1/sqrt(2)
+    }
+    trCosts.push_back( TrCost( int(sumAbs*scaleSAD), pos++ ) );
+#else
     trCosts.push_back( TrCost( sumAbs, pos++ ) );
+#endif
     it++;
   }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  // it gets the distribution of the DCT-II coefficients energy, which will be useful to discard ISP tests
+  CoeffBuf coeffsDCT( m_mtsCoeffs[0], rect );
+  xGetCoeffEnergy( tu, compID, coeffsDCT, diagRatio, horVerRatio );
+#endif
   int numTests = 0;
   std::vector<TrCost>::iterator itC = trCosts.begin();
   const double fac   = facBB[g_aucLog2[std::max(width, height)]-2];
@@ -533,10 +699,18 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
 #endif
 
 #if JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr, double* diagRatio, double* horVerRatio )
+#else
 void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr)
+#endif
+#else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, double* diagRatio, double* horVerRatio)
 #else
 void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx)
 #endif
+#endif
 {
         CodingStructure &cs = *tu.cs;
   const SPS &sps            = *cs.sps;
@@ -547,6 +721,15 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
   const CPelBuf resiBuf     = cs.getResiBuf(rect);
         CoeffBuf rpcCoeff   = tu.getCoeffs(compID);
 
+#if JVET_M0140_SBT
+  if( tu.noResidual )
+  {
+    uiAbsSum = 0;
+    TU::setCbfAtDepth( tu, compID, tu.depth, uiAbsSum > 0 );
+    return;
+  }
+#endif
+
   RDPCMMode rdpcmMode = RDPCM_OFF;
   rdpcmNxN(tu, compID, cQP, uiAbsSum, rdpcmMode);
 
@@ -593,7 +776,7 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
 #if JVET_M0464_UNI_MTS
       if( !loadTr )
       {
-        if( tu.mtsIdx == 1 )
+        if( isLuma(compID) && tu.mtsIdx == 1 )
 #else
       if( tu.transformSkip[compID] )
 #endif
@@ -608,6 +791,20 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
       }
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      //we do this only with the DCT-II coefficients
+      if( isLuma(compID) &&
+#if JVET_M0464_UNI_MTS
+        !loadTr && tu.mtsIdx == 0
+#else
+        !tu.cu->emtFlag
+#endif
+        )
+      {
+        //it gets the distribution of the coefficients energy, which will be useful to discard ISP tests
+        xGetCoeffEnergy( tu, compID, tempCoeff, diagRatio, horVerRatio );
+      }
+#endif
       DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
 
       xQuant( tu, compID, tempCoeff, uiAbsSum, cQP, ctx );
@@ -620,6 +817,43 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
   TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0);
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void TrQuant::xGetCoeffEnergy( TransformUnit &tu, const ComponentID &compID, const CoeffBuf& coeffs, double* diagRatio, double* horVerRatio )
+{
+  if( nullptr == diagRatio || nullptr == horVerRatio ) return;
+
+  if( tu.cu->predMode == MODE_INTRA && !tu.cu->ispMode && isLuma( compID ) && CU::canUseISPSplit( *tu.cu, compID ) != NOT_INTRA_SUBPARTITIONS )
+  {
+    const int width   = tu.cu->blocks[compID].width;
+    const int height  = tu.cu->blocks[compID].height;
+    const int log2Sl  = width <= height ? g_aucLog2[height >> g_aucLog2[width]] : g_aucLog2[width >> g_aucLog2[height]];
+    const int diPos1  = width <= height ? width  : height;
+    const int diPos2  = width <= height ? height : width;
+    const int ofsPos1 = width <= height ? 1 : coeffs.stride;
+    const int ofsPos2 = width <= height ? coeffs.stride : 1;
+
+    int wdtE = 0, hgtE = 0, diaE = 0;
+    int* gtE = width <= height ? &wdtE : &hgtE;
+    int* stE = width <= height ? &hgtE : &wdtE;
+
+    for( int pos1 = 0; pos1 < diPos1; pos1++ )
+    {
+      const int posN = pos1 << log2Sl;
+      for( int pos2 = 0; pos2 < diPos2; pos2++ )
+      {
+        const int blkP = pos1 * ofsPos1 + pos2 * ofsPos2;
+        if( posN  > pos2 ) *gtE += abs( coeffs.buf[ blkP ] );
+        if( posN  < pos2 ) *stE += abs( coeffs.buf[ blkP ] );
+        if( posN == pos2 ) diaE += abs( coeffs.buf[ blkP ] );
+      }
+    }
+
+    *horVerRatio = 0 == wdtE && 0 == hgtE ? 1 : double( wdtE ) / double( hgtE );
+    *diagRatio   = 0 == wdtE && 0 == hgtE && 0 == diaE ? 1 : double( diaE ) / double( wdtE + hgtE );
+  }
+}
+#endif
+
 void TrQuant::applyForwardRDPCM(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const RDPCMMode &mode)
 {
   const bool bLossless      = tu.cu->transQuantBypass;
@@ -762,7 +996,7 @@ void TrQuant::xTransformSkip(const TransformUnit &tu, const ComponentID &compID,
   }
 
   int iWHScale = 1;
-#if HM_QTBT_AS_IN_JEM_QUANT
+#if HM_QTBT_AS_IN_JEM_QUANT && !JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
   if( TU::needsBlockSizeTrafoScale( rect ) )
   {
     iTransformShift -= ADJ_DEQUANT_SHIFT;
diff --git a/source/Lib/CommonLib/TrQuant.h b/source/Lib/CommonLib/TrQuant.h
index aa58a29981b7f6a8ac09601972a487a8811cc6f5..9f477ea9f9d853e531634673a3396d6054008b6d 100644
--- a/source/Lib/CommonLib/TrQuant.h
+++ b/source/Lib/CommonLib/TrQuant.h
@@ -88,10 +88,19 @@ public:
   void invTransformNxN  (TransformUnit &tu, const ComponentID &compID, PelBuf &pResi, const QpParam &cQPs);
 
 #if JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void transformNxN     ( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand, double* diagRatio = nullptr, double* horVerRatio = nullptr );
+  void transformNxN     ( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr = false, double* diagRatio = nullptr, double* horVerRatio = nullptr );
+#else
   void transformNxN     (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand);
   void transformNxN     (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr=false);
+#endif
+#else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void transformNxN     (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, double* diagRatio = nullptr, double* horVerRatio = nullptr);
 #else
   void transformNxN     (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx);
+#endif
 #endif
   void rdpcmNxN         (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum,       RDPCMMode &rdpcmMode);
   void applyForwardRDPCM(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const RDPCMMode &rdpcmMode);
@@ -157,6 +166,14 @@ private:
                  const TransformUnit &tu,
                  const ComponentID   &component);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void xGetCoeffEnergy(
+                       TransformUnit  &tu,
+                 const ComponentID    &compID,
+                 const CoeffBuf       &coeffs,
+                       double*        diagRatio,
+                       double*        horVerRatio );
+#endif
 
 #ifdef TARGET_SIMD_X86
   template<X86_VEXT vext>
diff --git a/source/Lib/CommonLib/TrQuant_EMT.cpp b/source/Lib/CommonLib/TrQuant_EMT.cpp
index 3ea8ce7306e663478e28f20dfac2a5251e1b70ba..d12b5c39221667729b53ddf14ff502b3ded960d9 100644
--- a/source/Lib/CommonLib/TrQuant_EMT.cpp
+++ b/source/Lib/CommonLib/TrQuant_EMT.cpp
@@ -1018,7 +1018,7 @@ void fastInverseDST7_B16(const TCoeff *src, TCoeff *dst, int shift, int line, in
 #if JVET_M0497_FAST_DST7 && !JVET_M0497_MATRIX_MULT
   int j, k;
   TCoeff a[5], b[5], c[5], d[5], t;
-  
+
   TCoeff add = (shift > 0) ? (1 << (shift - 1)) : 0;
 
   const TMatrixCoeff *iT = g_trCoreDST7P16[TRANSFORM_INVERSE][0];
@@ -1208,7 +1208,7 @@ void fastInverseDST7_B32(const TCoeff *src, TCoeff *dst, int shift, int line, in
 
     t[0] = iT[12] * src[6*line] + iT[25] * src[19*line];
     t[1] = iT[25] * src[6*line] - iT[12] * src[19*line];
-    
+
     dst[ 0] = Clip3(outputMinimum, outputMaximum, (int)( iT[0] * a[1][0] - iT[11] * a[8][0] + iT[13] * a[7][0] + iT[24] * a[4][5] - iT[1] * a[8][5] + iT[10] * a[1][5] + iT[14] * a[4][0] + iT[23] * a[7][5] + iT[2] * a[1][1] - iT[9] * a[8][1] + iT[15] * a[7][1] + iT[22] * a[4][4] - iT[3] * a[8][4] + iT[8] * a[1][4] + iT[16] * a[4][1] + iT[21] * a[7][4] + iT[4] * a[1][2] - iT[7] * a[8][2] + iT[17] * a[7][2] + iT[20] * a[4][3] - iT[5] * a[8][3] + iT[6] * a[1][3] + iT[18] * a[4][2] + iT[19] * a[7][3] + t[0] + add) >> shift);
     dst[ 1] = Clip3(outputMinimum, outputMaximum, (int)(-iT[0] * a[4][2] - iT[11] * a[6][2] + iT[13] * a[0][3] + iT[24] * a[5][2] + iT[1] * a[2][0] + iT[10] * a[7][0] + iT[14] * a[5][5] - iT[23] * a[9][5] + iT[2] * a[7][2] + iT[9] * a[2][2] - iT[15] * a[9][3] + iT[22] * a[5][3] - iT[3] * a[6][0] - iT[8] * a[4][0] + iT[16] * a[5][0] + iT[21] * a[0][5] - iT[4] * a[4][1] - iT[7] * a[6][1] + iT[17] * a[0][4] + iT[20] * a[5][1] + iT[5] * a[2][1] + iT[6] * a[7][1] + iT[18] * a[5][4] - iT[19] * a[9][4] + t[1] + add) >> shift);
     dst[ 2] = Clip3(outputMinimum, outputMaximum, (int)(-iT[0] * a[2][4] - iT[11] * a[3][4] + iT[13] * a[0][4] + iT[24] * a[1][4] + iT[1] * a[4][3] + iT[10] * a[7][2] + iT[14] * a[1][2] - iT[23] * a[8][2] + iT[2] * a[3][0] - iT[9] * a[6][5] - iT[15] * a[8][0] + iT[22] * a[9][5] - iT[3] * a[6][4] + iT[8] * a[3][1] + iT[16] * a[9][4] - iT[21] * a[8][1] + iT[4] * a[7][3] + iT[7] * a[4][2] - iT[17] * a[8][3] + iT[20] * a[1][3] - iT[5] * a[3][5] - iT[6] * a[2][5] + iT[18] * a[1][5] + iT[19] * a[0][5] + t[1] + add) >> shift);
@@ -1240,7 +1240,7 @@ void fastInverseDST7_B32(const TCoeff *src, TCoeff *dst, int shift, int line, in
     dst[19] = Clip3(outputMinimum, outputMaximum, (int)(iT[19] * b[0] + iT[ 4] * b[1] - iT[29] * b[2] + iT[ 9] * b[3] + iT[14] * b[4] - iT[24] * b[5] + add) >> shift);
     dst[24] = Clip3(outputMinimum, outputMaximum, (int)(iT[24] * b[0] - iT[ 9] * b[1] - iT[ 4] * b[2] + iT[19] * b[3] - iT[29] * b[4] + iT[14] * b[5] + add) >> shift);
     dst[29] = Clip3(outputMinimum, outputMaximum, (int)(iT[29] * b[0] - iT[24] * b[1] + iT[19] * b[2] - iT[14] * b[3] + iT[ 9] * b[4] - iT[ 4] * b[5] + add) >> shift);
-    
+
     dst[12] = Clip3(outputMinimum, outputMaximum, (int)(iT[12]*c[0] + iT[25]*c[1] + add) >> shift);
     dst[25] = Clip3(outputMinimum, outputMaximum, (int)(iT[25]*c[0] - iT[12]*c[1] + add) >> shift);
 
@@ -1411,7 +1411,7 @@ void fastInverseDCT8_B16(const TCoeff *src, TCoeff *dst, int shift, int line, in
 #if JVET_M0497_FAST_DST7 && !JVET_M0497_MATRIX_MULT
   int j, k;
   TCoeff a[5], b[5], c[5], d[5], t;
-  
+
   TCoeff add = (shift > 0) ? (1 << (shift - 1)) : 0;
 
   const TMatrixCoeff *iT = g_trCoreDST7P16[TRANSFORM_INVERSE][0];
@@ -1495,14 +1495,14 @@ void fastForwardDCT8_B32(const TCoeff *src, TCoeff *dst, int shift, int line, in
 
       b[k] = src[31-k] + src[20+k] - src[18-k] - src[7+k] + src[5-k];
     }
-    
+
     for (k = 0; k < 2; k++)
     {
       c[k] = src[31-k] + src[28+k] - src[26-k] - src[23+k] + src[21-k] + src[18+k] - src[16-k] - src[13+k] + src[11-k] + src[8+k] - src[6-k] - src[3+k] + src[1-k];
     }
-    
-    t[0] = iT[12] * src[19] + iT[25] * src[6]; 
-    t[1] = iT[12] * src[6] - iT[25] * src[19]; 
+
+    t[0] = iT[12] * src[19] + iT[25] * src[6];
+    t[1] = iT[12] * src[6] - iT[25] * src[19];
 
     dst[ 0 * line] = (   iT[0] * a[3][0] + iT[11] * a[6][5] + iT[13] * a[8][0] + iT[24] * a[9][5] + iT[1] * a[3][1] + iT[10] * a[6][4] + iT[14] * a[8][1] + iT[23] * a[9][4] + iT[2] * a[3][2] + iT[9] * a[6][3] + iT[15] * a[8][2] + iT[22] * a[9][3] + iT[3] * a[3][3] + iT[8] * a[6][2] + iT[16] * a[8][3] + iT[21] * a[9][2] + iT[4] * a[3][4] + iT[7] * a[6][1] + iT[17] * a[8][4] + iT[20] * a[9][1] + iT[5] * a[3][5] + iT[6] * a[6][0] + iT[18] * a[8][5] + iT[19] * a[9][0] + t[0] + add) >> shift;
     dst[ 1 * line] = (   iT[0] * a[5][2] - iT[11] * a[0][3] - iT[13] * a[4][2] - iT[24] * a[6][2] - iT[1] * a[9][1] - iT[10] * a[8][4] - iT[14] * a[3][4] - iT[23] * a[6][1] - iT[2] * a[0][0] + iT[9] * a[5][5] - iT[15] * a[6][5] - iT[22] * a[4][5] + iT[3] * a[5][3] - iT[8] * a[0][2] - iT[16] * a[4][3] - iT[21] * a[6][3] - iT[4] * a[9][0] - iT[7] * a[8][5] - iT[17] * a[3][5] - iT[20] * a[6][0] - iT[5] * a[0][1] + iT[6] * a[5][4] - iT[18] * a[6][4] - iT[19] * a[4][4] + t[1] + add) >> shift;
@@ -1535,7 +1535,7 @@ void fastForwardDCT8_B32(const TCoeff *src, TCoeff *dst, int shift, int line, in
     dst[17 * line] = ( - iT[29] * b[0] + iT[ 4] * b[1] + iT[24] * b[2] - iT[ 9] * b[3] - iT[19] * b[4] + iT[14] * b[5] + add) >> shift;
     dst[22 * line] = (   iT[19] * b[0] - iT[24] * b[1] + iT[ 4] * b[2] + iT[14] * b[3] - iT[29] * b[4] + iT[ 9] * b[5] + add) >> shift;
     dst[27 * line] = ( - iT[ 9] * b[0] + iT[19] * b[1] - iT[29] * b[2] + iT[24] * b[3] - iT[14] * b[4] + iT[ 4] * b[5] + add) >> shift;
-                       
+
     dst[ 6 * line] = (   iT[12] * c[0] + iT[25] * c[1] + add) >> shift;
     dst[19 * line] = ( - iT[25] * c[0] + iT[12] * c[1] + add) >> shift;
 
@@ -1600,8 +1600,8 @@ void fastInverseDCT8_B32(const TCoeff *src, TCoeff *dst, int shift, int line, in
       c[k] = src[(31 - k)*line] + src[(28 + k)*line] - src[(26 - k)*line] - src[(23 + k)*line] + src[(21 - k)*line] + src[(18 + k)*line] - src[(16 - k)*line] - src[(13 + k)*line] + src[(11 - k)*line] + src[(8 + k)*line] - src[(6 - k)*line] - src[(3 + k)*line] + src[(1 - k)*line];
     }
 
-    t[0] = iT[12] * src[19 * line] + iT[25] * src[ 6 * line]; 
-    t[1] = iT[12] * src[ 6 * line] - iT[25] * src[19 * line]; 
+    t[0] = iT[12] * src[19 * line] + iT[25] * src[ 6 * line];
+    t[1] = iT[12] * src[ 6 * line] - iT[25] * src[19 * line];
 
     dst[ 0] = Clip3(outputMinimum, outputMaximum, (int)(   iT[0] * a[3][0] + iT[11] * a[6][5] + iT[13] * a[8][0] + iT[24] * a[9][5] + iT[1] * a[3][1] + iT[10] * a[6][4] + iT[14] * a[8][1] + iT[23] * a[9][4] + iT[2] * a[3][2] + iT[9] * a[6][3] + iT[15] * a[8][2] + iT[22] * a[9][3] + iT[3] * a[3][3] + iT[8] * a[6][2] + iT[16] * a[8][3] + iT[21] * a[9][2] + iT[4] * a[3][4] + iT[7] * a[6][1] + iT[17] * a[8][4] + iT[20] * a[9][1] + iT[5] * a[3][5] + iT[6] * a[6][0] + iT[18] * a[8][5] + iT[19] * a[9][0] + t[0] + add) >> shift);
     dst[ 1] = Clip3(outputMinimum, outputMaximum, (int)(   iT[0] * a[5][2] - iT[11] * a[0][3] - iT[13] * a[4][2] - iT[24] * a[6][2] - iT[1] * a[9][1] - iT[10] * a[8][4] - iT[14] * a[3][4] - iT[23] * a[6][1] - iT[2] * a[0][0] + iT[9] * a[5][5] - iT[15] * a[6][5] - iT[22] * a[4][5] + iT[3] * a[5][3] - iT[8] * a[0][2] - iT[16] * a[4][3] - iT[21] * a[6][3] - iT[4] * a[9][0] - iT[7] * a[8][5] - iT[17] * a[3][5] - iT[20] * a[6][0] - iT[5] * a[0][1] + iT[6] * a[5][4] - iT[18] * a[6][4] - iT[19] * a[4][4] + t[1] + add) >> shift);
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 7e15e14992f67adeb9ea2d1d6e8c0f46e1cda2e2..46832b51cc8356467ff4f5d2cf55fff7a812dee3 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,50 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_M0055_DEBUG_CTU                              1 // DebugCTU encoder debug option
+
+#define JVET_M0297_32PT_MTS_ZERO_OUT                      1 // 32 point MTS based on skipping high frequency coefficients
+
+#define JVET_M0126_HMVP_MRG_PRUNING                       1 // HMVP merge candidates pruning simplification
+
+#define JVET_M0483_IBC                                    1 // Block level flag signaling and independent IBC mode
+
+#define JVET_M0102_INTRA_SUBPARTITIONS                    1
+
+#define JVET_M0303_IMPLICIT_MTS                           1 // Implicit transform selection (can be enabled with MTSImplicit encoder config parameter)
+
+#define FIX_DB_MAX_TRANSFORM_SIZE                         1
+#define JVET_M0908_CIIP_DB                                1
+#define JVET_M0471_LONG_DEBLOCKING_FILTERS                1
+#define JVET_M0427_INLOOP_RESHAPER                        1
+#define JVET_M0470                                        1 // Fixed GR/TU+EG-k transition point, use limited prefix length for escape codes
+
+#define JVET_M0253_HASH_ME                                1
+
+#define JVET_M0257                                        1 // Scan only non zero-out regions of large TUs
+#define JVET_M0193_PAIR_AVG_REDUCTION                     1 //Use only one pairwise average candidate
+
+#define JVET_M0281_AMVP_ROUNDING                          1 // Perform all AMVP rounding before pruning even AMVR is off
+
+#define JVET_M0117_AMVP_LIST_GEN                          1 // AMVP candidate list generation simplification
+
+#define JVET_M0192_AFF_CHROMA_SIMPL                       1 // Affine chroma MV derivation simplification and rounding unification
+
+#define JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET               1 // Only use left neighbor for ATMVP offset derivation, from M0273, M0240, M0116, M0338, M0204
+
+#define JVET_M0063_BDOF_FIX                               1 // BDOF bitdepth bugfix
+
+#define JVET_M0265_MV_ROUNDING_CLEANUP                    1 // Unify MV roundings and make SW/WD allignment
+#define JVET_M0883_TRIANGLE_SIGNALING                     1 // Using regular merge index signaling for triangle mode
+
+#define JVET_M0228_REMOVE_CPMV_COMPARE                    1 // Remove CPMV comparisons for construnted affine merge candidates from JVET-M0228, M0166, M0477
+
+#define JVET_M0145_AFFINE_MV_CLIP                         1 // Missing clipping for MV storage in affine
+
+#define JVET_M0264_HMVP_WITH_GBIIDX                       1 // Harmonization between HMVP and GBi
+
+#define JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX           1 // CE2.2.2 a: one context for subblock Merge index
+
 #define JVET_M0118_M0185_TRIANGLE_FLAG_FIX                1 // Avoid signaling triangle flag if a CU uses MMVD or CIIP
 
 #define JVET_M0487_INT_EXTEND                             1  // CE9.1.1 b: integer reference samples as 1 extended samples
@@ -65,6 +109,7 @@
 
 #define JVET_M0142_CCLM_COLLOCATED_CHROMA                 1 // Adding support for chroma sample location type 2 in CCLM
 
+#define JVET_M0328_KEEP_ONE_WEIGHT_GROUP                  1
 
 #define JVET_M0479_18BITS_MV_CLIP                         1
 
@@ -74,31 +119,52 @@
 #endif
 #define JVET_M0502_PRED_MODE_CTX                          1
 
+#define JVET_M0140_SBT                                    1 // Sub-Block transform for Inter blocks
+#if JVET_M0140_SBT
+#define APPLY_SBT_SL_ON_MTS                               1 // apply save & load fast algorithm on inter MTS when SBT is on
+#endif
+
 #define JVET_M0407_IBC_RANGE                              1 // extend IBC search range to some part of left CTU
 
 #define JVET_M0464_UNI_MTS                                1
 #define JVET_M0068_M0171_MMVD_CLEANUP                     1 // MMVD cleanup with 1) flip removal, 2) L1 zero vector fix, 3) bi-pred restriction after merge/MMVD
+#define JVET_M0255_FRACMMVD_SWITCH                        1 // disable fractional MVD in MMVD adaptively
+#define JVET_M0854_FRACMMVD_SWITCH_FOR_UHD                1 // disable fractional MVD for UHD pictures
+#define JVET_M0823_MMVD_ENCOPT                            1 // encoder optimization for MMVD
+
+#define JVET_M0147_DMVR                                   1 //Decoder side Motion Vector Refinement
 
 #if JVET_M0464_UNI_MTS
 typedef std::pair<int, bool> TrMode;
 typedef std::pair<int, int>  TrCost;
 #endif
 
+#define JVET_M0246_AFFINE_AMVR                            1
+#if JVET_M0246_AFFINE_AMVR
+#define JVET_M0247_AFFINE_AMVR_ENCOPT                     1
+#endif
 #define JVET_M0421_SPLIT_SIG                              1
 
 #define JVET_M0173_MOVE_GT2_TO_FIRST_PASS                 1 // Moving the gtr2 flag to the first coding pass
 
 #define REMOVE_BIN_DECISION_TREE                          1
 
-#define JVET_M0446_M0888_M0905_VPDU_AT_PIC_BOUNDARY       1 
+#define JVET_M0446_M0888_M0905_VPDU_AT_PIC_BOUNDARY       1
 
 // clang-format off
 #define JVET_M0453_CABAC_ENGINE                           1
+#define JVET_M0512_MOTION_BUFFER_COMPRESSION              1
+#define JVET_M0238_PDPC_NO_INTERPOLATION                  1
 
 #define JVET_M0409_ATMVP_FIX                              1
 
+#define ENABLE_JVET_L0283_MRL                             1 // 1: Enable MRL, 0: Disable MRL
 #define JVET_L0090_PAIR_AVG                               1 // Add pairwise average candidates, replace HEVC combined candidates
 #define REUSE_CU_RESULTS                                  1
+#if REUSE_CU_RESULTS && JVET_M0102_INTRA_SUBPARTITIONS
+#define REUSE_CU_RESULTS_WITH_MULTIPLE_TUS                1
+#define MAX_NUM_TUS                                       4
+#endif
 // clang-format on
 
 #ifndef JVET_B0051_NON_MPM_MODE
@@ -148,24 +214,27 @@ typedef std::pair<int, int>  TrCost;
 
 #ifndef ENABLE_TRACING
 #define ENABLE_TRACING                                    0 // DISABLE by default (enable only when debugging, requires 15% run-time in decoding) -- see documentation in 'doc/DTrace for NextSoftware.pdf'
+#endif
+
 #if ENABLE_TRACING
 #define K0149_BLOCK_STATISTICS                            1 // enables block statistics, which can be analysed with YUView (https://github.com/IENT/YUView)
 #if K0149_BLOCK_STATISTICS
 #define BLOCK_STATS_AS_CSV                                0 // statistics will be written in a comma separated value format. this is not supported by YUView
 #endif
 #endif
-#endif // ! ENABLE_TRACING
 
+#if JVET_M0427_INLOOP_RESHAPER
+#define WCG_EXT                                           1
+#else
 #define WCG_EXT                                           0 // part of JEM sharp Luma qp
+#endif
 #define WCG_WPSNR                                         WCG_EXT
 
 #if HEVC_TOOLS
 #define HEVC_USE_INTRA_SMOOTHING_T32                      1
 #define HEVC_USE_INTRA_SMOOTHING_T64                      1
-#define JEM_USE_INTRA_BOUNDARY                            1
 #define HEVC_USE_DC_PREDFILTERING                         1
 #define HEVC_USE_HOR_VER_PREDFILTERING                    1
-#define HEVC_USE_4x4_DSTVII                               1
 #define HEVC_USE_MDCS                                     1
 #define HEVC_USE_SIGN_HIDING                              1
 #define HEVC_USE_SCALING_LISTS                            1
@@ -192,6 +261,8 @@ typedef std::pair<int, int>  TrCost;
 #define HM_JEM_CLIP_PEL                                   1   // ***
 #define HM_JEM_MERGE_CANDS                                0   // ***
 
+#define JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT 1 ///< When 1, do not scale transform skip blocks by sqrt(2) between (I)Transform and (I)Quantizer
+
 #endif//JEM_COMP
 
 // ====================================================================================================================
@@ -248,7 +319,7 @@ typedef std::pair<int, int>  TrCost;
 #define ENABLE_SIMD_OPT_AFFINE_ME                       ( 1 && ENABLE_SIMD_OPT )                            ///< SIMD optimization for affine ME, no impact on RD performance
 #define ENABLE_SIMD_OPT_ALF                             ( 1 && ENABLE_SIMD_OPT )                            ///< SIMD optimization for ALF
 #if ENABLE_SIMD_OPT_BUFFER
-#define ENABLE_SIMD_OPT_GBI                               1                                                 ///< SIMD optimization for GBi   
+#define ENABLE_SIMD_OPT_GBI                               1                                                 ///< SIMD optimization for GBi
 #endif
 
 // End of SIMD optimizations
@@ -348,6 +419,50 @@ enum TransType
   DCT2_EMT = 4
 };
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+enum ISPType
+{
+  NOT_INTRA_SUBPARTITIONS       = 0,
+  HOR_INTRA_SUBPARTITIONS       = 1,
+  VER_INTRA_SUBPARTITIONS       = 2,
+  NUM_INTRA_SUBPARTITIONS_MODES = 3,
+  CAN_USE_VER_AND_HORL_SPLITS   = 4
+};
+#endif
+
+#if JVET_M0140_SBT
+enum SbtIdx
+{
+  SBT_OFF_DCT  = 0,
+  SBT_VER_HALF = 1,
+  SBT_HOR_HALF = 2,
+  SBT_VER_QUAD = 3,
+  SBT_HOR_QUAD = 4,
+  NUMBER_SBT_IDX,
+  SBT_OFF_MTS, //note: must be after all SBT modes, only used in fast algorithm to discern the best mode is inter EMT
+};
+
+enum SbtPos
+{
+  SBT_POS0 = 0,
+  SBT_POS1 = 1,
+  NUMBER_SBT_POS
+};
+
+enum SbtMode
+{
+  SBT_VER_H0 = 0,
+  SBT_VER_H1 = 1,
+  SBT_HOR_H0 = 2,
+  SBT_HOR_H1 = 3,
+  SBT_VER_Q0 = 4,
+  SBT_VER_Q1 = 5,
+  SBT_HOR_Q0 = 6,
+  SBT_HOR_Q1 = 7,
+  NUMBER_SBT_MODE
+};
+#endif
+
 enum RDPCMMode
 {
   RDPCM_OFF             = 0,
@@ -439,7 +554,12 @@ enum PredMode
 {
   MODE_INTER                 = 0,     ///< inter-prediction mode
   MODE_INTRA                 = 1,     ///< intra-prediction mode
+#if JVET_M0483_IBC
+  MODE_IBC                   = 2,     ///< ibc-prediction mode
+  NUMBER_OF_PREDICTION_MODES = 3,
+#else
   NUMBER_OF_PREDICTION_MODES = 2,
+#endif
 };
 
 /// reference list index
@@ -883,7 +1003,7 @@ enum MergeType
 {
   MRG_TYPE_DEFAULT_N        = 0, // 0
   MRG_TYPE_SUBPU_ATMVP,
-  MRG_TYPE_IBC,                  
+  MRG_TYPE_IBC,
   NUM_MRG_TYPE                   // 5
 };
 
@@ -1116,6 +1236,15 @@ enum MsgLevel
   VERBOSE = 5,
   DETAILS = 6
 };
+#if JVET_M0427_INLOOP_RESHAPER
+enum RESHAPE_SIGNAL_TYPE
+{
+  RESHAPE_SIGNAL_SDR = 0,
+  RESHAPE_SIGNAL_PQ  = 1,
+  RESHAPE_SIGNAL_HLG = 2,
+  RESHAPE_SIGNAL_NULL = 100,
+};
+#endif
 
 
 // ---------------------------------------------------------------------------
@@ -1458,10 +1587,10 @@ struct AlfSliceParam
   short                        lumaCoeff[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF]; // alf_coeff_luma_delta[i][j]
   short                        chromaCoeff[MAX_NUM_ALF_CHROMA_COEFF];                   // alf_coeff_chroma[i]
   short                        filterCoeffDeltaIdx[MAX_NUM_ALF_CLASSES];                // filter_coeff_delta[i]
-  bool                         filterCoeffFlag[MAX_NUM_ALF_CLASSES];                    // filter_coefficient_flag[i]
+  bool                         alfLumaCoeffFlag[MAX_NUM_ALF_CLASSES];                   // alf_luma_coeff_flag[i]
   int                          numLumaFilters;                                          // number_of_filters_minus1 + 1
-  bool                         coeffDeltaFlag;                                          // alf_coefficients_delta_flag
-  bool                         coeffDeltaPredModeFlag;                                  // coeff_delta_pred_mode_flag
+  bool                         alfLumaCoeffDeltaFlag;                                   // alf_luma_coeff_delta_flag
+  bool                         alfLumaCoeffDeltaPredictionFlag;                         // alf_luma_coeff_delta_prediction_flag
   std::vector<AlfFilterShape>* filterShapes;
 
   void reset()
@@ -1470,10 +1599,10 @@ struct AlfSliceParam
     std::memset( lumaCoeff, 0, sizeof( lumaCoeff ) );
     std::memset( chromaCoeff, 0, sizeof( chromaCoeff ) );
     std::memset( filterCoeffDeltaIdx, 0, sizeof( filterCoeffDeltaIdx ) );
-    std::memset( filterCoeffFlag, true, sizeof( filterCoeffFlag ) );
+    std::memset( alfLumaCoeffFlag, true, sizeof( alfLumaCoeffFlag ) );
     numLumaFilters = 1;
-    coeffDeltaFlag = false;
-    coeffDeltaPredModeFlag = false;
+    alfLumaCoeffDeltaFlag = false;
+    alfLumaCoeffDeltaPredictionFlag = false;
   }
 
   const AlfSliceParam& operator = ( const AlfSliceParam& src )
@@ -1482,10 +1611,10 @@ struct AlfSliceParam
     std::memcpy( lumaCoeff, src.lumaCoeff, sizeof( lumaCoeff ) );
     std::memcpy( chromaCoeff, src.chromaCoeff, sizeof( chromaCoeff ) );
     std::memcpy( filterCoeffDeltaIdx, src.filterCoeffDeltaIdx, sizeof( filterCoeffDeltaIdx ) );
-    std::memcpy( filterCoeffFlag, src.filterCoeffFlag, sizeof( filterCoeffFlag ) );
+    std::memcpy( alfLumaCoeffFlag, src.alfLumaCoeffFlag, sizeof( alfLumaCoeffFlag ) );
     numLumaFilters = src.numLumaFilters;
-    coeffDeltaFlag = src.coeffDeltaFlag;
-    coeffDeltaPredModeFlag = src.coeffDeltaPredModeFlag;
+    alfLumaCoeffDeltaFlag = src.alfLumaCoeffDeltaFlag;
+    alfLumaCoeffDeltaPredictionFlag = src.alfLumaCoeffDeltaPredictionFlag;
     filterShapes = src.filterShapes;
     return *this;
   }
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index ecaf89ca16990d33b31fcee0e1c6c86d1e0c0d15..aed894214e8ef54511e2fa2b3df9679bff5ae53e 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -189,6 +189,16 @@ bool UnitArea::contains( const UnitArea& other, const ChannelType chType ) const
   return any && ret;
 }
 
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+void UnitArea::resizeTo( const UnitArea& unitArea )
+{
+  for( uint32_t i = 0; i < blocks.size(); i++ )
+  {
+    blocks[i].resizeTo( unitArea.blocks[i] );
+  }
+}
+#endif
+
 void UnitArea::repositionTo(const UnitArea& unitArea)
 {
   for(uint32_t i = 0; i < blocks.size(); i++)
@@ -261,6 +271,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
   qp                = other.qp;
   chromaQpAdj       = other.chromaQpAdj;
   rootCbf           = other.rootCbf;
+#if JVET_M0140_SBT
+  sbtInfo           = other.sbtInfo;
+#endif
 #if !JVET_M0464_UNI_MTS
   emtFlag           = other.emtFlag;
 #endif
@@ -277,11 +290,15 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
   shareParentPos    = other.shareParentPos;
   shareParentSize   = other.shareParentSize;
 #endif
+#if JVET_M0483_IBC==0
   ibc               = other.ibc;
+#endif
 #if JVET_M0444_SMVD
   smvdMode        = other.smvdMode;
 #endif
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  ispMode           = other.ispMode;
+#endif
   return *this;
 }
 
@@ -303,6 +320,9 @@ void CodingUnit::initData()
   qp                = 0;
   chromaQpAdj       = 0;
   rootCbf           = true;
+#if JVET_M0140_SBT
+  sbtInfo           = 0;
+#endif
 #if !JVET_M0464_UNI_MTS
   emtFlag           = 0;
 #endif
@@ -319,12 +339,85 @@ void CodingUnit::initData()
   shareParentSize.width = -1;
   shareParentSize.height = -1;
 #endif
+#if JVET_M0483_IBC==0
   ibc               = false;
+#endif
 #if JVET_M0444_SMVD
   smvdMode        = 0;
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  ispMode           = 0;
+#endif
+}
+
+#if JVET_M0140_SBT
+const uint8_t CodingUnit::checkAllowedSbt() const
+{
+  if( !slice->getSPS()->getUseSBT() )
+  {
+    return 0;
+  }
+
+  //check on prediction mode
+#if JVET_M0483_IBC
+  if( predMode == MODE_INTRA || predMode == MODE_IBC ) //intra or IBC
+#else
+  if( predMode == MODE_INTRA || ibc ) //intra or IBC
+#endif
+  {
+    return 0;
+  }
+  if( firstPU->mhIntraFlag )
+  {
+    return 0;
+  }
+
+  uint8_t sbtAllowed = 0;
+  int cuWidth  = lwidth();
+  int cuHeight = lheight();
+  bool allow_type[NUMBER_SBT_IDX];
+  memset( allow_type, false, NUMBER_SBT_IDX * sizeof( bool ) );
+
+  //parameter
+  int maxSbtCUSize = cs->sps->getMaxSbtSize();
+  int minSbtCUSize = 1 << ( MIN_CU_LOG2 + 1 );
+
+  //check on size
+  if( cuWidth > maxSbtCUSize || cuHeight > maxSbtCUSize )
+  {
+    return 0;
+  }
+
+  allow_type[SBT_VER_HALF] = cuWidth  >= minSbtCUSize;
+  allow_type[SBT_HOR_HALF] = cuHeight >= minSbtCUSize;
+  allow_type[SBT_VER_QUAD] = cuWidth  >= ( minSbtCUSize << 1 );
+  allow_type[SBT_HOR_QUAD] = cuHeight >= ( minSbtCUSize << 1 );
+
+  for( int i = 0; i < NUMBER_SBT_IDX; i++ )
+  {
+    sbtAllowed += (uint8_t)allow_type[i] << i;
+  }
+
+  return sbtAllowed;
 }
 
+uint8_t CodingUnit::getSbtTuSplit() const
+{
+  uint8_t sbtTuSplitType = 0;
+
+  switch( getSbtIdx() )
+  {
+  case SBT_VER_HALF: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_VER_HALF_POS0_SPLIT; break;
+  case SBT_HOR_HALF: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_HALF_POS0_SPLIT; break;
+  case SBT_VER_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_VER_QUAD_POS0_SPLIT; break;
+  case SBT_HOR_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_QUAD_POS0_SPLIT; break;
+  default: assert( 0 );  break;
+  }
+
+  assert( sbtTuSplitType <= SBT_HOR_QUAD_POS1_SPLIT && sbtTuSplitType >= SBT_VER_HALF_POS0_SPLIT );
+  return sbtTuSplitType;
+}
+#endif
 
 // ---------------------------------------------------------------------------
 // prediction unit method definitions
@@ -343,12 +436,24 @@ void PredictionUnit::initData()
   // inter data
   mergeFlag   = false;
   mergeIdx    = MAX_UCHAR;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = MAX_UCHAR;
+  triangleMergeIdx0 = MAX_UCHAR;
+  triangleMergeIdx1 = MAX_UCHAR;
+#endif
   mmvdMergeFlag = false;
   mmvdMergeIdx = MAX_UINT;
   interDir    = MAX_UCHAR;
   mergeType   = MRG_TYPE_DEFAULT_N;
   bv.setZero();
   bvd.setZero();
+#if JVET_M0147_DMVR
+  mvRefine = false;
+  for (uint32_t i = 0; i < MAX_NUM_SUBCU_DMVR; i++)
+  {
+    mvdL0SubPu[i].setZero();
+  }
+#endif
   for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
     mvpIdx[i] = MAX_UCHAR;
@@ -371,6 +476,9 @@ void PredictionUnit::initData()
   shareParentSize.width = -1;
   shareParentSize.height = -1;
 #endif
+#if JVET_M0823_MMVD_ENCOPT
+  mmvdEncOptMode = 0;
+#endif
 }
 
 PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData)
@@ -388,12 +496,24 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
 {
   mergeFlag   = predData.mergeFlag;
   mergeIdx    = predData.mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = predData.triangleSplitDir  ;
+  triangleMergeIdx0 = predData.triangleMergeIdx0 ;
+  triangleMergeIdx1 = predData.triangleMergeIdx1 ;
+#endif
   mmvdMergeFlag = predData.mmvdMergeFlag;
   mmvdMergeIdx = predData.mmvdMergeIdx;
   interDir    = predData.interDir;
   mergeType   = predData.mergeType;
   bv          = predData.bv;
   bvd         = predData.bvd;
+#if JVET_M0147_DMVR
+  mvRefine = predData.mvRefine;
+  for (uint32_t i = 0; i < MAX_NUM_SUBCU_DMVR; i++)
+  {
+    mvdL0SubPu[i] = predData.mvdL0SubPu[i];
+  }
+#endif
   for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
     mvpIdx[i]   = predData.mvpIdx[i];
@@ -428,12 +548,24 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
 
   mergeFlag   = other.mergeFlag;
   mergeIdx    = other.mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = other.triangleSplitDir  ;
+  triangleMergeIdx0 = other.triangleMergeIdx0 ;
+  triangleMergeIdx1 = other.triangleMergeIdx1 ;
+#endif
   mmvdMergeFlag = other.mmvdMergeFlag;
   mmvdMergeIdx = other.mmvdMergeIdx;
   interDir    = other.interDir;
   mergeType   = other.mergeType;
   bv          = other.bv;
   bvd         = other.bvd;
+#if JVET_M0147_DMVR
+  mvRefine = other.mvRefine;
+  for (uint32_t i = 0; i < MAX_NUM_SUBCU_DMVR; i++)
+  {
+    mvdL0SubPu[i] = other.mvdL0SubPu[i];
+  }
+#endif
   for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
     mvpIdx[i]   = other.mvpIdx[i];
@@ -536,6 +668,12 @@ void TransformUnit::initData()
 #else
   emtIdx             = 0;
 #endif
+#if JVET_M0140_SBT
+  noResidual         = false;
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_chromaResScaleInv = 0;
+#endif
 }
 
 void TransformUnit::init(TCoeff **coeffs, Pel **pcmbuf)
@@ -575,6 +713,9 @@ TransformUnit& TransformUnit::operator=(const TransformUnit& other)
   mtsIdx             = other.mtsIdx;
 #else
   emtIdx             = other.emtIdx;
+#endif
+#if JVET_M0140_SBT
+  noResidual         = other.noResidual;
 #endif
   return *this;
 }
@@ -606,6 +747,9 @@ void TransformUnit::copyComponentFrom(const TransformUnit& other, const Componen
     emtIdx         = other.emtIdx;
   }
 #endif
+#if JVET_M0140_SBT
+  noResidual       = other.noResidual;
+#endif
 }
 
        CoeffBuf TransformUnit::getCoeffs(const ComponentID id)       { return  CoeffBuf(m_coeffs[id], blocks[id]); }
@@ -613,3 +757,22 @@ const CCoeffBuf TransformUnit::getCoeffs(const ComponentID id) const { return CC
 
        PelBuf   TransformUnit::getPcmbuf(const ComponentID id)       { return  PelBuf  (m_pcmbuf[id], blocks[id]); }
 const CPelBuf   TransformUnit::getPcmbuf(const ComponentID id) const { return CPelBuf  (m_pcmbuf[id], blocks[id]); }
+
+#if JVET_M0140_SBT
+void TransformUnit::checkTuNoResidual( unsigned idx )
+{
+  if( CU::getSbtIdx( cu->sbtInfo ) == SBT_OFF_DCT )
+  {
+    return;
+  }
+
+  if( ( CU::getSbtPos( cu->sbtInfo ) == SBT_POS0 && idx == 1 ) || ( CU::getSbtPos( cu->sbtInfo ) == SBT_POS1 && idx == 0 ) )
+  {
+    noResidual = true;
+  }
+}
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+int          TransformUnit::getChromaAdj()                     const { return m_chromaResScaleInv; }
+void         TransformUnit::setChromaAdj(int i)                      { m_chromaResScaleInv = i;    }
+#endif
\ No newline at end of file
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 4eb057dde4a9cfe99bc1f4970d4f1e29e9f9613d..ad4eee3b5e29daff548f36e0869ff58db1341cb7 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -153,6 +153,9 @@ struct CompArea : public Area
 
   const bool operator!=(const CompArea &other) const { return !(operator==(other)); }
 
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  void     resizeTo          (const Size& newSize)          { Size::resizeTo(newSize); }
+#endif
   void     repositionTo      (const Position& newPos)       { Position::repositionTo(newPos); }
   void     positionRelativeTo(const CompArea& origCompArea) { Position::relativeTo(origCompArea); }
 
@@ -214,6 +217,9 @@ struct UnitArea
     return true;
   }
 
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  void resizeTo    (const UnitArea& unit);
+#endif
   void repositionTo(const UnitArea& unit);
 
   const bool operator!=(const UnitArea &other) const { return !(*this == other); }
@@ -302,6 +308,9 @@ struct CodingUnit : public UnitArea
   bool           ipcm;
   uint8_t          imv;
   bool           rootCbf;
+#if JVET_M0140_SBT
+  uint8_t        sbtInfo;
+#endif
 #if HEVC_TILES_WPP
   uint32_t           tileIdx;
 #endif
@@ -316,10 +325,15 @@ struct CodingUnit : public UnitArea
   Position       shareParentPos;
   Size           shareParentSize;
 #endif
+#if JVET_M0483_IBC ==0
   bool           ibc;
+#endif
 #if JVET_M0444_SMVD
   uint8_t          smvdMode;
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  uint8_t        ispMode;
+#endif
 
   CodingUnit() : chType( CH_L ) { }
   CodingUnit(const UnitArea &unit);
@@ -342,6 +356,14 @@ struct CodingUnit : public UnitArea
   int64_t cacheId;
   bool    cacheUsed;
 #endif
+#if JVET_M0140_SBT
+  const uint8_t     getSbtIdx() const { assert( ( ( sbtInfo >> 0 ) & 0xf ) < NUMBER_SBT_IDX ); return ( sbtInfo >> 0 ) & 0xf; }
+  const uint8_t     getSbtPos() const { return ( sbtInfo >> 4 ) & 0x3; }
+  void              setSbtIdx( uint8_t idx ) { CHECK( idx >= NUMBER_SBT_IDX, "sbt_idx wrong" ); sbtInfo = ( idx << 0 ) + ( sbtInfo & 0xf0 ); }
+  void              setSbtPos( uint8_t pos ) { CHECK( pos >= 4, "sbt_pos wrong" ); sbtInfo = ( pos << 4 ) + ( sbtInfo & 0xcf ); }
+  uint8_t           getSbtTuSplit() const;
+  const uint8_t     checkAllowedSbt() const;
+#endif
 };
 
 // ---------------------------------------------------------------------------
@@ -358,6 +380,11 @@ struct InterPredictionData
 {
   bool      mergeFlag;
   uint8_t     mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  uint8_t     triangleSplitDir;
+  uint8_t     triangleMergeIdx0;
+  uint8_t     triangleMergeIdx1;
+#endif
   bool           mmvdMergeFlag;
   uint32_t       mmvdMergeIdx;
   uint8_t     interDir;
@@ -367,6 +394,10 @@ struct InterPredictionData
   Mv        mv      [NUM_REF_PIC_LIST_01];
   int16_t     refIdx  [NUM_REF_PIC_LIST_01];
   MergeType mergeType;
+#if JVET_M0147_DMVR
+  bool      mvRefine;
+  Mv        mvdL0SubPu[MAX_NUM_SUBCU_DMVR];
+#endif
   Mv        mvdAffi [NUM_REF_PIC_LIST_01][3];
   Mv        mvAffi[NUM_REF_PIC_LIST_01][3];
   bool      mhIntraFlag;
@@ -377,6 +408,9 @@ struct InterPredictionData
 #endif
   Mv        bv;                             // block vector for IBC
   Mv        bvd;                            // block vector difference for IBC
+#if JVET_M0823_MMVD_ENCOPT
+  uint8_t   mmvdEncOptMode;                  // 0: no action 1: skip chroma MC for MMVD candidate pre-selection 2: skip chroma MC and BIO for MMVD candidate pre-selection
+#endif
 };
 
 struct PredictionUnit : public UnitArea, public IntraPredictionData, public InterPredictionData
@@ -427,12 +461,18 @@ struct TransformUnit : public UnitArea
   CodingUnit      *cu;
   CodingStructure *cs;
   ChannelType      chType;
+ #if JVET_M0427_INLOOP_RESHAPER
+  int              m_chromaResScaleInv;
+#endif
 
   uint8_t        depth;
 #if JVET_M0464_UNI_MTS
   uint8_t        mtsIdx;
 #else
   uint8_t        emtIdx;
+#endif
+#if JVET_M0140_SBT
+  bool           noResidual;
 #endif
   uint8_t        cbf        [ MAX_NUM_TBLOCKS ];
   RDPCMMode    rdpcm        [ MAX_NUM_TBLOCKS ];
@@ -449,16 +489,26 @@ struct TransformUnit : public UnitArea
 
   unsigned       idx;
   TransformUnit *next;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  TransformUnit *prev;
+#endif
 
   void init(TCoeff **coeffs, Pel **pcmbuf);
 
   TransformUnit& operator=(const TransformUnit& other);
   void copyComponentFrom  (const TransformUnit& other, const ComponentID compID);
+#if JVET_M0140_SBT
+  void checkTuNoResidual( unsigned idx );
+#endif
 
          CoeffBuf getCoeffs(const ComponentID id);
   const CCoeffBuf getCoeffs(const ComponentID id) const;
          PelBuf   getPcmbuf(const ComponentID id);
   const CPelBuf   getPcmbuf(const ComponentID id) const;
+#if JVET_M0427_INLOOP_RESHAPER
+        int       getChromaAdj( )                 const;
+        void      setChromaAdj(int i);
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
   int64_t cacheId;
diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp
index dae0769736f028afa368c3d303d82047aeb09b0b..af9fce47a613a805cb6ec83779f7cc0f7811ab7c 100644
--- a/source/Lib/CommonLib/UnitPartitioner.cpp
+++ b/source/Lib/CommonLib/UnitPartitioner.cpp
@@ -139,14 +139,14 @@ void AdaptiveDepthPartitioner::setMaxMinDepth( unsigned& minDepth, unsigned& max
   const unsigned    curTileIdx  = cs.picture->tileMap->getTileIdxMap( currArea().lumaPos() );
 
   const CodingUnit* cuLeft        = cs.getCURestricted( pos.offset( -1,                               0 ), curSliceIdx, curTileIdx, chType );
-  const CodingUnit* cuBelowLeft   = cs.getCURestricted( pos.offset( -1, currArea().blocks[chType].height), curSliceIdx, curTileIdx, chType );  
+  const CodingUnit* cuBelowLeft   = cs.getCURestricted( pos.offset( -1, currArea().blocks[chType].height), curSliceIdx, curTileIdx, chType );
   const CodingUnit* cuAbove       = cs.getCURestricted( pos.offset(  0,                              -1 ), curSliceIdx, curTileIdx, chType );
-  const CodingUnit* cuAboveRight  = cs.getCURestricted( pos.offset( currArea().blocks[chType].width, -1 ), curSliceIdx, curTileIdx, chType );  
+  const CodingUnit* cuAboveRight  = cs.getCURestricted( pos.offset( currArea().blocks[chType].width, -1 ), curSliceIdx, curTileIdx, chType );
 #else
   const CodingUnit* cuLeft        = cs.getCURestricted( pos.offset( -1,                               0 ), curSliceIdx, chType );
   const CodingUnit* cuBelowLeft   = cs.getCURestricted( pos.offset( -1, currArea().blocks[chType].height), curSliceIdx, chType );
   const CodingUnit* cuAbove       = cs.getCURestricted( pos.offset(  0,                              -1 ), curSliceIdx, chType );
-  const CodingUnit* cuAboveRight  = cs.getCURestricted( pos.offset( currArea().blocks[chType].width, -1 ), curSliceIdx, chType ); 
+  const CodingUnit* cuAboveRight  = cs.getCURestricted( pos.offset( currArea().blocks[chType].width, -1 ), curSliceIdx, chType );
 #endif
 
   minDepth = stdMaxDepth;
@@ -249,12 +249,23 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
     break;
   case CU_TRIH_SPLIT:
   case CU_TRIV_SPLIT:
-    CHECK( ( cs.sps->getSpsNext().getMTTMode() & 1 ) != 1, "Triple splits are not allowed" );
     m_partStack.push_back( PartLevel( split, PartitionerImpl::getCUSubPartitions( currArea(), cs, split ) ) );
     break;
   case TU_MAX_TR_SPLIT:
     m_partStack.push_back( PartLevel( split, PartitionerImpl::getMaxTuTiling( currArea(), cs ) ) );
     break;
+#if JVET_M0140_SBT
+  case SBT_VER_HALF_POS0_SPLIT:
+  case SBT_VER_HALF_POS1_SPLIT:
+  case SBT_HOR_HALF_POS0_SPLIT:
+  case SBT_HOR_HALF_POS1_SPLIT:
+  case SBT_VER_QUAD_POS0_SPLIT:
+  case SBT_VER_QUAD_POS1_SPLIT:
+  case SBT_HOR_QUAD_POS0_SPLIT:
+  case SBT_HOR_QUAD_POS1_SPLIT:
+    m_partStack.push_back( PartLevel( split, PartitionerImpl::getSbtTuTiling( currArea(), cs, split ) ) );
+    break;
+#endif
   default:
     THROW( "Unknown split mode" );
     break;
@@ -269,6 +280,12 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
   {
     currTrDepth++;
   }
+#if JVET_M0140_SBT
+  else if( split >= SBT_VER_HALF_POS0_SPLIT && split <= SBT_HOR_QUAD_POS1_SPLIT )
+  {
+    currTrDepth++;
+  }
+#endif
   else
   {
     currTrDepth = 0;
@@ -301,7 +318,7 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
 void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& canQt, bool& canBh, bool& canBv, bool& canTh, bool& canTv )
 {
   const PartSplit implicitSplit = m_partStack.back().checkdIfImplicit ? m_partStack.back().implicitSplit : getImplicitSplit( cs );
-  
+
   const unsigned maxBTD         = cs.pcv->getMaxBtDepth( *cs.slice, chType ) + currImplicitBtDepth;
   const unsigned maxBtSize      = cs.pcv->getMaxBtSize ( *cs.slice, chType );
   const unsigned minBtSize      = cs.pcv->getMinBtSize ( *cs.slice, chType );
@@ -340,14 +357,12 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   }
 
   if( canBtt && ( area.width <= minBtSize && area.height <= minBtSize )
-      && ( ( area.width <= minTtSize && area.height <= minTtSize )
-           || cs.sps->getSpsNext().getMTTMode() == 0 ) )
+      && ( ( area.width <= minTtSize && area.height <= minTtSize ) ) )
   {
     canBtt = false;
   }
   if( canBtt && ( area.width > maxBtSize || area.height > maxBtSize )
-      && ( ( area.width > maxTtSize || area.height > maxTtSize )
-           || cs.sps->getSpsNext().getMTTMode() == 0 ) )
+      && ( ( area.width > maxTtSize || area.height > maxTtSize ) ) )
   {
     canBtt = false;
   }
@@ -366,12 +381,10 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   if( area.width <= minBtSize || area.width > maxBtSize )                              canBv = false;
   if( area.width <= MAX_TU_SIZE_FOR_PROFILE && area.height > MAX_TU_SIZE_FOR_PROFILE ) canBv = false;
 
-  if( ( cs.sps->getSpsNext().getMTTMode() & 1 ) != 1 )                                 canTh = false;
-  if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize ) 
+  if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize )
                                                                                        canTh = false;
   if( area.width > MAX_TU_SIZE_FOR_PROFILE || area.height > MAX_TU_SIZE_FOR_PROFILE )  canTh = false;
 
-  if( ( cs.sps->getSpsNext().getMTTMode() & 1 ) != 1 )                                 canTv = false;
   if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize )
                                                                                        canTv = false;
   if( area.width > MAX_TU_SIZE_FOR_PROFILE || area.height > MAX_TU_SIZE_FOR_PROFILE )  canTv = false;
@@ -418,6 +431,18 @@ bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs
   case TU_MAX_TR_SPLIT:
     return area.width > maxTrSize || area.height > maxTrSize;
     break;
+#if JVET_M0140_SBT
+  case SBT_VER_HALF_POS0_SPLIT:
+  case SBT_VER_HALF_POS1_SPLIT:
+  case SBT_HOR_HALF_POS0_SPLIT:
+  case SBT_HOR_HALF_POS1_SPLIT:
+  case SBT_VER_QUAD_POS0_SPLIT:
+  case SBT_VER_QUAD_POS1_SPLIT:
+  case SBT_HOR_QUAD_POS0_SPLIT:
+  case SBT_HOR_QUAD_POS1_SPLIT:
+    return currTrDepth == 0;
+    break;
+#endif
 #if JVET_M0421_SPLIT_SIG
   case CU_QUAD_SPLIT:
     return canQt;
@@ -485,9 +510,9 @@ bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs
   {
     if( currMtDepth >= maxBTD )                               return false;
     if(      ( area.width <= minBtSize && area.height <= minBtSize )
-        && ( ( area.width <= minTtSize && area.height <= minTtSize ) || cs.sps->getSpsNext().getMTTMode() == 0 ) ) return false;
+        && ( ( area.width <= minTtSize && area.height <= minTtSize ) ) ) return false;
     if(      ( area.width > maxBtSize || area.height > maxBtSize )
-        && ( ( area.width > maxTtSize || area.height > maxTtSize ) || cs.sps->getSpsNext().getMTTMode() == 0 ) ) return false;
+        && ( ( area.width > maxTtSize || area.height > maxTtSize ) ) ) return false;
     if (CS::isDualITree(cs) && (area.width > 64 || area.height > 64))
     {
       return false;
@@ -513,12 +538,10 @@ bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs
     if( area.width <= MAX_TU_SIZE_FOR_PROFILE && area.height > MAX_TU_SIZE_FOR_PROFILE ) return false;
     break;
   case CU_TRIH_SPLIT:
-    if( ( cs.sps->getSpsNext().getMTTMode() & 1 ) != 1 )          return false;
     if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize) return false;
     if( area.width > MAX_TU_SIZE_FOR_PROFILE || area.height > MAX_TU_SIZE_FOR_PROFILE ) return false;
     break;
   case CU_TRIV_SPLIT:
-    if( ( cs.sps->getSpsNext().getMTTMode() & 1 ) != 1 )          return false;
     if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize)  return false;
     if( area.width > MAX_TU_SIZE_FOR_PROFILE || area.height > MAX_TU_SIZE_FOR_PROFILE ) return false;
     break;
@@ -622,6 +645,13 @@ void QTBTPartitioner::exitCurrSplit()
     CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" );
     currTrDepth--;
   }
+#if JVET_M0140_SBT
+  else if( currSplit >= SBT_VER_HALF_POS0_SPLIT && currSplit <= SBT_HOR_QUAD_POS1_SPLIT )
+  {
+    CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" );
+    currTrDepth--;
+  }
+#endif
   else
   {
     CHECK( currTrDepth > 0, "RQT found with QTBT partitioner" );
@@ -671,6 +701,106 @@ bool QTBTPartitioner::hasNextPart()
   return ( ( m_partStack.back().idx + 1 ) < m_partStack.back().parts.size() );
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void TUIntraSubPartitioner::splitCurrArea( const PartSplit split, const CodingStructure& cs )
+{
+  switch( split )
+  {
+    case TU_1D_HORZ_SPLIT:
+    case TU_1D_VERT_SPLIT:
+    {
+      const UnitArea &area = currArea();
+      m_partStack.push_back( PartLevel() );
+      m_partStack.back().split = split;
+      PartitionerImpl::getTUIntraSubPartitions( m_partStack.back().parts, area, cs, split );
+      break;
+    }
+    case TU_MAX_TR_SPLIT: //we need this non ISP split because of the maxTrSize limitation
+      m_partStack.push_back( PartLevel( split, PartitionerImpl::getMaxTuTiling( currArea(), cs ) ) );
+      break;
+    default:
+      THROW( "Unknown ISP split mode" );
+      break;
+  }
+
+  currDepth++;
+  currTrDepth++; // we need this to identify the level. since the 1d partitions are forbidden if the RQT is on, there area no compatibility issues
+
+#if _DEBUG
+  m_currArea = m_partStack.back().parts.front();
+#endif
+}
+
+void TUIntraSubPartitioner::exitCurrSplit()
+{
+  PartSplit currSplit = m_partStack.back().split;
+
+  m_partStack.pop_back();
+
+  CHECK( currDepth == 0, "depth is '0', although a split was performed" );
+
+  currDepth--;
+  currTrDepth--;
+
+#if _DEBUG
+  m_currArea = m_partStack.back().parts[m_partStack.back().idx];
+#endif
+
+  CHECK( !( currSplit == TU_1D_HORZ_SPLIT || currSplit == TU_1D_VERT_SPLIT || currSplit == TU_MAX_TR_SPLIT ), "Unknown 1D partition split type!" );
+}
+
+bool TUIntraSubPartitioner::nextPart( const CodingStructure &cs, bool autoPop /*= false*/ )
+{
+  unsigned currIdx = ++m_partStack.back().idx;
+
+  m_partStack.back().checkdIfImplicit = false;
+  m_partStack.back().isImplicit = false;
+
+  if( currIdx < m_partStack.back().parts.size() )
+  {
+#if _DEBUG
+    m_currArea = m_partStack.back().parts[m_partStack.back().idx];
+#endif
+    return true;
+  }
+  else
+  {
+    if( autoPop ) exitCurrSplit();
+    return false;
+  }
+}
+
+bool TUIntraSubPartitioner::hasNextPart()
+{
+  return ( ( m_partStack.back().idx + 1 ) < m_partStack.back().parts.size() );
+}
+
+bool TUIntraSubPartitioner::canSplit( const PartSplit split, const CodingStructure &cs )
+{
+  //const PartSplit implicitSplit = getImplicitSplit(cs);
+  const UnitArea &area = currArea();
+
+  switch( split )
+  {
+    case TU_1D_HORZ_SPLIT:
+    {
+      return area.lheight() == m_partStack[0].parts[0].lheight();
+    }
+    case TU_1D_VERT_SPLIT:
+    {
+      return area.lwidth() == m_partStack[0].parts[0].lwidth();
+    }
+    case TU_MAX_TR_SPLIT:
+    {
+      //this split is performed implicitly with the other splits
+      return false;
+    }
+    default:
+      THROW( "Unknown 1-D split mode" );
+      break;
+  }
+}
+#endif
 
 
 //////////////////////////////////////////////////////////////////////////
@@ -879,6 +1009,63 @@ Partitioning PartitionerImpl::getCUSubPartitions( const UnitArea &cuArea, const
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void PartitionerImpl::getTUIntraSubPartitions( Partitioning &sub, const UnitArea &tuArea, const CodingStructure &cs, const PartSplit splitType )
+{
+  uint32_t nPartitions;
+  uint32_t splitDimensionSize = CU::getISPSplitDim( tuArea.lumaSize().width, tuArea.lumaSize().height, splitType );
+
+  bool isDualTree = CS::isDualITree( cs );
+
+  if( splitType == TU_1D_HORZ_SPLIT )
+  {
+    nPartitions = tuArea.lumaSize().height >> g_aucLog2[splitDimensionSize];
+
+    sub.resize( nPartitions );
+
+    for( uint32_t i = 0; i < nPartitions; i++ )
+    {
+      sub[i] = tuArea;
+      CompArea& blkY = sub[i].blocks[COMPONENT_Y];
+
+      blkY.height = splitDimensionSize;
+      blkY.y = i > 0 ? sub[i - 1].blocks[COMPONENT_Y].y + splitDimensionSize : blkY.y;
+
+      CHECK( sub[i].lumaSize().height < 1, "the cs split causes the block to be smaller than the minimal TU size" );
+    }
+  }
+  else if( splitType == TU_1D_VERT_SPLIT )
+  {
+    nPartitions = tuArea.lumaSize().width >> g_aucLog2[splitDimensionSize];
+
+    sub.resize( nPartitions );
+
+    for( uint32_t i = 0; i < nPartitions; i++ )
+    {
+      sub[i] = tuArea;
+      CompArea& blkY = sub[i].blocks[COMPONENT_Y];
+
+      blkY.width = splitDimensionSize;
+      blkY.x = i > 0 ? sub[i - 1].blocks[COMPONENT_Y].x + splitDimensionSize : blkY.x;
+      CHECK( sub[i].lumaSize().width < 1, "the split causes the block to be smaller than the minimal TU size" );
+    }
+  }
+  else
+  {
+    THROW( "Unknown TU sub-partitioning" );
+  }
+  //we only partition luma, so there is going to be only one chroma tu at the end (unless it is dual tree, in which case there won't be any chroma components)
+  uint32_t partitionsWithoutChroma = isDualTree ? nPartitions : nPartitions - 1;
+  for( uint32_t i = 0; i < partitionsWithoutChroma; i++ )
+  {
+    CompArea& blkCb = sub[i].blocks[COMPONENT_Cb];
+    CompArea& blkCr = sub[i].blocks[COMPONENT_Cr];
+    blkCb = CompArea();
+    blkCr = CompArea();
+  }
+}
+#endif
+
 static const int g_maxRtGridSize = 3;
 
 static const int g_zScanToX[1 << ( g_maxRtGridSize << 1 )] =
@@ -954,3 +1141,64 @@ Partitioning PartitionerImpl::getMaxTuTiling( const UnitArea &cuArea, const Codi
 
   return ret;
 }
+
+#if JVET_M0140_SBT
+Partitioning PartitionerImpl::getSbtTuTiling( const UnitArea& cuArea, const CodingStructure &cs, const PartSplit splitType )
+{
+  Partitioning ret;
+  int numTiles = 2;
+  int widthFactor, heightFactor, xOffsetFactor, yOffsetFactor; // y = (x * factor) >> 2;
+  assert( splitType >= SBT_VER_HALF_POS0_SPLIT && splitType <= SBT_HOR_QUAD_POS1_SPLIT );
+
+  ret.resize( numTiles, cuArea );
+  for( int i = 0; i < numTiles; i++ )
+  {
+    if( splitType >= SBT_VER_QUAD_POS0_SPLIT )
+    {
+      if( splitType == SBT_HOR_QUAD_POS0_SPLIT || splitType == SBT_HOR_QUAD_POS1_SPLIT )
+      {
+        widthFactor = 4;
+        xOffsetFactor = 0;
+        heightFactor = ( ( i == 0 && splitType == SBT_HOR_QUAD_POS0_SPLIT ) || ( i == 1 && splitType == SBT_HOR_QUAD_POS1_SPLIT ) ) ? 1 : 3;
+        yOffsetFactor = ( i == 0 ) ? 0 : ( splitType == SBT_HOR_QUAD_POS0_SPLIT ? 1 : 3 );
+      }
+      else
+      {
+        widthFactor = ( ( i == 0 && splitType == SBT_VER_QUAD_POS0_SPLIT ) || ( i == 1 && splitType == SBT_VER_QUAD_POS1_SPLIT ) ) ? 1 : 3;
+        xOffsetFactor = ( i == 0 ) ? 0 : ( splitType == SBT_VER_QUAD_POS0_SPLIT ? 1 : 3 );
+        heightFactor = 4;
+        yOffsetFactor = 0;
+      }
+    }
+    else
+    {
+      if( splitType == SBT_HOR_HALF_POS0_SPLIT || splitType == SBT_HOR_HALF_POS1_SPLIT )
+      {
+        widthFactor = 4;
+        xOffsetFactor = 0;
+        heightFactor = 2;
+        yOffsetFactor = ( i == 0 ) ? 0 : 2;
+      }
+      else
+      {
+        widthFactor = 2;
+        xOffsetFactor = ( i == 0 ) ? 0 : 2;
+        heightFactor = 4;
+        yOffsetFactor = 0;
+      }
+    }
+
+    UnitArea& tile = ret[i];
+    for( CompArea &comp : tile.blocks )
+    {
+      if( !comp.valid() ) continue;
+      comp.x += ( comp.width  * xOffsetFactor ) >> 2;
+      comp.y += ( comp.height * yOffsetFactor ) >> 2;
+      comp.width = ( comp.width  * widthFactor ) >> 2;
+      comp.height = ( comp.height * heightFactor ) >> 2;
+    }
+  }
+
+  return ret;
+}
+#endif
diff --git a/source/Lib/CommonLib/UnitPartitioner.h b/source/Lib/CommonLib/UnitPartitioner.h
index 222fe99edeb0a83f5ef5ab5462a25f63d1bb1eb5..3060e8459eaea49de2550f987fea8a468b7806aa 100644
--- a/source/Lib/CommonLib/UnitPartitioner.h
+++ b/source/Lib/CommonLib/UnitPartitioner.h
@@ -43,7 +43,11 @@
 #include "CommonDef.h"
 
 static_assert( MAX_CU_TILING_PARTITIONS >= 4, "Minimum required number of partitions for the Partitioning type is 4!" );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+typedef std::vector <UnitArea> Partitioning;
+#else
 typedef static_vector<UnitArea, MAX_CU_TILING_PARTITIONS> Partitioning;
+#endif
 
 //////////////////////////////////////////////////////////////////////////
 // PartManager class - manages the partitioning tree
@@ -63,6 +67,21 @@ enum PartSplit
   CU_TRIH_SPLIT,
   CU_TRIV_SPLIT,
   TU_MAX_TR_SPLIT,
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  TU_NO_ISP,
+  TU_1D_HORZ_SPLIT,
+  TU_1D_VERT_SPLIT,
+#endif
+#if JVET_M0140_SBT
+  SBT_VER_HALF_POS0_SPLIT,
+  SBT_VER_HALF_POS1_SPLIT,
+  SBT_HOR_HALF_POS0_SPLIT,
+  SBT_HOR_HALF_POS1_SPLIT,
+  SBT_VER_QUAD_POS0_SPLIT,
+  SBT_VER_QUAD_POS1_SPLIT,
+  SBT_HOR_QUAD_POS0_SPLIT,
+  SBT_HOR_QUAD_POS1_SPLIT,
+#endif
   NUM_PART_SPLIT,
   CU_MT_SPLIT             = 1000, ///< dummy element to indicate the MT (multi-type-tree) split
   CU_BT_SPLIT             = 1001, ///< dummy element to indicate the BT split
@@ -150,7 +169,7 @@ public:
   void exitCurrSplit              ();
   bool nextPart                   ( const CodingStructure &cs, bool autoPop = false );
   bool hasNextPart                ();
-  
+
 #if JVET_M0421_SPLIT_SIG
   void canSplit                   ( const CodingStructure &cs, bool& canNo, bool& canQt, bool& canBh, bool& canBv, bool& canTh, bool& canTv );
 #endif
@@ -159,6 +178,37 @@ public:
   PartSplit getImplicitSplit      (                                                 const CodingStructure &cs );
 };
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+class TUIntraSubPartitioner : public Partitioner
+{
+public:
+  TUIntraSubPartitioner(Partitioner& _initialState)
+  {
+    //we copy the input partitioner data
+    m_partStack.push_back(PartLevel(TU_NO_ISP, { _initialState.currArea() }));
+
+    currDepth    = _initialState.currDepth;
+    currQtDepth  = _initialState.currQtDepth;
+    currTrDepth  = _initialState.currTrDepth;
+    currBtDepth  = _initialState.currBtDepth;
+    currMtDepth  = _initialState.currMtDepth;
+    chType       = _initialState.chType;
+#if _DEBUG
+    m_currArea   = _initialState.currArea();
+#endif
+  }
+
+  void initCtu               (const UnitArea& ctuArea, const ChannelType chType, const Slice& slice) {}; // not needed
+  void splitCurrArea         (const PartSplit split, const CodingStructure &cs);
+  void exitCurrSplit         ();
+  bool nextPart              (const CodingStructure &cs, bool autoPop = false);
+  bool hasNextPart           ();
+  void canSplit              (const CodingStructure &cs, bool& canNo, bool& canQt, bool& canBh, bool& canBv, bool& canTh, bool& canTv) {};
+  bool canSplit              (const PartSplit split, const CodingStructure &cs);
+  bool isSplitImplicit       (const PartSplit split, const CodingStructure &cs) { return false; }; //not needed
+  PartSplit getImplicitSplit (const CodingStructure &cs) { return CU_DONT_SPLIT; }; //not needed
+};
+#endif
 
 
 
@@ -176,6 +226,12 @@ namespace PartitionerImpl
 {
   Partitioning getCUSubPartitions( const UnitArea   &cuArea, const CodingStructure &cs, const PartSplit splitType = CU_QUAD_SPLIT );
   Partitioning getMaxTuTiling    ( const UnitArea& curArea, const CodingStructure &cs );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void    getTUIntraSubPartitions( Partitioning &sub, const UnitArea &tuArea, const CodingStructure &cs, const PartSplit splitType );
+#endif
+#if JVET_M0140_SBT
+  Partitioning getSbtTuTiling    ( const UnitArea& curArea, const CodingStructure &cs, const PartSplit splitType );
+#endif
 };
 
 #endif
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 5bb6c03629e76d5b62c5bab6d180f5f04acbd58e..5a7dc7bf71254686b8669a3ae89ca16b8c3d39fb 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -65,7 +65,39 @@ UnitArea CS::getArea( const CodingStructure &cs, const UnitArea &area, const Cha
 {
   return isDualITree( cs ) ? area.singleChan( chType ) : area;
 }
-
+#if JVET_M0147_DMVR
+void CS::setRefinedMotionField(CodingStructure &cs)
+{
+  for (CodingUnit *cu : cs.cus)
+  {
+    for (auto &pu : CU::traversePUs(*cu))
+    {
+      PredictionUnit subPu = pu;
+      int dx, dy, x, y, num = 0;
+      dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT);
+      dx = std::min<int>(pu.lumaSize().width, DMVR_SUBCU_WIDTH);
+      Position puPos = pu.lumaPos();
+      if (PU::checkDMVRCondition(pu))
+      {
+        for (y = puPos.y; y < (puPos.y + pu.lumaSize().height); y = y + dy)
+        {
+          for (x = puPos.x; x < (puPos.x + pu.lumaSize().width); x = x + dx)
+          {
+            subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
+            subPu.mv[0] = pu.mv[0];
+            subPu.mv[1] = pu.mv[1];
+            subPu.mv[REF_PIC_LIST_0] += pu.mvdL0SubPu[num];
+            subPu.mv[REF_PIC_LIST_1] -= pu.mvdL0SubPu[num];
+            pu.mvdL0SubPu[num].setZero();
+            num++;
+            PU::spanMotionInfo(subPu);
+          }
+        }
+      }
+    }
+  }
+}
+#endif
 // CU tools
 
 bool CU::isIntra(const CodingUnit &cu)
@@ -78,6 +110,13 @@ bool CU::isInter(const CodingUnit &cu)
   return cu.predMode == MODE_INTER;
 }
 
+#if JVET_M0483_IBC
+bool CU::isIBC(const CodingUnit &cu)
+{
+  return cu.predMode == MODE_IBC;
+}
+#endif
+
 bool CU::isRDPCMEnabled(const CodingUnit& cu)
 {
   return cu.cs->sps->getSpsRangeExtension().getRdpcmEnabledFlag(cu.predMode == MODE_INTRA ? RDPCM_SIGNAL_IMPLICIT : RDPCM_SIGNAL_EXPLICIT);
@@ -150,25 +189,6 @@ int CU::predictQP( const CodingUnit& cu, const int prevQP )
 {
   const CodingStructure &cs = *cu.cs;
 
-#if ENABLE_WPP_PARALLELISM
-  if( cs.sps->getSpsNext().getUseNextDQP() )
-  {
-    // Inter-CTU 2D "planar"   c(orner)  a(bove)
-    // predictor arrangement:  b(efore)  p(rediction)
-
-    // restrict the lookup, as it might cross CTU/slice/tile boundaries
-    const CodingUnit *cuA = cs.getCURestricted( cu.blocks[cu.chType].pos().offset(  0, -1 ), cu, cu.chType );
-    const CodingUnit *cuB = cs.getCURestricted( cu.blocks[cu.chType].pos().offset( -1,  0 ), cu, cu.chType );
-    const CodingUnit *cuC = cs.getCURestricted( cu.blocks[cu.chType].pos().offset( -1, -1 ), cu, cu.chType );
-
-    const int a = cuA ? cuA->qp : cs.slice->getSliceQpBase();
-    const int b = cuB ? cuB->qp : cs.slice->getSliceQpBase();
-    const int c = cuC ? cuC->qp : cs.slice->getSliceQpBase();
-
-    return Clip3( ( a < b ? a : b ), ( a > b ? a : b ), a + b - c ); // derived from Martucci's Median Adaptive Prediction, 1990
-  }
-
-#endif
   // only predict within the same CTU, use HEVC's above+left prediction
   const int a = ( cu.blocks[cu.chType].y & ( cs.pcv->maxCUHeightMask >> getChannelTypeScaleY( cu.chType, cu.chromaFormat ) ) ) ? ( cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType ) )->qp : prevQP;
   const int b = ( cu.blocks[cu.chType].x & ( cs.pcv->maxCUWidthMask  >> getChannelTypeScaleX( cu.chType, cu.chromaFormat ) ) ) ? ( cs.getCU( cu.blocks[cu.chType].pos().offset( -1, 0 ), cu.chType ) )->qp : prevQP;
@@ -181,7 +201,7 @@ bool CU::isQGStart( const CodingUnit& cu, Partitioner& partitioner )
   int maxDqpDepth = cu.slice->getPPS()->getMaxCuDQPDepth();
   if( partitioner.currDepth >= maxDqpDepth )
   {
-    PartLevel splitAtMaxDepth = partitioner.getPartStack().at( maxDqpDepth ); 
+    PartLevel splitAtMaxDepth = partitioner.getPartStack().at( maxDqpDepth );
     // the parent node of qtDepth + mttDepth == maxDqpDepth
     if( splitAtMaxDepth.parts[splitAtMaxDepth.idx].blocks[partitioner.chType].pos() == cu.blocks[partitioner.chType].pos() )
       return true;
@@ -258,7 +278,175 @@ uint32_t CU::getNumNonZeroCoeffNonTs( const CodingUnit& cu )
   return count;
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+bool CU::divideTuInRows( const CodingUnit &cu )
+{
+  CHECK( cu.ispMode != HOR_INTRA_SUBPARTITIONS && cu.ispMode != VER_INTRA_SUBPARTITIONS, "Intra Subpartitions type not recognized!" );
+  return cu.ispMode == HOR_INTRA_SUBPARTITIONS ? true : false;
+}
+
+bool CU::firstTestISPHorSplit( const int width, const int height, const ComponentID compID, const CodingUnit *cuLeft, const CodingUnit *cuAbove )
+{
+  //this function decides which split mode (horizontal or vertical) is tested first (encoder only)
+  //we check the logarithmic aspect ratios of the block
+  int aspectRatio = g_aucLog2[width] - g_aucLog2[height];
+  if( aspectRatio > 0 )
+  {
+    return true;
+  }
+  else if( aspectRatio < 0 )
+  {
+    return false;
+  }
+  else //if (aspectRatio == 0)
+  {
+    //we gather data from the neighboring CUs
+    const int cuLeftWidth    = cuLeft  != nullptr                                    ? cuLeft->blocks[compID].width   : -1;
+    const int cuLeftHeight   = cuLeft  != nullptr                                    ? cuLeft->blocks[compID].height  : -1;
+    const int cuAboveWidth   = cuAbove != nullptr                                    ? cuAbove->blocks[compID].width  : -1;
+    const int cuAboveHeight  = cuAbove != nullptr                                    ? cuAbove->blocks[compID].height : -1;
+    const int cuLeft1dSplit  = cuLeft  != nullptr &&  cuLeft->predMode == MODE_INTRA ? cuLeft->ispMode                :  0;
+    const int cuAbove1dSplit = cuAbove != nullptr && cuAbove->predMode == MODE_INTRA ? cuAbove->ispMode               :  0;
+    if( cuLeftWidth != -1 && cuAboveWidth == -1 )
+    {
+      int cuLeftAspectRatio = g_aucLog2[cuLeftWidth] - g_aucLog2[cuLeftHeight];
+      return cuLeftAspectRatio < 0 ? false : cuLeftAspectRatio > 0 ? true : cuLeft1dSplit == VER_INTRA_SUBPARTITIONS ? false : true;
+    }
+    else if( cuLeftWidth == -1 && cuAboveWidth != -1 )
+    {
+      int cuAboveAspectRatio = g_aucLog2[cuAboveWidth] - g_aucLog2[cuAboveHeight];
+      return cuAboveAspectRatio < 0 ? false : cuAboveAspectRatio > 0 ? true : cuAbove1dSplit == VER_INTRA_SUBPARTITIONS ? false : true;
+    }
+    else if( cuLeftWidth != -1 && cuAboveWidth != -1 )
+    {
+      int cuLeftAspectRatio = g_aucLog2[cuLeftWidth] - g_aucLog2[cuLeftHeight];
+      int cuAboveAspectRatio = g_aucLog2[cuAboveWidth] - g_aucLog2[cuAboveHeight];
+      if( cuLeftAspectRatio < 0 && cuAboveAspectRatio < 0 )
+      {
+        return false;
+      }
+      else if( cuLeftAspectRatio > 0 && cuAboveAspectRatio > 0 )
+      {
+        return true;
+      }
+      else if( cuLeftAspectRatio == 0 && cuAboveAspectRatio == 0 )
+      {
+        if( cuLeft1dSplit != 0 && cuAbove1dSplit != 0 )
+        {
+          return cuLeft1dSplit == VER_INTRA_SUBPARTITIONS && cuAbove1dSplit == VER_INTRA_SUBPARTITIONS ? false : true;
+        }
+        else if( cuLeft1dSplit != 0 && cuAbove1dSplit == 0 )
+        {
+          return cuLeft1dSplit == VER_INTRA_SUBPARTITIONS ? false : true;
+        }
+        else if( cuLeft1dSplit == 0 && cuAbove1dSplit != 0 )
+        {
+          return cuAbove1dSplit == VER_INTRA_SUBPARTITIONS ? false : true;
+        }
+        return true;
+      }
+      else
+      {
+        return cuLeftAspectRatio > cuAboveAspectRatio ? cuLeftAspectRatio > 0 : cuAboveAspectRatio > 0;
+      }
+      //return true;
+    }
+    return true;
+  }
+}
+
+PartSplit CU::getISPType( const CodingUnit &cu, const ComponentID compID )
+{
+  if( cu.ispMode && isLuma( compID ) )
+  {
+    const bool tuIsDividedInRows = CU::divideTuInRows( cu );
+
+    return tuIsDividedInRows ? TU_1D_HORZ_SPLIT : TU_1D_VERT_SPLIT;
+  }
+  return TU_NO_ISP;
+}
+
+bool CU::isISPLast( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID )
+{
+  PartSplit partitionType = CU::getISPType( cu, compID );
+
+  Area originalArea = cu.blocks[compID];
+  switch( partitionType )
+  {
+    case TU_1D_HORZ_SPLIT:
+      return tuArea.y + tuArea.height == originalArea.y + originalArea.height;
+    case TU_1D_VERT_SPLIT:
+      return tuArea.x + tuArea.width == originalArea.x + originalArea.width;
+    default:
+      THROW( "Unknown ISP processing order type!" );
+      return false;
+  }
+}
+
+bool CU::isISPFirst( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID )
+{
+  return tuArea == cu.firstTU->blocks[compID];
+}
+
+ISPType CU::canUseISPSplit( const CodingUnit &cu, const ComponentID compID )
+{
+  const int width     = cu.blocks[compID].width;
+  const int height    = cu.blocks[compID].height;
+  const int maxTrSize = cu.cs->sps->getMaxTrSize();
+  return CU::canUseISPSplit( width, height, maxTrSize );
+}
+
+ISPType CU::canUseISPSplit( const int width, const int height, const int maxTrSize )
+{
+  bool widthCannotBeUsed = false, heightCannotBeUsed = false;
+
+  const uint32_t minTuSizeForISP = MIN_TU_SIZE;
+  bool  notEnoughSamplesToSplit = ( g_aucLog2[width] + g_aucLog2[height] <= ( g_aucLog2[minTuSizeForISP] << 1 ) );
+  widthCannotBeUsed  = width  > maxTrSize || notEnoughSamplesToSplit;
+  heightCannotBeUsed = height > maxTrSize || notEnoughSamplesToSplit;
+
+  if( !widthCannotBeUsed && !heightCannotBeUsed )
+  {
+    return CAN_USE_VER_AND_HORL_SPLITS; //both splits can be used
+  }
+  else if( widthCannotBeUsed && !heightCannotBeUsed )
+  {
+    return VER_INTRA_SUBPARTITIONS; //only the vertical split can be performed
+  }
+  else if( !widthCannotBeUsed && heightCannotBeUsed )
+  {
+    return HOR_INTRA_SUBPARTITIONS; //only the horizontal split can be performed
+  }
+  else
+  {
+    return NOT_INTRA_SUBPARTITIONS; //neither of the splits can be used
+  }
+}
+
+uint32_t CU::getISPSplitDim( const int width, const int height, const PartSplit ispType )
+{
+  bool divideTuInRows = ispType == TU_1D_HORZ_SPLIT;
+  uint32_t splitDimensionSize, nonSplitDimensionSize, partitionSize, divShift = 2;
+
+  if( divideTuInRows )
+  {
+    splitDimensionSize    = height;
+    nonSplitDimensionSize = width;
+  }
+  else
+  {
+    splitDimensionSize    = width;
+    nonSplitDimensionSize = height;
+  }
+
+  const int minNumberOfSamplesPerCu = 1 << ( ( g_aucLog2[MIN_TU_SIZE] << 1 ) );
+  const int factorToMinSamples = nonSplitDimensionSize < minNumberOfSamplesPerCu ? minNumberOfSamplesPerCu >> g_aucLog2[nonSplitDimensionSize] : 1;
+  partitionSize = ( splitDimensionSize >> divShift ) < factorToMinSamples ? factorToMinSamples : ( splitDimensionSize >> divShift );
 
+  CHECK( g_aucLog2[partitionSize] + g_aucLog2[nonSplitDimensionSize] < g_aucLog2[minNumberOfSamplesPerCu], "A partition has less than the minimum amount of samples!" );
+  return partitionSize;
+}
+#endif
 
 
 PUTraverser CU::traversePUs( CodingUnit& cu )
@@ -287,6 +475,10 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
 {
   const int numMPMs = NUM_MOST_PROBABLE_MODES;
   const int extendRefLine = (channelType == CHANNEL_TYPE_LUMA) ? pu.multiRefIdx : 0;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const ISPType ispType = isLuma( channelType ) ? ISPType( pu.cu->ispMode ) : NOT_INTRA_SUBPARTITIONS;
+  const bool isHorSplit = ispType == HOR_INTRA_SUBPARTITIONS;
+#endif
   {
     int numCand      = -1;
     int leftIntraDir = PLANAR_IDX, aboveIntraDir = PLANAR_IDX;
@@ -381,6 +573,116 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
         }
       }
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    else if( ispType != NOT_INTRA_SUBPARTITIONS )
+    {
+      //default case
+      mpm[0] = PLANAR_IDX;
+      if( isHorSplit )
+      {
+        mpm[1] = HOR_IDX;
+        mpm[2] = 25;
+        mpm[3] = 10;
+        mpm[4] = 65;
+        mpm[5] = VER_IDX;
+      }
+      else
+      {
+        mpm[1] = VER_IDX;
+        mpm[2] = 43;
+        mpm[3] = 60;
+        mpm[4] = 3;
+        mpm[5] = HOR_IDX;
+      }
+      int canonicalMode = mpm[1];
+      if( leftIntraDir == aboveIntraDir ) //L=A
+      {
+        numCand = 1;
+        if( leftIntraDir > DC_IDX )
+        {
+          mpm[0] =     leftIntraDir;
+          mpm[1] = ( ( leftIntraDir + offset ) % mod ) + 2;
+          mpm[2] = ( ( leftIntraDir - 1 ) % mod ) + 2;
+          if( ( isHorSplit && leftIntraDir < DIA_IDX ) || ( !isHorSplit && leftIntraDir >= DIA_IDX ) )
+          {
+            mpm[3] = ( ( leftIntraDir + offset - 1 ) % mod ) + 2;
+            mpm[4] =   ( leftIntraDir                % mod ) + 2;
+            mpm[5] = ( ( leftIntraDir + offset - 2 ) % mod ) + 2;;
+          }
+          else
+          {
+            if( isHorSplit )
+            {
+              mpm[3] = HOR_IDX;
+              mpm[4] = 5;
+            }
+            else
+            {
+              mpm[3] = VER_IDX;
+              mpm[4] = VDIA_IDX - 3;
+            }
+            mpm[5] = PLANAR_IDX;
+          }
+        }
+      }
+      else //L!=A
+      {
+        numCand = 2;
+        if( ( leftIntraDir > DC_IDX ) && ( aboveIntraDir > DC_IDX ) )
+        {
+          int distLeftToCanonicalMode  = abs( leftIntraDir - canonicalMode );
+          int distAboveToCanonicalMode = abs( aboveIntraDir - canonicalMode );
+          mpm[0] = aboveIntraDir;
+          mpm[1] = leftIntraDir;
+          if( distLeftToCanonicalMode <= distAboveToCanonicalMode )
+          {
+            mpm[0] = leftIntraDir;
+            mpm[1] = aboveIntraDir;
+          }
+          int maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
+          int minCandModeIdx = 1 - maxCandModeIdx;
+          if( mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 1 )
+          {
+            mpm[2] = ( ( mpm[minCandModeIdx] + offset )     % mod ) + 2;
+            mpm[3] = ( ( mpm[maxCandModeIdx] - 1 )          % mod ) + 2;
+            mpm[4] = ( ( mpm[minCandModeIdx] + offset - 1 ) % mod ) + 2;
+            mpm[5] =   ( mpm[maxCandModeIdx]                % mod ) + 2;
+          }
+          else if( mpm[maxCandModeIdx] - mpm[minCandModeIdx] >= 62 )
+          {
+            mpm[2] = ( ( mpm[minCandModeIdx] - 1 )          % mod ) + 2;
+            mpm[3] = ( ( mpm[maxCandModeIdx] + offset )     % mod ) + 2;
+            mpm[4] = ( ( mpm[minCandModeIdx] )              % mod ) + 2;
+            mpm[5] = ( ( mpm[maxCandModeIdx] + offset - 1 ) % mod ) + 2;
+          }
+          else if( mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 2 )
+          {
+            mpm[2] = ( ( mpm[minCandModeIdx] - 1 )          % mod ) + 2;
+            mpm[3] = ( ( mpm[minCandModeIdx] + offset )     % mod ) + 2;
+            mpm[4] = ( ( mpm[maxCandModeIdx] - 1 )          % mod ) + 2;
+            mpm[5] = ( ( mpm[minCandModeIdx] + offset - 1 ) % mod ) + 2;
+          }
+          else
+          {
+            mpm[2] = ( ( mpm[minCandModeIdx] + offset )     % mod ) + 2;
+            mpm[3] = ( ( mpm[minCandModeIdx] - 1 )          % mod ) + 2;
+            mpm[4] = ( ( mpm[maxCandModeIdx] + offset )     % mod ) + 2;
+            mpm[5] = ( ( mpm[maxCandModeIdx] - 1 )          % mod ) + 2;
+          }
+        }
+        else if( leftIntraDir + aboveIntraDir > 2 )
+        {
+          //mpm[0] = PLANAR_IDX;
+          int angMode = leftIntraDir > DC_IDX ? leftIntraDir : aboveIntraDir;
+          mpm[1] = angMode;
+          mpm[2] = ( ( angMode + offset )     % mod ) + 2;
+          mpm[3] = ( ( angMode - 1 )          % mod ) + 2;
+          mpm[4] = ( ( angMode + offset - 1 ) % mod ) + 2;
+          mpm[5] = ( ( angMode )              % mod ) + 2;
+        }
+      }
+    }
+#endif
     else
     {
       mpm[0] = leftIntraDir;
@@ -478,7 +780,7 @@ bool PU::isLMCMode(unsigned mode)
 }
 bool PU::isLMCModeEnabled(const PredictionUnit &pu, unsigned mode)
 {
-  if ( pu.cs->sps->getSpsNext().getUseLMChroma() )
+  if ( pu.cs->sps->getUseLMChroma() )
   {
     return true;
   }
@@ -711,7 +1013,12 @@ bool PU::xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const
 #if JVET_L0090_PAIR_AVG
 
 bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos
+#if JVET_M0483_IBC==0
   , int mmvdList
+#endif
+#if JVET_M0483_IBC
+  , bool ibcFlag
+#endif
 #if JVET_M0170_MRG_SHARELIST
   , bool isShared
 #endif
@@ -723,7 +1030,9 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter
 )
 #endif
 {
+#if JVET_M0483_IBC==0
   int mrgCandIdxIBC = mrgCandIdx;
+#endif
   MotionInfo miNeighbor;
   bool hasPruned[MRG_MAX_NUM_CANDS];
   memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool));
@@ -732,17 +1041,36 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter
     hasPruned[subPuMvpPos] = true;
   }
 #if JVET_M0170_MRG_SHARELIST
+#if JVET_M0483_IBC
+  int num_avai_candInLUT = ibcFlag ? slice.getAvailableLUTIBCMrgNum() : (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum());
+  int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0;
+#else
   int num_avai_candInLUT = (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum());
+#endif
+#else
+#if JVET_M0483_IBC
+  int num_avai_candInLUT = ibcFlag ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum();
+  int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0;
 #else
   int num_avai_candInLUT = slice.getAvailableLUTMrgNum();
+#endif
 #endif
 
   for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
   {
 #if JVET_M0170_MRG_SHARELIST
+#if JVET_M0483_IBC
+    miNeighbor = ibcFlag ? slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset)
+                          : (isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx));
+#else
     miNeighbor = isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
+#endif
+#else
+#if JVET_M0483_IBC
+    miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset);
 #else
     miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
+#endif
 #endif
     mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
     mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
@@ -750,30 +1078,313 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter
     {
       mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
     }
+#if JVET_M0126_HMVP_MRG_PRUNING
+    if (mrgIdx > 2 || !xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
+#else
     if (!xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
+#endif
+    {
+#if !JVET_L0090_PAIR_AVG
+      isCandInter[cnt] = true;
+#endif
+#if JVET_M0264_HMVP_WITH_GBIIDX
+      mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? miNeighbor.GBiIdx : GBI_DEFAULT;
+#endif
+#if JVET_M0483_IBC==0
+      if (miNeighbor.interDir == 1 && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0])->getPOC() == slice.getPOC())
+      {
+        mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
+        if(mmvdList != 0 && mrgCandIdx != -1)
+          mrgCandIdxIBC++;
+      }
+      if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+      if (mrgCandIdx == cnt && canFastExit)
+#endif
+      {
+        return true;
+      }
+      cnt ++;
+      if (cnt  == maxNumMergeCandMin1)
+      {
+        break;
+      }
+    }
+  }
+  return false;
+}
+
+#if JVET_M0483_IBC
+void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
+{
+  const CodingStructure &cs = *pu.cs;
+  const Slice &slice = *pu.cs->slice;
+  const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand();
+  const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0;
+
+  for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
+  {
+    mrgCtx.GBiIdx[ui] = GBI_DEFAULT;
+    mrgCtx.interDirNeighbours[ui] = 0;
+    mrgCtx.mrgTypeNeighbours[ui] = MRG_TYPE_IBC;
+    mrgCtx.mvFieldNeighbours[ui * 2].refIdx = NOT_VALID;
+    mrgCtx.mvFieldNeighbours[ui * 2 + 1].refIdx = NOT_VALID;
+  }
+
+  mrgCtx.numValidMergeCand = maxNumMergeCand;
+  // compute the location of the current PU
+
+  int cnt = 0;
+
+  const Position posLT = pu.Y().topLeft();
+  const Position posRT = pu.Y().topRight();
+  const Position posLB = pu.Y().bottomLeft();
+
+  MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
+
+  //left
+  const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  const bool isAvailableA1 = puLeft && isDiffMER(pu, *puLeft) && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu);
+  if (isAvailableA1)
+  {
+    miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
+
+    // get Inter Dir
+    mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
+    // get Mv from Left
+    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
+    if (mrgCandIdx == cnt && canFastExit)
+    {
+      return;
+    }
+    cnt++;
+  }
+
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+
+  // above
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+  bool isAvailableB1 = puAbove && isDiffMER(pu, *puAbove) && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu);
+  if (isAvailableB1)
+  {
+    miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
+
+    if (!isAvailableA1 || (miAbove != miLeft))
+    {
+      // get Inter Dir
+      mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
+      // get Mv from Above
+      mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
+      if (mrgCandIdx == cnt && canFastExit)
+      {
+        return;
+      }
+
+      cnt++;
+    }
+  }
+
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+#if JVET_M0126_HMVP_MRG_PRUNING
+  int spatialCandPos = cnt;
+#endif
+
+  // above right
+  const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
+  bool isAvailableB0 = puAboveRight && isDiffMER(pu, *puAboveRight) && CU::isIBC(*puAboveRight->cu);
+  if (isAvailableB0)
+  {
+    miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1));
+
+#if HM_JEM_MERGE_CANDS
+    if ((!isAvailableB1 || (miAbove != miAboveRight)) && (!isAvailableA1 || (miLeft != miAboveRight)))
+#else
+    if (!isAvailableB1 || (miAbove != miAboveRight))
+#endif
+    {
+      // get Inter Dir
+      mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
+      // get Mv from Above-right
+      mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]);
+
+      if (mrgCandIdx == cnt && canFastExit)
+      {
+        return;
+      }
+
+      cnt++;
+    }
+  }
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  //left bottom
+  const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
+  bool isAvailableA0 = puLeftBottom && isDiffMER(pu, *puLeftBottom) && CU::isIBC(*puLeftBottom->cu);
+  if (isAvailableA0)
+  {
+    miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1));
+
+#if HM_JEM_MERGE_CANDS
+    if ((!isAvailableA1 || (miBelowLeft != miLeft)) && (!isAvailableB1 || (miBelowLeft != miAbove)) && (!isAvailableB0 || (miBelowLeft != miAboveRight)))
+#else
+    if (!isAvailableA1 || (miBelowLeft != miLeft))
+#endif
+    {
+      // get Inter Dir
+      mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
+      mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]);
+      if (mrgCandIdx == cnt && canFastExit)
+      {
+        return;
+      }
+
+      cnt++;
+    }
+  }
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  // above left
+  if (cnt < 4)
+  {
+    const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
+    bool isAvailableB2 = puAboveLeft && isDiffMER(pu, *puAboveLeft) && CU::isIBC(*puAboveLeft->cu);
+    if (isAvailableB2)
+    {
+      miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1));
+
+#if HM_JEM_MERGE_CANDS
+      if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft)) && (!isAvailableA0 || (miBelowLeft != miAboveLeft)) && (!isAvailableB0 || (miAboveRight != miAboveLeft)))
+#else
+      if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft)))
+#endif
+      {
+        // get Inter Dir
+        mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
+        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]);
+        if (mrgCandIdx == cnt && canFastExit)
+        {
+          return;
+        }
+
+        cnt++;
+      }
+    }
+  }
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  int maxNumMergeCandMin1 = maxNumMergeCand - 1;
+  if (cnt != maxNumMergeCandMin1)
+  {
+    bool isAvailableSubPu = false;
+    unsigned subPuMvpPos = 0;
+
+#if JVET_L0090_PAIR_AVG
+    bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit
+      , mrgCandIdx
+      , maxNumMergeCandMin1, cnt
+#if JVET_M0126_HMVP_MRG_PRUNING
+      , spatialCandPos
+#else
+      , cnt
+#endif
+      , isAvailableSubPu, subPuMvpPos
+#if JVET_M0483_IBC
+      , true
+#endif
+#if JVET_M0170_MRG_SHARELIST
+      , false
+#endif
+    );
+#else
+    bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit
+      , mrgCandIdx
+      , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
+    );
+#endif
+    if (bFound)
+    {
+      return;
+    }
+  }
+
+#if JVET_L0090_PAIR_AVG
+  // pairwise-average candidates
+#if JVET_M0193_PAIR_AVG_REDUCTION==0
+    const int cutoff = std::min(cnt, 4);
+    const int end = cutoff * (cutoff - 1) / 2;
+    constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 };
+    constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 };
+
+    for (int idx = 0; idx < end && cnt != maxNumMergeCand; idx++)
+    {
+      const int i = PRIORITY_LIST0[idx];
+      const int j = PRIORITY_LIST1[idx];
+#else
+    if (cnt>1 && cnt <maxNumMergeCand)
+    {
+#endif
+       mrgCtx.mvFieldNeighbours[cnt * 2    ].setMvField(Mv(0, 0), NOT_VALID);
+       mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID);
+
+#if JVET_M0193_PAIR_AVG_REDUCTION
+       const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2].mv;
+       const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2].mv;
+#else
+       const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 ].mv;
+       const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 ].mv;
+#endif
+       // average two MVs
+       Mv avgMv = MvI;
+
+       avgMv += MvJ;
+       mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+       roundAffineMv(avgMv.hor, avgMv.ver, 1);
+       avgMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
+#else
+       avgMv.setHor(avgMv.getHor() / 2);
+       avgMv.setVer(avgMv.getVer() / 2);
+       avgMv.setHor((avgMv.getHor() / 16) << 4);
+       avgMv.setVer((avgMv.getVer() / 16) << 4);
+#endif
+      mrgCtx.mvFieldNeighbours[cnt * 2 ].setMvField(avgMv, MAX_NUM_REF);
+      mrgCtx.interDirNeighbours[cnt] = 1;
+      cnt++;
+    }
+
+    // early termination
+    if (cnt == maxNumMergeCand)
     {
-#if !JVET_L0090_PAIR_AVG
-      isCandInter[cnt] = true;
-#endif
-      if (miNeighbor.interDir == 1 && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0])->getPOC() == slice.getPOC())
-      {
-        mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
-        if(mmvdList != 0 && mrgCandIdx != -1)
-          mrgCandIdxIBC++;
-      }
-      if (mrgCandIdxIBC == cnt && canFastExit)
-      {
-        return true;
-      }
-      cnt ++;
-      if (cnt  == maxNumMergeCandMin1)
-      {
-        break;
-      }
+      return;
     }
-  }
-  return false;
+#endif
+
+  mrgCtx.numValidMergeCand = cnt;
+
 }
+#endif
 
 void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
                                  int mmvdList,
@@ -806,8 +1417,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
 
   int cnt = 0;
 
-
+#if JVET_M0483_IBC==0
   int mrgCandIdxIBC = mrgCandIdx;
+#endif
 
 #if JVET_M0170_MRG_SHARELIST
   const Position posLT = pu.shareParentPos;
@@ -837,19 +1449,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
     mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->GBiIdx : GBI_DEFAULT;
     // get Mv from Left
+#if JVET_M0483_IBC==0
     if (puLeft->cu->ibc)
     {
       mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
       if (mmvdList != 0 && mrgCandIdx != -1)
         mrgCandIdxIBC++;
     }
+#endif
     mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
 
     if (slice.isInterB())
     {
       mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]);
     }
+#if JVET_M0483_IBC==0
     if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+    if (mrgCandIdx == cnt && canFastExit)
+#endif
     {
       return;
     }
@@ -883,19 +1501,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
       // get Mv from Above
       mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->GBiIdx : GBI_DEFAULT;
+#if JVET_M0483_IBC==0
       if (puAbove->cu->ibc)
       {
         mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
         if (mmvdList != 0 && mrgCandIdx != -1)
           mrgCandIdxIBC++;
       }
+#endif
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAbove.mv[0], miAbove.refIdx[0] );
 
       if( slice.isInterB() )
       {
         mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAbove.mv[1], miAbove.refIdx[1] );
       }
+#if JVET_M0483_IBC==0
       if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+      if (mrgCandIdx == cnt && canFastExit)
+#endif
       {
         return;
       }
@@ -910,6 +1534,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     return;
   }
 
+#if JVET_M0126_HMVP_MRG_PRUNING
+  int spatialCandPos = cnt;
+#endif
+
   // above right
   const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType );
 
@@ -933,12 +1561,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
       // get Mv from Above-right
       mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->GBiIdx : GBI_DEFAULT;
+#if JVET_M0483_IBC==0
       if (puAboveRight->cu->ibc)
       {
         mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
         if (mmvdList != 0 && mrgCandIdx != -1)
           mrgCandIdxIBC++;
       }
+#endif
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] );
 
       if( slice.isInterB() )
@@ -946,7 +1576,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] );
       }
 
+#if JVET_M0483_IBC==0
       if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+      if (mrgCandIdx == cnt && canFastExit)
+#endif
       {
         return;
       }
@@ -983,12 +1617,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
       mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->GBiIdx : GBI_DEFAULT;
       // get Mv from Bottom-Left
+#if JVET_M0483_IBC==0
       if (puLeftBottom->cu->ibc)
       {
         mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
         if (mmvdList != 0 && mrgCandIdx != -1)
           mrgCandIdxIBC++;
       }
+#endif
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] );
 
       if( slice.isInterB() )
@@ -996,7 +1632,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] );
       }
 
+#if JVET_M0483_IBC==0
       if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+      if (mrgCandIdx == cnt && canFastExit)
+#endif
       {
         return;
       }
@@ -1036,12 +1676,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
         mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->GBiIdx : GBI_DEFAULT;
         // get Mv from Above-Left
+#if JVET_M0483_IBC==0
         if (puAboveLeft->cu->ibc)
         {
           mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
           if (mmvdList != 0 && mrgCandIdx != -1)
             mrgCandIdxIBC++;
         }
+#endif
         mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] );
 
         if( slice.isInterB() )
@@ -1049,7 +1691,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
           mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] );
         }
 
+#if JVET_M0483_IBC==0
         if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+        if (mrgCandIdx == cnt && canFastExit)
+#endif
         {
           return;
         }
@@ -1170,7 +1816,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         isCandInter              [uiArrayAddr] = true;
 #endif
         mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT;
+#if JVET_M0483_IBC==0
         if (mrgCandIdxIBC == cnt && canFastExit)
+#else
+        if (mrgCandIdx == cnt && canFastExit)
+#endif
         {
           return;
         }
@@ -1196,9 +1846,24 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     bool  isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height));
 #endif
     bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit
+#if JVET_M0483_IBC==0
       , (mmvdList != 0 && mrgCandIdx != -1) ? (const int) mrgCandIdxIBC : mrgCandIdx
-      , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
+#else
+      , mrgCandIdx
+#endif
+      , maxNumMergeCandMin1, cnt
+#if JVET_M0126_HMVP_MRG_PRUNING
+      , spatialCandPos
+#else
+      , cnt
+#endif
+      , isAvailableSubPu, subPuMvpPos
+#if JVET_M0483_IBC==0
       , mmvdList
+#endif
+#if JVET_M0483_IBC
+      , CU::isIBC(*pu.cu)
+#endif
 #if JVET_M0170_MRG_SHARELIST
       , isShared
 #endif
@@ -1219,15 +1884,28 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
 #if JVET_L0090_PAIR_AVG
   // pairwise-average candidates
   {
+#if !JVET_M0193_PAIR_AVG_REDUCTION
     const int cutoff = std::min( cnt, 4 );
     const int end = cutoff * (cutoff - 1) / 2;
     constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 };
     constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 };
+#endif
 
+#if JVET_M0193_PAIR_AVG_REDUCTION
+#if JVET_M0483_IBC
+    if (cnt > 1 && cnt < maxNumMergeCand)
+#else
+    // skip when only 1 candidate is added so far or one is BV and one is MV
+    if( cnt > 1 && cnt < maxNumMergeCand && !(mrgCtx.mrgTypeNeighbours[0] != mrgCtx.mrgTypeNeighbours[1] && pu.cs->sps->getIBCMode()))
+#endif
+#else
     for( int idx = 0; idx < end && cnt != maxNumMergeCand; idx++ )
+#endif
     {
+#if !JVET_M0193_PAIR_AVG_REDUCTION
       const int i = PRIORITY_LIST0[idx];
       const int j = PRIORITY_LIST1[idx];
+#endif
 
       mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
       mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID );
@@ -1235,15 +1913,22 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       unsigned char interDir = 0;
 
 
+#if !JVET_M0193_PAIR_AVG_REDUCTION && JVET_M0483_IBC==0
       // skip when one is BV and one is MV
-      if (mrgCtx.mrgTypeNeighbours[i] != mrgCtx.mrgTypeNeighbours[j] && pu.cs->sps->getSpsNext().getIBCMode())
+      if (mrgCtx.mrgTypeNeighbours[i] != mrgCtx.mrgTypeNeighbours[j] && pu.cs->sps->getIBCMode())
       {
         continue;
       }
+#endif
       for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
       {
+#if JVET_M0193_PAIR_AVG_REDUCTION
+        const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx;
+        const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx;
+#else
         const short refIdxI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].refIdx;
         const short refIdxJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].refIdx;
+#endif
 
         // both MVs are invalid, skip
         if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) )
@@ -1255,35 +1940,55 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         // both MVs are valid, average these two MVs
         if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) )
         {
+#if JVET_M0193_PAIR_AVG_REDUCTION
+          const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
+          const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
+#else
           const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
           const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv;
+#endif
 
           // average two MVs
           Mv avgMv = MvI;
           avgMv += MvJ;
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+          roundAffineMv(avgMv.hor, avgMv.ver, 1);
+#else
           avgMv.setHor( avgMv.getHor() / 2 );
           avgMv.setVer( avgMv.getVer() / 2 );
+#endif
 
-
-
-          if (mrgCtx.mrgTypeNeighbours[i] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[j] == MRG_TYPE_IBC && pu.cs->sps->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+#if JVET_M0193_PAIR_AVG_REDUCTION
+          if (mrgCtx.mrgTypeNeighbours[0] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[1] == MRG_TYPE_IBC && pu.cs->sps->getIBCMode())
+#else
+          if (mrgCtx.mrgTypeNeighbours[i] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[j] == MRG_TYPE_IBC && pu.cs->sps->getIBCMode())
+#endif
           {
              mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
              avgMv.setHor((avgMv.getHor() / 16) << 4);
              avgMv.setVer((avgMv.getVer() / 16) << 4);
           }
-
+#endif
           mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
         }
         // only one MV is valid, take the only one MV
         else if( refIdxI != NOT_VALID )
         {
+#if JVET_M0193_PAIR_AVG_REDUCTION
+          Mv singleMv = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
+#else
           Mv singleMv = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
+#endif
           mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
         }
         else if( refIdxJ != NOT_VALID )
         {
+#if JVET_M0193_PAIR_AVG_REDUCTION
+          Mv singleMv = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
+#else
           Mv singleMv = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv;
+#endif
           mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ );
         }
       }
@@ -1387,6 +2092,27 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   }
   mrgCtx.numValidMergeCand = uiArrayAddr;
 }
+#if JVET_M0147_DMVR
+bool PU::checkDMVRCondition(const PredictionUnit& pu)
+{
+  if (pu.cs->sps->getUseDMVR())
+  {
+    return pu.mergeFlag
+      && pu.mergeType == MRG_TYPE_DEFAULT_N
+      && !pu.cu->affine
+      && !pu.mmvdMergeFlag
+      && !pu.cu->mmvdSkip
+      && PU::isBiPredFromDifferentDirEqDistPoc(pu)
+      && (pu.lheight() >= 8)
+      && ((pu.lheight() * pu.lwidth()) >= 64)
+      ;
+  }
+  else
+  {
+    return false;
+  }
+}
+#endif
 // for ibc pu validation
 bool PU::isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize)
 {
@@ -1501,6 +2227,44 @@ static int xGetDistScaleFactor(const int &iCurrPOC, const int &iCurrRefPOC, cons
     return iScale;
   }
 }
+
+#if JVET_M0512_MOTION_BUFFER_COMPRESSION
+int convertMvFixedToFloat(int32_t val)
+{
+  int sign  = val >> 31;
+  int scale = floorLog2((val ^ sign) | MV_MANTISSA_UPPER_LIMIT) - (MV_MANTISSA_BITCOUNT - 1);
+
+  int exponent;
+  int mantissa;
+  if (scale >= 0)
+  {
+    int round = (1 << scale) >> 1;
+    int n     = (val + round) >> scale;
+    exponent  = scale + ((n ^ sign) >> (MV_MANTISSA_BITCOUNT - 1));
+    mantissa  = (n & MV_MANTISSA_UPPER_LIMIT) | (sign << (MV_MANTISSA_BITCOUNT - 1));
+  }
+  else
+  {
+    exponent = 0;
+    mantissa = val;
+  }
+
+  return exponent | (mantissa << MV_EXPONENT_BITCOUNT);
+}
+
+int convertMvFloatToFixed(int val)
+{
+  int exponent = val & MV_EXPONENT_MASK;
+  int mantissa = val >> MV_EXPONENT_BITCOUNT;
+  return exponent == 0 ? mantissa : (mantissa ^ MV_MANTISSA_LIMIT) << (exponent - 1);
+}
+
+int roundMvComp(int x)
+{
+  return convertMvFloatToFixed(convertMvFixedToFloat(x));
+}
+#endif
+
 int PU::getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC)
 {
   return xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
@@ -1561,7 +2325,7 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx )
 {
   // don't perform MV compression when generally disabled or subPuMvp is used
-  const unsigned scale = ( pu.cs->pcv->noMotComp ? 1 : 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4) );
+  const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
   const unsigned mask  = ~( scale - 1 );
 
   const Position pos = Position{ PosType( _pos.x & mask ), PosType( _pos.y & mask ) };
@@ -1584,7 +2348,17 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList
   {
     return false;
   }
+#if JVET_M0483_IBC
+  if (mi.isIBCmot)
+  {
+    return false;
+  }
+#endif
+#if JVET_M0483_IBC
+  if (CU::isIBC(*pu.cu))
+#else
   if (eRefPicList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefPicList, refIdx)->getPOC() == pu.cs->slice->getPOC())
+#endif
   {
     return false;
   }
@@ -1627,6 +2401,10 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList
 
   // Scale the vector.
   Mv cColMv = mi.mv[eColRefPicList];
+#if JVET_M0512_MOTION_BUFFER_COMPRESSION
+  cColMv.setHor(roundMvComp(cColMv.getHor()));
+  cColMv.setVer(roundMvComp(cColMv.getVer()));
+#endif
 
   if (bIsCurrRefLongTerm /*|| bIsColRefLongTerm*/)
   {
@@ -1687,7 +2465,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
   //left
   const PredictionUnit *neibLeftPU = NULL;
   neibLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 0), pu, pu.cs->chType);
+#if JVET_M0483_IBC
+  left = (neibLeftPU) ? CU::isIBC(*neibLeftPU->cu) : 0;
+#else
   left = (neibLeftPU) ? neibLeftPU->cu->ibc : 0;
+#endif
 
   if (left)
   {
@@ -1699,7 +2481,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
   //above
   const PredictionUnit *neibAbovePU = NULL;
   neibAbovePU = pu.cs->getPURestricted(posRT.offset(0, -1), pu, pu.cs->chType);
+#if JVET_M0483_IBC
+  above = (neibAbovePU) ? CU::isIBC(*neibAbovePU->cu) : 0;
+#else
   above = (neibAbovePU) ? neibAbovePU->cu->ibc : 0;
+#endif
 
   if (above)
   {
@@ -1711,7 +2497,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
   // Below Left predictor search
   const PredictionUnit *neibBelowLeftPU = NULL;
   neibBelowLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 1), pu, pu.cs->chType);
+#if JVET_M0483_IBC
+  unsigned int belowLeft = (neibBelowLeftPU) ? CU::isIBC(*neibBelowLeftPU->cu) : 0;
+#else
   unsigned int belowLeft = (neibBelowLeftPU) ? neibBelowLeftPU->cu->ibc : 0;
+#endif
 
   if (belowLeft)
   {
@@ -1724,7 +2514,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
   // Above Right predictor search
   const PredictionUnit *neibAboveRightPU = NULL;
   neibAboveRightPU = pu.cs->getPURestricted(posRT.offset(1, -1), pu, pu.cs->chType);
+#if JVET_M0483_IBC
+  unsigned int aboveRight = (neibAboveRightPU) ? CU::isIBC(*neibAboveRightPU->cu) : 0;
+#else
   unsigned int aboveRight = (neibAboveRightPU) ? neibAboveRightPU->cu->ibc : 0;
+#endif
 
   if (aboveRight)
   {
@@ -1737,7 +2531,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
   // Above Left predictor search
   const PredictionUnit *neibAboveLeftPU = NULL;
   neibAboveLeftPU = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, pu.cs->chType);
+#if JVET_M0483_IBC
+  unsigned int aboveLeft = (neibAboveLeftPU) ? CU::isIBC(*neibAboveLeftPU->cu) : 0;
+#else
   unsigned int aboveLeft = (neibAboveLeftPU) ? neibAboveLeftPU->cu->ibc : 0;
+#endif
 
   if (aboveLeft)
   {
@@ -1765,7 +2563,11 @@ bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv)
   const PredictionUnit *neibRefPU = NULL;
   neibRefPU = pu.cs->getPURestricted(pu.lumaPos().offset(offsetX, offsetY), pu, pu.cs->chType);
 
+#if JVET_M0483_IBC
+  bool isIBC = (neibRefPU) ? CU::isIBC(*neibRefPU->cu) : 0;
+#else
   bool isIBC = (neibRefPU) ? neibRefPU->cu->ibc : 0;
+#endif
   if (isIBC)
   {
     derivedMv = neibRefPU->bv;
@@ -1773,6 +2575,102 @@ bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv)
   }
   return isIBC;
 }
+
+#if JVET_M0483_IBC
+/**
+ * Constructs a list of candidates for IBC AMVP (See specification, section "Derivation process for motion vector predictor candidates")
+ */
+void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
+{
+  CodingStructure &cs = *pu.cs;
+
+  AMVPInfo *pInfo = &amvpInfo;
+
+  pInfo->numCand = 0;
+
+  //-- Get Spatial MV
+  Position posLT = pu.Y().topLeft();
+  Position posRT = pu.Y().topRight();
+  Position posLB = pu.Y().bottomLeft();
+
+  bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).
+  {
+    const PredictionUnit* tmpPU = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); // getPUBelowLeft(idx, partIdxLB);
+    isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
+    if (!isScaledFlagLX)
+    {
+      tmpPU = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+      isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
+    }
+  }
+
+  // Left predictor search
+  if (isScaledFlagLX)
+  {
+    bool isAdded = addIBCMVPCand(pu, posLB, MD_BELOW_LEFT, *pInfo);
+
+    if (!isAdded)
+    {
+      isAdded = addIBCMVPCand(pu, posLB, MD_LEFT, *pInfo);
+    }
+  }
+
+  // Above predictor search
+  {
+    bool isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE_RIGHT, *pInfo);
+
+    if (!isAdded)
+    {
+      isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE, *pInfo);
+
+      if (!isAdded)
+      {
+        addIBCMVPCand(pu, posLT, MD_ABOVE_LEFT, *pInfo);
+      }
+    }
+  }
+
+  if (pu.cu->imv != 0)
+  {
+    for (int i = 0; i < pInfo->numCand; i++)
+    {
+      pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
+    }
+  }
+
+  if (pInfo->numCand == 2)
+  {
+    if (pInfo->mvCand[0] == pInfo->mvCand[1])
+    {
+      pInfo->numCand = 1;
+    }
+  }
+
+  if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
+  {
+    addAMVPHMVPCand(pu, REF_PIC_LIST_0, REF_PIC_LIST_1, cs.slice->getPOC(), *pInfo, pu.cu->imv);
+  }
+
+  if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
+  {
+    pInfo->numCand = AMVP_MAX_NUM_CANDS;
+  }
+
+  while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
+  {
+    pInfo->mvCand[pInfo->numCand] = Mv(0, 0);
+    pInfo->numCand++;
+  }
+
+  for (Mv &mv : pInfo->mvCand)
+  {
+    mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+    mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv);
+  }
+}
+
+#endif
+
 /** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates")
 * \param uiPartIdx
 * \param uiPartAddr
@@ -1862,6 +2760,12 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
     }
   }
 
+#if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
+  for( int i = 0; i < pInfo->numCand; i++ )
+  {
+    pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
+  }
+#else
   if( pu.cu->imv != 0)
   {
     for( int i = 0; i < pInfo->numCand; i++ )
@@ -1869,6 +2773,7 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
       pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
     }
   }
+#endif
 
   if( pInfo->numCand == 2 )
   {
@@ -1878,7 +2783,11 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
     }
   }
 
+#if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
+  if( cs.slice->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS )
+#else
   if( cs.slice->getEnableTMVPFlag() )
+#endif
   {
     // Get Temporal Motion Predictor
     const int refIdx_Col = refIdx;
@@ -1929,10 +2838,17 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
     if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col))
 #endif
     {
+#if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
+      cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
+#else
       if (pu.cu->imv != 0)
       {
-        cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv); 
+        cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
       }
+#endif
+#if JVET_M0117_AMVP_LIST_GEN
+      pInfo->mvCand[pInfo->numCand++] = cColMv;
+#else
       int i = 0;
       for (i = 0; i < pInfo->numCand; i++)
       {
@@ -1945,14 +2861,17 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
       {
         pInfo->mvCand[pInfo->numCand++] = cColMv;
       }
+#endif
     }
   }
+
   if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
   {
     const int        currRefPOC = cs.slice->getRefPic(eRefPicList, refIdx)->getPOC();
     const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
     addAMVPHMVPCand(pu, eRefPicList, eRefPicList2nd, currRefPOC, *pInfo, pu.cu->imv);
   }
+
   if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
   {
     pInfo->numCand = AMVP_MAX_NUM_CANDS;
@@ -1963,10 +2882,13 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
     pInfo->mvCand[pInfo->numCand] = Mv( 0, 0 );
     pInfo->numCand++;
   }
+
   for (Mv &mv : pInfo->mvCand)
   {
     mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if !JVET_M0281_AMVP_ROUNDING && !JVET_M0117_AMVP_LIST_GEN
     mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv);
+#endif
   }
 }
 
@@ -2023,14 +2945,36 @@ bool PU::addAffineMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &r
     }
 
     xInheritedAffineMv( pu, neibPU, eRefPicListIndex, outputAffineMv );
-
-    outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-    outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+    if ( pu.cu->imv == 0 )
+    {
+#endif
+      outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+      outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+    }
+    else if ( pu.cu->imv == 2 )
+    {
+      outputAffineMv[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+      outputAffineMv[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    }
+#endif
     affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
     affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
     if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
     {
-      outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      if ( pu.cu->imv == 0 )
+      {
+#endif
+        outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      }
+      else if ( pu.cu->imv == 2 )
+      {
+        outputAffineMv[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+      }
+#endif
       affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
     }
     affiAMVPInfo.numCand++;
@@ -2051,7 +2995,7 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN
   int curW = pu.Y().width;
   int neiH = puNeighbour->Y().height;
   int curH = pu.Y().height;
-  
+
   Mv mvLT, mvRT, mvLB;
   mvLT = puNeighbour->mvAffi[eRefPicList][0];
   mvRT = puNeighbour->mvAffi[eRefPicList][1];
@@ -2095,6 +3039,9 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN
   roundAffineMv( horTmp, verTmp, shift );
   rcMv[0].hor = horTmp;
   rcMv[0].ver = verTmp;
+#if JVET_M0145_AFFINE_MV_CLIP
+  rcMv[0].clipToStorageBitDepth();
+#endif
 
   // v1
   horTmp = iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY - posNeiY);
@@ -2102,6 +3049,9 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN
   roundAffineMv( horTmp, verTmp, shift );
   rcMv[1].hor = horTmp;
   rcMv[1].ver = verTmp;
+#if JVET_M0145_AFFINE_MV_CLIP
+  rcMv[1].clipToStorageBitDepth();
+#endif
 
   // v2
   if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
@@ -2111,6 +3061,9 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN
     roundAffineMv( horTmp, verTmp, shift );
     rcMv[2].hor = horTmp;
     rcMv[2].ver = verTmp;
+#if JVET_M0145_AFFINE_MV_CLIP
+    rcMv[2].clipToStorageBitDepth();
+#endif
   }
 }
 
@@ -2131,7 +3084,7 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
   Position posRT = pu.Y().topRight();
   Position posLB = pu.Y().bottomLeft();
 
-  // check left neighbor 
+  // check left neighbor
   if ( !addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, affiAMVPInfo ) )
   {
     addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_LEFT, affiAMVPInfo );
@@ -2150,9 +3103,16 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
   {
     for (int i = 0; i < affiAMVPInfo.numCand; i++)
     {
-      affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-      affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-      affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      if ( pu.cu->imv != 1 )
+      {
+#endif
+        affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+        affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+        affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      }
+#endif
     }
     return;
   }
@@ -2204,10 +3164,22 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
   outputAffineMv[1] = amvpInfo1.mvCand[0];
   outputAffineMv[2] = amvpInfo2.mvCand[0];
 
-
-  outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-  outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-  outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+  if ( pu.cu->imv == 0 )
+  {
+#endif
+    outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+    outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+    outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+  }
+  else if ( pu.cu->imv == 2 )
+  {
+    outputAffineMv[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    outputAffineMv[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    outputAffineMv[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+  }
+#endif
 
   if ( cornerMVPattern == 7 || (cornerMVPattern == 3 && pu.cu->affineType == AFFINEMODEL_4PARAM) )
   {
@@ -2282,7 +3254,18 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
       if ( (C0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdxCol )) || getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdxCol ) )
 #endif
       {
-        cColMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+        if ( pu.cu->imv == 0 )
+        {
+#endif
+          cColMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+        }
+        else if ( pu.cu->imv == 2 )
+        {
+          cColMv.roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+        }
+#endif
         affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv;
         affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv;
         affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv;
@@ -2303,15 +3286,63 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
     }
   }
 
-  for (int i = 0; i < affiAMVPInfo.numCand; i++)
+  for (int i = 0; i < affiAMVPInfo.numCand; i++)
+  {
+#if JVET_M0246_AFFINE_AMVR
+    if ( pu.cu->imv != 1 )
+    {
+#endif
+      affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+      affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+      affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+    }
+#endif
+  }
+
+
+}
+
+#if JVET_M0483_IBC
+bool PU::addIBCMVPCand(const PredictionUnit &pu, const Position &pos, const MvpDir &eDir, AMVPInfo &info)
+{
+  CodingStructure &cs = *pu.cs;
+  const PredictionUnit *neibPU = NULL;
+  Position neibPos;
+
+  switch (eDir)
   {
-    affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER); 
-    affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER); 
-    affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+  case MD_LEFT:
+    neibPos = pos.offset(-1, 0);
+    break;
+  case MD_ABOVE:
+    neibPos = pos.offset(0, -1);
+    break;
+  case MD_ABOVE_RIGHT:
+    neibPos = pos.offset(1, -1);
+    break;
+  case MD_BELOW_LEFT:
+    neibPos = pos.offset(-1, 1);
+    break;
+  case MD_ABOVE_LEFT:
+    neibPos = pos.offset(-1, -1);
+    break;
+  default:
+    break;
   }
 
+  neibPU = cs.getPURestricted(neibPos, pu, pu.chType);
+
+  if (neibPU == NULL || CU::isIBC(*neibPU->cu)==false)
+  {
+    return false;
+  }
 
+  const MotionInfo& neibMi = neibPU->getMotionInfo(neibPos);
+  info.mvCand[info.numCand++] = neibMi.mv[REF_PIC_LIST_0];
+  return true;
 }
+#endif
 
 bool PU::addMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &info )
 {
@@ -2405,7 +3436,11 @@ bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRef
 
   neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
 
+#if JVET_M0483_IBC
+  if (neibPU == NULL || !CU::isInter(*neibPU->cu) || !CU::isInter(*pu.cu))
+#else
   if( neibPU == NULL || !CU::isInter( *neibPU->cu ) )
+#endif
   {
     return false;
   }
@@ -2456,8 +3491,15 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList,
   const Slice &slice = *(*pu.cs).slice;
 
   MotionInfo neibMi;
+#if !JVET_M0117_AMVP_LIST_GEN
   int i = 0;
+#endif
+#if JVET_M0483_IBC
+  int offset = CU::isIBC(*pu.cu) ? MAX_NUM_HMVP_CANDS : 0;
+  int num_avai_candInLUT = CU::isIBC(*pu.cu) ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum();
+#else
   int num_avai_candInLUT = slice.getAvailableLUTMrgNum();
+#endif
   int num_allowedCand = std::min(MAX_NUM_HMVP_AVMPCANDS, num_avai_candInLUT);
 
   for (int mrgIdx = 1; mrgIdx <= num_allowedCand; mrgIdx++)
@@ -2466,20 +3508,48 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList,
     {
       return;
     }
+#if JVET_M0117_AMVP_LIST_GEN
+#if JVET_M0483_IBC
+    neibMi = slice.getMotionInfoFromLUTs(mrgIdx - 1 + offset) ;
+#else
+    neibMi = slice.getMotionInfoFromLUTs(mrgIdx - 1);
+#endif
+#else
+#if JVET_M0483_IBC
+    neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset);
+#else
     neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
+#endif
+#endif
 
-    for (int predictorSource = 0; predictorSource < 2; predictorSource++) 
+    for (int predictorSource = 0; predictorSource < 2; predictorSource++)
     {
       const RefPicList eRefPicListIndex = (predictorSource == 0) ? eRefPicList : eRefPicList2nd;
       const int        neibRefIdx = neibMi.refIdx[eRefPicListIndex];
 
+#if JVET_M0483_IBC
+      if (neibRefIdx >= 0 && (CU::isIBC(*pu.cu) || (currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx))))
+#else
       if (neibRefIdx >= 0 && currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx))
+#endif
       {
         Mv pmv = neibMi.mv[eRefPicListIndex];
+#if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
+        pmv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
+#else
         if (imv != 0)
         {
           pmv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, imv);
         }
+#endif
+
+#if JVET_M0117_AMVP_LIST_GEN
+        info.mvCand[info.numCand++] = pmv;
+        if (info.numCand >= AMVP_MAX_NUM_CANDS)
+        {
+          return;
+        }
+#else
         for (i = 0; i < info.numCand; i++)
         {
           if (pmv == info.mvCand[i])
@@ -2495,10 +3565,12 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList,
             return;
           }
         }
+#endif
       }
     }
   }
 }
+
 bool PU::isBipredRestriction(const PredictionUnit &pu)
 {
   if(pu.cu->lumaSize().width == 4 && pu.cu->lumaSize().height ==4 )
@@ -2535,7 +3607,11 @@ void PU::getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4],
       if ( mi[idx0].refIdx[l] >= 0 && mi[idx1].refIdx[l] >= 0 )
       {
         // check same refidx and different mv
+#if JVET_M0228_REMOVE_CPMV_COMPARE
+        if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l])
+#else
         if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].mv[l] != mi[idx1].mv[l] )
+#endif
         {
           dir |= (l + 1);
           refIdx[l] = mi[idx0].refIdx[l];
@@ -2556,7 +3632,11 @@ void PU::getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4],
       if ( mi[idx0].refIdx[l] >= 0 && mi[idx1].refIdx[l] >= 0 && mi[idx2].refIdx[l] >= 0 )
       {
         // check same refidx and different mv
+#if JVET_M0228_REMOVE_CPMV_COMPARE
+        if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].refIdx[l] == mi[idx2].refIdx[l])
+#else
         if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].refIdx[l] == mi[idx2].refIdx[l] && (mi[idx0].mv[l] != mi[idx1].mv[l] || mi[idx0].mv[l] != mi[idx2].mv[l]) )
+#endif
         {
           dir |= (l + 1);
           refIdx[l] = mi[idx0].refIdx[l];
@@ -2730,7 +3810,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
   bool isAvailableSubPu = false;
   if ( enableSubPuMvp && slice.getEnableTMVPFlag() )
   {
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
     int  cntIBC = 0;
 #endif
     MergeCtx mrgCtx = *affMrgCtx.mrgCtx;
@@ -2741,9 +3821,14 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
 
     int pos = 0;
     // Get spatial MV
+#if JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET
+    const Position posCurLB = pu.Y().bottomLeft();
+    MotionInfo miLeft;
+#else
     const Position posCurRT = pu.Y().topRight();
     const Position posCurLB = pu.Y().bottomLeft();
     MotionInfo miAbove, miLeft, miAboveRight, miBelowLeft;
+#endif
 
     //left
     const PredictionUnit* puLeft = cs.getPURestricted( posCurLB.offset( -1, 0 ), pu, pu.chType );
@@ -2755,7 +3840,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
       mrgCtx.interDirNeighbours[pos] = miLeft.interDir;
 
       // get Mv from Left
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
       if (puLeft->cu->ibc)
       {
         cntIBC++;
@@ -2770,6 +3855,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
       pos++;
     }
 
+#if !JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET
     // above
     const PredictionUnit *puAbove = cs.getPURestricted( posCurRT.offset( 0, -1 ), pu, pu.chType );
     bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu );
@@ -2782,7 +3868,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         // get Inter Dir
         mrgCtx.interDirNeighbours[pos] = miAbove.interDir;
         // get Mv from Left
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
         if (puAbove->cu->ibc)
         {
           cntIBC++;
@@ -2815,7 +3901,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         // get Inter Dir
         mrgCtx.interDirNeighbours[pos] = miAboveRight.interDir;
         // get Mv from Left
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
         if (puAboveRight->cu->ibc)
         {
           cntIBC++;
@@ -2848,7 +3934,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         // get Inter Dir
         mrgCtx.interDirNeighbours[pos] = miBelowLeft.interDir;
         // get Mv from Bottom-Left
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
         if (puLeftBottom->cu->ibc)
         {
           cntIBC++;
@@ -2863,11 +3949,12 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         pos++;
       }
     }
+#endif
     mrgCtx.numValidMergeCand = pos;
 
     isAvailableSubPu = getInterMergeSubPuMvpCand( pu, mrgCtx, tmpLICFlag, pos
       , 0
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
       , cntIBC
 #endif
     );
@@ -2897,7 +3984,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
     }
   }
 
-  if ( slice.getSPS()->getSpsNext().getUseAffine() )
+  if ( slice.getSPS()->getUseAffine() )
   {
     ///> Start: inherited affine candidates
     const PredictionUnit* npu[5];
@@ -2957,7 +4044,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         const PredictionUnit* puNeigh = cs.getPURestricted( pos, pu, pu.chType );
 
         if ( puNeigh && CU::isInter( *puNeigh->cu )
+#if JVET_M0483_IBC==0
           && !puNeigh->cu->ibc
+#endif
           )
         {
           isAvailable[0] = true;
@@ -2974,8 +4063,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         const PredictionUnit* puNeigh = cs.getPURestricted( pos, pu, pu.chType );
 
 
-        if ( puNeigh && CU::isInter( *puNeigh->cu ) 
+        if ( puNeigh && CU::isInter( *puNeigh->cu )
+#if JVET_M0483_IBC==0
           && !puNeigh->cu->ibc
+#endif
           )
         {
           isAvailable[1] = true;
@@ -2992,8 +4083,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         const PredictionUnit* puNeigh = cs.getPURestricted( pos, pu, pu.chType );
 
 
-        if ( puNeigh && CU::isInter( *puNeigh->cu ) 
+        if ( puNeigh && CU::isInter( *puNeigh->cu )
+#if JVET_M0483_IBC==0
           && !puNeigh->cu->ibc
+#endif
           )
         {
           isAvailable[2] = true;
@@ -3077,7 +4170,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
       };
 
       int verNum[6] = { 3, 3, 3, 3, 2, 2 };
-      int startIdx = pu.cs->sps->getSpsNext().getUseAffineType() ? 0 : 4;
+      int startIdx = pu.cs->sps->getUseAffineType() ? 0 : 4;
       for ( int idx = startIdx; idx < modelNum; idx++ )
       {
         int modelIdx = order[idx];
@@ -3182,13 +4275,21 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi
       mvScaleTmpHor = mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h);
       mvScaleTmpVer = mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h);
       roundAffineMv( mvScaleTmpHor, mvScaleTmpVer, shift );
+#if JVET_M0145_AFFINE_MV_CLIP
+      Mv curMv(mvScaleTmpHor, mvScaleTmpVer);
+      curMv.clipToStorageBitDepth();
+#endif
 
       for ( int y = (h >> MIN_CU_LOG2); y < ((h + blockHeight) >> MIN_CU_LOG2); y++ )
       {
         for ( int x = (w >> MIN_CU_LOG2); x < ((w + blockWidth) >> MIN_CU_LOG2); x++ )
         {
+#if JVET_M0145_AFFINE_MV_CLIP
+          mb.at(x, y).mv[eRefList] = curMv;
+#else
           mb.at(x, y).mv[eRefList].hor = mvScaleTmpHor;
           mb.at(x, y).mv[eRefList].ver = mvScaleTmpVer;
+#endif
         }
       }
     }
@@ -3260,6 +4361,10 @@ static bool deriveScaledMotionTemporal( const Slice&      slice,
     iCurrRefPOC = slice.getRefPic(eCurrRefPicList, 0)->getPOC();
     // Scale the vector.
     cColMv = mi.mv[eColRefPicList];
+#if JVET_M0512_MOTION_BUFFER_COMPRESSION
+    cColMv.setHor(roundMvComp(cColMv.getHor()));
+    cColMv.setVer(roundMvComp(cColMv.getVer()));
+#endif
     //pcMvFieldSP[2*iPartition + eCurrRefPicList].getMv();
     // Assume always short-term for now
     iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC);
@@ -3292,13 +4397,13 @@ void clipColPos(int& posX, int& posY, const PredictionUnit& pu)
 
 bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count
   , int mmvdList
-#if !JVET_M0409_ATMVP_FIX
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
   , const int countIBC
 #endif
 )
 {
-#if !JVET_M0409_ATMVP_FIX
-  if (count == countIBC && pu.cs->slice->getSPS()->getSpsNext().getIBCMode())
+#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
+  if (count == countIBC && pu.cs->slice->getSPS()->getIBCMode())
     return false;
 #endif
   const Slice   &slice = *pu.cs->slice;
@@ -3315,7 +4420,7 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b
     if ( count )
     {
       RefPicList currRefPicList = RefPicList(slice.getCheckLDC() ? (slice.getColFromL0Flag() ? currRefListId : 1 - currRefListId) : currRefListId);
-        
+
       if ((mrgCtx.interDirNeighbours[0] & (1 << currRefPicList)) && slice.getRefPic(currRefPicList, mrgCtx.mvFieldNeighbours[0 * 2 + currRefPicList].refIdx) == pColPic)
       {
         cTMv = mrgCtx.mvFieldNeighbours[0 * 2 + currRefPicList].mv;
@@ -3363,7 +4468,11 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b
   // derivation of center motion parameters from the collocated CU
   const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos);
 
+#if JVET_M0483_IBC
+  if (mi.isInter && mi.isIBCmot == false)
+#else
   if (mi.isInter)
+#endif
   {
     for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
     {
@@ -3413,9 +4522,19 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b
 
       MotionInfo mi;
 
+      // initialize to default vector in case no motion vector is available
+      mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv;
+      mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv;
+      mi.refIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].refIdx;
+      mi.refIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].refIdx;
       mi.isInter = true;
       mi.sliceIdx = slice.getIndependentSliceIdx();
-      if (colMi.isInter && !((colMi.interDir == 1 || colMi.interDir == 3) && (pColPic->cs->slice->getRefPOC(REF_PIC_LIST_0, colMi.refIdx[0]) == pColPic->cs->slice->getPOC()) && pu.cs->sps->getSpsNext().getIBCMode()))
+#if JVET_M0483_IBC
+      mi.isIBCmot = false;
+      if (colMi.isInter && colMi.isIBCmot == false)
+#else
+      if (colMi.isInter && !((colMi.interDir == 1 || colMi.interDir == 3) && (pColPic->cs->slice->getRefPOC(REF_PIC_LIST_0, colMi.refIdx[0]) == pColPic->cs->slice->getPOC()) && pu.cs->sps->getIBCMode()))
+#endif
       {
         for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
         {
@@ -3426,14 +4545,6 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b
             mi.mv[currRefListId] = cColMv;
           }
         }
-        }
-      else
-      {
-        // intra coded, in this case, no motion vector is available for list 0 or list 1, so use default
-        mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv;
-        mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv;
-        mi.refIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].refIdx;
-        mi.refIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].refIdx;
       }
 
       mi.interDir = (mi.refIdx[0] != -1 ? 1 : 0) + (mi.refIdx[1] != -1 ? 2 : 0);
@@ -3456,13 +4567,18 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
 {
   MotionBuf mb = pu.getMotionBuf();
 
-  if( !pu.mergeFlag || pu.mergeType == MRG_TYPE_DEFAULT_N 
+  if( !pu.mergeFlag || pu.mergeType == MRG_TYPE_DEFAULT_N
     || pu.mergeType == MRG_TYPE_IBC
     )
   {
     MotionInfo mi;
 
+#if JVET_M0483_IBC
+    mi.isInter = !CU::isIntra(*pu.cu);
+    mi.isIBCmot = CU::isIBC(*pu.cu);
+#else
     mi.isInter  = CU::isInter( *pu.cu );
+#endif
     mi.sliceIdx = pu.cu->slice->getIndependentSliceIdx();
 
     if( mi.isInter )
@@ -3474,7 +4590,11 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
         mi.mv[i]     = pu.mv[i];
         mi.refIdx[i] = pu.refIdx[i];
       }
+#if JVET_M0483_IBC
+      if (mi.isIBCmot)
+#else
       if (pu.interDir == 1 && pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]) == pu.cu->slice->getPOC())
+#endif
       {
         mi.bv = pu.bv;
       }
@@ -3488,6 +4608,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
         {
           MotionInfo &dest = mb.at( x, y );
           dest.isInter  = mi.isInter;
+#if JVET_M0483_IBC
+          dest.isIBCmot = false;
+#endif
           dest.interDir = mi.interDir;
           dest.sliceIdx = mi.sliceIdx;
           for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
@@ -3542,15 +4665,24 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP
       pu.mvd[0].changePrecisionAmvr( pu.cu->imv, MV_PRECISION_QUARTER);
       unsigned mvp_idx = pu.mvpIdx[0];
       AMVPInfo amvpInfo;
+#if JVET_M0483_IBC
+      if (CU::isIBC(*pu.cu))
+      {
+        PU::fillIBCMvpCand(pu, amvpInfo);
+      }
+      else
+#endif
       PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
       pu.mvpNum[0] = amvpInfo.numCand;
       pu.mvpIdx[0] = mvp_idx;
       pu.mv    [0] = amvpInfo.mvCand[mvp_idx] + pu.mvd[0];
       pu.mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0483_IBC==0
       if (pu.interDir == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0])->getPOC() == pu.cs->slice->getPOC())
       {
         pu.cu->ibc = true;
       }
+#endif
     }
 
     if (pu.interDir != 1 /* PRED_L0 */)
@@ -3572,7 +4704,7 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP
   {
     // this function is never called for merge
     THROW("unexpected");
-    PU::getInterMergeCandidates ( pu, mrgCtx 
+    PU::getInterMergeCandidates ( pu, mrgCtx
       , 0
     );
 #if !JVET_M0068_M0171_MMVD_CLEANUP
@@ -3600,7 +4732,25 @@ bool PU::isBiPredFromDifferentDir( const PredictionUnit& pu )
 
   return false;
 }
-
+#if JVET_M0147_DMVR
+bool PU::isBiPredFromDifferentDirEqDistPoc(const PredictionUnit& pu)
+{
+  if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+  {
+    const int poc0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]);
+    const int poc1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, pu.refIdx[1]);
+    const int poc = pu.cu->slice->getPOC();
+    if ((poc - poc0)*(poc - poc1) < 0)
+    {
+      if (abs(poc - poc0) == abs(poc - poc1))
+      {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+#endif
 void PU::restrictBiPredMergeCands( const PredictionUnit &pu, MergeCtx& mergeCtx )
 {
   if( PU::isBipredRestriction( pu ) )
@@ -3662,7 +4812,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
   //left
   const PredictionUnit* puLeft = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );
   const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu )
+#if JVET_M0483_IBC==0
     && !puLeft->cu->ibc
+#endif
     ;
   if( isAvailableA1 )
   {
@@ -3679,12 +4831,14 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
   // above
   const PredictionUnit *puAbove = cs.getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType );
   bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu )
+#if JVET_M0483_IBC==0
     && !puAbove->cu->ibc
+#endif
     ;
   if( isAvailableB1 )
   {
     miAbove = puAbove->getMotionInfo( posRT.offset( 0, -1 ) );
-    
+
     if( !isAvailableA1 || ( miAbove != miLeft ) )
     {
       candidate[candCount].isInter   = true;
@@ -3696,11 +4850,13 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candCount++;
     }
   }
-  
+
   // above right
   const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType );
   bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu )
+#if JVET_M0483_IBC==0
     && !puAboveRight->cu->ibc
+#endif
     ;
 
   if( isAvailableB0 )
@@ -3717,17 +4873,19 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candidate[candCount].refIdx[1] = miAboveRight.refIdx[1];
       candCount++;
     }
-  }  
+  }
 
   //left bottom
   const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType );
   bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu )
+#if JVET_M0483_IBC==0
     && !puLeftBottom->cu->ibc
+#endif
     ;
   if( isAvailableA0 )
   {
     miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) );
-    
+
     if( ( !isAvailableA1 || ( miBelowLeft != miLeft ) ) && ( !isAvailableB1 || ( miBelowLeft != miAbove ) ) && ( !isAvailableB0 || ( miBelowLeft != miAboveRight ) ) )
     {
       candidate[candCount].isInter   = true;
@@ -3743,7 +4901,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
   // above left
   const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType );
   bool isAvailableB2 = puAboveLeft && isDiffMER( pu, *puAboveLeft ) && CU::isInter( *puAboveLeft->cu )
+#if JVET_M0483_IBC==0
     && !puAboveLeft->cu->ibc
+#endif
     ;
 
   if( isAvailableB2 )
@@ -3761,7 +4921,7 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candCount++;
     }
   }
-  
+
   if( slice.getEnableTMVPFlag() )
   {
     Position posRB = pu.Y().bottomRight().offset(-3, -3);
@@ -3833,7 +4993,7 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candidate[candCount].refIdx[1] = temporalMv.refIdx[1];
       candCount++;
     }
-   
+
     // C1
     temporalMv.interDir = 0;
 #if JVET_M0170_MRG_SHARELIST
@@ -3871,10 +5031,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candCount++;
     }
   }
-  
   // put uni-prediction candidate to the triangle candidate list
   for( int32_t i = 0; i < candCount; i++ )
-  { 
+  {
     if( candidate[i].interDir != 3 )
     {
       triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = candidate[i].interDir;
@@ -3943,9 +5102,13 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       {
         aveMv = aveMv.scaleMv( distscale ); // scaling to L0
       }
+#if JVET_M0265_MV_ROUNDING_CLEANUP
+      aveMv = aveMv + candidate[i].mv[0];
+      roundAffineMv(aveMv.hor, aveMv.ver, 1);
+#else
       aveMv.setHor( ( aveMv.getHor() + candidate[i].mv[0].getHor() + 1 ) >> 1 );
       aveMv.setVer( ( aveMv.getVer() + candidate[i].mv[0].getVer() + 1 ) >> 1 );
-          
+#endif
       triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
       triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
       triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].mv = aveMv;
@@ -3958,8 +5121,8 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
         return;
       }
     }
-  } 
-    
+  }
+
   // fill with Mv(0, 0)
   int32_t numRefIdx = std::min( slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1) );
   int32_t cnt = 0;
@@ -3969,20 +5132,24 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
     {
       triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
       triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].setMvField(Mv(0, 0), cnt);
+      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = NOT_VALID;
+      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv();
       triangleMrgCtx.numValidMergeCand++;
-      
+
       if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
       {
         return;
       }
-      
+
       triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2;
       triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1 ].setMvField(Mv(0, 0), cnt);
+      triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].refIdx = NOT_VALID;
+      triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].mv = Mv();
       triangleMrgCtx.numValidMergeCand++;
-      
+
       cnt = (cnt + 1) % numRefIdx;
     }
-  }  
+  }
 }
 
 bool PU::isUniqueTriangleCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
@@ -3999,26 +5166,27 @@ bool PU::isUniqueTriangleCandidates( const PredictionUnit &pu, MergeCtx& triangl
       return false;
     }
   }
-  return true;  
+  return true;
 }
 
+#if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
 bool PU::getTriangleWeights( const PredictionUnit& pu, MergeCtx &triangleMrgCtx, const uint8_t candIdx0, const uint8_t candIdx1 )
 {
   RefPicList refPicListCand0 = triangleMrgCtx.interDirNeighbours[candIdx0] == 1 ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
   RefPicList refPicListCand1 = triangleMrgCtx.interDirNeighbours[candIdx1] == 1 ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
   int32_t refPicPoc0 = pu.cs->slice->getRefPOC( refPicListCand0, triangleMrgCtx.mvFieldNeighbours[ (candIdx0 << 1) + refPicListCand0 ].refIdx );
   int32_t refPicPoc1 = pu.cs->slice->getRefPOC( refPicListCand1, triangleMrgCtx.mvFieldNeighbours[ (candIdx1 << 1) + refPicListCand1 ].refIdx );
-  
+
   if( refPicPoc0 != refPicPoc1 )
   {
     // different reference picture
     return true;
   }
-  
+
   // same reference picture, but mv difference is larger than 16 pel
   int32_t threshold = 16 << 4;
   Mv diffMv = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + refPicListCand0].mv - triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + refPicListCand1].mv;
-  
+
   if( diffMv.getAbsHor() > threshold || diffMv.getAbsVer() > threshold  )
   {
     return true;
@@ -4026,15 +5194,26 @@ bool PU::getTriangleWeights( const PredictionUnit& pu, MergeCtx &triangleMrgCtx,
 
   return false;
 }
+#endif
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
+#else
 void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t mergeIdx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
+#endif
 {
+#if JVET_M0883_TRIANGLE_SIGNALING
+  pu.triangleSplitDir = splitDir;
+  pu.triangleMergeIdx0 = candIdx0;
+  pu.triangleMergeIdx1 = candIdx1;
+#else
   pu.mergeIdx  = mergeIdx;
+#endif
   MotionBuf mb = pu.getMotionBuf();
 
   MotionInfo biMv;
   biMv.isInter  = true;
-  
+
   if( triangleMrgCtx.interDirNeighbours[candIdx0] == 1 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
   {
     biMv.interDir  = 3;
@@ -4089,7 +5268,7 @@ void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, c
       biMv.interDir  = ( refIdx != -1 ) ? 3 : 2;
       biMv.mv[0]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv : Mv(0, 0);
       biMv.mv[1]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
-      biMv.refIdx[0] = ( refIdx != -1 ) ? refIdx : -1; 
+      biMv.refIdx[0] = ( refIdx != -1 ) ? refIdx : -1;
       biMv.refIdx[1] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
     }
   }
@@ -4158,6 +5337,11 @@ void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred )
         Mv mv        = pu.mv[0];
         Mv mvPred;
         AMVPInfo amvpInfo;
+#if JVET_M0483_IBC
+        if (CU::isIBC(*pu.cu))
+          PU::fillIBCMvpCand(pu, amvpInfo);
+        else
+#endif
         PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
         pu.mvpNum[0] = amvpInfo.numCand;
 
@@ -4194,7 +5378,7 @@ void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred )
     }
     else
     {
-        PU::getInterMergeCandidates ( pu, mrgCtx 
+        PU::getInterMergeCandidates ( pu, mrgCtx
           , 0
         );
 #if !JVET_M0068_M0171_MMVD_CLEANUP
@@ -4235,6 +5419,47 @@ bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
   return bNonZeroMvd;
 }
 
+#if JVET_M0246_AFFINE_AMVR
+bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
+{
+  bool nonZeroAffineMvd = false;
+
+  if ( !cu.affine || cu.firstPU->mergeFlag )
+  {
+    return false;
+  }
+
+  for ( const auto &pu : CU::traversePUs( cu ) )
+  {
+    if ( ( !pu.mergeFlag ) && ( !cu.skip ) )
+    {
+      if ( pu.interDir != 2 /* PRED_L1 */ )
+      {
+        for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
+        {
+          nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getHor() != 0;
+          nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getVer() != 0;
+        }
+      }
+
+      if ( pu.interDir != 1 /* PRED_L0 */ )
+      {
+        if ( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
+        {
+          for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
+          {
+            nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getHor() != 0;
+            nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getVer() != 0;
+          }
+        }
+      }
+    }
+  }
+
+  return nonZeroAffineMvd;
+}
+#endif
+
 int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos )
 {
   const int  numDefault     = 0;
@@ -4259,14 +5484,136 @@ int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos
   return maxImvNumCand;
 }
 
+#if JVET_M0140_SBT
+uint8_t CU::getSbtInfo( uint8_t idx, uint8_t pos )
+{
+  return ( pos << 4 ) + ( idx << 0 );
+}
+
+uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
+{
+  return ( sbtInfo >> 0 ) & 0xf;
+}
+
+uint8_t CU::getSbtPos( const uint8_t sbtInfo )
+{
+  return ( sbtInfo >> 4 ) & 0x3;
+}
+
+uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos )
+{
+  uint8_t sbtMode = 0;
+  switch( sbtIdx )
+  {
+  case SBT_VER_HALF: sbtMode = sbtPos + SBT_VER_H0;  break;
+  case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0;  break;
+  case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0;  break;
+  case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0;  break;
+  default:           assert( 0 );
+  }
+
+  assert( sbtMode < NUMBER_SBT_MODE );
+  return sbtMode;
+}
+
+uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode )
+{
+  if( sbtMode <= SBT_VER_H1 )
+    return SBT_VER_HALF;
+  else if( sbtMode <= SBT_HOR_H1 )
+    return SBT_HOR_HALF;
+  else if( sbtMode <= SBT_VER_Q1 )
+    return SBT_VER_QUAD;
+  else if( sbtMode <= SBT_HOR_Q1 )
+    return SBT_HOR_QUAD;
+  else
+  {
+    assert( 0 );
+    return 0;
+  }
+}
+
+uint8_t CU::getSbtPosFromSbtMode( uint8_t sbtMode )
+{
+  if( sbtMode <= SBT_VER_H1 )
+    return sbtMode - SBT_VER_H0;
+  else if( sbtMode <= SBT_HOR_H1 )
+    return sbtMode - SBT_HOR_H0;
+  else if( sbtMode <= SBT_VER_Q1 )
+    return sbtMode - SBT_VER_Q0;
+  else if( sbtMode <= SBT_HOR_Q1 )
+    return sbtMode - SBT_HOR_Q0;
+  else
+  {
+    assert( 0 );
+    return 0;
+  }
+}
+
+uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed )
+{
+  uint8_t val = 0;
+  switch( sbtIdx )
+  {
+  case SBT_VER_HALF: val = ( ( sbtAllowed >> SBT_VER_HALF ) & 0x1 ); break;
+  case SBT_HOR_HALF: val = ( ( sbtAllowed >> SBT_HOR_HALF ) & 0x1 ); break;
+  case SBT_VER_QUAD: val = ( ( sbtAllowed >> SBT_VER_QUAD ) & 0x1 ); break;
+  case SBT_HOR_QUAD: val = ( ( sbtAllowed >> SBT_HOR_QUAD ) & 0x1 ); break;
+  default:           CHECK( 1, "unknown SBT type" );
+  }
+  return val;
+}
+
+uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed )
+{
+  uint8_t num = 0;
+  uint8_t sum = 0;
+  num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
+  sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
+  num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
+  sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
+  return sum;
+}
+
+bool CU::isMtsMode( const uint8_t sbtInfo )
+{
+  return getSbtIdx( sbtInfo ) == SBT_OFF_MTS;
+}
+
+bool CU::isSbtMode( const uint8_t sbtInfo )
+{
+  uint8_t sbtIdx = getSbtIdx( sbtInfo );
+  return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD;
+}
+
+bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 )
+{
+  uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 );
+  uint8_t sbtIdx2 = getSbtIdxFromSbtMode( sbtInfo2 );
+  if( sbtIdx1 == SBT_HOR_HALF || sbtIdx1 == SBT_VER_HALF )
+    return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF;
+  else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD )
+    return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD;
+  else
+    return false;
+}
+#endif
+
 bool CU::isGBiIdxCoded( const CodingUnit &cu )
 {
-  if( cu.cs->sps->getSpsNext().getUseGBi() == false )
+  if( cu.cs->sps->getUseGBi() == false )
   {
     CHECK(cu.GBiIdx != GBI_DEFAULT, "Error: cu.GBiIdx != GBI_DEFAULT");
     return false;
   }
 
+#if JVET_M0483_IBC
+  if (cu.predMode == MODE_IBC)
+  {
+    return false;
+  }
+#endif
+
   if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() )
   {
     return false;
@@ -4362,14 +5709,6 @@ uint8_t CU::deriveGbiIdx( uint8_t gbiLO, uint8_t gbiL1 )
 
 // TU tools
 
-#if HEVC_USE_4x4_DSTVII
-bool TU::useDST(const TransformUnit &tu, const ComponentID &compID)
-{
-  return isLuma(compID) && tu.cu->predMode == MODE_INTRA;
-}
-
-#endif
-
 bool TU::isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID)
 {
   return tu.cs->sps->getSpsRangeExtension().getTransformSkipRotationEnabledFlag() && tu.blocks[compID].width == 4 && tu.cu->predMode == MODE_INTRA;
@@ -4401,9 +5740,15 @@ bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
 
   tsAllowed &= tu.cs->pps->getUseTransformSkip();
   tsAllowed &= !tu.cu->transQuantBypass;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  tsAllowed &= ( !tu.cu->ispMode || !isLuma(compID) );
+#endif
 
   SizeType transformSkipMaxSize = 1 << maxSize;
   tsAllowed &= tu.lwidth() <= transformSkipMaxSize && tu.lheight() <= transformSkipMaxSize;
+#if JVET_M0140_SBT
+  tsAllowed &= !tu.cu->sbtInfo;
+#endif
 
   return tsAllowed;
 }
@@ -4413,8 +5758,14 @@ bool TU::isMTSAllowed(const TransformUnit &tu, const ComponentID compID)
   bool   mtsAllowed = compID == COMPONENT_Y;
   const int maxSize = CU::isIntra( *tu.cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
 
-  mtsAllowed &= CU::isIntra( *tu.cu ) ? tu.cs->sps->getSpsNext().getUseIntraMTS() : tu.cs->sps->getSpsNext().getUseInterMTS();
+  mtsAllowed &= CU::isIntra( *tu.cu ) ? tu.cs->sps->getUseIntraMTS() : tu.cs->sps->getUseInterMTS();
   mtsAllowed &= ( tu.lwidth() <= maxSize && tu.lheight() <= maxSize );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  mtsAllowed &= !tu.cu->ispMode;
+#endif
+#if JVET_M0140_SBT
+  mtsAllowed &= !tu.cu->sbtInfo;
+#endif
   return mtsAllowed;
 }
 #else
@@ -4506,8 +5857,13 @@ uint32_t TU::getCoefScanIdx(const TransformUnit &tu, const ComponentID &compID)
 #endif
 bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID )
 {
+#if JVET_M0483_IBC
+  return (isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf(tu, COMPONENT_Y) &&
+    (!CU::isIntra(*tu.cu) || PU::isChromaIntraModeCrossCheckMode(*tu.cs->getPU(tu.blocks[compID].pos(), toChannelType(compID)))));
+#else
   return ( isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf( tu, COMPONENT_Y ) &&
          ( CU::isInter(*tu.cu) || PU::isChromaIntraModeCrossCheckMode( *tu.cs->getPU( tu.blocks[compID].pos(), toChannelType( compID ) ) ) ) );
+#endif
 }
 
 uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma, const bool bChroma )
@@ -4535,17 +5891,37 @@ uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma
   return count;
 }
 
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
+{
+  const Size &size=tu.blocks[compID];
+#if JVET_M0464_UNI_MTS
+  const bool isTransformSkip = tu.mtsIdx==1 && isLuma(compID);
+#else
+  const bool isTransformSkip = tu.transformSkip[compID];
+#endif
+  return (!isTransformSkip) && (((g_aucLog2[size.width] + g_aucLog2[size.height]) & 1) == 1);
+}
+#else
 bool TU::needsSqrt2Scale( const Size& size )
 {
   return (((g_aucLog2[size.width] + g_aucLog2[size.height]) & 1) == 1);
 }
+#endif
 
 #if HM_QTBT_AS_IN_JEM_QUANT
 
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+bool TU::needsBlockSizeTrafoScale( const TransformUnit &tu, const ComponentID &compID )
+{
+  return needsSqrt2Scale( tu, compID ) || isNonLog2BlockSize( tu.blocks[compID] );
+}
+#else
 bool TU::needsBlockSizeTrafoScale( const Size& size )
 {
   return needsSqrt2Scale( size ) || isNonLog2BlockSize( size );
 }
+#endif
 #else
 bool TU::needsQP3Offset(const TransformUnit &tu, const ComponentID &compID)
 {
@@ -4558,7 +5934,57 @@ bool TU::needsQP3Offset(const TransformUnit &tu, const ComponentID &compID)
 #endif
 
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+TransformUnit* TU::getPrevTU( const TransformUnit &tu, const ComponentID compID )
+{
+  TransformUnit* prevTU = tu.prev;
+
+  if( prevTU != nullptr && ( prevTU->cu != tu.cu || !prevTU->blocks[compID].valid() ) )
+  {
+    prevTU = nullptr;
+  }
+
+  return prevTU;
+}
+
+bool TU::getPrevTuCbfAtDepth( const TransformUnit &currentTu, const ComponentID compID, const int trDepth )
+{
+  const TransformUnit* prevTU = getPrevTU( currentTu, compID );
+  return ( prevTU != nullptr ) ? TU::getCbfAtDepth( *prevTU, compID, trDepth ) : false;
+}
+
+void TU::getTransformTypeISP( const TransformUnit &tu, const ComponentID compID, int &typeH, int &typeV )
+{
+  typeH = DCT2, typeV = DCT2;
+  const int uiChFinalMode = PU::getFinalIntraMode( *tu.cu->firstPU, toChannelType( compID ) );
+  bool intraModeIsEven = uiChFinalMode % 2 == 0;
 
+  if( uiChFinalMode == DC_IDX || uiChFinalMode == 33 || uiChFinalMode == 35 )
+  {
+    typeH = DCT2;
+    typeV = typeH;
+  }
+  else if( uiChFinalMode == PLANAR_IDX || ( uiChFinalMode >= 31 && uiChFinalMode <= 37 ) )
+  {
+    typeH = DST7;
+    typeV = typeH;
+  }
+  else if( ( intraModeIsEven && uiChFinalMode >= 2 && uiChFinalMode <= 30 ) || ( !intraModeIsEven && uiChFinalMode >= 39 && uiChFinalMode <= 65 ) )
+  {
+    typeH = DST7;
+    typeV = DCT2;
+  }
+  else if( ( !intraModeIsEven && uiChFinalMode >= 3 && uiChFinalMode <= 29 ) || ( intraModeIsEven && uiChFinalMode >= 38 && uiChFinalMode <= 66 ) )
+  {
+    typeH = DCT2;
+    typeV = DST7;
+  }
+  //Size restriction for non-DCT-II transforms
+  Area tuArea = tu.blocks[compID];
+  typeH = tuArea.width  <= 2 || tuArea.width  >= 32 ? DCT2 : typeH;
+  typeV = tuArea.height <= 2 || tuArea.height >= 32 ? DCT2 : typeV;
+}
+#endif
 
 
 // other tools
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 0b7c97f00bbcb8f128e2befbc791a9d559ad5034..b49f8b758672f21d4c397ba1506802bf21e3ea1b 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -49,6 +49,9 @@ namespace CS
   uint64_t getEstBits                   ( const CodingStructure &cs );
   UnitArea getArea                    ( const CodingStructure &cs, const UnitArea &area, const ChannelType chType );
   bool   isDualITree                  ( const CodingStructure &cs );
+#if JVET_M0147_DMVR
+  void   setRefinedMotionField(CodingStructure &cs);
+#endif
 }
 
 
@@ -57,6 +60,9 @@ namespace CU
 {
   bool isIntra                        (const CodingUnit &cu);
   bool isInter                        (const CodingUnit &cu);
+#if JVET_M0483_IBC
+  bool isIBC                          (const CodingUnit &cu);
+#endif
   bool isRDPCMEnabled                 (const CodingUnit &cu);
   bool isLosslessCoded                (const CodingUnit &cu);
   uint32_t getIntraSizeIdx                (const CodingUnit &cu);
@@ -86,16 +92,42 @@ namespace CU
   void  setGbiIdx                     (CodingUnit& cu, uint8_t uh);
   uint8_t deriveGbiIdx                (uint8_t gbiLO, uint8_t gbiL1);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  bool      divideTuInRows            ( const CodingUnit &cu );
+  bool      firstTestISPHorSplit      ( const int width, const int height,            const ComponentID compID, const CodingUnit *cuLeft = nullptr, const CodingUnit *cuAbove = nullptr );
+  PartSplit getISPType                ( const CodingUnit &cu,                         const ComponentID compID );
+  bool      isISPLast                 ( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID );
+  bool      isISPFirst                ( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID );
+  ISPType   canUseISPSplit            ( const CodingUnit &cu,                         const ComponentID compID );
+  ISPType   canUseISPSplit            ( const int width, const int height, const int maxTrSize = MAX_TU_SIZE );
+  uint32_t  getISPSplitDim            ( const int width, const int height, const PartSplit ispType );
+#endif
+
   PUTraverser traversePUs             (      CodingUnit& cu);
   TUTraverser traverseTUs             (      CodingUnit& cu);
   cPUTraverser traversePUs            (const CodingUnit& cu);
   cTUTraverser traverseTUs            (const CodingUnit& cu);
 
   bool  hasSubCUNonZeroMVd            (const CodingUnit& cu);
+#if JVET_M0246_AFFINE_AMVR
+  bool  hasSubCUNonZeroAffineMVd      ( const CodingUnit& cu );
+#endif
   int   getMaxNeighboriMVCandNum      (const CodingStructure& cs, const Position& pos);
   void  resetMVDandMV2Int             (      CodingUnit& cu, InterPrediction *interPred );
 
-
+#if JVET_M0140_SBT
+  uint8_t getSbtInfo                  (uint8_t idx, uint8_t pos);
+  uint8_t getSbtIdx                   (const uint8_t sbtInfo);
+  uint8_t getSbtPos                   (const uint8_t sbtInfo);
+  uint8_t getSbtMode                  (const uint8_t sbtIdx, const uint8_t sbtPos);
+  uint8_t getSbtIdxFromSbtMode        (const uint8_t sbtMode);
+  uint8_t getSbtPosFromSbtMode        (const uint8_t sbtMode);
+  uint8_t targetSbtAllowed            (uint8_t idx, uint8_t sbtAllowed);
+  uint8_t numSbtModeRdo               (uint8_t sbtAllowed);
+  bool    isMtsMode                   (const uint8_t sbtInfo);
+  bool    isSbtMode                   (const uint8_t sbtInfo);
+  bool    isSameSbtSize               (const uint8_t sbtInfo1, const uint8_t sbtInfo2);
+#endif
 }
 // PU tools
 namespace PU
@@ -107,11 +139,18 @@ namespace PU
   void getInterMergeCandidates        (const PredictionUnit &pu, MergeCtx& mrgCtx,
     int mmvdList,
     const int& mrgCandIdx = -1 );
+#if JVET_M0483_IBC
+  void getIBCMergeCandidates          (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1);
+#endif
   void getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1);
   int getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC);
   bool isDiffMER                      (const PredictionUnit &pu, const PredictionUnit &pu2);
   bool getColocatedMVP                (const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &pos, Mv& rcMv, const int &refIdx);
   void fillMvpCand                    (      PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo );
+#if JVET_M0483_IBC
+  void fillIBCMvpCand                 (PredictionUnit &pu, AMVPInfo &amvpInfo);
+  bool addIBCMVPCand                  (const PredictionUnit &pu, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo);
+#endif
   void fillAffineMvpCand              (      PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AffineAMVPInfo &affiAMVPInfo);
   bool addMVPCandUnscaled             (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo);
   bool addMVPCandWithScaling          (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo);
@@ -119,14 +158,21 @@ namespace PU
   bool xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS]);
 #if JVET_L0090_PAIR_AVG
   bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos
+#if JVET_M0483_IBC==0
     , int mmvdList
+#endif
+#if JVET_M0483_IBC
+    , bool ibcFlag
+#endif
 #if JVET_M0170_MRG_SHARELIST
     , bool isShared
 #endif
   );
 #else
   bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter[MRG_MAX_NUM_CANDS], bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos
+#if JVET_M0483_IBC==0
     , int mmvdList
+#endif
   );
 #endif
   void addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicList2nd, const int currRefPOC, AMVPInfo &info, uint8_t imv);
@@ -137,17 +183,22 @@ namespace PU
   void getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4], bool isAvailable[4], int verIdx[4], int modelIdx, int verNum, AffineMergeCtx& affMrgCtx );
   void getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, const int mrgCandIdx = -1 );
   void setAllAffineMvField            (      PredictionUnit &pu, MvField *mvField, RefPicList eRefList );
-  void setAllAffineMv                 (      PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList 
+  void setAllAffineMv                 (      PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList
     , bool setHighPrec = false
   );
   bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count
     , int mmvdList
 #if !JVET_M0409_ATMVP_FIX
+#if JVET_M0483_IBC==0
     , const int countIBC
+#endif
 #endif
   );
   bool getInterMergeSubPuRecurCand(const PredictionUnit &pu, MergeCtx &mrgCtx, const int count);
   bool isBiPredFromDifferentDir       (const PredictionUnit &pu);
+#if JVET_M0147_DMVR
+  bool isBiPredFromDifferentDirEqDistPoc(const PredictionUnit &pu);
+#endif
   void restrictBiPredMergeCands       (const PredictionUnit &pu, MergeCtx& mrgCtx);
 #if JVET_M0068_M0171_MMVD_CLEANUP
   void restrictBiPredMergeCandsOne    (PredictionUnit &pu);
@@ -160,21 +211,27 @@ namespace PU
   int  getNarrowShape                 (const int width, const int height);
   void getTriangleMergeCandidates     (const PredictionUnit &pu, MergeCtx &triangleMrgCtx);
   bool isUniqueTriangleCandidates     (const PredictionUnit &pu, MergeCtx &triangleMrgCtx);
+#if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
   bool getTriangleWeights             (const PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t candIdx0, const uint8_t candIdx1);
+#endif
+#if JVET_M0883_TRIANGLE_SIGNALING
+  void spanTriangleMotionInfo         (      PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1);
+#else
   void spanTriangleMotionInfo         (      PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t mergeIdx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1);
+#endif
   int32_t mappingRefPic               (const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList);
   void getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred);
   bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv);
   bool isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize);
+#if JVET_M0147_DMVR
+  bool checkDMVRCondition(const PredictionUnit& pu);
+#endif
 }
 
 // TU tools
 namespace TU
 {
   uint32_t getNumNonZeroCoeffsNonTS       (const TransformUnit &tu, const bool bLuma = true, const bool bChroma = true);
-#if HEVC_USE_4x4_DSTVII
-  bool useDST                         (const TransformUnit &tu, const ComponentID &compID);
-#endif
   bool isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID);
   bool getCbf                         (const TransformUnit &tu, const ComponentID &compID);
   bool getCbfAtDepth                  (const TransformUnit &tu, const ComponentID &compID, const unsigned &depth);
@@ -191,12 +248,26 @@ namespace TU
 #endif
   bool hasCrossCompPredInfo           (const TransformUnit &tu, const ComponentID &compID);
 
+
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  bool needsSqrt2Scale                ( const TransformUnit &tu, const ComponentID &compID );
+#else
   bool needsSqrt2Scale                ( const Size& size );
+#endif
 #if HM_QTBT_AS_IN_JEM_QUANT
+#if JVET_M0119_NO_TRANSFORM_SKIP_QUANTISATION_ADJUSTMENT
+  bool needsBlockSizeTrafoScale       ( const TransformUnit &tu, const ComponentID &compID );
+#else
   bool needsBlockSizeTrafoScale       ( const Size& size );
+#endif
 #else
   bool needsQP3Offset                 (const TransformUnit &tu, const ComponentID &compID);
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  TransformUnit* getPrevTU          ( const TransformUnit &tu, const ComponentID compID );
+  bool           getPrevTuCbfAtDepth( const TransformUnit &tu, const ComponentID compID, const int trDepth );
+  void           getTransformTypeISP( const TransformUnit &tu, const ComponentID compID, int &typeH, int &typeV );
+#endif
 }
 
 uint32_t getCtuAddr        (const Position& pos, const PreCalcValues &pcv);
@@ -227,7 +298,7 @@ uint32_t updateCandList(T uiMode, double uiCost, static_vector<T, N>& candModeLi
       if (extendRef != -1)
       {
         extendRefList[currSize - i] = extendRefList[currSize - 1 - i];
-      }  
+      }
     }
     candModeList[currSize - shift] = uiMode;
     candCostList[currSize - shift] = uiCost;
@@ -301,7 +372,7 @@ uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candMode
     candCostList.insert(candCostList.end() - shift, cost);
     if (iserttPos != nullptr)
     {
-      *iserttPos = int(candModeList.size() - shift - 1);  
+      *iserttPos = int(candModeList.size() - shift - 1);
     }
     return 1;
   }
diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.cpp b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
index 5971ab4046563e91164918e0f8c3608e9921a4fa..a0557fd30d6555b0a340149d039fb68cab62572f 100644
--- a/source/Lib/CommonLib/dtrace_blockstatistics.cpp
+++ b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
@@ -195,7 +195,7 @@ void CDTrace::dtrace_block_vector( int k, const PredictionUnit &pu, std::string
 }
 
 void CDTrace::dtrace_block_scalar(int k, const TransformUnit &tu, std::string stat_type, signed value, bool isChroma /*= false*/  )
-{ 
+{
   const CodingStructure& cs = *tu.cs;
 #if BLOCK_STATS_AS_CSV
   if(isChroma)
@@ -273,7 +273,11 @@ void CDTrace::dtrace_polygon_vector(int k, int poc, const std::vector<Position>
 
 void retrieveTriangularMvInfo(const PredictionUnit& pu, MotionInfo& mi0, MotionInfo& mi1)
 {
+#if JVET_M0883_TRIANGLE_SIGNALING
+  int triangleDir = pu.triangleSplitDir;
+#else
   int triangleDir = g_triangleCombination[pu.mergeIdx][0];
+#endif
   CMotionBuf mb = pu.getMotionBuf();
   bool foundMv[2] = { false, false };
   bool foundBi = false;
@@ -296,7 +300,7 @@ void retrieveTriangularMvInfo(const PredictionUnit& pu, MotionInfo& mi0, MotionI
         mi1.mv[0]     = mb.at(x, y).mv[0];
         mi1.mv[1]     = mb.at(x, y).mv[1];
         mi1.refIdx[0] = mb.at(x, y).refIdx[0];
-        mi1.refIdx[1] = mb.at(x, y).refIdx[1];        
+        mi1.refIdx[1] = mb.at(x, y).refIdx[1];
         foundMv[1] = true;
       }
       if (g_triangleMvStorage[triangleDir][idxH][idxW][y][x] == 2 && foundMv[0] == false && foundMv[1] == false)
@@ -325,8 +329,12 @@ void retrieveTriangularMvInfo(const PredictionUnit& pu, MotionInfo& mi0, MotionI
 }
 void retrieveTrianglePolygon(const PredictionUnit& pu, std::vector<Position>& triangle0, std::vector<Position>& triangle1, Position& S, Position& E)
 {
+#if JVET_M0883_TRIANGLE_SIGNALING
+  TriangleSplit triangleDir = TriangleSplit(pu.triangleSplitDir);
+#else
   TriangleSplit triangleDir = TriangleSplit(g_triangleCombination[pu.mergeIdx][0]);
-  Position TL = pu.Y().topLeft();  
+#endif
+  Position TL = pu.Y().topLeft();
   Position TR = pu.Y().topRight();    TR = TR.offset(1, 0);
   Position BL = pu.Y().bottomLeft();  BL = BL.offset(0, 1);
   Position BR = pu.Y().bottomRight(); BR = BR.offset(1, 1);
@@ -337,7 +345,7 @@ void retrieveTrianglePolygon(const PredictionUnit& pu, std::vector<Position>& tr
     E = Position(pu.Y().width, pu.Y().height);
     triangle0.push_back(TL);
     triangle0.push_back(TR);
-    triangle0.push_back(BR);               
+    triangle0.push_back(BR);
     triangle1.push_back(TL);
     triangle1.push_back(BL);
     triangle1.push_back(BR);
@@ -348,7 +356,7 @@ void retrieveTrianglePolygon(const PredictionUnit& pu, std::vector<Position>& tr
     E = Position(pu.Y().width, 0);
     triangle0.push_back(TL);
     triangle0.push_back(TR);
-    triangle0.push_back(BL);               
+    triangle0.push_back(BL);
     triangle1.push_back(TR);
     triangle1.push_back(BL);
     triangle1.push_back(BR);
@@ -437,10 +445,12 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::SkipFlag), cu.skip);
         }
 
-        if (!(!((cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getSpsNext().getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
+#if !JVET_M0464_UNI_MTS
+        if (!(!((cs.sps->getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
         {
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::EMTFlag), cu.emtFlag);
         }
+#endif
         DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::MMVDSkipFlag), cu.mmvdSkip);
       }
       else if( chType == CHANNEL_TYPE_CHROMA )
@@ -458,10 +468,12 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::TransQuantBypassFlag_Chroma), cu.transQuantBypass);
         }
 
-        if (!(!((cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getSpsNext().getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
+#if !JVET_M0464_UNI_MTS
+        if (!(!((cs.sps->getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
         {
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::EMTFlag_Chroma), cu.emtFlag);
         }
+#endif
       }
 
 
@@ -668,8 +680,11 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::IMVMode), cu.imv);
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::RootCbf), cu.rootCbf);
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::GBIIndex), cu.GBiIdx);
+#if !JVET_M0483_IBC
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::IBCFlag), cu.ibc);
-
+#else
+          DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::IBCFlag), cu.predMode == MODE_IBC);
+#endif
         }
         break;
       case MODE_INTRA:
@@ -721,15 +736,21 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
         if (tu.Y().valid())
         {
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::Cbf_Y), tu.cbf[COMPONENT_Y]);
+#if JVET_M0464_UNI_MTS
+          DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::MTSIdx), tu.mtsIdx);
+#else
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Y), tu.transformSkip[COMPONENT_Y]);
+#endif
         }
         if (!(cu.chromaFormat == CHROMA_400 || (CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_LUMA)))
         {
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::Cbf_Cb), tu.cbf[COMPONENT_Cb]);
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::Cbf_Cr), tu.cbf[COMPONENT_Cr]);
+#if !JVET_M0464_UNI_MTS
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Cb), tu.transformSkip[COMPONENT_Cb]);
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Cr), tu.transformSkip[COMPONENT_Cr]);
-        }        
+#endif
+        }
       }
     }
   }
@@ -777,7 +798,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
 
         if (CU::isIntra(cu))
         {
-          if (!(!sps.getUsePCM() || cu.lumaSize().width > (1 << sps.getPCMLog2MaxSize()) || cu.lumaSize().width < (1 << sps.getPCMLog2MinSize())))
+          if (!(!sps.getPCMEnabledFlag() || cu.lumaSize().width > (1 << sps.getPCMLog2MaxSize()) || cu.lumaSize().width < (1 << sps.getPCMLog2MinSize())))
           {
             DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, cu, GetBlockStatisticName(BlockStatistic::IPCM), cu.ipcm);
           }
@@ -800,7 +821,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
 
         if (CU::isIntra(cu))
         {
-          if (!(!sps.getUsePCM() || cu.lumaSize().width > (1 << sps.getPCMLog2MaxSize()) || cu.lumaSize().width < (1 << sps.getPCMLog2MinSize())))
+          if (!(!sps.getPCMEnabledFlag() || cu.lumaSize().width > (1 << sps.getPCMLog2MaxSize()) || cu.lumaSize().width < (1 << sps.getPCMLog2MinSize())))
           {
             DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, cu, GetBlockStatisticName(BlockStatistic::IPCM_Chroma), cu.ipcm);
           }
@@ -812,7 +833,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
         switch (pu.cu->predMode)
         {
           case MODE_INTRA:
-          {          
+          {
             if (pu.Y().valid())
             {
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::Luma_IntraMode), PU::getFinalIntraMode(pu, ChannelType(chType)));
@@ -842,13 +863,13 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
               {
                 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MMVDMergeIdx), pu.mmvdMergeIdx);
               }
-              if (!cu.cs->slice->isIntra() && cu.cs->sps->getSpsNext().getUseAffine() && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8
+              if (!cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8
                 && !pu.mmvdMergeFlag && !cu.mmvdSkip
                 )
               {
                 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::AffineFlag), pu.cu->affine);
               }
-              if (pu.cs->sps->getSpsNext().getUseMHIntra() && !pu.cu->skip && !pu.cu->affine && !(pu.cu->lwidth() * pu.cu->lheight() < 64 || pu.cu->lwidth() >= MAX_CU_SIZE || pu.cu->lheight() >= MAX_CU_SIZE)
+              if (pu.cs->sps->getUseMHIntra() && !pu.cu->skip && !pu.cu->affine && !(pu.cu->lwidth() * pu.cu->lheight() < 64 || pu.cu->lwidth() >= MAX_CU_SIZE || pu.cu->lheight() >= MAX_CU_SIZE)
                 && !pu.mmvdMergeFlag
                 )
               {
@@ -862,7 +883,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
                   }
                 }
               }
-              if (cu.cs->slice->getSPS()->getSpsNext().getUseTriangle() && cu.cs->slice->isInterB() && cu.lwidth() * cu.lheight() >= TRIANGLE_MIN_SIZE && !cu.affine)
+              if (cu.cs->slice->getSPS()->getUseTriangle() && cu.cs->slice->isInterB() && cu.lwidth() * cu.lheight() >= TRIANGLE_MIN_SIZE && !cu.affine)
               {
                 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, cu, GetBlockStatisticName(BlockStatistic::TriangleFlag), cu.triangle);
 
@@ -874,10 +895,10 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
               {
                 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::InterDir), pu.interDir);
               }
-              if (!cu.cs->slice->isIntra() && cu.cs->sps->getSpsNext().getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8)
+              if (!cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8)
               {
                 DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::AffineFlag), pu.cu->affine);
-                if (cu.affine && !cu.firstPU->mergeFlag && cu.cs->sps->getSpsNext().getUseAffineType())
+                if (cu.affine && !cu.firstPU->mergeFlag && cu.cs->sps->getUseAffineType())
                 {
                   DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::AffineType), pu.cu->affineType);
                 }
@@ -974,13 +995,13 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
                 DTRACE_BLOCK_AFFINETF(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::AffineMVL1), mv[0].hor, mv[0].ver, mv[1].hor, mv[1].ver, mv[2].hor, mv[2].ver);
               }
             }
-            if (cu.cs->sps->getSpsNext().getUseIMV() && CU::hasSubCUNonZeroMVd(cu))
+            if (cu.cs->sps->getAMVREnabledFlag() && CU::hasSubCUNonZeroMVd(cu))
             {
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, cu, GetBlockStatisticName(BlockStatistic::IMVMode), cu.imv);
             }
             if (CU::isGBiIdxCoded(cu))
             {
-              DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::GBIIndex), cu.GBiIdx);           
+              DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::GBIIndex), cu.GBiIdx);
             }
             break;
           }
@@ -1000,21 +1021,26 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
         }
       }
       if (cu.rootCbf || CU::isIntra(cu))
-      {        
+      {
         for (const TransformUnit &tu : CU::traverseTUs(cu))
         {
           if (tu.Y().valid())
           {
             DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::Cbf_Y), tu.cbf[COMPONENT_Y]);
+#if JVET_M0464_UNI_MTS
+            DTRACE_BLOCK_SCALAR( g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName( BlockStatistic::MTSIdx ), tu.mtsIdx );
+#else
             if (!(!tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag(*tu.cs, tu.blocks[COMPONENT_Y]) || (isLuma(COMPONENT_Y) && tu.cu->emtFlag)))
             {
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Y), tu.transformSkip[COMPONENT_Y]);
             }
+#endif
           }
           if (!(cu.chromaFormat == CHROMA_400 || (CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_LUMA)))
           {
             DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::Cbf_Cb), tu.cbf[COMPONENT_Cb]);
             DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::Cbf_Cr), tu.cbf[COMPONENT_Cr]);
+#if !JVET_M0464_UNI_MTS
             if (!(!tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag(*tu.cs, tu.blocks[COMPONENT_Cb]) || (isLuma(COMPONENT_Cb) && tu.cu->emtFlag)))
             {
               DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Cb), tu.transformSkip[COMPONENT_Cb]);
@@ -1023,10 +1049,12 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
             {
               DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, tu, GetBlockStatisticName(BlockStatistic::TransformSkipFlag_Cr), tu.transformSkip[COMPONENT_Cr]);
             }
+#endif
           }
         }
       }
-      if (!(!((cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getSpsNext().getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
+#if !JVET_M0464_UNI_MTS
+      if (!(!((cs.sps->getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getUseInterEMT() && CU::isInter(cu))) || isChroma(cu.chType)))
       {
         if( isLuma( ChannelType( chType ) ) )
         {
@@ -1037,6 +1065,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
           DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_CODED, cu, GetBlockStatisticName(BlockStatistic::EMTFlag_Chroma), cu.emtFlag);
         }
       }
+#endif
     }
   }
 }
diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.h b/source/Lib/CommonLib/dtrace_blockstatistics.h
index 34d457098ab571aa683c1cd49efbba568eee2515..72241ce8ae4f56ea5b04dbcd5d4be5cfd8e7c0bd 100644
--- a/source/Lib/CommonLib/dtrace_blockstatistics.h
+++ b/source/Lib/CommonLib/dtrace_blockstatistics.h
@@ -64,10 +64,14 @@ enum class BlockStatistic {
   QP,
   SplitSeries,
   TransQuantBypassFlag,
+#if JVET_M0464_UNI_MTS
+  MTSIdx,
+#else
   EMTFlag,
   TransformSkipFlag_Y,
   TransformSkipFlag_Cb,
   TransformSkipFlag_Cr,
+#endif
 
   // intra
   IPCM,
@@ -119,7 +123,9 @@ enum class BlockStatistic {
   QP_Chroma,
   SplitSeries_Chroma,
   TransQuantBypassFlag_Chroma,
+#if !JVET_M0464_UNI_MTS
   EMTFlag_Chroma, // this is called flag, though the type is UChar ?!
+#endif
 
   // intra
   IPCM_Chroma,
@@ -150,14 +156,18 @@ static const std::map<BlockStatistic, std::tuple<std::string, BlockStatisticType
   { BlockStatistic::Luma_IntraMode,         std::tuple<std::string, BlockStatisticType, std::string>{"Luma_IntraMode",              BlockStatisticType::Integer,                "[0, " + std::to_string(NUM_INTRA_MODE) + "]"}},
   { BlockStatistic::Chroma_IntraMode,       std::tuple<std::string, BlockStatisticType, std::string>{"Chroma_IntraMode",            BlockStatisticType::Integer,                "[0, " + std::to_string(NUM_INTRA_MODE) + "]"}},
   { BlockStatistic::SkipFlag,               std::tuple<std::string, BlockStatisticType, std::string>{"SkipFlag",                    BlockStatisticType::Flag,                   ""}},
+#if JVET_M0464_UNI_MTS
+  { BlockStatistic::MTSIdx,                 std::tuple<std::string, BlockStatisticType, std::string>{"TransformSkipFlag_Y",         BlockStatisticType::Integer,                ""}},
+#else
   { BlockStatistic::TransformSkipFlag_Y,    std::tuple<std::string, BlockStatisticType, std::string>{"TransformSkipFlag_Y",         BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::TransformSkipFlag_Cb,   std::tuple<std::string, BlockStatisticType, std::string>{"TransformSkipFlag_Cb",        BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::TransformSkipFlag_Cr,   std::tuple<std::string, BlockStatisticType, std::string>{"TransformSkipFlag_Cr",        BlockStatisticType::Flag,                   ""}},
-  { BlockStatistic::Depth,                  std::tuple<std::string, BlockStatisticType, std::string>{"Depth",                       BlockStatisticType::Integer,                "[0, 7]"}}, 
-  { BlockStatistic::QT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"QT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}}, 
-  { BlockStatistic::BT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"BT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}}, 
-  { BlockStatistic::MT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"MT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}}, 
-  { BlockStatistic::ChromaQPAdj,            std::tuple<std::string, BlockStatisticType, std::string>{"ChromaQPAdj",                 BlockStatisticType::Integer,                "[-10, 10]"}}, 
+#endif
+  { BlockStatistic::Depth,                  std::tuple<std::string, BlockStatisticType, std::string>{"Depth",                       BlockStatisticType::Integer,                "[0, 7]"}},
+  { BlockStatistic::QT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"QT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}},
+  { BlockStatistic::BT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"BT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}},
+  { BlockStatistic::MT_Depth,               std::tuple<std::string, BlockStatisticType, std::string>{"MT_Depth",                    BlockStatisticType::Integer,                "[0, 7]"}},
+  { BlockStatistic::ChromaQPAdj,            std::tuple<std::string, BlockStatisticType, std::string>{"ChromaQPAdj",                 BlockStatisticType::Integer,                "[-10, 10]"}},
   { BlockStatistic::QP,                     std::tuple<std::string, BlockStatisticType, std::string>{"QP",                          BlockStatisticType::Integer,                "[0, 51]"}},
   { BlockStatistic::SplitSeries,            std::tuple<std::string, BlockStatisticType, std::string>{"SplitSeries",                 BlockStatisticType::Integer,                "[0, " + std::to_string(std::numeric_limits<SplitSeries>::max()) + "]"}},
   { BlockStatistic::RootCbf,                std::tuple<std::string, BlockStatisticType, std::string>{"RootCbf",                     BlockStatisticType::Flag,                   ""}},
@@ -168,30 +178,32 @@ static const std::map<BlockStatistic, std::tuple<std::string, BlockStatisticType
   { BlockStatistic::MergeIdx,               std::tuple<std::string, BlockStatisticType, std::string>{"MergeIdx",                    BlockStatisticType::Integer,                "[0, 7]"}},
   { BlockStatistic::InterDir,               std::tuple<std::string, BlockStatisticType, std::string>{"InterDir",                    BlockStatisticType::Integer,                "[1, 3]"}},
   { BlockStatistic::MergeType,              std::tuple<std::string, BlockStatisticType, std::string>{"MergeType",                   BlockStatisticType::Integer,                "[0, 2]"}},
-  { BlockStatistic::MVPIdxL0,               std::tuple<std::string, BlockStatisticType, std::string>{"MVPIdxL0",                    BlockStatisticType::Integer,                "[0, 1]"}}, 
+  { BlockStatistic::MVPIdxL0,               std::tuple<std::string, BlockStatisticType, std::string>{"MVPIdxL0",                    BlockStatisticType::Integer,                "[0, 1]"}},
   { BlockStatistic::MVDL0,                  std::tuple<std::string, BlockStatisticType, std::string>{"MVDL0",                       BlockStatisticType::Vector,                 "Scale: 4"}},
-  { BlockStatistic::RefIdxL0,               std::tuple<std::string, BlockStatisticType, std::string>{"RefIdxL0",                    BlockStatisticType::Integer,                "[0, 4]"}}, 
-  { BlockStatistic::MVPIdxL1,               std::tuple<std::string, BlockStatisticType, std::string>{"MVPIdxL1",                    BlockStatisticType::Integer,                "[0, 1]"}}, 
+  { BlockStatistic::RefIdxL0,               std::tuple<std::string, BlockStatisticType, std::string>{"RefIdxL0",                    BlockStatisticType::Integer,                "[0, 4]"}},
+  { BlockStatistic::MVPIdxL1,               std::tuple<std::string, BlockStatisticType, std::string>{"MVPIdxL1",                    BlockStatisticType::Integer,                "[0, 1]"}},
   { BlockStatistic::MVDL1,                  std::tuple<std::string, BlockStatisticType, std::string>{"MVDL1",                       BlockStatisticType::Vector,                 "Scale: 4"}},
-  { BlockStatistic::RefIdxL1,               std::tuple<std::string, BlockStatisticType, std::string>{"RefIdxL1",                    BlockStatisticType::Integer,                "[0, 4]"}}, 
+  { BlockStatistic::RefIdxL1,               std::tuple<std::string, BlockStatisticType, std::string>{"RefIdxL1",                    BlockStatisticType::Integer,                "[0, 4]"}},
   { BlockStatistic::IMVMode,                std::tuple<std::string, BlockStatisticType, std::string>{"IMVMode",                     BlockStatisticType::Integer,                "[0, 2]"}},
   { BlockStatistic::AffineFlag,             std::tuple<std::string, BlockStatisticType, std::string>{"AffineFlag",                  BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::AffineMVL0,             std::tuple<std::string, BlockStatisticType, std::string>{"AffineMVL0",                  BlockStatisticType::AffineTFVectors,        "Scale: 4"}},
   { BlockStatistic::AffineMVL1,             std::tuple<std::string, BlockStatisticType, std::string>{"AffineMVL1",                  BlockStatisticType::AffineTFVectors,        "Scale: 4"}},
   { BlockStatistic::AffineType,             std::tuple<std::string, BlockStatisticType, std::string>{"AffineType",                  BlockStatisticType::Flag,                   ""} },
+#if !JVET_M0464_UNI_MTS
   { BlockStatistic::EMTFlag,                std::tuple<std::string, BlockStatisticType, std::string>{"EMTFlag",                     BlockStatisticType::Flag,                   ""}},
+#endif
   { BlockStatistic::MotionBufL0,            std::tuple<std::string, BlockStatisticType, std::string>{"MotionBufL0",                 BlockStatisticType::Vector,                 "Scale: 16"}},
   { BlockStatistic::MotionBufL1,            std::tuple<std::string, BlockStatisticType, std::string>{"MotionBufL1",                 BlockStatisticType::Vector,                 "Scale: 16"}},
-  { BlockStatistic::MultiRefIdx,            std::tuple<std::string, BlockStatisticType, std::string>{"MultiRefIdx",                 BlockStatisticType::Integer,                "[0, 1]"}}, 
+  { BlockStatistic::MultiRefIdx,            std::tuple<std::string, BlockStatisticType, std::string>{"MultiRefIdx",                 BlockStatisticType::Integer,                "[0, 1]"}},
   { BlockStatistic::MMVDSkipFlag,           std::tuple<std::string, BlockStatisticType, std::string>{"MMVDSkipFlag",                BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::MMVDMergeFlag,          std::tuple<std::string, BlockStatisticType, std::string>{"MMVDMergeFlag",               BlockStatisticType::Flag,                   ""}},
-  { BlockStatistic::MMVDMergeIdx,           std::tuple<std::string, BlockStatisticType, std::string>{"MMVDMergeIdx",                BlockStatisticType::Integer,                "[0, 1]"}}, 
+  { BlockStatistic::MMVDMergeIdx,           std::tuple<std::string, BlockStatisticType, std::string>{"MMVDMergeIdx",                BlockStatisticType::Integer,                "[0, 1]"}},
   { BlockStatistic::MHIntraFlag,            std::tuple<std::string, BlockStatisticType, std::string>{"MHIntraFlag",                 BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::TriangleFlag,           std::tuple<std::string, BlockStatisticType, std::string>{"TriangleFlag",                BlockStatisticType::Flag,                   ""}},
   { BlockStatistic::TrianglePartitioning,   std::tuple<std::string, BlockStatisticType, std::string>{"TrianglePartitioning",        BlockStatisticType::Line,                   ""}},
   { BlockStatistic::TriangleMVL0,           std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL0",                BlockStatisticType::VectorPolygon,          "Scale: 4"}},
   { BlockStatistic::TriangleMVL1,           std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL1",                BlockStatisticType::VectorPolygon,          "Scale: 4"}},
-  { BlockStatistic::GBIIndex,               std::tuple<std::string, BlockStatisticType, std::string>{"GBIIndex",                    BlockStatisticType::Integer,                "[0, 4]"}}, 
+  { BlockStatistic::GBIIndex,               std::tuple<std::string, BlockStatisticType, std::string>{"GBIIndex",                    BlockStatisticType::Integer,                "[0, 4]"}},
   { BlockStatistic::IBCFlag,                std::tuple<std::string, BlockStatisticType, std::string>{"IBCFlag",                     BlockStatisticType::Flag,                   ""}},
   // for dual tree
   { BlockStatistic::Depth_Chroma,                  std::tuple<std::string, BlockStatisticType, std::string>{"Depth_Chroma",                       BlockStatisticType::Integer,                "[0, 10]"}}, // todo: actual limits?
@@ -202,7 +214,9 @@ static const std::map<BlockStatistic, std::tuple<std::string, BlockStatisticType
   { BlockStatistic::QP_Chroma,                     std::tuple<std::string, BlockStatisticType, std::string>{"QP_Chroma",                          BlockStatisticType::Integer,                "[0, 51]"}},
   { BlockStatistic::SplitSeries_Chroma,            std::tuple<std::string, BlockStatisticType, std::string>{"SplitSeries_Chroma",                 BlockStatisticType::Integer,                "[0, " + std::to_string(std::numeric_limits<SplitSeries>::max()) + "]"}},
   { BlockStatistic::TransQuantBypassFlag_Chroma,   std::tuple<std::string, BlockStatisticType, std::string>{"TransQuantBypassFlag_Chroma",        BlockStatisticType::Flag,                   ""}},
+#if !JVET_M0464_UNI_MTS
   { BlockStatistic::EMTFlag_Chroma,                std::tuple<std::string, BlockStatisticType, std::string>{"EMTFlag_Chroma",                     BlockStatisticType::Integer,                "[0, 10]"}}, // todo: actual limits?
+#endif
   { BlockStatistic::IPCM_Chroma,                   std::tuple<std::string, BlockStatisticType, std::string>{"IPCM_Chroma",                        BlockStatisticType::Flag,                   ""}},
 
 };
diff --git a/source/Lib/CommonLib/dtrace_codingstruct.h b/source/Lib/CommonLib/dtrace_codingstruct.h
index a6876cd95ee89111e17e98f020488d9a5beeb1d7..eafc916e1b9cbfbb4fb646a057cbd8e59f1bc436 100644
--- a/source/Lib/CommonLib/dtrace_codingstruct.h
+++ b/source/Lib/CommonLib/dtrace_codingstruct.h
@@ -107,7 +107,7 @@ inline void dtraceModeCost(CodingStructure &cs, double lambda)
     cs.cus[0]->predMode,
     cs.cus[0]->skip,
     cs.pus[0]->mergeFlag,
-    0, 0, 
+    0, 0,
     imvVal,
     0, 0,
           intraModeL, intraModeC,
diff --git a/source/Lib/CommonLib/version.h b/source/Lib/CommonLib/version.h
index 31f140a5fca24d5bd588d7ed3d0e9ffe33735350..bc3dcb17073bc44cd1bfe4840b773451d978a4db 100644
--- a/source/Lib/CommonLib/version.h
+++ b/source/Lib/CommonLib/version.h
@@ -1,3 +1,3 @@
 #if ! defined( VTM_VERSION )
-#define VTM_VERSION "3.2"
+#define VTM_VERSION "4.0"
 #endif
diff --git a/source/Lib/CommonLib/x86/AffineGradientSearchX86.h b/source/Lib/CommonLib/x86/AffineGradientSearchX86.h
index b422db4f866e9c189c5d596e044e11d44dfc61c7..b49d703b9113dabc67a7c9d0637da9035a8cb3f7 100644
--- a/source/Lib/CommonLib/x86/AffineGradientSearchX86.h
+++ b/source/Lib/CommonLib/x86/AffineGradientSearchX86.h
@@ -214,7 +214,7 @@ static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDe
   int idx1 = 0, idx2 = 0;
   idx1 = -2 * derivateBufStride - 4;
   idx2 = -derivateBufStride - 4;
-  
+
   for ( int j = 0; j < height; j += 2 )
   {
     if (!(j & 3))
diff --git a/source/Lib/CommonLib/x86/BufferX86.h b/source/Lib/CommonLib/x86/BufferX86.h
index bdae6dcc51a4b2c2d87629bf3ff32b6e79e4bc64..0f10ff83cf6fd5ab2a39fb5b5109af51d1575a8b 100644
--- a/source/Lib/CommonLib/x86/BufferX86.h
+++ b/source/Lib/CommonLib/x86/BufferX86.h
@@ -128,6 +128,125 @@ void addAvg_SSE( const int16_t* src0, int src0Stride, const int16_t* src1, int s
   }
 }
 
+#if JVET_M0147_DMVR
+template<X86_VEXT vext>
+void copyBufferSimd(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height)
+{
+  __m128i x;
+#ifdef USE_AVX2
+  __m256i x16;
+#endif
+  int j, temp;
+  for (int i = 0; i < height; i++)
+  {
+    j = 0;
+    temp = width;
+#ifdef USE_AVX2
+    while ((temp >> 4) > 0)
+    {
+      x16 = _mm256_loadu_si256((const __m256i*)(&src[i * srcStride + j]));
+      _mm256_storeu_si256((__m256i*)(&dst[i * dstStride + j]), x16);
+      j += 16;
+      temp -= 16;
+    }
+#endif
+    while ((temp >> 3) > 0)
+    {
+      x = _mm_loadu_si128((const __m128i*)(&src[ i * srcStride + j]));
+      _mm_storeu_si128((__m128i*)(&dst[ i * dstStride + j]), x);
+      j += 8;
+      temp -= 8;
+    }
+    while ((temp >> 2) > 0)
+    {
+      x = _mm_loadl_epi64((const __m128i*)(&src[i * srcStride + j]));
+      _mm_storel_epi64((__m128i*)(&dst[i*dstStride + j]), x);
+      j += 4;
+      temp -= 4;
+    }
+    while (temp > 0)
+    {
+      dst[i * dstStride + j] = src[i * srcStride + j];
+      j++;
+      temp--;
+    }
+  }
+}
+
+
+template<X86_VEXT vext>
+void paddingSimd(Pel *dst, int stride, int width, int height, int padSize)
+{
+  __m128i x;
+#ifdef USE_AVX2
+  __m256i x16;
+#endif
+  int temp, j;
+  for (int i = 1; i <= padSize; i++)
+  {
+    j = 0;
+    temp = width;
+#ifdef USE_AVX2
+    while ((temp >> 4) > 0)
+    {
+
+      x16 = _mm256_loadu_si256((const __m256i*)(&(dst[j])));
+      _mm256_storeu_si256((__m256i*)(dst + j - i*stride), x16);
+      x16 = _mm256_loadu_si256((const __m256i*)(dst + j + (height - 1)*stride));
+      _mm256_storeu_si256((__m256i*)(dst + j + (height - 1 + i)*stride), x16);
+
+
+      j = j + 16;
+      temp = temp - 16;
+    }
+#endif
+    while ((temp >> 3) > 0)
+    {
+
+      x = _mm_loadu_si128((const __m128i*)(&(dst[j])));
+      _mm_storeu_si128((__m128i*)(dst + j - i*stride), x);
+      x = _mm_loadu_si128((const __m128i*)(dst + j + (height - 1)*stride));
+      _mm_storeu_si128((__m128i*)(dst + j + (height - 1 + i)*stride), x);
+
+      j = j + 8;
+      temp = temp - 8;
+    }
+    while ((temp >> 2) > 0)
+    {
+      x = _mm_loadl_epi64((const __m128i*)(&dst[j]));
+      _mm_storel_epi64((__m128i*)(dst + j - i*stride), x);
+      x = _mm_loadl_epi64((const __m128i*)(dst + j + (height - 1)*stride));
+      _mm_storel_epi64((__m128i*)(dst + j + (height - 1 + i)*stride), x);
+
+      j = j + 4;
+      temp = temp - 4;
+    }
+    while (temp > 0)
+    {
+      dst[j - i*stride] = dst[j];
+      dst[j + (height - 1 + i)*stride] = dst[j + (height - 1)*stride];
+      j++;
+      temp--;
+    }
+  }
+
+
+  //Left and Right Padding
+  Pel* ptr1 = dst - padSize*stride;
+  Pel* ptr2 = dst - padSize*stride + width - 1;
+  int offset = 0;
+  for (int i = 0; i < height + 2 * padSize; i++)
+  {
+    offset = stride * i;
+    for (int j = 1; j <= padSize; j++)
+    {
+      *(ptr1 - j + offset) = *(ptr1 + offset);
+      *(ptr2 + j + offset) = *(ptr2 + offset);
+    }
+
+  }
+}
+#endif
 template< X86_VEXT vext >
 void addBIOAvg4_SSE(const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel*gradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng)
 {
@@ -162,7 +281,11 @@ void addBIOAvg4_SSE(const Pel* src0, int src0Stride, const Pel* src1, int src1St
 }
 
 template< X86_VEXT vext >
+#if JVET_M0063_BDOF_FIX
+void gradFilter_SSE(Pel* src, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, const int bitDepth)
+#else
 void gradFilter_SSE(Pel* src, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY)
+#endif
 {
   __m128i vzero = _mm_setzero_si128();
   Pel* srcTmp = src + srcStride + 1;
@@ -171,6 +294,10 @@ void gradFilter_SSE(Pel* src, int srcStride, int width, int height, int gradStri
 
   int widthInside = width - 2 * BIO_EXTEND_SIZE;
   int heightInside = height - 2 * BIO_EXTEND_SIZE;
+#if JVET_M0063_BDOF_FIX
+  int shift1 = std::max<int>(2, (14 - bitDepth));
+#endif
+
 
   assert((widthInside & 3) == 0);
 
@@ -184,8 +311,13 @@ void gradFilter_SSE(Pel* src, int srcStride, int width, int height, int gradStri
       __m128i mmPixLeft = _mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i*)(srcTmp + x - 1)));
       __m128i mmPixRight = _mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i*)(srcTmp + x + 1)));
 
+#if JVET_M0063_BDOF_FIX
+      __m128i mmGradVer = _mm_sra_epi32(_mm_sub_epi32(mmPixBottom, mmPixTop), _mm_cvtsi32_si128(shift1));
+      __m128i mmGradHor = _mm_sra_epi32(_mm_sub_epi32(mmPixRight, mmPixLeft), _mm_cvtsi32_si128(shift1));
+#else
       __m128i mmGradVer = _mm_srai_epi32(_mm_sub_epi32(mmPixBottom, mmPixTop), 4);
       __m128i mmGradHor = _mm_srai_epi32(_mm_sub_epi32(mmPixRight, mmPixLeft), 4);
+#endif
       mmGradVer = _mm_packs_epi32(mmGradVer, vzero);
       mmGradHor = _mm_packs_epi32(mmGradHor, vzero);
 
@@ -220,23 +352,41 @@ void gradFilter_SSE(Pel* src, int srcStride, int width, int height, int gradStri
 }
 
 template< X86_VEXT vext >
+#if JVET_M0063_BDOF_FIX
+void calcBIOPar_SSE(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, const int bitDepth)
+#else
 void calcBIOPar_SSE(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG)
+#endif
 {
+#if JVET_M0063_BDOF_FIX
+  int shift4 = std::min<int>(8, (bitDepth - 4));
+  int shift5 = std::min<int>(5, (bitDepth - 7));
+#endif
   for (int y = 0; y < heightG; y++)
   {
     int x = 0;
     for (; x < ((widthG >> 3) << 3); x += 8)
     {
+#if JVET_M0063_BDOF_FIX
+      __m128i mmSrcY0Temp = _mm_sra_epi16(_mm_loadu_si128((__m128i*)(srcY0Temp + x)), _mm_cvtsi32_si128(shift4));
+      __m128i mmSrcY1Temp = _mm_sra_epi16(_mm_loadu_si128((__m128i*)(srcY1Temp + x)), _mm_cvtsi32_si128(shift4));
+#else
       __m128i mmSrcY0Temp = _mm_srai_epi16(_mm_loadu_si128((__m128i*)(srcY0Temp + x)), 6);
       __m128i mmSrcY1Temp = _mm_srai_epi16(_mm_loadu_si128((__m128i*)(srcY1Temp + x)), 6);
+#endif
       __m128i mmGradX0 = _mm_loadu_si128((__m128i*)(gradX0 + x));
       __m128i mmGradX1 = _mm_loadu_si128((__m128i*)(gradX1 + x));
       __m128i mmGradY0 = _mm_loadu_si128((__m128i*)(gradY0 + x));
       __m128i mmGradY1 = _mm_loadu_si128((__m128i*)(gradY1 + x));
 
       __m128i mmTemp1 = _mm_sub_epi16(mmSrcY1Temp, mmSrcY0Temp);
+#if JVET_M0063_BDOF_FIX
+      __m128i mmTempX = _mm_sra_epi16(_mm_add_epi16(mmGradX0, mmGradX1), _mm_cvtsi32_si128(shift5));
+      __m128i mmTempY = _mm_sra_epi16(_mm_add_epi16(mmGradY0, mmGradY1), _mm_cvtsi32_si128(shift5));
+#else
       __m128i mmTempX = _mm_srai_epi16(_mm_add_epi16(mmGradX0, mmGradX1), 3);
       __m128i mmTempY = _mm_srai_epi16(_mm_add_epi16(mmGradY0, mmGradY1), 3);
+#endif
 
       // m_piDotProductTemp1
       __m128i mm_b = _mm_mulhi_epi16(mmTempX, mmTempX);
@@ -291,16 +441,26 @@ void calcBIOPar_SSE(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX
 
     for (; x < ((widthG >> 2) << 2); x += 4)
     {
+#if JVET_M0063_BDOF_FIX
+      __m128i mmSrcY0Temp = _mm_sra_epi16(_mm_loadl_epi64((__m128i*)(srcY0Temp + x)), _mm_cvtsi32_si128(shift4));
+      __m128i mmSrcY1Temp = _mm_sra_epi16(_mm_loadl_epi64((__m128i*)(srcY1Temp + x)), _mm_cvtsi32_si128(shift4));
+#else
       __m128i mmSrcY0Temp = _mm_srai_epi16(_mm_loadl_epi64((__m128i*)(srcY0Temp + x)), 6);
       __m128i mmSrcY1Temp = _mm_srai_epi16(_mm_loadl_epi64((__m128i*)(srcY1Temp + x)), 6);
+#endif
       __m128i mmGradX0 = _mm_loadl_epi64((__m128i*)(gradX0 + x));
       __m128i mmGradX1 = _mm_loadl_epi64((__m128i*)(gradX1 + x));
       __m128i mmGradY0 = _mm_loadl_epi64((__m128i*)(gradY0 + x));
       __m128i mmGradY1 = _mm_loadl_epi64((__m128i*)(gradY1 + x));
 
       __m128i mmTemp1 = _mm_sub_epi16(mmSrcY1Temp, mmSrcY0Temp);
+#if JVET_M0063_BDOF_FIX
+      __m128i mmTempX = _mm_sra_epi16(_mm_add_epi16(mmGradX0, mmGradX1), _mm_cvtsi32_si128(shift5));
+      __m128i mmTempY = _mm_sra_epi16(_mm_add_epi16(mmGradY0, mmGradY1), _mm_cvtsi32_si128(shift5));
+#else
       __m128i mmTempX = _mm_srai_epi16(_mm_add_epi16(mmGradX0, mmGradX1), 3);
       __m128i mmTempY = _mm_srai_epi16(_mm_add_epi16(mmGradY0, mmGradY1), 3);
+#endif
 
       // m_piDotProductTemp1
       __m128i mm_b = _mm_mulhi_epi16(mmTempX, mmTempX);
@@ -340,9 +500,15 @@ void calcBIOPar_SSE(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX
 
     for (; x < widthG; x++)
     {
+#if JVET_M0063_BDOF_FIX
+      int temp = (srcY0Temp[x] >> shift4) - (srcY1Temp[x] >> shift4);
+      int tempX = (gradX0[x] + gradX1[x]) >> shift5;
+      int tempY = (gradY0[x] + gradY1[x]) >> shift5;
+#else
       int temp = (srcY0Temp[x] >> 6) - (srcY1Temp[x] >> 6);
       int tempX = (gradX0[x] + gradX1[x]) >> 3;
       int tempY = (gradY0[x] + gradY1[x]) >> 3;
+#endif
       dotProductTemp1[x] = tempX * tempX;
       dotProductTemp2[x] = tempX * tempY;
       dotProductTemp3[x] = -tempX * temp;
@@ -446,7 +612,7 @@ void reco_SSE( const int16_t* src0, int src0Stride, const int16_t* src1, int src
           __m256i vdest = _mm256_lddqu_si256( ( const __m256i * )&src0[col] );
           __m256i vsrc1 = _mm256_lddqu_si256( ( const __m256i * )&src1[col] );
 
-          vdest = _mm256_add_epi16( vdest, vsrc1 );
+          vdest = _mm256_adds_epi16( vdest, vsrc1 );
           vdest = _mm256_min_epi16( vbdmax, _mm256_max_epi16( vbdmin, vdest ) );
 
           _mm256_storeu_si256( ( __m256i * )&dst[col], vdest );
@@ -470,7 +636,7 @@ void reco_SSE( const int16_t* src0, int src0Stride, const int16_t* src1, int src
           __m128i vdest = _mm_loadu_si128( ( const __m128i * )&src0[col] );
           __m128i vsrc1 = _mm_loadu_si128( ( const __m128i * )&src1[col] );
 
-          vdest = _mm_add_epi16( vdest, vsrc1 );
+          vdest = _mm_adds_epi16( vdest, vsrc1 );
           vdest = _mm_min_epi16( vbdmax, _mm_max_epi16( vbdmin, vdest ) );
 
           _mm_storeu_si128( ( __m128i * )&dst[col], vdest );
@@ -494,7 +660,7 @@ void reco_SSE( const int16_t* src0, int src0Stride, const int16_t* src1, int src
         __m128i vsrc = _mm_loadl_epi64( ( const __m128i * )&src0[col] );
         __m128i vdst = _mm_loadl_epi64( ( const __m128i * )&src1[col] );
 
-        vdst = _mm_add_epi16( vdst, vsrc );
+        vdst = _mm_adds_epi16( vdst, vsrc );
         vdst = _mm_min_epi16( vbdmax, _mm_max_epi16( vbdmin, vdst ) );
 
         _mm_storel_epi64( ( __m128i * )&dst[col], vdst );
@@ -801,6 +967,10 @@ void PelBufferOps::_initPelBufOpsX86()
   calcBIOPar      = calcBIOPar_SSE<vext>;
   calcBlkGradient = calcBlkGradient_SSE<vext>;
 
+#if JVET_M0147_DMVR
+  copyBuffer = copyBufferSimd<vext>;
+  padding    = paddingSimd<vext>;
+#endif
   reco8 = reco_SSE<vext, 8>;
   reco4 = reco_SSE<vext, 4>;
 
diff --git a/source/Lib/CommonLib/x86/InitX86.cpp b/source/Lib/CommonLib/x86/InitX86.cpp
index 00f18ae12450d7db4c8c03c51cd6d3c31850b756..334987013a8315ad5381a103efed5cbf226c448c 100644
--- a/source/Lib/CommonLib/x86/InitX86.cpp
+++ b/source/Lib/CommonLib/x86/InitX86.cpp
@@ -171,7 +171,7 @@ void AdaptiveLoopFilter::initAdaptiveLoopFilterX86()
 void IbcHashMap::initIbcHashMapX86()
 {
   auto vext = read_x86_extension_flags();
-  switch (vext) 
+  switch (vext)
   {
   case AVX512:
   case AVX2:
diff --git a/source/Lib/CommonLib/x86/InterpolationFilterX86.h b/source/Lib/CommonLib/x86/InterpolationFilterX86.h
index 1c3b75f5383f4d4d51f27f44f23fb0f354c043eb..4bea013a3de5c0948e0d580980e0adf18c2df25c 100644
--- a/source/Lib/CommonLib/x86/InterpolationFilterX86.h
+++ b/source/Lib/CommonLib/x86/InterpolationFilterX86.h
@@ -193,7 +193,11 @@ static void fullPelCopyAVX2( const ClpRng& clpRng, const void*_src, int srcStrid
 
 
 template<X86_VEXT vext, bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+static void simdFilterCopy( const ClpRng& clpRng, const Pel* src, int srcStride, int16_t* dst, int dstStride, int width, int height, bool biMCForDMVR)
+#else
 static void simdFilterCopy( const ClpRng& clpRng, const Pel* src, int srcStride, int16_t* dst, int dstStride, int width, int height )
+#endif
 {
 #if !HM_JEM_CLIP_PEL
   if( vext >= AVX2 && ( width % 16 ) == 0 )
@@ -211,7 +215,11 @@ static void simdFilterCopy( const ClpRng& clpRng, const Pel* src, int srcStride,
   else
 #endif
   { //Scalar
+#if JVET_M0147_DMVR
+    InterpolationFilter::filterCopy<isFirst, isLast>( clpRng, src, srcStride, dst, dstStride, width, height, biMCForDMVR);
+#else
     InterpolationFilter::filterCopy<isFirst, isLast>( clpRng, src, srcStride, dst, dstStride, width, height );
+#endif
   }
 }
 
@@ -979,9 +987,102 @@ static void simdInterpolateN2_M4( const int16_t* src, int srcStride, int16_t *ds
     dst += dstStride;
   }
 }
+#if JVET_M0147_DMVR
+#ifdef USE_AVX2
+static inline __m256i simdInterpolateLuma10Bit2P16(int16_t const *src1, int srcStride, __m256i *mmCoeff, const __m256i & mmOffset, __m128i &mmShift)
+{
+  __m256i sumLo;
+  {
+    __m256i mmPix = _mm256_loadu_si256((__m256i*)src1);
+    __m256i mmPix1 = _mm256_loadu_si256((__m256i*)(src1 + srcStride));
+    __m256i lo0 = _mm256_mullo_epi16(mmPix, mmCoeff[0]);
+    __m256i lo1 = _mm256_mullo_epi16(mmPix1, mmCoeff[1]);
+    sumLo = _mm256_add_epi16(lo0, lo1);
+  }
+  sumLo = _mm256_sra_epi16(_mm256_add_epi16(sumLo, mmOffset), mmShift);
+  return(sumLo);
+}
+#endif
+
+static inline __m128i simdInterpolateLuma10Bit2P8(int16_t const *src1, int srcStride, __m128i *mmCoeff, const __m128i & mmOffset, __m128i &mmShift)
+{
+  __m128i sumLo;
+  {
+    __m128i mmPix = _mm_loadu_si128((__m128i*)src1);
+    __m128i mmPix1 = _mm_loadu_si128((__m128i*)(src1 + srcStride));
+    __m128i lo0 = _mm_mullo_epi16(mmPix, mmCoeff[0]);
+    __m128i lo1 = _mm_mullo_epi16(mmPix1, mmCoeff[1]);
+    sumLo = _mm_add_epi16(lo0, lo1);
+  }
+  sumLo = _mm_sra_epi16(_mm_add_epi16(sumLo, mmOffset), mmShift);
+  return(sumLo);
+}
+
+static inline __m128i simdInterpolateLuma10Bit2P4(int16_t const *src, int srcStride, __m128i *mmCoeff, const __m128i & mmOffset, __m128i &mmShift)
+{
+  __m128i sumLo;
+  {
+    __m128i mmPix = _mm_loadl_epi64((__m128i*)src);
+    __m128i mmPix1 = _mm_loadl_epi64((__m128i*)(src + srcStride));
+    __m128i lo0 = _mm_mullo_epi16(mmPix, mmCoeff[0]);
+    __m128i lo1 = _mm_mullo_epi16(mmPix1, mmCoeff[1]);
+    sumLo = _mm_add_epi16(lo0, lo1);
+  }
+  sumLo = _mm_sra_epi16(_mm_add_epi16(sumLo, mmOffset), mmShift);
+  return sumLo;
+}
+
+template<X86_VEXT vext, bool isLast>
+static void simdInterpolateN2_10BIT_M4(const int16_t* src, int srcStride, int16_t *dst, int dstStride, int cStride, int width, int height, int shift, int offset, const ClpRng& clpRng, int16_t const *c)
+{
+  int row, col;
+  __m128i mmOffset = _mm_set1_epi16(offset);
+  __m128i mmShift = _mm_set_epi64x(0, shift);
+  __m128i mmCoeff[2];
+  for (int n = 0; n < 2; n++)
+    mmCoeff[n] = _mm_set1_epi16(c[n]);
+
+  CHECK(isLast, "Not Supported");
+
+#if USE_AVX2
+  __m256i mm256Offset = _mm256_set1_epi16(offset);
+  __m256i mm256Coeff[2];
+  for (int n = 0; n < 2; n++)
+    mm256Coeff[n] = _mm256_set1_epi16(c[n]);
+#endif
+  for (row = 0; row < height; row++)
+  {
+    col = 0;
+#if USE_AVX2
+    // multiple of 16
+    for (; col < ((width >> 4) << 4); col += 16)
+    {
+      __m256i mmFiltered = simdInterpolateLuma10Bit2P16(src + col, cStride, mm256Coeff, mm256Offset, mmShift);
+      _mm256_storeu_si256((__m256i *)(dst + col), mmFiltered);
+    }
+#endif
+    // multiple of 8
+    for (; col < ((width >> 3) << 3); col += 8)
+    {
+      __m128i mmFiltered = simdInterpolateLuma10Bit2P8(src + col, cStride, mmCoeff, mmOffset, mmShift);
+      _mm_storeu_si128((__m128i *)(dst + col), mmFiltered);
+    }
+
+    // last 4 samples
+    __m128i mmFiltered = simdInterpolateLuma10Bit2P4(src + col, cStride, mmCoeff, mmOffset, mmShift);
+    _mm_storel_epi64((__m128i *)(dst + col), mmFiltered);
+    src += srcStride;
+    dst += dstStride;
+  }
+}
+#endif
 
 template<X86_VEXT vext, int N, bool isVertical, bool isFirst, bool isLast>
+#if JVET_M0147_DMVR
+static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR)
+#else
 static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff )
+#endif
 {
   int row, col;
 
@@ -1027,6 +1128,13 @@ static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel
     offset = ( isFirst ) ? -IF_INTERNAL_OFFS << shift : 0;
   }
 
+#if JVET_M0147_DMVR
+  if (biMCForDMVR)
+  {
+    shift = IF_FILTER_PREC_BILINEAR - (IF_INTERNAL_PREC_BILINEAR - clpRng.bd);
+    offset = 1 << (shift - 1);
+  }
+#endif
   if( clpRng.bd <= 10 )
   {
     if( N == 8 && !( width & 0x07 ) )
@@ -1075,6 +1183,16 @@ static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel
         simdInterpolateVerM4<vext, 4, isLast>( src, srcStride, dst, dstStride, width, height, shift, offset, clpRng, c );
       return;
     }
+#if JVET_M0147_DMVR
+    else if (biMCForDMVR)
+    {
+      if (N == 2 && !(width & 0x03))
+      {
+        simdInterpolateN2_10BIT_M4<vext, isLast>(src, srcStride, dst, dstStride, cStride, width, height, shift, offset, clpRng, c);
+        return;
+      }
+    }
+#endif
     else if( N == 2 && !( width & 0x07 ) )
     {
       simdInterpolateN2_M8<vext, isLast>( src, srcStride, dst, dstStride, cStride, width, height, shift, offset, clpRng, c );
diff --git a/source/Lib/DecoderLib/BinDecoder.cpp b/source/Lib/DecoderLib/BinDecoder.cpp
index 6486ebe33d38be96d304fdc5b91666194f5975c7..d86ba85529a7db610aa0eda10d8fde4538d9a277 100644
--- a/source/Lib/DecoderLib/BinDecoder.cpp
+++ b/source/Lib/DecoderLib/BinDecoder.cpp
@@ -182,8 +182,14 @@ unsigned BinDecoderBase::decodeBinsEP( unsigned numBins )
 
 unsigned BinDecoderBase::decodeRemAbsEP( unsigned goRicePar, bool useLimitedPrefixLength, int maxLog2TrDynamicRange )
 {
+#if JVET_M0470
+  unsigned cutoff = COEF_REMAIN_BIN_REDUCTION;
+  unsigned prefix = 0;
+  useLimitedPrefixLength = true;
+#else
   unsigned cutoff = g_auiGoRiceRange[ goRicePar ];
   unsigned prefix = 0;
+#endif
   if( useLimitedPrefixLength )
   {
     const unsigned  maxPrefix = 32 - maxLog2TrDynamicRange;
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 6015b1921d223706e2740de44633a9e6e42c505d..4fb88ca5c9b5052e9487536da93e44777ab1ed7d 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -127,10 +127,6 @@ void CABACReader::remaining_bytes( bool noTrailingBytesExpected )
   }
 }
 
-
-
-
-
 //================================================================================
 //  clause 7.3.8.2
 //--------------------------------------------------------------------------------
@@ -217,10 +213,6 @@ bool CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, i
   return isLast;
 }
 
-
-
-
-
 //================================================================================
 //  clause 7.3.8.3
 //--------------------------------------------------------------------------------
@@ -380,9 +372,6 @@ void CABACReader::sao( CodingStructure& cs, unsigned ctuRsAddr )
   }
 }
 
-
-
-
 //================================================================================
 //  clause 7.3.8.4
 //--------------------------------------------------------------------------------
@@ -690,7 +679,7 @@ PartSplit CABACReader::split_cu_mode( CodingStructure& cs, Partitioner &partitio
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__SPLIT_FLAG, partitioner.currArea().blocks[partitioner.chType].size(), partitioner.chType );
 
   PartSplit mode = CU_DONT_SPLIT;
-  
+
   bool canNo, canQt, canBh, canBv, canTh, canTv;
   partitioner.canSplit( cs, canNo, canQt, canBh, canBv, canTh, canTv );
 
@@ -813,7 +802,7 @@ PartSplit CABACReader::split_cu_mode_mt( CodingStructure& cs, Partitioner &parti
 
   dt.setAvail( DTT_SPLIT_BT_HORZ,  partitioner.canSplit( CU_HORZ_SPLIT, cs ) );
   dt.setAvail( DTT_SPLIT_BT_VERT,  partitioner.canSplit( CU_VERT_SPLIT, cs ) );
-  
+
   dt.setAvail( DTT_SPLIT_TT_HORZ,  partitioner.canSplit( CU_TRIH_SPLIT, cs ) );
   dt.setAvail( DTT_SPLIT_TT_VERT,  partitioner.canSplit( CU_TRIV_SPLIT, cs ) );
   dt.setAvail( DTT_SPLIT_NO_SPLIT, partitioner.canSplit( CU_DONT_SPLIT, cs ) );
@@ -885,7 +874,11 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
   }
 
   // skip flag
+#if JVET_M0483_IBC
+  if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid())
+#else
   if (!cs.slice->isIntra() && cu.Y().valid())
+#endif
   {
     cu_skip_flag( cu );
   }
@@ -924,6 +917,9 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
 
   extend_ref_line( cu );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  isp_mode( cu );
+#endif
 
   // prediction data ( intra prediction modes / reference indexes + motion vectors )
   cu_pred_data( cu );
@@ -948,12 +944,54 @@ void CABACReader::cu_skip_flag( CodingUnit& cu )
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SKIP_FLAG );
 
+#if JVET_M0483_IBC
+  if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    cu.skip = false;
+    cu.rootCbf = false;
+    cu.predMode = MODE_INTRA;
+    cu.mmvdSkip = false;
+    unsigned ctxId = DeriveCtx::CtxSkipFlag(cu);
+    unsigned skip = m_BinDecoder.decodeBin(Ctx::SkipFlag(ctxId));
+    if (skip)
+    {
+      cu.skip = true;
+      cu.rootCbf = false;
+      cu.predMode = MODE_IBC;
+      cu.mmvdSkip = false;
+    }
+
+    return;
+  }
+#endif
+
   unsigned ctxId  = DeriveCtx::CtxSkipFlag(cu);
   unsigned skip   = m_BinDecoder.decodeBin( Ctx::SkipFlag(ctxId) );
 
   DTRACE( g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, skip ? 1 : 0 );
 
+#if JVET_M0483_IBC
+  if (skip && cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+    if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx)))
+    {
+      cu.skip = true;
+      cu.rootCbf = false;
+      cu.predMode = MODE_IBC;
+      cu.mmvdSkip = false;
+    }
+    else
+    {
+      cu.predMode = MODE_INTER;
+    }
+    DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode);
+  }
+  if ((skip && CU::isInter(cu) && cu.cs->slice->getSPS()->getIBCFlag()) ||
+    (skip && !cu.cs->slice->getSPS()->getIBCFlag()))
+#else
   if( skip )
+#endif
   {
     unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0));
     cu.mmvdSkip = mmvdSkip;
@@ -968,7 +1006,7 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx )
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__OTHER );
 
-  if( !cu.cs->sps->getSpsNext().getUseIMV() )
+  if( !cu.cs->sps->getAMVREnabledFlag() )
   {
     return;
   }
@@ -979,17 +1017,28 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx )
     return;
   }
 
-  const SPSNext& spsNext = cu.cs->sps->getSpsNext();
+#if JVET_M0246_AFFINE_AMVR
+  if ( cu.affine )
+  {
+    return;
+  }
+#endif
+
+  const SPS *sps = cu.cs->sps;
 
   unsigned value = 0;
   unsigned ctxId = DeriveCtx::CtxIMVFlag( cu );
+#if JVET_M0483_IBC
+  if (CU::isIBC(cu))
+#else
   if (cu.firstPU->interDir == 1 && cu.cs->slice->getRefPic(REF_PIC_LIST_0, cu.firstPU->refIdx[REF_PIC_LIST_0])->getPOC() == cu.cs->slice->getPOC()) // the first bin of IMV flag does need to be signaled in IBC block
+#endif
     value = 1;
   else
     value = m_BinDecoder.decodeBin( Ctx::ImvFlag( ctxId ) );
   DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", value, ctxId );
 
-  if( spsNext.getImvMode() == IMV_4PEL && value )
+  if( sps->getAMVREnabledFlag() && value )
   {
     value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 3 ) );
     DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", value, 3 );
@@ -1000,10 +1049,92 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx )
   DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv );
 }
 
+#if JVET_M0246_AFFINE_AMVR
+void CABACReader::affine_amvr_mode( CodingUnit& cu, MergeCtx& mrgCtx )
+{
+  RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__OTHER );
+
+  const SPS* sps = cu.slice->getSPS();
+
+  if( !sps->getAffineAmvrEnabledFlag() || !cu.affine )
+  {
+    return;
+  }
+
+  if ( !CU::hasSubCUNonZeroAffineMVd( cu ) )
+  {
+    return;
+  }
+
+  unsigned value = 0;
+  value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 4 ) );
+  DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", value, 4 );
+
+  if( value )
+  {
+    value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 5 ) );
+    DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", value, 5 );
+    value++;
+  }
+
+  cu.imv = value;
+  DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() IMVFlag=%d\n", cu.imv );
+}
+#endif
+
 void CABACReader::pred_mode( CodingUnit& cu )
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__PRED_MODE );
 
+#if JVET_M0483_IBC
+  if (cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    if (cu.cs->slice->isIntra())
+    {
+      cu.predMode = MODE_INTRA;
+      unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+      if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx)))
+      {
+        cu.predMode = MODE_IBC;
+      }
+    }
+    else
+    {
+#if JVET_M0502_PRED_MODE_CTX
+      if (m_BinDecoder.decodeBin(Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu))))
+#else
+      if (m_BinDecoder.decodeBin(Ctx::PredMode()))
+#endif
+      {
+        cu.predMode = MODE_INTRA;
+      }
+      else
+      {
+        cu.predMode = MODE_INTER;
+        unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+        if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx)))
+        {
+          cu.predMode = MODE_IBC;
+        }
+      }
+    }
+  }
+  else
+  {
+#if JVET_M0502_PRED_MODE_CTX
+    if (cu.cs->slice->isIntra() || m_BinDecoder.decodeBin(Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu))))
+#else
+    if (cu.cs->slice->isIntra() || m_BinDecoder.decodeBin(Ctx::PredMode()))
+#endif
+    {
+      cu.predMode = MODE_INTRA;
+    }
+    else
+    {
+      cu.predMode = MODE_INTER;
+    }
+  }
+#else
 #if JVET_M0502_PRED_MODE_CTX
   if( cu.cs->slice->isIntra() || m_BinDecoder.decodeBin( Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)) ) )
 #else
@@ -1016,12 +1147,13 @@ void CABACReader::pred_mode( CodingUnit& cu )
   {
     cu.predMode = MODE_INTER;
   }
+#endif
 }
 
 void CABACReader::pcm_flag( CodingUnit& cu, Partitioner &partitioner )
 {
   const SPS& sps = *cu.cs->sps;
-  if( !sps.getPCMEnabledFlag() || partitioner.currArea().lwidth() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lwidth() < (1 << sps.getPCMLog2MinSize()) 
+  if( !sps.getPCMEnabledFlag() || partitioner.currArea().lwidth() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lwidth() < (1 << sps.getPCMLog2MinSize())
       || partitioner.currArea().lheight() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lheight() < (1 << sps.getPCMLog2MinSize()) )
   {
     cu.ipcm = false;
@@ -1041,8 +1173,12 @@ void CABACReader::cu_pred_data( CodingUnit &cu )
   }
   if (!cu.Y().valid()) // dual tree chroma CU
   {
+#if JVET_M0483_IBC
+    cu.predMode = MODE_IBC;
+#else
     cu.predMode = MODE_INTER;
     cu.ibc = true;
+#endif
     return;
   }
   MergeCtx mrgCtx;
@@ -1057,7 +1193,9 @@ void CABACReader::cu_pred_data( CodingUnit &cu )
   }
 
   imv_mode   ( cu, mrgCtx );
-
+#if JVET_M0246_AFFINE_AMVR
+  affine_amvr_mode( cu, mrgCtx );
+#endif
   cu_gbi_flag( cu );
 
 }
@@ -1142,8 +1280,13 @@ void CABACReader::xReadTruncBinCode(uint32_t& symbol, uint32_t maxSymbol)
     symbol -= (val - b);
   }
 }
+
 void CABACReader::extend_ref_line(CodingUnit& cu)
 {
+#if !ENABLE_JVET_L0283_MRL
+  return;
+#endif
+
   if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
   {
     cu.firstPU->multiRefIdx = 0;
@@ -1197,12 +1340,18 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
   for( int k = 0; k < numBlocks; k++ )
   {
     CHECK(numBlocks != 1, "not supported yet");
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( cu.firstPU->multiRefIdx || ( cu.ispMode && isLuma( cu.chType ) ) )
+#else
     if (cu.firstPU->multiRefIdx)
+#endif
     {
       mpmFlag[0] = true;
     }
     else
-    mpmFlag[k] = m_BinDecoder.decodeBin( Ctx::IPredMode[0]() );
+    {
+      mpmFlag[k] = m_BinDecoder.decodeBin(Ctx::IntraLumaMpmFlag());
+    }
   }
 
   PredictionUnit *pu = cu.firstPU;
@@ -1273,16 +1422,17 @@ void CABACReader::intra_chroma_pred_modes( CodingUnit& cu )
     intra_chroma_pred_mode( *pu );
   }
 }
+
 bool CABACReader::intra_chroma_lmc_mode( PredictionUnit& pu )
 {
-    int lmModeList[10];
-    int maxSymbol = PU::getLMSymbolList(pu, lmModeList);
-    int symbol    = unary_max_symbol( Ctx::IPredMode[1]( 2 ), Ctx::IPredMode[1]( 3 ), maxSymbol - 1 );
-    if ( lmModeList[ symbol ] != -1 )
-    {
-      pu.intraDir[1] = lmModeList[ symbol ];
-      return true;
-    }
+  int lmModeList[10];
+  int maxSymbol = PU::getLMSymbolList(pu, lmModeList);
+  int symbol    = unary_max_symbol(Ctx::IntraChromaPredMode(1), Ctx::IntraChromaPredMode(2), maxSymbol - 1);
+  if (lmModeList[symbol] != -1)
+  {
+    pu.intraDir[1] = lmModeList[symbol];
+    return true;
+  }
   return false;
 }
 
@@ -1290,16 +1440,14 @@ void CABACReader::intra_chroma_pred_mode( PredictionUnit& pu )
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__INTRA_DIR_ANG, pu.cu->blocks[pu.chType].lumaSize(), CHANNEL_TYPE_CHROMA );
 
+  if (m_BinDecoder.decodeBin(Ctx::IntraChromaPredMode(0)) == 0)
   {
-    if( m_BinDecoder.decodeBin( Ctx::IPredMode[1]( 1 ) ) == 0 )
-    {
-      pu.intraDir[1] = DM_CHROMA_IDX;
-      return;
-    }
+    pu.intraDir[1] = DM_CHROMA_IDX;
+    return;
   }
 
   // LM chroma mode
-  if( pu.cs->sps->getSpsNext().getUseLMChroma() )
+  if( pu.cs->sps->getUseLMChroma() )
   {
     if( intra_chroma_lmc_mode( pu ) )
     {
@@ -1320,7 +1468,11 @@ void CABACReader::intra_chroma_pred_mode( PredictionUnit& pu )
 
 void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& cuCtx )
 {
+#if JVET_M0483_IBC
+  if (!CU::isIntra(cu))
+#else
   if( CU::isInter( cu ) )
+#endif
   {
     PredictionUnit& pu = *cu.firstPU;
     if( !pu.mergeFlag )
@@ -1331,6 +1483,12 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx&
     {
       cu.rootCbf = true;
     }
+#if JVET_M0140_SBT
+    if( cu.rootCbf )
+    {
+      sbt_mode( cu );
+    }
+#endif
     if( !cu.rootCbf )
     {
       TransformUnit& tu = cu.cs->addTU(cu, partitioner.chType);
@@ -1347,7 +1505,19 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx&
   }
 
   ChromaCbfs chromaCbfs;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( cu.ispMode && isLuma( partitioner.chType ) )
+  {
+    TUIntraSubPartitioner subTuPartitioner( partitioner );
+    transform_tree( *cu.cs, subTuPartitioner, cuCtx, chromaCbfs, CU::getISPType( cu, getFirstComponentOfChannel( partitioner.chType ) ), 0 );
+  }
+  else
+  {
+    transform_tree( *cu.cs, partitioner, cuCtx, chromaCbfs );
+  }
+#else
   transform_tree( *cu.cs, partitioner, cuCtx, chromaCbfs );
+#endif
 }
 
 void CABACReader::rqt_root_cbf( CodingUnit& cu )
@@ -1359,6 +1529,64 @@ void CABACReader::rqt_root_cbf( CodingUnit& cu )
   DTRACE( g_trace_ctx, D_SYNTAX, "rqt_root_cbf() ctx=0 root_cbf=%d pos=(%d,%d)\n", cu.rootCbf ? 1 : 0, cu.lumaPos().x, cu.lumaPos().y );
 }
 
+#if JVET_M0140_SBT
+void CABACReader::sbt_mode( CodingUnit& cu )
+{
+  const uint8_t sbtAllowed = cu.checkAllowedSbt();
+  if( !sbtAllowed )
+  {
+    return;
+  }
+
+  SizeType cuWidth = cu.lwidth();
+  SizeType cuHeight = cu.lheight();
+
+  RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SBT_MODE );
+  //bin - flag
+  uint8_t ctxIdx = ( cuWidth * cuHeight <= 256 ) ? 1 : 0;
+  bool sbtFlag = m_BinDecoder.decodeBin( Ctx::SbtFlag( ctxIdx ) );
+  if( !sbtFlag )
+  {
+    return;
+  }
+
+  uint8_t sbtVerHalfAllow = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed );
+  uint8_t sbtHorHalfAllow = CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
+  uint8_t sbtVerQuadAllow = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed );
+  uint8_t sbtHorQuadAllow = CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
+
+  //bin - type
+  bool sbtQuadFlag = false;
+  if( ( sbtHorHalfAllow || sbtVerHalfAllow ) && ( sbtHorQuadAllow || sbtVerQuadAllow ) )
+  {
+    sbtQuadFlag = m_BinDecoder.decodeBin( Ctx::SbtQuadFlag( 0 ) );
+  }
+  else
+  {
+    sbtQuadFlag = 0;
+  }
+
+  //bin - dir
+  bool sbtHorFlag = false;
+  if( ( sbtQuadFlag && sbtVerQuadAllow && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtVerHalfAllow && sbtHorHalfAllow ) ) //both direction allowed
+  {
+    uint8_t ctxIdx = ( cuWidth == cuHeight ) ? 0 : ( cuWidth < cuHeight ? 1 : 2 );
+    sbtHorFlag = m_BinDecoder.decodeBin( Ctx::SbtHorFlag( ctxIdx ) );
+  }
+  else
+  {
+    sbtHorFlag = ( sbtQuadFlag && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtHorHalfAllow );
+  }
+  cu.setSbtIdx( sbtHorFlag ? ( sbtQuadFlag ? SBT_HOR_QUAD : SBT_HOR_HALF ) : ( sbtQuadFlag ? SBT_VER_QUAD : SBT_VER_HALF ) );
+
+  //bin - pos
+  bool sbtPosFlag = m_BinDecoder.decodeBin( Ctx::SbtPosFlag( 0 ) );
+  cu.setSbtPos( sbtPosFlag ? SBT_POS1 : SBT_POS0 );
+
+  DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), (int)cu.sbtInfo );
+}
+#endif
+
 
 bool CABACReader::end_of_ctu( CodingUnit& cu, CUCtx& cuCtx )
 {
@@ -1378,8 +1606,6 @@ bool CABACReader::end_of_ctu( CodingUnit& cu, CUCtx& cuCtx )
   return false;
 }
 
-
-
 //================================================================================
 //  clause 7.3.8.6
 //--------------------------------------------------------------------------------
@@ -1404,6 +1630,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
   }
   if( pu.mergeFlag )
   {
+#if JVET_M0483_IBC
+    if (CU::isIBC(*pu.cu))
+    {
+      merge_idx(pu);
+    }
+    else
+    {
+#endif
     subblock_merge_flag( *pu.cu );
     MHIntra_flag(pu);
     if (pu.mhIntraFlag)
@@ -1417,8 +1651,21 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
       mmvd_merge_idx(pu);
     }
     else
-    merge_data   ( pu );
+      merge_data   ( pu );
+#if JVET_M0483_IBC
+    }
+#endif
   }
+#if JVET_M0483_IBC
+  else if (CU::isIBC(*pu.cu))
+  {
+    pu.interDir = 1;
+    pu.cu->affine = false;
+    pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
+    mvd_coding(pu.mvd[REF_PIC_LIST_0]);
+    mvp_flag(pu, REF_PIC_LIST_0);
+  }
+#endif
   else
   {
     inter_pred_idc( pu );
@@ -1528,7 +1775,7 @@ void CABACReader::subblock_merge_flag( CodingUnit& cu )
     return;
   }
 
-  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getSpsNext().getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__AFFINE_FLAG );
 
@@ -1540,7 +1787,7 @@ void CABACReader::subblock_merge_flag( CodingUnit& cu )
 
 void CABACReader::affine_flag( CodingUnit& cu )
 {
-  if ( !cu.cs->slice->isIntra() && cu.cs->sps->getSpsNext().getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8 )
+  if ( !cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8 )
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__AFFINE_FLAG );
 
@@ -1548,7 +1795,7 @@ void CABACReader::affine_flag( CodingUnit& cu )
     cu.affine = m_BinDecoder.decodeBin( Ctx::AffineFlag( ctxId ) );
     DTRACE( g_trace_ctx, D_SYNTAX, "affine_flag() affine=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y );
 
-    if ( cu.affine && cu.cs->sps->getSpsNext().getUseAffineType() )
+    if ( cu.affine && cu.cs->sps->getUseAffineType() )
     {
       ctxId = 0;
       cu.affineType = m_BinDecoder.decodeBin( Ctx::AffineType( ctxId ) );
@@ -1568,6 +1815,15 @@ void CABACReader::merge_flag( PredictionUnit& pu )
   pu.mergeFlag = ( m_BinDecoder.decodeBin( Ctx::MergeFlag() ) );
 
   DTRACE( g_trace_ctx, D_SYNTAX, "merge_flag() merge=%d pos=(%d,%d) size=%dx%d\n", pu.mergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
+
+#if JVET_M0483_IBC
+  if (pu.mergeFlag && CU::isIBC(*pu.cu))
+  {
+    pu.mmvdMergeFlag = false;
+    return;
+  }
+#endif
+
   if (pu.mergeFlag)
   {
     pu.mmvdMergeFlag = (m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)));
@@ -1578,13 +1834,14 @@ void CABACReader::merge_flag( PredictionUnit& pu )
 
 void CABACReader::merge_data( PredictionUnit& pu )
 {
-
   if (pu.cu->mmvdSkip)
   {
     mmvd_merge_idx(pu);
   }
   else
-  merge_idx( pu );
+  {
+    merge_idx(pu);
+  }
 }
 
 
@@ -1600,10 +1857,13 @@ void CABACReader::merge_idx( PredictionUnit& pu )
     {
       if ( m_BinDecoder.decodeBin( Ctx::AffMergeIdx() ) )
       {
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
         bool useExtCtx = pu.cs->sps->getSBTMVPEnabledFlag();
+#endif
         pu.mergeIdx++;
         for ( ; pu.mergeIdx < numCandminus1; pu.mergeIdx++ )
         {
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
           if ( useExtCtx )
           {
             if ( !m_BinDecoder.decodeBin( Ctx::AffMergeIdx( std::min<int>( pu.mergeIdx, NUM_MERGE_IDX_EXT_CTX - 1 ) ) ) )
@@ -1613,11 +1873,14 @@ void CABACReader::merge_idx( PredictionUnit& pu )
           }
           else
           {
+#endif
             if ( !m_BinDecoder.decodeBinEP() )
             {
               break;
             }
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
           }
+#endif
         }
       }
     }
@@ -1631,6 +1894,38 @@ void CABACReader::merge_idx( PredictionUnit& pu )
   if( pu.cu->triangle )
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__TRIANGLE_INDEX );
+#if JVET_M0883_TRIANGLE_SIGNALING
+    bool    splitDir;
+    uint8_t candIdx0;
+    uint8_t candIdx1;
+    splitDir = m_BinDecoder.decodeBinEP();
+    auto decodeOneIdx = [this](int numCandminus1) -> uint8_t
+    {
+      uint8_t decIdx = 0;
+      if( numCandminus1 > 0 )
+      {
+        if( this->m_BinDecoder.decodeBin( Ctx::MergeIdx() ) )
+        {
+          decIdx++;
+          for( ; decIdx < numCandminus1; decIdx++ )
+          {
+            if( !this->m_BinDecoder.decodeBinEP() )
+              break;
+          }
+        }
+      }
+      return decIdx;
+    };
+    candIdx0 = decodeOneIdx(TRIANGLE_MAX_NUM_UNI_CANDS - 1);
+    candIdx1 = decodeOneIdx(TRIANGLE_MAX_NUM_UNI_CANDS - 2);
+    candIdx1 += candIdx1 >= candIdx0 ? 1 : 0;
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_split_dir=%d\n", splitDir );
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx0=%d\n", candIdx0 );
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx1=%d\n", candIdx1 );
+    pu.triangleSplitDir = splitDir;
+    pu.triangleMergeIdx0 = candIdx0;
+    pu.triangleMergeIdx1 = candIdx1;
+#else
     if( m_BinDecoder.decodeBin( Ctx::TriangleIdx() ) == 0 )
     {
       pu.mergeIdx += m_BinDecoder.decodeBinEP();
@@ -1641,6 +1936,7 @@ void CABACReader::merge_idx( PredictionUnit& pu )
     }
 
     DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx=%d\n", pu.mergeIdx );
+#endif
     return;
   }
 
@@ -1775,6 +2071,7 @@ void CABACReader::ref_idx( PredictionUnit &pu, RefPicList eRefList )
 #endif
 
   int numRef  = pu.cs->slice->getNumRefIdx(eRefList);
+
   if( numRef <= 1 || !m_BinDecoder.decodeBin( Ctx::RefPic() ) )
   {
     if( numRef > 1 )
@@ -1816,7 +2113,7 @@ void CABACReader::mvp_flag( PredictionUnit& pu, RefPicList eRefList )
 
 void CABACReader::MHIntra_flag(PredictionUnit& pu)
 {
-  if (!pu.cs->sps->getSpsNext().getUseMHIntra())
+  if (!pu.cs->sps->getUseMHIntra())
   {
     pu.mhIntraFlag = false;
     return;
@@ -1946,11 +2243,11 @@ void CABACReader::triangle_mode( CodingUnit& cu )
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__TRIANGLE_FLAG );
 
-  if( !cu.cs->slice->getSPS()->getSpsNext().getUseTriangle() || !cu.cs->slice->isInterB() || cu.lwidth() * cu.lheight() < TRIANGLE_MIN_SIZE || cu.affine )
+  if( !cu.cs->slice->getSPS()->getUseTriangle() || !cu.cs->slice->isInterB() || cu.lwidth() * cu.lheight() < TRIANGLE_MIN_SIZE || cu.affine )
   {
     return;
   }
-  
+
 #if JVET_M0118_M0185_TRIANGLE_FLAG_FIX
   if ( cu.firstPU->mmvdMergeFlag || cu.mmvdSkip )
   {
@@ -2003,10 +2300,6 @@ void CABACReader::pcm_samples( TransformUnit& tu )
   m_BinDecoder.start();
 }
 
-
-
-
-
 //================================================================================
 //  clause 7.3.8.8
 //--------------------------------------------------------------------------------
@@ -2015,33 +2308,83 @@ void CABACReader::pcm_samples( TransformUnit& tu )
 //    bool  cbf_comp            ( area, depth )
 //================================================================================
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner, CUCtx& cuCtx, ChromaCbfs& chromaCbfs, const PartSplit ispType, const int subTuIdx )
+#else
 void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner, CUCtx& cuCtx, ChromaCbfs& chromaCbfs )
+#endif
 {
+#if JVET_M0140_SBT
+  ChromaCbfs chromaCbfsLastDepth;
+  chromaCbfsLastDepth.Cb        = chromaCbfs.Cb;
+  chromaCbfsLastDepth.Cr        = chromaCbfs.Cr;
+#endif
   const UnitArea& area          = partitioner.currArea();
 
   CodingUnit&     cu            = *cs.getCU( area.blocks[partitioner.chType], partitioner.chType );
   const unsigned  trDepth       = partitioner.currTrDepth;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        int       subTuCounter  = subTuIdx;
+#endif
 
   // split_transform_flag
   bool split = false;
 
   split = partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
+#if JVET_M0140_SBT
+  if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+  {
+    split = true;
+  }
+#endif
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( !split && cu.ispMode )
+  {
+    split = partitioner.canSplit( ispType, cs );
+  }
+  const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode && !split;
+#endif
 
   // cbf_cb & cbf_cr
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && ( !CS::isDualITree( cs ) || partitioner.chType == CHANNEL_TYPE_CHROMA ) && ( !cu.ispMode || chromaCbfISP ) )
+#else
   if( area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && ( !CS::isDualITree( cs ) || partitioner.chType == CHANNEL_TYPE_CHROMA ) )
+#endif
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    const int cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
+    if (chromaCbfs.Cb)
     {
-      {
-        if( chromaCbfs.Cb )
-        {
-          chromaCbfs.Cb &= cbf_comp( cs, area.blocks[COMPONENT_Cb], trDepth );
-        }
-        if( chromaCbfs.Cr )
-        {
-          chromaCbfs.Cr &= cbf_comp( cs, area.blocks[COMPONENT_Cr], trDepth, chromaCbfs.Cb );
-        }
-      }
+#if JVET_M0140_SBT
+      if (!(cu.sbtInfo && trDepth == 1))
+#endif
+        chromaCbfs.Cb &= cbf_comp(cs, area.blocks[COMPONENT_Cb], cbfDepth);
     }
+    if (chromaCbfs.Cr)
+    {
+#if JVET_M0140_SBT
+      if (!(cu.sbtInfo && trDepth == 1))
+#endif
+        chromaCbfs.Cr &= cbf_comp(cs, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb);
+    }
+#else
+    if (chromaCbfs.Cb)
+    {
+#if JVET_M0140_SBT
+      if (!(cu.sbtInfo && trDepth == 1))
+#endif
+        chromaCbfs.Cb &= cbf_comp(cs, area.blocks[COMPONENT_Cb], trDepth);
+    }
+    if (chromaCbfs.Cr)
+    {
+#if JVET_M0140_SBT
+      if (!(cu.sbtInfo && trDepth == 1))
+#endif
+        chromaCbfs.Cr &= cbf_comp(cs, area.blocks[COMPONENT_Cr], trDepth, chromaCbfs.Cb);
+    }
+#endif
   }
   else if( CS::isDualITree( cs ) )
   {
@@ -2052,7 +2395,11 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
   {
     {
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( trDepth == 0 && !cu.ispMode ) emt_cu_flag( cu );
+#else
       if( trDepth == 0 ) emt_cu_flag( cu );
+#endif
 #endif
 
       if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
@@ -2064,6 +2411,18 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
 #endif
         partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
       }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      else if( cu.ispMode )
+      {
+        partitioner.splitCurrArea( ispType, cs );
+      }
+#endif
+#if JVET_M0140_SBT
+      else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+      {
+        partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
+      }
+#endif
       else
         THROW( "Implicit TU split not available!" );
     }
@@ -2071,7 +2430,12 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
     do
     {
       ChromaCbfs subCbfs = chromaCbfs;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      transform_tree( cs, partitioner, cuCtx, subCbfs, ispType, subTuCounter );
+      subTuCounter += subTuCounter != -1 ? 1 : 0;
+#else
       transform_tree( cs, partitioner, cuCtx, subCbfs );
+#endif
     } while( partitioner.nextPart( cs ) );
 
     partitioner.exitCurrSplit();
@@ -2081,7 +2445,17 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
     const unsigned numTBlocks = getNumberValidTBlocks( *cs.pcv );
 
     unsigned        compCbf[3] = { 0, 0, 0 };
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    unsigned        cbfDepth   = 0;
+    for( auto &currTU : cs.traverseTUs( currArea, partitioner.chType ) )
+    {
+      for( unsigned ch = 0; ch < numTBlocks; ch++ )
+      {
+        cbfDepth     = !isLuma( ComponentID( ch ) ) && cu.ispMode ? currDepth : currDepth + 1;
+        compCbf[ch] |= ( TU::getCbfAtDepth( currTU, ComponentID( ch ), cbfDepth ) ? 1 : 0 );
+      }
+    }
+#else
     for( auto &currTU : cs.traverseTUs( currArea, partitioner.chType ) )
     {
       for( unsigned ch = 0; ch < numTBlocks; ch++ )
@@ -2089,17 +2463,15 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
         compCbf[ch] |= ( TU::getCbfAtDepth( currTU, ComponentID( ch ), currDepth + 1 ) ? 1 : 0 );
       }
     }
+#endif
 
+    for (auto &currTU: cs.traverseTUs(currArea, partitioner.chType))
     {
-
-      for( auto &currTU : cs.traverseTUs( currArea, partitioner.chType ) )
+      TU::setCbfAtDepth(currTU, COMPONENT_Y, currDepth, compCbf[COMPONENT_Y]);
+      if (currArea.chromaFormat != CHROMA_400)
       {
-        TU::setCbfAtDepth( currTU, COMPONENT_Y, currDepth, compCbf[COMPONENT_Y] );
-        if( currArea.chromaFormat != CHROMA_400 )
-        {
-          TU::setCbfAtDepth( currTU, COMPONENT_Cb, currDepth, compCbf[COMPONENT_Cb] );
-          TU::setCbfAtDepth( currTU, COMPONENT_Cr, currDepth, compCbf[COMPONENT_Cr] );
-        }
+        TU::setCbfAtDepth(currTU, COMPONENT_Cb, currDepth, compCbf[COMPONENT_Cb]);
+        TU::setCbfAtDepth(currTU, COMPONENT_Cr, currDepth, compCbf[COMPONENT_Cr]);
       }
     }
   }
@@ -2107,6 +2479,11 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
   {
     TransformUnit &tu = cs.addTU( CS::getArea( cs, area, partitioner.chType ), partitioner.chType );
     unsigned numBlocks = ::getNumberValidTBlocks( *cs.pcv );
+#if JVET_M0140_SBT
+    tu.checkTuNoResidual( partitioner.currPartIdx() );
+    chromaCbfs.Cb &= !tu.noResidual;
+    chromaCbfs.Cr &= !tu.noResidual;
+#endif
 
     for( unsigned compID = COMPONENT_Y; compID < numBlocks; compID++ )
     {
@@ -2125,13 +2502,56 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
       {
         TU::setCbfAtDepth( tu, COMPONENT_Y, trDepth, 1 );
       }
+#if JVET_M0140_SBT
+      else if( cu.sbtInfo && tu.noResidual )
+      {
+        TU::setCbfAtDepth( tu, COMPONENT_Y, trDepth, 0 );
+      }
+      else if( cu.sbtInfo && !chromaCbfsLastDepth.sigChroma( area.chromaFormat ) )
+      {
+        assert( !tu.noResidual );
+        TU::setCbfAtDepth( tu, COMPONENT_Y, trDepth, 1 );
+      }
+#endif
       else
       {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        bool previousCbf       = false;
+        bool rootCbfSoFar      = false;
+        bool lastCbfIsInferred = false;
+        if( cu.ispMode )
+        {
+          uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[tu.lheight()] : cu.lwidth() >> g_aucLog2[tu.lwidth()];
+          if( subTuCounter == nTus - 1 )
+          {
+            TransformUnit* tuPointer = cu.firstTU;
+            for( int tuIdx = 0; tuIdx < nTus - 1; tuIdx++ )
+            {
+              rootCbfSoFar |= TU::getCbfAtDepth( *tuPointer, COMPONENT_Y, trDepth );
+              tuPointer = tuPointer->next;
+            }
+            if( !rootCbfSoFar )
+            {
+              lastCbfIsInferred = true;
+            }
+          }
+          if( !lastCbfIsInferred )
+          {
+            previousCbf = TU::getPrevTuCbfAtDepth( tu, COMPONENT_Y, trDepth );
+          }
+        }
+        bool cbfY = lastCbfIsInferred ? true : cbf_comp( cs, tu.Y(), trDepth, previousCbf, cu.ispMode );
+#else
         bool cbfY = cbf_comp( cs, tu.Y(), trDepth );
+#endif
         TU::setCbfAtDepth( tu, COMPONENT_Y, trDepth, ( cbfY ? 1 : 0 ) );
       }
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( area.chromaFormat != CHROMA_400 && ( !cu.ispMode || chromaCbfISP ) )
+#else
     if( area.chromaFormat != CHROMA_400 )
+#endif
     {
       TU::setCbfAtDepth( tu, COMPONENT_Cb, trDepth, ( chromaCbfs.Cb ? 1 : 0 ) );
       TU::setCbfAtDepth( tu, COMPONENT_Cr, trDepth, ( chromaCbfs.Cr ? 1 : 0 ) );
@@ -2145,9 +2565,15 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+bool CABACReader::cbf_comp( CodingStructure& cs, const CompArea& area, unsigned depth, const bool prevCbf, const bool useISP )
+{
+  const unsigned  ctxId = DeriveCtx::CtxQtCbf( area.compID, depth, prevCbf, useISP && isLuma( area.compID ) );
+#else
 bool CABACReader::cbf_comp( CodingStructure& cs, const CompArea& area, unsigned depth, const bool prevCbCbf )
 {
   const unsigned  ctxId   = DeriveCtx::CtxQtCbf( area.compID, depth, prevCbCbf );
+#endif
   const CtxSet&   ctxSet  = Ctx::QtCbf[ area.compID ];
 
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2(STATS__CABAC_BITS__QT_CBF, area.size(), area.compID);
@@ -2158,10 +2584,6 @@ bool CABACReader::cbf_comp( CodingStructure& cs, const CompArea& area, unsigned
   return cbf;
 }
 
-
-
-
-
 //================================================================================
 //  clause 7.3.8.9
 //--------------------------------------------------------------------------------
@@ -2233,7 +2655,11 @@ void CABACReader::transform_unit( TransformUnit& tu, CUCtx& cuCtx, ChromaCbfs& c
   CodingUnit& cu         = *tu.cu;
   bool        lumaOnly   = ( cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid() );
   bool        cbfLuma    = ( tu.cbf[ COMPONENT_Y ] != 0 );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  bool        cbfChroma  = ( lumaOnly ? false : ( chromaCbfs.Cb || chromaCbfs.Cr ) );
+#else
   bool        cbfChroma  = ( cu.chromaFormat == CHROMA_400 ? false : ( chromaCbfs.Cb || chromaCbfs.Cr ) );
+#endif
 
   if( cbfLuma || cbfChroma )
   {
@@ -2316,10 +2742,6 @@ void CABACReader::cu_chroma_qp_offset( CodingUnit& cu )
   cu.chromaQpAdj = cu.cs->chromaQpAdj = qpAdj;
 }
 
-
-
-
-
 //================================================================================
 //  clause 7.3.8.11
 //--------------------------------------------------------------------------------
@@ -2374,20 +2796,48 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID )
 #endif
 
   // parse last coeff position
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  cctx.setScanPosLast( last_sig_coeff( cctx, tu, compID ) );
+#else
   cctx.setScanPosLast( last_sig_coeff( cctx ) );
+#endif
 
   // parse subblocks
   const int stateTransTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
   int       state         = 0;
 
 #if !JVET_M0464_UNI_MTS
-  bool useEmt = ( cu.cs->sps->getSpsNext().getUseIntraEMT() && cu.predMode == MODE_INTRA ) || ( cu.cs->sps->getSpsNext().getUseInterEMT() && cu.predMode != MODE_INTRA );
+  bool useEmt = ( cu.cs->sps->getUseIntraEMT() && cu.predMode == MODE_INTRA ) || ( cu.cs->sps->getUseInterEMT() && cu.predMode != MODE_INTRA );
   useEmt = useEmt && isLuma(compID);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  useEmt = useEmt && !cu.ispMode;
+#endif
 #endif
 
     for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
     {
       cctx.initSubblock       ( subSetId );
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+#if JVET_M0140_SBT
+#if JVET_M0464_UNI_MTS
+      if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+      if( ( ( tu.cu->emtFlag && !tu.transformSkip[ compID ] ) || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#else
+#if JVET_M0464_UNI_MTS
+      if( tu.mtsIdx > 1 && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+      if( tu.cu->emtFlag && !tu.transformSkip[ compID ] && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#endif
+      {
+        if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) ) || ( tu.blocks[ compID ].width == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth() ) ) )
+        {
+          continue;
+        }
+      }
+#endif
       residual_coding_subblock( cctx, coeff, stateTransTab, state );
 #if !JVET_M0464_UNI_MTS
       if (useEmt)
@@ -2422,6 +2872,8 @@ void CABACReader::mts_coding( TransformUnit& tu, ComponentID compID )
 
   if( !mtsAllowed && !tsAllowed ) return;
 
+  RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__MTS_FLAGS, tu.blocks[compID], compID );
+
   int symbol = 0;
   int ctxIdx = 0;
 
@@ -2461,8 +2913,11 @@ void CABACReader::mts_coding( TransformUnit& tu, ComponentID compID )
 #else
 void CABACReader::transform_skip_flag( TransformUnit& tu, ComponentID compID )
 {
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( !tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag( *tu.cs, tu.blocks[compID] ) || ( isLuma( compID ) && tu.cu->emtFlag ) || ( tu.cu->ispMode && isLuma( compID ) ) )
+#else
   if( !tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag( *tu.cs, tu.blocks[compID] ) || ( isLuma( compID ) && tu.cu->emtFlag ) )
+#endif
   {
     tu.transformSkip[compID] = false;
     return;
@@ -2506,9 +2961,19 @@ void CABACReader::emt_tu_index( TransformUnit& tu )
 
 void CABACReader::emt_cu_flag( CodingUnit& cu )
 {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if ( CU::isIntra( cu ) && cu.ispMode )
+  {
+    return;
+  }
+#endif
   const CodingStructure &cs = *cu.cs;
 
-  if( !( ( cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getSpsNext().getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) )
+#if JVET_M0483_IBC
+  if (!((cs.sps->getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getUseInterEMT() && !CU::isIntra(cu))) || isChroma(cu.chType))
+#else
+  if( !( ( cs.sps->getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) )
+#endif
   {
     return;
   }
@@ -2539,6 +3004,46 @@ void CABACReader::emt_cu_flag( CodingUnit& cu )
 }
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void CABACReader::isp_mode( CodingUnit& cu )
+{
+  if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx )
+  {
+    cu.ispMode = NOT_INTRA_SUBPARTITIONS;
+    return;
+  }
+
+  const ISPType allowedSplits = CU::canUseISPSplit( cu, getFirstComponentOfChannel( cu.chType ) );
+  if( allowedSplits == NOT_INTRA_SUBPARTITIONS )
+  {
+    cu.ispMode = NOT_INTRA_SUBPARTITIONS;
+    return;
+  }
+
+  RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__ISP_MODE_FLAG );
+  cu.ispMode = NOT_INTRA_SUBPARTITIONS;
+  int symbol = m_BinDecoder.decodeBin( Ctx::ISPMode( 0 ) );
+
+  if( symbol )
+  {
+    if( allowedSplits == HOR_INTRA_SUBPARTITIONS )
+    {
+      cu.ispMode = HOR_INTRA_SUBPARTITIONS;
+    }
+    else if( allowedSplits == VER_INTRA_SUBPARTITIONS )
+    {
+      cu.ispMode = VER_INTRA_SUBPARTITIONS;
+    }
+    else
+    {
+      RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__ISP_SPLIT_FLAG );
+      cu.ispMode = 1 + m_BinDecoder.decodeBin( Ctx::ISPMode( 1 ) );
+    }
+  }
+  DTRACE( g_trace_ctx, D_SYNTAX, "intra_subPartitions() etype=%d pos=(%d,%d) ispIdx=%d\n", cu.chType, cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, (int)cu.ispMode );
+}
+#endif
+
 void CABACReader::explicit_rdpcm_mode( TransformUnit& tu, ComponentID compID )
 {
   const CodingUnit& cu = *tu.cu;
@@ -2569,11 +3074,52 @@ void CABACReader::explicit_rdpcm_mode( TransformUnit& tu, ComponentID compID )
 }
 
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+int CABACReader::last_sig_coeff( CoeffCodingContext& cctx, TransformUnit& tu, ComponentID compID )
+#else
 int CABACReader::last_sig_coeff( CoeffCodingContext& cctx )
+#endif
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__LAST_SIG_X_Y, Size( cctx.width(), cctx.height() ), cctx.compID() );
 
   unsigned PosLastX = 0, PosLastY = 0;
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  unsigned maxLastPosX = cctx.maxLastPosX();
+  unsigned maxLastPosY = cctx.maxLastPosY();
+
+#if JVET_M0140_SBT
+#if JVET_M0464_UNI_MTS
+  if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+  if( ( ( tu.cu->emtFlag && !tu.transformSkip[ compID ] ) || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#else
+#if JVET_M0464_UNI_MTS
+  if( tu.mtsIdx > 1 && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+  if( tu.cu->emtFlag && !tu.transformSkip[ compID ] && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#endif
+  {
+    maxLastPosX = ( tu.blocks[ compID ].width  == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
+    maxLastPosY = ( tu.blocks[ compID ].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;
+  }
+
+  for( ; PosLastX < maxLastPosX; PosLastX++ )
+  {
+    if( !m_BinDecoder.decodeBin( cctx.lastXCtxId( PosLastX ) ) )
+    {
+      break;
+    }
+  }
+  for( ; PosLastY < maxLastPosY; PosLastY++ )
+  {
+    if( !m_BinDecoder.decodeBin( cctx.lastYCtxId( PosLastY ) ) )
+    {
+      break;
+    }
+  }
+#else
   for( ; PosLastX < cctx.maxLastPosX(); PosLastX++ )
   {
     if( ! m_BinDecoder.decodeBin( cctx.lastXCtxId( PosLastX ) ) )
@@ -2588,6 +3134,7 @@ int CABACReader::last_sig_coeff( CoeffCodingContext& cctx )
       break;
     }
   }
+#endif
   if( PosLastX > 3 )
   {
     uint32_t uiTemp  = 0;
@@ -2873,11 +3420,6 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co
 #endif
 }
 
-
-
-
-
-
 //================================================================================
 //  clause 7.3.8.12
 //--------------------------------------------------------------------------------
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index 8e5586e5007f95e5575812bfd5fbe899116e6aca..e0724dac6d9fe647a80ef5751e64e9a051e08898 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -96,6 +96,9 @@ public:
   void        intra_chroma_pred_mode    ( PredictionUnit&               pu );
   void        cu_residual               ( CodingUnit&                   cu,     Partitioner&    pm,       CUCtx& cuCtx );
   void        rqt_root_cbf              ( CodingUnit&                   cu );
+#if JVET_M0140_SBT
+  void        sbt_mode                  ( CodingUnit&                   cu );
+#endif
   bool        end_of_ctu                ( CodingUnit&                   cu,     CUCtx&          cuCtx );
 
   // prediction unit (clause 7.3.8.6)
@@ -107,6 +110,9 @@ public:
   void        merge_idx                 ( PredictionUnit&               pu );
   void        mmvd_merge_idx(PredictionUnit&               pu);
   void        imv_mode                  ( CodingUnit&                   cu,     MergeCtx&       mrgCtx );
+#if JVET_M0246_AFFINE_AMVR
+  void        affine_amvr_mode          ( CodingUnit&                   cu,     MergeCtx&       mrgCtx );
+#endif
   void        inter_pred_idc            ( PredictionUnit&               pu );
   void        ref_idx                   ( PredictionUnit&               pu,     RefPicList      eRefList );
   void        mvp_flag                  ( PredictionUnit&               pu,     RefPicList      eRefList );
@@ -121,8 +127,13 @@ public:
   void        pcm_samples               ( TransformUnit&                tu );
 
   // transform tree (clause 7.3.8.8)
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void        transform_tree            ( CodingStructure&              cs,     Partitioner&    pm,       CUCtx& cuCtx,  ChromaCbfs& chromaCbfs, const PartSplit ispType = TU_NO_ISP, const int subTuIdx = -1 );
+  bool        cbf_comp                  ( CodingStructure&              cs,     const CompArea& area,     unsigned depth, const bool prevCbCbf = false, const bool useISP = false );
+#else
   void        transform_tree            ( CodingStructure&              cs,     Partitioner&    pm,       CUCtx& cuCtx,  ChromaCbfs& chromaCbfs );
   bool        cbf_comp                  ( CodingStructure&              cs,     const CompArea& area,     unsigned depth, const bool prevCbCbf = false );
+#endif
 
   // mvd coding (clause 7.3.8.9)
   void        mvd_coding                ( Mv &rMvd );
@@ -140,9 +151,16 @@ public:
   void        transform_skip_flag       ( TransformUnit&                tu,     ComponentID     compID );
   void        emt_tu_index              ( TransformUnit&                tu );
   void        emt_cu_flag               ( CodingUnit&                   cu );
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void        isp_mode                  ( CodingUnit&                   cu );
 #endif
   void        explicit_rdpcm_mode       ( TransformUnit&                tu,     ComponentID     compID );
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  int         last_sig_coeff            ( CoeffCodingContext&           cctx,   TransformUnit& tu, ComponentID   compID );
+#else
   int         last_sig_coeff            ( CoeffCodingContext&           cctx );
+#endif
   void        residual_coding_subblock  ( CoeffCodingContext&           cctx,   TCoeff*         coeff, const int stateTransTable, int& state );
 
   // cross component prediction (clause 7.3.8.12)
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 6913f67f690f184b7f47a0e3664118494d989372..8a85f4cc748f6b1789d92f6f44eece7df1bdf674 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -62,6 +62,9 @@
 
 DecCu::DecCu()
 {
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU = NULL;
+#endif
 }
 
 DecCu::~DecCu()
@@ -74,6 +77,27 @@ void DecCu::init( TrQuant* pcTrQuant, IntraPrediction* pcIntra, InterPrediction*
   m_pcIntraPred     = pcIntra;
   m_pcInterPred     = pcInter;
 }
+#if JVET_M0427_INLOOP_RESHAPER
+void DecCu::initDecCuReshaper  (Reshape* pcReshape, ChromaFormat chromaFormatIDC)
+{
+  m_pcReshape = pcReshape;
+  if (m_tmpStorageLCU == NULL)
+  {
+    m_tmpStorageLCU = new PelStorage;
+    m_tmpStorageLCU->create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+  }
+
+}
+void DecCu::destoryDecCuReshaprBuf()
+{
+  if (m_tmpStorageLCU)
+  {
+    m_tmpStorageLCU->destroy();
+    delete m_tmpStorageLCU;
+    m_tmpStorageLCU = NULL;
+  }
+}
+#endif
 
 // ====================================================================================================================
 // Public member functions
@@ -96,7 +120,7 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
     const ChannelType chType = ChannelType( ch );
 #if JVET_M0170_MRG_SHARELIST
     Position prevTmpPos;
-    prevTmpPos.x = -1; prevTmpPos.y = -1; 
+    prevTmpPos.x = -1; prevTmpPos.y = -1;
 #endif
 
     for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) )
@@ -109,7 +133,7 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
           m_shareStateDec = GEN_ON_SHARED_BOUND;
           cs.slice->copyMotionLUTs(cs.slice->getMotionLUTs(), cs.slice->m_MotionCandLuTsBkup);
         }
-        
+
         if (currCU.shareParentPos.x < 0)
         {
           m_shareStateDec = 0;
@@ -125,6 +149,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
       switch( currCU.predMode )
       {
       case MODE_INTER:
+#if JVET_M0483_IBC
+      case MODE_IBC:
+#endif
         xReconInter( currCU );
         break;
       case MODE_INTRA:
@@ -185,7 +212,24 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
   {
     m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
   }
-
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+#if JVET_M0483_IBC
+  bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()));
+#else
+  bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()) || (slice.getSliceType() == P_SLICE && slice.getSPS()->getIBCMode()));
+#endif
+  if (flag && slice.getReshapeInfo().getSliceReshapeChromaAdj() && (compID != COMPONENT_Y))
+  {
+    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
+    const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
+    PelBuf piPredY;
+    piPredY = cs.picture->getPredBuf(areaY);
+    const Pel avgLuma = piPredY.computeAvg();
+    int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+    tu.setChromaAdj(adj);
+  }
+#endif
   //===== inverse transform =====
   PelBuf piResi = cs.getResiBuf( area );
 
@@ -201,6 +245,13 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
+  if (flag && TU::getCbf(tu, compID) && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+  {
+    piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
+  }
+#endif
   if( isChroma(compID) && tu.compAlpha[compID] != 0 )
   {
     CrossComponentPrediction::crossComponentPrediction( tu, compID, cs.getResiBuf( tu.Y() ), piResi, piResi, true );
@@ -208,8 +259,38 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
 
   PelBuf pReco = cs.getRecoBuf( area );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( !tu.cu->ispMode || !isLuma( compID ) )
+  {
+    cs.setDecomp( area );
+  }
+  else if( tu.cu->ispMode && isLuma( compID ) && CU::isISPFirst( *tu.cu, tu.blocks[compID], compID ) )
+  {
+    cs.setDecomp( tu.cu->blocks[compID] );
+  }
+#else
   cs.setDecomp( area );
+#endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+#if REUSE_CU_RESULTS
+  CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+  PelBuf tmpPred;
+#endif
+#if JVET_M0483_IBC
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
+#else
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra() || (slice.getSliceType() == P_SLICE && slice.getSPS()->getIBCMode())) && compID == COMPONENT_Y)
+#endif
+  {
+#if REUSE_CU_RESULTS
+    {
+      tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+      tmpPred.copyFrom(piPred);
+    }
+#endif
+  }
+#endif
 #if KEEP_PRED_AND_RESI_SIGNALS
   pReco.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );
 #else
@@ -218,10 +299,27 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
 #if !KEEP_PRED_AND_RESI_SIGNALS
   pReco.copyFrom( piPred );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
+#else
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra() || (slice.getSliceType() == P_SLICE && slice.getSPS()->getIBCMode())) && compID == COMPONENT_Y)
+#endif
+  {
+#if REUSE_CU_RESULTS
+    {
+      piPred.copyFrom(tmpPred);
+    }
+#endif
+  }
+#endif
 #if REUSE_CU_RESULTS
   if( cs.pcv->isEncoder )
   {
     cs.picture->getRecoBuf( area ).copyFrom( pReco );
+#if JVET_M0427_INLOOP_RESHAPER
+    cs.picture->getPredBuf(area).copyFrom(piPred);
+#endif
   }
 #endif
 }
@@ -352,22 +450,39 @@ void DecCu::xReconInter(CodingUnit &cu)
 {
   if( cu.triangle )
   {
+#if JVET_M0883_TRIANGLE_SIGNALING
+    const bool    splitDir = cu.firstPU->triangleSplitDir;
+    const uint8_t candIdx0 = cu.firstPU->triangleMergeIdx0;
+    const uint8_t candIdx1 = cu.firstPU->triangleMergeIdx1;
+#else
     const uint8_t mergeIdx = cu.firstPU->mergeIdx;
     const bool    splitDir = g_triangleCombination[mergeIdx][0];
     const uint8_t candIdx0 = g_triangleCombination[mergeIdx][1];
     const uint8_t candIdx1 = g_triangleCombination[mergeIdx][2];
+#endif
     m_pcInterPred->motionCompensation4Triangle( cu, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#if JVET_M0883_TRIANGLE_SIGNALING
+    PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#else
     PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, mergeIdx, splitDir, candIdx0, candIdx1 );
+#endif
   }
   else
   {
   m_pcIntraPred->geneIntrainterPred(cu);
 
   // inter prediction
+#if JVET_M0483_IBC
+  CHECK(CU::isIBC(cu) && cu.firstPU->mhIntraFlag, "IBC and MHIntra cannot be used together");
+  CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together");
+  CHECK(CU::isIBC(cu) && cu.triangle, "IBC and triangle cannot be used together");
+  CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together");
+#else
   CHECK(cu.ibc && cu.firstPU->mhIntraFlag, "IBC and MHIntra cannot be used together");
   CHECK(cu.ibc && cu.affine, "IBC and Affine cannot be used together");
   CHECK(cu.ibc && cu.triangle, "IBC and triangle cannot be used together");
   CHECK(cu.ibc && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together");
+#endif
   const bool luma = cu.Y().valid();
   const bool chroma = cu.Cb().valid();
   if (luma && chroma)
@@ -384,6 +499,12 @@ void DecCu::xReconInter(CodingUnit &cu)
 
   if (cu.firstPU->mhIntraFlag)
   {
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif
     m_pcIntraPred->geneWeightedPred(COMPONENT_Y, cu.cs->getPredBuf(*cu.firstPU).Y(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Y, 0));
     m_pcIntraPred->geneWeightedPred(COMPONENT_Cb, cu.cs->getPredBuf(*cu.firstPU).Cb(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cb, 0));
     m_pcIntraPred->geneWeightedPred(COMPONENT_Cr, cu.cs->getPredBuf(*cu.firstPU).Cr(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cr, 0));
@@ -391,7 +512,7 @@ void DecCu::xReconInter(CodingUnit &cu)
 
   DTRACE    ( g_trace_ctx, D_TMP, "pred " );
   DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getPredBuf( cu ), &cu.Y() );
-    
+
   // inter recon
   xDecodeInterTexture(cu);
 
@@ -400,18 +521,62 @@ void DecCu::xReconInter(CodingUnit &cu)
 
   if (cu.rootCbf)
   {
+#if JVET_M0427_INLOOP_RESHAPER
+#if REUSE_CU_RESULTS
+    const CompArea &area = cu.blocks[COMPONENT_Y];
+    CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+    PelBuf tmpPred;
+#endif
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+#if REUSE_CU_RESULTS
+      if (cs.pcv->isEncoder)
+      {
+        tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpPred.copyFrom(cs.getPredBuf(cu).get(COMPONENT_Y));
+      }
+#endif
+#if JVET_M0483_IBC
+      if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (!cu.firstPU->mhIntraFlag && !cu.ibc )
+#endif
+        cs.getPredBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif
 #if KEEP_PRED_AND_RESI_SIGNALS
     cs.getRecoBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
 #else
     cs.getResiBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
     cs.getRecoBuf( cu ).copyFrom   (                      cs.getResiBuf( cu ) );
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+#if REUSE_CU_RESULTS
+      if (cs.pcv->isEncoder)
+      {
+        cs.getPredBuf(cu).get(COMPONENT_Y).copyFrom(tmpPred);
+      }
+#endif
+    }
 #endif
   }
   else
   {
     cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs());
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+    {
+      cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif
   }
-  
+
   DTRACE    ( g_trace_ctx, D_TMP, "reco " );
   DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cu ), &cu.Y() );
 
@@ -441,6 +606,13 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+  if ( slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && TU::getCbf(currTU, compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && currTU.blocks[compID].width*currTU.blocks[compID].height > 4 )
+  {
+    resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID));
+  }
+#endif
   if( isChroma( compID ) && currTU.compAlpha[compID] != 0 )
   {
     CrossComponentPrediction::crossComponentPrediction( currTU, compID, cs.getResiBuf( currTU.Y() ), resiBuf, resiBuf, true );
@@ -462,6 +634,27 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu)
 
     for( auto& currTU : CU::traverseTUs( cu ) )
     {
+#if JVET_M0427_INLOOP_RESHAPER
+      CodingStructure  &cs = *cu.cs;
+      const Slice &slice = *cs.slice;
+      if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && slice.getReshapeInfo().getSliceReshapeChromaAdj() && (compID == COMPONENT_Y))
+      {
+        const CompArea &areaY = currTU.blocks[COMPONENT_Y];
+        PelBuf predY = cs.getPredBuf(areaY);
+        CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+        PelBuf tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpPred.copyFrom(predY);
+#if JVET_M0483_IBC
+      if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (!cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+          tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+        const Pel avgLuma = tmpPred.computeAvg();
+        int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+        currTU.setChromaAdj(adj);
+    }
+#endif
       xDecodeInterTU( currTU, compID );
     }
   }
@@ -557,6 +750,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if JVET_M0170_MRG_SHARELIST
           pu.shareParentPos = cu.shareParentPos;
           pu.shareParentSize = cu.shareParentSize;
+#endif
+#if JVET_M0483_IBC
+          if (CU::isIBC(*pu.cu))
+            PU::getIBCMergeCandidates(pu, mrgCtx, pu.mergeIdx);
+          else
 #endif
             PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx);
 #if !JVET_M0068_M0171_MMVD_CLEANUP
@@ -573,7 +771,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
     else
     {
 #if REUSE_CU_RESULTS
+#if JVET_M0246_AFFINE_AMVR
+      if ( cu.imv && !pu.cu->affine && !cu.cs->pcv->isEncoder )
+#else
         if (cu.imv && !cu.cs->pcv->isEncoder)
+#endif
 #else
         if (cu.imv)
 #endif
@@ -598,7 +800,39 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 
               //    Mv mv[3];
               CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
+#if JVET_M0246_AFFINE_AMVR
+#if !JVET_M0055_DEBUG_CTU 
+              Mv tmpMvd[3];
+              memcpy( tmpMvd, pu.mvdAffi[eRefList], 3 * sizeof( Mv ) );
+#endif
+              const int imvShift = ( !cu.cs->pcv->isEncoder && pu.cu->imv == 2 ) ? MV_FRACTIONAL_BITS_DIFF : 0;
+              pu.mvdAffi[eRefList][0] <<= imvShift;
+              pu.mvdAffi[eRefList][1] <<= imvShift;
 
+              Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
+              Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
+              mvRT += pu.mvdAffi[eRefList][0];
+              if ( pu.cu->imv != 1 )
+              {
+                mvLT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
+                mvRT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
+              }
+
+              Mv mvLB;
+              if ( cu.affineType == AFFINEMODEL_6PARAM )
+              {
+                pu.mvdAffi[eRefList][2] <<= imvShift;
+                mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + pu.mvdAffi[eRefList][2];
+                mvLB += pu.mvdAffi[eRefList][0];
+                if ( pu.cu->imv != 1 )
+                {
+                  mvLB.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
+                }
+              }
+#if !JVET_M0055_DEBUG_CTU //th this leads to different interpretation of mvdAffi at encoder and decoder
+              memcpy( pu.mvdAffi[eRefList], tmpMvd, 3 * sizeof( Mv ) );
+#endif 
+#else
               Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
               Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
               mvRT += pu.mvdAffi[eRefList][0];
@@ -612,20 +846,41 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                 mvLB += pu.mvdAffi[eRefList][0];
                 mvLB.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
               }
+#endif
               PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, eRefList );
             }
           }
         }
+#if JVET_M0483_IBC
+        else if (CU::isIBC(*pu.cu) && pu.interDir == 1)
+        {
+          AMVPInfo amvpInfo;
+          PU::fillIBCMvpCand(pu, amvpInfo);
+          pu.mvpNum[REF_PIC_LIST_0] = amvpInfo.numCand;
+          Mv mvd = pu.mvd[REF_PIC_LIST_0];
+#if REUSE_CU_RESULTS
+          if (!cu.cs->pcv->isEncoder)
+#endif
+            mvd <<= 2;
+          pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd;
+          pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+        }
+#endif
         else
         {
           for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
           {
             RefPicList eRefList = RefPicList( uiRefListIdx );
+#if JVET_M0483_IBC
+            if ((pu.cs->slice->getNumRefIdx(eRefList) > 0 || (eRefList == REF_PIC_LIST_0 && CU::isIBC(*pu.cu))) && (pu.interDir & (1 << uiRefListIdx)))
+#else
             if ( pu.cs->slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir & ( 1 << uiRefListIdx ) ) )
+#endif
             {
               AMVPInfo amvpInfo;
               PU::fillMvpCand(pu, eRefList, pu.refIdx[eRefList], amvpInfo);
               pu.mvpNum [eRefList] = amvpInfo.numCand;
+#if JVET_M0483_IBC==0
               Mv mvd = pu.mvd[eRefList];
               if (eRefList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefList, pu.refIdx[eRefList])->getPOC() == pu.cs->slice->getPOC())
               {
@@ -636,6 +891,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                   mvd.changePrecision(MV_PRECISION_INT, MV_PRECISION_QUARTER);
               }
               pu.mv     [eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + mvd;
+#else
+              pu.mv[eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + pu.mvd[eRefList];
+#endif
               pu.mv[eRefList].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
             }
           }
diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h
index 67e5dc4fbc2a15faa777b7c1c34b35042e1d6fa0..40114ce68e6528104ff586e1d387dd5535ff956f 100644
--- a/source/Lib/DecoderLib/DecCu.h
+++ b/source/Lib/DecoderLib/DecCu.h
@@ -48,7 +48,9 @@
 #include "CommonLib/InterPrediction.h"
 #include "CommonLib/IntraPrediction.h"
 #include "CommonLib/Unit.h"
-
+#if JVET_M0427_INLOOP_RESHAPER
+#include "CommonLib/Reshape.h"
+#endif
 //! \ingroup DecoderLib
 //! \{
 
@@ -68,6 +70,12 @@ public:
 
   /// destroy internal buffers
   void  decompressCtu     ( CodingStructure& cs, const UnitArea& ctuArea );
+#if JVET_M0427_INLOOP_RESHAPER
+  Reshape*          m_pcReshape;
+  Reshape* getReshape     () { return m_pcReshape; }
+  void initDecCuReshaper  ( Reshape* pcReshape, ChromaFormat chromaFormatIDC) ;
+  void destoryDecCuReshaprBuf();
+#endif
 
 #if JVET_M0170_MRG_SHARELIST
   void setShareStateDec (int shareStateDecIn)  { m_shareStateDec = shareStateDecIn; }
@@ -87,7 +95,9 @@ protected:
   void xDecodeInterTU     ( TransformUnit&   tu, const ComponentID compID );
 
   void xDeriveCUMV        ( CodingUnit&      cu );
-
+#if JVET_M0427_INLOOP_RESHAPER
+  PelStorage        *m_tmpStorageLCU;
+#endif
 private:
   TrQuant*          m_pcTrQuant;
   IntraPrediction*  m_pcIntraPred;
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 09b493dd5c22f0168a000b5768cd947043a1d35d..6190cfb5b474d53e4570dcd60527186eca241b33 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -56,7 +56,11 @@
 #include "CommonLib/CodingStatistics.h"
 #endif
 
+#if JVET_M0055_DEBUG_CTU
+bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound /* = false */, int debugCTU /* = -1*/, int debugPOC /* = -1*/ )
+#else
 bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound /* = false */ )
+#endif
 {
   int      poc;
   PicList* pcListPic = NULL;
@@ -91,6 +95,10 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 #endif
       );
 
+#if JVET_M0055_DEBUG_CTU
+      pcDecLib->setDebugCTU( debugCTU );
+      pcDecLib->setDebugPOC( debugPOC );
+#endif
       pcDecLib->setDecodedPictureHashSEIEnabled( true );
 
       bFirstCall = false;
@@ -156,6 +164,10 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 
                 CHECK( expectedPoc != poc, "mismatch in POC - check encoder configuration" );
 
+#if JVET_M0055_DEBUG_CTU
+                if( debugCTU < 0 || poc != debugPOC )
+                {
+#endif
                 for( int i = 0; i < pic->slices.size(); i++ )
                 {
                   if( pcEncPic->slices.size() <= i )
@@ -165,9 +177,33 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
                   }
                   pcEncPic->slices[i]->copySliceInfo( pic->slices[i], false );
                 }
+#if JVET_M0055_DEBUG_CTU
+                }
+#endif
 
                 pcEncPic->cs->slice = pcEncPic->slices.back();
 
+#if JVET_M0055_DEBUG_CTU
+                if( debugCTU >= 0 && poc == debugPOC )
+                {
+                  pcEncPic->cs->initStructData();
+
+                  pcEncPic->cs->copyStructure( *pic->cs, CH_L, true, true );
+
+                  if( CS::isDualITree( *pcEncPic->cs ) )
+                  {
+                    pcEncPic->cs->copyStructure( *pic->cs, CH_C, true, true );
+                  }
+
+                  for( auto &cu : pcEncPic->cs->cus )
+                  {
+                    cu->slice = pcEncPic->cs->slice;
+                  }
+                  pcEncPic->cs->slice->copyMotionLUTs( pic->slices.back()->getMotionLUTs(), pcEncPic->slices.back()->getMotionLUTs());
+                }
+                else
+                {
+#endif
                 if ( pic->cs->sps->getSAOEnabledFlag() )
                 {
                   pcEncPic->copySAO( *pic, 0 );
@@ -198,6 +234,9 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
                 {
                   pcEncPic->cs->copyStructure( *pic->cs, CH_C, true, true );
                 }
+#if JVET_M0055_DEBUG_CTU
+                }
+#endif
                 goOn = false; // exit the loop return
                 bRet = true;
                 break;
@@ -353,6 +392,9 @@ DecLib::DecLib()
   , m_cSAO()
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
   , m_cacheModel()
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_cReshaper()
 #endif
   , m_pcPic(NULL)
   , m_prevPOC(MAX_INT)
@@ -370,6 +412,10 @@ DecLib::DecLib()
   , m_numberOfChecksumErrorsDetected(0)
   , m_warningMessageSkipPicture(false)
   , m_prefixSEINALUs()
+#if JVET_M0055_DEBUG_CTU
+  , m_debugPOC( -1 )
+  , m_debugCTU( -1 )
+#endif
 {
 #if ENABLE_SIMD_OPT_BUFFER
   g_pelBufOP.initPelBufOpsX86();
@@ -401,7 +447,7 @@ void DecLib::destroy()
 
 void DecLib::init(
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
-  const std::string& cacheCfgFileName 
+  const std::string& cacheCfgFileName
 #endif
 )
 {
@@ -434,6 +480,10 @@ void DecLib::deletePicBuffer ( )
   m_cacheModel.reportSequence( );
   m_cacheModel.destroy( );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cCuDecoder.destoryDecCuReshaprBuf();
+  m_cReshaper.destroy();
+#endif
 }
 
 Picture* DecLib::xGetNewPicBuffer ( const SPS &sps, const PPS &pps, const uint32_t temporalLayer )
@@ -508,9 +558,19 @@ void DecLib::executeLoopFilters()
 
   CodingStructure& cs = *m_pcPic->cs;
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (cs.sps->getUseReshaper() && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+  {
+      CHECK((m_cReshaper.getRecReshaped() == false), "Rec picture is not reshaped!");
+      m_pcPic->getRecoBuf(COMPONENT_Y).rspSignal(m_cReshaper.getInvLUT());
+      m_cReshaper.setRecReshaped(false);
+  }
+#endif
   // deblocking filter
   m_cLoopFilter.loopFilterPic( cs );
-
+#if JVET_M0147_DMVR
+  CS::setRefinedMotionField(cs);
+#endif
   if( cs.sps->getSAOEnabledFlag() )
   {
     m_cSAO.SAOProcess( cs, cs.picture->getSAO() );
@@ -738,7 +798,12 @@ void DecLib::xActivateParameterSets()
     m_cLoopFilter.create( sps->getMaxCodingDepth() );
     m_cIntraPred.init( sps->getChromaFormatIdc(), sps->getBitDepth( CHANNEL_TYPE_LUMA ) );
     m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc() );
-
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      m_cReshaper.createDec(sps->getBitDepth(CHANNEL_TYPE_LUMA));
+    }
+#endif
 
     bool isField = false;
     bool isTopField = false;
@@ -765,6 +830,12 @@ void DecLib::xActivateParameterSets()
 
     // Recursive structure
     m_cCuDecoder.init( &m_cTrQuant, &m_cIntraPred, &m_cInterPred );
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      m_cCuDecoder.initDecCuReshaper(&m_cReshaper, sps->getChromaFormatIdc());
+    }
+#endif
     m_cTrQuant.init( nullptr, sps->getMaxTrSize(), false, false, false, false, false );
 
     // RdCost
@@ -1228,20 +1299,71 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   }
 #endif
 
-  if (pcSlice->getSPS()->getSpsNext().getIBCMode() && pcSlice->getEnableTMVPFlag())
+#if JVET_M0483_IBC
+  if (pcSlice->getSPS()->getIBCFlag() && pcSlice->getEnableTMVPFlag())
+#else
+  if (pcSlice->getSPS()->getIBCMode() && pcSlice->getEnableTMVPFlag())
+#endif
   {
     CHECK(pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx())->getPOC() == pcSlice->getPOC(), "curr ref picture cannot be collocated picture");
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (pcSlice->getSPS()->getUseReshaper())
+  {
+    m_cReshaper.copySliceReshaperInfo(m_cReshaper.getSliceReshaperInfo(), pcSlice->getReshapeInfo());
+    if (pcSlice->getReshapeInfo().getSliceReshapeModelPresentFlag())
+    {
+      m_cReshaper.constructReshaper();
+    }
+    else
+    {
+      m_cReshaper.setReshapeFlag(false);
+    }
+#if JVET_M0483_IBC
+    if ((pcSlice->getSliceType() == I_SLICE) && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+#else
+    if ((pcSlice->getSliceType() == I_SLICE || (pcSlice->getSliceType() == P_SLICE && pcSlice->getSPS()->getIBCMode())) && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+#endif
+    {
+      m_cReshaper.setCTUFlag(false);
+      m_cReshaper.setRecReshaped(true);
+    }
+    else
+    {
+      if (m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+      {
+        m_cReshaper.setCTUFlag(true);
+        m_cReshaper.setRecReshaped(true);
+      }
+      else
+      {
+        m_cReshaper.setCTUFlag(false);
+        m_cReshaper.setRecReshaped(false);
+      }
+    }
+  }
+  else
+  {
+    m_cReshaper.setCTUFlag(false);
+    m_cReshaper.setRecReshaped(false);
+  }
+#endif
 
   //  Decode a picture
+#if JVET_M0055_DEBUG_CTU
+  m_cSliceDecoder.decompressSlice( pcSlice, &( nalu.getBitstream() ), ( m_pcPic->poc == getDebugPOC() ? getDebugCTU() : -1 ) );
+#else
   m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) );
+#endif
 
   m_bFirstSliceInPicture = false;
-  if (pcSlice->getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+  if (pcSlice->getSPS()->getIBCMode())
   {
     pcSlice->getPic()->longTerm = false;
   }
+#endif
   m_uiSliceSegmentIdx++;
 
   return false;
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index 687ea822a8f759b03c5cea533c8f7ca244fcb608..ae94530450e6a9402275be64a23afaf6454dd2ba 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -53,14 +53,20 @@
 #include "CommonLib/AdaptiveLoopFilter.h"
 #include "CommonLib/SEI.h"
 #include "CommonLib/Unit.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "CommonLib/Reshape.h"
+#endif
 
 class InputNALUnit;
 
 //! \ingroup DecoderLib
 //! \{
 
-bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false );
-// ====================================================================================================================
+#if JVET_M0055_DEBUG_CTU
+bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false, int debugCTU = -1, int debugPOC = -1 );
+#else
+ bool tryDecodePicture( Picture* pcPic, const int expectedPoc, const std::string& bitstreamFileName, bool bDecodeUntilPocFound = false );
+#endif// ====================================================================================================================
 // Class definition
 // ====================================================================================================================
 
@@ -94,6 +100,9 @@ private:
   LoopFilter              m_cLoopFilter;
   SampleAdaptiveOffset    m_cSAO;
   AdaptiveLoopFilter      m_cALF;
+#if JVET_M0427_INLOOP_RESHAPER
+  Reshape                 m_cReshaper;                        ///< reshaper class
+#endif
   // decoder side RD cost computation
   RdCost                  m_cRdCost;                      ///< RD cost computation class
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
@@ -122,6 +131,10 @@ private:
   bool                    m_warningMessageSkipPicture;
 
   std::list<InputNALUnit*> m_prefixSEINALUs; /// Buffered up prefix SEI NAL Units.
+#if JVET_M0055_DEBUG_CTU
+  int                     m_debugPOC;
+  int                     m_debugCTU;
+#endif
 public:
   DecLib();
   virtual ~DecLib();
@@ -152,6 +165,12 @@ public:
   void  setDecodedSEIMessageOutputStream(std::ostream *pOpStream) { m_pDecodedSEIOutputStream = pOpStream; }
   uint32_t  getNumberOfChecksumErrorsDetected() const { return m_numberOfChecksumErrorsDetected; }
 
+#if JVET_M0055_DEBUG_CTU
+  int  getDebugCTU( )               const { return m_debugCTU; }
+  void setDebugCTU( int debugCTU )        { m_debugCTU = debugCTU; }
+  int  getDebugPOC( )               const { return m_debugPOC; };
+  void setDebugPOC( int debugPOC )        { m_debugPOC = debugPOC; };
+#endif
 protected:
   void  xUpdateRasInit(Slice* slice);
 
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index 9f53af255e94362f985c8613ff890863acd4ae89..13be91a5c29412727f28774ed1a5f21893f29a8c 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -70,7 +70,11 @@ void DecSlice::init( CABACDecoder* cabacDecoder, DecCu* pcCuDecoder )
   m_pcCuDecoder     = pcCuDecoder;
 }
 
+#if JVET_M0055_DEBUG_CTU 
+void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int debugCTU )
+#else
 void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream )
+#endif
 {
   //-- For time output for each slice
   slice->startProcessingTimer();
@@ -231,6 +235,14 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream )
       cs.slice->resetMotionLUTs();
     }
 
+#if JVET_M0055_DEBUG_CTU 
+ 
+    if( ctuRsAddr == debugCTU )
+    {
+      isLastCtuOfSliceSegment = true; // get out here
+      break;
+    }
+#endif
     isLastCtuOfSliceSegment = cabacReader.coding_tree_unit( cs, ctuArea, pic->m_prevQP, ctuRsAddr );
 
     m_pcCuDecoder->decompressCtu( cs, ctuArea );
diff --git a/source/Lib/DecoderLib/DecSlice.h b/source/Lib/DecoderLib/DecSlice.h
index 10304cf0e0084c3a9885e85ea9c93856f806f65e..f4a14e5b7dc24b67b2b593106665f8de6056f851 100644
--- a/source/Lib/DecoderLib/DecSlice.h
+++ b/source/Lib/DecoderLib/DecSlice.h
@@ -77,7 +77,11 @@ public:
   void  create            ();
   void  destroy           ();
 
+#if JVET_M0055_DEBUG_CTU
+  void  decompressSlice   ( Slice* slice, InputBitstream* bitstream, int debugCTU );
+#else
   void  decompressSlice   ( Slice* slice, InputBitstream* bitstream );
+#endif
 };
 
 //! \}
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 8e1725797c1a84d4eb0812d62a0b0356e20d60f7..2f740018f318cc38bd8a342a0df276952a2b4269 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -782,89 +782,62 @@ void HLSyntaxReader::parseHrdParameters(HRD *hrd, bool commonInfPresentFlag, uin
   }
 }
 
-
-void HLSyntaxReader::parseSPSNext( SPSNext& spsNext, const bool usePCM )
+#if JVET_M0427_INLOOP_RESHAPER
+void HLSyntaxReader::parseReshaper(SliceReshapeInfo& info, const SPS* pcSPS, const bool isIntra)
 {
   unsigned  symbol = 0;
-
-  // tool enabling flags
-  READ_FLAG( symbol,    "large_ctu_flag" );                         spsNext.setUseLargeCTU            ( symbol != 0 );
-  READ_FLAG( symbol,    "imv_enable_flag" );                        spsNext.setUseIMV                 ( symbol != 0 );
-  READ_FLAG( symbol,    "disable_motion_compression_flag" );        spsNext.setDisableMotCompress     ( symbol != 0 );
-  READ_FLAG( symbol,    "lm_chroma_enabled_flag" );                 spsNext.setUseLMChroma            ( symbol != 0 );
-#if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  if ( spsNext.getUseLMChroma() && spsNext.getSPS().getChromaFormatIdc() == CHROMA_420 )
-  {
-    READ_FLAG( symbol,  "sps_cclm_collocated_chroma_flag" );        spsNext.setCclmCollocatedChromaFlag( symbol != 0 );
-  }
-#endif
-#if JVET_M0464_UNI_MTS
-  READ_FLAG( symbol,    "mts_intra_enabled_flag" );                 spsNext.setUseIntraMTS            ( symbol != 0 );
-  READ_FLAG( symbol,    "mts_inter_enabled_flag" );                 spsNext.setUseInterMTS            ( symbol != 0 );
-#else
-  READ_FLAG( symbol,    "emt_intra_enabled_flag" );                 spsNext.setUseIntraEMT            ( symbol != 0 );
-  READ_FLAG( symbol,    "emt_inter_enabled_flag" );                 spsNext.setUseInterEMT            ( symbol != 0 );
-#endif
-  READ_FLAG( symbol,    "affine_flag" );                            spsNext.setUseAffine              ( symbol != 0 );
-  if ( spsNext.getUseAffine() )
-  {
-    READ_FLAG( symbol,  "affine_type_flag" );                       spsNext.setUseAffineType          ( symbol != 0 );
-  }
-  READ_FLAG( symbol,    "gbi_flag" );                               spsNext.setUseGBi                 ( symbol != 0 );
-  READ_FLAG( symbol, "ibc_flag");                                   spsNext.setIBCMode                ( symbol != 0 );
-  for( int k = 0; k < SPSNext::NumReservedFlags; k++ )
-  {
-    READ_FLAG( symbol,  "reserved_flag" );                          if( symbol != 0 ) EXIT("Incompatible version: SPSNext reserved flag not equal to zero (bitstream was probably created with newer software version)" );
-  }
-  READ_FLAG( symbol,  "mtt_enabled_flag" );                       spsNext.setMTTMode                ( symbol );
-  READ_FLAG( symbol,  "mhintra_flag" );                           spsNext.setUseMHIntra             ( symbol != 0 );
-  READ_FLAG( symbol,    "triangle_flag" );                          spsNext.setUseTriangle            ( symbol != 0 );
-#if ENABLE_WPP_PARALLELISM
-  READ_FLAG( symbol,  "next_dqp_enabled_flag" );                  spsNext.setUseNextDQP             ( symbol != 0 );
-#else
-  READ_FLAG( symbol,  "reserved_flag" );                          CHECK( symbol, "reserved flag not 0!" );
-#endif
-
-  if( spsNext.getUseIMV() )
-  {
-    READ_UVLC( symbol, "imv_mode_minus1" );                         spsNext.setImvMode( ImvMode( symbol + 1 ) );
-  }
-  if( spsNext.getMTTEnabled() )
-  {
-    READ_UVLC( symbol,  "mtt_mode_minus1" );                        spsNext.setMTTMode( symbol + 1 );
+  READ_FLAG(symbol, "tile_group_reshaper_model_present_flag");                 info.setSliceReshapeModelPresentFlag(symbol == 1);
+  if (info.getSliceReshapeModelPresentFlag())
+  {
+    memset(info.reshaperModelBinCWDelta, 0, PIC_CODE_CW_BINS * sizeof(int));
+    READ_UVLC(symbol, "reshaper_model_min_bin_idx");                             info.reshaperModelMinBinIdx = symbol;
+    READ_UVLC(symbol, "reshaper_model_delta_max_bin_idx");                       info.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1 - symbol;
+    READ_UVLC(symbol, "reshaper_model_bin_delta_abs_cw_prec_minus1");            info.maxNbitsNeededDeltaCW = symbol + 1;
+    assert(info.maxNbitsNeededDeltaCW > 0);
+    for (uint32_t i = info.reshaperModelMinBinIdx; i <= info.reshaperModelMaxBinIdx; i++)
+    {
+      READ_CODE(info.maxNbitsNeededDeltaCW, symbol, "reshaper_model_bin_delta_abs_CW");
+      int absCW = symbol;
+      if (absCW > 0)
+      {
+        READ_CODE(1, symbol, "reshaper_model_bin_delta_sign_CW_flag");
+      }
+      int signCW = symbol;
+      info.reshaperModelBinCWDelta[i] = (1 - 2 * signCW) * absCW;
+    }
   }
-
-
-#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  READ_FLAG( symbol, "sps_ladf_enabled_flag" );                     spsNext.setLadfEnabled( symbol != 0 );
-  if ( spsNext.getLadfEnabled() )
+  READ_FLAG(symbol, "tile_group_reshaper_enable_flag");           info.setUseSliceReshaper(symbol == 1);
+  if (info.getUseSliceReshaper())
   {
-    int signedSymbol = 0;
-    READ_CODE( 2, symbol, "sps_num_ladf_intervals_minus2");         spsNext.setLadfNumIntervals( symbol + 2 );
-    READ_SVLC(signedSymbol, "sps_ladf_lowest_interval_qp_offset" );      spsNext.setLadfQpOffset( signedSymbol, 0 );
-    for ( int k = 1; k < spsNext.getLadfNumIntervals(); k++ )
+    if (!(pcSPS->getUseDualITree() && isIntra))
+    {
+      READ_FLAG(symbol, "slice_reshaper_ChromaAdj");                info.setSliceReshapeChromaAdj(symbol);
+    }
+    else
     {
-      READ_SVLC(signedSymbol, "sps_ladf_qp_offset" );                    spsNext.setLadfQpOffset( signedSymbol, k );
-      READ_UVLC( symbol, "sps_ladf_delta_threshold_minus1");
-      spsNext.setLadfIntervalLowerBound(symbol + spsNext.getLadfIntervalLowerBound(k - 1) + 1, k);
+      info.setSliceReshapeChromaAdj(0);
     }
   }
-#endif
-  // ADD_NEW_TOOL : (sps extension parser) read tool enabling flags and associated parameters here
 }
-
+#endif
 void HLSyntaxReader::parseSPS(SPS* pcSPS)
 {
+  uint32_t  uiCode;
+
 #if ENABLE_TRACING
   xTraceSPSHeader ();
 #endif
+#if HEVC_VPS
+  READ_CODE( 4,  uiCode, "sps_video_parameter_set_id");          pcSPS->setVPSId        ( uiCode );
+#endif
+  READ_UVLC(     uiCode, "sps_seq_parameter_set_id" );           pcSPS->setSPSId( uiCode );
+  CHECK(uiCode > 15, "Invalid SPS id signalled");
 
-  uint32_t  uiCode;
   READ_FLAG(uiCode, "intra_only_constraint_flag");               pcSPS->setIntraOnlyConstraintFlag(uiCode > 0 ? true : false);
   READ_CODE(4, uiCode, "max_bitdepth_constraint_idc");           pcSPS->setMaxBitDepthConstraintIdc(uiCode);
   READ_CODE(2, uiCode, "max_chroma_format_constraint_idc");      pcSPS->setMaxChromaFormatConstraintIdc(uiCode);
-  READ_FLAG(uiCode, "frame_constraint_flag");                    pcSPS->setFrameConstraintFlag(uiCode > 0 ? true : false);
-  READ_FLAG(uiCode, "no_qtbtt_dual_tree_intra constraint_flag"); pcSPS->setNoQtbttDualTreeIntraConstraintFlag(uiCode > 0 ? true : false);
+  READ_FLAG(uiCode, "frame_only_constraint_flag");               pcSPS->setFrameConstraintFlag(uiCode > 0 ? true : false);
+  READ_FLAG(uiCode, "no_qtbtt_dual_tree_intra_constraint_flag"); pcSPS->setNoQtbttDualTreeIntraConstraintFlag(uiCode > 0 ? true : false);
   READ_FLAG(uiCode, "no_cclm_constraint_flag");                  pcSPS->setNoCclmConstraintFlag(uiCode > 0 ? true : false);
   READ_FLAG(uiCode, "no_sao_constraint_flag");                   pcSPS->setNoSaoConstraintFlag(uiCode > 0 ? true : false);
   READ_FLAG(uiCode, "no_alf_constraint_flag");                   pcSPS->setNoAlfConstraintFlag(uiCode > 0 ? true : false);
@@ -877,25 +850,22 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_FLAG(uiCode, "no_ladf_constraint_flag");                  pcSPS->setNoLadfConstraintFlag(uiCode > 0 ? true : false);
   READ_FLAG(uiCode, "no_dep_quant_constraint_flag");             pcSPS->setNoDepQuantConstraintFlag(uiCode > 0 ? true : false);
   READ_FLAG(uiCode, "no_sign_data_hiding_constraint_flag");      pcSPS->setNoSignDataHidingConstraintFlag(uiCode > 0 ? true : false);
-#if HEVC_VPS
-  READ_CODE( 4,  uiCode, "sps_video_parameter_set_id");          pcSPS->setVPSId        ( uiCode );
-#endif
+
+  // KJS: Marakech decision: sub-layers added back
   READ_CODE( 3,  uiCode, "sps_max_sub_layers_minus1" );          pcSPS->setMaxTLayers   ( uiCode+1 );
   CHECK(uiCode > 6, "Invalid maximum number of T-layer signalled");
-
   READ_FLAG( uiCode, "sps_temporal_id_nesting_flag" );           pcSPS->setTemporalIdNestingFlag ( uiCode > 0 ? true : false );
   if ( pcSPS->getMaxTLayers() == 1 )
   {
     // sps_temporal_id_nesting_flag must be 1 when sps_max_sub_layers_minus1 is 0
     CHECK( uiCode != 1, "Invalid maximum number of T-layers" );
   }
-
   parsePTL(pcSPS->getPTL(), 1, pcSPS->getMaxTLayers() - 1);
-  READ_UVLC(     uiCode, "sps_seq_parameter_set_id" );           pcSPS->setSPSId( uiCode );
-  CHECK(uiCode > 15, "Invalid SPS id signalled");
 
   READ_UVLC(     uiCode, "chroma_format_idc" );                  pcSPS->setChromaFormatIdc( ChromaFormat(uiCode) );
   CHECK(uiCode > 3, "Invalid chroma format signalled");
+
+  // KJS: ENABLE_CHROMA_422 does not exist anymore o.O
   if( pcSPS->getChromaFormatIdc() == CHROMA_422 )
   {
     EXIT( "Error:  4:2:2 chroma sampling format not supported with current compiler setting."
@@ -909,6 +879,8 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 
   READ_UVLC (    uiCode, "pic_width_in_luma_samples" );          pcSPS->setPicWidthInLumaSamples ( uiCode    );
   READ_UVLC (    uiCode, "pic_height_in_luma_samples" );         pcSPS->setPicHeightInLumaSamples( uiCode    );
+
+  // KJS: not removing yet
   READ_FLAG(     uiCode, "conformance_window_flag");
   if (uiCode != 0)
   {
@@ -933,6 +905,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_UVLC( uiCode,    "log2_max_pic_order_cnt_lsb_minus4" );   pcSPS->setBitsForPOC( 4 + uiCode );
   CHECK(uiCode > 12, "Invalid code");
 
+  // KJS: Marakech decision: sub-layers added back
   uint32_t subLayerOrderingInfoPresentFlag;
   READ_FLAG(subLayerOrderingInfoPresentFlag, "sps_sub_layer_ordering_info_present_flag");
 
@@ -962,8 +935,8 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 
   unsigned  maxBTSize[3] = { 0, 0, 0 };
   unsigned  maxTTSize[3] = { 0, 0, 0 };
-  READ_FLAG(uiCode, "qtbt_dual_intra_tree");                   pcSPS->setUseDualITree(uiCode);
-  READ_UVLC(uiCode, "log2_CTU_size_minus2");                   pcSPS->setCTUSize(1 << (uiCode + 2));
+  READ_FLAG(uiCode, "qtbtt_dual_tree_intra_flag");             pcSPS->setUseDualITree(uiCode);
+  READ_UVLC(uiCode, "log2_ctu_size_minus2");                   pcSPS->setCTUSize(1 << (uiCode + 2));
   pcSPS->setMaxCodingDepth(uiCode);
   pcSPS->setLog2DiffMaxMinCodingBlockSize(uiCode);
   pcSPS->setMaxCUWidth(pcSPS->getCTUSize());
@@ -972,33 +945,33 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_UVLC(uiCode, "log2_min_luma_coding_block_size_minus2");
   int log2MinCUSize = uiCode + 2;
   pcSPS->setLog2MinCodingBlockSize(log2MinCUSize);
-  READ_FLAG(uiCode, "sps_override_partition_constraints_enable_flag"); pcSPS->setSplitConsOverrideEnabledFlag(uiCode);
-  READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_intra_slice");      minQT[0] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
-  READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_inter_slice");      minQT[1] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
-  READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_inter_slices");     maxBTD[1] = uiCode;
-  READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_intra_slices");     maxBTD[0] = uiCode;
+  READ_FLAG(uiCode, "partition_constraints_override_enabled_flag"); pcSPS->setSplitConsOverrideEnabledFlag(uiCode);
+  READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_intra_tile_group_luma");      minQT[0] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
+  READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_inter_tile_group");      minQT[1] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
+  READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_inter_tile_group");     maxBTD[1] = uiCode;
+  READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_intra_tile_group_luma");     maxBTD[0] = uiCode;
 
   maxTTSize[0] = maxBTSize[0] = minQT[0];
   if (maxBTD[0] != 0)
   {
-    READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_intra_slice");     maxBTSize[0] <<= uiCode;
-    READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_intra_slice");     maxTTSize[0] <<= uiCode;
+    READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_intra_tile_group_luma");     maxBTSize[0] <<= uiCode;
+    READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_intra_tile_group_luma");     maxTTSize[0] <<= uiCode;
   }
   maxTTSize[1] = maxBTSize[1] = minQT[1];
   if (maxBTD[1] != 0)
   {
-    READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_inter_slice");     maxBTSize[1] <<= uiCode;
-    READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_inter_slice");     maxTTSize[1] <<= uiCode;
+    READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_inter_tile_group");     maxBTSize[1] <<= uiCode;
+    READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_inter_tile_group");     maxTTSize[1] <<= uiCode;
   }
   if (pcSPS->getUseDualITree())
   {
-    READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_intra_slice_chroma"); minQT[2] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
-    READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_intra_slices_chroma"); maxBTD[2] = uiCode;
+    READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_intra_tile_group_chroma"); minQT[2] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize());
+    READ_UVLC(uiCode, "sps_max_mtt_hierarchy_depth_intra_tile_group_chroma"); maxBTD[2] = uiCode;
     maxTTSize[2] = maxBTSize[2] = minQT[2];
     if (maxBTD[2] != 0)
     {
-      READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_intra_slice_chroma");       maxBTSize[2] <<= uiCode;
-      READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_intra_slice_chroma");       maxTTSize[2] <<= uiCode;
+      READ_UVLC(uiCode, "sps_log2_diff_max_bt_min_qt_intra_tile_group_chroma");       maxBTSize[2] <<= uiCode;
+      READ_UVLC(uiCode, "sps_log2_diff_max_tt_min_qt_intra_tile_group_chroma");       maxTTSize[2] <<= uiCode;
     }
 }
 
@@ -1011,15 +984,16 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   {
     CHECK(log2MinCUSize + pcSPS->getLog2DiffMaxMinCodingBlockSize() < 5, "Invalid code");
   }
-  READ_UVLC( uiCode, "log2_min_luma_transform_block_size_minus2" );   pcSPS->setQuadtreeTULog2MinSize( uiCode + 2 );
 
+  // KJS: does not exist anymore -> remove!
+  READ_UVLC( uiCode, "log2_min_luma_transform_block_size_minus2" );   pcSPS->setQuadtreeTULog2MinSize( uiCode + 2 );
   READ_UVLC( uiCode, "log2_diff_max_min_luma_transform_block_size" ); pcSPS->setQuadtreeTULog2MaxSize( uiCode + pcSPS->getQuadtreeTULog2MinSize() );
   pcSPS->setMaxTrSize( 1<<(uiCode + pcSPS->getQuadtreeTULog2MinSize()) );
 
   READ_FLAG( uiCode, "sps_sao_enabled_flag" );                      pcSPS->setSAOEnabledFlag ( uiCode ? true : false );
   READ_FLAG( uiCode, "sps_alf_enabled_flag" );                      pcSPS->setALFEnabledFlag ( uiCode ? true : false );
 
-  READ_FLAG( uiCode, "pcm_enabled_flag" );                          pcSPS->setPCMEnabledFlag( uiCode ? true : false );
+  READ_FLAG( uiCode, "sps_pcm_enabled_flag" );                          pcSPS->setPCMEnabledFlag( uiCode ? true : false );
   if( pcSPS->getPCMEnabledFlag() )
   {
     READ_CODE( 4, uiCode, "pcm_sample_bit_depth_luma_minus1" );          pcSPS->setPCMBitDepth    ( CHANNEL_TYPE_LUMA, 1 + uiCode );
@@ -1036,7 +1010,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   }
 
   READ_FLAG( uiCode, "sps_temporal_mvp_enabled_flag" );                  pcSPS->setSPSTemporalMVPEnabledFlag(uiCode);
-  
+
   if ( pcSPS->getSPSTemporalMVPEnabledFlag() )
   {
     READ_FLAG( uiCode,    "sps_sbtmvp_enabled_flag" );                   pcSPS->setSBTMVPEnabledFlag      ( uiCode != 0 );
@@ -1046,20 +1020,93 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
     pcSPS->setSBTMVPEnabledFlag(false);
   }
 
-  READ_FLAG( uiCode, "sps_bdof_enable_flag" );                      pcSPS->setBDOFEnabledFlag ( uiCode != 0 );
+  READ_FLAG( uiCode,  "sps_amvr_enabled_flag" );                     pcSPS->setAMVREnabledFlag ( uiCode != 0 );
+
+  READ_FLAG( uiCode, "sps_bdof_enabled_flag" );                      pcSPS->setBDOFEnabledFlag ( uiCode != 0 );
+
+#if JVET_M0246_AFFINE_AMVR
+  READ_FLAG( uiCode,  "sps_affine_amvr_enabled_flag" );             pcSPS->setAffineAmvrEnabledFlag ( uiCode != 0 );
+#endif
+
+#if JVET_M0147_DMVR
+  READ_FLAG(uiCode, "sps_dmvr_enable_flag");                        pcSPS->setUseDMVR(uiCode != 0);
+#endif
+
+  // KJS: sps_cclm_enabled_flag
+  READ_FLAG( uiCode,    "lm_chroma_enabled_flag" );                 pcSPS->setUseLMChroma            ( uiCode != 0 );
+#if JVET_M0142_CCLM_COLLOCATED_CHROMA
+  if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 )
+  {
+    READ_FLAG( uiCode,  "sps_cclm_collocated_chroma_flag" );        pcSPS->setCclmCollocatedChromaFlag( uiCode != 0 );
+  }
+#endif
+
+#if JVET_M0303_IMPLICIT_MTS
+  READ_FLAG( uiCode,    "mts_enabled_flag" );                       pcSPS->setUseMTS                 ( uiCode != 0 );
+  if ( pcSPS->getUseMTS() )
+  {
+#endif
+#if JVET_M0464_UNI_MTS
+    READ_FLAG( uiCode,    "mts_intra_enabled_flag" );               pcSPS->setUseIntraMTS            ( uiCode != 0 );
+    READ_FLAG( uiCode,    "mts_inter_enabled_flag" );               pcSPS->setUseInterMTS            ( uiCode != 0 );
+#else
+    READ_FLAG( uiCode,    "emt_intra_enabled_flag" );               pcSPS->setUseIntraEMT            ( uiCode != 0 );
+    READ_FLAG( uiCode,    "emt_inter_enabled_flag" );               pcSPS->setUseInterEMT            ( uiCode != 0 );
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  }
+#endif
+  // KJS: sps_affine_enabled_flag
+  READ_FLAG( uiCode,    "affine_flag" );                            pcSPS->setUseAffine              ( uiCode != 0 );
+  if ( pcSPS->getUseAffine() )
+  {
+    READ_FLAG( uiCode,  "affine_type_flag" );                       pcSPS->setUseAffineType          ( uiCode != 0 );
+  }
+  READ_FLAG( uiCode,    "gbi_flag" );                               pcSPS->setUseGBi                 ( uiCode != 0 );
+#if JVET_M0483_IBC
+  READ_FLAG(uiCode, "ibc_flag");                                    pcSPS->setIBCFlag(uiCode);
+#else
+  READ_FLAG( uiCode, "ibc_flag");                                   pcSPS->setIBCMode                ( uiCode != 0 );
+#endif
+  // KJS: sps_ciip_enabled_flag
+  READ_FLAG( uiCode,     "mhintra_flag" );                           pcSPS->setUseMHIntra             ( uiCode != 0 );
+
+  READ_FLAG( uiCode,    "triangle_flag" );                          pcSPS->setUseTriangle            ( uiCode != 0 );
+
+  // KJS: not in draft yet
+#if JVET_M0255_FRACMMVD_SWITCH
+  READ_FLAG( uiCode,  "sps_fracmmvd_disabled_flag" );               pcSPS->setDisFracMmvdEnabledFlag ( uiCode != 0 );
+#endif
+  // KJS: not in draft yet
+#if JVET_M0140_SBT
+  READ_FLAG(uiCode, "sbt_enable_flag");                             pcSPS->setUseSBT(uiCode != 0);
+  if( pcSPS->getUseSBT() )
+  {
+    READ_FLAG(uiCode, "max_sbt_size_64_flag");                      pcSPS->setMaxSbtSize(uiCode != 0 ? 64 : 32);
+  }
+#endif
+  // KJS: not in draft yet
+#if JVET_M0427_INLOOP_RESHAPER
+  READ_FLAG(uiCode, "sps_reshaper_enable_flag");                   pcSPS->setUseReshaper(uiCode == 1);
+#endif
   
-#if HEVC_USE_SCALING_LISTS
-  READ_FLAG( uiCode, "scaling_list_enabled_flag" );                 pcSPS->setScalingListFlag ( uiCode );
-  if(pcSPS->getScalingListFlag())
+#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
+  READ_FLAG( uiCode, "sps_ladf_enabled_flag" );                     pcSPS->setLadfEnabled( uiCode != 0 );
+  if ( pcSPS->getLadfEnabled() )
   {
-    READ_FLAG( uiCode, "sps_scaling_list_data_present_flag" );                 pcSPS->setScalingListPresentFlag ( uiCode );
-    if(pcSPS->getScalingListPresentFlag ())
+    int signedSymbol = 0;
+    READ_CODE( 2, uiCode, "sps_num_ladf_intervals_minus2");         pcSPS->setLadfNumIntervals( uiCode + 2 );
+    READ_SVLC(signedSymbol, "sps_ladf_lowest_interval_qp_offset" );      pcSPS->setLadfQpOffset( signedSymbol, 0 );
+    for ( int k = 1; k < pcSPS->getLadfNumIntervals(); k++ )
     {
-      parseScalingList( &(pcSPS->getScalingList()) );
+      READ_SVLC(signedSymbol, "sps_ladf_qp_offset" );                    pcSPS->setLadfQpOffset( signedSymbol, k );
+      READ_UVLC( uiCode, "sps_ladf_delta_threshold_minus1");
+      pcSPS->setLadfIntervalLowerBound(uiCode + pcSPS->getLadfIntervalLowerBound(k - 1) + 1, k);
     }
   }
 #endif
-
+ 
+  // KJS: reference picture sets to be replaced
   READ_UVLC( uiCode, "num_short_term_ref_pic_sets" );
   CHECK(uiCode > 64, "Invalid code");
   pcSPS->createRPSList(uiCode);
@@ -1085,10 +1132,26 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       pcSPS->setUsedByCurrPicLtSPSFlag(k, uiCode?1:0);
     }
   }
+
+  // KJS: not found in draft -> does not exist
 #if HEVC_USE_INTRA_SMOOTHING_T32 || HEVC_USE_INTRA_SMOOTHING_T64
   READ_FLAG( uiCode, "strong_intra_smoothing_enable_flag" );      pcSPS->setUseStrongIntraSmoothing(uiCode);
+#endif
 
+  // KJS: remove scaling lists?
+#if HEVC_USE_SCALING_LISTS
+  READ_FLAG( uiCode, "scaling_list_enabled_flag" );                 pcSPS->setScalingListFlag ( uiCode );
+  if(pcSPS->getScalingListFlag())
+  {
+    READ_FLAG( uiCode, "sps_scaling_list_data_present_flag" );                 pcSPS->setScalingListPresentFlag ( uiCode );
+    if(pcSPS->getScalingListPresentFlag ())
+    {
+      parseScalingList( &(pcSPS->getScalingList()) );
+    }
+  }
 #endif
+
+  // KJS: no VUI defined yet
   READ_FLAG( uiCode, "vui_parameters_present_flag" );             pcSPS->setVuiParametersPresentFlag(uiCode);
 
   if (pcSPS->getVuiParametersPresentFlag())
@@ -1096,7 +1159,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
     parseVUI(pcSPS->getVuiParameters(), pcSPS);
   }
 
-
+  // KJS: no SPS extensions defined yet
 
   READ_FLAG( uiCode, "sps_extension_present_flag");
   if (uiCode)
@@ -1119,11 +1182,6 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       sps_extension_flags[i] = uiCode!=0;
     }
 
-    if( pcSPS->getPTL()->getGeneralPTL()->getProfileIdc() == Profile::NEXT )
-    {
-      pcSPS->getSpsNext().setNextToolsEnabled( true );
-    }
-
     bool bSkipTrailingExtensionBits=false;
     for(int i=0; i<NUM_SPS_EXTENSION_FLAGS; i++) // loop used so that the order is determined by the enum.
     {
@@ -1146,12 +1204,6 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
             READ_FLAG( uiCode, "cabac_bypass_alignment_enabled_flag");      spsRangeExtension.setCabacBypassAlignmentEnabledFlag  (uiCode != 0);
           }
           break;
-        case SPS_EXT__NEXT:
-        {
-          CHECK( !pcSPS->getSpsNext().nextToolsEnabled(), "Got SPS Next extension in non NEXT profile" );
-          parseSPSNext( pcSPS->getSpsNext(), pcSPS->getPCMEnabledFlag() );
-          break;
-        }
         default:
           bSkipTrailingExtensionBits=true;
           break;
@@ -1166,7 +1218,6 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       }
     }
   }
-
   xReadRbspTrailingBits();
 }
 
@@ -1748,25 +1799,43 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
         }
       }
     }
+
+#if JVET_M0483_IBC
+    if (!pcSlice->isIntra() || sps->getIBCFlag())
+    {
+      READ_UVLC(uiCode, "six_minus_max_num_merge_cand");
+      pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode);
+    }
+#endif
+
     if (!pcSlice->isIntra())
     {
+#if JVET_M0483_IBC==0
       READ_UVLC(uiCode, "six_minus_max_num_merge_cand");
       pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode);
+#endif
 
-      if ( sps->getSBTMVPEnabledFlag() && !sps->getSpsNext().getUseAffine() ) // ATMVP only
+      if ( sps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // ATMVP only
       {
         pcSlice->setMaxNumAffineMergeCand( 1 );
       }
-      else if ( !sps->getSBTMVPEnabledFlag() && !sps->getSpsNext().getUseAffine() ) // both off
+      else if ( !sps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // both off
       {
         pcSlice->setMaxNumAffineMergeCand( 0 );
       }
       else
-      if ( sps->getSpsNext().getUseAffine() )
+      if ( sps->getUseAffine() )
       {
         READ_UVLC( uiCode, "five_minus_max_num_affine_merge_cand" );
         pcSlice->setMaxNumAffineMergeCand( AFFINE_MRG_MAX_NUM_CANDS - uiCode );
       }
+#if JVET_M0255_FRACMMVD_SWITCH
+      if ( sps->getDisFracMmvdEnabledFlag() )
+      {
+        READ_FLAG( uiCode, "tile_group_fracmmvd_disabled_flag" );
+        pcSlice->setDisFracMMVD( uiCode ? true : false );
+      }
+#endif
     }
 
     READ_SVLC( iCode, "slice_qp_delta" );
@@ -1857,6 +1926,13 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       uiCode = pps->getLoopFilterAcrossSlicesEnabledFlag()?1:0;
     }
     pcSlice->setLFCrossSliceBoundaryFlag( (uiCode==1)?true:false);
+
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      parseReshaper(pcSlice->getReshapeInfo(), sps, pcSlice->isIntra());
+    }
+#endif
 #if HEVC_DEPENDENT_SLICES
   }
 #endif
@@ -2335,7 +2411,7 @@ bool HLSyntaxReader::xMoreRbspData()
 void HLSyntaxReader::alf( AlfSliceParam& alfSliceParam )
 {
   uint32_t code;
-  READ_FLAG( code, "alf_slice_enable_flag" );
+  READ_FLAG( code, "tile_group_alf_enabled_flag" );
   alfSliceParam.enabledFlag[COMPONENT_Y] = code ? true : false;
 
   if( !code )
@@ -2420,33 +2496,33 @@ void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChrom
   uint32_t code;
   if( !isChroma )
   {
-    READ_FLAG( code, "alf_coefficients_delta_flag" );
-    alfSliceParam.coeffDeltaFlag = code;
+    READ_FLAG( code, "alf_luma_coeff_delta_flag" );
+    alfSliceParam.alfLumaCoeffDeltaFlag = code;
 
-    if( !alfSliceParam.coeffDeltaFlag )
+    if( !alfSliceParam.alfLumaCoeffDeltaFlag )
     {
-      std::memset( alfSliceParam.filterCoeffFlag, true, sizeof( alfSliceParam.filterCoeffFlag ) );
+      std::memset( alfSliceParam.alfLumaCoeffFlag, true, sizeof( alfSliceParam.alfLumaCoeffFlag ) );
 
       if( alfSliceParam.numLumaFilters > 1 )
       {
-        READ_FLAG( code, "coeff_delta_pred_mode_flag" );
-        alfSliceParam.coeffDeltaPredModeFlag = code;
+        READ_FLAG( code, "alf_luma_coeff_delta_prediction_flag" );
+        alfSliceParam.alfLumaCoeffDeltaPredictionFlag = code;
       }
       else
       {
-        alfSliceParam.coeffDeltaPredModeFlag = 0;
+        alfSliceParam.alfLumaCoeffDeltaPredictionFlag = 0;
       }
     }
     else
     {
-      alfSliceParam.coeffDeltaPredModeFlag = 0;
+      alfSliceParam.alfLumaCoeffDeltaPredictionFlag = 0;
     }
   }
 
   // derive maxGolombIdx
   AlfFilterShape alfShape( isChroma ? 5 : 7 );
   const int maxGolombIdx = AdaptiveLoopFilter::getMaxGolombIdx( alfShape.filterType );
-  READ_UVLC( code, "min_golomb_order" );
+  READ_UVLC( code, isChroma ? "alf_chroma_min_eg_order_minus1" : "alf_luma_min_eg_order_minus1" );
 
   int kMin = code + 1;
   static int kMinTab[MAX_NUM_ALF_COEFF];
@@ -2455,7 +2531,7 @@ void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChrom
 
   for( int idx = 0; idx < maxGolombIdx; idx++ )
   {
-    READ_FLAG( code, "golomb_order_increase_flag" );
+    READ_FLAG( code, isChroma ? "alf_chroma_eg_order_increase_flag"  : "alf_luma_eg_order_increase_flag" );
     CHECK( code > 1, "Wrong golomb_order_increase_flag" );
     kMinTab[idx] = kMin + code;
     kMin = kMinTab[idx];
@@ -2463,12 +2539,12 @@ void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChrom
 
   if( !isChroma )
   {
-    if( alfSliceParam.coeffDeltaFlag )
+    if( alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       for( int ind = 0; ind < alfSliceParam.numLumaFilters; ++ind )
       {
-        READ_FLAG( code, "filter_coefficient_flag[i]" );
-        alfSliceParam.filterCoeffFlag[ind] = code;
+        READ_FLAG( code, "alf_luma_coeff_flag[i]" );
+        alfSliceParam.alfLumaCoeffFlag[ind] = code;
       }
     }
   }
@@ -2476,7 +2552,7 @@ void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChrom
   // Filter coefficients
   for( int ind = 0; ind < numFilters; ++ind )
   {
-    if( !isChroma && !alfSliceParam.filterCoeffFlag[ind] && alfSliceParam.coeffDeltaFlag )
+    if( !isChroma && !alfSliceParam.alfLumaCoeffFlag[ind] && alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       memset( coeff + ind * MAX_NUM_ALF_LUMA_COEFF, 0, sizeof( *coeff ) * alfShape.numCoeff );
       continue;
diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h
index 56fc8eb43e5f0d8f2c56c0827c142b7de11a0ef9..b8fa2d66a90a105247e1f3e3cc17bfe53e499de4 100644
--- a/source/Lib/DecoderLib/VLCReader.h
+++ b/source/Lib/DecoderLib/VLCReader.h
@@ -147,7 +147,6 @@ public:
 #if HEVC_VPS
   void  parseVPS            ( VPS* pcVPS );
 #endif
-  void  parseSPSNext        ( SPSNext& spsNext, const bool usePCM );
   void  parseSPS            ( SPS* pcSPS );
   void  parsePPS            ( PPS* pcPPS );
   void  parseVUI            ( VUI* pcVUI, SPS* pcSPS );
@@ -163,7 +162,9 @@ public:
   void  parseScalingList    ( ScalingList* scalingList );
   void  decodeScalingList   ( ScalingList *scalingList, uint32_t sizeId, uint32_t listId);
 #endif
-
+#if JVET_M0427_INLOOP_RESHAPER
+  void parseReshaper        ( SliceReshapeInfo& sliceReshaperInfo, const SPS* pcSPS, const bool isIntra );
+#endif
   void alf( AlfSliceParam& alfSliceParam );
   void alfFilter( AlfSliceParam& alfSliceParam, const bool isChroma );
 
diff --git a/source/Lib/EncoderLib/BinEncoder.cpp b/source/Lib/EncoderLib/BinEncoder.cpp
index c67efa03fc38b80a5da45fd2755993c137c9096f..b80f248043c025257609c5e20cd200f323859972 100644
--- a/source/Lib/EncoderLib/BinEncoder.cpp
+++ b/source/Lib/EncoderLib/BinEncoder.cpp
@@ -207,7 +207,12 @@ void BinEncoderBase::encodeBinsEP( unsigned bins, unsigned numBins )
 
 void BinEncoderBase::encodeRemAbsEP( unsigned bins, unsigned goRicePar, bool useLimitedPrefixLength, int maxLog2TrDynamicRange )
 {
-  const unsigned threshold = g_auiGoRiceRange[ goRicePar ] << goRicePar;
+#if JVET_M0470
+  const unsigned threshold = COEF_REMAIN_BIN_REDUCTION << goRicePar;
+  useLimitedPrefixLength = true;
+#else
+  const unsigned threshold = g_auiGoRiceRange[goRicePar] << goRicePar;
+#endif
   if( bins < threshold )
   {
     const unsigned bitMask  = ( 1 << goRicePar ) - 1;
@@ -251,7 +256,11 @@ void BinEncoderBase::encodeRemAbsEP( unsigned bins, unsigned goRicePar, bool use
       bins -= delta;
       delta = 1 << (++length);
     }
+#if JVET_M0470
+    unsigned numBin = COEF_REMAIN_BIN_REDUCTION + length + 1 - goRicePar;
+#else
     unsigned numBin = g_auiGoRiceRange[ goRicePar ] + length + 1 - goRicePar;
+#endif
     encodeBinsEP( ( 1 << numBin ) - 2, numBin );
     encodeBinsEP( bins,                length );
   }
@@ -438,7 +447,12 @@ BitEstimatorBase::BitEstimatorBase( const BinProbModel* dummy )
 
 void BitEstimatorBase::encodeRemAbsEP( unsigned bins, unsigned goRicePar, bool useLimitedPrefixLength, int maxLog2TrDynamicRange )
 {
-  const unsigned threshold = g_auiGoRiceRange[ goRicePar ] << goRicePar;
+#if JVET_M0470
+  const unsigned threshold = COEF_REMAIN_BIN_REDUCTION << goRicePar;
+  useLimitedPrefixLength = true;
+#else
+  const unsigned threshold = g_auiGoRiceRange[goRicePar] << goRicePar;
+#endif
   if( bins < threshold )
   {
     m_EstFracBits += BinProbModelBase::estFracBitsEP( ( bins >> goRicePar ) + 1 + goRicePar );
@@ -474,7 +488,11 @@ void BitEstimatorBase::encodeRemAbsEP( unsigned bins, unsigned goRicePar, bool u
       bins -= delta;
       delta = 1 << (++length);
     }
+#if JVET_M0470
+    m_EstFracBits += BinProbModelBase::estFracBitsEP(COEF_REMAIN_BIN_REDUCTION + 1 + (length << 1) - goRicePar);
+#else
     m_EstFracBits += BinProbModelBase::estFracBitsEP( g_auiGoRiceRange[ goRicePar ] + 1 + ( length << 1 ) - goRicePar );
+#endif
   }
 }
 
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index a9795b6dbf2e120a85cfced81944161f270c5930..372cf7ae57367f2f3e144c0b45fbe449962414b7 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -544,7 +544,7 @@ void CABACWriter::split_cu_mode( const PartSplit split, const CodingStructure& c
 
   unsigned ctxSplit = 0, ctxQtSplit = 0, ctxBttHV = 0, ctxBttH12 = 0, ctxBttV12;
   DeriveCtx::CtxSplit( cs, partitioner, ctxSplit, ctxQtSplit, ctxBttHV, ctxBttH12, ctxBttV12, canSpl );
-  
+
   const bool canSplit = canBh || canBv || canTh || canTv || canQt;
   const bool isNo     = split == CU_DONT_SPLIT;
 
@@ -713,7 +713,11 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C
   }
 
   // skip flag
+#if JVET_M0483_IBC
+  if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid())
+#else
   if (!cs.slice->isIntra() && cu.Y().valid())
+#endif
   {
     cu_skip_flag( cu );
   }
@@ -745,6 +749,9 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C
 
   extend_ref_line(cu);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  isp_mode( cu );
+#endif
 
   // prediction data ( intra prediction modes / reference indexes + motion vectors )
   cu_pred_data( cu );
@@ -766,19 +773,86 @@ void CABACWriter::cu_transquant_bypass_flag( const CodingUnit& cu )
 void CABACWriter::cu_skip_flag( const CodingUnit& cu )
 {
   unsigned ctxId = DeriveCtx::CtxSkipFlag( cu );
+
+#if JVET_M0483_IBC
+  if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    m_BinEncoder.encodeBin((cu.skip), Ctx::SkipFlag(ctxId));
+    DTRACE(g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0);
+    return;
+  }
+#endif
+
   m_BinEncoder.encodeBin( ( cu.skip ), Ctx::SkipFlag( ctxId ) );
 
   DTRACE( g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0 );
+#if JVET_M0483_IBC
+  if (cu.skip && cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+    m_BinEncoder.encodeBin(CU::isIBC(cu) ? 1 : 0, Ctx::IBCFlag(ctxidx));
+    DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode);
+
+    if (CU::isInter(cu))
+    {
+      m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
+      DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
+    }
+  }
+  if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
+    DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
+  }
+#else
   if (cu.skip)
   {
     m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
     DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
   }
+#endif
 }
 
 
 void CABACWriter::pred_mode( const CodingUnit& cu )
 {
+#if JVET_M0483_IBC
+  if (cu.cs->slice->getSPS()->getIBCFlag())
+  {
+#endif
+#if JVET_M0483_IBC
+    if (cu.cs->slice->isIntra())
+    {
+      unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+      m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx));
+    }
+    else
+    {
+#if JVET_M0502_PRED_MODE_CTX
+      m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)));
+#else
+      m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode());
+#endif
+      if (!CU::isIntra(cu))
+      {
+        unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
+        m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx));
+      }
+    }
+  }
+  else
+  {
+    if (cu.cs->slice->isIntra())
+    {
+      return;
+    }
+#if JVET_M0502_PRED_MODE_CTX
+    m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)));
+#else
+    m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode());
+#endif
+  }
+#else
   if( cu.cs->slice->isIntra() )
   {
     return;
@@ -788,6 +862,7 @@ void CABACWriter::pred_mode( const CodingUnit& cu )
 #else
   m_BinEncoder.encodeBin( ( CU::isIntra( cu ) ), Ctx::PredMode() );
 #endif
+#endif
 }
 
 void CABACWriter::pcm_data( const CodingUnit& cu, Partitioner& partitioner  )
@@ -803,7 +878,7 @@ void CABACWriter::pcm_data( const CodingUnit& cu, Partitioner& partitioner  )
 void CABACWriter::pcm_flag( const CodingUnit& cu, Partitioner& partitioner )
 {
   const SPS& sps = *cu.cs->sps;
-  if( !sps.getPCMEnabledFlag() || partitioner.currArea().lwidth() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lwidth() < (1 << sps.getPCMLog2MinSize()) 
+  if( !sps.getPCMEnabledFlag() || partitioner.currArea().lwidth() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lwidth() < (1 << sps.getPCMLog2MinSize())
       || partitioner.currArea().lheight() > (1 << sps.getPCMLog2MaxSize()) || partitioner.currArea().lheight() < (1 << sps.getPCMLog2MinSize()) )
   {
     return;
@@ -830,6 +905,9 @@ void CABACWriter::cu_pred_data( const CodingUnit& cu )
   }
 
   imv_mode   ( cu );
+#if JVET_M0246_AFFINE_AMVR
+  affine_amvr_mode( cu );
+#endif
 
   cu_gbi_flag( cu );
 
@@ -918,6 +996,10 @@ void CABACWriter::xWriteTruncBinCode(uint32_t symbol, uint32_t maxSymbol)
 
 void CABACWriter::extend_ref_line(const PredictionUnit& pu)
 {
+#if !ENABLE_JVET_L0283_MRL
+  return;
+#endif
+
   const CodingUnit& cu = *pu.cu;
   if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
   {
@@ -945,6 +1027,10 @@ void CABACWriter::extend_ref_line(const PredictionUnit& pu)
 
 void CABACWriter::extend_ref_line(const CodingUnit& cu)
 {
+#if !ENABLE_JVET_L0283_MRL
+  return;
+#endif
+
   if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
   {
     return;
@@ -1012,12 +1098,18 @@ void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu )
         break;
       }
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( pu->multiRefIdx || ( cu.ispMode && isLuma( cu.chType ) ) )
+#else
     if (pu->multiRefIdx)
+#endif
     {
       CHECK(mpm_idx >= numMPMs, "use of non-MPM");
     }
     else
-    m_BinEncoder.encodeBin( mpm_idx < numMPMs, Ctx::IPredMode[0]() );
+    {
+      m_BinEncoder.encodeBin(mpm_idx < numMPMs, Ctx::IntraLumaMpmFlag());
+    }
 
     pu = pu->next;
   }
@@ -1083,7 +1175,7 @@ void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu )
   // prev_intra_luma_pred_flag
   const int numMPMs  = NUM_MOST_PROBABLE_MODES;
   unsigned  mpm_pred[numMPMs];
-  
+
   PU::getIntraMPMs( pu, mpm_pred );
 
   unsigned ipred_mode = pu.intraDir[0];
@@ -1097,12 +1189,18 @@ void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu )
       break;
     }
   }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( pu.multiRefIdx || ( pu.cu->ispMode && isLuma( pu.cu->chType ) ) )
+#else
   if (pu.multiRefIdx)
+#endif
   {
     CHECK(mpm_idx >= numMPMs, "use of non-MPM");
   }
   else
-  m_BinEncoder.encodeBin( mpm_idx < numMPMs, Ctx::IPredMode[0]() );
+  {
+    m_BinEncoder.encodeBin(mpm_idx < numMPMs, Ctx::IntraLumaMpmFlag());
+  }
 
   // mpm_idx / rem_intra_luma_pred_mode
   if( mpm_idx < numMPMs )
@@ -1172,24 +1270,24 @@ void CABACWriter::intra_chroma_lmc_mode( const PredictionUnit& pu )
     }
     CHECK( symbol < 0, "invalid symbol found" );
 
-    unary_max_symbol( symbol, Ctx::IPredMode[1]( 2 ), Ctx::IPredMode[1]( 3 ), maxSymbol - 1 );
+    unary_max_symbol(symbol, Ctx::IntraChromaPredMode(1), Ctx::IntraChromaPredMode(2), maxSymbol - 1);
 }
 
 
 void CABACWriter::intra_chroma_pred_mode( const PredictionUnit& pu )
 {
   const unsigned intraDir = pu.intraDir[1];
+  const bool     isDerivedMode = intraDir == DM_CHROMA_IDX;
+
+  m_BinEncoder.encodeBin(isDerivedMode ? 0 : 1, Ctx::IntraChromaPredMode(0));
+
+  if (isDerivedMode)
   {
-    if( intraDir == DM_CHROMA_IDX )
-    {
-      m_BinEncoder.encodeBin( 0, Ctx::IPredMode[1]( 1 ) );
-      return;
-    }
-    m_BinEncoder.encodeBin( 1, Ctx::IPredMode[1]( 1 ) );
+    return;
   }
 
   // LM chroma mode
-  if( pu.cs->sps->getSpsNext().getUseLMChroma() )
+  if( pu.cs->sps->getUseLMChroma() )
   {
     intra_chroma_lmc_mode( pu );
     if ( PU::isLMCMode( intraDir ) )
@@ -1221,13 +1319,23 @@ void CABACWriter::intra_chroma_pred_mode( const PredictionUnit& pu )
 
 void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, CUCtx& cuCtx )
 {
+#if JVET_M0483_IBC
+  if (!CU::isIntra(cu))
+#else
   if( CU::isInter( cu ) )
+#endif
   {
     PredictionUnit& pu = *cu.firstPU;
     if( !pu.mergeFlag )
     {
       rqt_root_cbf( cu );
     }
+#if JVET_M0140_SBT
+    if( cu.rootCbf )
+    {
+      sbt_mode( cu );
+    }
+#endif
 
     if( !cu.rootCbf )
     {
@@ -1237,7 +1345,19 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C
 
 
   ChromaCbfs chromaCbfs;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( cu.ispMode && isLuma( partitioner.chType ) )
+  {
+    TUIntraSubPartitioner subTuPartitioner( partitioner );
+    transform_tree( *cu.cs, subTuPartitioner, cuCtx, chromaCbfs, CU::getISPType( cu, getFirstComponentOfChannel( partitioner.chType ) ), 0 );
+  }
+  else
+  {
+    transform_tree( *cu.cs, partitioner, cuCtx, chromaCbfs );
+  }
+#else
   transform_tree( *cu.cs, partitioner, cuCtx, chromaCbfs );
+#endif
 }
 
 void CABACWriter::rqt_root_cbf( const CodingUnit& cu )
@@ -1247,6 +1367,64 @@ void CABACWriter::rqt_root_cbf( const CodingUnit& cu )
   DTRACE( g_trace_ctx, D_SYNTAX, "rqt_root_cbf() ctx=0 root_cbf=%d pos=(%d,%d)\n", cu.rootCbf ? 1 : 0, cu.lumaPos().x, cu.lumaPos().y );
 }
 
+#if JVET_M0140_SBT
+void CABACWriter::sbt_mode( const CodingUnit& cu )
+{
+  uint8_t sbtAllowed = cu.checkAllowedSbt();
+  if( !sbtAllowed )
+  {
+    return;
+  }
+
+  SizeType cuWidth = cu.lwidth();
+  SizeType cuHeight = cu.lheight();
+  uint8_t sbtIdx = cu.getSbtIdx();
+  uint8_t sbtPos = cu.getSbtPos();
+
+  //bin - flag
+  bool sbtFlag = cu.sbtInfo != 0;
+  uint8_t ctxIdx = ( cuWidth * cuHeight <= 256 ) ? 1 : 0;
+  m_BinEncoder.encodeBin( sbtFlag, Ctx::SbtFlag( ctxIdx ) );
+  if( !sbtFlag )
+  {
+    return;
+  }
+
+  bool sbtQuadFlag = sbtIdx == SBT_HOR_QUAD || sbtIdx == SBT_VER_QUAD;
+  bool sbtHorFlag = sbtIdx == SBT_HOR_HALF || sbtIdx == SBT_HOR_QUAD;
+  bool sbtPosFlag = sbtPos == SBT_POS1;
+
+  uint8_t sbtVerHalfAllow = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed );
+  uint8_t sbtHorHalfAllow = CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
+  uint8_t sbtVerQuadAllow = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed );
+  uint8_t sbtHorQuadAllow = CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
+  //bin - type
+  if( ( sbtHorHalfAllow || sbtVerHalfAllow ) && ( sbtHorQuadAllow || sbtVerQuadAllow ) )
+  {
+    m_BinEncoder.encodeBin( sbtQuadFlag, Ctx::SbtQuadFlag( 0 ) );
+  }
+  else
+  {
+    assert( sbtQuadFlag == 0 );
+  }
+
+  //bin - dir
+  if( ( sbtQuadFlag && sbtVerQuadAllow && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtVerHalfAllow && sbtHorHalfAllow ) ) //both direction allowed
+  {
+    uint8_t ctxIdx = ( cuWidth == cuHeight ) ? 0 : ( cuWidth < cuHeight ? 1 : 2 );
+    m_BinEncoder.encodeBin( sbtHorFlag, Ctx::SbtHorFlag( ctxIdx ) );
+  }
+  else
+  {
+    assert( sbtHorFlag == ( ( sbtQuadFlag && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtHorHalfAllow ) ) );
+  }
+
+  //bin - pos
+  m_BinEncoder.encodeBin( sbtPosFlag, Ctx::SbtPosFlag( 0 ) );
+
+  DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), (int)cu.sbtInfo );
+}
+#endif
 
 void CABACWriter::end_of_ctu( const CodingUnit& cu, CUCtx& cuCtx )
 {
@@ -1310,6 +1488,13 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
   }
   if( pu.mergeFlag )
   {
+#if JVET_M0483_IBC
+    if (CU::isIBC(*pu.cu))
+    {
+      merge_idx(pu);
+      return;
+    }
+#endif
     subblock_merge_flag( *pu.cu );
     MHIntra_flag( pu );
     if ( pu.mhIntraFlag )
@@ -1324,8 +1509,19 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
     else
     merge_idx    ( pu );
   }
+#if JVET_M0483_IBC
+  else if (CU::isIBC(*pu.cu))
+  {
+    ref_idx(pu, REF_PIC_LIST_0);
+    mvd_coding(pu.mvd[REF_PIC_LIST_0], pu.cu->imv);
+    mvp_flag(pu, REF_PIC_LIST_0);
+  }
+#endif
   else
   {
+#if JVET_M0246_AFFINE_AMVR
+    int8_t affineMvdShift = pu.cu->imv ? ( pu.cu->imv == 1 ? -1 : 1 ) : 0;
+#endif
     inter_pred_idc( pu );
     affine_flag   ( *pu.cu );
 #if JVET_M0444_SMVD
@@ -1336,12 +1532,21 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
       ref_idx     ( pu, REF_PIC_LIST_0 );
       if ( pu.cu->affine )
       {
+#if JVET_M0246_AFFINE_AMVR
+        mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][0], affineMvdShift );
+        mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][1], affineMvdShift );
+        if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
+        {
+          mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][2], affineMvdShift );
+        }
+#else
         mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][0], 0);
         mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][1], 0);
         if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
         {
           mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][2], 0);
         }
+#endif
       }
       else
       {
@@ -1360,12 +1565,21 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
       {
         if ( pu.cu->affine )
         {
+#if JVET_M0246_AFFINE_AMVR
+          mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][0], affineMvdShift );
+          mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][1], affineMvdShift );
+          if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
+          {
+            mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][2], affineMvdShift );
+          }
+#else
           mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][0], 0);
           mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][1], 0);
           if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
           {
             mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][2], 0);
           }
+#endif
         }
         else
         {
@@ -1406,7 +1620,7 @@ void CABACWriter::subblock_merge_flag( const CodingUnit& cu )
     return;
   }
 
-  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getSpsNext().getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
   {
     unsigned ctxId = DeriveCtx::CtxAffineFlag( cu );
     m_BinEncoder.encodeBin( cu.affine, Ctx::AffineFlag( ctxId ) );
@@ -1416,13 +1630,13 @@ void CABACWriter::subblock_merge_flag( const CodingUnit& cu )
 
 void CABACWriter::affine_flag( const CodingUnit& cu )
 {
-  if ( !cu.cs->slice->isIntra() && cu.cs->sps->getSpsNext().getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8 )
+  if ( !cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8 )
   {
     unsigned ctxId = DeriveCtx::CtxAffineFlag( cu );
     m_BinEncoder.encodeBin( cu.affine, Ctx::AffineFlag( ctxId ) );
     DTRACE( g_trace_ctx, D_SYNTAX, "affine_flag() affine=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y );
 
-    if ( cu.affine && cu.cs->sps->getSpsNext().getUseAffineType() )
+    if ( cu.affine && cu.cs->sps->getUseAffineType() )
     {
       unsigned ctxId = 0;
       m_BinEncoder.encodeBin( cu.affineType, Ctx::AffineType( ctxId ) );
@@ -1436,6 +1650,14 @@ void CABACWriter::merge_flag( const PredictionUnit& pu )
   m_BinEncoder.encodeBin( pu.mergeFlag, Ctx::MergeFlag() );
 
   DTRACE( g_trace_ctx, D_SYNTAX, "merge_flag() merge=%d pos=(%d,%d) size=%dx%d\n", pu.mergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
+
+#if JVET_M0483_IBC
+  if (pu.mergeFlag && CU::isIBC(*pu.cu))
+  {
+    return;
+  }
+#endif
+
   if (pu.mergeFlag)
   {
     m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0));
@@ -1445,12 +1667,18 @@ void CABACWriter::merge_flag( const PredictionUnit& pu )
 
 void CABACWriter::imv_mode( const CodingUnit& cu )
 {
-  const SPSNext& spsNext = cu.cs->sps->getSpsNext();
+  const SPS *sps = cu.cs->sps;
 
-  if( !spsNext.getUseIMV() )
+  if( !sps->getAMVREnabledFlag() )
   {
     return;
   }
+#if JVET_M0246_AFFINE_AMVR
+  if ( cu.affine )
+  {
+    return;
+  }
+#endif
 
   bool bNonZeroMvd = CU::hasSubCUNonZeroMVd( cu );
   if( !bNonZeroMvd )
@@ -1459,11 +1687,15 @@ void CABACWriter::imv_mode( const CodingUnit& cu )
   }
 
   unsigned ctxId = DeriveCtx::CtxIMVFlag( cu );
+#if JVET_M0483_IBC
+  if (CU::isIBC(cu) == false)
+#else
   if (!(cu.firstPU->interDir == 1 && cu.cs->slice->getRefPic(REF_PIC_LIST_0, cu.firstPU->refIdx[REF_PIC_LIST_0])->getPOC() == cu.cs->slice->getPOC())) // the first bin of IMV flag does need to be signaled in IBC block
+#endif
     m_BinEncoder.encodeBin( ( cu.imv > 0 ), Ctx::ImvFlag( ctxId ) );
   DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", (cu.imv > 0), ctxId );
 
-  if( spsNext.getImvMode() == IMV_4PEL && cu.imv > 0 )
+  if( sps->getAMVREnabledFlag() && cu.imv > 0 )
   {
     m_BinEncoder.encodeBin( ( cu.imv > 1 ), Ctx::ImvFlag( 3 ) );
     DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", ( cu.imv > 1 ), 3 );
@@ -1472,6 +1704,33 @@ void CABACWriter::imv_mode( const CodingUnit& cu )
   DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv );
 }
 
+#if JVET_M0246_AFFINE_AMVR
+void CABACWriter::affine_amvr_mode( const CodingUnit& cu )
+{
+  const SPS* sps = cu.slice->getSPS();
+
+  if( !sps->getAffineAmvrEnabledFlag() || !cu.affine )
+  {
+    return;
+  }
+
+  if ( !CU::hasSubCUNonZeroAffineMVd( cu ) )
+  {
+    return;
+  }
+
+  m_BinEncoder.encodeBin( ( cu.imv > 0 ), Ctx::ImvFlag( 4 ) );
+  DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", ( cu.imv > 0 ), 4 );
+
+  if( cu.imv > 0 )
+  {
+    m_BinEncoder.encodeBin( ( cu.imv > 1 ), Ctx::ImvFlag( 5 ) );
+    DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", ( cu.imv > 1 ), 5 );
+  }
+  DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() IMVFlag=%d\n", cu.imv );
+}
+#endif
+
 void CABACWriter::merge_idx( const PredictionUnit& pu )
 {
 
@@ -1488,18 +1747,24 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
       }
       else
       {
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
         bool useExtCtx = pu.cs->sps->getSBTMVPEnabledFlag();
+#endif
         m_BinEncoder.encodeBin( 1, Ctx::AffMergeIdx() );
         for ( unsigned idx = 1; idx < numCandminus1; idx++ )
         {
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
           if ( useExtCtx )
           {
             m_BinEncoder.encodeBin( pu.mergeIdx == idx ? 0 : 1, Ctx::AffMergeIdx( std::min<int>( idx, NUM_MERGE_IDX_EXT_CTX - 1 ) ) );
           }
           else
           {
+#endif
             m_BinEncoder.encodeBinEP( pu.mergeIdx == idx ? 0 : 1 );
+#if !JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX
           }
+#endif
           if ( pu.mergeIdx == idx )
           {
             break;
@@ -1513,6 +1778,38 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
   {
     if( pu.cu->triangle )
     {
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool    splitDir = pu.triangleSplitDir;
+      uint8_t candIdx0 = pu.triangleMergeIdx0;
+      uint8_t candIdx1 = pu.triangleMergeIdx1;
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_split_dir=%d\n", splitDir );
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx0=%d\n", candIdx0 );
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx1=%d\n", candIdx1 );
+      candIdx1 -= candIdx1 < candIdx0 ? 0 : 1;
+      auto encodeOneIdx = [this](uint8_t mrgIdx, int numCandminus1)
+      {
+        if(mrgIdx == 0)
+        {
+          this->m_BinEncoder.encodeBin( 0, Ctx::MergeIdx() );
+          return;
+        }
+        else
+        {
+          this->m_BinEncoder.encodeBin( 1, Ctx::MergeIdx() );
+          for( unsigned idx = 1; idx < numCandminus1; idx++ )
+          {
+            this->m_BinEncoder.encodeBinEP( mrgIdx == idx ? 0 : 1 );
+            if( mrgIdx == idx )
+            {
+              break;
+            }
+          }
+        }
+      };
+      m_BinEncoder.encodeBinEP(splitDir);
+      encodeOneIdx(candIdx0, TRIANGLE_MAX_NUM_UNI_CANDS - 1);
+      encodeOneIdx(candIdx1, TRIANGLE_MAX_NUM_UNI_CANDS - 2);
+#else
       if( pu.mergeIdx < 2 )
       {
         m_BinEncoder.encodeBin( 0, Ctx::TriangleIdx() );
@@ -1525,6 +1822,7 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
       }
 
       DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx=%d\n", pu.mergeIdx );
+#endif
       return;
     }
   int numCandminus1 = int( pu.cs->slice->getMaxNumMergeCand() ) - 1;
@@ -1645,6 +1943,15 @@ void CABACWriter::ref_idx( const PredictionUnit& pu, RefPicList eRefList )
 #endif
 
   int numRef  = pu.cs->slice->getNumRefIdx(eRefList);
+
+#if JVET_M0483_IBC
+  if (eRefList == REF_PIC_LIST_0 && pu.cs->sps->getIBCFlag())
+  {
+    if (CU::isIBC(*pu.cu))
+      return;
+  }
+#endif
+
   if( numRef <= 1 )
   {
     return;
@@ -1686,7 +1993,7 @@ void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList )
 
 void CABACWriter::MHIntra_flag(const PredictionUnit& pu)
 {
-  if (!pu.cs->sps->getSpsNext().getUseMHIntra())
+  if (!pu.cs->sps->getUseMHIntra())
   {
     CHECK(pu.mhIntraFlag == true, "invalid MHIntra SPS");
     return;
@@ -1777,7 +2084,7 @@ void CABACWriter::MHIntra_luma_pred_modes(const CodingUnit& cu)
 
 void CABACWriter::triangle_mode( const CodingUnit& cu )
 {
-  if( !cu.cs->slice->getSPS()->getSpsNext().getUseTriangle() || !cu.cs->slice->isInterB() || cu.lwidth() * cu.lheight() < TRIANGLE_MIN_SIZE || cu.affine )
+  if( !cu.cs->slice->getSPS()->getUseTriangle() || !cu.cs->slice->isInterB() || cu.lwidth() * cu.lheight() < TRIANGLE_MIN_SIZE || cu.affine )
   {
     return;
   }
@@ -1843,29 +2150,92 @@ void CABACWriter::pcm_samples( const TransformUnit& tu )
 //    bool  cbf_comp            ( cbf, area, depth )
 //================================================================================
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, ChromaCbfs& chromaCbfs, const PartSplit ispType, const int subTuIdx )
+#else
 void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, ChromaCbfs& chromaCbfs )
+#endif
 {
+#if JVET_M0140_SBT
+  ChromaCbfs chromaCbfsLastDepth;
+  chromaCbfsLastDepth.Cb              = chromaCbfs.Cb;
+  chromaCbfsLastDepth.Cr              = chromaCbfs.Cr;
+#endif
   const UnitArea&       area          = partitioner.currArea();
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        int             subTuCounter  = subTuIdx;
+  const TransformUnit&  tu            = *cs.getTU( area.blocks[partitioner.chType].pos(), partitioner.chType, subTuIdx );
+#else
   const TransformUnit&  tu            = *cs.getTU( area.blocks[partitioner.chType].pos(), partitioner.chType );
+#endif
   const CodingUnit&     cu            = *tu.cu;
   const unsigned        trDepth       = partitioner.currTrDepth;
   const bool            split         = ( tu.depth > trDepth );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const bool            chromaCbfISP  = area.blocks[COMPONENT_Cb].valid() && cu.ispMode && !split;
+#endif
 
   // split_transform_flag
   if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
   {
     CHECK( !split, "transform split implied" );
   }
+#if JVET_M0140_SBT
+  else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+  {
+    CHECK( !split, "transform split implied - sbt" );
+  }
+#endif
   else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  CHECK( split && !cu.ispMode, "transform split not allowed with QTBT" );
+#else
   CHECK( split, "transform split not allowed with QTBT" );
+#endif
+
 
   // cbf_cb & cbf_cr
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && ( !CS::isDualITree( cs ) || partitioner.chType == CHANNEL_TYPE_CHROMA ) && ( !cu.ispMode || chromaCbfISP ) )
+#else
   if( area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && ( !CS::isDualITree( cs ) || partitioner.chType == CHANNEL_TYPE_CHROMA ) )
+#endif
   {
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
+      if( trDepth == 0 || chromaCbfs.Cb || chromaCbfISP )
+      {
+        chromaCbfs.Cb = TU::getCbfAtDepth( tu, COMPONENT_Cb, trDepth );
+#if JVET_M0140_SBT
+        if( !( cu.sbtInfo && trDepth == 1 ) )
+#endif
+        cbf_comp( cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth );
+      }
+      else
+      {
+        CHECK( TU::getCbfAtDepth( tu, COMPONENT_Cb, cbfDepth ) != chromaCbfs.Cb, "incorrect Cb cbf" );
+      }
+
+      if( trDepth == 0 || chromaCbfs.Cr || chromaCbfISP )
+      {
+        chromaCbfs.Cr = TU::getCbfAtDepth( tu, COMPONENT_Cr, trDepth );
+#if JVET_M0140_SBT
+        if( !( cu.sbtInfo && trDepth == 1 ) )
+#endif
+        cbf_comp( cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb );
+      }
+      else
+      {
+        CHECK( TU::getCbfAtDepth( tu, COMPONENT_Cr, cbfDepth ) != chromaCbfs.Cr, "incorrect Cr cbf" );
+      }
+#else
       if( trDepth == 0 || chromaCbfs.Cb )
       {
         chromaCbfs.Cb = TU::getCbfAtDepth( tu, COMPONENT_Cb, trDepth );
+#if JVET_M0140_SBT
+        if( !( cu.sbtInfo && trDepth == 1 ) )
+#endif
         cbf_comp( cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], trDepth );
       }
       else
@@ -1876,12 +2246,16 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
       if( trDepth == 0 || chromaCbfs.Cr )
       {
         chromaCbfs.Cr = TU::getCbfAtDepth( tu, COMPONENT_Cr,   trDepth );
+#if JVET_M0140_SBT
+        if( !( cu.sbtInfo && trDepth == 1 ) )
+#endif
         cbf_comp( cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], trDepth, chromaCbfs.Cb );
       }
       else
       {
         CHECK( TU::getCbfAtDepth( tu, COMPONENT_Cr, trDepth ) != chromaCbfs.Cr, "incorrect Cr cbf" );
       }
+#endif
     }
   }
   else if( CS::isDualITree( cs ) )
@@ -1897,7 +2271,11 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
       chromaCbfs.Cr        = TU::getCbfAtDepth( tu, COMPONENT_Cr,  trDepth );
     }
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if ( trDepth == 0 && !cu.ispMode ) emt_cu_flag( cu );
+#else
     if( trDepth == 0 ) emt_cu_flag( cu );
+#endif
 #endif
 
     if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
@@ -1909,13 +2287,30 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
 #endif
       partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    else if( cu.ispMode )
+    {
+      partitioner.splitCurrArea( ispType, cs );
+    }
+#endif
+#if JVET_M0140_SBT
+    else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+    {
+      partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
+    }
+#endif
     else
       THROW( "Implicit TU split not available" );
 
     do
     {
       ChromaCbfs subChromaCbfs = chromaCbfs;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      transform_tree( cs, partitioner, cuCtx, subChromaCbfs, ispType, subTuCounter );
+      subTuCounter += subTuCounter != -1 ? 1 : 0;
+#else
       transform_tree( cs, partitioner, cuCtx, subChromaCbfs );
+#endif
     } while( partitioner.nextPart( cs ) );
 
     partitioner.exitCurrSplit();
@@ -1930,9 +2325,51 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
       {
         CHECK( !TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be true for inter units with no chroma coeffs" );
       }
+#if JVET_M0140_SBT
+      else if( cu.sbtInfo && tu.noResidual )
+      {
+        CHECK( TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be false for inter sbt no-residual tu" );
+      }
+      else if( cu.sbtInfo && !chromaCbfsLastDepth.sigChroma( area.chromaFormat ) )
+      {
+        assert( !tu.noResidual );
+        CHECK( !TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), "Luma cbf must be true for inter sbt residual tu" );
+      }
+#endif
       else
       {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        bool previousCbf       = false;
+        bool rootCbfSoFar      = false;
+        bool lastCbfIsInferred = false;
+        if( cu.ispMode )
+        {
+          uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[tu.lheight()] : cu.lwidth() >> g_aucLog2[tu.lwidth()];
+          if( subTuCounter == nTus - 1 )
+          {
+            TransformUnit* tuPointer = cu.firstTU;
+            for( int tuIdx = 0; tuIdx < subTuCounter; tuIdx++ )
+            {
+              rootCbfSoFar |= TU::getCbfAtDepth( *tuPointer, COMPONENT_Y, trDepth );
+              tuPointer = tuPointer->next;
+            }
+            if( !rootCbfSoFar )
+            {
+              lastCbfIsInferred = true;
+            }
+          }
+          if( !lastCbfIsInferred )
+          {
+            previousCbf = TU::getPrevTuCbfAtDepth( tu, COMPONENT_Y, partitioner.currTrDepth );
+          }
+        }
+        if( !lastCbfIsInferred )
+        {
+          cbf_comp( cs, TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), tu.Y(), trDepth, previousCbf, cu.ispMode );
+        }
+#else
         cbf_comp( cs, TU::getCbfAtDepth( tu, COMPONENT_Y, trDepth ), tu.Y(), trDepth );
+#endif
       }
     }
 
@@ -1944,9 +2381,15 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbCbf, const bool useISP )
+{
+  const unsigned  ctxId   = DeriveCtx::CtxQtCbf( area.compID, depth, prevCbCbf, useISP && isLuma(area.compID) );
+#else
 void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbCbf )
 {
   const unsigned  ctxId   = DeriveCtx::CtxQtCbf( area.compID, depth, prevCbCbf );
+#endif
   const CtxSet&   ctxSet  = Ctx::QtCbf[ area.compID ];
 
   m_BinEncoder.encodeBin( cbf, ctxSet( ctxId ) );
@@ -1962,12 +2405,19 @@ void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea&
 //--------------------------------------------------------------------------------
 //    void  mvd_coding( pu, refList )
 //================================================================================
-
+#if JVET_M0246_AFFINE_AMVR
+void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv )
+#else
 void CABACWriter::mvd_coding( const Mv &rMvd, uint8_t imv )
+#endif
 {
   int       horMvd = rMvd.getHor();
   int       verMvd = rMvd.getVer();
+#if JVET_M0246_AFFINE_AMVR
+  if ( imv > 0 )
+#else
   if( imv )
+#endif
   {
     CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 4" );
     horMvd >>= 2;
@@ -2035,7 +2485,11 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, ChromaC
   bool        cbfLuma   = ( cbf[ COMPONENT_Y ] != 0 );
   bool        cbfChroma = false;
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( !lumaOnly )
+#else
   if( cu.chromaFormat != CHROMA_400 )
+#endif
   {
     if( tu.blocks[COMPONENT_Cb].valid() )
     {
@@ -2195,19 +2649,48 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID )
   cctx.setScanPosLast(scanPosLast);
 
   // code last coeff position
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  last_sig_coeff( cctx, tu, compID );
+#else
   last_sig_coeff( cctx );
+#endif
 
   // code subblocks
   const int stateTab  = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
   int       state     = 0;
 #if !JVET_M0464_UNI_MTS
-  bool useEmt = ( cu.cs->sps->getSpsNext().getUseIntraEMT() && cu.predMode == MODE_INTRA ) || ( cu.cs->sps->getSpsNext().getUseInterEMT() && cu.predMode != MODE_INTRA );
+  bool useEmt = ( cu.cs->sps->getUseIntraEMT() && cu.predMode == MODE_INTRA ) || ( cu.cs->sps->getUseInterEMT() && cu.predMode != MODE_INTRA );
   useEmt = useEmt && isLuma(compID);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  useEmt = useEmt && !cu.ispMode;
+#endif
 #endif
 
   for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
   {
     cctx.initSubblock       ( subSetId, sigGroupFlags[subSetId] );
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+#if JVET_M0140_SBT
+#if JVET_M0464_UNI_MTS
+    if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+    if( ( ( tu.cu->emtFlag && !tu.transformSkip[ compID ] ) || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#else
+#if JVET_M0464_UNI_MTS
+    if( tu.mtsIdx > 1 && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+    if( tu.cu->emtFlag && !tu.transformSkip[ compID ] && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#endif
+    {
+      if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) )
+       || ( tu.blocks[ compID ].width  == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth()  ) ) )
+      {
+        continue;
+      }
+    }
+#endif
     residual_coding_subblock( cctx, coeff, stateTab, state );
 
 #if !JVET_M0464_UNI_MTS
@@ -2284,7 +2767,11 @@ void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID )
 #else
 void CABACWriter::transform_skip_flag( const TransformUnit& tu, ComponentID compID )
 {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if (!tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag(*tu.cs, tu.blocks[compID]) || (isLuma(compID) && tu.cu->emtFlag) || (tu.cu->ispMode && isLuma(compID)))
+#else
   if( !tu.cu->cs->pps->getUseTransformSkip() || tu.cu->transQuantBypass || !TU::hasTransformSkipFlag( *tu.cs, tu.blocks[compID] ) || ( isLuma( compID ) && tu.cu->emtFlag ) )
+#endif
   {
     return;
   }
@@ -2317,9 +2804,19 @@ void CABACWriter::emt_tu_index( const TransformUnit& tu )
 //void CABACWriter::emt_cu_flag(const CodingUnit& cu, uint32_t depth, bool codeCuFlag, const int tuWidth,const int tuHeight)
 void CABACWriter::emt_cu_flag( const CodingUnit& cu )
 {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if ( CU::isIntra( cu ) && cu.ispMode )
+  {
+    return;
+  }
+#endif
   const CodingStructure& cs = *cu.cs;
 
-  if( !( ( cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getSpsNext().getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) )
+#if JVET_M0483_IBC
+  if (!((cs.sps->getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getUseInterEMT() && !CU::isIntra(cu))) || isChroma(cu.chType))
+#else
+  if( !( ( cs.sps->getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) )
+#endif
   {
     return;
   }
@@ -2345,6 +2842,33 @@ void CABACWriter::emt_cu_flag( const CodingUnit& cu )
 }
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void CABACWriter::isp_mode( const CodingUnit& cu )
+{
+  if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx )
+  {
+    CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "error: cu.intraSubPartitions != 0" );
+    return;
+  }
+  const ISPType allowedSplits = CU::canUseISPSplit( cu, getFirstComponentOfChannel( cu.chType ) );
+  if( allowedSplits == NOT_INTRA_SUBPARTITIONS ) return;
+
+  if( cu.ispMode == NOT_INTRA_SUBPARTITIONS )
+  {
+    m_BinEncoder.encodeBin( 0, Ctx::ISPMode( 0 ) );
+  }
+  else
+  {
+    m_BinEncoder.encodeBin( 1, Ctx::ISPMode( 0 ) );
+
+    if( allowedSplits == CAN_USE_VER_AND_HORL_SPLITS )
+    {
+      m_BinEncoder.encodeBin( cu.ispMode - 1, Ctx::ISPMode( 1 ) );
+    }
+  }
+  DTRACE( g_trace_ctx, D_SYNTAX, "intra_subPartitions() etype=%d pos=(%d,%d) ispIdx=%d\n", cu.chType, cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, (int)cu.ispMode );
+}
+#endif
 
 void CABACWriter::explicit_rdpcm_mode( const TransformUnit& tu, ComponentID compID )
 {
@@ -2373,7 +2897,11 @@ void CABACWriter::explicit_rdpcm_mode( const TransformUnit& tu, ComponentID comp
 }
 
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID )
+#else
 void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx )
+#endif
 {
   unsigned blkPos = cctx.blockPos( cctx.scanPosLast() );
   unsigned posX, posY;
@@ -2394,11 +2922,38 @@ void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx )
   unsigned GroupIdxX = g_uiGroupIdx[ posX ];
   unsigned GroupIdxY = g_uiGroupIdx[ posY ];
 
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  unsigned maxLastPosX = cctx.maxLastPosX();
+  unsigned maxLastPosY = cctx.maxLastPosY();
+
+#if JVET_M0140_SBT
+#if JVET_M0464_UNI_MTS
+  if( ( tu.mtsIdx > 1 || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+  if( ( ( tu.cu->emtFlag && !tu.transformSkip[ compID ] ) || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#else
+#if JVET_M0464_UNI_MTS
+  if( tu.mtsIdx > 1 && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#else
+  if( tu.cu->emtFlag && !tu.transformSkip[ compID ] && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
+#endif
+#endif
+  {
+    maxLastPosX = ( tu.blocks[compID].width  == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
+    maxLastPosY = ( tu.blocks[compID].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;
+  }
+#endif
+
   for( CtxLast = 0; CtxLast < GroupIdxX; CtxLast++ )
   {
     m_BinEncoder.encodeBin( 1, cctx.lastXCtxId( CtxLast ) );
   }
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  if( GroupIdxX < maxLastPosX )
+#else
   if( GroupIdxX < cctx.maxLastPosX() )
+#endif
   {
     m_BinEncoder.encodeBin( 0, cctx.lastXCtxId( CtxLast ) );
   }
@@ -2406,7 +2961,11 @@ void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx )
   {
     m_BinEncoder.encodeBin( 1, cctx.lastYCtxId( CtxLast ) );
   }
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  if( GroupIdxY < maxLastPosY )
+#else
   if( GroupIdxY < cctx.maxLastPosY() )
+#endif
   {
     m_BinEncoder.encodeBin( 0, cctx.lastYCtxId( CtxLast ) );
   }
diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h
index 10c97e26f7796ea71d546d39521533b9f4fa2c19..ab7ebb08f54bb6a40e53a65456baa0aa6c5ba64f 100644
--- a/source/Lib/EncoderLib/CABACWriter.h
+++ b/source/Lib/EncoderLib/CABACWriter.h
@@ -107,6 +107,9 @@ public:
   void        intra_chroma_pred_mode    ( const PredictionUnit&         pu );
   void        cu_residual               ( const CodingUnit&             cu,       Partitioner&      pm,         CUCtx& cuCtx );
   void        rqt_root_cbf              ( const CodingUnit&             cu );
+#if JVET_M0140_SBT
+  void        sbt_mode                  ( const CodingUnit&             cu );
+#endif
   void        end_of_ctu                ( const CodingUnit&             cu,       CUCtx&            cuCtx );
 
   // prediction unit (clause 7.3.8.6)
@@ -117,6 +120,9 @@ public:
   void        merge_idx                 ( const PredictionUnit&         pu );
   void        mmvd_merge_idx(const PredictionUnit&         pu);
   void        imv_mode                  ( const CodingUnit&             cu );
+#if JVET_M0246_AFFINE_AMVR
+  void        affine_amvr_mode          ( const CodingUnit&             cu );
+#endif
   void        inter_pred_idc            ( const PredictionUnit&         pu );
   void        ref_idx                   ( const PredictionUnit&         pu,       RefPicList        eRefList );
   void        mvp_flag                  ( const PredictionUnit&         pu,       RefPicList        eRefList );
@@ -132,12 +138,20 @@ public:
   void        pcm_samples               ( const TransformUnit&          tu );
 
   // transform tree (clause 7.3.8.8)
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void        transform_tree            ( const CodingStructure&        cs,       Partitioner&      pm,     CUCtx& cuCtx, ChromaCbfs& chromaCbfs, const PartSplit ispType = TU_NO_ISP, const int subTuIdx = -1 );
+  void        cbf_comp                  ( const CodingStructure&        cs,       bool              cbf,    const CompArea& area, unsigned depth, const bool prevCbCbf = false, const bool useISP = false );
+#else
   void        transform_tree            ( const CodingStructure&        cs,       Partitioner&      pm,     CUCtx& cuCtx,   ChromaCbfs& chromaCbfs );
   void        cbf_comp                  ( const CodingStructure&        cs,       bool              cbf,    const CompArea& area, unsigned depth, const bool prevCbCbf = false );
+#endif
 
   // mvd coding (clause 7.3.8.9)
+#if JVET_M0246_AFFINE_AMVR
+  void        mvd_coding                ( const Mv &rMvd, int8_t imv );
+#else
   void        mvd_coding                ( const Mv &rMvd, uint8_t imv );
-
+#endif
   // transform unit (clause 7.3.8.10)
   void        transform_unit            ( const TransformUnit&          tu,       CUCtx&            cuCtx,  ChromaCbfs& chromaCbfs );
   void        cu_qp_delta               ( const CodingUnit&             cu,       int               predQP, const int8_t qp );
@@ -151,10 +165,17 @@ public:
   void        transform_skip_flag       ( const TransformUnit&          tu,       ComponentID       compID );
   void        emt_tu_index              ( const TransformUnit&          tu );
   void        emt_cu_flag               ( const CodingUnit&             cu );
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void        isp_mode                  ( const CodingUnit&             cu );
 #endif
   void        explicit_rdpcm_mode       ( const TransformUnit&          tu,       ComponentID       compID );
+#if JVET_M0297_32PT_MTS_ZERO_OUT
+  void        last_sig_coeff            ( CoeffCodingContext&           cctx,     const TransformUnit& tu, ComponentID       compID );
+#else
   void        last_sig_coeff            ( CoeffCodingContext&           cctx );
-  void        residual_coding_subblock  ( CoeffCodingContext&           cctx,     const TCoeff*     coeff, const int stateTransTable, int& state   );
+#endif
+  void        residual_coding_subblock  ( CoeffCodingContext&           cctx,     const TCoeff*     coeff, const int stateTransTable, int& state );
 
   // cross component prediction (clause 7.3.8.12)
   void        cross_comp_pred           ( const TransformUnit&          tu,       ComponentID       compID );
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index f8a713d34689c63d76e8badcb55ca89fb2f01fe0..a160fe70993d3eb6c9f7d9988480609f3929e9a0 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -40,6 +40,9 @@
 #include "CommonLib/CodingStructure.h"
 
 #define AlfCtx(c) SubCtx( Ctx::ctbAlfFlag, c )
+#if JVET_M0427_INLOOP_RESHAPER
+std::vector<double> EncAdaptiveLoopFilter::m_lumaLevelToWeightPLUT;
+#endif
 
 EncAdaptiveLoopFilter::EncAdaptiveLoopFilter()
   : m_CABACEstimator( nullptr )
@@ -55,6 +58,10 @@ EncAdaptiveLoopFilter::EncAdaptiveLoopFilter()
   m_filterCoeffQuant = nullptr;
   m_filterCoeffSet = nullptr;
   m_diffFilterCoeff = nullptr;
+
+#if JVET_M0427_INLOOP_RESHAPER
+  m_alfWSSD = 0;
+#endif
 }
 
 void EncAdaptiveLoopFilter::create( const int picWidth, const int picHeight, const ChromaFormat chromaFormatIDC, const int maxCUWidth, const int maxCUHeight, const int maxCUDepth, const int inputBitDepth[MAX_NUM_CHANNEL_TYPE], const int internalBitDepth[MAX_NUM_CHANNEL_TYPE] )
@@ -515,7 +522,7 @@ double EncAdaptiveLoopFilter::getFilterCoeffAndCost( CodingStructure& cs, double
     uiSliceFlag = lengthTruncatedUnary(alfChromaIdc, 3);
   }
 
-  double rate = uiCoeffBits + uiSliceFlag;  
+  double rate = uiCoeffBits + uiSliceFlag;
   m_CABACEstimator->resetBits();
   m_CABACEstimator->codeAlfCtuEnableFlags( cs, channel, &m_alfSliceParamTemp);
   rate += FracBitsScale * (double)m_CABACEstimator->getEstFracBits();
@@ -528,7 +535,7 @@ int EncAdaptiveLoopFilter::getCoeffRate( AlfSliceParam& alfSliceParam, bool isCh
   if( !isChroma )
   {
     iBits++;                                               // alf_coefficients_delta_flag
-    if( !alfSliceParam.coeffDeltaFlag )
+    if( !alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       if( alfSliceParam.numLumaFilters > 1 )
       {
@@ -546,7 +553,7 @@ int EncAdaptiveLoopFilter::getCoeffRate( AlfSliceParam& alfSliceParam, bool isCh
   // vlc for all
   for( int ind = 0; ind < numFilters; ++ind )
   {
-    if( isChroma || !alfSliceParam.coeffDeltaFlag || alfSliceParam.filterCoeffFlag[ind] )
+    if( isChroma || !alfSliceParam.alfLumaCoeffDeltaFlag || alfSliceParam.alfLumaCoeffFlag[ind] )
     {
       for( int i = 0; i < alfShape.numCoeff - 1; i++ )
       {
@@ -576,7 +583,7 @@ int EncAdaptiveLoopFilter::getCoeffRate( AlfSliceParam& alfSliceParam, bool isCh
 
   if( !isChroma )
   {
-    if( alfSliceParam.coeffDeltaFlag )
+    if( alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       iBits += numFilters;             //filter_coefficient_flag[i]
     }
@@ -585,7 +592,7 @@ int EncAdaptiveLoopFilter::getCoeffRate( AlfSliceParam& alfSliceParam, bool isCh
   // Filter coefficients
   for( int ind = 0; ind < numFilters; ++ind )
   {
-    if( !isChroma && !alfSliceParam.filterCoeffFlag[ind] && alfSliceParam.coeffDeltaFlag )
+    if( !isChroma && !alfSliceParam.alfLumaCoeffFlag[ind] && alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       continue;
     }
@@ -652,7 +659,7 @@ double EncAdaptiveLoopFilter::mergeFiltersAndCost( AlfSliceParam& alfSliceParam,
     dist = deriveFilterCoeffs( covFrame, covMerged, alfShape, m_filterIndices[numFilters - 1], numFilters, errorForce0CoeffTab );
     // filter coeffs are stored in m_filterCoeffSet
     distForce0 = getDistForce0( alfShape, numFilters, errorForce0CoeffTab, codedVarBins );
-    coeffBits = deriveFilterCoefficientsPredictionMode( alfShape, m_filterCoeffSet, m_diffFilterCoeff, numFilters, predMode ); 
+    coeffBits = deriveFilterCoefficientsPredictionMode( alfShape, m_filterCoeffSet, m_diffFilterCoeff, numFilters, predMode );
     coeffBitsForce0 = getCostFilterCoeffForce0( alfShape, m_filterCoeffSet, numFilters, codedVarBins );
 
     cost = dist + m_lambda[COMPONENT_Y] * coeffBits;
@@ -685,17 +692,17 @@ double EncAdaptiveLoopFilter::mergeFiltersAndCost( AlfSliceParam& alfSliceParam,
   if (cost <= cost0)
   {
     distReturn = dist;
-    alfSliceParam.coeffDeltaFlag = 0;
+    alfSliceParam.alfLumaCoeffDeltaFlag = 0;
     uiCoeffBits = coeffBits;
-    alfSliceParam.coeffDeltaPredModeFlag = bestPredMode;
+    alfSliceParam.alfLumaCoeffDeltaPredictionFlag = bestPredMode;
   }
   else
   {
     distReturn = distForce0;
-    alfSliceParam.coeffDeltaFlag = 1;
+    alfSliceParam.alfLumaCoeffDeltaFlag = 1;
     uiCoeffBits = coeffBitsForce0;
-    memcpy( alfSliceParam.filterCoeffFlag, codedVarBins, sizeof( codedVarBins ) );
-    alfSliceParam.coeffDeltaPredModeFlag = 0;
+    memcpy( alfSliceParam.alfLumaCoeffFlag, codedVarBins, sizeof( codedVarBins ) );
+    alfSliceParam.alfLumaCoeffDeltaPredictionFlag = 0;
 
     for( int varInd = 0; varInd < numFiltersBest; varInd++ )
     {
@@ -710,7 +717,7 @@ double EncAdaptiveLoopFilter::mergeFiltersAndCost( AlfSliceParam& alfSliceParam,
   {
     for( int i = 0; i < alfShape.numCoeff; i++ )
     {
-      if( alfSliceParam.coeffDeltaPredModeFlag )
+      if( alfSliceParam.alfLumaCoeffDeltaPredictionFlag )
       {
         alfSliceParam.lumaCoeff[ind * MAX_NUM_ALF_LUMA_COEFF + i] = m_diffFilterCoeff[ind][i];
       }
@@ -1146,7 +1153,7 @@ double EncAdaptiveLoopFilter::deriveCoeffQuant( int *filterCoeffQuant, double **
   filterCoeffQuant[numCoeff - 1] = -quantCoeffSum;
   filterCoeff[numCoeff - 1] = filterCoeffQuant[numCoeff - 1] / double(factor);
 
-  
+
   //Restrict the range of the center coefficient
   int max_value_center = (2 * factor - 1) - factor;
   int min_value_center = 0 - factor;
@@ -1472,16 +1479,44 @@ void EncAdaptiveLoopFilter::getBlkStats( AlfCovariance* alfCovariace, const AlfF
         classIdx = cl.classIdx;
       }
 
+#if JVET_M0427_INLOOP_RESHAPER
+      double weight = 1.0;
+      if (m_alfWSSD)
+      {
+        weight = m_lumaLevelToWeightPLUT[org[j]];
+      }
+#endif
       int yLocal = org[j] - rec[j];
       calcCovariance( ELocal, rec + j, recStride, shape.pattern.data(), shape.filterLength >> 1, transposeIdx );
       for( int k = 0; k < shape.numCoeff; k++ )
       {
         for( int l = k; l < shape.numCoeff; l++ )
         {
+#if JVET_M0427_INLOOP_RESHAPER
+          if (m_alfWSSD)
+          {
+            alfCovariace[classIdx].E[k][l] += weight * (double)(ELocal[k] * ELocal[l]);
+          }
+          else
+#endif
           alfCovariace[classIdx].E[k][l] += ELocal[k] * ELocal[l];
         }
+#if JVET_M0427_INLOOP_RESHAPER
+        if (m_alfWSSD)
+        {
+          alfCovariace[classIdx].y[k] += weight * (double)(ELocal[k] * yLocal);
+        }
+        else
+#endif
         alfCovariace[classIdx].y[k] += ELocal[k] * yLocal;
       }
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_alfWSSD)
+      {
+        alfCovariace[classIdx].pixAcc += weight * (double)(yLocal * yLocal);
+      }
+      else
+#endif
       alfCovariace[classIdx].pixAcc += yLocal * yLocal;
     }
     org += orgStride;
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
index da36a50e59e89898e8c54a547238fcf818ee80b7..1a0a67a4326c062232722c0b7e1dc9583756a6cc 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
@@ -151,6 +151,12 @@ class EncAdaptiveLoopFilter : public AdaptiveLoopFilter
 public:
   static constexpr int   m_MAX_SCAN_VAL = 11;
   static constexpr int   m_MAX_EXP_GOLOMB = 16;
+#if JVET_M0427_INLOOP_RESHAPER
+  int m_alfWSSD;
+  inline void           setAlfWSSD(int alfWSSD) { m_alfWSSD = alfWSSD; }
+  static std::vector<double>  m_lumaLevelToWeightPLUT;
+  inline std::vector<double>& getLumaLevelWeightTable() { return m_lumaLevelToWeightPLUT; }
+#endif
 
 private:
   AlfCovariance***       m_alfCovariance[MAX_NUM_COMPONENT];          // [compIdx][shapeIdx][ctbAddr][classIdx]
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 0fdf461193b496844a0114d1dc5da9f382ac02bf..6a89a07fd3a2aba71fa58e5d17e24ef28b5b8d31 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -215,17 +215,17 @@ protected:
   int       m_FastIntraEMT;
   int       m_FastInterEMT;
 #endif
-  bool      m_LargeCTU;
+#if JVET_M0303_IMPLICIT_MTS
+  int       m_ImplicitMTS;
+#endif
+#if JVET_M0140_SBT
+  bool      m_SBT;                                ///< Sub-Block Transform for inter blocks
+#endif
   int       m_SubPuMvpMode;
   bool      m_Affine;
   bool      m_AffineType;
   bool      m_BIO;
-  bool      m_DisableMotionCompression;
-  unsigned  m_MTTMode;
 
-#if ENABLE_WPP_PARALLELISM
-  bool      m_AltDQPCoding;
-#endif
   bool      m_compositeRefEnabled;        //composite reference
   bool      m_GBi;
   bool      m_GBiFast;
@@ -238,7 +238,21 @@ protected:
 
   bool      m_MHIntra;
   bool      m_Triangle;
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  bool      m_allowDisFracMMVD;
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  bool      m_AffineAmvr;
+#endif
+#if JVET_M0253_HASH_ME
+  bool      m_HashME;
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  bool      m_AffineAmvrEncOpt;
+#endif
+#if JVET_M0147_DMVR
+  bool      m_DMVR;
+#endif
   unsigned  m_IBCMode;
   unsigned  m_IBCLocalSearchRangeX;
   unsigned  m_IBCLocalSearchRangeY;
@@ -246,12 +260,17 @@ protected:
   unsigned  m_IBCHashSearchMaxCand;
   unsigned  m_IBCHashSearchRange4SmallBlk;
   unsigned  m_IBCFastMethod;
-  
+
   bool      m_wrapAround;
   unsigned  m_wrapAroundOffset;
 
   // ADD_NEW_TOOL : (encoder lib) add tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  bool      m_lumaReshapeEnable;
+  unsigned  m_reshapeSignalType;
+  unsigned  m_intraCMD;
+  ReshapeCW m_reshapeCW;
+#endif
   bool      m_useFastLCTU;
   bool      m_useFastMrg;
   bool      m_usePbIntraFast;
@@ -302,8 +321,8 @@ protected:
 
   int       m_chromaCbQpOffset;                 //  Chroma Cb QP Offset (0:default)
   int       m_chromaCrQpOffset;                 //  Chroma Cr Qp Offset (0:default)
-  int       m_chromaCbQpOffsetDualTree;         //  Chroma Cb QP Offset for dual tree 
-  int       m_chromaCrQpOffsetDualTree;         //  Chroma Cr Qp Offset for dual tree 
+  int       m_chromaCbQpOffsetDualTree;         //  Chroma Cb QP Offset for dual tree
+  int       m_chromaCrQpOffsetDualTree;         //  Chroma Cr Qp Offset for dual tree
 #if ER_CHROMA_QP_WCG_PPS
   WCGChromaQPControl m_wcgChromaQpControl;                    ///< Wide-colour-gamut chroma QP control.
 #endif
@@ -547,6 +566,9 @@ protected:
   int         m_switchDQP;                                    ///< dqp applied to  switchPOC and subsequent pictures.
   int         m_fastForwardToPOC;                             ///<
   bool        m_stopAfterFFtoPOC;                             ///<
+#if JVET_M0055_DEBUG_CTU
+  int         m_debugCTU;                                     ///< dbg ctu
+#endif
   bool        m_bs2ModPOCAndType;
 
 
@@ -678,9 +700,6 @@ public:
   void      setDualITree                    ( bool b )       { m_dualITree = b; }
   bool      getDualITree                    ()         const { return m_dualITree; }
 
-  void      setLargeCTU                     ( bool b )       { m_LargeCTU = b; }
-  bool      getLargeCTU                     ()         const { return m_LargeCTU; }
-
   void      setUseLMChroma                  ( int n )        { m_LMChroma = n; }
   int       getUseLMChroma()                           const { return m_LMChroma; }
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
@@ -697,16 +716,6 @@ public:
   bool      getAffineType()                            const { return m_AffineType; }
   void      setBIO(bool b)                                   { m_BIO = b; }
   bool      getBIO()                                   const { return m_BIO; }
-  void      setDisableMotionCompression     ( bool b )       { m_DisableMotionCompression = b; }
-  bool      getDisableMotionCompression     ()         const { return m_DisableMotionCompression; }
-
-
-  void      setMTTMode                      ( unsigned u )   { m_MTTMode = u; }
-  unsigned  getMTTMode                      ()         const { return m_MTTMode; }
-#if ENABLE_WPP_PARALLELISM
-  void      setUseAltDQPCoding              ( bool b )       { m_AltDQPCoding = b; }
-  bool      getUseAltDQPCoding              ()         const { return m_AltDQPCoding; }
-#endif
 
 #if JVET_M0464_UNI_MTS
   void      setIntraMTSMaxCand              ( unsigned u )   { m_IntraMTSMaxCand = u; }
@@ -727,9 +736,14 @@ public:
   void      setInterEMT                     ( bool b )       { m_InterEMT = b; }
   bool      getInterEMT                     ()         const { return m_InterEMT; }
 #endif
-
-
-
+#if JVET_M0303_IMPLICIT_MTS
+  void      setImplicitMTS                  ( bool b )       { m_ImplicitMTS = b; }
+  bool      getImplicitMTS                  ()         const { return m_ImplicitMTS; }
+#endif
+#if JVET_M0140_SBT
+  void      setUseSBT                       ( bool b )       { m_SBT = b; }
+  bool      getUseSBT                       ()         const { return m_SBT; }
+#endif
 
   void      setUseCompositeRef              (bool b)         { m_compositeRefEnabled = b; }
   bool      getUseCompositeRef              ()         const { return m_compositeRefEnabled; }
@@ -754,7 +768,26 @@ public:
   bool      getUseMHIntra                   ()         const { return m_MHIntra; }
   void      setUseTriangle                  ( bool b )       { m_Triangle = b; }
   bool      getUseTriangle                  ()         const { return m_Triangle; }
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  void      setAllowDisFracMMVD             ( bool b )       { m_allowDisFracMMVD = b;    }
+  bool      getAllowDisFracMMVD             ()         const { return m_allowDisFracMMVD; }
+#endif
+#if JVET_M0253_HASH_ME
+  void      setUseHashME                    ( bool b )       { m_HashME = b; }
+  bool      getUseHashME                    ()         const { return m_HashME; }
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  void      setUseAffineAmvr                ( bool b )       { m_AffineAmvr = b;    }
+  bool      getUseAffineAmvr                ()         const { return m_AffineAmvr; }
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  void      setUseAffineAmvrEncOpt          ( bool b )       { m_AffineAmvrEncOpt = b;    }
+  bool      getUseAffineAmvrEncOpt          ()         const { return m_AffineAmvrEncOpt; }
+#endif
+#if JVET_M0147_DMVR
+  void      setDMVR                      ( bool b )       { m_DMVR = b; }
+  bool      getDMVR                      ()         const { return m_DMVR; }
+#endif
 
   void      setIBCMode                      (unsigned n)     { m_IBCMode = n; }
   unsigned  getIBCMode                      ()         const { return m_IBCMode; }
@@ -778,7 +811,16 @@ public:
 
   // ADD_NEW_TOOL : (encoder lib) add access functions here
 
-
+#if JVET_M0427_INLOOP_RESHAPER
+  void      setReshaper                     ( bool b )                   { m_lumaReshapeEnable = b; }
+  bool      getReshaper                     () const                     { return m_lumaReshapeEnable; }
+  void      setReshapeSignalType            ( uint32_t signalType )      { m_reshapeSignalType = signalType; }
+  uint32_t  getReshapeSignalType            () const                     { return m_reshapeSignalType; }
+  void      setReshapeIntraCMD              (uint32_t intraCMD)          { m_intraCMD = intraCMD; }
+  uint32_t  getReshapeIntraCMD              ()                           { return m_intraCMD; }
+  void      setReshapeCW                    (const ReshapeCW &reshapeCW) { m_reshapeCW = reshapeCW; }
+  const ReshapeCW& getReshapeCW             ()                           { return m_reshapeCW; }
+#endif
   void      setMaxCUWidth                   ( uint32_t  u )      { m_maxCUWidth  = u; }
   uint32_t      getMaxCUWidth                   () const         { return m_maxCUWidth; }
   void      setMaxCUHeight                  ( uint32_t  u )      { m_maxCUHeight = u; }
@@ -1420,7 +1462,10 @@ public:
   bool         getStopAfterFFtoPOC()                           const { return m_stopAfterFFtoPOC; }
   void         setBs2ModPOCAndType( bool b )                         { m_bs2ModPOCAndType = b; }
   bool         getBs2ModPOCAndType()                           const { return m_bs2ModPOCAndType; }
-
+#if JVET_M0055_DEBUG_CTU
+  void         setDebugCTU( int i )                                  { m_debugCTU = i; }
+  int          getDebugCTU()                                   const { return m_debugCTU; }
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
   void         setNumSplitThreads( int n )                           { m_numSplitThreads = n; }
@@ -1441,5 +1486,5 @@ public:
 };
 
 //! \}
-  
+
 #endif // !defined(AFX_TENCCFG_H__6B99B797_F4DA_4E46_8E78_7656339A6C41__INCLUDED_)
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 2b41fcb861b2322aa96914164e4b886e52868414..e26650fdcb7264ce6a71245a40fd37f26762f365 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -64,6 +64,19 @@ extern std::recursive_mutex g_cache_mutex;
 // ====================================================================================================================
 // Constructor / destructor / create / destroy
 // ====================================================================================================================
+#if JVET_M0883_TRIANGLE_SIGNALING
+const TriangleMotionInfo  EncCu::m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS] =
+{
+  TriangleMotionInfo( 0, 1, 0 ), TriangleMotionInfo( 1, 0, 1 ), TriangleMotionInfo( 1, 0, 2 ), TriangleMotionInfo( 0, 0, 1 ), TriangleMotionInfo( 0, 2, 0 ),
+  TriangleMotionInfo( 1, 0, 3 ), TriangleMotionInfo( 1, 0, 4 ), TriangleMotionInfo( 1, 1, 0 ), TriangleMotionInfo( 0, 3, 0 ), TriangleMotionInfo( 0, 4, 0 ),
+  TriangleMotionInfo( 0, 0, 2 ), TriangleMotionInfo( 0, 1, 2 ), TriangleMotionInfo( 1, 1, 2 ), TriangleMotionInfo( 0, 0, 4 ), TriangleMotionInfo( 0, 0, 3 ),
+  TriangleMotionInfo( 0, 1, 3 ), TriangleMotionInfo( 0, 1, 4 ), TriangleMotionInfo( 1, 1, 4 ), TriangleMotionInfo( 1, 1, 3 ), TriangleMotionInfo( 1, 2, 1 ),
+  TriangleMotionInfo( 1, 2, 0 ), TriangleMotionInfo( 0, 2, 1 ), TriangleMotionInfo( 0, 4, 3 ), TriangleMotionInfo( 1, 3, 0 ), TriangleMotionInfo( 1, 3, 2 ),
+  TriangleMotionInfo( 1, 3, 4 ), TriangleMotionInfo( 1, 4, 0 ), TriangleMotionInfo( 1, 3, 1 ), TriangleMotionInfo( 1, 2, 3 ), TriangleMotionInfo( 1, 4, 1 ),
+  TriangleMotionInfo( 0, 4, 1 ), TriangleMotionInfo( 0, 2, 3 ), TriangleMotionInfo( 1, 4, 2 ), TriangleMotionInfo( 0, 3, 2 ), TriangleMotionInfo( 1, 4, 3 ),
+  TriangleMotionInfo( 0, 3, 1 ), TriangleMotionInfo( 0, 2, 4 ), TriangleMotionInfo( 1, 2, 4 ), TriangleMotionInfo( 0, 4, 2 ), TriangleMotionInfo( 0, 3, 4 ),
+};
+#endif
 
 void EncCu::create( EncCfg* encCfg )
 {
@@ -103,6 +116,22 @@ void EncCu::create( EncCfg* encCfg )
         m_pTempMotLUTs[w][h] = new LutMotionCand ;
         m_pBestMotLUTs[w][h] = new LutMotionCand ;
         m_pSplitTempMotLUTs[w][h] = new LutMotionCand;
+#if JVET_M0483_IBC
+        m_pSplitTempMotLUTs[w][h]->currCnt = 0;
+        m_pSplitTempMotLUTs[w][h]->currCntIBC = 0;
+        m_pSplitTempMotLUTs[w][h]->motionCand = nullptr;
+        m_pSplitTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2];
+
+        m_pTempMotLUTs[w][h]->currCnt = 0;
+        m_pTempMotLUTs[w][h]->currCntIBC = 0;
+        m_pTempMotLUTs[w][h]->motionCand = nullptr;
+        m_pTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2];
+
+        m_pBestMotLUTs[w][h]->currCnt = 0;
+        m_pBestMotLUTs[w][h]->currCntIBC = 0;
+        m_pBestMotLUTs[w][h]->motionCand = nullptr;
+        m_pBestMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2];
+#else
         m_pSplitTempMotLUTs[w][h]->currCnt = 0;
         m_pSplitTempMotLUTs[w][h]->motionCand = nullptr;
         m_pSplitTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS];
@@ -114,6 +143,7 @@ void EncCu::create( EncCfg* encCfg )
         m_pBestMotLUTs[w][h]->currCnt = 0;
         m_pBestMotLUTs[w][h]->motionCand = nullptr;
         m_pBestMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS];
+#endif
       }
       else
       {
@@ -147,6 +177,20 @@ void EncCu::create( EncCfg* encCfg )
   {
     m_acRealMergeBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight));
   }
+#if JVET_M0883_TRIANGLE_SIGNALING
+  for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_UNI_CANDS; ui++ )
+  {
+    for( unsigned uj = 0; uj < TRIANGLE_MAX_NUM_UNI_CANDS; uj++ )
+    {
+      if(ui == uj)
+        continue;
+      uint8_t idxBits0 = ui + (ui == TRIANGLE_MAX_NUM_UNI_CANDS - 1 ? 0 : 1);
+      uint8_t candIdx1Enc = uj - (uj > ui ? 1 : 0);
+      uint8_t idxBits1 = candIdx1Enc + (candIdx1Enc == TRIANGLE_MAX_NUM_UNI_CANDS - 2 ? 0 : 1);
+      m_triangleIdxBins[1][ui][uj] = m_triangleIdxBins[0][ui][uj] = 1 + idxBits0 + idxBits1;
+    }
+  }
+#endif
   for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_CANDS; ui++ )
   {
     m_acTriangleWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) );
@@ -205,6 +249,14 @@ void EncCu::destroy()
   delete[] m_pBestMotLUTs; m_pBestMotLUTs = nullptr;
   delete[] m_pTempMotLUTs; m_pTempMotLUTs = nullptr;
 
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+  if (m_tmpStorageLCU)
+  {
+    m_tmpStorageLCU->destroy();
+    delete m_tmpStorageLCU;  m_tmpStorageLCU = nullptr;
+  }
+#endif
+
 #if REUSE_CU_RESULTS
   m_modeCtrl->destroy();
 
@@ -288,11 +340,18 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) )
   m_modeCtrl->init( m_pcEncCfg, m_pcRateCtrl, m_pcRdCost );
 
   m_pcInterSearch->setModeCtrl( m_modeCtrl );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  m_pcIntraSearch->setModeCtrl( m_modeCtrl );
+#endif
   ::memset(m_subMergeBlkSize, 0, sizeof(m_subMergeBlkSize));
   ::memset(m_subMergeBlkNum, 0, sizeof(m_subMergeBlkNum));
   m_prevPOC = MAX_UINT;
 
+#if  JVET_M0255_FRACMMVD_SWITCH
+  if ( ( m_pcEncCfg->getIBCHashSearch() && m_pcEncCfg->getIBCMode() ) || m_pcEncCfg->getAllowDisFracMMVD() )
+#else
   if (m_pcEncCfg->getIBCHashSearch() && m_pcEncCfg->getIBCMode())
+#endif
   {
     m_ibcHashMap.init(m_pcEncCfg->getSourceWidth(), m_pcEncCfg->getSourceHeight());
   }
@@ -304,10 +363,20 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) )
 
 void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[], const int currQP[] )
 {
-  if (m_pcEncCfg->getIBCHashSearch() && ctuRsAddr == 0 && cs.slice->getSPS()->getSpsNext().getIBCMode())
+#if !JVET_M0255_FRACMMVD_SWITCH
+  if (m_pcEncCfg->getIBCHashSearch() && ctuRsAddr == 0 && cs.slice->getSPS()->getIBCMode())
   {
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getSPS()->getUseReshaper() && m_pcReshape->getCTUFlag())
+      cs.picture->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+#endif
     m_ibcHashMap.rebuildPicHashMap(cs.picture->getOrigBuf());
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getSPS()->getUseReshaper() && m_pcReshape->getCTUFlag())
+      cs.picture->getOrigBuf().copyFrom(cs.picture->getTrueOrigBuf());
+#endif
   }
+#endif
   m_modeCtrl->initCTUEncoding( *cs.slice );
 
 #if ENABLE_SPLIT_PARALLELISM
@@ -331,6 +400,10 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
   partitioner->initCtu( area, CH_L, *cs.slice );
   if (m_pcEncCfg->getIBCMode())
   {
+    if (area.lx() == 0 && area.ly() == 0)
+    {
+      m_pcInterSearch->resetIbcSearch();
+    }
     m_pcInterSearch->resetCtuRecord();
     m_ctuIbcSearchRangeX = m_pcEncCfg->getIBCLocalSearchRangeX();
     m_ctuIbcSearchRangeY = m_pcEncCfg->getIBCLocalSearchRangeY();
@@ -343,7 +416,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
       m_ctuIbcSearchRangeX >>= 1;
       m_ctuIbcSearchRangeY >>= 1;
     }
+#if JVET_M0483_IBC
+    if (cs.slice->getNumRefIdx(REF_PIC_LIST_0) > 0)
+#else
     if (cs.slice->getNumRefIdx(REF_PIC_LIST_0) > 1)
+#endif
     {
       m_ctuIbcSearchRangeX >>= 1;
       m_ctuIbcSearchRangeY >>= 1;
@@ -371,7 +448,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
   );
 
   // all signals were already copied during compression if the CTU was split - at this point only the structures are copied to the top level CS
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1;
+#else
   const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1 && KEEP_PRED_AND_RESI_SIGNALS;
+#endif
   cs.useSubStructure( *bestCS, partitioner->chType, CS::getArea( *bestCS, area, partitioner->chType ), copyUnsplitCTUSignals, false, false, copyUnsplitCTUSignals );
   cs.slice->copyMotionLUTs(bestMotCandLUTs, cs.slice->getMotionLUTs());
 
@@ -392,7 +473,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
       , bestMotCandLUTs
     );
 
+#if JVET_M0427_INLOOP_RESHAPER
+    const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1;
+#else
     const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1 && KEEP_PRED_AND_RESI_SIGNALS;
+#endif
     cs.useSubStructure( *bestCS, partitioner->chType, CS::getArea( *bestCS, area, partitioner->chType ), copyUnsplitCTUSignals, false, false, copyUnsplitCTUSignals );
   }
 
@@ -620,7 +705,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
   const unsigned wIdx = gp_sizeIdxInfo->idxFrom( partitioner.currArea().lwidth()  );
 
   const UnitArea currCsArea = clipArea( CS::getArea( *bestCS, bestCS->area, partitioner.chType ), *tempCS->picture );
+#if JVET_M0483_IBC
+  if (m_pImvTempCS && (!slice.isIntra() || slice.getSPS()->getIBCFlag()))
+#else
   if( m_pImvTempCS && !slice.isIntra() )
+#endif
   {
     tempCS->initSubStructure( *m_pImvTempCS[wIdx], partitioner.chType, partitioner.currArea(), false );
   }
@@ -628,6 +717,15 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
   tempCS->chType = partitioner.chType;
   bestCS->chType = partitioner.chType;
   m_modeCtrl->initCULevel( partitioner, *tempCS );
+#if JVET_M0140_SBT
+  if( partitioner.currQtDepth == 0 && partitioner.currMtDepth == 0 && !tempCS->slice->isIntra() && ( sps.getUseSBT() || sps.getUseInterMTS() ) )
+  {
+    auto slsSbt = dynamic_cast<SaveLoadEncInfoSbt*>( m_modeCtrl );
+    int maxSLSize = sps.getUseSBT() ? tempCS->slice->getSPS()->getMaxSbtSize() : MTS_INTER_MAX_CU_SIZE;
+    slsSbt->resetSaveloadSbt( maxSLSize );
+  }
+  m_sbtCostSave[0] = m_sbtCostSave[1] = MAX_DOUBLE;
+#endif
 
   m_CurrCtx->start = m_CABACEstimator->getCtx();
 
@@ -645,7 +743,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
     m_modeCtrl->finishCULevel( partitioner );
     return;
   }
+#if JVET_M0483_IBC
+  if ((!slice.isIntra() || slice.getSPS()->getIBCFlag())
+#else
   if (!slice.isIntra()
+#endif
     && tempCS->chType == CHANNEL_TYPE_LUMA
     )
   {
@@ -662,6 +764,9 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
 #if JVET_M0170_MRG_SHARELIST
   int startShareThisLevel = 0;
 #endif
+#if JVET_M0246_AFFINE_AMVR
+  m_pcInterSearch->resetSavedAffineMotion();
+#endif
 
   do
   {
@@ -673,9 +778,8 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
       const Position lumaRefPos(chromaCentral.x << getComponentScaleX(COMPONENT_Cb, tempCS->area.chromaFormat), chromaCentral.y << getComponentScaleY(COMPONENT_Cb, tempCS->area.chromaFormat));
       const CodingStructure* baseCS = bestCS->picture->cs;
       const CodingUnit* colLumaCu = baseCS->getCU(lumaRefPos, CHANNEL_TYPE_LUMA);
-      const TransformUnit*  tu = baseCS->getTU(lumaRefPos, CHANNEL_TYPE_LUMA);
 
-      if (colLumaCu && tu)
+      if (colLumaCu)
       {
         currTestMode.qp = colLumaCu->qp;
       }
@@ -707,14 +811,32 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
     {
       if( ( currTestMode.opts & ETO_IMV ) != 0 )
       {
+#if JVET_M0246_AFFINE_AMVR
+        tempCS->bestCS = bestCS;
+        xCheckRDCostInterIMV( tempCS, bestCS, partitioner, currTestMode );
+        tempCS->bestCS = nullptr;
+#else
         xCheckRDCostInterIMV(tempCS, bestCS, partitioner, currTestMode);
+#endif
       }
       else
       {
+#if JVET_M0246_AFFINE_AMVR
+        tempCS->bestCS = bestCS;
         xCheckRDCostInter( tempCS, bestCS, partitioner, currTestMode );
+        tempCS->bestCS = nullptr;
+#else
+        xCheckRDCostInter( tempCS, bestCS, partitioner, currTestMode );
+#endif
       }
 
     }
+#if JVET_M0253_HASH_ME
+    else if (currTestMode.type == ETM_HASH_INTER)
+    {
+      xCheckRDCostHashInter( tempCS, bestCS, partitioner, currTestMode );
+    }
+#endif
     else if( currTestMode.type == ETM_AFFINE )
     {
       xCheckRDCostAffineMerge2Nx2N( tempCS, bestCS, partitioner, currTestMode );
@@ -794,14 +916,25 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
 
   // QP from last processed CU for further processing
   bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp;
-  if (!slice.isIntra() 
+#if JVET_M0483_IBC
+  if ((!slice.isIntra() || slice.getSPS()->getIBCFlag())
+#else
+  if (!slice.isIntra()
+#endif
     && bestCS->chType == CHANNEL_TYPE_LUMA
-    && bestCS->cus.size() == 1 && bestCS->cus.back()->predMode == MODE_INTER 
+#if JVET_M0483_IBC
+    && bestCS->cus.size() == 1 && (bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC)
+#else
+    && bestCS->cus.size() == 1 && bestCS->cus.back()->predMode == MODE_INTER
+#endif
     && bestCS->area.Y() == (*bestCS->cus.back()).Y()
     )
   {
     bestCS->slice->updateMotionLUTs(bestMotCandLUTs, (*bestCS->cus.back()));
   }
+#if JVET_M0427_INLOOP_RESHAPER
+  bestCS->picture->getPredBuf(currCsArea).copyFrom(bestCS->getPredBuf(currCsArea));
+#endif
   bestCS->picture->getRecoBuf( currCsArea ).copyFrom( bestCS->getRecoBuf( currCsArea ) );
   m_modeCtrl->finishCULevel( partitioner );
 
@@ -904,7 +1037,10 @@ void EncCu::updateLambda (Slice* slice, const int dQP, const bool updateRdCostLa
 #else
   m_pcTrQuant->setLambda (newLambda);
 #endif
-  if (updateRdCostLambda) m_pcRdCost->setLambda (newLambda, slice->getSPS()->getBitDepths());
+  if (updateRdCostLambda)
+  {
+    m_pcRdCost->setLambda (newLambda, slice->getSPS()->getBitDepths());
+  }
 #endif
 }
 #endif
@@ -1183,6 +1319,10 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
   m_CurrCtx++;
 
   tempCS->getRecoBuf().fill( 0 );
+
+#if JVET_M0427_INLOOP_RESHAPER
+  tempCS->getPredBuf().fill(0);
+#endif
   AffineMVInfo tmpMVInfo;
   bool isAffMVInfoSaved;
   m_pcInterSearch->savePrevAffMVInfo(0, tmpMVInfo, isAffMVInfoSaved);
@@ -1257,7 +1397,7 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
 
   partitioner.exitCurrSplit();
 
-#if JVET_M0170_MRG_SHARELIST 
+#if JVET_M0170_MRG_SHARELIST
   if (startShareThisLevel == 1)
   {
     m_shareState = NO_SHARE;
@@ -1366,7 +1506,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
   if (isAffMVInfoSaved)
     m_pcInterSearch->addAffMVInfo(tmpMVInfo);
 
+#if JVET_M0483_IBC
+  if ((!slice.isIntra() || slice.getSPS()->getIBCFlag())
+#else
   if (!slice.isIntra()
+#endif
     && tempCS->chType == CHANNEL_TYPE_LUMA
     )
   {
@@ -1395,9 +1539,16 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
 #if !JVET_M0464_UNI_MTS
   const CodingUnit *bestCU    = bestCS->getCU( partitioner.chType );
   const int maxSizeEMT        = EMT_INTRA_MAX_CU_WITH_QTBT;
-  uint8_t considerEmtSecondPass = ( sps.getSpsNext().getUseIntraEMT() && isLuma( partitioner.chType ) && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT ) ? 1 : 0;
+  uint8_t considerEmtSecondPass = ( sps.getUseIntraEMT() && isLuma( partitioner.chType ) && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT ) ? 1 : 0;
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  bool   useIntraSubPartitions   = false;
+  double maxCostAllowedForChroma = MAX_DOUBLE;
+#if JVET_M0464_UNI_MTS
+  const  CodingUnit *bestCU      = bestCS->getCU( partitioner.chType );
+#endif
+#endif
   Distortion interHad = m_modeCtrl->getInterHad();
 
 
@@ -1438,6 +1589,9 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
 #if !JVET_M0464_UNI_MTS
     cu.emtFlag          = emtCuFlag;
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    cu.ispMode          = NOT_INTRA_SUBPARTITIONS;
+#endif
 
     CU::addPUs( cu );
 
@@ -1445,7 +1599,24 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
 
     if( isLuma( partitioner.chType ) )
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      //the Intra SubPartitions mode uses the value of the best cost so far (luma if it is the fast version) to avoid test non-necessary lines
+      const double bestCostSoFar = CS::isDualITree( *tempCS ) ? m_modeCtrl->getBestCostWithoutSplitFlags() : bestCU && bestCU->predMode == MODE_INTRA ? bestCS->lumaCost : bestCS->cost;
+      m_pcIntraSearch->estIntraPredLumaQT( cu, partitioner, bestCostSoFar );
+
+      useIntraSubPartitions = cu.ispMode != NOT_INTRA_SUBPARTITIONS;
+      if( !CS::isDualITree( *tempCS ) )
+      {
+        tempCS->lumaCost = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
+        if( useIntraSubPartitions )
+        {
+          //the difference between the best cost so far and the current luma cost is stored to avoid testing the Cr component if the cost of luma + Cb is larger than the best cost
+          maxCostAllowedForChroma = bestCS->cost < MAX_DOUBLE ? bestCS->cost - tempCS->lumaCost : MAX_DOUBLE;
+        }
+      }
+#else
       m_pcIntraSearch->estIntraPredLumaQT( cu, partitioner );
+#endif
 
       if (m_pcEncCfg->getUsePbIntraFast() && tempCS->dist == std::numeric_limits<Distortion>::max()
           && tempCS->interHad == 0)
@@ -1463,12 +1634,29 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
       if( !CS::isDualITree( *tempCS ) )
       {
         cu.cs->picture->getRecoBuf( cu.Y() ).copyFrom( cu.cs->getRecoBuf( COMPONENT_Y ) );
+#if JVET_M0427_INLOOP_RESHAPER
+        cu.cs->picture->getPredBuf(cu.Y()).copyFrom(cu.cs->getPredBuf(COMPONENT_Y));
+#endif
       }
     }
 
     if( tempCS->area.chromaFormat != CHROMA_400 && ( partitioner.chType == CHANNEL_TYPE_CHROMA || !CS::isDualITree( *tempCS ) ) )
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      TUIntraSubPartitioner subTuPartitioner( partitioner );
+      m_pcIntraSearch->estIntraPredChromaQT( cu, ( !useIntraSubPartitions || ( CS::isDualITree( *cu.cs ) && !isLuma( CHANNEL_TYPE_CHROMA ) ) ) ? partitioner : subTuPartitioner, maxCostAllowedForChroma );
+      if( useIntraSubPartitions && !cu.ispMode )
+      {
+        //At this point the temp cost is larger than the best cost. Therefore, we can already skip the remaining calculations
+#if JVET_M0464_UNI_MTS
+        return;
+#else
+        continue;
+#endif
+      }
+#else
       m_pcIntraSearch->estIntraPredChromaQT( cu, partitioner );
+#endif
     }
 
     cu.rootCbf = false;
@@ -1486,7 +1674,11 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
       m_CABACEstimator->cu_transquant_bypass_flag( cu );
     }
 
-    if( !cu.cs->slice->isIntra() 
+#if JVET_M0483_IBC
+    if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getIBCFlag())
+#else
+    if( !cu.cs->slice->isIntra()
+#endif
       && cu.Y().valid()
       )
     {
@@ -1494,6 +1686,9 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
     }
     m_CABACEstimator->pred_mode      ( cu );
     m_CABACEstimator->extend_ref_line( cu );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    m_CABACEstimator->isp_mode       ( cu );
+#endif
     m_CABACEstimator->cu_pred_data   ( cu );
     m_CABACEstimator->pcm_data       ( cu, partitioner );
 
@@ -1506,10 +1701,22 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
     tempCS->fracBits = m_CABACEstimator->getEstFracBits();
     tempCS->cost     = m_pcRdCost->calcRdCost(tempCS->fracBits, tempCS->dist);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+#if !JVET_M0464_UNI_MTS
+    double bestIspCost = cu.ispMode ? CS::isDualITree(*tempCS) ? tempCS->cost : tempCS->lumaCost : MAX_DOUBLE;
+#endif
+    const double tmpCostWithoutSplitFlags = tempCS->cost;
+#endif
     xEncodeDontSplit( *tempCS, partitioner );
 
     xCheckDQP( *tempCS, partitioner );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( tempCS->cost < bestCS->cost )
+    {
+      m_modeCtrl->setBestCostWithoutSplitFlags( tmpCostWithoutSplitFlags );
+    }
+#endif
 #if !JVET_M0464_UNI_MTS
     // we save the cost of the modes for the first EMT pass
     if( !emtCuFlag ) static_cast< double& >( costSize2Nx2NemtFirstPass ) = tempCS->cost;
@@ -1523,6 +1730,22 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
     xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
 
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    //we decide to skip the second emt pass or not according to the ISP results
+    if (considerEmtSecondPass && cu.ispMode && !emtCuFlag && tempCS->slice->isIntra())
+    {
+      double bestCostDct2NoIsp = m_modeCtrl->getEmtFirstPassNoIspCost();
+      CHECKD(bestCostDct2NoIsp <= bestIspCost, "wrong cost!");
+      double nSamples = (double)(cu.lwidth() << g_aucLog2[cu.lheight()]);
+      double threshold = 1 + 1.4 / sqrt(nSamples);
+      if (bestCostDct2NoIsp > bestIspCost*threshold)
+      {
+        skipSecondEmtPass = true;
+        m_modeCtrl->setSkipSecondEMTPass(true);
+        break;
+      }
+    }
+#endif
     //now we check whether the second pass of SIZE_2Nx2N and the whole Intra SIZE_NxN should be skipped or not
     if( !emtCuFlag && !tempCS->slice->isIntra() && bestCU && bestCU->predMode != MODE_INTRA && m_pcEncCfg->getFastInterEMT() )
     {
@@ -1572,7 +1795,11 @@ void EncCu::xCheckIntraPCM(CodingStructure *&tempCS, CodingStructure *&bestCS, P
     m_CABACEstimator->cu_transquant_bypass_flag( cu );
   }
 
-  if( !cu.cs->slice->isIntra() 
+#if JVET_M0483_IBC
+  if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getIBCFlag())
+#else
+  if( !cu.cs->slice->isIntra()
+#endif
     && cu.Y().valid()
     )
   {
@@ -1692,7 +1919,58 @@ void EncCu::xFillPCMBuffer( CodingUnit &cu )
     }
   }
 }
+#if JVET_M0253_HASH_ME
+void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
+{
+  bool isPerfectMatch = false;
+
+  tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
+  m_pcInterSearch->resetBufferedUniMotions();
+  m_pcInterSearch->setAffineModeSelected(false);
+  CodingUnit &cu = tempCS->addCU(tempCS->area, partitioner.chType);
 
+  partitioner.setCUData(cu);
+  cu.slice = tempCS->slice;
+  cu.skip = false;
+  cu.predMode = MODE_INTER;
+  cu.transQuantBypass = encTestMode.lossless;
+  cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
+  cu.qp = encTestMode.qp;
+#if !JVET_M0483_IBC
+  cu.ibc = false;
+#endif
+  CU::addPUs(cu);
+  cu.mmvdSkip = false;
+  cu.firstPU->mmvdMergeFlag = false;
+
+  if (m_pcInterSearch->predInterHashSearch(cu, partitioner, isPerfectMatch))
+  {
+    const unsigned wIdx = gp_sizeIdxInfo->idxFrom(tempCS->area.lwidth());
+    double equGBiCost = MAX_DOUBLE;
+
+#if JVET_M0464_UNI_MTS
+    xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0
+      , m_pImvTempCS ? m_pImvTempCS[wIdx] : NULL
+      , 0
+      , &equGBiCost
+#else
+    xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0
+      , m_pImvTempCS ? m_pImvTempCS[wIdx] : NULL
+      , 1
+      , 0
+      , &equGBiCost
+#endif
+    );
+  }
+  tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
+
+  if (cu.lwidth() != 64)
+  {
+    isPerfectMatch = false;
+  }
+  m_modeCtrl->setIsHashPerfectMatch(isPerfectMatch);
+}
+#endif
 
 void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
 {
@@ -1711,6 +1989,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     mergeCtx.subPuMvpMiBuf    = MotionBuf( m_SubPuMiBuf,    bufSize );
   }
 
+#if JVET_M0147_DMVR
+  Mv   refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS];
+#endif
   setMergeBestSATDCost( MAX_DOUBLE );
 
   {
@@ -1777,12 +2058,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
   static_vector<unsigned, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList2; // store the Intra mode for Intrainter
   RdModeList2.clear();
-  bool isIntrainterEnabled = sps.getSpsNext().getUseMHIntra();
+  bool isIntrainterEnabled = sps.getUseMHIntra();
   if (bestCS->area.lwidth() * bestCS->area.lheight() < 64 || bestCS->area.lwidth() >= MAX_CU_SIZE || bestCS->area.lheight() >= MAX_CU_SIZE)
   {
     isIntrainterEnabled = false;
   }
-  bool isTestSkipMerge[MRG_MAX_NUM_CANDS]; // record if the merge candidate has tried skip mode 
+  bool isTestSkipMerge[MRG_MAX_NUM_CANDS]; // record if the merge candidate has tried skip mode
   for (uint32_t idx = 0; idx < MRG_MAX_NUM_CANDS; idx++)
   {
     isTestSkipMerge[idx] = false;
@@ -1798,7 +2079,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
     if( auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >( m_modeCtrl ) )
     {
-      if (slice.getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC
+      if (slice.getSPS()->getIBCFlag())
+#else
+      if (slice.getSPS()->getIBCMode())
+#endif
       {
         ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx();
         bestIsSkip = blkCache->isSkip(tempCS->area) && cuECtx.bestCU;
@@ -1848,27 +2133,55 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       m_pcRdCost->setDistParam (distParam, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth (CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
 
       const UnitArea localUnitArea( tempCS->area.chromaFormat, Area( 0, 0, tempCS->area.Y().width, tempCS->area.Y().height) );
+#if JVET_M0483_IBC==0
       uint32_t ibcCand = 0;
       uint32_t numValidMv = mergeCtx.numValidMergeCand;
+#endif
       for( uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++ )
       {
+#if JVET_M0483_IBC==0
         if ((mergeCtx.interDirNeighbours[uiMergeCand] == 1 || mergeCtx.interDirNeighbours[uiMergeCand] == 3) && tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[uiMergeCand << 1].refIdx)->getPOC() == tempCS->slice->getPOC())
         {
           ibcCand++;
           numValidMv--;
           continue;
         }
+#endif
         mergeCtx.setMergeInfo( pu, uiMergeCand );
 
         PU::spanMotionInfo( pu, mergeCtx );
+#if JVET_M0147_DMVR
+        pu.mvRefine = true;
+#endif
         distParam.cur = singleMergeTempBuffer->Y();
         m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
         acMergeBuffer[uiMergeCand] = m_acRealMergeBuffer[uiMergeCand].getBuf(localUnitArea);
         acMergeBuffer[uiMergeCand].copyFrom(*singleMergeTempBuffer);
+#if JVET_M0147_DMVR
+        pu.mvRefine = false;
+#endif
         if( mergeCtx.interDirNeighbours[uiMergeCand] == 3 && mergeCtx.mrgTypeNeighbours[uiMergeCand] == MRG_TYPE_DEFAULT_N )
         {
           mergeCtx.mvFieldNeighbours[2*uiMergeCand].mv   = pu.mv[0];
           mergeCtx.mvFieldNeighbours[2*uiMergeCand+1].mv = pu.mv[1];
+#if JVET_M0147_DMVR
+          {
+            int dx, dy, i, j, num = 0;
+            dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT);
+            dx = std::min<int>(pu.lumaSize().width, DMVR_SUBCU_WIDTH);
+            if (PU::checkDMVRCondition(pu))
+            {
+              for (i = 0; i < (pu.lumaSize().height); i += dy)
+              {
+                for (j = 0; j < (pu.lumaSize().width); j += dx)
+                {
+                  refinedMvdL0[num][uiMergeCand] = pu.mvdL0SubPu[num];
+                  num++;
+                }
+              }
+            }
+          }
+#endif
         }
 
         Distortion uiSad = distParam.distFunc(distParam);
@@ -1896,13 +2209,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
           }
         }
+#if JVET_M0483_IBC==0
         CHECK(std::min(uiMergeCand + 1 - ibcCand, uiNumMrgSATDCand) != RdModeList.size(), "");
+#else
+        CHECK(std::min(uiMergeCand + 1, uiNumMrgSATDCand) != RdModeList.size(), "");
+#endif
       }
+#if JVET_M0483_IBC==0
       if (numValidMv < uiNumMrgSATDCand)
         uiNumMrgSATDCand = numValidMv;
       if (numValidMv == 0)
         return;
-
+#endif
 
       if (isIntrainterEnabled)
       {
@@ -1919,11 +2237,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
         // save the to-be-tested merge candidates
         uint32_t MHIntraMergeCand[NUM_MRG_SATD_CAND];
+#if JVET_M0483_IBC==0
         for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, (const int) uiNumMrgSATDCand); mergeCnt++)
+#else
+        for (uint32_t mergeCnt = 0; mergeCnt < NUM_MRG_SATD_CAND; mergeCnt++)
+#endif
         {
           MHIntraMergeCand[mergeCnt] = RdModeList[mergeCnt];
         }
+#if JVET_M0483_IBC==0
         for (uint32_t mergeCnt = 0; mergeCnt < std::min( std::min(NUM_MRG_SATD_CAND, (const int)uiNumMrgSATDCand), 4); mergeCnt++)
+#else
+        for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, 4); mergeCnt++)
+#endif
         {
           uint32_t mergeCand = MHIntraMergeCand[mergeCnt];
           acMergeBuffer[mergeCand] = m_acRealMergeBuffer[mergeCand].getBuf(localUnitArea);
@@ -1963,11 +2289,29 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
               m_pcIntraSearch->switchBuffer(pu, COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
             }
             pu.cs->getPredBuf(pu).copyFrom(acMergeBuffer[mergeCand]);
+#if JVET_M0427_INLOOP_RESHAPER
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+              pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT());
+            }
+#endif
             m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
 
             // calculate cost
+#if JVET_M0427_INLOOP_RESHAPER
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+               pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getInvLUT());
+            }
+#endif
             distParam.cur = pu.cs->getPredBuf(pu).Y();
             Distortion sadValue = distParam.distFunc(distParam);
+#if JVET_M0427_INLOOP_RESHAPER
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+              pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT());
+            }
+#endif
             m_CABACEstimator->getCtx() = SubCtx(Ctx::MHIntraPredMode, ctxStartIntraMode);
             uint64_t fracModeBits = m_pcIntraSearch->xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
             double cost = (double)sadValue + (double)(bitsCand + 1) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
@@ -1996,7 +2340,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       cu.mmvdSkip = true;
       int tempNum = 0;
       tempNum = MMVD_ADD_NUM;
+#if !JVET_M0823_MMVD_ENCOPT
       bool allowDirection[4] = { true, true, true, true };
+#endif
       for (uint32_t mergeCand = mergeCtx.numValidMergeCand; mergeCand < mergeCtx.numValidMergeCand + tempNum; mergeCand++)
       {
         const int mmvdMergeCand = mergeCand - mergeCtx.numValidMergeCand;
@@ -2006,9 +2352,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         int bitsCand = 0;
         int baseIdx;
         int refineStep;
+#if !JVET_M0823_MMVD_ENCOPT
         int direction;
+#endif
         baseIdx = mmvdMergeCand / MMVD_MAX_REFINE_NUM;
         refineStep = (mmvdMergeCand - (baseIdx * MMVD_MAX_REFINE_NUM)) / 4;
+#if !JVET_M0823_MMVD_ENCOPT
         direction = (mmvdMergeCand - baseIdx * MMVD_MAX_REFINE_NUM - refineStep * 4) % 4;
         if (refineStep == 0)
         {
@@ -2018,6 +2367,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         {
           continue;
         }
+#endif
         bitsBaseIdx = baseIdx + 1;
         if (baseIdx == MMVD_BASE_MV_NUM - 1)
         {
@@ -2036,14 +2386,29 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand);
 
         PU::spanMotionInfo(pu, mergeCtx);
+#if JVET_M0147_DMVR
+        pu.mvRefine = true;
+#endif
         distParam.cur = singleMergeTempBuffer->Y();
+#if JVET_M0823_MMVD_ENCOPT
+        pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1);
+        CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set");
+        // Don't do chroma MC here
+        m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false);
+        pu.mmvdEncOptMode = 0;
+#else
         m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
-
+#endif
+#if JVET_M0147_DMVR // store the refined MV
+        pu.mvRefine = false;
+#endif
         Distortion uiSad = distParam.distFunc(distParam);
 
 
         double cost = (double)uiSad + (double)bitsCand * sqrtLambdaForFirstPass;
+#if !JVET_M0823_MMVD_ENCOPT
         allowDirection[direction] = cost >  1.3 * candCostList[0] ? 0 : 1;
+#endif
         insertPos = -1;
         updateDoubleCandList(mergeCand, cost, RdModeList, candCostList, RdModeList2, (uint32_t)NUM_LUMA_MODE, uiNumMrgSATDCand, &insertPos);
         if (insertPos != -1)
@@ -2106,21 +2471,37 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     }
   }
 
+#if !JVET_M0253_HASH_ME
   const uint32_t iteration = encTestMode.lossless ? 1 : 2;
 
   // 2. Pass: check candidates using full RD test
   for( uint32_t uiNoResidualPass = 0; uiNoResidualPass < iteration; uiNoResidualPass++ )
+#else
+  uint32_t iteration;
+  uint32_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
+  if (encTestMode.lossless)
+  {
+    iteration = 1;
+    iterationBegin = 0;
+  }
+  else
+  {
+    iteration = 2;
+  }
+  for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
+#endif
   {
     for( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
     {
       uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];
 
-
+#if JVET_M0483_IBC==0
       if(uiMergeCand < mergeCtx.numValidMergeCand)
         if ((mergeCtx.interDirNeighbours[uiMergeCand] == 1 || mergeCtx.interDirNeighbours[uiMergeCand] == 3) && tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[uiMergeCand << 1].refIdx)->getPOC() == tempCS->slice->getPOC())
         {
           continue;
         }
+#endif
 
       if (uiNoResidualPass != 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM)) // intrainter does not support skip mode
       {
@@ -2181,11 +2562,35 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
       if( mrgTempBufSet )
       {
+#if JVET_M0147_DMVR
+        {
+          int dx, dy, i, j, num = 0;
+          dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT);
+          dx = std::min<int>(pu.lumaSize().width, DMVR_SUBCU_WIDTH);
+          if (PU::checkDMVRCondition(pu))
+          {
+            for (i = 0; i < (pu.lumaSize().height); i += dy)
+            {
+              for (j = 0; j < (pu.lumaSize().width); j += dx)
+              {
+                pu.mvdL0SubPu[num] = refinedMvdL0[num][uiMergeCand];
+                num++;
+              }
+            }
+          }
+        }
+#endif
         if (pu.mhIntraFlag)
         {
           uint32_t bufIdx = (pu.intraDir[0] > 1) ? (pu.intraDir[0] == HOR_IDX ? 2 : 3) : pu.intraDir[0];
           PelBuf tmpBuf = tempCS->getPredBuf(pu).Y();
           tmpBuf.copyFrom(acMergeBuffer[uiMergeCand].Y());
+#if JVET_M0427_INLOOP_RESHAPER
+          if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+          {
+            tmpBuf.rspSignal(m_pcReshape->getFwdLUT());
+          }
+#endif
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, bufIdx));
           tmpBuf = tempCS->getPredBuf(pu).Cb();
           tmpBuf.copyFrom(acMergeBuffer[uiMergeCand].Cb());
@@ -2196,6 +2601,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
         else
         {
+#if JVET_M0823_MMVD_ENCOPT
+          if (uiMergeCand >= mergeCtx.numValidMergeCand && uiMergeCand < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM) {
+            pu.mmvdEncOptMode = 0;
+            m_pcInterSearch->motionCompensation(pu);
+          }
+          else
+#endif
           if (uiNoResidualPass != 0 && uiMergeCand < mergeCtx.numValidMergeCand && RdModeList[uiMrgHADIdx] >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM))
           {
             tempCS->getPredBuf().copyFrom(acMergeBuffer[uiMergeCand]);
@@ -2208,8 +2620,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       }
       else
       {
+#if JVET_M0147_DMVR
+        pu.mvRefine = true;
+#endif
         m_pcInterSearch->motionCompensation( pu );
-        
+#if JVET_M0147_DMVR
+        pu.mvRefine = false;
+#endif
       }
       if (!cu.mmvdSkip && !pu.mhIntraFlag && uiNoResidualPass != 0)
       {
@@ -2272,9 +2689,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
   const SPS &sps = *tempCS->sps;
 
   CHECK( slice.getSliceType() != B_SLICE, "Triangle mode is only applied to B-slices" );
-  
+
   tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
-  
+
   bool trianglecandHasNoResidual[TRIANGLE_MAX_NUM_CANDS];
   for( int mergeCand = 0; mergeCand < TRIANGLE_MAX_NUM_CANDS; mergeCand++ )
   {
@@ -2331,7 +2748,7 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
       triangleBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea);
       triangleMrgCtx.setMergeInfo( pu, mergeCand );
       PU::spanMotionInfo( pu, triangleMrgCtx );
-      
+
       m_pcInterSearch->motionCompensation( pu, triangleBuffer[mergeCand] );
     }
   }
@@ -2348,7 +2765,7 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
   else
   {
     CodingUnit &cu      = tempCS->addCU( tempCS->area, partitioner.chType );
-      
+
     partitioner.setCUData( cu );
     cu.slice            = tempCS->slice;
 #if HEVC_TILES_WPP
@@ -2364,7 +2781,7 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     cu.GBiIdx           = GBI_DEFAULT;
 
     PredictionUnit &pu  = tempCS->addPU( cu, partitioner.chType );
-      
+
     if( abs(g_aucLog2[cu.lwidth()] - g_aucLog2[cu.lheight()]) >= 2 )
     {
       numTriangleCandidate = 30;
@@ -2376,23 +2793,42 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
     for( uint8_t mergeCand = 0; mergeCand < numTriangleCandidate; mergeCand++ )
     {
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool    splitDir = m_triangleModeTest[mergeCand].m_splitDir;
+      uint8_t candIdx0 = m_triangleModeTest[mergeCand].m_candIdx0;
+      uint8_t candIdx1 = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
       bool    splitDir = g_triangleCombination[mergeCand][0];
       uint8_t candIdx0 = g_triangleCombination[mergeCand][1];
       uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
+#endif
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+      pu.triangleSplitDir = splitDir;
+      pu.triangleMergeIdx0 = candIdx0;
+      pu.triangleMergeIdx1 = candIdx1;
+#else
       pu.mergeIdx  = mergeCand;
+#endif
       pu.mergeFlag = true;
       triangleWeightedBuffer[mergeCand] = m_acTriangleWeightedBuffer[mergeCand].getBuf( localUnitArea );
       triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
       triangleBuffer[candIdx1] = m_acMergeBuffer[candIdx1].getBuf( localUnitArea );
 
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+      m_pcInterSearch->weightedTriangleBlk( pu, splitDir, CHANNEL_TYPE_LUMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
+#else
       m_pcInterSearch->weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, CHANNEL_TYPE_LUMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
-      
+#endif
       distParam.cur = triangleWeightedBuffer[mergeCand].Y();
 
       Distortion uiSad = distParam.distFunc( distParam );
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+      uint32_t uiBitsCand = m_triangleIdxBins[splitDir][candIdx0][candIdx1];
+#else
       uint32_t uiBitsCand = g_triangleIdxBins[mergeCand];
+#endif
 
       double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
 
@@ -2401,7 +2837,7 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
         , *nullList, -1
         , triangleNumMrgSATDCand );
     }
-        
+
     // limit number of candidates using SATD-costs
     for( uint8_t i = 0; i < triangleNumMrgSATDCand; i++ )
     {
@@ -2416,22 +2852,53 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     for( uint8_t i = 0; i < triangleNumMrgSATDCand; i++ )
     {
       uint8_t  mergeCand = triangleRdModeList[i];
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool     splitDir  = m_triangleModeTest[mergeCand].m_splitDir;
+      uint8_t  candIdx0  = m_triangleModeTest[mergeCand].m_candIdx0;
+      uint8_t  candIdx1  = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
       bool     splitDir  = g_triangleCombination[mergeCand][0];
       uint8_t  candIdx0  = g_triangleCombination[mergeCand][1];
       uint8_t  candIdx1  = g_triangleCombination[mergeCand][2];
-        
+#endif
+
+#if JVET_M0883_TRIANGLE_SIGNALING
+      pu.triangleSplitDir = splitDir;
+      pu.triangleMergeIdx0 = candIdx0;
+      pu.triangleMergeIdx1 = candIdx1;
+#else
       pu.mergeIdx  = mergeCand;
+#endif
       pu.mergeFlag = true;
-                
+
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+      m_pcInterSearch->weightedTriangleBlk( pu, splitDir, CHANNEL_TYPE_CHROMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
+#else
       m_pcInterSearch->weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, CHANNEL_TYPE_CHROMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
+#endif
     }
 
     tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
   }
 
   {
+#if !JVET_M0253_HASH_ME
     const uint8_t iteration = encTestMode.lossless ? 1 : 2;
     for( uint8_t noResidualPass = 0; noResidualPass < iteration; noResidualPass++ )
+#else
+    uint8_t iteration;
+    uint8_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
+    if (encTestMode.lossless)
+    {
+      iteration = 1;
+      iterationBegin = 0;
+    }
+    else
+    {
+      iteration = 2;
+    }
+    for (uint8_t noResidualPass = iterationBegin; noResidualPass < iteration; ++noResidualPass)
+#endif
     {
       for( uint8_t mrgHADIdx = 0; mrgHADIdx < triangleNumMrgSATDCand; mrgHADIdx++ )
       {
@@ -2443,9 +2910,15 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
           continue;
         }
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        bool    splitDir = m_triangleModeTest[mergeCand].m_splitDir;
+        uint8_t candIdx0 = m_triangleModeTest[mergeCand].m_candIdx0;
+        uint8_t candIdx1 = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
         bool    splitDir = g_triangleCombination[mergeCand][0];
         uint8_t candIdx0 = g_triangleCombination[mergeCand][1];
         uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
+#endif
 
         CodingUnit &cu = tempCS->addCU(tempCS->area, partitioner.chType);
 
@@ -2464,10 +2937,20 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
         cu.GBiIdx   = GBI_DEFAULT;
         PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        pu.triangleSplitDir = splitDir;
+        pu.triangleMergeIdx0 = candIdx0;
+        pu.triangleMergeIdx1 = candIdx1;
+#else
         pu.mergeIdx = mergeCand;
+#endif
         pu.mergeFlag = true;
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        PU::spanTriangleMotionInfo(pu, triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#else
         PU::spanTriangleMotionInfo(pu, triangleMrgCtx, mergeCand, splitDir, candIdx0, candIdx1 );
+#endif
 
         if( tempBufSet )
         {
@@ -2478,9 +2961,13 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
           triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
           triangleBuffer[candIdx1] = m_acMergeBuffer[candIdx1].getBuf( localUnitArea );
           PelUnitBuf predBuf         = tempCS->getPredBuf();
+#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
+          m_pcInterSearch->weightedTriangleBlk( pu, splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
+#else
           m_pcInterSearch->weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
+#endif
         }
-        
+
 #if JVET_M0464_UNI_MTS
         xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, NULL, ( noResidualPass == 0 ? &trianglecandHasNoResidual[mergeCand] : NULL ) );
 #else
@@ -2493,7 +2980,7 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
         }
         tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
       }// end loop mrgHADIdx
-    }   
+    }
   }
 }
 
@@ -2644,9 +3131,9 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
           uiBitsCand--;
         }
         double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
-        static_vector<int, AFFINE_MRG_MAX_NUM_CANDS> * nullList = nullptr;
+        static_vector<int, AFFINE_MRG_MAX_NUM_CANDS> emptyList;
         updateCandList( uiMergeCand, cost, RdModeList, candCostList
-          , *nullList, -1
+          , emptyList, -1
           , uiNumMrgSATDCand );
 
         CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );
@@ -2670,10 +3157,25 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     }
   }
 
+#if !JVET_M0253_HASH_ME
   const uint32_t iteration = encTestMode.lossless ? 1 : 2;
 
   // 2. Pass: check candidates using full RD test
   for ( uint32_t uiNoResidualPass = 0; uiNoResidualPass < iteration; uiNoResidualPass++ )
+#else
+  uint32_t iteration;
+  uint32_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
+  if (encTestMode.lossless)
+  {
+    iteration = 1;
+    iterationBegin = 0;
+  }
+  else
+  {
+    iteration = 2;
+  }
+  for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
+#endif
   {
     for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
     {
@@ -2803,8 +3305,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
     // first get merge candidates
     CodingUnit cu(tempCS->area);
     cu.cs = tempCS;
+#if JVET_M0483_IBC
+    cu.predMode = MODE_IBC;
+#else
     cu.predMode = MODE_INTER;
     cu.ibc = true;
+#endif
     cu.slice = tempCS->slice;
 #if HEVC_TILES_WPP
     cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
@@ -2819,9 +3325,13 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
     pu.shareParentPos = tempCS->sharedBndPos;
     pu.shareParentSize = tempCS->sharedBndSize;
 #endif
+#if JVET_M0483_IBC
+    PU::getIBCMergeCandidates(pu, mergeCtx);
+#else
     PU::getInterMergeCandidates(pu, mergeCtx
       , 0
     );
+#endif
   }
 
   int candHasNoResidual[MRG_MAX_NUM_CANDS];
@@ -2852,8 +3362,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
 #endif
       cu.skip = false;
+#if JVET_M0483_IBC
+      cu.predMode = MODE_IBC;
+#else
       cu.predMode = MODE_INTER;
       cu.ibc = true;
+#endif
       cu.transQuantBypass = encTestMode.lossless;
       cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
       cu.qp = encTestMode.qp;
@@ -2866,12 +3380,25 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       Picture* refPic = pu.cu->slice->getPic();
       const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
       const Pel*        piRefSrch = refBuf.buf;
+#if JVET_M0427_INLOOP_RESHAPER
+      if (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+      {
+        const CompArea &area = cu.blocks[COMPONENT_Y];
+        CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+        PelBuf tmpLuma = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpLuma.copyFrom(tempCS->getOrgBuf().Y());
+        tmpLuma.rspSignal(m_pcReshape->getFwdLUT());
+        m_pcRdCost->setDistParam(distParam, tmpLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+      }
+      else
+#endif
       m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
       int refStride = refBuf.stride;
       const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
       int numValidBv = mergeCtx.numValidMergeCand;
       for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
       {
+#if JVET_M0483_IBC==0
         if (mergeCtx.interDirNeighbours[mergeCand] != 1)
         {
           numValidBv--;
@@ -2882,6 +3409,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
           numValidBv--;
           continue;
         }
+#endif
         mergeCtx.setMergeInfo(pu, mergeCand); // set bv info in merge mode
         const int cuPelX = pu.Y().x;
         const int cuPelY = pu.Y().y;
@@ -2951,6 +3479,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
     for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++)
     {
       unsigned int mergeCand = RdModeList[mrgHADIdx];
+#if JVET_M0483_IBC==0
       if (mergeCtx.interDirNeighbours[mergeCand] != 1)
       {
         continue;
@@ -2959,6 +3488,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       {
         continue;
       }
+#endif
       if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
       {
         if (!(bestIsSkip && (numResidualPass == 0)))
@@ -2989,14 +3519,21 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
             cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
 #endif
             cu.skip = false;
+#if JVET_M0483_IBC
+            cu.predMode = MODE_IBC;
+#else
             cu.predMode = MODE_INTER;
             cu.ibc = true;
+#endif
             cu.transQuantBypass = encTestMode.lossless;
             cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
             cu.qp = encTestMode.qp;
 #if !JVET_M0464_UNI_MTS
             cu.emtFlag = false;
 #endif
+#if JVET_M0140_SBT
+            cu.sbtInfo = 0;
+#endif
 
             PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);// tempCS->addPU(cu);
             pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
@@ -3062,6 +3599,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
 void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
 {
+  if (tempCS->area.lwidth() > IBC_MAX_CAND_SIZE || tempCS->area.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip
+  {
+    return;
+  }
+
     tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
 
     CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
@@ -3072,12 +3614,21 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
     cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
 #endif
     cu.skip = false;
+#if JVET_M0483_IBC
+    cu.predMode = MODE_IBC;
+#else
     cu.predMode = MODE_INTER;
+#endif
     cu.transQuantBypass = encTestMode.lossless;
     cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
     cu.qp = encTestMode.qp;
+#if JVET_M0483_IBC==0
     cu.ibc = true;
+#endif
     cu.imv = 0;
+#if JVET_M0140_SBT
+    cu.sbtInfo = 0;
+#endif
 
     CU::addPUs(cu);
 
@@ -3089,8 +3640,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
     pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
 
     pu.interDir = 1; // use list 0 for IBC mode
+#if JVET_M0483_IBC
+    pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
+#else
     pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list
-
+#endif
 
     if (partitioner.chType == CHANNEL_TYPE_LUMA)
     {
@@ -3254,7 +3808,7 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
 {
   tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
 
-  
+
   m_pcInterSearch->setAffineModeSelected(false);
 
   if( tempCS->slice->getCheckLDC() )
@@ -3265,7 +3819,7 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
 
   m_pcInterSearch->resetBufferedUniMotions();
   int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
-  gbiLoopNum = (tempCS->sps->getSpsNext().getUseGBi() ? gbiLoopNum : 1);
+  gbiLoopNum = (tempCS->sps->getUseGBi() ? gbiLoopNum : 1);
 
   if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
   {
@@ -3403,13 +3957,16 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
   m_pcInterSearch->resetBufferedUniMotions();
   int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
   gbiLoopNum = (pcCUInfo2Reuse != NULL ? 1 : gbiLoopNum);
-  gbiLoopNum = (tempCS->slice->getSPS()->getSpsNext().getUseGBi() ? gbiLoopNum : 1);
+  gbiLoopNum = (tempCS->slice->getSPS()->getUseGBi() ? gbiLoopNum : 1);
 
   if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
   {
     gbiLoopNum = 1;
   }
 
+#if JVET_M0246_AFFINE_AMVR
+  bool validMode = false;
+#endif
   double curBestCost = bestCS->cost;
   double equGBiCost = MAX_DOUBLE;
 
@@ -3481,7 +4038,10 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
 
   bool testGbi;
   uint8_t gbiIdx;
-  
+#if JVET_M0246_AFFINE_AMVR
+  bool affineAmvrEanbledFlag = cu.slice->getSPS()->getAffineAmvrEnabledFlag();
+#endif
+
   if( pcCUInfo2Reuse != nullptr )
   {
     // reuse the motion info from pcCUInfo2Reuse
@@ -3491,7 +4051,11 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
     gbiIdx = CU::getValidGbiIdx(cu);
     testGbi = (gbiIdx != GBI_DEFAULT);
 
+#if JVET_M0246_AFFINE_AMVR
+    if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
+#else
     if( !CU::hasSubCUNonZeroMVd( cu ) )
+#endif
     {
       if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
       {
@@ -3499,7 +4063,19 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
         // store temp best CI for next CU coding
         m_CurrCtx->best = m_CABACEstimator->getCtx();
       }
+#if JVET_M0246_AFFINE_AMVR
+      if ( affineAmvrEanbledFlag )
+      {
+        tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
+        continue;
+      }
+      else
+      {
+        return false;
+      }
+#else
       return false;
+#endif
     }
     else
     {
@@ -3512,9 +4088,24 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
     gbiIdx = cu.GBiIdx;
     testGbi = (gbiIdx != GBI_DEFAULT);
 
+#if JVET_M0246_AFFINE_AMVR
+    cu.firstPU->interDir = 10;
+#endif
+
     m_pcInterSearch->predInterSearch( cu, partitioner );
 
+#if JVET_M0246_AFFINE_AMVR
+    if ( cu.firstPU->interDir <= 3 )
+    {
+      gbiIdx = CU::getValidGbiIdx(cu);
+    }
+    else
+    {
+      return false;
+    }
+#else
     gbiIdx = CU::getValidGbiIdx(cu);
+#endif
   }
 
   if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
@@ -3533,7 +4124,11 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
     }
   }
 
+#if JVET_M0246_AFFINE_AMVR
+  if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
+#else
   if( !CU::hasSubCUNonZeroMVd( cu ) )
+#endif
   {
     if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
     {
@@ -3541,7 +4136,19 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
       // store temp best CI for next CU coding
       m_CurrCtx->best = m_CABACEstimator->getCtx();
     }
+#if JVET_M0246_AFFINE_AMVR
+    if ( affineAmvrEanbledFlag )
+    {
+      tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
+      continue;
+    }
+    else
+    {
+      return false;
+    }
+#else
     return false;
+#endif
   }
 
 #if JVET_M0464_UNI_MTS
@@ -3578,9 +4185,16 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
   {
     break;
   }
+#if JVET_M0246_AFFINE_AMVR
+  validMode = true;
+#endif
  } // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
 
+#if JVET_M0246_AFFINE_AMVR
+  return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
+#else
   return true;
+#endif
 }
 
 #if JVET_M0464_UNI_MTS
@@ -3609,6 +4223,11 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
   CodingUnit*            cu        = tempCS->getCU( partitioner.chType );
   double   bestCostInternal        = MAX_DOUBLE;
   double           bestCost        = bestCS->cost;
+#if JVET_M0140_SBT
+  double           bestCostBegin   = bestCS->cost;
+  CodingUnit*      prevBestCU      = bestCS->getCU( partitioner.chType );
+  uint8_t          prevBestSbt     = ( prevBestCU == nullptr ) ? 0 : prevBestCU->sbtInfo;
+#endif
 #if !JVET_M0464_UNI_MTS
   const SPS&            sps        = *tempCS->sps;
   const int      maxSizeEMT        = EMT_INTER_MAX_CU_WITH_QTBT;
@@ -3616,7 +4235,7 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
   bool              swapped        = false; // avoid unwanted data copy
   bool             reloadCU        = false;
 #if !JVET_M0464_UNI_MTS
-  const bool considerEmtSecondPass = emtMode && sps.getSpsNext().getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
+  const bool considerEmtSecondPass = emtMode && sps.getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
 
   int minEMTMode = 0;
   int maxEMTMode = (considerEmtSecondPass?1:0);
@@ -3649,6 +4268,51 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
       }
     }
   }
+#if JVET_M0140_SBT
+  const bool mtsAllowed = tempCS->sps->getUseInterMTS() && partitioner.currArea().lwidth() <= MTS_INTER_MAX_CU_SIZE && partitioner.currArea().lheight() <= MTS_INTER_MAX_CU_SIZE;
+  uint8_t sbtAllowed = cu->checkAllowedSbt();
+  uint8_t numRDOTried = 0;
+  Distortion sbtOffDist = 0;
+  bool    sbtOffRootCbf = 0;
+  double  sbtOffCost      = MAX_DOUBLE;
+  double  currBestCost = MAX_DOUBLE;
+  bool    doPreAnalyzeResi = ( sbtAllowed || mtsAllowed ) && residualPass == 0;
+
+  m_pcInterSearch->initTuAnalyzer();
+  if( doPreAnalyzeResi )
+  {
+    m_pcInterSearch->calcMinDistSbt( *tempCS, *cu, sbtAllowed );
+  }
+
+  auto    slsSbt = dynamic_cast<SaveLoadEncInfoSbt*>( m_modeCtrl );
+  int     slShift = 4 + std::min( (int)gp_sizeIdxInfo->idxFrom( cu->lwidth() ) + (int)gp_sizeIdxInfo->idxFrom( cu->lheight() ), 9 );
+  Distortion curPuSse = m_pcInterSearch->getEstDistSbt( NUMBER_SBT_MODE );
+  uint8_t currBestSbt = 0;
+  uint8_t currBestTrs = MAX_UCHAR;
+  uint8_t histBestSbt = MAX_UCHAR;
+  uint8_t histBestTrs = MAX_UCHAR;
+  m_pcInterSearch->setHistBestTrs( MAX_UCHAR, MAX_UCHAR );
+  if( doPreAnalyzeResi )
+  {
+    if( m_pcInterSearch->getSkipSbtAll() && !mtsAllowed ) //emt is off
+    {
+      histBestSbt = 0; //try DCT2
+      m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
+    }
+    else
+    {
+      assert( curPuSse != std::numeric_limits<uint64_t>::max() );
+      uint16_t compositeSbtTrs = slsSbt->findBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ) );
+      histBestSbt = ( compositeSbtTrs >> 0 ) & 0xff;
+      histBestTrs = ( compositeSbtTrs >> 8 ) & 0xff;
+      if( m_pcInterSearch->getSkipSbtAll() && CU::isSbtMode( histBestSbt ) ) //special case, skip SBT when loading SBT
+      {
+        histBestSbt = 0; //try DCT2
+      }
+      m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
+    }
+  }
+#endif
 
 #if !JVET_M0464_UNI_MTS
   if( emtMode == 2 )
@@ -3692,14 +4356,24 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
 #if !JVET_M0464_UNI_MTS
     cu->emtFlag = curEmtMode;
 #endif
+#if JVET_M0140_SBT
+    cu->sbtInfo = 0;
+#endif
 
     const bool skipResidual = residualPass == 1;
+#if JVET_M0140_SBT // skip DCT-2 and EMT if historical best transform mode is SBT
+    if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) )
+    {
+#endif
     m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
-
+#if JVET_M0140_SBT
+    numRDOTried += mtsAllowed ? 2 : 1;
+#endif
     xEncodeDontSplit( *tempCS, partitioner );
 
     xCheckDQP( *tempCS, partitioner );
 
+#if !JVET_M0140_SBT //harmonize with GBI fast algorithm (move the code to the end of this function)
     if( ETM_INTER_ME == encTestMode.type )
     {
       if( equGBiCost != NULL )
@@ -3729,6 +4403,7 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
         }
       }
     }
+#endif
 
 #if !JVET_M0464_UNI_MTS
     double emtFirstPassCost = tempCS->cost;
@@ -3756,6 +4431,18 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
         return;
       }
     }
+#if JVET_M0140_SBT
+    currBestCost = tempCS->cost;
+    sbtOffCost = tempCS->cost;
+    sbtOffDist = tempCS->dist;
+    sbtOffRootCbf = cu->rootCbf;
+    currBestSbt = CU::getSbtInfo( cu->firstTU->mtsIdx > 1 ? SBT_OFF_MTS : SBT_OFF_DCT, 0 );
+    currBestTrs = cu->firstTU->mtsIdx;
+    if( cu->lwidth() <= MAX_TU_SIZE_FOR_PROFILE && cu->lheight() <= MAX_TU_SIZE_FOR_PROFILE )
+    {
+      CHECK( tempCS->tus.size() != 1, "tu must be only one" );
+    }
+#endif
 
 #if WCG_EXT
     DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
@@ -3773,13 +4460,205 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
 
       const bool bCond3 = emtFirstPassCost > ( bestCost * thresholdToSkipEmtSecondPass );
 
-      if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) ) 
+      if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) )
       {
         maxEMTMode = 0; // do not test EMT
       }
     }
+#endif
+#if JVET_M0140_SBT // skip DCT-2 and EMT
+    }
+#endif
+
+#if JVET_M0140_SBT //RDO for SBT
+    uint8_t numSbtRdo = CU::numSbtModeRdo( sbtAllowed );
+    //early termination if all SBT modes are not allowed
+    //normative
+    if( !sbtAllowed || skipResidual )
+    {
+      numSbtRdo = 0;
+    }
+    //fast algorithm
+    if( ( histBestSbt != MAX_UCHAR && !CU::isSbtMode( histBestSbt ) ) || m_pcInterSearch->getSkipSbtAll() )
+    {
+      numSbtRdo = 0;
+    }
+    if( bestCost != MAX_DOUBLE && sbtOffCost != MAX_DOUBLE )
+    {
+      double th = 1.07;
+      if( !( prevBestSbt == 0 || m_sbtCostSave[0] == MAX_DOUBLE ) )
+      {
+        assert( m_sbtCostSave[1] <= m_sbtCostSave[0] );
+        th *= ( m_sbtCostSave[0] / m_sbtCostSave[1] );
+      }
+      if( sbtOffCost > bestCost * th )
+      {
+        numSbtRdo = 0;
+      }
+    }
+    if( !sbtOffRootCbf && sbtOffCost != MAX_DOUBLE )
+    {
+      double th = Clip3( 0.05, 0.55, ( 27 - cu->qp ) * 0.02 + 0.35 );
+      if( sbtOffCost < m_pcRdCost->calcRdCost( ( cu->lwidth() * cu->lheight() ) << SCALE_BITS, 0 ) * th )
+      {
+        numSbtRdo = 0;
+      }
+    }
+
+    if( histBestSbt != MAX_UCHAR && numSbtRdo != 0 )
+    {
+      numSbtRdo = 1;
+      m_pcInterSearch->initSbtRdoOrder( CU::getSbtMode( CU::getSbtIdx( histBestSbt ), CU::getSbtPos( histBestSbt ) ) );
+    }
+
+    for( int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++ )
+    {
+      uint8_t sbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx );
+      uint8_t sbtIdx = CU::getSbtIdxFromSbtMode( sbtMode );
+      uint8_t sbtPos = CU::getSbtPosFromSbtMode( sbtMode );
+
+      //fast algorithm (early skip, save & load)
+      if( histBestSbt == MAX_UCHAR )
+      {
+        uint8_t skipCode = m_pcInterSearch->skipSbtByRDCost( cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf );
+        if( skipCode != MAX_UCHAR )
+        {
+          continue;
+        }
+
+        if( sbtModeIdx > 0 )
+        {
+          uint8_t prevSbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx - 1 );
+          //make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable)
+          if( CU::isSameSbtSize( prevSbtMode, sbtMode ) )
+          {
+            Distortion currEstDist = m_pcInterSearch->getEstDistSbt( sbtMode );
+            Distortion prevEstDist = m_pcInterSearch->getEstDistSbt( prevSbtMode );
+            if( currEstDist > prevEstDist * 1.15 )
+            {
+              continue;
+            }
+          }
+        }
+      }
+
+      //init tempCS and TU
+      if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
+      {
+        tempCS->clearTUs();
+      }
+      else if( false == swapped )
+      {
+        tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
+        tempCS->copyStructure( *bestCS, partitioner.chType );
+        tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
+        bestCost = bestCS->cost;
+        cu = tempCS->getCU( partitioner.chType );
+        swapped = true;
+      }
+      else
+      {
+        tempCS->clearTUs();
+        bestCost = bestCS->cost;
+        cu = tempCS->getCU( partitioner.chType );
+      }
+
+      //we need to restart the distortion for the new tempCS, the bit count and the cost
+      tempCS->dist = 0;
+      tempCS->fracBits = 0;
+      tempCS->cost = MAX_DOUBLE;
+      cu->skip = false;
+
+      //set SBT info
+      cu->setSbtIdx( sbtIdx );
+      cu->setSbtPos( sbtPos );
+
+      //try residual coding
+      m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
+      numRDOTried++;
+
+      xEncodeDontSplit( *tempCS, partitioner );
+
+      xCheckDQP( *tempCS, partitioner );
+
+      if( imvCS && ( tempCS->cost < imvCS->cost ) )
+      {
+        if( imvCS->cost != MAX_DOUBLE )
+        {
+          imvCS->initStructData( encTestMode.qp, encTestMode.lossless );
+        }
+        imvCS->copyStructure( *tempCS, partitioner.chType );
+      }
+
+      if( NULL != bestHasNonResi && ( bestCostInternal > tempCS->cost ) )
+      {
+        bestCostInternal = tempCS->cost;
+        if( !( tempCS->getPU( partitioner.chType )->mhIntraFlag ) )
+          *bestHasNonResi = !cu->rootCbf;
+      }
+
+      if( tempCS->cost < currBestCost )
+      {
+        currBestSbt = cu->sbtInfo;
+        currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->mtsIdx;
+        assert( currBestTrs == 0 || currBestTrs == 1 );
+        currBestCost = tempCS->cost;
+      }
+
+#if WCG_EXT
+      DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
+#else
+      DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
+#endif
+      xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
+    }
+
+    if( bestCostBegin != bestCS->cost )
+    {
+      m_sbtCostSave[0] = sbtOffCost;
+      m_sbtCostSave[1] = currBestCost;
+    }
 #endif
   } //end emt loop
+
+#if JVET_M0140_SBT
+  if( histBestSbt == MAX_UCHAR && doPreAnalyzeResi && numRDOTried > 1 )
+  {
+    slsSbt->saveBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ), currBestSbt, currBestTrs );
+  }
+#endif
+#if JVET_M0140_SBT //harmonize with GBI fast algorithm (move the code here)
+  tempCS->cost = currBestCost;
+  if( ETM_INTER_ME == encTestMode.type )
+  {
+    if( equGBiCost != NULL )
+    {
+      if( tempCS->cost < ( *equGBiCost ) && cu->GBiIdx == GBI_DEFAULT )
+      {
+        ( *equGBiCost ) = tempCS->cost;
+      }
+    }
+    else
+    {
+      CHECK( equGBiCost == NULL, "equGBiCost == NULL" );
+    }
+    if( tempCS->slice->getCheckLDC() && !cu->imv && cu->GBiIdx != GBI_DEFAULT && tempCS->cost < m_bestGbiCost[1] )
+    {
+      if( tempCS->cost < m_bestGbiCost[0] )
+      {
+        m_bestGbiCost[1] = m_bestGbiCost[0];
+        m_bestGbiCost[0] = tempCS->cost;
+        m_bestGbiIdx[1] = m_bestGbiIdx[0];
+        m_bestGbiIdx[0] = cu->GBiIdx;
+      }
+      else
+      {
+        m_bestGbiCost[1] = tempCS->cost;
+        m_bestGbiIdx[1] = cu->GBiIdx;
+      }
+    }
+  }
+#endif
 }
 
 
@@ -3851,9 +4730,26 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
       CPelBuf org  = tempCS->getOrgBuf ( compID );
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+        m_pcEncCfg->getReshaper() && (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())))
+#else
       if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
       {
         const CPelBuf orgLuma = tempCS->getOrgBuf(tempCS->area.blocks[COMPONENT_Y]);
+#if JVET_M0427_INLOOP_RESHAPER
+        if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
+        {
+          const CompArea &area = cu.blocks[COMPONENT_Y];
+          CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+          PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf(tmpArea);
+          tmpRecLuma.copyFrom(reco);
+          tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+          finalDistortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+        }
+        else
+#endif
         finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
       }
       else
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index b239ed8baf3e9351f980d0f2c13265898150f27e..bbc3156010ccb34efb75c2b097f3683848304310 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -68,6 +68,16 @@ class EncSlice;
 // ====================================================================================================================
 
 /// CU encoder class
+#if JVET_M0883_TRIANGLE_SIGNALING
+struct TriangleMotionInfo
+{
+  uint8_t   m_splitDir;
+  uint8_t   m_candIdx0;
+  uint8_t   m_candIdx1;
+
+  TriangleMotionInfo ( uint8_t splitDir, uint8_t candIdx0, uint8_t candIdx1 ): m_splitDir(splitDir), m_candIdx0(candIdx0), m_candIdx1(candIdx1) { }
+};
+#endif
 class EncCu
 #if REUSE_CU_RESULTS
   : DecCu
@@ -135,14 +145,23 @@ private:
 #endif
   int                   m_bestGbiIdx[2];
   double                m_bestGbiCost[2];
+#if JVET_M0883_TRIANGLE_SIGNALING
+  static const TriangleMotionInfo  m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS];
+  uint8_t                          m_triangleIdxBins[2][TRIANGLE_MAX_NUM_UNI_CANDS][TRIANGLE_MAX_NUM_UNI_CANDS];
+#endif
 #if SHARP_LUMA_DELTA_QP || ENABLE_QPA_SUB_CTU
   void    updateLambda      ( Slice* slice, const int dQP, const bool updateRdCostLambda );
 #endif
+#if JVET_M0140_SBT
+  double                m_sbtCostSave[2];
+#endif
 
 public:
   /// copy parameters from encoder class
   void  init                ( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int jId = 0 ) );
-
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+  void setDecCuReshaperInEncCU(EncReshape* pcReshape, ChromaFormat chromaFormatIDC) { initDecCuReshaper((Reshape*) pcReshape, chromaFormatIDC); }
+#endif
   /// create internal buffers
   void  create              ( EncCfg* encCfg );
 
@@ -159,6 +178,10 @@ public:
 
   void   setMergeBestSATDCost(double cost) { m_mergeBestSATDCost = cost; }
   double getMergeBestSATDCost()            { return m_mergeBestSATDCost; }
+#if JVET_M0255_FRACMMVD_SWITCH
+  IbcHashMap& getIbcHashMap()              { return m_ibcHashMap;        }
+  EncCfg*     getEncCfg()            const { return m_pcEncCfg;          }
+#endif
 
 #if JVET_M0170_MRG_SHARELIST
   Position shareParentPos;
@@ -192,6 +215,9 @@ protected:
   void xCheckDQP              ( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx = false);
   void xFillPCMBuffer         ( CodingUnit &cu);
 
+#if JVET_M0253_HASH_ME
+  void xCheckRDCostHashInter  ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
+#endif
   void xCheckRDCostAffineMerge2Nx2N
                               ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode );
   void xCheckRDCostInter      ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 0872980a6a75910484f743ffbbd9bd40ef719c8f..fc134aa842f6f4341494d6f4a505b9d481e4a213 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -178,8 +178,33 @@ void EncGOP::init ( EncLib* pcEncLib )
   m_AUWriterIf = pcEncLib->getAUWriterIf();
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_pcCfg->getReshaper())
+  {
+    pcEncLib->getRdCost()->setReshapeInfo(m_pcCfg->getReshapeSignalType(), m_pcCfg->getBitDepth(CHANNEL_TYPE_LUMA));
+    pcEncLib->getRdCost()->initLumaLevelToWeightTableReshape();
+  }
+  else if (m_pcCfg->getLumaLevelToDeltaQPMapping().mode)
+  {
+    pcEncLib->getRdCost()->setReshapeInfo(RESHAPE_SIGNAL_PQ, m_pcCfg->getBitDepth(CHANNEL_TYPE_LUMA));
+    pcEncLib->getRdCost()->initLumaLevelToWeightTableReshape();
+#else
   pcEncLib->getRdCost()->initLumaLevelToWeightTable();
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  }
+  pcEncLib->getALF()->getLumaLevelWeightTable() = pcEncLib->getRdCost()->getLumaLevelWeightTable();
+  int alfWSSD = 0;
+  if (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ )
+  {
+    alfWSSD = 1;
+  }
+  pcEncLib->getALF()->setAlfWSSD(alfWSSD);
+#endif
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshaper = pcEncLib->getReshaper();
+#endif
 }
 
 #if HEVC_VPS
@@ -1207,11 +1232,29 @@ void trySkipOrDecodePicture( bool& decPic, bool& encPic, const EncCfg& cfg, Pict
       else
       {
         // update decode decision
+#if JVET_M0055_DEBUG_CTU
+        bool dbgCTU = cfg.getDebugCTU() != -1 && cfg.getSwitchPOC() == pcPic->getPOC();
+
+        if( ( bDecode1stPart = ( cfg.getSwitchPOC() != pcPic->getPOC() ) || dbgCTU ) && ( bDecode1stPart = tryDecodePicture( pcPic, pcPic->getPOC(), cfg.getDecodeBitstream( 0 ), false, cfg.getDebugCTU(), cfg.getSwitchPOC() ) ) )
+        {
+          if( dbgCTU )
+          {
+            encPic = true;
+            decPic = false;
+            bDecode1stPart = false;
+
+            return;
+          }
+          decPic = bDecode1stPart;
+          return;
+        }
+#else
         if( ( bDecode1stPart = ( cfg.getSwitchPOC() != pcPic->getPOC() )) && ( bDecode1stPart = tryDecodePicture( pcPic, pcPic->getPOC(), cfg.getDecodeBitstream( 0 ), false ) ) )
         {
           decPic = bDecode1stPart;
           return;
         }
+#endif
         else if( pcPic->getPOC() )
         {
           // reset decoder if used and not required any further
@@ -1456,10 +1499,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     {
       pcSlice->setSliceType(I_SLICE);
     }
-    if (pcSlice->getSliceType() == I_SLICE && pcSlice->getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC ==0
+    if (pcSlice->getSliceType() == I_SLICE && pcSlice->getSPS()->getIBCMode())
     {
       pcSlice->setSliceType(P_SLICE);
     }
+#endif
     // Set the nal unit type
     pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
     if(pcSlice->getTemporalLayerNonReferenceFlag())
@@ -1504,7 +1549,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       setNewestBgPOC(pocCurr);
       setLastLTRefPoc(pocCurr);
     }
-    else if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && getLastLTRefPoc() >= 0 && getEncodedLTRef()==false && !getPicBg()->getSpliceFull() && (pocCurr - getLastLTRefPoc()) > (m_pcCfg->getFrameRate() * 2))
+    else if (pcPic->cs->sps->getUseCompositeRef() && getLastLTRefPoc() >= 0 && getEncodedLTRef()==false && !getPicBg()->getSpliceFull() && (pocCurr - getLastLTRefPoc()) > (m_pcCfg->getFrameRate() * 2))
     {
       setUseLTRef(false);
       setPrepareLTRef(false);
@@ -1513,7 +1558,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       setLastLTRefPoc(-1);
     }
 
-    if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && m_picBg->getSpliceFull() && getUseLTRef())
+    if (pcPic->cs->sps->getUseCompositeRef() && m_picBg->getSpliceFull() && getUseLTRef())
     {
       m_pcEncLib->selectReferencePictureSet(pcSlice, pocCurr, iGOPid, m_bgPOC);
     }
@@ -1627,10 +1672,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       pcSlice->setNumRefIdx(REF_PIC_LIST_0, std::min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive, pcSlice->getRPS()->getNumberOfPictures()));
       pcSlice->setNumRefIdx(REF_PIC_LIST_1, std::min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive, pcSlice->getRPS()->getNumberOfPictures()));
     }
-    if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && getPrepareLTRef()) {
+    if (pcPic->cs->sps->getUseCompositeRef() && getPrepareLTRef()) {
       arrangeCompositeReference(pcSlice, rcListPic, pocCurr);
     }
-    if (pcSlice->getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+    if (pcSlice->getSPS()->getIBCMode())
     {
       if (m_pcCfg->getIntraPeriod() > 0 && pcSlice->getPOC() % m_pcCfg->getIntraPeriod() == 0)
       {
@@ -1640,9 +1686,78 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
       pcSlice->setNumRefIdx(REF_PIC_LIST_0, pcSlice->getNumRefIdx(REF_PIC_LIST_0) + 1);
     }
+#endif
     //  Set reference list
     pcSlice->setRefPicList ( rcListPic );
 
+#if JVET_M0253_HASH_ME
+    if (m_pcCfg->getUseHashME())
+    {
+      PicList::iterator iterPic = rcListPic.begin();
+      while (iterPic != rcListPic.end())
+      {
+        Picture* refPic = *(iterPic++);
+
+        if (refPic->poc != pcPic->poc && refPic->referenced)
+        {
+          if (!refPic->getHashMap()->isInitial())
+          {
+            if (refPic->getPOC() == 0)
+            {
+              Pel* picSrc = refPic->getOrigBuf().get(COMPONENT_Y).buf;
+              int stridePic = refPic->getOrigBuf().get(COMPONENT_Y).stride;
+              int picWidth = pcSlice->getSPS()->getPicWidthInLumaSamples();
+              int picHeight = pcSlice->getSPS()->getPicHeightInLumaSamples();
+              int blockSize = 4;
+              int allNum = 0;
+              int simpleNum = 0;
+              for (int j = 0; j <= picHeight - blockSize; j += blockSize)
+              {
+                for (int i = 0; i <= picWidth - blockSize; i += blockSize)
+                {
+                  Pel* curBlock = picSrc + j * stridePic + i;
+                  bool isHorSame = true;
+                  for (int m = 0; m < blockSize&&isHorSame; m++)
+                  {
+                    for (int n = 1; n < blockSize&&isHorSame; n++)
+                    {
+                      if (curBlock[m*stridePic] != curBlock[m*stridePic + n])
+                      {
+                        isHorSame = false;
+                      }
+                    }
+                  }
+                  bool isVerSame = true;
+                  for (int m = 1; m < blockSize&&isVerSame; m++)
+                  {
+                    for (int n = 0; n < blockSize&&isVerSame; n++)
+                    {
+                      if (curBlock[n] != curBlock[m*stridePic + n])
+                      {
+                        isVerSame = false;
+                      }
+                    }
+                  }
+                  allNum++;
+                  if (isHorSame || isVerSame)
+                  {
+                    simpleNum++;
+                  }
+                }
+              }
+
+              if (simpleNum < 0.3*allNum)
+              {
+                m_pcCfg->setUseHashME(false);
+                break;
+              }
+            }
+            refPic->addPictureToHashMapForInter();
+          }
+        }
+      }
+    }
+#endif
     if( m_pcCfg->getUseAMaxBT() )
     {
       if( !pcSlice->isIRAP() )
@@ -1696,10 +1811,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     {
       pcSlice->setSliceType ( P_SLICE );
     }
-    if (pcSlice->getSPS()->getSpsNext().getIBCMode() && pcSlice->getNumRefIdx(REF_PIC_LIST_0) == 1)
+#if JVET_M0483_IBC==0
+    if (pcSlice->getSPS()->getIBCMode() && pcSlice->getNumRefIdx(REF_PIC_LIST_0) == 1)
     {
       m_pcSliceEncoder->setEncCABACTableIdx(P_SLICE);
     }
+#endif
     xUpdateRasInit( pcSlice );
 
     // Do decoding refresh marking if any
@@ -1786,7 +1903,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     }
 
     // disable TMVP when current picture is the only ref picture
-    if (pcSlice->isIRAP() && pcSlice->getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC
+    if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag())
+#else
+    if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCMode())
+#endif
     {
       pcSlice->setEnableTMVPFlag(0);
     }
@@ -1800,7 +1921,8 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     bool bGPBcheck=false;
     if ( pcSlice->getSliceType() == B_SLICE)
     {
-      if (pcSlice->getSPS()->getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+      if (pcSlice->getSPS()->getIBCMode())
       {
         if (pcSlice->getNumRefIdx(RefPicList(0)) - 1 == pcSlice->getNumRefIdx(RefPicList(1)))
         {
@@ -1816,6 +1938,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         }
       }
       else
+#endif
       if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
       {
         bGPBcheck=true;
@@ -2096,6 +2219,109 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       pcSlice->setSliceChromaQpDelta(COMPONENT_Cr, m_pcCfg->getChromaCrQpOffsetDualTree());
       m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp());
     }
+#if JVET_M0427_INLOOP_RESHAPER
+    if (pcSlice->getSPS()->getUseReshaper())
+    {
+      m_pcReshaper->getReshapeCW()->rspTid = pcSlice->getTLayer() + (pcSlice->isIntra() ? 0 : 1);
+      m_pcReshaper->getReshapeCW()->rspSliceQP = pcSlice->getSliceQp();
+
+      m_pcReshaper->setSrcReshaped(false);
+      m_pcReshaper->setRecReshaped(true);
+
+      if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ)
+      {
+#if JVET_M0483_IBC
+        m_pcReshaper->preAnalyzerHDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree());
+#else
+        m_pcReshaper->preAnalyzerHDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree(), m_pcCfg->getIBCMode());
+#endif
+      }
+      else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+      {
+#if JVET_M0483_IBC
+        m_pcReshaper->preAnalyzerSDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree());
+#else
+        m_pcReshaper->preAnalyzerSDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree(), m_pcCfg->getIBCMode());
+#endif
+      }
+      else
+      {
+        THROW("Reshaper for other signal currently not defined!");
+      }
+
+#if JVET_M0483_IBC
+      if (pcSlice->getSliceType() == I_SLICE )
+#else
+      if (pcSlice->getSliceType() == I_SLICE || (pcSlice->getSliceType() == P_SLICE && m_pcCfg->getIBCMode()))
+#endif
+      {
+        if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ)
+        {
+          m_pcReshaper->initLUTfromdQPModel();
+          m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTableChromaMD(m_pcReshaper->getInvLUT());
+        }
+        else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+        {
+          if (m_pcReshaper->getReshapeFlag())
+          {
+            m_pcReshaper->constructReshaperSDR();
+            m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTable(m_pcReshaper->getSliceReshaperInfo(), m_pcReshaper->getWeightTable(), m_pcReshaper->getCWeight());
+          }
+        }
+        else
+        {
+          THROW("Reshaper for other signal currently not defined!");
+        }
+
+        m_pcReshaper->setCTUFlag(false);
+
+        //reshape original signal
+        if (m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
+        {
+          pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());
+          m_pcReshaper->setSrcReshaped(true);
+          m_pcReshaper->setRecReshaped(true);
+        }
+      }
+      else
+      {
+        if (!m_pcReshaper->getReshapeFlag())
+        {
+          m_pcReshaper->setCTUFlag(false);
+        }
+        else
+          m_pcReshaper->setCTUFlag(true);
+
+        m_pcReshaper->getSliceReshaperInfo().setSliceReshapeModelPresentFlag(false);
+
+        if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ)
+        {
+          m_pcEncLib->getRdCost()->restoreReshapeLumaLevelToWeightTable();
+        }
+        else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+        {
+          int modIP = pcPic->getPOC() - pcPic->getPOC() / m_pcCfg->getReshapeCW().rspFpsToIp * m_pcCfg->getReshapeCW().rspFpsToIp;
+          if (m_pcReshaper->getReshapeFlag() && m_pcCfg->getReshapeCW().rspIntraPeriod == -1 && modIP == 0)           // for LDB, update reshaping curve every second
+          {
+            m_pcReshaper->getSliceReshaperInfo().setSliceReshapeModelPresentFlag(true);
+            m_pcReshaper->constructReshaperSDR();
+            m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTable(m_pcReshaper->getSliceReshaperInfo(), m_pcReshaper->getWeightTable(), m_pcReshaper->getCWeight());
+          }
+        }
+        else
+        {
+          THROW("Reshaper for other signal currently not defined!");
+        }
+      }
+
+      m_pcReshaper->copySliceReshaperInfo(pcSlice->getReshapeInfo(), m_pcReshaper->getSliceReshaperInfo());
+    }
+    else
+    {
+      m_pcReshaper->setCTUFlag(false);
+    }
+#endif
+
     if( encPic )
     // now compress (trial encode) the various slice segments (slices, and dependent slices)
     {
@@ -2169,6 +2395,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       CodingStructure& cs = *pcPic->cs;
       pcSlice = pcPic->slices[0];
 
+#if JVET_M0427_INLOOP_RESHAPER
+      if (pcSlice->getSPS()->getUseReshaper() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
+      {
+          CHECK((m_pcReshaper->getRecReshaped() == false), "Rec picture is not reshaped!");
+          pcPic->getRecoBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getInvLUT());
+          m_pcReshaper->setRecReshaped(false);
+
+          pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
+      }
+#endif
+
       // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
       if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() )
       {
@@ -2194,6 +2431,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
       m_pcLoopFilter->loopFilterPic( cs );
 
+#if JVET_M0147_DMVR
+      CS::setRefinedMotionField(cs);
+#endif
       DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 1 ) ) );
 
       if( pcSlice->getSPS()->getSAOEnabledFlag() )
@@ -2235,7 +2475,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
           pcPic->slices[s]->setAlfSliceParam( alfSliceParam );
         }
       }
-      if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && getPrepareLTRef())
+      if (pcPic->cs->sps->getUseCompositeRef() && getPrepareLTRef())
       {
         updateCompositeReference(pcSlice, rcListPic, pocCurr);
       }
@@ -2506,10 +2746,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 0 ) ) );
 
     pcPic->reconstructed = true;
+#if JVET_M0483_IBC ==0
     pcPic->longTerm = false;
+#endif
     m_bFirst = false;
     m_iNumPicCoded++;
-    if (!(pcPic->cs->sps->getSpsNext().getUseCompositeRef() && isEncodeLtRef))
+    if (!(pcPic->cs->sps->getUseCompositeRef() && isEncodeLtRef))
       m_totalCoded ++;
     /* logging: insert a newline at end of picture period */
 
@@ -2535,7 +2777,11 @@ void EncGOP::printOutSummary(uint32_t uiNumAllPicCoded, bool isField, const bool
   const bool    useWPSNR = m_pcEncLib->getUseWPSNR();
 #endif
 #if WCG_WPSNR
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
 #endif
 
   if( m_pcCfg->getDecodeBitstream(0).empty() && m_pcCfg->getDecodeBitstream(1).empty() && !m_pcCfg->useFastForwardToPOC() )
@@ -2574,7 +2820,7 @@ void EncGOP::printOutSummary(uint32_t uiNumAllPicCoded, bool isField, const bool
 
   msg( DETAILS,"\n\nB Slices--------------------------------------------------------\n" );
   m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths);
-  
+
 #if WCG_WPSNR
   if (useLumaWPSNR)
   {
@@ -2876,7 +3122,11 @@ uint64_t EncGOP::xFindDistortionPlane(const CPelBuf& pic0, const CPelBuf& pic1,
 double EncGOP::xFindDistortionPlaneWPSNR(const CPelBuf& pic0, const CPelBuf& pic1, const uint32_t rshift, const CPelBuf& picLuma0,
   ComponentID compID, const ChromaFormat chfmt    )
 {
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
   if (!useLumaWPSNR)
   {
     return 0;
@@ -3009,13 +3259,21 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
   const CPelUnitBuf& pic = cPicD;
   CHECK(!(conversion == IPCOLOURSPACE_UNCHANGED), "Unspecified error");
 //  const CPelUnitBuf& org = (conversion != IPCOLOURSPACE_UNCHANGED) ? pcPic->getPicYuvTrueOrg()->getBuf() : pcPic->getPicYuvOrg()->getBuf();
+#if JVET_M0427_INLOOP_RESHAPER
+  const CPelUnitBuf& org = sps.getUseReshaper() ? pcPic->getTrueOrigBuf() : pcPic->getOrigBuf();
+#else
   const CPelUnitBuf& org = pcPic->getOrigBuf();
+#endif
 #if ENABLE_QPA
   const bool    useWPSNR = m_pcEncLib->getUseWPSNR();
 #endif
   double  dPSNR[MAX_NUM_COMPONENT];
 #if WCG_WPSNR
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
   double  dPSNRWeighted[MAX_NUM_COMPONENT];
   double  MSEyuvframeWeighted[MAX_NUM_COMPONENT];
 #endif
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index ca212145176f7fcf46f251e54abe39d7bfd6de05..e2c11c170105b077021b497b661030ac06930798 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -47,6 +47,9 @@
 #include "CommonLib/NAL.h"
 #include "EncSampleAdaptiveOffset.h"
 #include "EncAdaptiveLoopFilter.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 #include "EncSlice.h"
 #include "VLCWriter.h"
 #include "CABACWriter.h"
@@ -139,6 +142,9 @@ private:
   //--Adaptive Loop filter
   EncSampleAdaptiveOffset*  m_pcSAO;
   EncAdaptiveLoopFilter*    m_pcALF;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*               m_pcReshaper;
+#endif
   RateCtrl*                 m_pcRateCtrl;
   // indicate sequence first
   bool                    m_bSeqFirst;
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 56f49fc8620590b9f275d78e319747df63f7f826..a418140860f7cc143c41f56887269fb1213a1488 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -84,9 +84,9 @@ void EncLib::create ()
 {
   // initialize global variables
   initROM();
-
-
-
+#if JVET_M0253_HASH_ME
+  TComHash::initBlockSizeToIndex();
+#endif
   m_iPOCLast = m_compositeRefEnabled ? -2 : -1;
   // create processing unit classes
   m_cGOPEncoder.        create( );
@@ -136,6 +136,12 @@ void EncLib::create ()
     m_cEncALF.create( getSourceWidth(), getSourceHeight(), m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, m_bitDepth, m_inputBitDepth );
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_lumaReshapeEnable)
+  {
+    m_cReshaper.createEnc( getSourceWidth(), getSourceHeight(), m_maxCUWidth, m_maxCUHeight, m_bitDepth[COMPONENT_Y]);
+  }
+#endif
   if ( m_RCEnableRateControl )
   {
     m_cRateCtrl.init(m_framesToBeEncoded, m_RCTargetBitrate, (int)((double)m_iFrameRate / m_temporalSubsampleRatio + 0.5), m_iGOPSize, m_iSourceWidth, m_iSourceHeight,
@@ -165,6 +171,9 @@ void EncLib::destroy ()
   m_cEncSAO.            destroy();
   m_cLoopFilter.        destroy();
   m_cRateCtrl.          destroy();
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cReshaper.          destroy();
+#endif
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
   for( int jId = 0; jId < m_numCuEncStacks; jId++ )
   {
@@ -215,7 +224,7 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
   omp_set_nested( true );
 #endif
 
-  if (sps0.getSpsNext().getUseCompositeRef()) 
+  if (sps0.getUseCompositeRef())
   {
     sps0.setLongTermRefsPresent(true);
   }
@@ -246,7 +255,7 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
     xInitPPS(pps1, sps0);
   }
 #endif
-  if (sps0.getSpsNext().getUseCompositeRef())
+  if (sps0.getUseCompositeRef())
   {
     PPS &pps2 = *(m_ppsMap.allocatePS(2));
     xInitPPS(pps2, sps0);
@@ -318,13 +327,21 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
                        &m_cTrQuant,
                        &m_cRdCost,
                        cabacEstimator,
-                       getCtxCache(), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth );
+                       getCtxCache(), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth
+#if JVET_M0427_INLOOP_RESHAPER
+                     , &m_cReshaper
+#endif
+  );
   m_cInterSearch.init( this,
                        &m_cTrQuant,
                        m_iSearchRange,
                        m_bipredSearchRange,
                        m_motionEstimationSearchMethod,
-                       m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost, cabacEstimator, getCtxCache() );
+    m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost, cabacEstimator, getCtxCache()
+#if JVET_M0427_INLOOP_RESHAPER
+                     , &m_cReshaper
+#endif
+  );
 
   // link temporary buffets from intra search with inter search to avoid unneccessary memory overhead
   m_cInterSearch.setTempBuffers( m_cIntraSearch.getSplitCSBuf(), m_cIntraSearch.getFullCSBuf(), m_cIntraSearch.getSaveCSBuf() );
@@ -348,7 +365,7 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
 #if ENABLE_WPP_PARALLELISM
   m_entropyCodingSyncContextStateVec.resize( pps0.pcv->heightInCtus );
 #endif
-  if (sps0.getSpsNext().getUseCompositeRef()) 
+  if (sps0.getUseCompositeRef())
   {
     Picture *picBg = new Picture;
     picBg->create(sps0.getChromaFormatIdc(), Size(sps0.getPicWidthInLumaSamples(), sps0.getPicHeightInLumaSamples()), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false);
@@ -551,6 +568,9 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
       const SPS *pSPS=m_spsMap.getPS(pPPS->getSPSId());
 
       pcPicCurr->M_BUFS( 0, PIC_ORIGINAL ).swap( *pcPicYuvOrg );
+#if JVET_M0427_INLOOP_RESHAPER
+      pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL).swap(*cPicYuvTrueOrg);
+#endif
 
       pcPicCurr->finalInit( *pSPS, *pPPS );
     }
@@ -756,6 +776,9 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict
   rpcPic->setBorderExtension( false );
   rpcPic->reconstructed = false;
   rpcPic->referenced = true;
+#if JVET_M0253_HASH_ME
+  rpcPic->getHashMap()->clearAll();
+#endif
 
   m_iPOCLast += (m_compositeRefEnabled ? 2 : 1);
   m_iNumPicRcvd++;
@@ -798,9 +821,17 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setNoAmvrConstraintFlag(!m_bNoAmvrConstraintFlag);
   sps.setNoAffineMotionConstraintFlag(!m_Affine);
 #if JVET_M0464_UNI_MTS
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setNoMtsConstraintFlag((m_IntraMTS || m_InterMTS || m_ImplicitMTS) ? false : true);
+#else
   sps.setNoMtsConstraintFlag((m_IntraMTS || m_InterMTS) ? false : true);
+#endif
+#else
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setNoMtsConstraintFlag((m_IntraEMT || m_InterEMT || m_ImplicitMTS) ? false : true);
 #else
   sps.setNoMtsConstraintFlag((m_IntraEMT || m_InterEMT) ? false : true);
+#endif
 #endif
   sps.setNoLadfConstraintFlag(!m_LadfEnabled);
   sps.setNoDepQuantConstraintFlag(!m_DepQuantEnabledFlag);
@@ -844,60 +875,79 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setChromaFormatIdc        ( m_chromaFormatIDC   );
   sps.setLog2DiffMaxMinCodingBlockSize(m_log2DiffMaxMinCodingBlockSize);
 
-  sps.getSpsNext().setNextToolsEnabled      ( m_profile == Profile::NEXT );
   sps.setCTUSize                             ( m_CTUSize );
   sps.setSplitConsOverrideEnabledFlag        ( m_useSplitConsOverride );
   sps.setMinQTSizes                          ( m_uiMinQT );
-  sps.getSpsNext().setUseLargeCTU            ( m_LargeCTU );
   sps.setMaxBTDepth                          ( m_uiMaxBTDepth, m_uiMaxBTDepthI, m_uiMaxBTDepthIChroma );
   sps.setUseDualITree                        ( m_dualITree );
   sps.setSBTMVPEnabledFlag                  ( m_SubPuMvpMode );
-  sps.getSpsNext().setImvMode               ( ImvMode(m_ImvMode) );
-  sps.getSpsNext().setUseIMV                ( m_ImvMode != IMV_OFF );
+  sps.setAMVREnabledFlag                ( m_ImvMode != IMV_OFF );
   sps.setBDOFEnabledFlag                    ( m_BIO );
-  sps.getSpsNext().setUseAffine             ( m_Affine );
-  sps.getSpsNext().setUseAffineType         ( m_AffineType );
-  sps.getSpsNext().setDisableMotCompress    ( m_DisableMotionCompression );
-  sps.getSpsNext().setMTTMode               ( m_MTTMode );
-  sps.getSpsNext().setUseLMChroma           ( m_LMChroma ? true : false );
+  sps.setUseAffine             ( m_Affine );
+  sps.setUseAffineType         ( m_AffineType );
+  sps.setUseLMChroma           ( m_LMChroma ? true : false );
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  sps.getSpsNext().setCclmCollocatedChromaFlag( m_cclmCollocatedChromaFlag );
-#endif
-#if ENABLE_WPP_PARALLELISM
-  sps.getSpsNext().setUseNextDQP            ( m_AltDQPCoding );
+  sps.setCclmCollocatedChromaFlag( m_cclmCollocatedChromaFlag );
 #endif
 #if JVET_M0464_UNI_MTS
-  sps.getSpsNext().setUseIntraMTS           ( m_IntraMTS );
-  sps.getSpsNext().setUseInterMTS           ( m_InterMTS );
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setUseMTS                ( m_IntraMTS || m_InterMTS || m_ImplicitMTS );
+#endif
+  sps.setUseIntraMTS           ( m_IntraMTS );
+  sps.setUseInterMTS           ( m_InterMTS );
 #else
-  sps.getSpsNext().setUseIntraEMT           ( m_IntraEMT );
-  sps.getSpsNext().setUseInterEMT           ( m_InterEMT );
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setUseMTS                ( m_IntraEMT || m_InterEMT || m_ImplicitMTS );
+#endif
+  sps.setUseIntraEMT           ( m_IntraEMT );
+  sps.setUseInterEMT           ( m_InterEMT );
 #endif
-  sps.getSpsNext().setUseCompositeRef       ( m_compositeRefEnabled );
-  sps.getSpsNext().setUseGBi                ( m_GBi );
+#if JVET_M0140_SBT
+  sps.setUseSBT                             ( m_SBT );
+  if( sps.getUseSBT() )
+  {
+    sps.setMaxSbtSize                       ( m_iSourceWidth >= 1920 ? 64 : 32 );
+  }
+#endif
+  sps.setUseCompositeRef       ( m_compositeRefEnabled );
+  sps.setUseGBi                ( m_GBi );
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  sps.getSpsNext().setLadfEnabled           ( m_LadfEnabled );
+  sps.setLadfEnabled           ( m_LadfEnabled );
   if ( m_LadfEnabled )
   {
-    sps.getSpsNext().setLadfNumIntervals    ( m_LadfNumIntervals );
+    sps.setLadfNumIntervals    ( m_LadfNumIntervals );
     for ( int k = 0; k < m_LadfNumIntervals; k++ )
     {
-      sps.getSpsNext().setLadfQpOffset( m_LadfQpOffset[k], k );
-      sps.getSpsNext().setLadfIntervalLowerBound( m_LadfIntervalLowerBound[k], k );
+      sps.setLadfQpOffset( m_LadfQpOffset[k], k );
+      sps.setLadfIntervalLowerBound( m_LadfIntervalLowerBound[k], k );
     }
     CHECK( m_LadfIntervalLowerBound[0] != 0, "abnormal value set to LadfIntervalLowerBound[0]" );
   }
 #endif
 
-  sps.getSpsNext().setUseMHIntra            ( m_MHIntra );
-  sps.getSpsNext().setUseTriangle           ( m_Triangle );
-
-  sps.getSpsNext().setIBCMode               ( m_IBCMode );
+  sps.setUseMHIntra            ( m_MHIntra );
+  sps.setUseTriangle           ( m_Triangle );
+#if JVET_M0255_FRACMMVD_SWITCH
+  sps.setDisFracMmvdEnabledFlag             ( m_allowDisFracMMVD );
+#endif
+#if JVET_M0246_AFFINE_AMVR
+  sps.setAffineAmvrEnabledFlag              ( m_AffineAmvr );
+#endif
+#if JVET_M0147_DMVR
+  sps.setUseDMVR                            ( m_DMVR );
+#endif
 
+#if JVET_M0483_IBC
+  sps.setIBCFlag                            ( m_IBCMode);
+#else
+  sps.setIBCMode               (m_IBCMode);
+#endif
   sps.setWrapAroundEnabledFlag                      ( m_wrapAround );
   sps.setWrapAroundOffset                   ( m_wrapAroundOffset );
   // ADD_NEW_TOOL : (encoder lib) set tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  sps.setUseReshaper                        ( m_lumaReshapeEnable );
+#endif
   int minCUSize =  sps.getMaxCUWidth() >> sps.getLog2DiffMaxMinCodingBlockSize();
   int log2MinCUSize = 0;
   while(minCUSize > 1)
@@ -1324,7 +1374,7 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps)
   pps.setSliceChromaQpFlag(bChromaDeltaQPEnabled);
 #endif
   if (
-    !pps.getSliceChromaQpFlag() && sps.getUseDualITree() 
+    !pps.getSliceChromaQpFlag() && sps.getUseDualITree()
     && (getChromaFormatIdc() != CHROMA_400))
   {
     pps.setSliceChromaQpFlag(m_chromaCbQpOffsetDualTree != 0 || m_chromaCrQpOffsetDualTree != 0);
@@ -1395,11 +1445,13 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps)
     }
   }
   CHECK(!(bestPos <= 15), "Unspecified error");
-  if (sps.getSpsNext().getIBCMode())
+#if JVET_M0483_IBC==0
+  if (sps.getIBCMode())
   {
     pps.setNumRefIdxL0DefaultActive(bestPos + 1);
   }
   else
+#endif
     pps.setNumRefIdxL0DefaultActive(bestPos);
   pps.setNumRefIdxL1DefaultActive(bestPos);
   pps.setTransquantBypassEnabledFlag(getTransquantBypassEnabledFlag());
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index 07109efcd1b51da2883577204cfb82538855da4c..f966d8277a5ac70b0fda79da0cb912d01994c61d 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -53,6 +53,9 @@
 #include "InterSearch.h"
 #include "IntraSearch.h"
 #include "EncSampleAdaptiveOffset.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 #include "EncAdaptiveLoopFilter.h"
 #include "RateCtrl.h"
 
@@ -98,6 +101,10 @@ private:
   CABACEncoder              m_CABACEncoder;
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape                m_cReshaper;                        ///< reshaper class
+#endif
+
   // processing unit
   EncGOP                    m_cGOPEncoder;                        ///< GOP encoder
   EncSlice                  m_cSliceEncoder;                      ///< slice encoder
@@ -219,6 +226,9 @@ public:
   int                    getNumCuEncStacks()              const { return m_numCuEncStacks; }
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*            getReshaper()                          { return  &m_cReshaper; }
+#endif
   // -------------------------------------------------------------------------------------------------------------------
   // encoder function
   // -------------------------------------------------------------------------------------------------------------------
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index c9a6863301a9e2c439e7fafdb209a4f9ce99ee2d..9fc58805e972734397b41227ca75408626c3d97d 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -191,7 +191,7 @@ void EncModeCtrl::xGetMinMaxQP( int& minQP, int& maxQP, const CodingStructure& c
 
   if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() && (!CS::isDualITree (cs) || isLuma (partitioner.chType)))
   {
-    minQP = Clip3 (-sps.getQpBDOffset (CHANNEL_TYPE_LUMA), MAX_QP, baseQP - m_lumaQPOffset);
+    minQP = Clip3( -sps.getQpBDOffset( CHANNEL_TYPE_LUMA ), MAX_QP, baseQP - m_lumaQPOffset );
     maxQP = minQP;
   }
 #endif
@@ -251,7 +251,7 @@ int EncModeCtrl::calculateLumaDQP( const CPelBuf& rcOrg )
 #endif
   {
     // Use average luma value
-    avg = (double) rcOrg.mean();
+    avg = (double) rcOrg.computeAvg();
   }
 #if !WCG_EXT
   else
@@ -505,6 +505,106 @@ bool CacheBlkInfoCtrl::getMv( const UnitArea& area, const RefPicList refPicList,
   return m_codedCUInfo[idx1][idx2][idx3][idx4]->validMv[refPicList][iRefIdx];
 }
 
+#if JVET_M0140_SBT
+void SaveLoadEncInfoSbt::init( const Slice &slice )
+{
+  m_sliceSbt = &slice;
+}
+
+void SaveLoadEncInfoSbt::create()
+{
+  int numSizeIdx = gp_sizeIdxInfo->idxFrom( SBT_MAX_SIZE ) - MIN_CU_LOG2 + 1;
+  int numPosIdx = MAX_CU_SIZE >> MIN_CU_LOG2;
+
+  m_saveLoadSbt = new SaveLoadStructSbt***[numPosIdx];
+
+  for( int xIdx = 0; xIdx < numPosIdx; xIdx++ )
+  {
+    m_saveLoadSbt[xIdx] = new SaveLoadStructSbt**[numPosIdx];
+    for( int yIdx = 0; yIdx < numPosIdx; yIdx++ )
+    {
+      m_saveLoadSbt[xIdx][yIdx] = new SaveLoadStructSbt*[numSizeIdx];
+      for( int wIdx = 0; wIdx < numSizeIdx; wIdx++ )
+      {
+        m_saveLoadSbt[xIdx][yIdx][wIdx] = new SaveLoadStructSbt[numSizeIdx];
+      }
+    }
+  }
+}
+
+void SaveLoadEncInfoSbt::destroy()
+{
+  int numSizeIdx = gp_sizeIdxInfo->idxFrom( SBT_MAX_SIZE ) - MIN_CU_LOG2 + 1;
+  int numPosIdx = MAX_CU_SIZE >> MIN_CU_LOG2;
+
+  for( int xIdx = 0; xIdx < numPosIdx; xIdx++ )
+  {
+    for( int yIdx = 0; yIdx < numPosIdx; yIdx++ )
+    {
+      for( int wIdx = 0; wIdx < numSizeIdx; wIdx++ )
+      {
+        delete[] m_saveLoadSbt[xIdx][yIdx][wIdx];
+      }
+      delete[] m_saveLoadSbt[xIdx][yIdx];
+    }
+    delete[] m_saveLoadSbt[xIdx];
+  }
+  delete[] m_saveLoadSbt;
+}
+
+uint16_t SaveLoadEncInfoSbt::findBestSbt( const UnitArea& area, const uint32_t curPuSse )
+{
+  unsigned idx1, idx2, idx3, idx4;
+  getAreaIdx( area.Y(), *m_sliceSbt->getPPS()->pcv, idx1, idx2, idx3, idx4 );
+  SaveLoadStructSbt* pSbtSave = &m_saveLoadSbt[idx1][idx2][idx3 - MIN_CU_LOG2][idx4 - MIN_CU_LOG2];
+
+  for( int i = 0; i < pSbtSave->numPuInfoStored; i++ )
+  {
+    if( curPuSse == pSbtSave->puSse[i] )
+    {
+      return pSbtSave->puSbt[i] + ( pSbtSave->puTrs[i] << 8 );
+    }
+  }
+
+  return MAX_UCHAR + ( MAX_UCHAR << 8 );
+}
+
+bool SaveLoadEncInfoSbt::saveBestSbt( const UnitArea& area, const uint32_t curPuSse, const uint8_t curPuSbt, const uint8_t curPuTrs )
+{
+  unsigned idx1, idx2, idx3, idx4;
+  getAreaIdx( area.Y(), *m_sliceSbt->getPPS()->pcv, idx1, idx2, idx3, idx4 );
+  SaveLoadStructSbt* pSbtSave = &m_saveLoadSbt[idx1][idx2][idx3 - MIN_CU_LOG2][idx4 - MIN_CU_LOG2];
+
+  if( pSbtSave->numPuInfoStored == SBT_NUM_SL )
+  {
+    return false;
+  }
+
+  pSbtSave->puSse[pSbtSave->numPuInfoStored] = curPuSse;
+  pSbtSave->puSbt[pSbtSave->numPuInfoStored] = curPuSbt;
+  pSbtSave->puTrs[pSbtSave->numPuInfoStored] = curPuTrs;
+  pSbtSave->numPuInfoStored++;
+  return true;
+}
+
+void SaveLoadEncInfoSbt::resetSaveloadSbt( int maxSbtSize )
+{
+  int numSizeIdx = gp_sizeIdxInfo->idxFrom( maxSbtSize ) - MIN_CU_LOG2 + 1;
+  int numPosIdx = MAX_CU_SIZE >> MIN_CU_LOG2;
+
+  for( int xIdx = 0; xIdx < numPosIdx; xIdx++ )
+  {
+    for( int yIdx = 0; yIdx < numPosIdx; yIdx++ )
+    {
+      for( int wIdx = 0; wIdx < numSizeIdx; wIdx++ )
+      {
+        memset( m_saveLoadSbt[xIdx][yIdx][wIdx], 0, numSizeIdx * sizeof( SaveLoadStructSbt ) );
+      }
+    }
+  }
+}
+#endif
+
 bool CacheBlkInfoCtrl::getInter(const UnitArea& area)
 {
   unsigned idx1, idx2, idx3, idx4;
@@ -557,7 +657,7 @@ static bool isTheSameNbHood( const CodingUnit &cu, const CodingStructure& cs, co
   bool sharedListReuseMode = true;
   if(
       pu.mergeFlag == true &&
-      cu.affine == false &&    
+      cu.affine == false &&
       cu.predMode == MODE_INTER
     )
   {
@@ -628,9 +728,17 @@ void BestEncInfoCache::create( const ChromaFormat chFmt )
 
               const UnitArea area( chFmt, Area( 0, 0, w, h ) );
 
-              m_bestEncInfo[x][y][wIdx][hIdx]->cu.UnitArea::operator=( area );
-              m_bestEncInfo[x][y][wIdx][hIdx]->pu.UnitArea::operator=( area );
-              m_bestEncInfo[x][y][wIdx][hIdx]->tu.UnitArea::operator=( area );
+              new ( &m_bestEncInfo[x][y][wIdx][hIdx]->cu ) CodingUnit    ( area );
+              new ( &m_bestEncInfo[x][y][wIdx][hIdx]->pu ) PredictionUnit( area );
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+              m_bestEncInfo[x][y][wIdx][hIdx]->numTus = 0;
+              for( int i = 0; i < MAX_NUM_TUS; i++ )
+              {
+                new ( &m_bestEncInfo[x][y][wIdx][hIdx]->tus[i] ) TransformUnit( area );
+              }
+#else
+              new ( &m_bestEncInfo[x][y][wIdx][hIdx]->tu ) TransformUnit( area );
+#endif
 
               m_bestEncInfo[x][y][wIdx][hIdx]->poc      = -1;
               m_bestEncInfo[x][y][wIdx][hIdx]->testMode = EncTestMode();
@@ -689,14 +797,14 @@ void BestEncInfoCache::init( const Slice &slice )
   m_slice_bencinf = &slice;
 
   if( isInitialized ) return;
-  
+
   const unsigned numPos = MAX_CU_SIZE >> MIN_CU_LOG2;
 
   m_numWidths  = gp_sizeIdxInfo->numWidths();
   m_numHeights = gp_sizeIdxInfo->numHeights();
 
   size_t numCoeff = 0;
-  
+
   for( unsigned x = 0; x < numPos; x++ )
   {
     for( unsigned y = 0; y < numPos; y++ )
@@ -717,8 +825,13 @@ void BestEncInfoCache::init( const Slice &slice )
     }
   }
 
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  m_pCoeff  = new TCoeff[numCoeff*MAX_NUM_TUS];
+  m_pPcmBuf = new Pel   [numCoeff*MAX_NUM_TUS];
+#else
   m_pCoeff  = new TCoeff[numCoeff];
   m_pPcmBuf = new Pel   [numCoeff];
+#endif
 
   TCoeff *coeffPtr = m_pCoeff;
   Pel    *pcmPtr   = m_pPcmBuf;
@@ -738,6 +851,22 @@ void BestEncInfoCache::init( const Slice &slice )
             TCoeff *coeff[MAX_NUM_TBLOCKS] = { 0, };
             Pel    *pcmbf[MAX_NUM_TBLOCKS] = { 0, };
 
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+            for( int i = 0; i < MAX_NUM_TUS; i++ )
+            {
+              TransformUnit &tu = m_bestEncInfo[x][y][wIdx][hIdx]->tus[i];
+              const UnitArea &area = tu;
+
+              for( int i = 0; i < area.blocks.size(); i++ )
+              {
+                coeff[i] = coeffPtr; coeffPtr += area.blocks[i].area();
+                pcmbf[i] = pcmPtr;   pcmPtr += area.blocks[i].area();
+              }
+
+              tu.cs = &m_dummyCS;
+              tu.init(coeff, pcmbf);
+            }
+#else
             const UnitArea &area = m_bestEncInfo[x][y][wIdx][hIdx]->tu;
 
             for( int i = 0; i < area.blocks.size(); i++ )
@@ -748,6 +877,7 @@ void BestEncInfoCache::init( const Slice &slice )
 
             m_bestEncInfo[x][y][wIdx][hIdx]->tu.cs = &m_dummyCS;
             m_bestEncInfo[x][y][wIdx][hIdx]->tu.init( coeff, pcmbf );
+#endif
           }
         }
       }
@@ -757,7 +887,11 @@ void BestEncInfoCache::init( const Slice &slice )
 
 bool BestEncInfoCache::setFromCs( const CodingStructure& cs, const Partitioner& partitioner )
 {
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  if( cs.cus.size() != 1 || cs.pus.size() != 1 )
+#else
   if( cs.cus.size() != 1 || cs.tus.size() != 1 || cs.pus.size() != 1 )
+#endif
   {
     return false;
   }
@@ -770,13 +904,32 @@ bool BestEncInfoCache::setFromCs( const CodingStructure& cs, const Partitioner&
   encInfo.poc            =  cs.picture->poc;
   encInfo.cu.repositionTo( *cs.cus.front() );
   encInfo.pu.repositionTo( *cs.pus.front() );
+#if !REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
   encInfo.tu.repositionTo( *cs.tus.front() );
+#endif
   encInfo.cu             = *cs.cus.front();
   encInfo.pu             = *cs.pus.front();
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  int tuIdx = 0;
+  for( auto tu : cs.tus )
+  {
+    encInfo.tus[tuIdx].repositionTo( *tu );
+    encInfo.tus[tuIdx].resizeTo( *tu );
+    for( auto &blk : tu->blocks )
+    {
+      if( blk.valid() )
+        encInfo.tus[tuIdx].copyComponentFrom( *tu, blk.compID );
+    }
+    tuIdx++;
+  }
+  CHECKD( cs.tus.size() > MAX_NUM_TUS, "Exceeding tus array boundaries" );
+  encInfo.numTus = cs.tus.size();
+#else
   for( auto &blk : cs.tus.front()->blocks )
   {
     if( blk.valid() ) encInfo.tu.copyComponentFrom( *cs.tus.front(), blk.compID );
   }
+#endif
   encInfo.testMode       = getCSEncMode( cs );
 
   return true;
@@ -795,8 +948,13 @@ bool BestEncInfoCache::isValid( const CodingStructure& cs, const Partitioner& pa
 #if JVET_M0170_MRG_SHARELIST
     , encInfo.pu, (cs.picture->Y().width), (cs.picture->Y().height)
 #endif
-) 
+)
+#if JVET_M0483_IBC
+    || CU::isIBC(encInfo.cu)
+#else
     || encInfo.cu.ibc
+#endif
+    || partitioner.currDepth <= cs.pps->getMaxCuDQPDepth() || cs.currQP[partitioner.chType] != encInfo.cu.qp
     )
   {
     return false;
@@ -814,29 +972,48 @@ bool BestEncInfoCache::setCsFrom( CodingStructure& cs, EncTestMode& testMode, co
 
   BestEncodingInfo& encInfo = *m_bestEncInfo[idx1][idx2][idx3][idx4];
 
-  if( cs.picture->poc != encInfo.poc || CS::getArea( cs, cs.area, partitioner.chType ) != CS::getArea( cs, encInfo.cu, partitioner.chType ) || !isTheSameNbHood( encInfo.cu, cs, partitioner 
+  if( cs.picture->poc != encInfo.poc || CS::getArea( cs, cs.area, partitioner.chType ) != CS::getArea( cs, encInfo.cu, partitioner.chType ) || !isTheSameNbHood( encInfo.cu, cs, partitioner
 #if JVET_M0170_MRG_SHARELIST
     , encInfo.pu, (cs.picture->Y().width), (cs.picture->Y().height)
 #endif
-) )
+    )
+    || partitioner.currDepth <= cs.pps->getMaxCuDQPDepth() || cs.currQP[partitioner.chType] != encInfo.cu.qp
+    )
   {
     return false;
   }
 
   CodingUnit     &cu = cs.addCU( CS::getArea( cs, cs.area, partitioner.chType ), partitioner.chType );
   PredictionUnit &pu = cs.addPU( CS::getArea( cs, cs.area, partitioner.chType ), partitioner.chType );
+#if !REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
   TransformUnit  &tu = cs.addTU( CS::getArea( cs, cs.area, partitioner.chType ), partitioner.chType );
+#endif
 
   cu          .repositionTo( encInfo.cu );
   pu          .repositionTo( encInfo.pu );
+#if !REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
   tu          .repositionTo( encInfo.tu );
+#endif
 
   cu          = encInfo.cu;
   pu          = encInfo.pu;
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  CHECKD( !( encInfo.numTus > 0 ), "Empty tus array" );
+  for( int i = 0; i < encInfo.numTus; i++ )
+  {
+    TransformUnit  &tu = cs.addTU( encInfo.tus[i], partitioner.chType );
+
+    for( auto &blk : tu.blocks )
+    {
+      if( blk.valid() ) tu.copyComponentFrom( encInfo.tus[i], blk.compID );
+    }
+  }
+#else
   for( auto &blk : tu.blocks )
   {
     if( blk.valid() ) tu.copyComponentFrom( encInfo.tu, blk.compID );
   }
+#endif
 
   testMode    = encInfo.testMode;
 
@@ -873,12 +1050,18 @@ void EncModeCtrlMTnoRQT::create( const EncCfg& cfg )
 {
   CacheBlkInfoCtrl::create();
   BestEncInfoCache::create( cfg.getChromaFormatIdc() );
+#if JVET_M0140_SBT
+  SaveLoadEncInfoSbt::create();
+#endif
 }
 
 void EncModeCtrlMTnoRQT::destroy()
 {
   CacheBlkInfoCtrl::destroy();
   BestEncInfoCache::destroy();
+#if JVET_M0140_SBT
+  SaveLoadEncInfoSbt::destroy();
+#endif
 }
 
 #endif
@@ -888,6 +1071,9 @@ void EncModeCtrlMTnoRQT::initCTUEncoding( const Slice &slice )
 #if REUSE_CU_RESULTS
   BestEncInfoCache::init( slice );
 #endif
+#if JVET_M0140_SBT
+  SaveLoadEncInfoSbt::init( slice );
+#endif
 
   CHECK( !m_ComprCUCtxList.empty(), "Mode list is not empty at the beginning of a CTU" );
 
@@ -968,8 +1154,8 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
   cuECtx.set( BEST_HORZ_SPLIT_COST, MAX_DOUBLE );
   cuECtx.set( BEST_TRIH_SPLIT_COST, MAX_DOUBLE );
   cuECtx.set( BEST_TRIV_SPLIT_COST, MAX_DOUBLE );
-  cuECtx.set( DO_TRIH_SPLIT,        cs.sps->getSpsNext().getMTTMode() & 1 );
-  cuECtx.set( DO_TRIV_SPLIT,        cs.sps->getSpsNext().getMTTMode() & 1 );
+  cuECtx.set( DO_TRIH_SPLIT,        1 );
+  cuECtx.set( DO_TRIV_SPLIT,        1 );
   cuECtx.set( BEST_IMV_COST,        MAX_DOUBLE * .5 );
   cuECtx.set( BEST_NO_IMV_COST,     MAX_DOUBLE * .5 );
   cuECtx.set( QT_BEFORE_BT,         qtBeforeBt );
@@ -983,7 +1169,7 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
   {
     if (m_pcEncCfg->getUseAdaptiveQP())
     {
-      baseQP = Clip3(-cs.sps->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, baseQP + xComputeDQP (cs, partitioner));
+      baseQP = Clip3(-cs.sps->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, baseQP + xComputeDQP(cs, partitioner));
     }
 #if ENABLE_QPA_SUB_CTU
     else if (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && cs.pps->getUseDQP() && cs.pps->getMaxCuDQPDepth() > 0)
@@ -1020,7 +1206,7 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
     switch (ibcLumaCoverage)
     {
     case IBC_LUMA_COVERAGE_FULL:
-      // check IBC 
+      // check IBC
       break;
     case IBC_LUMA_COVERAGE_PARTIAL:
       // do not check IBC
@@ -1139,7 +1325,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
     m_ComprCUCtxList.back().testModes.push_back( { ETM_IPCM,  ETO_STANDARD, qp, lossless } );
     m_ComprCUCtxList.back().testModes.push_back( { ETM_INTRA, ETO_STANDARD, qp, lossless } );
     // add ibc mode to intra path
-    if (cs.sps->getSpsNext().getIBCMode() && checkIbc )
+#if JVET_M0483_IBC
+    if (cs.sps->getIBCFlag() && checkIbc)
+#else
+    if (cs.sps->getIBCMode() && checkIbc )
+#endif
     {
       m_ComprCUCtxList.back().testModes.push_back({ ETM_IBC,         ETO_STANDARD,  qp, lossless });
       if (cs.chType == CHANNEL_TYPE_LUMA)
@@ -1156,25 +1346,25 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
     {
       const int  qp       = std::max( qpLoop, lowestQP );
       const bool lossless = useLossless && qpLoop == minQP;
-
+#if JVET_M0246_AFFINE_AMVR
+      if( m_pcEncCfg->getIMV() || m_pcEncCfg->getUseAffineAmvr() )
+#else
       if( m_pcEncCfg->getIMV() )
+#endif
       {
-        if( m_pcEncCfg->getIMV() == IMV_4PEL )
-        {
-          int imv = m_pcEncCfg->getIMV4PelFast() ? 3 : 2;
-          m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME, EncTestModeOpts( imv << ETO_IMV_SHIFT ), qp, lossless } );
-        }
+        int imv = m_pcEncCfg->getIMV4PelFast() ? 3 : 2;
+        m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME, EncTestModeOpts( imv << ETO_IMV_SHIFT ), qp, lossless } );
         m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME, EncTestModeOpts( 1 << ETO_IMV_SHIFT ), qp, lossless } );
       }
       // add inter modes
       if( m_pcEncCfg->getUseEarlySkipDetection() )
       {
-        if( cs.sps->getSpsNext().getUseTriangle() && cs.slice->isInterB() )
+        if( cs.sps->getUseTriangle() && cs.slice->isInterB() )
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp, lossless } );
         }
         m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP,  ETO_STANDARD, qp, lossless } );
-        if ( cs.sps->getSpsNext().getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
+        if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_AFFINE,    ETO_STANDARD, qp, lossless } );
         }
@@ -1183,16 +1373,25 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
       else
       {
         m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME,    ETO_STANDARD, qp, lossless } );
-        if( cs.sps->getSpsNext().getUseTriangle() && cs.slice->isInterB() )
+        if( cs.sps->getUseTriangle() && cs.slice->isInterB() )
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp, lossless } );
         }
         m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP,  ETO_STANDARD, qp, lossless } );
-        if ( cs.sps->getSpsNext().getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
+        if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_AFFINE,    ETO_STANDARD, qp, lossless } );
         }
       }
+#if JVET_M0253_HASH_ME
+      if (m_pcEncCfg->getUseHashME())
+      {
+        if ((cs.area.lwidth() == cs.area.lheight() && cs.area.lwidth() <= 64 && cs.area.lwidth() >= 4) || (cs.area.lwidth() == 4 && cs.area.lheight() == 8) || (cs.area.lwidth() == 8 && cs.area.lheight() == 4))
+        {
+          m_ComprCUCtxList.back().testModes.push_back({ ETM_HASH_INTER, ETO_STANDARD, qp, lossless });
+        }
+      }
+#endif
     }
   }
 
@@ -1216,6 +1415,12 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
   ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
 
   // Fast checks, partitioning depended
+#if JVET_M0253_HASH_ME
+  if (cuECtx.isHashPerfectMatch && encTestmode.type != ETM_MERGE_SKIP && encTestmode.type != ETM_AFFINE && encTestmode.type != ETM_MERGE_TRIANGLE)
+  {
+    return false;
+  }
+#endif
 
   // if early skip detected, skip all modes checking but the splits
   if( cuECtx.earlySkip && m_pcEncCfg->getUseEarlySkipDetection() && !isModeSplit( encTestmode ) && !( isModeInter( encTestmode ) ) )
@@ -1297,18 +1502,30 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
       return false;
     }
 
+#if JVET_M0483_IBC
+    if (m_pcEncCfg->getUsePbIntraFast() && (!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && !interHadActive(cuECtx) && cuECtx.bestCU && !CU::isIntra(*cuECtx.bestCU))
+#else
     if( m_pcEncCfg->getUsePbIntraFast() && !cs.slice->isIntra() && !interHadActive( cuECtx ) && cuECtx.bestCU && CU::isInter( *cuECtx.bestCU ) )
+#endif
     {
       return false;
     }
 
     // INTRA MODES
-    if (cs.sps->getSpsNext().getIBCMode() && !cuECtx.bestTU)
+#if JVET_M0483_IBC
+    if (cs.sps->getIBCFlag() && !cuECtx.bestTU)
+#else
+    if (cs.sps->getIBCMode() && !cuECtx.bestTU)
+#endif
       return true;
     CHECK( !slice.isIntra() && !cuECtx.bestTU, "No possible non-intra encoding for a P- or B-slice found" );
 
-    if( !( slice.isIRAP() || bestMode.type == ETM_INTRA || 
-          ( ( !m_pcEncCfg->getDisableIntraPUsInInterSlices() ) && !relatedCU.isInter && (
+    if( !( slice.isIRAP() || bestMode.type == ETM_INTRA ||
+#if JVET_M0483_IBC
+      ((!m_pcEncCfg->getDisableIntraPUsInInterSlices()) && (!relatedCU.isInter || !relatedCU.isIBC) && (
+#else
+      ( ( !m_pcEncCfg->getDisableIntraPUsInInterSlices() ) && !relatedCU.isInter && (
+#endif
                                          ( cuECtx.bestTU->cbf[0] != 0 ) ||
            ( ( numComp > COMPONENT_Cb ) && cuECtx.bestTU->cbf[1] != 0 ) ||
            ( ( numComp > COMPONENT_Cr ) && cuECtx.bestTU->cbf[2] != 0 )  // avoid very complex intra if it is unlikely
@@ -1330,7 +1547,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
       if( !cs.slice->isIRAP() && m_pcEncCfg->getUsePbIntraFast() )
       {
         CodingUnit* bestCU = cuECtx.bestCU;
+#if JVET_M0483_IBC
+        if (bestCU && !CU::isIntra(*bestCU))
+#else
         if( bestCU && CU::isInter( *bestCU ) )
+#endif
         {
           DistParam distParam;
           const bool useHad = !bestCU->transQuantBypass;
@@ -1361,7 +1582,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
   else if (encTestmode.type == ETM_IBC || encTestmode.type == ETM_IBC_MERGE)
   {
     // IBC MODES
-    return sps.getSpsNext().getIBCMode() && width <= IBC_MAX_CAND_SIZE && partitioner.currArea().lumaSize().height <= IBC_MAX_CAND_SIZE;
+#if JVET_M0483_IBC
+    return sps.getIBCFlag() && width <= IBC_MAX_CAND_SIZE && partitioner.currArea().lumaSize().height <= IBC_MAX_CAND_SIZE;
+#else
+    return sps.getIBCMode() && width <= IBC_MAX_CAND_SIZE && partitioner.currArea().lumaSize().height <= IBC_MAX_CAND_SIZE;
+#endif
   }
   else if( isModeInter( encTestmode ) )
   {
@@ -1401,6 +1626,9 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
 
         if (imvOpt == 3 && cuECtx.get<double>(BEST_NO_IMV_COST) * 1.06 < cuECtx.get<double>(BEST_IMV_COST))
         {
+#if JVET_M0246_AFFINE_AMVR
+          if ( !m_pcEncCfg->getUseAffineAmvr() )
+#endif
           return false;
         }
       }
@@ -1411,7 +1639,7 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
       return false;
     }
     if( encTestmode.type == ETM_MERGE_TRIANGLE && ( partitioner.currArea().lumaSize().area() < TRIANGLE_MIN_SIZE || relatedCU.isIntra ) )
-    { 
+    {
       return false;
     }
     return true;
@@ -1424,7 +1652,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
     //////////////////////////////////////////////////////////////////////////
     int skipScore = 0;
 
+#if JVET_M0483_IBC
+    if ((!slice.isIntra() || slice.getSPS()->getIBCFlag()) && cuECtx.get<bool>(IS_BEST_NOSPLIT_SKIP))
+#else
     if( !slice.isIntra() && cuECtx.get<bool>( IS_BEST_NOSPLIT_SKIP ) )
+#endif
     {
       for( int i = 2; i < m_ComprCUCtxList.size(); i++ )
       {
@@ -1519,6 +1751,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
             const CodingUnit *cuBR = bestCS->cus.back();
             unsigned height        = partitioner.currArea().lumaSize().height;
 
+#if JVET_M0483_IBC
+            if (bestCU && ((bestCU->btDepth == 0 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getIBCFlag()) ? 3 : 2))
+              || (bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getIBCFlag()) ? 4 : 3)))
+              && (width <= MAX_TU_SIZE_FOR_PROFILE && height <= MAX_TU_SIZE_FOR_PROFILE)
+              && cuECtx.get<bool>(DID_HORZ_SPLIT) && cuECtx.get<bool>(DID_VERT_SPLIT))
+            {
+              return false;
+            }
+#else
             if( bestCU && ( ( bestCU->btDepth == 0 &&                               maxBTD >= ( slice.isIntra() ? 3 : 2 ) )
                          || ( bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ( slice.isIntra() ? 4 : 3 ) ) )
                        && ( width <= MAX_TU_SIZE_FOR_PROFILE && height <= MAX_TU_SIZE_FOR_PROFILE )
@@ -1526,6 +1767,7 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
             {
               return false;
             }
+#endif
           }
           if( m_pcEncCfg->getUseEarlyCU() && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip )
           {
@@ -1630,6 +1872,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
 #endif
           relatedCU.GBiIdx    = bestCU->GBiIdx;
         }
+#if JVET_M0483_IBC
+        else if (CU::isIBC(*bestCU))
+        {
+          relatedCU.isIBC = true;
+#if HM_CODED_CU_INFO
+          relatedCU.isSkip |= bestCU->skip;
+#endif
+        }
+#endif
         else if( CU::isIntra( *bestCU ) )
         {
           relatedCU.isIntra   = true;
@@ -1677,6 +1928,12 @@ bool EncModeCtrlMTnoRQT::useModeResult( const EncTestMode& encTestmode, CodingSt
     {
       cuECtx.bestEmtSize2Nx2N1stPass = tempCS->cost;
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if (!cu.ispMode)
+    {
+      cuECtx.bestCostEmtFirstPassNoIsp = tempCS->cost;
+    }
+#endif
   }
 #endif
 
@@ -1710,31 +1967,28 @@ bool EncModeCtrlMTnoRQT::useModeResult( const EncTestMode& encTestmode, CodingSt
     cuECtx.set( MAX_QT_SUB_DEPTH, maxQtD );
   }
 
-  if( ( tempCS->sps->getSpsNext().getMTTMode() & 1 ) == 1 )
-  {
-    int maxMtD = tempCS->pcv->getMaxBtDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
+  int maxMtD = tempCS->pcv->getMaxBtDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
 
-    if( encTestmode.type == ETM_SPLIT_BT_H )
+  if( encTestmode.type == ETM_SPLIT_BT_H )
+  {
+    if( tempCS->cus.size() > 2 )
     {
-      if( tempCS->cus.size() > 2 )
-      {
-        int h_2   = tempCS->area.blocks[partitioner.chType].height / 2;
-        int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
-        int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
+      int h_2   = tempCS->area.blocks[partitioner.chType].height / 2;
+      int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
+      int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
 
-        cuECtx.set( DO_TRIH_SPLIT, cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD );
-      }
+      cuECtx.set( DO_TRIH_SPLIT, cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD );
     }
-    else if( encTestmode.type == ETM_SPLIT_BT_V )
+  }
+  else if( encTestmode.type == ETM_SPLIT_BT_V )
+  {
+    if( tempCS->cus.size() > 2 )
     {
-      if( tempCS->cus.size() > 2 )
-      {
-        int w_2   = tempCS->area.blocks[partitioner.chType].width / 2;
-        int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
-        int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
+      int w_2   = tempCS->area.blocks[partitioner.chType].width / 2;
+      int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
+      int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
 
-        cuECtx.set( DO_TRIV_SPLIT, cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD );
-      }
+      cuECtx.set( DO_TRIV_SPLIT, cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD );
     }
   }
 
diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h
index 422e4c80840c1bd6b3960c1b1abe75129e6c0249..bda381a20add28a2700b6d833f3939c0c24fc4df 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.h
+++ b/source/Lib/EncoderLib/EncModeCtrl.h
@@ -54,6 +54,9 @@
 
 enum EncTestModeType
 {
+#if JVET_M0253_HASH_ME
+  ETM_HASH_INTER,
+#endif
   ETM_MERGE_SKIP,
   ETM_INTER_ME,
   ETM_AFFINE,
@@ -137,6 +140,9 @@ inline bool isModeInter( const EncTestMode& encTestmode ) // perhaps remove
           || encTestmode.type == ETM_MERGE_SKIP
           || encTestmode.type == ETM_AFFINE
           || encTestmode.type == ETM_MERGE_TRIANGLE
+#if JVET_M0253_HASH_ME
+          || encTestmode.type == ETM_HASH_INTER
+#endif
          );
 }
 
@@ -178,6 +184,10 @@ struct ComprCUCtx
     , testModes     (            )
     , lastTestMode  (            )
     , earlySkip     ( false      )
+#if JVET_M0253_HASH_ME
+    , isHashPerfectMatch
+                    ( false      )
+#endif
     , bestCS        ( nullptr    )
     , bestCU        ( nullptr    )
     , bestTU        ( nullptr    )
@@ -194,6 +204,12 @@ struct ComprCUCtx
 #if ENABLE_SPLIT_PARALLELISM
     , isLevelSplitParallel
                     ( false )
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    , bestCostWithoutSplitFlags( MAX_DOUBLE )
+#if !JVET_M0464_UNI_MTS
+    , bestCostEmtFirstPassNoIsp( MAX_DOUBLE )
+#endif
 #endif
   {
     getAreaIdx( cs.area.Y(), *cs.pcv, cuX, cuY, cuW, cuH );
@@ -212,6 +228,9 @@ struct ComprCUCtx
   std::vector<EncTestMode>          testModes;
   EncTestMode                       lastTestMode;
   bool                              earlySkip;
+#if JVET_M0253_HASH_ME
+  bool                              isHashPerfectMatch;
+#endif
   CodingStructure                  *bestCS;
   CodingUnit                       *bestCU;
   TransformUnit                    *bestTU;
@@ -225,6 +244,12 @@ struct ComprCUCtx
   Distortion                        interHad;
 #if ENABLE_SPLIT_PARALLELISM
   bool                              isLevelSplitParallel;
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  double                            bestCostWithoutSplitFlags;
+#if !JVET_M0464_UNI_MTS
+  double                            bestCostEmtFirstPassNoIsp;
+#endif
 #endif
 
   template<typename T> T    get( int ft )       const { return typeid(T) == typeid(double) ? (T&)extraFeaturesd[ft] : T(extraFeatures[ft]); }
@@ -257,7 +282,7 @@ protected:
 public:
 
   virtual ~EncModeCtrl              () {}
-  
+
 #if REUSE_CU_RESULTS
   virtual void create               ( const EncCfg& cfg )                                                                   = 0;
   virtual void destroy              ()                                                                                      = 0;
@@ -287,6 +312,10 @@ public:
   EncTestMode  currTestMode         () const;
   EncTestMode  lastTestMode         () const;
   void         setEarlySkipDetected ();
+#if JVET_M0253_HASH_ME
+  void         setIsHashPerfectMatch( bool b ) { m_ComprCUCtxList.back().isHashPerfectMatch = b; }
+  bool         getIsHashPerfectMatch() { return m_ComprCUCtxList.back().isHashPerfectMatch; }
+#endif
   virtual void setBest              ( CodingStructure& cs );
   bool         anyMode              () const;
 
@@ -307,6 +336,14 @@ public:
   bool getSkipSecondEMTPass           ()                  const { return m_ComprCUCtxList.back().skipSecondEMTPass;       }
   void setSkipSecondEMTPass           ( bool b )                {        m_ComprCUCtxList.back().skipSecondEMTPass = b;   }
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  double getBestCostWithoutSplitFlags ()                  const { return m_ComprCUCtxList.back().bestCostWithoutSplitFlags;         }
+  void   setBestCostWithoutSplitFlags ( double cost )           { m_ComprCUCtxList.back().bestCostWithoutSplitFlags = cost;         }
+#if !JVET_M0464_UNI_MTS
+  double getEmtFirstPassNoIspCost     ()                  const { return m_ComprCUCtxList.back().bestCostEmtFirstPassNoIsp; }
+  void   setEmtFirstPassNoIspCost     ( double cost )           { m_ComprCUCtxList.back().bestCostEmtFirstPassNoIsp = cost; }
+#endif
+#endif
 
 protected:
   void xExtractFeatures ( const EncTestMode encTestmode, CodingStructure& cs );
@@ -318,6 +355,33 @@ protected:
 //////////////////////////////////////////////////////////////////////////
 // some utility interfaces that expose some functionality that can be used without concerning about which particular controller is used
 //////////////////////////////////////////////////////////////////////////
+#if JVET_M0140_SBT
+struct SaveLoadStructSbt
+{
+  uint8_t  numPuInfoStored;
+  uint32_t puSse[SBT_NUM_SL];
+  uint8_t  puSbt[SBT_NUM_SL];
+  uint8_t  puTrs[SBT_NUM_SL];
+};
+
+class SaveLoadEncInfoSbt
+{
+protected:
+  void init( const Slice &slice );
+  void create();
+  void destroy();
+
+private:
+  SaveLoadStructSbt ****m_saveLoadSbt;
+  Slice const       *m_sliceSbt;
+
+public:
+  virtual  ~SaveLoadEncInfoSbt() { }
+  void     resetSaveloadSbt( int maxSbtSize );
+  uint16_t findBestSbt( const UnitArea& area, const uint32_t curPuSse );
+  bool     saveBestSbt( const UnitArea& area, const uint32_t curPuSse, const uint8_t curPuSbt, const uint8_t curPuTrs );
+};
+#endif
 
 static const int MAX_STORED_CU_INFO_REFS = 4;
 
@@ -327,6 +391,9 @@ struct CodedCUInfo
   bool isIntra;
   bool isSkip;
   bool isMMVDSkip;
+#if JVET_M0483_IBC
+  bool isIBC;
+#endif
   bool validMv[NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
   Mv   saveMv [NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
 
@@ -389,7 +456,12 @@ struct BestEncodingInfo
 {
   CodingUnit     cu;
   PredictionUnit pu;
+#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
+  TransformUnit  tus[MAX_NUM_TUS];
+  size_t         numTus;
+#else
   TransformUnit  tu;
+#endif
   EncTestMode    testMode;
 
   int            poc;
@@ -436,6 +508,9 @@ class EncModeCtrlMTnoRQT : public EncModeCtrl, public CacheBlkInfoCtrl
 #if REUSE_CU_RESULTS
   , public BestEncInfoCache
 #endif
+#if JVET_M0140_SBT
+  , public SaveLoadEncInfoSbt
+#endif
 {
   enum ExtraFeatures
   {
diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ce7d76aa2f826341f21c7b15e6aa425b02a7441a
--- /dev/null
+++ b/source/Lib/EncoderLib/EncReshape.cpp
@@ -0,0 +1,1312 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, 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.
+*/
+
+/** \file     EncReshape.cpp
+\brief    encoder reshaper class
+*/
+#include "EncReshape.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#if JVET_M0427_INLOOP_RESHAPER
+//! \ingroup EncLib
+//! \{
+
+// ====================================================================================================================
+// Constructor / destructor / create / destroy
+// ====================================================================================================================
+
+EncReshape::EncReshape()
+{
+  m_CTUFlag      = false;
+  m_srcReshaped  = false;
+  m_recReshaped  = false;
+  m_reshape      = true;
+  m_exceedSTD    = false;
+  m_tcase        = 0;
+  m_rateAdpMode  = 0;
+  m_chromaAdj    = 0;
+}
+
+EncReshape::~EncReshape()
+{
+}
+
+void  EncReshape::createEnc(int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight, int bitDepth)
+{
+  m_lumaBD = bitDepth;
+  m_reshapeLUTSize = 1 << m_lumaBD;
+  m_initCWAnalyze = m_reshapeLUTSize / PIC_ANALYZE_CW_BINS;
+  m_initCW = m_reshapeLUTSize / PIC_CODE_CW_BINS;
+
+  if (m_fwdLUT.empty())
+    m_fwdLUT.resize(m_reshapeLUTSize, 0);
+  if (m_invLUT.empty())
+    m_invLUT.resize(m_reshapeLUTSize,0);
+  if (m_binCW.empty())
+    m_binCW.resize(PIC_ANALYZE_CW_BINS);
+  if (m_binImportance.empty())
+    m_binImportance.resize(PIC_ANALYZE_CW_BINS);
+  if (m_reshapePivot.empty())
+    m_reshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (m_chromaAdjHelpLUT.empty())
+    m_chromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 1<<CSCALE_FP_PREC);
+
+  m_sliceReshapeInfo.setUseSliceReshaper(true);
+  m_sliceReshapeInfo.setSliceReshapeChromaAdj(true);
+  m_sliceReshapeInfo.setSliceReshapeModelPresentFlag(true);
+  m_sliceReshapeInfo.reshaperModelMinBinIdx = 0;
+  m_sliceReshapeInfo.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1;
+  memset(m_sliceReshapeInfo.reshaperModelBinCWDelta, 0, (PIC_CODE_CW_BINS) * sizeof(int));
+
+  m_picWidth = picWidth;
+  m_picHeight = picHeight;
+  m_maxCUWidth = maxCUWidth;
+  m_maxCUHeight = maxCUHeight;
+  m_widthInCtus = (m_picWidth + m_maxCUWidth - 1) / m_maxCUWidth;
+  m_heightInCtus = (m_picHeight + m_maxCUHeight - 1) / m_maxCUHeight;
+  m_numCtuInFrame = m_widthInCtus * m_heightInCtus;
+}
+
+void  EncReshape::destroy()
+{
+}
+
+/**
+-Perform HDR set up
+\param   pcPic describe pointer of current coding picture
+\param   sliceType describe the slice type
+*/
+#if JVET_M0483_IBC
+void EncReshape::preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT)
+#else
+void EncReshape::preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isIBC)
+#endif
+{
+  if (m_lumaBD >= 10)
+  {
+    m_sliceReshapeInfo.sliceReshaperEnableFlag = true;
+    if (reshapeCW.rspIntraPeriod == 1)
+    {
+      if (pcPic->getPOC() == 0)          { m_sliceReshapeInfo.sliceReshaperModelPresentFlag = true;  }
+      else                               { m_sliceReshapeInfo.sliceReshaperModelPresentFlag = false; }
+    }
+    else
+    {
+#if JVET_M0483_IBC
+      if (sliceType == I_SLICE )                                              { m_sliceReshapeInfo.sliceReshaperModelPresentFlag = true;  }
+#else
+      if (sliceType == I_SLICE || (sliceType == P_SLICE && isIBC))            { m_sliceReshapeInfo.sliceReshaperModelPresentFlag = true;  }
+#endif
+      else                                                                    { m_sliceReshapeInfo.sliceReshaperModelPresentFlag = false; }
+    }
+#if JVET_M0483_IBC
+    if (sliceType == I_SLICE  && isDualT)                                     { m_sliceReshapeInfo.enableChromaAdj = 0;                   }
+#else
+    if ((sliceType == I_SLICE || (sliceType == P_SLICE && isIBC)) && isDualT) { m_sliceReshapeInfo.enableChromaAdj = 0;                   }
+#endif
+    else                                                                      { m_sliceReshapeInfo.enableChromaAdj = 1;                   }
+  }
+  else
+  {
+    m_sliceReshapeInfo.sliceReshaperEnableFlag = false;
+    m_sliceReshapeInfo.sliceReshaperModelPresentFlag = false;
+  }
+}
+
+/**
+-Perform picture analysis for SDR
+\param   pcPic describe pointer of current coding picture
+\param   sliceType describe the slice type
+\param   reshapeCW describe some input info
+*/
+#if JVET_M0483_IBC
+void EncReshape::preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT)
+#else
+void EncReshape::preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isIBC)
+#endif
+{
+  m_sliceReshapeInfo.sliceReshaperModelPresentFlag = true;
+  m_sliceReshapeInfo.sliceReshaperEnableFlag = true;
+
+  int modIP = pcPic->getPOC() - pcPic->getPOC() / reshapeCW.rspFpsToIp * reshapeCW.rspFpsToIp;
+#if JVET_M0483_IBC
+  if (sliceType == I_SLICE || (reshapeCW.rspIntraPeriod == -1 && modIP == 0))
+#else
+  if (sliceType == I_SLICE || (reshapeCW.rspIntraPeriod == -1 && modIP == 0) || (sliceType == P_SLICE && isIBC))
+#endif
+  {
+    if (m_sliceReshapeInfo.sliceReshaperModelPresentFlag == true)
+    {
+      int stdMin = 16 <<(m_lumaBD-8);
+      int stdMax = 235 << (m_lumaBD - 8);
+      int  binLen = m_reshapeLUTSize / PIC_ANALYZE_CW_BINS;
+
+      m_reshapeCW = reshapeCW;
+      m_initCWAnalyze = binLen;
+
+      for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+      {
+        m_binImportance[b] = 0;
+        m_binCW[b] = binLen;
+      }
+
+      int startBinIdx = stdMin / binLen;
+      int endBinIdx = stdMax / binLen;
+      m_sliceReshapeInfo.reshaperModelMinBinIdx = startBinIdx;
+      m_sliceReshapeInfo.reshaperModelMaxBinIdx = endBinIdx;
+
+      PelBuf picY = pcPic->getOrigBuf(COMPONENT_Y);
+      const int width = picY.width;
+      const int height = picY.height;
+      const int stride = picY.stride;
+
+      double blockBinVarSum[PIC_ANALYZE_CW_BINS] = { 0.0 };
+      uint32_t   bockBinCnt[PIC_ANALYZE_CW_BINS] = { 0 };
+
+      const int PIC_ANALYZE_WIN_SIZE = 5;
+      const uint32_t winSize = PIC_ANALYZE_WIN_SIZE;
+      const uint32_t winLens = (winSize - 1) >> 1;
+
+      int64_t tempSq = 0;
+      int64_t leftSum = 0, leftSumSq = 0;
+      int64_t *leftColSum = new int64_t[width];
+      int64_t *leftColSumSq = new int64_t[width];
+      memset(leftColSum, 0, width * sizeof(int64_t));
+      memset(leftColSumSq, 0, width * sizeof(int64_t));
+      int64_t topSum = 0, topSumSq = 0;
+      int64_t *topRowSum = new int64_t[height];
+      int64_t *topRowSumSq = new int64_t[height];
+      memset(topRowSum, 0, height * sizeof(int64_t));
+      memset(topRowSumSq, 0, height * sizeof(int64_t));
+      int64_t *topColSum = new int64_t[width];
+      int64_t *topColSumSq = new int64_t[width];
+      memset(topColSum, 0, width * sizeof(int64_t));
+      memset(topColSumSq, 0, width * sizeof(int64_t));
+
+      for (uint32_t y = 0; y < height; y++)
+      {
+        for (uint32_t x = 0; x < width; x++)
+        {
+          const Pel pxlY = picY.buf[x];
+          int64_t sum = 0;
+          int64_t sumSq = 0;
+          uint32_t numPixInPart = 0;
+
+          uint32_t y1 = std::max((int)(y - winLens), 0);
+          uint32_t y2 = std::min((int)(y + winLens), (height - 1));
+          uint32_t x1 = std::max((int)(x - winLens), 0);
+          uint32_t x2 = std::min((int)(x + winLens), (width - 1));
+
+
+          uint32_t bx = 0, by = 0;
+          const Pel *pWinY = &picY.buf[0];
+          numPixInPart = (x2 - x1 + 1) * (y2 - y1 + 1);
+
+          if (x == 0 && y == 0)           // for the 1st Pixel, calc all points
+          {
+            for (by = y1; by <= y2; by++)
+            {
+              for (bx = x1; bx <= x2; bx++)
+              {
+                tempSq = pWinY[bx] * pWinY[bx];
+                leftSum += pWinY[bx];
+                leftSumSq += tempSq;
+                leftColSum[bx] += pWinY[bx];
+                leftColSumSq[bx] += tempSq;
+                topColSum[bx] += pWinY[bx];
+                topColSumSq[bx] += tempSq;
+                topRowSum[by] += pWinY[bx];
+                topRowSumSq[by] += tempSq;
+              }
+              pWinY += stride;
+            }
+            topSum = leftSum;
+            topSumSq = leftSumSq;
+            sum = leftSum;
+            sumSq = leftSumSq;
+          }
+          else if (x == 0 && y > 0)       // for the 1st column, calc the bottom stripe
+          {
+            if (y < height - winLens)
+            {
+              pWinY += winLens*stride;
+              topRowSum[y + winLens] = 0;
+              topRowSumSq[y + winLens] = 0;
+              for (bx = x1; bx <= x2; bx++)
+              {
+                topRowSum[y + winLens] += pWinY[bx];
+                topRowSumSq[y + winLens] += pWinY[bx] * pWinY[bx];
+              }
+              topSum += topRowSum[y + winLens];
+              topSumSq += topRowSumSq[y + winLens];
+            }
+            if (y > winLens)
+            {
+              topSum -= topRowSum[y - 1 - winLens];
+              topSumSq -= topRowSumSq[y - 1 - winLens];
+            }
+
+            memset(leftColSum, 0, width * sizeof(int64_t));
+            memset(leftColSumSq, 0, width * sizeof(int64_t));
+            pWinY = &picY.buf[0];
+            pWinY -= (y <= winLens ? y : winLens)*stride;
+            for (by = y1; by <= y2; by++)
+            {
+              for (bx = x1; bx <= x2; bx++)
+              {
+                leftColSum[bx] += pWinY[bx];
+                leftColSumSq[bx] += pWinY[bx] * pWinY[bx];
+              }
+              pWinY += stride;
+            }
+
+            leftSum = topSum;
+            leftSumSq = topSumSq;
+            sum = topSum;
+            sumSq = topSumSq;
+          }
+
+          else if (x > 0)
+          {
+            if (x < width - winLens)
+            {
+              pWinY -= (y <= winLens ? y : winLens)*stride;
+              if (y == 0)                 // for the 1st row, calc the right stripe
+              {
+                leftColSum[x + winLens] = 0;
+                leftColSumSq[x + winLens] = 0;
+                for (by = y1; by <= y2; by++)
+                {
+                  leftColSum[x + winLens] += pWinY[x + winLens];
+                  leftColSumSq[x + winLens] += pWinY[x + winLens] * pWinY[x + winLens];
+                  pWinY += stride;
+                }
+              }
+              else                        // for the main area, calc the B-R point
+              {
+                leftColSum[x + winLens] = topColSum[x + winLens];
+                leftColSumSq[x + winLens] = topColSumSq[x + winLens];
+                if (y < height - winLens)
+                {
+                  pWinY = &picY.buf[0];
+                  pWinY += winLens * stride;
+                  leftColSum[x + winLens] += pWinY[x + winLens];
+                  leftColSumSq[x + winLens] += pWinY[x + winLens] * pWinY[x + winLens];
+                }
+                if (y > winLens)
+                {
+                  pWinY = &picY.buf[0];
+                  pWinY -= (winLens + 1) * stride;
+                  leftColSum[x + winLens] -= pWinY[x + winLens];
+                  leftColSumSq[x + winLens] -= pWinY[x + winLens] * pWinY[x + winLens];
+                }
+              }
+              topColSum[x + winLens] = leftColSum[x + winLens];
+              topColSumSq[x + winLens] = leftColSumSq[x + winLens];
+              leftSum += leftColSum[x + winLens];
+              leftSumSq += leftColSumSq[x + winLens];
+            }
+            if (x > winLens)
+            {
+              leftSum -= leftColSum[x - 1 - winLens];
+              leftSumSq -= leftColSumSq[x - 1 - winLens];
+            }
+            sum = leftSum;
+            sumSq = leftSumSq;
+          }
+
+          double average = double(sum) / numPixInPart;
+          double variance = double(sumSq) / numPixInPart - average * average;
+          uint32_t binNum = (uint32_t)(pxlY/PIC_ANALYZE_CW_BINS);
+
+          if (m_lumaBD > 10)
+          {
+            average = average / (double)(1<<(m_lumaBD - 10));
+            variance = variance / (double)(1 << (2*m_lumaBD - 20));
+            binNum = (uint32_t)((pxlY>>(m_lumaBD - 10)) / PIC_ANALYZE_CW_BINS);
+          }
+          else if (m_lumaBD < 10)
+          {
+            average = average * (double)(1 << (10 - m_lumaBD));
+            variance = variance * (double)(1 << (20-2*m_lumaBD));
+            binNum = (uint32_t)((pxlY << (10 - m_lumaBD)) / PIC_ANALYZE_CW_BINS);
+          }
+          double varLog10 = log10(variance + 1.0);
+          blockBinVarSum[binNum] += varLog10;
+          bockBinCnt[binNum]++;
+        }
+        picY.buf += stride;
+      }
+
+      delete[] topColSum;
+      delete[] topColSumSq;
+      delete[] topRowSum;
+      delete[] topRowSumSq;
+      delete[] leftColSum;
+      delete[] leftColSumSq;
+
+      for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+      {
+        if (bockBinCnt[b] > 0)
+          blockBinVarSum[b] = blockBinVarSum[b] / bockBinCnt[b];
+      }
+
+      m_reshape = true;
+      m_exceedSTD = false;
+      m_useAdpCW = false;
+      m_chromaWeight = 1.0;
+      m_sliceReshapeInfo.enableChromaAdj = 1;
+      bool   intraAdp = false;
+      bool   interAdp = true;
+      double reshapeTH1 = 0.0;
+      double reshapeTH2 = 5.0;
+      deriveReshapeParametersSDRfromStats(bockBinCnt, blockBinVarSum, &reshapeTH1, &reshapeTH2, &intraAdp, &interAdp);
+
+      if (m_rateAdpMode == 2 && reshapeCW.rspBaseQP <= 22)
+      {
+        intraAdp = false;
+        interAdp = false;
+      }
+
+      m_sliceReshapeInfo.sliceReshaperEnableFlag = intraAdp;
+
+      if (!intraAdp && !interAdp)
+      {
+        m_sliceReshapeInfo.sliceReshaperModelPresentFlag = false;
+        m_reshape = false;
+        return;
+      }
+
+      if (m_exceedSTD)
+      {
+        startBinIdx = 2;
+        endBinIdx = 29;
+        for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+        {
+          if (bockBinCnt[b] > 0 && b < startBinIdx)
+            startBinIdx = b;
+          if (bockBinCnt[b] > 0 && b > endBinIdx)
+            endBinIdx = b;
+        }
+        m_sliceReshapeInfo.reshaperModelMinBinIdx = startBinIdx;
+        m_sliceReshapeInfo.reshaperModelMaxBinIdx = endBinIdx;
+      }
+
+      m_initCWAnalyze = m_lumaBD > 10 ? (m_initCWAnalyze >> (m_lumaBD - 10)) : m_lumaBD < 10 ? (m_initCWAnalyze << (10 - m_lumaBD)) : m_initCWAnalyze;
+      if (reshapeCW.rspBaseQP <= 22 && m_rateAdpMode == 1)
+      {
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (i >= startBinIdx && i <= endBinIdx)
+            m_binCW[i] = m_initCWAnalyze + 1;
+          else
+            m_binCW[i] = 0;
+        }
+      }
+      else if (m_useAdpCW)
+      {
+        double Alpha = 1.0, Beta = 0.0;
+        deriveReshapeParameters(blockBinVarSum, startBinIdx, endBinIdx, m_reshapeCW, Alpha, Beta);
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (i >= startBinIdx && i <= endBinIdx)
+            m_binCW[i] = (uint32_t)round(Alpha*blockBinVarSum[i] + Beta);
+          else
+            m_binCW[i] = 0;
+        }
+      }
+      else
+      {
+        for (int b = startBinIdx; b <= endBinIdx; b++)
+        {
+          if (blockBinVarSum[b] < reshapeTH1)
+            m_binImportance[b] = 2;
+          else if (blockBinVarSum[b] > reshapeTH2)
+            m_binImportance[b] = 3;
+          else
+            m_binImportance[b] = 1;
+        }
+
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (m_binImportance[i] == 0)
+            m_binCW[i] = 0;
+          else if (m_binImportance[i] == 1)
+            m_binCW[i] = m_initCWAnalyze + 1;
+          else if (m_binImportance[i] == 2)
+            m_binCW[i] = m_reshapeCW.binCW[0];
+          else if (m_binImportance[i] == 3)
+            m_binCW[i] = m_reshapeCW.binCW[1];
+          else
+            THROW("SDR Reshape Bin Importance not supported");
+        }
+      }
+      if (m_reshapeCW.rspPicSize <= 1497600 && reshapeCW.rspIntraPeriod == -1 && modIP == 0 && sliceType != I_SLICE)
+      {
+        m_sliceReshapeInfo.sliceReshaperEnableFlag = false;
+      }
+
+    }
+    m_chromaAdj = m_sliceReshapeInfo.enableChromaAdj;
+#if JVET_M0483_IBC
+    if (sliceType == I_SLICE && isDualT)
+#else
+    if ((sliceType == I_SLICE || (sliceType == P_SLICE && isIBC)) && isDualT)
+#endif
+    {
+        m_sliceReshapeInfo.enableChromaAdj = 0;
+    }
+  }
+  else // Inter slices
+  {
+    m_sliceReshapeInfo.sliceReshaperModelPresentFlag = false;
+    m_sliceReshapeInfo.enableChromaAdj = m_chromaAdj;
+
+    if (!m_reshape)
+    {
+      m_sliceReshapeInfo.sliceReshaperEnableFlag = false;
+    }
+    else
+    {
+      const int cTid = m_reshapeCW.rspTid;
+      bool enableRsp = m_tcase == 5 ? false : (m_tcase < 5 ? (cTid < m_tcase + 1 ? false : true) : (cTid <= 10 - m_tcase ? true : false));
+      m_sliceReshapeInfo.sliceReshaperEnableFlag = enableRsp;
+    }
+  }
+}
+
+// Bubble Sort to  descending order with index
+void EncReshape::bubbleSortDsd(double* array, int * idx, int n)
+{
+  int i, j;
+  bool swapped;
+  for (i = 0; i < n - 1; i++)
+  {
+    swapped = false;
+    for (j = 0; j < n - i - 1; j++)
+    {
+      if (array[j] < array[j + 1])
+      {
+        swap(&array[j], &array[j + 1]);
+        swap(&idx[j], &idx[j + 1]);
+        swapped = true;
+      }
+    }
+    if (swapped == false)
+      break;
+  }
+}
+
+void EncReshape::deriveReshapeParametersSDRfromStats(uint32_t * blockBinCnt, double *blockBinVarSum, double* reshapeTH1, double* reshapeTH2, bool *intraAdp, bool *interAdp)
+{
+  int    binIdxSortDsd[PIC_ANALYZE_CW_BINS]    = { 0 };
+  double binVarSortDsd[PIC_ANALYZE_CW_BINS]    = { 0.0 };
+  double binHist[PIC_ANALYZE_CW_BINS]          = { 0.0 };
+  double binVarSortDsdCDF[PIC_ANALYZE_CW_BINS] = { 0.0 };
+  double maxBinVar = 0.0, meanBinVar = 0.0, minBinVar = 5.0;
+  int    nonZeroBinCt = 0;
+  int    firstBinVarLessThanVal1 = 0;
+  int    firstBinVarLessThanVal2 = 0;
+  int    firstBinVarLessThanVal3 = 0;
+  int    firstBinVarLessThanVal4 = 0;
+
+  for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+  {
+    binHist[b] = (double) blockBinCnt[b] / (double)(m_reshapeCW.rspPicSize);
+    if (binHist[b] > 0.001)
+    {
+      nonZeroBinCt++;
+      meanBinVar += blockBinVarSum[b];
+      if (blockBinVarSum[b] > maxBinVar)        {        maxBinVar = blockBinVarSum[b];      }
+      if (blockBinVarSum[b] < minBinVar)        {        minBinVar = blockBinVarSum[b];      }
+    }
+    binVarSortDsd[b] = blockBinVarSum[b];
+    binIdxSortDsd[b] = b;
+  }
+  if ((binHist[0] + binHist[1] + binHist[PIC_ANALYZE_CW_BINS - 2] + binHist[PIC_ANALYZE_CW_BINS - 1]) > 0.01)   {    m_exceedSTD = true;  }
+  if ((binHist[PIC_ANALYZE_CW_BINS - 2] + binHist[PIC_ANALYZE_CW_BINS - 1]) > 0.01)   {    *interAdp = false;    return;   }
+  else                                                                                {    *interAdp = true;               }
+
+  meanBinVar = meanBinVar / (double)nonZeroBinCt;
+  bubbleSortDsd(binVarSortDsd, binIdxSortDsd, PIC_ANALYZE_CW_BINS);
+  binVarSortDsdCDF[0] = binHist[binIdxSortDsd[0]];
+
+  for (int b = 1; b < PIC_ANALYZE_CW_BINS; b++)
+  {
+    binVarSortDsdCDF[b] = binVarSortDsdCDF[b - 1] + binHist[binIdxSortDsd[b]];
+  }
+
+  for (int b = 0; b < PIC_ANALYZE_CW_BINS - 1; b++)
+  {
+    if (binVarSortDsd[b] > 3.5)     {      firstBinVarLessThanVal1 = b + 1;    }
+    if (binVarSortDsd[b] > 3.0)     {      firstBinVarLessThanVal2 = b + 1;    }
+    if (binVarSortDsd[b] > 2.5)     {      firstBinVarLessThanVal3 = b + 1;    }
+    if (binVarSortDsd[b] > 2.0)     {      firstBinVarLessThanVal4 = b + 1;    }
+  }
+
+  m_reshapeCW.binCW[0] = 38;
+  m_reshapeCW.binCW[1] = 28;
+
+  if (m_reshapeCW.rspIntraPeriod == -1)
+  {
+    *intraAdp = true;
+    if (m_reshapeCW.rspPicSize > 1497600)
+    {
+      m_reshapeCW.binCW[0] = 36;
+      *reshapeTH1 = 2.4;
+      *reshapeTH2 = 4.5;
+      m_rateAdpMode = 2;
+
+      if (meanBinVar >= 2.52)
+      {
+        if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *reshapeTH1 = 2.5;
+          *reshapeTH2 = 3.0;
+        }
+        else if (binVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && binVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+        {
+          *reshapeTH1 = 2.2;
+        }
+        else if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+        {
+          m_reshapeCW.binCW[1] = 30;
+          *reshapeTH1 = 2.0;
+          m_rateAdpMode = 0;
+        }
+        else
+        {
+          m_reshapeCW.binCW[1] = 30;
+          m_rateAdpMode = 1;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 660480)
+    {
+      m_reshapeCW.binCW[0] = 34;
+      *reshapeTH1 = 3.4;
+      *reshapeTH2 = 4.0;
+      m_rateAdpMode = 2;
+
+      if (binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          m_useAdpCW = true;
+          m_reshapeCW.binCW[0] = 38;
+        }
+        else
+        {
+          m_reshapeCW.binCW[0] = 40;
+          *reshapeTH1 = 2.2;
+          *reshapeTH2 = 4.5;
+          m_rateAdpMode = 0;
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          m_reshapeCW.binCW[1] = 30;
+        }
+        else
+        {
+          m_reshapeCW.binCW[1] = 28;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 249600)
+    {
+      m_reshapeCW.binCW[0] = 36;
+      *reshapeTH1 = 2.5;
+      *reshapeTH2 = 4.5;
+
+      if (m_exceedSTD)
+      {
+        m_reshapeCW.binCW[0] = 36;
+        m_reshapeCW.binCW[1] = 30;
+      }
+      if (minBinVar > 2.6)
+      {
+        *reshapeTH1 = 3.0;
+      }
+      else {
+        double diff1 = binVarSortDsdCDF[firstBinVarLessThanVal4] - binVarSortDsdCDF[firstBinVarLessThanVal3];
+        double diff2 = binVarSortDsdCDF[firstBinVarLessThanVal2] - binVarSortDsdCDF[firstBinVarLessThanVal1];
+        if (diff1 > 0.4 || binVarSortDsdCDF[firstBinVarLessThanVal1] > 0.1)
+        {
+          m_useAdpCW = true;
+          m_rateAdpMode = 1;
+        }
+        else if (diff2 <= 0.1 && binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.99 && binVarSortDsdCDF[firstBinVarLessThanVal3] > 0.642 && binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.03)
+        {
+          m_useAdpCW = true;
+          m_rateAdpMode = 1;
+        }
+        else
+        {
+          m_rateAdpMode = 2;
+        }
+      }
+    }
+    else
+    {
+      m_reshapeCW.binCW[0] = 36;
+      *reshapeTH1 = 2.6;
+      *reshapeTH2 = 4.5;
+
+      if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5 && maxBinVar < 4.7)
+      {
+        *reshapeTH1 = 3.2;
+        m_rateAdpMode = 1;
+      }
+    }
+  }
+  else if (m_reshapeCW.rspIntraPeriod == 1)
+  {
+    *intraAdp = true;
+    if (m_reshapeCW.rspPicSize > 5184000)
+    {
+      *reshapeTH1 = 2.0;
+      *reshapeTH2 = 3.0;
+      m_rateAdpMode = 2;
+
+      if (maxBinVar > 2.4)
+      {
+        if (binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.88)
+        {
+          if (maxBinVar < 2.695)
+          {
+            *reshapeTH2 = 2.2;
+          }
+          else
+          {
+            if (binVarSortDsdCDF[firstBinVarLessThanVal3] < 0.45)
+            {
+              *reshapeTH1 = 2.5;
+              *reshapeTH2 = 4.0;
+              m_reshapeCW.binCW[0] = 36;
+              m_sliceReshapeInfo.enableChromaAdj = 0;
+              m_rateAdpMode = 0;
+            }
+            else
+            {
+              m_useAdpCW = true;
+              m_reshapeCW.binCW[0] = 36;
+              m_reshapeCW.binCW[1] = 30;
+            }
+          }
+        }
+        else
+        {
+          if (maxBinVar > 2.8)
+          {
+            *reshapeTH1 = 2.2;
+            *reshapeTH2 = 4.0;
+            m_reshapeCW.binCW[0] = 36;
+            m_sliceReshapeInfo.enableChromaAdj = 0;
+          }
+          else
+          {
+            m_useAdpCW = true;
+            m_reshapeCW.binCW[0] = 38;
+            m_reshapeCW.binCW[1] = 28;
+          }
+        }
+      }
+      else
+      {
+        if (maxBinVar > 2.24)
+        {
+          m_useAdpCW = true;
+          m_reshapeCW.binCW[0] = 34;
+          m_reshapeCW.binCW[1] = 30;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 1497600)
+    {
+      *reshapeTH1 = 2.0;
+      *reshapeTH2 = 4.5;
+      m_rateAdpMode = 2;
+
+      if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+      {
+        int firstVarCDFLargerThanVal = 1;
+        for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+        {
+          if (binVarSortDsdCDF[b] > 0.7)
+          {
+            firstVarCDFLargerThanVal = b;
+            break;
+          }
+        }
+        if (meanBinVar < 2.52 || binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *reshapeTH1 = 2.2;
+          *reshapeTH2 = (binVarSortDsd[firstVarCDFLargerThanVal] + binVarSortDsd[firstVarCDFLargerThanVal - 1]) / 2.0;
+        }
+        else
+        {
+          m_reshapeCW.binCW[1] = 30;
+          *reshapeTH2 = 2.8;
+        }
+      }
+      else if (binVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && binVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+      {
+        m_reshapeCW.binCW[0] = 36;
+        *reshapeTH1 = 3.5;
+        m_rateAdpMode = 1;
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 660480)
+    {
+      *reshapeTH1 = 2.5;
+      *reshapeTH2 = 4.5;
+      m_rateAdpMode = 1;
+
+      if (binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          *reshapeTH1 = 2.0;
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          m_reshapeCW.binCW[0] = 35;
+        }
+        else
+        {
+          *reshapeTH1 = 2.8;
+          m_reshapeCW.binCW[0] = 35;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 249600)
+    {
+      m_rateAdpMode = 1;
+      m_reshapeCW.binCW[0] = 36;
+      *reshapeTH1 = 2.5;
+      *reshapeTH2 = 4.5;
+    }
+    else
+    {
+      if (binVarSortDsdCDF[firstBinVarLessThanVal2] < 0.33 && m_reshapeCW.rspFps>40)
+      {
+        *intraAdp = false;
+        *interAdp = false;
+      }
+      else
+      {
+        m_rateAdpMode = 1;
+        m_reshapeCW.binCW[0] = 36;
+        *reshapeTH1 = 3.0;
+        *reshapeTH2 = 4.0;
+      }
+    }
+  }
+  else
+  {
+    if (m_reshapeCW.rspPicSize > 5184000)
+    {
+      m_reshapeCW.binCW[0] = 40;
+      *reshapeTH2 = 4.0;
+      m_rateAdpMode = 2;
+
+      if (maxBinVar < 2.4)
+      {
+        *reshapeTH1 = 3.0;
+        if (m_reshapeCW.rspBaseQP <= 22)
+          m_tcase = 3;
+      }
+      else if (maxBinVar > 3.0)
+      {
+        if (minBinVar > 1)
+        {
+          m_reshapeCW.binCW[0] = 36;
+          *reshapeTH1 = 2.8;
+          *reshapeTH2 = 3.5;
+          m_sliceReshapeInfo.enableChromaAdj = 0;
+          m_chromaWeight = 1.05;
+          m_rateAdpMode = 0;
+        }
+        else
+        {
+          m_reshapeCW.binCW[0] = 36;
+          *reshapeTH1 = 2.2;
+          *reshapeTH2 = 3.5;
+          m_sliceReshapeInfo.enableChromaAdj = 0;
+          m_chromaWeight = 0.95;
+        }
+      }
+      else
+      {
+        *reshapeTH1 = 1.5;
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 1497600)
+    {
+      *reshapeTH1 = 2.5;
+      *reshapeTH2 = 4.5;
+      m_rateAdpMode = 1;
+
+      if (meanBinVar < 2.52)
+      {
+        *intraAdp = true;
+        m_rateAdpMode = 0;
+        m_tcase = 9;
+      }
+      else
+      {
+        if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *reshapeTH2 = 3.0;
+          *intraAdp = true;
+        }
+        else if (binVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && binVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+        {
+          *reshapeTH1 = 3.0;
+          *intraAdp = true;
+          m_rateAdpMode = 0;
+          m_tcase = 9;
+        }
+        else if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+        {
+          *reshapeTH1 = 2.4;
+          m_reshapeCW.binCW[0] = 36;
+        }
+        else
+        {
+          *reshapeTH1 = 2.4;
+          m_reshapeCW.binCW[0] = 36;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 660480)
+    {
+      *intraAdp = true;
+      m_rateAdpMode = 1;
+
+      if (binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          *reshapeTH1 = 2.1;
+          *reshapeTH2 = 3.5;
+        }
+        else
+        {
+          *reshapeTH1 = 2.4;
+          *reshapeTH2 = 4.5;
+          m_reshapeCW.binCW[0] = 40;
+          m_rateAdpMode = 0;
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          *reshapeTH1 = 3.5;
+          *reshapeTH2 = 3.8;
+        }
+        else
+        {
+          *reshapeTH1 = 3.0;
+          *reshapeTH2 = 4.0;
+          m_reshapeCW.binCW[1] = 30;
+        }
+      }
+    }
+    else if (m_reshapeCW.rspPicSize > 249600)
+    {
+      m_reshapeCW.binCW[1] = 30;
+      *reshapeTH1 = 2.5;
+      *reshapeTH2 = 4.5;
+      *intraAdp = true;
+      m_rateAdpMode = 1;
+
+      if (minBinVar > 2.6)
+      {
+        *reshapeTH1 = 3.2;
+        m_rateAdpMode = 0;
+        m_tcase = 9;
+      }
+      else {
+        double diff1 = binVarSortDsdCDF[firstBinVarLessThanVal4] - binVarSortDsdCDF[firstBinVarLessThanVal3];
+        double diff2 = binVarSortDsdCDF[firstBinVarLessThanVal2] - binVarSortDsdCDF[firstBinVarLessThanVal1];
+        if (diff1 > 0.4 || binVarSortDsdCDF[firstBinVarLessThanVal1] > 0.1)
+        {
+          *reshapeTH1 = 2.9;
+          *intraAdp = false;
+        }
+        else
+        {
+          if (diff2 > 0.1)
+          {
+            *reshapeTH1 = 2.5;
+          }
+          else
+          {
+            *reshapeTH1 = 2.9;
+            if (binVarSortDsdCDF[firstBinVarLessThanVal4] > 0.99 && binVarSortDsdCDF[firstBinVarLessThanVal3] > 0.642 && binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.03)
+            {
+              m_rateAdpMode = 0;
+              m_tcase = 9;
+            }
+          }
+        }
+      }
+    }
+    else
+    {
+      m_reshapeCW.binCW[0] = 36;
+      m_reshapeCW.binCW[1] = 30;
+      *reshapeTH1 = 2.6;
+      *reshapeTH2 = 4.5;
+      *intraAdp = true;
+      m_rateAdpMode = 1;
+      if (binVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5 && maxBinVar < 4.7)
+      {
+        *reshapeTH1 = 3.4;
+      }
+    }
+  }
+}
+
+void EncReshape::deriveReshapeParameters(double *array, int start, int end, ReshapeCW respCW, double &alpha, double &beta)
+{
+  double minVar = 10.0, maxVar = 0.0;
+  for (int b = start; b <= end; b++)
+  {
+    if (array[b] < minVar)       minVar = array[b];
+    if (array[b] > maxVar)       maxVar = array[b];
+  }
+  double maxCW = (double)respCW.binCW[0];
+  double minCW = (double)respCW.binCW[1];
+  alpha = (minCW - maxCW) / (maxVar - minVar);
+  beta = (maxCW*maxVar - minCW*minVar) / (maxVar - minVar);
+}
+
+/**
+-Init reshaping LUT  from dQP model
+*/
+void EncReshape::initLUTfromdQPModel()
+{
+  initModelParam();
+  int pwlFwdLUTsize = PIC_CODE_CW_BINS;
+  int pwlFwdBinLen = m_reshapeLUTSize / PIC_CODE_CW_BINS;
+  int p1 = m_dQPModel.scaleFracPrec;
+  int p2 = m_dQPModel.offsetFracPrec;
+  int totalShift = p1 + p2;
+  int scaleFP = (1 - 2 * m_dQPModel.scaleSign)  * m_dQPModel.scaleAbs;
+  int offsetFP = (1 - 2 * m_dQPModel.offsetSign) * m_dQPModel.offsetAbs;
+  int maxQP = (1 - 2 * m_dQPModel.maxQPSign)  * m_dQPModel.maxQPAbs;
+  int minQP = (1 - 2 * m_dQPModel.minQPSign)  * m_dQPModel.minQPAbs;
+  int maxFP = maxQP * (1 << totalShift);
+  int minFP = minQP * (1 << totalShift);
+  int temp, signval, absval;
+  int dQPDiv6FP;
+  int32_t * slopeLUT = new int32_t[m_reshapeLUTSize]();
+  int32_t * fwdLUTHighPrec = new int32_t[m_reshapeLUTSize]();
+
+  for (int i = 0; i < m_reshapeLUTSize; i++)
+  {
+    int inputY = m_lumaBD < 10 ? i << (10 - m_lumaBD) : m_lumaBD > 10 ? i >> (m_lumaBD - 10) : i;
+    temp = int64_t((scaleFP*inputY) * (1 << p2)) + int64_t(offsetFP * (1 << p1));
+    temp = temp > maxFP ? maxFP : temp < minFP ? minFP : temp;
+    signval = temp >= 0 ? 1 : -1;
+    absval = signval * temp;
+    dQPDiv6FP = signval * (((absval + 3) / 6 + (1 << (totalShift - 17))) >> (totalShift - 16));
+    slopeLUT[i] = calcEXP2(dQPDiv6FP);
+  }
+
+  if (m_dQPModel.fullRangeInputFlag == 0)
+  {
+    for (int i = 0; i < (16 << (m_lumaBD - 8)); i++)                    {      slopeLUT[i] = 0;    }
+    for (int i = (235 << (m_lumaBD - 8)); i < m_reshapeLUTSize; i++)    {      slopeLUT[i] = 0;    }
+  }
+
+  for (int i = 0; i < m_reshapeLUTSize - 1; i++)
+    fwdLUTHighPrec[i + 1] = fwdLUTHighPrec[i] + slopeLUT[i];
+  if (slopeLUT != nullptr)   {    delete[] slopeLUT;    slopeLUT = nullptr;  }
+
+  int max_Y = (fwdLUTHighPrec[m_reshapeLUTSize - 1] + (1 << 7)) >> 8;
+  int Roffset = max_Y >> 1;
+  for (int i = 0; i < m_reshapeLUTSize; i++)
+  {
+    m_fwdLUT[i] = (short)(((fwdLUTHighPrec[i] >> 8) * (m_reshapeLUTSize - 1) + Roffset) / max_Y);
+  }
+
+  if (fwdLUTHighPrec != nullptr)   {    delete[] fwdLUTHighPrec;    fwdLUTHighPrec = nullptr;  }
+  m_sliceReshapeInfo.reshaperModelMinBinIdx = 1;
+  m_sliceReshapeInfo.reshaperModelMaxBinIdx = 14;
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    int16_t X1 = i * pwlFwdBinLen;
+    m_reshapePivot[i] = m_fwdLUT[X1];
+  }
+  m_reshapePivot[pwlFwdLUTsize] = ((1 << m_lumaBD) - 1);
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_binCW[i] = m_reshapePivot[i + 1] - m_reshapePivot[i];
+  }
+
+  int maxAbsDeltaCW = 0, absDeltaCW = 0, deltaCW = 0;
+  for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
+  {
+    deltaCW = (int)m_binCW[i] - (int)m_initCW;
+    m_sliceReshapeInfo.reshaperModelBinCWDelta[i] = deltaCW;
+    absDeltaCW = (deltaCW < 0) ? (-deltaCW) : deltaCW;
+    if (absDeltaCW > maxAbsDeltaCW)     {      maxAbsDeltaCW = absDeltaCW;    }
+  }
+  m_sliceReshapeInfo.maxNbitsNeededDeltaCW = g_aucLog2[maxAbsDeltaCW << 1];
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    int16_t Y1 = m_reshapePivot[i];
+    int16_t Y2 = m_reshapePivot[i + 1];
+    m_fwdLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
+    int log2PwlFwdBinLen = g_aucLog2[pwlFwdBinLen];
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2PwlFwdBinLen - 1))) >> (log2PwlFwdBinLen);
+    for (int j = 1; j < pwlFwdBinLen; j++)
+    {
+      int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      m_fwdLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)((1<<m_lumaBD) -1), (Pel)tempVal);
+    }
+  }
+  reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
+  updateChromaScaleLUT();
+}
+
+
+/**
+-Perform fixe point exp2 calculation
+\param   val  input value
+\retval  output value = exp2(val)
+*/
+int EncReshape::calcEXP2(int val)
+{
+  int32_t i, f, r, s;
+  r = 0x00000e20;
+
+  i = ((int32_t)(val)+0x8000) & ~0xffff;
+  f = (int32_t)(val)-i;
+  s = ((15 << 16) - i) >> 16;
+
+  r = (r * f + 0x3e1cc333) >> 17;
+  r = (r * f + 0x58bd46a6) >> 16;
+  r = r * f + 0x7ffde4a3;
+  return (uint32_t)r >> s;
+}
+
+void EncReshape::constructReshaperSDR()
+{
+  int bdShift = m_lumaBD - 10;
+  int usedCW = 0;
+  int totCW = bdShift != 0 ? (bdShift > 0 ? m_reshapeLUTSize / (1<<bdShift) : m_reshapeLUTSize * (1 << (-bdShift))) : m_reshapeLUTSize;
+  int histBins = PIC_ANALYZE_CW_BINS;
+  int histLenth = totCW/histBins;
+  int log2HistLenth = g_aucLog2[histLenth];
+  int16_t *tempFwdLUT = new int16_t[m_reshapeLUTSize + 1]();
+  int i, j;
+  int cwScaleBins1, cwScaleBins2;
+  int maxAllowedCW = totCW-1;
+
+  cwScaleBins1 = m_reshapeCW.binCW[0];
+  cwScaleBins2 = m_reshapeCW.binCW[1];
+
+  for (i = 0; i < histBins; i++)
+    usedCW += m_binCW[i];
+
+  if (usedCW > maxAllowedCW)
+  {
+    int cnt0 = 0, cnt1 = 0, cnt2 = 0;
+    for (i = 0; i < histBins; i++)
+    {
+      if (m_binCW[i] == histLenth + 1)             cnt0++;
+      else if (m_binCW[i] == cwScaleBins1)         cnt1++;
+      else if (m_binCW[i] == cwScaleBins2)         cnt2++;
+    }
+
+    int resCW = usedCW - maxAllowedCW;
+    int cwReduce1 = (cwScaleBins1 - histLenth - 1) * cnt1;
+    int cwReduce2 = (histLenth + 1 - cwScaleBins2) * cnt0;
+
+    if (resCW <= cwReduce1)
+    {
+      int idx = 0;
+      while (resCW > 0)
+      {
+        if (m_binCW[idx] > (histLenth + 1))
+        {
+          m_binCW[idx]--;
+          resCW--;
+        }
+        idx++;
+        if (idx == histBins)
+          idx = 0;
+      }
+    }
+    else if (resCW > cwReduce1 && resCW <= (cwReduce1 + cwReduce2))
+    {
+      resCW -= cwReduce1;
+      int idx = 0;
+      while (resCW > 0)
+      {
+        if (m_binCW[idx] > cwScaleBins2 && m_binCW[idx] < cwScaleBins1)
+        {
+          m_binCW[idx]--;
+          resCW--;
+        }
+        idx++;
+        if (idx == histBins)
+          idx = 0;
+      }
+      for (i = 0; i < histBins; i++)
+      {
+        if (m_binCW[i] == cwScaleBins1)
+          m_binCW[i] = histLenth + 1;
+      }
+    }
+    else if (resCW > (cwReduce1 + cwReduce2))
+    {
+      resCW -= (cwReduce1 + cwReduce2);
+      int idx = 0;
+      while (resCW > 0)
+      {
+        if (m_binCW[idx] > 0 && m_binCW[idx] < (histLenth + 1))
+        {
+          m_binCW[idx]--;
+          resCW--;
+        }
+        idx++;
+        if (idx == histBins)
+          idx = 0;
+      }
+      for (i = 0; i < histBins; i++)
+      {
+        if (m_binCW[i] == histLenth + 1)
+          m_binCW[i] = cwScaleBins2;
+        if (m_binCW[i] == cwScaleBins1)
+          m_binCW[i] = histLenth + 1;
+      }
+    }
+  }
+
+  if (bdShift != 0)
+  {
+    for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+    {
+      m_binCW[i] = bdShift > 0 ? m_binCW[i] * (1 << bdShift) : m_binCW[i] / (1 << (-bdShift));
+    }
+  }
+
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    m_binCW[i] = m_binCW[2 * i] + m_binCW[2 * i + 1];
+  }
+  m_sliceReshapeInfo.reshaperModelMinBinIdx = 0;
+  m_sliceReshapeInfo.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1;
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    if (m_binCW[i] > 0)
+    {
+      m_sliceReshapeInfo.reshaperModelMinBinIdx = i;
+      break;
+    }
+  }
+  for (int i = PIC_CODE_CW_BINS - 1; i >= 0; i--)
+  {
+    if (m_binCW[i] > 0)
+    {
+      m_sliceReshapeInfo.reshaperModelMaxBinIdx = i;
+      break;
+    }
+  }
+
+  int maxAbsDeltaCW = 0, absDeltaCW = 0, deltaCW = 0;
+  for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
+  {
+    deltaCW = (int)m_binCW[i] - (int)m_initCW;
+    m_sliceReshapeInfo.reshaperModelBinCWDelta[i] = deltaCW;
+    absDeltaCW = (deltaCW < 0) ? (-deltaCW) : deltaCW;
+    if (absDeltaCW > maxAbsDeltaCW)      {      maxAbsDeltaCW = absDeltaCW;    }
+  }
+  m_sliceReshapeInfo.maxNbitsNeededDeltaCW = std::max(1, (int)g_aucLog2[maxAbsDeltaCW << 1]);
+
+  histLenth = m_initCW;
+  log2HistLenth = g_aucLog2[histLenth];
+
+  int sumBins = 0;
+  for (i = 0; i < PIC_CODE_CW_BINS; i++)   { sumBins += m_binCW[i];  }
+  CHECK(sumBins >= m_reshapeLUTSize, "SDR CW assignment is wrong!!");
+  memset(tempFwdLUT, 0, (m_reshapeLUTSize + 1) * sizeof(int16_t));
+  tempFwdLUT[0] = 0;
+
+  for (i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    tempFwdLUT[(i + 1)*histLenth] = tempFwdLUT[i*histLenth] + m_binCW[i];
+    int16_t Y1 = tempFwdLUT[i*histLenth];
+    int16_t Y2 = tempFwdLUT[(i + 1)*histLenth];
+    m_reshapePivot[i + 1] = Y2;
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2HistLenth - 1))) >> (log2HistLenth);
+    m_fwdLUT[i*histLenth] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
+    for (j = 1; j < histLenth; j++)
+    {
+      tempFwdLUT[i*histLenth + j] = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      m_fwdLUT[i*histLenth + j] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)tempFwdLUT[i*histLenth + j]);
+    }
+  }
+
+  for (i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    int start = i*histLenth;
+    int end = (i + 1)*histLenth - 1;
+    m_cwLumaWeight[i] = m_fwdLUT[end] - m_fwdLUT[start];
+  }
+
+  if (tempFwdLUT != nullptr)   {     delete[] tempFwdLUT;    tempFwdLUT = nullptr;  }
+
+  reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
+  updateChromaScaleLUT();
+}
+
+#endif
+//
+//! \}
diff --git a/source/Lib/EncoderLib/EncReshape.h b/source/Lib/EncoderLib/EncReshape.h
new file mode 100644
index 0000000000000000000000000000000000000000..81fc6a0b912f85858bfa820b503694e9f85f0b81
--- /dev/null
+++ b/source/Lib/EncoderLib/EncReshape.h
@@ -0,0 +1,153 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2019, 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.
+ */
+
+ /** \file     EncReshape.h
+     \brief    encoder reshaping header and class (header)
+ */
+
+#ifndef __ENCRESHAPE__
+#define __ENCRESHAPE__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#include "CommonLib/Reshape.h"
+#if JVET_M0427_INLOOP_RESHAPER
+
+//! \ingroup EncoderLib
+//! \{
+
+// ====================================================================================================================
+// Class definition
+// ====================================================================================================================
+
+struct ModelInfo
+{
+  unsigned fullRangeInputFlag;
+  unsigned scaleIntPrec;
+  unsigned scaleInt;
+  unsigned scaleFracPrec;
+  unsigned scaleFrac;
+  unsigned scaleSign;
+  unsigned offsetIntPrec;
+  unsigned offsetInt;
+  unsigned offsetFracPrec;
+  unsigned offsetFrac;
+  unsigned offsetSign;
+  unsigned minMaxQPAbsPrec;
+  unsigned maxQPAbs;
+  unsigned maxQPSign;
+  unsigned minQPAbs;
+  unsigned minQPSign;
+  unsigned scaleAbs;
+  unsigned offsetAbs;
+};
+
+class EncReshape : public Reshape
+{
+private:
+  bool                    m_srcReshaped;
+  int                     m_picWidth;
+  int                     m_picHeight;
+  uint32_t                m_maxCUWidth;
+  uint32_t                m_maxCUHeight;
+  uint32_t                m_widthInCtus;
+  uint32_t                m_heightInCtus;
+  uint32_t                m_numCtuInFrame;
+  bool                    m_exceedSTD;
+  std::vector<uint32_t>   m_binImportance;
+  int                     m_tcase;
+  int                     m_rateAdpMode;
+  bool                    m_useAdpCW;
+  uint16_t                m_initCWAnalyze;
+  ModelInfo               m_dQPModel;
+  ReshapeCW               m_reshapeCW;
+  Pel                     m_cwLumaWeight[PIC_CODE_CW_BINS];
+  double                  m_chromaWeight;
+  int                     m_chromaAdj;
+public:
+
+  EncReshape();
+  ~EncReshape();
+
+  void createEnc( int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight, int bitDepth);
+  void destroy();
+
+  bool getSrcReshaped() { return m_srcReshaped; }
+  void setSrcReshaped(bool b) { m_srcReshaped = b; }
+#if JVET_M0483_IBC
+  void preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT);
+  void preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT);
+#else
+  void preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isIBC);
+  void preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isIBC);
+#endif
+  void bubbleSortDsd(double *array, int * idx, int n);
+  void swap(int *xp, int *yp) { int temp = *xp;  *xp = *yp;  *yp = temp; }
+  void swap(double *xp, double *yp) { double temp = *xp;  *xp = *yp;  *yp = temp; }
+  void deriveReshapeParametersSDRfromStats(uint32_t *, double*, double* reshapeTH1, double* reshapeTH2, bool *intraAdp, bool *interAdp);
+  void deriveReshapeParameters(double *array, int start, int end, ReshapeCW respCW, double &alpha, double &beta);
+  void initLUTfromdQPModel();
+  int  calcEXP2(int val);
+  void constructReshaperSDR();
+  ReshapeCW * getReshapeCW() { return &m_reshapeCW; }
+  Pel * getWeightTable() { return m_cwLumaWeight; }
+  double getCWeight() { return m_chromaWeight; }
+
+  void initModelParam(double scale = 0.015, double offset = -7.5, int QPMax = 6, int QPMin = -3)
+  {
+    /// dQP model:  dQP = clip3(QPMin, QPMax, dScale*Y+dOffset);
+    m_dQPModel.fullRangeInputFlag = 0;
+    m_dQPModel.scaleIntPrec = 0;
+    m_dQPModel.scaleFracPrec = 16;
+    m_dQPModel.offsetIntPrec = 3;
+    m_dQPModel.offsetFracPrec = 1;
+    m_dQPModel.minMaxQPAbsPrec = 3;
+    m_dQPModel.scaleSign = scale < 0 ? 1 : 0;
+    m_dQPModel.scaleAbs = unsigned((scale < 0 ? -scale : scale) * (1 << m_dQPModel.scaleFracPrec));
+    m_dQPModel.scaleInt = m_dQPModel.scaleAbs >> m_dQPModel.scaleFracPrec;
+    m_dQPModel.scaleFrac = m_dQPModel.scaleAbs - (m_dQPModel.scaleInt << m_dQPModel.scaleFracPrec);
+    m_dQPModel.offsetSign = offset < 0 ? 1 : 0;
+    m_dQPModel.offsetAbs = unsigned((offset < 0 ? -offset : offset) * (1 << m_dQPModel.offsetFracPrec));
+    m_dQPModel.offsetInt = m_dQPModel.offsetAbs >> m_dQPModel.offsetFracPrec;
+    m_dQPModel.offsetFrac = m_dQPModel.offsetAbs - (m_dQPModel.offsetInt << m_dQPModel.offsetFracPrec);
+    m_dQPModel.maxQPSign = QPMax < 0 ? 1 : 0;
+    m_dQPModel.maxQPAbs = m_dQPModel.maxQPSign ? -QPMax : QPMax;
+    m_dQPModel.minQPSign = QPMin < 0 ? 1 : 0;
+    m_dQPModel.minQPAbs = m_dQPModel.minQPSign ? -QPMin : QPMin;
+  }
+};// END CLASS DEFINITION EncReshape
+
+//! \}
+#endif
+#endif
diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
index a3bfa14a62b059b379adf1a8bd09d1ebf5334428..8e467b2eec9fe3c335f9602e6efbe696cce1ab3a 100644
--- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
+++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
@@ -799,7 +799,7 @@ void EncSampleAdaptiveOffset::decideBlkParams(CodingStructure& cs, bool* sliceEn
   SAOBlkParam modeParam;
   double minCost, modeCost;
 
-#if K0238_SAO_GREEDY_MERGE_ENCODING 
+#if K0238_SAO_GREEDY_MERGE_ENCODING
   double minCost2 = 0;
   std::vector<SAOStatData**> groupBlkStat;
   if (isGreedymergeEncoding)
@@ -919,7 +919,7 @@ void EncSampleAdaptiveOffset::decideBlkParams(CodingStructure& cs, bool* sliceEn
       reconParams[ctuRsAddr] = codedParams[ctuRsAddr];
       reconstructBlkSAOParam(reconParams[ctuRsAddr], mergeList);
 
-#if K0238_SAO_GREEDY_MERGE_ENCODING  
+#if K0238_SAO_GREEDY_MERGE_ENCODING
       if (isGreedymergeEncoding)
       {
         if (ctuRsAddr == (mergeCtuAddr - 1))
@@ -1037,7 +1037,7 @@ void EncSampleAdaptiveOffset::decideBlkParams(CodingStructure& cs, bool* sliceEn
       {
 #endif
       offsetCTU(area, srcYuv, resYuv, reconParams[ctuRsAddr], cs);
-#if K0238_SAO_GREEDY_MERGE_ENCODING 
+#if K0238_SAO_GREEDY_MERGE_ENCODING
       }
 #endif
 
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 2843c2696bea129ad063b6216fcce17a90eed295..cf4585baee89c463ab3ff11b450158d6c80cf742 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -208,7 +208,7 @@ static int getGlaringColorQPOffset (Picture* const pcPic, const int ctuAddr, con
   const uint32_t chrHeight  = pcv.maxCUHeight >> getChannelTypeScaleY (CH_C, chrFmt);
   const int      midLevel   = 1 << (bitDepth - 1);
   int chrValue = MAX_INT;
-  avgLumaValue = (startAddr < boundingAddr) ? 0 : (uint32_t)pcPic->getOrigBuf().Y().mean();
+  avgLumaValue = (startAddr < boundingAddr) ? 0 : (uint32_t)pcPic->getOrigBuf().Y().computeAvg();
 
   if (ctuAddr >= 0) // luma
   {
@@ -238,9 +238,9 @@ static int getGlaringColorQPOffset (Picture* const pcPic, const int ctuAddr, con
     {
       const CompArea chrArea = clipArea (CompArea (compID, chrFmt, Area ((ctuAddr % pcv.widthInCtus) * chrWidth, (ctuAddr / pcv.widthInCtus) * chrHeight, chrWidth, chrHeight)), pcPic->block (compID));
 
-      avgCompValue = pcPic->getOrigBuf (chrArea).mean();
+      avgCompValue = pcPic->getOrigBuf (chrArea).computeAvg();
     }
-    else avgCompValue = pcPic->getOrigBuf (pcPic->block (compID)).mean();
+    else avgCompValue = pcPic->getOrigBuf (pcPic->block (compID)).computeAvg();
 
     if (chrValue > avgCompValue) chrValue = avgCompValue; // minimum of the DC offsets
   }
@@ -292,7 +292,7 @@ static int applyQPAdaptationChroma (Picture* const pcPic, Slice* const pcSlice,
         // change mean picture QP index based on picture's average luma value (Sharp)
         if (pcEncCfg->getLumaLevelToDeltaQPMapping().mode == LUMALVL_TO_DQP_NUM_MODES)
         {
-          if (meanLuma == MAX_UINT) meanLuma = pcPic->getOrigBuf().Y().mean();
+          if (meanLuma == MAX_UINT) meanLuma = pcPic->getOrigBuf().Y().computeAvg();
 
           averageAdaptedLumaQP = Clip3 (0, MAX_QP, averageAdaptedLumaQP + lumaDQPOffset (meanLuma, iBitDepth));
         }
@@ -339,8 +339,8 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
   rpcSlice->setSliceBits(0);
   rpcSlice->setPic( pcPic );
   rpcSlice->initSlice();
-  int multipleFactor = pcPic->cs->sps->getSpsNext().getUseCompositeRef() ? 2 : 1;
-  if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && isEncodeLtRef)
+  int multipleFactor = pcPic->cs->sps->getUseCompositeRef() ? 2 : 1;
+  if (pcPic->cs->sps->getUseCompositeRef() && isEncodeLtRef)
   {
     rpcSlice->setPicOutputFlag(false);
   }
@@ -600,7 +600,11 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
  #endif
   if(rpcSlice->getPPS()->getSliceChromaQpFlag())
   {
+#if JVET_M0483_IBC
+    const bool bUseIntraOrPeriodicOffset = (rpcSlice->isIntra() && !rpcSlice->getSPS()->getIBCFlag()) || (m_pcCfg->getSliceChromaOffsetQpPeriodicity() > 0 && (rpcSlice->getPOC() % m_pcCfg->getSliceChromaOffsetQpPeriodicity()) == 0);
+#else
     const bool bUseIntraOrPeriodicOffset = rpcSlice->isIntra() || (m_pcCfg->getSliceChromaOffsetQpPeriodicity() > 0 && (rpcSlice->getPOC() % m_pcCfg->getSliceChromaOffsetQpPeriodicity()) == 0);
+#endif
     int cbQP = bUseIntraOrPeriodicOffset ? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(false) : m_pcCfg->getGOPEntry(iGOPid).m_CbQPoffset;
     int crQP = bUseIntraOrPeriodicOffset ? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(true)  : m_pcCfg->getGOPEntry(iGOPid).m_CrQPoffset;
 
@@ -883,7 +887,7 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
                                          picOrig.height, picOrig.width,  iBitDepth);
       hpEnerAvg += hpEner;
       pcPic->m_uEnerHpCtu[ctuRsAddr] = hpEner;
-      pcPic->m_iOffsetCtu[ctuRsAddr] = pcPic->getOrigBuf (ctuArea).mean();
+      pcPic->m_iOffsetCtu[ctuRsAddr] = pcPic->getOrigBuf (ctuArea).computeAvg();
     }
 
     hpEnerAvg /= double (boundingAddr - startAddr);
@@ -1131,7 +1135,7 @@ static int applyQPAdaptationSubCtu (CodingStructure &cs, const UnitArea ctuArea,
         {
           const CompArea subArea = clipArea (CompArea (COMPONENT_Y, pcPic->chromaFormat, Area (x, y, mts, mts)), pcPic->Y());
 
-          subMLV[addr] = pcPic->getOrigBuf (subArea).mean();
+          subMLV[addr] = pcPic->getOrigBuf (subArea).computeAvg();
         }
 #endif
       }
@@ -1337,9 +1341,6 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   //   effectively disabling the slice-segment-mode.
 
   Slice* const pcSlice    = pcPic->slices[getSliceSegmentIdx()];
-#if HEVC_TILES_WPP
-  const TileMap&  tileMap = *pcPic->tileMap;
-#endif
   uint32_t  startCtuTsAddr;
   uint32_t  boundingCtuTsAddr;
 
@@ -1411,6 +1412,7 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
 #if HEVC_TILES_WPP
   // Adjust initial state if this is the start of a dependent slice.
   {
+    const TileMap&  tileMap                 = *pcPic->tileMap;
     const uint32_t      ctuRsAddr               = tileMap.getCtuTsToRsAddrMap( startCtuTsAddr);
     const uint32_t      currentTileIdx          = tileMap.getTileIdxMap(ctuRsAddr);
     const Tile&     currentTile             = tileMap.tiles[currentTileIdx];
@@ -1453,7 +1455,11 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   cs.pcv      = pcSlice->getPPS()->pcv;
   cs.fracBits = 0;
 
-  if (startCtuTsAddr == 0)
+#if JVET_M0055_DEBUG_CTU
+  if( startCtuTsAddr == 0 && ( pcSlice->getPOC() != m_pcCfg->getSwitchPOC() || -1 == m_pcCfg->getDebugCTU() ) )
+#else
+  if( startCtuTsAddr == 0 )
+#endif
   {
     cs.initStructData (pcSlice->getSliceQp(), pcSlice->getPPS()->getTransquantBypassEnabledFlag());
   }
@@ -1530,8 +1536,54 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
 
 }
 
+#if JVET_M0255_FRACMMVD_SWITCH
+void EncSlice::checkDisFracMmvd( Picture* pcPic, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr )
+{
+  CodingStructure&  cs            = *pcPic->cs;
+  Slice* pcSlice                  = cs.slice;
+  const PreCalcValues& pcv        = *cs.pcv;
+  const uint32_t    widthInCtus   = pcv.widthInCtus;
+#if HEVC_TILES_WPP
+  const TileMap&  tileMap         = *pcPic->tileMap;
+#endif
+  const uint32_t hashThreshold    = 20;
+  uint32_t totalCtu               = 0;
+  uint32_t hashRatio              = 0;
+
+  if ( !pcSlice->getSPS()->getDisFracMmvdEnabledFlag() )
+  {
+    return;
+  }
+
+  for ( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
+  {
+#if HEVC_TILES_WPP
+    const uint32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap( ctuTsAddr );
+#else
+    const uint32_t ctuRsAddr = ctuTsAddr;
+#endif
+    const uint32_t ctuXPosInCtus        = ctuRsAddr % widthInCtus;
+    const uint32_t ctuYPosInCtus        = ctuRsAddr / widthInCtus;
 
+    const Position pos ( ctuXPosInCtus * pcv.maxCUWidth, ctuYPosInCtus * pcv.maxCUHeight );
+    const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUWidth, pcv.maxCUHeight ) );
+
+    hashRatio += m_pcCuEncoder->getIbcHashMap().getHashHitRatio( ctuArea.Y() );
+    totalCtu++;
+  }
 
+  if ( hashRatio > totalCtu * hashThreshold )
+  {
+    pcSlice->setDisFracMMVD( true );
+  }
+#if JVET_M0854_FRACMMVD_SWITCH_FOR_UHD
+  if (!pcSlice->getDisFracMMVD()) {
+    bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080);
+    pcSlice->setDisFracMMVD( useIntegerMVD );
+  }
+#endif
+}
+#endif
 
 void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr, EncLib* pEncLib )
 {
@@ -1582,15 +1634,50 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
 #if HEVC_DEPENDENT_SLICES
   }
 #endif
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  if ( pcSlice->getSPS()->getDisFracMmvdEnabledFlag() ||
+#if JVET_M0483_IBC
+      (pcSlice->getSPS()->getIBCFlag() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch()))
+#else
+      ( pcSlice->getSPS()->getIBCMode() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch() ) )
+#endif
+  {
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+    if (pcSlice->getSPS()->getUseReshaper() && m_pcLib->getReshaper()->getCTUFlag() && pcSlice->getSPS()->getIBCFlag())
+#else
+    if (pcSlice->getSPS()->getUseReshaper() && m_pcLib->getReshaper()->getCTUFlag() && pcSlice->getSPS()->getIBCMode())
+#endif
+      cs.picture->getOrigBuf(COMPONENT_Y).rspSignal(m_pcLib->getReshaper()->getFwdLUT());
+#endif
+    m_pcCuEncoder->getIbcHashMap().rebuildPicHashMap( cs.picture->getOrigBuf() );
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+    if (pcSlice->getSPS()->getUseReshaper() && m_pcLib->getReshaper()->getCTUFlag() && pcSlice->getSPS()->getIBCFlag())
+#else
+    if (pcSlice->getSPS()->getUseReshaper() && m_pcLib->getReshaper()->getCTUFlag() && pcSlice->getSPS()->getIBCMode())
+#endif
+      cs.picture->getOrigBuf().copyFrom(cs.picture->getTrueOrigBuf());
+#endif
+  }
+  checkDisFracMmvd( pcPic, startCtuTsAddr, boundingCtuTsAddr );
+#endif
   // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment)
   for( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
   {
+#if JVET_M0055_DEBUG_CTU
+#if HEVC_TILES_WPP
+    const int32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap( ctuTsAddr );
+#else
+    const int32_t ctuRsAddr = ctuTsAddr;
+#endif
+#else
 #if HEVC_TILES_WPP
     const uint32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap(ctuTsAddr);
 #else
     const uint32_t ctuRsAddr = ctuTsAddr;
 #endif
+#endif
 
 #if HEVC_TILES_WPP
     // update CABAC state
@@ -1604,6 +1691,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUWidth, pcv.maxCUHeight ) );
     DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
 
+#if JVET_M0055_DEBUG_CTU
+    if( pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU() )
+#endif
     if ( pcSlice->getSliceType() != I_SLICE && ctuXPosInCtus == 0)
     {
       pcSlice->resetMotionLUTs();
@@ -1714,7 +1804,16 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       resetGbiCodingOrder(false, cs);
       m_pcInterSearch->initWeightIdxBits();
     }
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+    if (pcSlice->getSPS()->getUseReshaper())
+    {
+      m_pcCuEncoder->setDecCuReshaperInEncCU(m_pcLib->getReshaper(), pcSlice->getSPS()->getChromaFormatIdc());
+    }
+#endif
 
+#if JVET_M0055_DEBUG_CTU
+  if (pCfg->getSwitchPOC() != pcPic->poc || ctuRsAddr >= pCfg->getDebugCTU())
+#endif
 #if ENABLE_WPP_PARALLELISM
     pEncLib->getCuEncoder( dataId )->compressCtu( cs, ctuArea, ctuRsAddr, prevQP, currQP );
 #else
diff --git a/source/Lib/EncoderLib/EncSlice.h b/source/Lib/EncoderLib/EncSlice.h
index 39dca4341792cc7f13838691c458417380d64734..7314ca287c92b95f69de9f5cba362641ea72994b 100644
--- a/source/Lib/EncoderLib/EncSlice.h
+++ b/source/Lib/EncoderLib/EncSlice.h
@@ -146,7 +146,9 @@ public:
   static
 #endif
   void    encodeCtus          ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr, EncLib* pcEncLib );
-
+#if JVET_M0255_FRACMMVD_SWITCH
+  void    checkDisFracMmvd    ( Picture* pcPic, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr );
+#endif
 
   // misc. functions
   void    setSearchRange      ( Slice* pcSlice  );                                  ///< set ME range adaptively
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index cad55ecf97b431ed446a4f85cea1a22aa389b9a3..1bcf318383da0753ecf6d41a841649cc469c069f 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -89,6 +89,9 @@ InterSearch::InterSearch()
   , m_pFullCS                     (nullptr)
   , m_pcEncCfg                    (nullptr)
   , m_pcTrQuant                   (nullptr)
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_pcReshape                   (nullptr)
+#endif
   , m_iSearchRange                (0)
   , m_bipredSearchRange           (0)
   , m_motionEstimationSearchMethod(MESEARCH_FULL)
@@ -110,6 +113,10 @@ InterSearch::InterSearch()
   m_affMVList = nullptr;
   m_affMVListSize = 0;
   m_affMVListIdx = 0;
+#if JVET_M0140_SBT
+  m_histBestSbt    = MAX_UCHAR;
+  m_histBestMtsIdx = MAX_UCHAR;
+#endif
 }
 
 
@@ -193,6 +200,9 @@ void InterSearch::init( EncCfg*        pcEncCfg,
                         RdCost*        pcRdCost,
                         CABACWriter*   CABACEstimator,
                         CtxCache*      ctxCache
+#if JVET_M0427_INLOOP_RESHAPER
+                      , EncReshape*    pcReshape
+#endif
 )
 {
   CHECK(m_isInitialized, "Already initialized");
@@ -205,6 +215,9 @@ void InterSearch::init( EncCfg*        pcEncCfg,
   m_motionEstimationSearchMethod = motionEstimationSearchMethod;
   m_CABACEstimator               = CABACEstimator;
   m_CtxCache                     = ctxCache;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshape                    = pcReshape;
+#endif
 
   for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
   {
@@ -251,6 +264,58 @@ void InterSearch::init( EncCfg*        pcEncCfg,
   m_isInitialized = true;
 }
 
+#if JVET_M0246_AFFINE_AMVR
+void InterSearch::resetSavedAffineMotion()
+{
+  for ( int i = 0; i < 2; i++ )
+  {
+    for ( int j = 0; j < 2; j++ )
+    {
+      m_affineMotion.acMvAffine4Para[i][j] = Mv( 0, 0 );
+      m_affineMotion.acMvAffine6Para[i][j] = Mv( 0, 0 );
+    }
+    m_affineMotion.acMvAffine6Para[i][2] = Mv( 0, 0 );
+
+    m_affineMotion.affine4ParaRefIdx[i] = -1;
+    m_affineMotion.affine6ParaRefIdx[i] = -1;
+  }
+  for ( int i = 0; i < 3; i++ )
+  {
+    m_affineMotion.hevcCost[i] = std::numeric_limits<Distortion>::max();
+  }
+  m_affineMotion.affine4ParaAvail = false;
+  m_affineMotion.affine6ParaAvail = false;
+}
+
+void InterSearch::storeAffineMotion( Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int gbiIdx )
+{
+  if ( ( gbiIdx == GBI_DEFAULT || !m_affineMotion.affine6ParaAvail ) && affineType == AFFINEMODEL_6PARAM )
+  {
+    for ( int i = 0; i < 2; i++ )
+    {
+      for ( int j = 0; j < 3; j++ )
+      {
+        m_affineMotion.acMvAffine6Para[i][j] = acAffineMv[i][j];
+      }
+      m_affineMotion.affine6ParaRefIdx[i] = affineRefIdx[i];
+    }
+    m_affineMotion.affine6ParaAvail = true;
+  }
+
+  if ( ( gbiIdx == GBI_DEFAULT || !m_affineMotion.affine4ParaAvail ) && affineType == AFFINEMODEL_4PARAM )
+  {
+    for ( int i = 0; i < 2; i++ )
+    {
+      for ( int j = 0; j < 2; j++ )
+      {
+        m_affineMotion.acMvAffine4Para[i][j] = acAffineMv[i][j];
+      }
+      m_affineMotion.affine4ParaRefIdx[i] = affineRefIdx[i];
+    }
+    m_affineMotion.affine4ParaAvail = true;
+  }
+}
+#endif
 
 inline void InterSearch::xTZSearchHelp( IntTZSearchStruct& rcStruct, const int iSearchX, const int iSearchY, const uint8_t ucPointNr, const uint32_t uiDistance )
 {
@@ -645,6 +710,12 @@ Distortion InterSearch::xPatternRefinement( const CPelBuf* pcPatternKey,
   const Mv* pcMvRefine = (iFrac == 2 ? s_acMvRefineH : s_acMvRefineQ);
   for (uint32_t i = 0; i < 9; i++)
   {
+#if JVET_M0253_HASH_ME
+    if (m_skipFracME && i > 0)
+    {
+      break;
+    }
+#endif
     Mv cMvTest = pcMvRefine[i];
     cMvTest += baseRefMv;
 
@@ -762,7 +833,11 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
     pu.mv[0] = cMVCand[cand];
     pu.mv[0].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
     pu.interDir = 1;
+#if JVET_M0483_IBC
+    pu.refIdx[0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0); // last idx in the list
+#else
     pu.refIdx[0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list
+#endif
 
     PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_0].getBuf(UnitAreaRelative(*pu.cu, pu));
     motionCompensation(pu, predBufTmp, REF_PIC_LIST_0);
@@ -913,7 +988,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
         if (validCand)
         {
-          sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+          sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag());
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * yPred + xPred;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -935,7 +1010,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
         continue;
       }
 
-      sad = m_pcRdCost->getBvCostMultiplePreds(0, y, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+      sad = m_pcRdCost->getBvCostMultiplePreds(0, y, pu.cs->sps->getAMVREnabledFlag());
       m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y;
       sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -960,7 +1035,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
         continue;
       }
 
-      sad = m_pcRdCost->getBvCostMultiplePreds(x, 0, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+      sad = m_pcRdCost->getBvCostMultiplePreds(x, 0, pu.cs->sps->getAMVREnabledFlag());
       m_cDistParam.cur.buf = piRefSrch + x;
       sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -981,7 +1056,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
     bestX = cMVCand[0].getHor();
     bestY = cMVCand[0].getVer();
     sadBest = sadBestCand[0];
-    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL) <= 32))
+    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag()) <= 32))
     {
       //chroma refine
       bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
@@ -1011,7 +1086,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
-          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1022,7 +1097,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
       bestX = cMVCand[0].getHor();
       bestY = cMVCand[0].getVer();
       sadBest = sadBestCand[0];
-      if (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL) <= 16)
+      if (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag()) <= 16)
       {
         //chroma refine
         bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
@@ -1051,7 +1126,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
-          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1075,7 +1150,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
       bestY = cMVCand[0].getVer();
       sadBest = sadBestCand[0];
 
-      if ((sadBest >= tempSadBest) || ((sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL)) <= 32))
+      if ((sadBest >= tempSadBest) || ((sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag())) <= 32))
       {
         //chroma refine
         bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
@@ -1108,7 +1183,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
-          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL);
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1216,6 +1291,18 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
     CPelBuf  tmpPattern = pBuf->Y();
     CPelBuf* pcPatternKey = &tmpPattern;
 
+#if JVET_M0427_INLOOP_RESHAPER
+    if ((pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()))
+    {
+      const CompArea &area = pu.blocks[COMPONENT_Y];
+      CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+      PelBuf tmpOrgLuma = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpOrgLuma.copyFrom(tmpPattern);
+      tmpOrgLuma.rspSignal(m_pcReshape->getFwdLUT());
+      pcPatternKey = (CPelBuf*)&tmpOrgLuma;
+    }
+#endif
+
     m_lumaClpRng = pu.cs->slice->clpRng(COMPONENT_Y);
     Picture* refPic = pu.cu->slice->getPic();
 
@@ -1270,10 +1357,10 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR
 
   rcMvSrchRngLT <<= 2;
   rcMvSrchRngRB <<= 2;
-  clipMv(rcMvSrchRngLT, pu.cu->lumaPos(),
+  xClipMv(rcMvSrchRngLT, pu.cu->lumaPos(),
          pu.cu->lumaSize(),
          sps);
-  clipMv(rcMvSrchRngRB, pu.cu->lumaPos(),
+  xClipMv(rcMvSrchRngRB, pu.cu->lumaPos(),
          pu.cu->lumaSize(),
          sps);
   rcMvSrchRngLT >>= 2;
@@ -1282,9 +1369,11 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR
 
 bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap)
 {
+#if JVET_M0483_IBC==0
   // check only no greater than IBC_MAX_CAND_SIZE
   if (cu.Y().width > IBC_MAX_CAND_SIZE || cu.Y().height > IBC_MAX_CAND_SIZE)
     return false;
+#endif
   Mv           cMvSrchRngLT;
   Mv           cMvSrchRngRB;
 
@@ -1300,13 +1389,20 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
     /// ibc search
     pu.cu->imv = 2;
     AMVPInfo amvpInfo4Pel;
+#if JVET_M0483_IBC
+    PU::fillIBCMvpCand(pu, amvpInfo4Pel);
+#else
     PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], amvpInfo4Pel);
+#endif
 
-
-    pu.cu->imv = 0;// (Int)cu.cs->sps->getSpsNext().getUseIMV(); // set as IMV=0 initially
+    pu.cu->imv = 0;// (Int)cu.cs->sps->getUseIMV(); // set as IMV=0 initially
     Mv    cMv, cMvPred[2];
     AMVPInfo amvpInfo;
+#if JVET_M0483_IBC
+    PU::fillIBCMvpCand(pu, amvpInfo);
+#else
     PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], amvpInfo);
+#endif
     cMvPred[0].set(amvpInfo.mvCand[0].getHor() >> (2), amvpInfo.mvCand[0].getVer() >> (2)); // store in full pel accuracy, shift before use in search
     cMvPred[1].set(amvpInfo.mvCand[1].getHor() >> (2), amvpInfo.mvCand[1].getVer() >> (2));
 
@@ -1348,7 +1444,7 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
         bitsBVPBest = bitsBVPTemp;
         bvpIdxBest = bvpIdxTemp;
 
-        if (cu.cs->sps->getSpsNext().getImvMode() && cMv != cMvPred[bvpIdxTemp])
+        if (cu.cs->sps->getAMVREnabledFlag() && cMv != cMvPred[bvpIdxTemp])
           pu.cu->imv = 1; // set as full-pel
         else
           pu.cu->imv = 0; // set as fractional-pel
@@ -1359,7 +1455,7 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
 
 
       Mv mvPredQuadPel;
-      if ((cMv.getHor() % 4 == 0) && (cMv.getVer() % 4 == 0) && (pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL))
+      if ((cMv.getHor() % 4 == 0) && (cMv.getVer() % 4 == 0) && (pu.cs->sps->getAMVREnabledFlag()))
       {
         mvPredQuadPel = amvpInfo4Pel.mvCand[bvpIdxTemp];// cMvPred[bvpIdxTemp];
 
@@ -1376,7 +1472,7 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
         bitsBVPBest = bitsBVPQP;
         bvpIdxBest = bvpIdxTemp;
 
-        if (cu.cs->sps->getSpsNext().getImvMode())
+        if (cu.cs->sps->getAMVREnabledFlag())
           pu.cu->imv = 2; // set as quad-pel
       }
 
@@ -1397,13 +1493,17 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
       pu.cu->imv = 0;
     if (pu.cu->imv == 2)
       assert((cMv.getHor() % 16 == 0) && (cMv.getVer() % 16 == 0));
-    if (cu.cs->sps->getSpsNext().getUseIMV())
+    if (cu.cs->sps->getAMVREnabledFlag())
       assert(pu.cu->imv>0 || pu.mvd[REF_PIC_LIST_0] == Mv());
 
-    if (!cu.cs->sps->getSpsNext().getUseIMV())
+    if (!cu.cs->sps->getAMVREnabledFlag())
       pu.mvd[REF_PIC_LIST_0] >>= (2);
 
+#if JVET_M0483_IBC
+    pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
+#else
     pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1;
+#endif
     pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
 
     m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[pu.bv] = cost;
@@ -1458,7 +1558,7 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
           }
 
           int costQuadPel = MAX_UINT;
-          if ((candMv.getHor() % 4 == 0) && (candMv.getVer() % 4 == 0) && (pu.cs->sps->getSpsNext().getImvMode() == IMV_4PEL))
+          if ((candMv.getHor() % 4 == 0) && (candMv.getVer() % 4 == 0) && (pu.cs->sps->getAMVREnabledFlag()))
           {
             Mv mvPredQuadPel;
             int imvShift = 2;
@@ -1486,6 +1586,316 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
 }
 
 
+#if JVET_M0253_HASH_ME
+void InterSearch::addToSortList(std::list<BlockHash>& listBlockHash, std::list<int>& listCost, int cost, const BlockHash& blockHash)
+{
+  std::list<BlockHash>::iterator itBlockHash = listBlockHash.begin();
+  std::list<int>::iterator itCost = listCost.begin();
+
+  while (itCost != listCost.end())
+  {
+    if (cost < (*itCost))
+    {
+      listCost.insert(itCost, cost);
+      listBlockHash.insert(itBlockHash, blockHash);
+      return;
+    }
+
+    ++itCost;
+    ++itBlockHash;
+  }
+
+  listCost.push_back(cost);
+  listBlockHash.push_back(blockHash);
+}
+
+void InterSearch::selectMatchesInter(const MapIterator& itBegin, int count, std::list<BlockHash>& listBlockHash, const BlockHash& currBlockHash)
+{
+  const int maxReturnNumber = 5;
+
+  listBlockHash.clear();
+  std::list<int> listCost;
+  listCost.clear();
+
+  MapIterator it = itBegin;
+  for (int i = 0; i < count; i++, it++)
+  {
+    if ((*it).hashValue2 != currBlockHash.hashValue2)
+    {
+      continue;
+    }
+
+    int currCost = RdCost::xGetExpGolombNumberOfBits((*it).x - currBlockHash.x) +
+      RdCost::xGetExpGolombNumberOfBits((*it).y - currBlockHash.y);
+
+    if (listBlockHash.size() < maxReturnNumber)
+    {
+      addToSortList(listBlockHash, listCost, currCost, (*it));
+    }
+    else if (!listCost.empty() && currCost < listCost.back())
+    {
+      listCost.pop_back();
+      listBlockHash.pop_back();
+      addToSortList(listBlockHash, listCost, currCost, (*it));
+    }
+  }
+}
+
+int InterSearch::xHashInterPredME(const PredictionUnit& pu, RefPicList currRefPicList, int currRefPicIndex, Mv bestMv[5])
+{
+  int width = pu.cu->lumaSize().width;
+  int height = pu.cu->lumaSize().height;
+  int xPos = pu.cu->lumaPos().x;
+  int yPos = pu.cu->lumaPos().y;
+
+  uint32_t hashValue1;
+  uint32_t hashValue2;
+
+  if (!TComHash::getBlockHashValue((pu.cs->picture->getOrigBuf()), width, height, xPos, yPos, pu.cu->slice->getSPS()->getBitDepths(), hashValue1, hashValue2))
+  {
+    return 0;
+  }
+  BlockHash currBlockHash;
+  currBlockHash.x = xPos;
+  currBlockHash.y = yPos;
+  currBlockHash.hashValue2 = hashValue2;
+
+  int count = static_cast<int>(pu.cu->slice->getRefPic(currRefPicList, currRefPicIndex)->getHashMap()->count(hashValue1));
+  if (count == 0)
+  {
+    return 0;
+  }
+
+  list<BlockHash> listBlockHash;
+  selectMatchesInter(pu.cu->slice->getRefPic(currRefPicList, currRefPicIndex)->getHashMap()->getFirstIterator(hashValue1), count, listBlockHash, currBlockHash);
+
+  if (listBlockHash.empty())
+  {
+    return 0;
+  }
+
+  int totalSize = 0;
+  list<BlockHash>::iterator it = listBlockHash.begin();
+  for (int i = 0; i < 5 && i < listBlockHash.size(); i++, it++)
+  {
+    bestMv[i].set((*it).x - currBlockHash.x, (*it).y - currBlockHash.y);
+    totalSize++;
+  }
+
+  return totalSize;
+}
+
+bool InterSearch::xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPicList, int& bestRefIndex, Mv& bestMv, Mv& bestMvd, int& bestMVPIndex, bool& isPerfectMatch)
+{
+  int width = pu.cu->lumaSize().width;
+  int height = pu.cu->lumaSize().height;
+  int xPos = pu.cu->lumaPos().x;
+  int yPos = pu.cu->lumaPos().y;
+
+  uint32_t hashValue1;
+  uint32_t hashValue2;
+  Distortion bestCost = UINT64_MAX;
+
+  if (!TComHash::getBlockHashValue((pu.cs->picture->getOrigBuf()), width, height, xPos, yPos, pu.cu->slice->getSPS()->getBitDepths(), hashValue1, hashValue2))
+  {
+    return false;
+  }
+
+  BlockHash currBlockHash;
+  currBlockHash.x = xPos;
+  currBlockHash.y = yPos;
+  currBlockHash.hashValue2 = hashValue2;
+
+  m_pcRdCost->setDistParam(m_cDistParam, pu.cs->getOrgBuf(pu).Y(), 0, 0, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, false);
+
+  int imvBest = 0;
+
+  int numPredDir = pu.cu->slice->isInterP() ? 1 : 2;
+  for (int refList = 0; refList < numPredDir; refList++)
+  {
+    RefPicList eRefPicList = (refList == 0) ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
+    int refPicNumber = pu.cu->slice->getNumRefIdx(eRefPicList);
+
+#if JVET_M0483_IBC
+    if (pu.cs->slice->getSPS()->getIBCFlag() && eRefPicList == REF_PIC_LIST_0)
+#else
+    if (pu.cs->slice->getSPS()->getIBCMode() && eRefPicList == REF_PIC_LIST_0)
+#endif
+    {
+      refPicNumber--;
+    }
+
+    for (int refIdx = 0; refIdx < refPicNumber; refIdx++)
+    {
+      int bitsOnRefIdx = refIdx + 1;
+      if (refIdx + 1 == refPicNumber)
+      {
+        bitsOnRefIdx--;
+      }
+
+      if (refList == 0 || pu.cu->slice->getList1IdxToList0Idx(refIdx) < 0)
+      {
+        int count = static_cast<int>(pu.cu->slice->getRefPic(eRefPicList, refIdx)->getHashMap()->count(hashValue1));
+        if (count == 0)
+        {
+          continue;
+        }
+
+        list<BlockHash> listBlockHash;
+        selectMatchesInter(pu.cu->slice->getRefPic(eRefPicList, refIdx)->getHashMap()->getFirstIterator(hashValue1), count, listBlockHash, currBlockHash);
+
+        if (listBlockHash.empty())
+        {
+          continue;
+        }
+        AMVPInfo currAMVPInfoPel;
+        AMVPInfo currAMVPInfo4Pel;
+        pu.cu->imv = 2;
+        PU::fillMvpCand(pu, eRefPicList, refIdx, currAMVPInfo4Pel);
+        pu.cu->imv = 1;
+        PU::fillMvpCand(pu, eRefPicList, refIdx, currAMVPInfoPel);
+        CHECK(currAMVPInfoPel.numCand <= 1, "Wrong")
+
+        const Pel* refBufStart = pu.cu->slice->getRefPic(eRefPicList, refIdx)->getRecoBuf().get(COMPONENT_Y).buf;
+        const int refStride = pu.cu->slice->getRefPic(eRefPicList, refIdx)->getRecoBuf().get(COMPONENT_Y).stride;
+
+        m_cDistParam.cur.stride = refStride;
+
+        m_pcRdCost->selectMotionLambda(pu.cu->transQuantBypass);
+        m_pcRdCost->setCostScale(0);
+
+        list<BlockHash>::iterator it;
+        for (it = listBlockHash.begin(); it != listBlockHash.end(); ++it)
+        {
+          int curMVPIdx = 0;
+          unsigned int curMVPbits = MAX_UINT;
+          Mv cMv((*it).x - currBlockHash.x, (*it).y - currBlockHash.y);
+
+          for (int mvpIdxTemp = 0; mvpIdxTemp < 2; mvpIdxTemp++)
+          {
+            Mv cMvPredPel = currAMVPInfoPel.mvCand[mvpIdxTemp];
+            cMvPredPel >>= 2;
+            m_pcRdCost->setPredictor(cMvPredPel);
+
+            unsigned int tempMVPbits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 0);
+
+            if (tempMVPbits < curMVPbits)
+            {
+              curMVPbits = tempMVPbits;
+              curMVPIdx = mvpIdxTemp;
+              pu.cu->imv = 1;
+            }
+
+            if ((cMv.getHor() % 4 == 0) && (cMv.getVer() % 4 == 0))
+            {
+              unsigned int bitsMVP4Pel = MAX_UINT;
+              Mv mvPredQuadPel = currAMVPInfo4Pel.mvCand[mvpIdxTemp];
+              mvPredQuadPel >>= 4;
+              m_pcRdCost->setPredictor(mvPredQuadPel);
+              bitsMVP4Pel = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor() >> 2, cMv.getVer() >> 2, 0);
+
+              if (bitsMVP4Pel < curMVPbits)
+              {
+                curMVPbits = bitsMVP4Pel;
+                curMVPIdx = mvpIdxTemp;
+                pu.cu->imv = 2;
+              }
+            }
+          }
+
+          curMVPbits += bitsOnRefIdx;
+
+          m_cDistParam.cur.buf = refBufStart + (*it).y*refStride + (*it).x;
+          Distortion currSad = m_cDistParam.distFunc(m_cDistParam);
+          Distortion currCost = currSad + m_pcRdCost->getCost(curMVPbits);
+
+          if (!isPerfectMatch)
+          {
+            if (pu.cu->slice->getRefPic(eRefPicList, refIdx)->slices[0]->getSliceQp() <= pu.cu->slice->getSliceQp())
+            {
+              isPerfectMatch = true;
+            }
+          }
+
+          if (currCost < bestCost)
+          {
+            cMv <<= 2;
+            bestCost = currCost;
+            bestRefPicList = eRefPicList;
+            bestRefIndex = refIdx;
+            bestMv = cMv;
+            bestMVPIndex = curMVPIdx;
+            imvBest = pu.cu->imv;
+            if (pu.cu->imv == 2)
+            {
+              bestMvd = cMv - currAMVPInfo4Pel.mvCand[curMVPIdx];
+            }
+            else if (pu.cu->imv == 1)
+            {
+              bestMvd = cMv - currAMVPInfoPel.mvCand[curMVPIdx];
+            }
+          }
+        }
+      }
+    }
+  }
+  pu.cu->imv = imvBest;
+  if (bestMvd == Mv(0, 0))
+  {
+    pu.cu->imv = 0;
+    return false;
+  }
+  return (bestCost < MAX_INT);
+}
+
+bool InterSearch::predInterHashSearch(CodingUnit& cu, Partitioner& partitioner, bool& isPerfectMatch)
+{
+  Mv       bestMv, bestMvd;
+  RefPicList   bestRefPicList;
+  int          bestRefIndex;
+  int          bestMVPIndex;
+
+  auto &pu = *cu.firstPU;
+
+  Mv cMvZero;
+  pu.mv[REF_PIC_LIST_0] = Mv();
+  pu.mv[REF_PIC_LIST_1] = Mv();
+  pu.mvd[REF_PIC_LIST_0] = cMvZero;
+  pu.mvd[REF_PIC_LIST_1] = cMvZero;
+  pu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
+  pu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
+  pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
+  pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
+  pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
+  pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
+
+  if (xHashInterEstimation(pu, bestRefPicList, bestRefIndex, bestMv, bestMvd, bestMVPIndex, isPerfectMatch))
+  {
+    pu.interDir = static_cast<int>(bestRefPicList) + 1;
+    pu.mv[bestRefPicList] = bestMv;
+    pu.mv[bestRefPicList].hor <<= MV_FRACTIONAL_BITS_DIFF;
+    pu.mv[bestRefPicList].ver <<= MV_FRACTIONAL_BITS_DIFF;
+
+    pu.mvd[bestRefPicList] = bestMvd;
+    pu.refIdx[bestRefPicList] = bestRefIndex;
+    pu.mvpIdx[bestRefPicList] = bestMVPIndex;
+
+    pu.mvpNum[bestRefPicList] = 2;
+
+    PU::spanMotionInfo(pu);
+    PelUnitBuf predBuf = pu.cs->getPredBuf(pu);
+    motionCompensation(pu, predBuf, REF_PIC_LIST_X);
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+
+  return true;
+}
+#endif
+
 
 //! search of the best candidate for inter prediction
 void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
@@ -1540,6 +1950,25 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
   uint32_t         puIdx = 0;
   auto &pu = *cu.firstPU;
 
+#if JVET_M0246_AFFINE_AMVR
+  bool checkAffine    = pu.cu->imv == 0 || pu.cu->slice->getSPS()->getAffineAmvrEnabledFlag();
+  bool checkNonAffine = pu.cu->imv == 0 || ( pu.cu->slice->getSPS()->getAMVREnabledFlag() &&
+                                             pu.cu->imv <= (pu.cu->slice->getSPS()->getAMVREnabledFlag() ? IMV_4PEL : 0));
+  CodingUnit *bestCU  = pu.cu->cs->bestCS != nullptr ? pu.cu->cs->bestCS->getCU( CHANNEL_TYPE_LUMA ) : nullptr;
+#if JVET_M0444_SMVD
+  bool trySmvd        = ( bestCU != nullptr && pu.cu->imv == 2 && checkAffine ) ? ( !bestCU->firstPU->mergeFlag && !bestCU->affine ) : true;
+#endif
+  if ( pu.cu->imv && bestCU != nullptr && checkAffine )
+  {
+    checkAffine = !( bestCU->firstPU->mergeFlag || !bestCU->affine );
+  }
+
+  if ( pu.cu->imv == 2 && checkNonAffine && pu.cu->slice->getSPS()->getAffineAmvrEnabledFlag() )
+  {
+    checkNonAffine = m_affineMotion.hevcCost[1] < m_affineMotion.hevcCost[0] * 1.06f;
+  }
+#endif
+
   {
     // motion estimation only evaluates luma component
     m_maxCompIDToPred = MAX_NUM_COMPONENT;
@@ -1583,16 +2012,24 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
     m_pcRdCost->selectMotionLambda( cu.transQuantBypass );
 
     unsigned imvShift = pu.cu->imv << 1;
+#if JVET_M0246_AFFINE_AMVR
+    if ( checkNonAffine )
+    {
+#endif
       //  Uni-directional prediction
       for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
       {
         RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
-        int refPicNumber = cs.slice->getNumRefIdx(eRefPicList);
-        if (cs.slice->getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0)
+#if JVET_M0483_IBC==0
+        int refPicNumber = cs.sl#ice->getNumRefIdx(eRefPicList);
+        if (cs.slice->getSPS()->getIBCMode() && eRefPicList == REF_PIC_LIST_0)
         {
           refPicNumber--;
         }
         for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++)
+#else
+        for (int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++)
+#endif
         {
           uiBitsTemp = uiMbBits[iRefList];
           if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
@@ -1640,7 +2077,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
           {
             xMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList] );
           }
-          if( cu.cs->sps->getSpsNext().getUseGBi() && cu.GBiIdx == GBI_DEFAULT && cu.cs->slice->isInterB() )
+          if( cu.cs->sps->getUseGBi() && cu.GBiIdx == GBI_DEFAULT && cu.cs->slice->isInterB() )
           {
             const bool checkIdentical = true;
             m_uniMotions.setReadMode(checkIdentical, (uint32_t)iRefList, (uint32_t)iRefIdxTemp);
@@ -1676,15 +2113,19 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
         }
       }
 
-      if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getSpsNext().getUseAffine()
+      if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getUseAffine()
+#if JVET_M0246_AFFINE_AMVR
+        && checkAffine
+#else
         && cu.imv == 0
+#endif
         && (gbiIdx == GBI_DEFAULT || m_affineModeSelected || !m_pcEncCfg->getUseGBiFast())
         )
       {
         ::memcpy( cMvHevcTemp, cMvTemp, sizeof( cMvTemp ) );
       }
       //  Bi-predictive Motion estimation
-      if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false ) 
+      if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false )
         && (cu.slice->getCheckLDC() || gbiIdx == GBI_DEFAULT || !m_affineModeSelected || !m_pcEncCfg->getUseGBiFast())
         )
       {
@@ -1794,10 +2235,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 
           iRefStart = 0;
           iRefEnd   = cs.slice->getNumRefIdx(eRefPicList)-1;
-          if (cs.slice->getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0)
+#if JVET_M0483_IBC==0
+          if (cs.slice->getSPS()->getIBCMode() && eRefPicList == REF_PIC_LIST_0)
           {
             iRefEnd--;
           }
+#endif
           for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++)
           {
             if( m_pcEncCfg->getUseGBiFast() && (gbiIdx != GBI_DEFAULT)
@@ -1807,7 +2250,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
               continue;
             }
             uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
-            uiBitsTemp += ((cs.slice->getSPS()->getSpsNext().getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
+            uiBitsTemp += ((cs.slice->getSPS()->getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
             if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
             {
               uiBitsTemp += iRefIdxTemp+1;
@@ -1836,7 +2279,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 
               uiCostBi            = uiCostTemp;
               uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
-              uiMotBits[iRefList] -= ((cs.slice->getSPS()->getSpsNext().getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
+              uiMotBits[iRefList] -= ((cs.slice->getSPS()->getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
               uiBits[2]           = uiBitsTemp;
 
               if(iNumIter!=1)
@@ -1871,7 +2314,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
         cu.refIdxBi[1] = iRefIdxBi[1];
 
 #if JVET_M0444_SMVD
+#if JVET_M0246_AFFINE_AMVR
+        if ( cs.slice->getBiDirPred() && trySmvd )
+#else
         if ( cs.slice->getBiDirPred() )
+#endif
         {
           Distortion symCost;
           Mv cMvPredSym[2];
@@ -1941,7 +2388,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 
           Distortion mvpCost = m_pcRdCost->getCost(m_auiMVPIdxCost[mvpIdxSym[curRefList]][AMVP_MAX_NUM_CANDS] + m_auiMVPIdxCost[mvpIdxSym[tarRefList]][AMVP_MAX_NUM_CANDS]);
           symCost = costStart - mvpCost;
-          
+
           // ME
           xSymmetricMotionEstimation( pu, origBuf, cMvPredSym[curRefList], cMvPredSym[tarRefList], eCurRefList, cCurMvField, cTarMvField, symCost, gbiIdx );
 
@@ -1953,8 +2400,8 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
           }
 
           bits = uiMbBits[2];
-          bits += 1; // add one bit for symmetrical MVD mode
-          bits += ((cs.slice->getSPS()->getSpsNext().getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
+          bits += 1; // add one bit for #symmetrical MVD mode
+          bits += ((cs.slice->getSPS()->getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0);
           symCost += m_pcRdCost->getCost(bits);
           cTarMvField.setMvField(cCurMvField.mv.getSymmvdMv(cMvPredSym[curRefList], cMvPredSym[tarRefList]), refIdxTar);
 
@@ -2011,8 +2458,8 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
         uiLastMode = 2;
         pu.mv    [REF_PIC_LIST_0] = cMvBi[0];
         pu.mv    [REF_PIC_LIST_1] = cMvBi[1];
-        pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
-        pu.mv[REF_PIC_LIST_1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+        pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+        pu.mv[REF_PIC_LIST_1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
         pu.mvd   [REF_PIC_LIST_0] = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]];
         pu.mvd   [REF_PIC_LIST_1] = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]];
         pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
@@ -2031,7 +2478,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       {
         uiLastMode = 0;
         pu.mv    [REF_PIC_LIST_0] = cMv[0];
-        pu.mv    [REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+        pu.mv    [REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
         pu.mvd   [REF_PIC_LIST_0] = cMv[0] - cMvPred[0][iRefIdx[0]];
         pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
         pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
@@ -2042,7 +2489,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       {
         uiLastMode = 1;
         pu.mv    [REF_PIC_LIST_1] = cMv[1];
-        pu.mv    [REF_PIC_LIST_1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+        pu.mv    [REF_PIC_LIST_1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
         pu.mvd   [REF_PIC_LIST_1] = cMv[1] - cMvPred[1][iRefIdx[1]];
         pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
         pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
@@ -2056,7 +2503,15 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       }
 
     uiHevcCost = ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] ) ? uiCostBi : ( ( uiCost[0] <= uiCost[1] ) ? uiCost[0] : uiCost[1] );
-    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0
+#if JVET_M0246_AFFINE_AMVR
+    }
+#endif
+    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getUseAffine()
+#if JVET_M0246_AFFINE_AMVR
+      && checkAffine
+#else
+      && cu.imv == 0
+#endif
       && (gbiIdx == GBI_DEFAULT || m_affineModeSelected || !m_pcEncCfg->getUseGBiFast())
       )
     {
@@ -2088,8 +2543,16 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       int refIdx4Para[2] = { -1, -1 };
 
       xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, gbiIdx, enforceGBiPred,
-        ((cu.slice->getSPS()->getSpsNext().getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0));
-      if ( cu.slice->getSPS()->getSpsNext().getUseAffineType() )
+        ((cu.slice->getSPS()->getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0));
+
+#if JVET_M0246_AFFINE_AMVR
+      if ( pu.cu->imv == 0 )
+      {
+        storeAffineMotion( pu.mvAffi, pu.refIdx, AFFINEMODEL_4PARAM, gbiIdx );
+      }
+#endif
+
+      if ( cu.slice->getSPS()->getUseAffineType() )
       {
         if ( uiAffineCost < uiHevcCost * 1.05 ) ///< condition for 6 parameter affine ME
         {
@@ -2122,7 +2585,14 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
           Distortion uiAffine6Cost = std::numeric_limits<Distortion>::max();
           cu.affineType = AFFINEMODEL_6PARAM;
           xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, gbiIdx, enforceGBiPred,
-            ((cu.slice->getSPS()->getSpsNext().getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0));
+            ((cu.slice->getSPS()->getUseGBi() == true) ? getWeightIdxBits(gbiIdx) : 0));
+
+#if JVET_M0246_AFFINE_AMVR
+          if ( pu.cu->imv == 0 )
+          {
+            storeAffineMotion( pu.mvAffi, pu.refIdx, AFFINEMODEL_6PARAM, gbiIdx );
+          }
+#endif
 
           // reset to 4 parameter affine inter mode
           if ( uiAffineCost <= uiAffine6Cost )
@@ -2142,10 +2612,10 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
               pu.mvdAffi[REF_PIC_LIST_1][verIdx] = bestMvd[1][verIdx];
             }
 
-            PU::setAllAffineMv( pu, bestMv[0][0], bestMv[0][1], bestMv[0][2], REF_PIC_LIST_0 
+            PU::setAllAffineMv( pu, bestMv[0][0], bestMv[0][1], bestMv[0][2], REF_PIC_LIST_0
               , false
             );
-            PU::setAllAffineMv( pu, bestMv[1][0], bestMv[1][1], bestMv[1][2], REF_PIC_LIST_1 
+            PU::setAllAffineMv( pu, bestMv[1][0], bestMv[1][1], bestMv[1][2], REF_PIC_LIST_1
               , false
             );
           }
@@ -2204,6 +2674,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 
     //  MC
     PelUnitBuf predBuf = pu.cs->getPredBuf(pu);
+#if JVET_M0246_AFFINE_AMVR
+    if ( gbiIdx == GBI_DEFAULT || !m_affineMotion.affine4ParaAvail || !m_affineMotion.affine6ParaAvail )
+    {
+      m_affineMotion.hevcCost[pu.cu->imv] = uiHevcCost;
+    }
+#endif
     motionCompensation( pu, predBuf, REF_PIC_LIST_X );
     puIdx++;
   }
@@ -2213,8 +2689,39 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
   return;
 }
 
+#if JVET_M0246_AFFINE_AMVR
+uint32_t InterSearch::xCalcAffineMVBits( PredictionUnit& pu, Mv acMvTemp[3], Mv acMvPred[3], bool mvHighPrec )
+{
+  int mvNum  = pu.cu->affineType ? 3 : 2;
+  Mv tempMv0 = acMvTemp[0];
+  const int shift = mvHighPrec ? MV_FRACTIONAL_BITS_DIFF : 0;
+  const unsigned int mvdShift = pu.cu->imv == 2 ? MV_FRACTIONAL_BITS_DIFF : 0;
+  Mv secondPred;
+
+  if ( mvHighPrec )
+  {
+    tempMv0.changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER );
+  }
+
+  m_pcRdCost->setCostScale( 0 );
+  uint32_t bitsTemp = 0;
+
+  for ( int verIdx = 0; verIdx < mvNum; verIdx++ )
+  {
+    m_pcRdCost->setPredictor( acMvPred[verIdx] );
+
+    if ( verIdx != 0 )
+    {
+      secondPred = acMvPred[verIdx] + ( tempMv0 - acMvPred[0] );
+      m_pcRdCost->setPredictor( secondPred );
+    }
 
+    bitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[verIdx].getHor() >> shift, acMvTemp[verIdx].getVer() >> shift, mvdShift );
+  }
 
+  return bitsTemp;
+}
+#endif
 
 // AMVP
 void InterSearch::xEstimateMvPredAMVP( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, int iRefIdx, Mv& rcMvPred, AMVPInfo& rAMVPInfo, bool bFilled, Distortion* puiDistBiP )
@@ -2372,7 +2879,7 @@ Distortion InterSearch::xGetTemplateCost( const PredictionUnit& pu,
   Distortion uiCost = std::numeric_limits<Distortion>::max();
 
   const Picture* picRef = pu.cu->slice->getRefPic( eRefPicList, iRefIdx );
-  cMvCand.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+  cMvCand.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
   clipMv( cMvCand, pu.cu->lumaPos(),
           pu.cu->lumaSize(),
           *pu.cs->sps );
@@ -2410,9 +2917,16 @@ Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf&
   const bool bi = pu.cu->slice->testWeightPred() && pu.cu->slice->getSliceType()==P_SLICE;
   Mv mv[3];
   memcpy(mv, acMvCand, sizeof(mv));
-  mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
-  mv[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
-  mv[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+#if JVET_M0246_AFFINE_AMVR
+  if ( pu.cu->imv != 1 )
+  {
+#endif
+    mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+    mv[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+    mv[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+  }
+#endif
   xPredAffineBlk(COMPONENT_Y, pu, picRef, mv, predBuf, bi, pu.cu->slice->clpRng(COMPONENT_Y));
   if( bi )
   {
@@ -2422,7 +2936,7 @@ Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf&
   // calc distortion
 
   uiCost  = m_pcRdCost->getDistPart( origBuf.Y(), predBuf.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y
-    , DF_HAD 
+    , DF_HAD
   );
   uiCost += m_pcRdCost->getCost( m_auiMVPIdxCost[iMVPIdx][iMVPNum] );
   DTRACE( g_trace_ctx, D_COMMON, " (%d) affineTemplateCost=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCost );
@@ -2431,7 +2945,7 @@ Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf&
 
 void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, Mv& rcMvPred, int iRefIdxPred, Mv& rcMv, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, bool bBi)
 {
-  if( pu.cu->cs->sps->getSpsNext().getUseGBi() && pu.cu->GBiIdx != GBI_DEFAULT && !bBi && xReadBufferedUniMv(pu, eRefPicList, iRefIdxPred, rcMvPred, rcMv, ruiBits, ruiCost) )
+  if( pu.cu->cs->sps->getUseGBi() && pu.cu->GBiIdx != GBI_DEFAULT && !bBi && xReadBufferedUniMv(pu, eRefPicList, iRefIdxPred, rcMvPred, rcMv, ruiBits, ruiCost) )
   {
     return;
   }
@@ -2477,7 +2991,7 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref
   cStruct.inCtuSearch = false;
   cStruct.zeroMV = false;
   {
-    if (pu.cs->sps->getSpsNext().getUseCompositeRef() && pu.cs->slice->getRefPic(eRefPicList, iRefIdxPred)->longTerm)
+    if (pu.cs->sps->getUseCompositeRef() && pu.cs->slice->getRefPic(eRefPicList, iRefIdxPred)->longTerm)
     {
       cStruct.inCtuSearch = true;
     }
@@ -2506,7 +3020,11 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref
   {
     setWpScalingDistParam(iRefIdxPred, eRefPicList, pu.cu->slice);
   }
-
+#if JVET_M0253_HASH_ME
+  m_currRefPicList = eRefPicList;
+  m_currRefPicIndex = iRefIdxPred;
+  m_skipFracME = false;
+#endif
   //  Do integer search
   if( ( m_motionEstimationSearchMethod == MESEARCH_FULL ) || bBi || bQTBTMV )
   {
@@ -2575,7 +3093,7 @@ void InterSearch::xSetSearchRange ( const PredictionUnit& pu,
 {
   const int iMvShift = MV_FRACTIONAL_BITS_INTERNAL;
   Mv cFPMvPred = cMvPred;
-  cFPMvPred.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+  cFPMvPred.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
   clipMv( cFPMvPred, pu.cu->lumaPos(),
           pu.cu->lumaSize(),
           *pu.cs->sps );
@@ -2583,10 +3101,10 @@ void InterSearch::xSetSearchRange ( const PredictionUnit& pu,
   Mv mvTL(cFPMvPred.getHor() - (iSrchRng << iMvShift), cFPMvPred.getVer() - (iSrchRng << iMvShift));
   Mv mvBR(cFPMvPred.getHor() + (iSrchRng << iMvShift), cFPMvPred.getVer() + (iSrchRng << iMvShift));
 
-  clipMv( mvTL, pu.cu->lumaPos(),
+  xClipMv( mvTL, pu.cu->lumaPos(),
           pu.cu->lumaSize(),
           *pu.cs->sps );
-  clipMv( mvBR, pu.cu->lumaPos(),
+  xClipMv( mvBR, pu.cu->lumaPos(),
           pu.cu->lumaSize(),
           *pu.cs->sps );
 
@@ -2598,7 +3116,7 @@ void InterSearch::xSetSearchRange ( const PredictionUnit& pu,
   sr.right  = mvBR.hor;
   sr.bottom = mvBR.ver;
 
-  if (pu.cs->sps->getSpsNext().getUseCompositeRef() && cStruct.inCtuSearch)
+  if (pu.cs->sps->getUseCompositeRef() && cStruct.inCtuSearch)
   {
     Position posRB = pu.Y().bottomRight();
     Position posTL = pu.Y().topLeft();
@@ -2731,11 +3249,11 @@ void InterSearch::xTZSearch( const PredictionUnit& pu,
   const bool bNewZeroNeighbourhoodTest               = bExtendedSettings;
 
   int iSearchRange = m_iSearchRange;
-  rcMv.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); 
+  rcMv.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
   clipMv( rcMv, pu.cu->lumaPos(),
           pu.cu->lumaSize(),
           *pu.cs->sps );
-  rcMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER); 
+  rcMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
   rcMv.divideByPowerOf2(2);
 
   // init TZSearchStruct
@@ -2789,9 +3307,34 @@ void InterSearch::xTZSearch( const PredictionUnit& pu,
       , cStruct
     );
   }
-
-  // start search
-  int  iDist = 0;
+#if JVET_M0253_HASH_ME
+  if (m_pcEncCfg->getUseHashME())
+  {
+    int width = pu.cu->lumaSize().width;
+    int height = pu.cu->lumaSize().height;
+    if ((width == height && width <= 64 && width >= 4) || (width == 8 && height == 4) || (width == 4 && height == 8))
+    {
+      Mv otherMvps[5];
+      int numberOfOtherMvps;
+      numberOfOtherMvps = xHashInterPredME(pu, m_currRefPicList, m_currRefPicIndex, otherMvps);
+      for (int i = 0; i < numberOfOtherMvps; i++)
+      {
+        xTZSearchHelp(cStruct, otherMvps[i].getHor(), otherMvps[i].getVer(), 0, 0);
+      }
+      if (numberOfOtherMvps > 0)
+      {
+        // write out best match
+        rcMv.set(cStruct.iBestX, cStruct.iBestY);
+        ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor(cStruct.iBestX, cStruct.iBestY, cStruct.imvShift);
+        m_skipFracME = true;
+        return;
+      }
+    }
+  }
+#endif
+
+  // start search
+  int  iDist = 0;
   int  iStartX = cStruct.iBestX;
   int  iStartY = cStruct.iBestY;
 
@@ -3046,6 +3589,33 @@ void InterSearch::xTZSearchSelective( const PredictionUnit& pu,
     );
   }
 
+#if JVET_M0253_HASH_ME
+  if (m_pcEncCfg->getUseHashME())
+  {
+    int width = pu.cu->lumaSize().width;
+    int height = pu.cu->lumaSize().height;
+    if ((width == height && width <= 64 && width >= 4) || (width == 8 && height == 4) || (width == 4 && height == 8))
+    {
+      Mv otherMvps[5];
+      int numberOfOtherMvps;
+      numberOfOtherMvps = xHashInterPredME(pu, m_currRefPicList, m_currRefPicIndex, otherMvps);
+      for (int i = 0; i < numberOfOtherMvps; i++)
+      {
+        xTZSearchHelp(cStruct, otherMvps[i].getHor(), otherMvps[i].getVer(), 0, 0);
+      }
+
+      if (numberOfOtherMvps > 0)
+      {
+        // write out best match
+        rcMv.set(cStruct.iBestX, cStruct.iBestY);
+        ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor(cStruct.iBestX, cStruct.iBestY, cStruct.imvShift);
+        m_skipFracME = true;
+        return;
+      }
+    }
+  }
+#endif
+
   // Initial search
   int iBestX = cStruct.iBestX;
   int iBestY = cStruct.iBestY;
@@ -3233,9 +3803,21 @@ void InterSearch::xPatternSearchFracDIF(
   //  Reference pattern initialization (integer scale)
   int         iOffset    = rcMvInt.getHor() + rcMvInt.getVer() * cStruct.iRefStride;
   CPelBuf cPatternRoi(cStruct.piRefY + iOffset, cStruct.iRefStride, *cStruct.pcPatternKey);
+#if JVET_M0253_HASH_ME
+  if (m_skipFracME)
+  {
+    Mv baseRefMv(0, 0);
+    rcMvHalf.setZero();
+    m_pcRdCost->setCostScale(0);
+    xExtDIFUpSamplingH(&cPatternRoi);
+    rcMvQter = rcMvInt;   rcMvQter <<= 2;    // for mv-cost
+    ruiCost = xPatternRefinement(cStruct.pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded);
+    return;
+  }
+#endif
 
 
-  if (cStruct.imvShift || (pu.cs->sps->getSpsNext().getUseCompositeRef() && cStruct.zeroMV))
+  if (cStruct.imvShift || (pu.cs->sps->getUseCompositeRef() && cStruct.zeroMV))
   {
     m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY + iOffset, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, m_pcEncCfg->getUseHADME() && !bIsLosslessCoded );
     ruiCost = m_cDistParam.distFunc( m_cDistParam );
@@ -3478,6 +4060,10 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
   uint32_t          bitsValidList1 = MAX_UINT;
   Distortion costValidList1 = std::numeric_limits<Distortion>::max();
   Mv            mvHevc[3];
+#if JVET_M0246_AFFINE_AMVR
+  const bool changeToHighPrec  = pu.cu->imv != 1;
+  const bool affineAmvrEnabled = pu.cu->slice->getSPS()->getAffineAmvrEnabledFlag();
+#endif
 
   xGetBlkBits( slice.isInterP(), puIdx, lastMode, uiMbBits);
 
@@ -3493,12 +4079,16 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
   for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
   {
     RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
-    int refPicNumber = slice.getNumRefIdx(eRefPicList);
-    if (slice.getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0)
+#if JVET_M0483_IBC==0
+    int refPicNumber = s#lice.getNumRefIdx(eRefPicList);
+    if (slice.getSPS()->getIBCMode() && eRefPicList == REF_PIC_LIST_0)
     {
       refPicNumber--;
     }
     for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++)
+#else
+    for (int iRefIdxTemp = 0; iRefIdxTemp < slice.getNumRefIdx(eRefPicList); iRefIdxTemp++)
+#endif
     {
       // Get RefIdx bits
       uiBitsTemp = uiMbBits[iRefList];
@@ -3513,6 +4103,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
 
       // Do Affine AMVP
       xEstimateAffineAMVP( pu, affiAMVPInfoTemp[eRefPicList], origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], &biPDistTemp );
+#if JVET_M0246_AFFINE_AMVR
+      if ( affineAmvrEnabled )
+      {
+        biPDistTemp += m_pcRdCost->getCost( xCalcAffineMVBits( pu, cMvPred[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp] ) );
+      }
+#endif
       aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList];
       aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];;
       if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp )
@@ -3525,13 +4121,59 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
       for ( int i=0; i<3; i++ )
       {
         mvHevc[i] = hevcMv[iRefList][iRefIdxTemp];
+#if JVET_M0246_AFFINE_AMVR
+        if ( pu.cu->imv == 1 )
+        {
+          mvHevc[i].changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
+        }
+        else if ( pu.cu->imv == 2 )
+        {
+          mvHevc[i].roundToPrecision( MV_PRECISION_QUARTER, MV_PRECISION_INT );
+        }
+#endif
       }
       PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
 
       Distortion uiCandCost = xGetAffineTemplateCost(pu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp],
                                                      AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp);
+
+#if JVET_M0246_AFFINE_AMVR
+      if ( affineAmvrEnabled )
+      {
+        uiCandCost += m_pcRdCost->getCost( xCalcAffineMVBits( pu, mvHevc, cMvPred[iRefList][iRefIdxTemp] ) );
+      }
+
+      //check stored affine motion
+      bool affine4Para    = pu.cu->affineType == AFFINEMODEL_4PARAM;
+      bool savedParaAvail = pu.cu->imv && ( ( m_affineMotion.affine4ParaRefIdx[iRefList] == iRefIdxTemp && affine4Para && m_affineMotion.affine4ParaAvail ) ||
+                                            ( m_affineMotion.affine6ParaRefIdx[iRefList] == iRefIdxTemp && !affine4Para && m_affineMotion.affine6ParaAvail ) );
+
+      if ( savedParaAvail )
+      {
+        Mv mvFour[3];
+        for ( int i = 0; i < mvNum; i++ )
+        {
+          mvFour[i] = affine4Para ? m_affineMotion.acMvAffine4Para[iRefList][i] : m_affineMotion.acMvAffine6Para[iRefList][i];
+          if ( pu.cu->imv != 1 )
+          {
+            mvFour[i].roundToPrecision( MV_PRECISION_INTERNAL, pu.cu->imv == 2 ? MV_PRECISION_INT : MV_PRECISION_QUARTER );
+            mvFour[i].changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER );
+          }
+        }
+
+        Distortion candCostInherit = xGetAffineTemplateCost( pu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp );
+        candCostInherit += m_pcRdCost->getCost( xCalcAffineMVBits( pu, mvFour, cMvPred[iRefList][iRefIdxTemp] ) );
+
+        if ( candCostInherit < uiCandCost )
+        {
+          uiCandCost = candCostInherit;
+          memcpy( mvHevc, mvFour, 3 * sizeof( Mv ) );
+        }
+      }
+#endif
+
       if (pu.cu->affineType == AFFINEMODEL_4PARAM && m_affMVListSize
-        && (!pu.cu->cs->sps->getSpsNext().getUseGBi() || gbiIdx == GBI_DEFAULT)
+        && (!pu.cu->cs->sps->getUseGBi() || gbiIdx == GBI_DEFAULT)
         )
       {
         int shift = MAX_CU_DEPTH;
@@ -3572,21 +4214,49 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
           vy = mvScaleVer + dMvHorY * (pu.Y().x - mvInfo->x) + dMvVerY * (pu.Y().y - mvInfo->y);
           roundAffineMv(vx, vy, shift);
           mvTmp[0] = Mv(vx, vy);
+#if JVET_M0145_AFFINE_MV_CLIP
+          mvTmp[0].clipToStorageBitDepth();
+#endif
           clipMv(mvTmp[0], pu.cu->lumaPos(),
                  pu.cu->lumaSize(),
                  *pu.cs->sps);
+#if JVET_M0246_AFFINE_AMVR
+          if ( pu.cu->imv == 2 )
+          {
+            mvTmp[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+          }
+          else if ( pu.cu->imv == 0 )
+#endif
           mvTmp[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
           vx = mvScaleHor + dMvHorX * (pu.Y().x + pu.Y().width - mvInfo->x) + dMvVerX * (pu.Y().y - mvInfo->y);
           vy = mvScaleVer + dMvHorY * (pu.Y().x + pu.Y().width - mvInfo->x) + dMvVerY * (pu.Y().y - mvInfo->y);
           roundAffineMv(vx, vy, shift);
           mvTmp[1] = Mv(vx, vy);
+#if JVET_M0145_AFFINE_MV_CLIP
+          mvTmp[1].clipToStorageBitDepth();
+#endif
           clipMv(mvTmp[1], pu.cu->lumaPos(),
                  pu.cu->lumaSize(),
                  *pu.cs->sps);
+#if JVET_M0246_AFFINE_AMVR
+          if ( pu.cu->imv != 1 )
+          {
+            mvTmp[1].roundToPrecision( MV_PRECISION_INTERNAL, pu.cu->imv == 2 ? MV_PRECISION_INT : MV_PRECISION_QUARTER );
+            mvTmp[0].changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER );
+            mvTmp[1].changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER );
+          }
+#else
           mvTmp[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
           mvTmp[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
           mvTmp[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#endif
           Distortion tmpCost = xGetAffineTemplateCost(pu, origBuf, predBuf, mvTmp, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp);
+#if JVET_M0246_AFFINE_AMVR
+          if ( affineAmvrEnabled )
+          {
+            tmpCost += m_pcRdCost->getCost( xCalcAffineMVBits( pu, mvTmp, cMvPred[iRefList][iRefIdxTemp] ) );
+          }
+#endif
           if (tmpCost < uiCandCost)
           {
             uiCandCost = tmpCost;
@@ -3597,13 +4267,26 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
       if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
       {
         Mv mvFour[3];
-        mvAffine4Para[iRefList][iRefIdxTemp][0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-        mvAffine4Para[iRefList][iRefIdxTemp][1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+        if ( pu.cu->imv != 1 )
+        {
+#endif
+          mvAffine4Para[iRefList][iRefIdxTemp][0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+          mvAffine4Para[iRefList][iRefIdxTemp][1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+        }
+#endif
         mvFour[0] = mvAffine4Para[iRefList][iRefIdxTemp][0];
         mvFour[1] = mvAffine4Para[iRefList][iRefIdxTemp][1];
-        mvAffine4Para[iRefList][iRefIdxTemp][0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-        mvAffine4Para[iRefList][iRefIdxTemp][1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-
+#if JVET_M0246_AFFINE_AMVR
+        if ( pu.cu->imv != 1 )
+        {
+#endif
+          mvAffine4Para[iRefList][iRefIdxTemp][0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+          mvAffine4Para[iRefList][iRefIdxTemp][1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+        }
+#endif
         int shift = MAX_CU_DEPTH;
         int vx2 = (mvFour[0].getHor() << shift) - ((mvFour[1].getVer() - mvFour[0].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]));
         int vy2 = (mvFour[0].getVer() << shift) + ((mvFour[1].getHor() - mvFour[0].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]));
@@ -3611,12 +4294,37 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
         vy2 >>= shift;
         mvFour[2].hor = vx2;
         mvFour[2].ver = vy2;
+#if JVET_M0145_AFFINE_MV_CLIP
+        mvFour[2].clipToStorageBitDepth();
+#endif
+#if JVET_M0246_AFFINE_AMVR
+        if ( pu.cu->imv != 1 )
+        {
+          mvFour[0].roundToPrecision( MV_PRECISION_INTERNAL, pu.cu->imv == 2 ? MV_PRECISION_INT : MV_PRECISION_QUARTER );
+          mvFour[1].roundToPrecision( MV_PRECISION_INTERNAL, pu.cu->imv == 2 ? MV_PRECISION_INT : MV_PRECISION_QUARTER );
+          mvFour[2].roundToPrecision( MV_PRECISION_INTERNAL, pu.cu->imv == 2 ? MV_PRECISION_INT : MV_PRECISION_QUARTER );
+        }
+#else
         mvFour[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#endif
         for (int i = 0; i < 3; i++)
         {
+#if JVET_M0246_AFFINE_AMVR
+          if ( pu.cu->imv != 1 )
+          {
+            mvFour[i].changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER );
+          }
+#else
           mvFour[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#endif
         }
         Distortion uiCandCostInherit = xGetAffineTemplateCost( pu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp );
+#if JVET_M0246_AFFINE_AMVR
+        if ( affineAmvrEnabled )
+        {
+          uiCandCostInherit += m_pcRdCost->getCost( xCalcAffineMVBits( pu, mvFour, cMvPred[iRefList][iRefIdxTemp] ) );
+        }
+#endif
         if ( uiCandCostInherit < uiCandCost )
         {
           uiCandCost = uiCandCostInherit;
@@ -3656,6 +4364,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
           uiCostTemp = uiCostTempL0[iList1ToList0Idx];
 
           uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[iList1ToList0Idx] );
+#if JVET_M0246_AFFINE_AMVR
+          uiBitsTemp += xCalcAffineMVBits( pu, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp] );
+#else
           for (int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++)
           {
             m_pcRdCost->setPredictor( cMvPred[iRefList][iRefIdxTemp][iVerIdx] );
@@ -3668,26 +4379,42 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
             }
             uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp][iVerIdx].getHor()>>shift, cMvTemp[1][iRefIdxTemp][iVerIdx].getVer()>>shift, 0 );
           }
+#endif
           /*calculate the correct cost*/
           uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
           DTRACE( g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCostTemp );
         }
         else
         {
-          xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
+          xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                   , aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[eRefPicList]
+#endif
+          );
         }
       }
       else
       {
-        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
+        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                 , aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[eRefPicList]
+#endif
+        );
       }
-      if(pu.cu->cs->sps->getSpsNext().getUseGBi() && pu.cu->GBiIdx == GBI_DEFAULT && pu.cu->slice->isInterB())
+      if(pu.cu->cs->sps->getUseGBi() && pu.cu->GBiIdx == GBI_DEFAULT && pu.cu->slice->isInterB())
       {
         m_uniMotions.setReadModeAffine(true, (uint8_t)iRefList, (uint8_t)iRefIdxTemp, pu.cu->affineType);
-        m_uniMotions.copyAffineMvFrom(cMvTemp[iRefList][iRefIdxTemp], uiCostTemp - m_pcRdCost->getCost(uiBitsTemp), (uint8_t)iRefList, (uint8_t)iRefIdxTemp, pu.cu->affineType);
+        m_uniMotions.copyAffineMvFrom(cMvTemp[iRefList][iRefIdxTemp], uiCostTemp - m_pcRdCost->getCost(uiBitsTemp), (uint8_t)iRefList, (uint8_t)iRefIdxTemp, pu.cu->affineType
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                      , aaiMvpIdx[iRefList][iRefIdxTemp]
+#endif
+        );
       }
       // Set best AMVP Index
       xCopyAffineAMVPInfo( affiAMVPInfoTemp[eRefPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp] );
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+      if ( pu.cu->imv != 2 || !m_pcEncCfg->getUseAffineAmvrEncOpt() )
+#endif
       xCheckBestAffineMVP( pu, affiAMVPInfoTemp[eRefPicList], eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
 
       if ( iRefList == 0 )
@@ -3721,7 +4448,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
   if ( pu.cu->affineType == AFFINEMODEL_4PARAM )
   {
     ::memcpy( mvAffine4Para, cMvTemp, sizeof( cMvTemp ) );
-    if (!pu.cu->cs->sps->getSpsNext().getUseGBi() || gbiIdx == GBI_DEFAULT)
+#if JVET_M0246_AFFINE_AMVR
+    if ( pu.cu->imv == 0 && ( !pu.cu->cs->sps->getUseGBi() || gbiIdx == GBI_DEFAULT ) )
+#else
+    if (!pu.cu->cs->sps->getUseGBi() || gbiIdx == GBI_DEFAULT)
+#endif
     {
       AffineMVInfo *affMVInfo = m_affMVList + m_affMVListIdx;
 
@@ -3781,8 +4512,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
       iRefIdxBi[1] = bestBiPRefIdxL1;
 
       // Get list1 prediction block
-      PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 
+      PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1
+#if JVET_M0246_AFFINE_AMVR
+        , changeToHighPrec
+#else
         , true
+#endif
       );
       pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
 
@@ -3846,8 +4581,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
       // First iterate, get prediction block of opposite direction
       if( iIter == 0 && !slice.getMvdL1ZeroFlag() )
       {
-        PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], RefPicList(1-iRefList) 
+        PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], RefPicList(1-iRefList)
+#if JVET_M0246_AFFINE_AMVR
+          , changeToHighPrec
+#else
           , true
+#endif
         );
         pu.refIdx[1-iRefList] = iRefIdx[1-iRefList];
 
@@ -3867,10 +4606,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
 
       iRefStart = 0;
       iRefEnd   = slice.getNumRefIdx(eRefPicList) - 1;
-      if (slice.getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0)
+#if JVET_M0483_IBC==0
+      if (slice.getSPS()->getIBCMode() && eRefPicList == REF_PIC_LIST_0)
       {
         iRefEnd--;
       }
+#endif
       for ( int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ )
       {
         if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp )
@@ -3885,7 +4626,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
         }
         // update bits
         uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
-        uiBitsTemp += ((pu.cu->slice->getSPS()->getSpsNext().getUseGBi() == true) ? gbiIdxBits : 0);
+        uiBitsTemp += ((pu.cu->slice->getSPS()->getUseGBi() == true) ? gbiIdxBits : 0);
         if( slice.getNumRefIdx(eRefPicList) > 1 )
         {
           uiBitsTemp += iRefIdxTemp+1;
@@ -3897,8 +4638,15 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
         uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
 
         // call Affine ME
-        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, true );
+        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp,
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                 aaiMvpIdxBi[iRefList][iRefIdxTemp], aacAffineAMVPInfo[iRefList][iRefIdxTemp],
+#endif
+          true );
         xCopyAffineAMVPInfo( aacAffineAMVPInfo[iRefList][iRefIdxTemp], affiAMVPInfoTemp[eRefPicList] );
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+        if ( pu.cu->imv != 2 || !m_pcEncCfg->getUseAffineAmvrEncOpt() )
+#endif
         xCheckBestAffineMVP( pu, affiAMVPInfoTemp[eRefPicList], eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
 
         if ( uiCostTemp < uiCostBi )
@@ -3909,14 +4657,18 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
 
           uiCostBi            = uiCostTemp;
           uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
-          uiMotBits[iRefList] -= ((pu.cu->slice->getSPS()->getSpsNext().getUseGBi() == true) ? gbiIdxBits : 0);
+          uiMotBits[iRefList] -= ((pu.cu->slice->getSPS()->getUseGBi() == true) ? gbiIdxBits : 0);
           uiBits[2]           = uiBitsTemp;
 
           if ( iNumIter != 1 ) // MC for next iter
           {
             //  Set motion
-            PU::setAllAffineMv( pu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], eRefPicList 
+            PU::setAllAffineMv( pu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], eRefPicList
+#if JVET_M0246_AFFINE_AMVR
+              , changeToHighPrec
+#else
               , true
+#endif
             );
             pu.refIdx[eRefPicList] = iRefIdxBi[eRefPicList];
             PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getBuf( UnitAreaRelative(*pu.cu, pu) );
@@ -3977,11 +4729,19 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
     lastMode = 2;
     affineCost = uiCostBi;
 
-    PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0 
+    PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0
+#if JVET_M0246_AFFINE_AMVR
+      , changeToHighPrec
+#else
       , true
+#endif
     );
-    PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 
+    PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1
+#if JVET_M0246_AFFINE_AMVR
+      , changeToHighPrec
+#else
       , true
+#endif
     );
     pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
     pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
@@ -4009,8 +4769,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
     lastMode = 0;
     affineCost = uiCost[0];
 
-    PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0 
+    PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0
+#if JVET_M0246_AFFINE_AMVR
+      , changeToHighPrec
+#else
       , true
+#endif
     );
     pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
 
@@ -4032,8 +4796,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
     lastMode = 1;
     affineCost = uiCost[1];
 
-    PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1 
+    PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1
+#if JVET_M0246_AFFINE_AMVR
+      , changeToHighPrec
+#else
       , true
+#endif
     );
     pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
 
@@ -4142,6 +4910,10 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin
   int iBestMVPIdx = riMVPIdx;
 
   // Get origin MV bits
+#if JVET_M0246_AFFINE_AMVR
+  Mv tmpPredMv[3];
+  int iOrgMvBits = xCalcAffineMVBits( pu, acMv, acMvPred );
+#else
   int iOrgMvBits = 0;
   for ( int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++ )
   {
@@ -4156,6 +4928,7 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin
     }
     iOrgMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor()>>shift, acMv[iVerIdx].getVer()>>shift, 0 );
   }
+#endif
   iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
 
   int iBestMvBits = iOrgMvBits;
@@ -4165,7 +4938,15 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin
     {
       continue;
     }
-
+#if JVET_M0246_AFFINE_AMVR
+    tmpPredMv[0] = affineAMVPInfo.mvCandLT[iMVPIdx];
+    tmpPredMv[1] = affineAMVPInfo.mvCandRT[iMVPIdx];
+    if ( mvNum == 3 )
+    {
+      tmpPredMv[2] = affineAMVPInfo.mvCandLB[iMVPIdx];
+    }
+    int iMvBits = xCalcAffineMVBits( pu, acMv, tmpPredMv );
+#else
     int iMvBits = 0;
     for ( int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++ )
     {
@@ -4181,6 +4962,7 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin
       }
       iMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor()>>shift, acMv[iVerIdx].getVer()>>shift, 0 );
     }
+#endif
     iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
 
     if (iMvBits < iBestMvBits)
@@ -4210,13 +4992,25 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
                                            Mv              acMv[3],
                                            uint32_t&           ruiBits,
                                            Distortion&     ruiCost,
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                           int&            mvpIdx,
+                                           const AffineAMVPInfo& aamvpi,
+#endif
                                            bool            bBi)
 {
-  if( pu.cu->cs->sps->getSpsNext().getUseGBi() && pu.cu->GBiIdx != GBI_DEFAULT && !bBi && xReadBufferedAffineUniMv(pu, eRefPicList, iRefIdxPred, acMvPred, acMv, ruiBits, ruiCost) )
+  if( pu.cu->cs->sps->getUseGBi() && pu.cu->GBiIdx != GBI_DEFAULT && !bBi && xReadBufferedAffineUniMv(pu, eRefPicList, iRefIdxPred, acMvPred, acMv, ruiBits, ruiCost
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+      , mvpIdx, aamvpi
+#endif
+  ) )
   {
     return;
   }
 
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  uint32_t dirBits = ruiBits - m_auiMVPIdxCost[mvpIdx][aamvpi.numCand];
+  int bestMvpIdx   = mvpIdx;
+#endif
   const int width  = pu.Y().width;
   const int height = pu.Y().height;
 
@@ -4248,10 +5042,16 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
   // Set start Mv position, use input mv as started search mv
   Mv acMvTemp[3];
   ::memcpy( acMvTemp, acMv, sizeof(Mv)*3 );
-  acMvTemp[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-  acMvTemp[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-  acMvTemp[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-
+#if JVET_M0246_AFFINE_AMVR
+  if ( pu.cu->imv != 1 )
+  {
+#endif
+    acMvTemp[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+    acMvTemp[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+    acMvTemp[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+  }
+#endif
   // Set delta mv
   // malloc buffer
   int iParaNum = pu.cu->affineType ? 7 : 5;
@@ -4286,6 +5086,18 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
             pu.cu->lumaSize(),
             *pu.cs->sps );
   }
+#if JVET_M0246_AFFINE_AMVR
+  int mvdPrecision = ( pu.cu->imv == 1 ) ? 2 : 0;
+  if ( pu.cu->imv == 2 )
+  {
+    acMvTemp[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    acMvTemp[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
+    {
+      acMvTemp[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+    }
+  }
+#endif
   xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cs->slice->clpRng( COMPONENT_Y ) );
 
   // get error
@@ -4294,7 +5106,25 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
   // get cost with mv
   m_pcRdCost->setCostScale(0);
   uiBitsBest = ruiBits;
-  DTRACE( g_trace_ctx, D_COMMON, " (%d) xx uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  if ( pu.cu->imv == 2 && m_pcEncCfg->getUseAffineAmvrEncOpt() )
+  {
+    uiBitsBest  = dirBits + xDetermineBestMvp( pu, acMvTemp, mvpIdx, aamvpi );
+    acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
+    acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
+    acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
+  }
+  else
+  {
+#endif
+    DTRACE( g_trace_ctx, D_COMMON, " (%d) xx uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
+#if JVET_M0246_AFFINE_AMVR
+    uiBitsBest += xCalcAffineMVBits( pu, acMvTemp, acMvPred, pu.cu->imv != 1 );
+    DTRACE( g_trace_ctx, D_COMMON, " (%d) yy uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  }
+#endif
+#else
   for ( int i = 0; i < mvNum; i++ )
   {
     DTRACE( g_trace_ctx, D_COMMON, "#mvPredForBits=(%d,%d) \n", acMvPred[i].getHor(), acMvPred[i].getVer() );
@@ -4313,6 +5143,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
     uiBitsBest += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor()>>shift, acMvTemp[i].getVer()>>shift, 0 );
     DTRACE( g_trace_ctx, D_COMMON, " (%d) yy uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
   }
+#endif
   uiCostBest = (Distortion)( floor( fWeight * (double)uiCostBest ) + (double)m_pcRdCost->getCost( uiBitsBest ) );
 
   DTRACE( g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest, uiCostBest );
@@ -4321,7 +5152,9 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
 
   const int bufStride = pBuf->Y().stride;
   const int predBufStride = predBuf.Y().stride;
-
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  Mv prevIterMv[7][3];
+#endif
   int iIterTime;
   if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
   {
@@ -4332,12 +5165,15 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
     iIterTime = bBi ? 3 : 5;
   }
 
-  if ( !pu.cu->cs->sps->getSpsNext().getUseAffineType() )
+  if ( !pu.cu->cs->sps->getUseAffineType() )
   {
     iIterTime = bBi ? 5 : 7;
   }
   for ( int iter=0; iter<iIterTime; iter++ )    // iterate loop
   {
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    memcpy( prevIterMv[iter], acMvTemp, sizeof( Mv ) * 3 );
+#endif
     /*********************************************************************************
      *                         use gradient to update mv
      *********************************************************************************/
@@ -4406,7 +5242,18 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
       dDeltaMv[3] = -dAffinePara[3] * width + dAffinePara[2];
     }
+#if JVET_M0246_AFFINE_AMVR
+    int mvShift = MV_FRACTIONAL_BITS_DIFF - mvdPrecision;
+    int multiShift = 1 << ( MV_FRACTIONAL_BITS_DIFF + mvdPrecision );
 
+    acDeltaMv[0] = Mv( ( int ) ( dDeltaMv[0] * multiShift + SIGN( dDeltaMv[0] ) * 0.5 ) << mvShift, ( int ) ( dDeltaMv[2] * multiShift + SIGN( dDeltaMv[2] ) * 0.5 ) << mvShift );
+    acDeltaMv[1] = Mv( ( int ) ( dDeltaMv[1] * multiShift + SIGN( dDeltaMv[1] ) * 0.5 ) << mvShift, ( int ) ( dDeltaMv[3] * multiShift + SIGN( dDeltaMv[3] ) * 0.5 ) << mvShift );
+
+    if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
+    {
+      acDeltaMv[2] = Mv( ( int ) ( dDeltaMv[4] * multiShift + SIGN( dDeltaMv[4] ) * 0.5 ) << mvShift, ( int ) ( dDeltaMv[5] * multiShift + SIGN( dDeltaMv[5] ) * 0.5 ) << mvShift );
+    }
+#else
     acDeltaMv[0] = Mv( (int)(dDeltaMv[0] * 4 + SIGN( dDeltaMv[0] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF, (int)(dDeltaMv[2] * 4 + SIGN( dDeltaMv[2] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF
       );
     acDeltaMv[1] = Mv( (int)(dDeltaMv[1] * 4 + SIGN( dDeltaMv[1] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF, (int)(dDeltaMv[3] * 4 + SIGN( dDeltaMv[3] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF
@@ -4417,21 +5264,36 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       acDeltaMv[2] = Mv( (int)(dDeltaMv[4] * 4 + SIGN( dDeltaMv[4] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF, (int)(dDeltaMv[5] * 4 + SIGN( dDeltaMv[5] ) * 0.5) << MV_FRACTIONAL_BITS_DIFF
       );
     }
-
-    bool bAllZero = false;
-    for ( int i = 0; i < mvNum; i++ )
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    if ( !m_pcEncCfg->getUseAffineAmvrEncOpt() )
     {
-      if ( acDeltaMv[i].getHor() != 0 || acDeltaMv[i].getVer() != 0 )
+#endif
+      bool bAllZero = false;
+      for ( int i = 0; i < mvNum; i++ )
       {
-        bAllZero = false;
-        break;
+#if JVET_M0246_AFFINE_AMVR
+        Mv deltaMv = acDeltaMv[i];
+        if ( pu.cu->imv == 2 )
+        {
+          deltaMv.roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_HALF );
+        }
+        if ( deltaMv.getHor() != 0 || deltaMv.getVer() != 0 )
+#else
+        if ( acDeltaMv[i].getHor() != 0 || acDeltaMv[i].getVer() != 0 )
+#endif
+        {
+          bAllZero = false;
+          break;
+        }
+        bAllZero = true;
       }
-      bAllZero = true;
-    }
-
-    if ( bAllZero )
-      break;
 
+      if ( bAllZero )
+        break;
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    }
+#endif
     // do motion compensation with updated mv
     for ( int i = 0; i < mvNum; i++ )
     {
@@ -4443,11 +5305,45 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       acMvTemp[i].hor = Clip3( -32768, 32767, acMvTemp[i].hor );
       acMvTemp[i].ver = Clip3( -32768, 32767, acMvTemp[i].ver );
 #endif
-      acMvTemp[i].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      if ( pu.cu->imv == 0 )
+      {
+#endif
+        acMvTemp[i].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+      }
+      else if ( pu.cu->imv == 2 )
+      {
+        acMvTemp[i].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
+      }
+#endif
       clipMv(acMvTemp[i], pu.cu->lumaPos(),
              pu.cu->lumaSize(),
              *pu.cs->sps);
     }
+
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    if ( m_pcEncCfg->getUseAffineAmvrEncOpt() )
+    {
+      bool identical = false;
+      for ( int k = iter; k >= 0; k-- )
+      {
+        if ( acMvTemp[0] == prevIterMv[k][0] && acMvTemp[1] == prevIterMv[k][1] )
+        {
+          identical = pu.cu->affineType ? acMvTemp[2] == prevIterMv[k][2] : true;
+          if ( identical )
+          {
+            break;
+          }
+        }
+      }
+      if ( identical )
+      {
+        break;
+      }
+    }
+#endif
+
     xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng( COMPONENT_Y ) );
 
     // get error
@@ -4457,6 +5353,23 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
     // get cost with mv
     m_pcRdCost->setCostScale(0);
     uint32_t uiBitsTemp = ruiBits;
+#if JVET_M0246_AFFINE_AMVR
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    if ( pu.cu->imv == 2 && m_pcEncCfg->getUseAffineAmvrEncOpt() )
+    {
+      uiBitsTemp  = dirBits + xDetermineBestMvp( pu, acMvTemp, bestMvpIdx, aamvpi );
+      acMvPred[0] = aamvpi.mvCandLT[bestMvpIdx];
+      acMvPred[1] = aamvpi.mvCandRT[bestMvpIdx];
+      acMvPred[2] = aamvpi.mvCandLB[bestMvpIdx];
+    }
+    else
+    {
+      uiBitsTemp += xCalcAffineMVBits( pu, acMvTemp, acMvPred, pu.cu->imv != 1 );
+    }
+#else
+    uiBitsTemp += xCalcAffineMVBits( pu, acMvTemp, acMvPred, pu.cu->imv != 1 );
+#endif
+#else
     for ( int i = 0; i < mvNum; i++ )
     {
       m_pcRdCost->setPredictor( acMvPred[i] );
@@ -4472,7 +5385,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       }
       uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor()>>shift, acMvTemp[i].getVer()>>shift, 0 );
     }
-
+#endif
     uiCostTemp = (Distortion)( floor( fWeight * (double)uiCostTemp ) + (double)m_pcRdCost->getCost( uiBitsTemp ) );
 
     // store best cost and mv
@@ -4481,10 +5394,13 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       uiCostBest = uiCostTemp;
       uiBitsBest = uiBitsTemp;
       memcpy( acMv, acMvTemp, sizeof(Mv) * 3 );
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+      mvpIdx = bestMvpIdx;
+#endif
     }
   }
 
-  auto checkCPMVRdCost = [&](Mv ctrlPtMv[3]) 
+  auto checkCPMVRdCost = [&](Mv ctrlPtMv[3])
   {
     xPredAffineBlk(COMPONENT_Y, pu, refPic, ctrlPtMv, predBuf, false, pu.cu->slice->clpRng(COMPONENT_Y));
     // get error
@@ -4492,6 +5408,9 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
     // get cost with mv
     m_pcRdCost->setCostScale(0);
     uint32_t bitsTemp = ruiBits;
+#if JVET_M0246_AFFINE_AMVR
+    bitsTemp += xCalcAffineMVBits( pu, ctrlPtMv, acMvPred, pu.cu->imv != 1 );
+#else
     for (int i = 0; i < mvNum; i++)
     {
       m_pcRdCost->setPredictor(acMvPred[i]);
@@ -4507,6 +5426,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       }
       bitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor(ctrlPtMv[i].getHor() >> shift, ctrlPtMv[i].getVer() >> shift, 0);
     }
+#endif
     costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp));
     // store best cost and mv
     if (costTemp < uiCostBest)
@@ -4519,10 +5439,67 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
 
   if (uiCostBest <= AFFINE_ME_LIST_MVP_TH*m_hevcCost)
   {
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    //search 8 nearest neighbors; integer distance
+    int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } };
+    const uint32_t mvShift = pu.cu->imv == 1 ? 0 : ( pu.cu->imv == 2 ? ( MV_FRACTIONAL_BITS_DIFF << 1 ) : MV_FRACTIONAL_BITS_DIFF );
+    const int maxSearchRound = 3;
+
+    if ( m_pcEncCfg->getUseAffineAmvrEncOpt() && m_pcEncCfg->getIntraPeriod() != ( uint32_t ) -1 && pu.cu->imv )
+    {
+      for ( int rnd = 0; rnd < ( pu.cu->slice->getTLayer() <= 2 ? maxSearchRound : maxSearchRound - 1 ); rnd++ )
+      {
+        bool modelChange = false;
+        //search the model parameters with finear granularity;
+        for ( int j = 0; j < mvNum; j++ )
+        {
+          for ( int iter = 0; iter < 2; iter++ )
+          {
+            Mv centerMv[3];
+            memcpy( centerMv, acMv, sizeof( Mv ) * 3 );
+            memcpy( acMvTemp, acMv, sizeof( Mv ) * 3 );
+            for ( int i = ( iter ? 0: 4 ); i < ( iter ? 4 : 8 ); i++ )
+            {
+              acMvTemp[j].set( centerMv[j].getHor() + ( testPos[i][0] << mvShift ), centerMv[j].getVer() + ( testPos[i][1] << mvShift ) );
+
+              clipMv( acMvTemp[j], pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps );
+              xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng( COMPONENT_Y ) );
+
+              Distortion costTemp = m_pcRdCost->getDistPart( predBuf.Y(), pBuf->Y(), pu.cs->sps->getBitDepth( CHANNEL_TYPE_LUMA ), COMPONENT_Y, DF_HAD );
+              uint32_t bitsTemp   = ruiBits;
+              bitsTemp += xCalcAffineMVBits( pu, acMvTemp, acMvPred, pu.cu->imv != 1 );
+              costTemp = ( Distortion ) ( floor( fWeight * ( double ) costTemp ) + ( double ) m_pcRdCost->getCost( bitsTemp ) );
+
+              if ( costTemp < uiCostBest )
+              {
+                uiCostBest = costTemp;
+                uiBitsBest = bitsTemp;
+                ::memcpy( acMv, acMvTemp, sizeof( Mv ) * 3 );
+                modelChange = true;
+              }
+            }
+          }
+        }
+
+        if ( !modelChange )
+        {
+          break;
+        }
+      }
+    }
+#endif
+
     Mv mvPredTmp[3] = { acMvPred[0], acMvPred[1], acMvPred[2] };
-    mvPredTmp[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-    mvPredTmp[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
-    mvPredTmp[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+    if ( pu.cu->imv != 1 )
+    {
+#endif
+      mvPredTmp[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+      mvPredTmp[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+      mvPredTmp[2].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
+#if JVET_M0246_AFFINE_AMVR
+    }
+#endif
     Mv mvME[3];
     ::memcpy(mvME, acMv, sizeof(Mv) * 3);
     Mv dMv = mvME[0] - mvPredTmp[0];
@@ -4554,7 +5531,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       checkCPMVRdCost(acMvTemp);
     }
 
-    //keep the translation; 
+    //keep the translation;
     if (pu.cu->affineType == AFFINEMODEL_6PARAM && mvME[1] != (mvPredTmp[1] + dMv) && mvME[2] != (mvPredTmp[2] + dMv))
     {
       ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
@@ -4571,20 +5548,38 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
       {
         int testPos[4][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 } };
         Mv centerMv[3];
+#if JVET_M0246_AFFINE_AMVR
+        const uint32_t mvShift = pu.cu->imv == 1 ? 0 : ( pu.cu->imv == 2 ? ( MV_FRACTIONAL_BITS_DIFF << 1 ) : MV_FRACTIONAL_BITS_DIFF );
+#endif
         ::memcpy(centerMv, acMv, sizeof(Mv) * 3);
         acMvTemp[0] = centerMv[0];
         for (int i = 0; i < 4; i++)
         {
+#if JVET_M0246_AFFINE_AMVR
+          acMvTemp[1].set( centerMv[1].getHor() + ( testPos[i][0] << mvShift ), centerMv[1].getVer() + ( testPos[i][1] << mvShift ) );
+#else
           acMvTemp[1].set(centerMv[1].getHor() + (testPos[i][0] << MV_FRACTIONAL_BITS_DIFF), centerMv[1].getVer() + (testPos[i][1] << MV_FRACTIONAL_BITS_DIFF));
+#endif
           checkCPMVRdCost(acMvTemp);
         }
       }
     }
   }
-
-  acMv[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-  acMv[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
-  acMv[2].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+  if ( pu.cu->imv != 1 )
+  {
+#endif
+    acMv[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+    acMv[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+    acMv[2].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
+#if JVET_M0246_AFFINE_AMVR
+  }
+#endif
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
+  acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
+  acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
+#endif
 
   // free buffer
   for (int i = 0; i<iParaNum; i++)
@@ -4678,11 +5673,24 @@ void InterSearch::xExtDIFUpSamplingH( CPelBuf* pattern )
   const ChromaFormat chFmt = m_currChromaFormat;
 
   m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0][0], intStride, width + 1, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng);
+#if JVET_M0253_HASH_ME
+  if (!m_skipFracME)
+  {
+#endif
   m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2][0], intStride, width + 1, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng);
+#if JVET_M0253_HASH_ME
+  }
+#endif
 
   intPtr = m_filteredBlockTmp[0][0] + halfFilterSize * intStride + 1;
   dstPtr = m_filteredBlock[0][0][0];
   m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng);
+#if JVET_M0253_HASH_ME
+  if (m_skipFracME)
+  {
+    return;
+  }
+#endif
 
   intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
   dstPtr = m_filteredBlock[2][0][0];
@@ -4928,6 +5936,12 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
     {
       CHECK( !bSubdiv, "Not performing the implicit TU split" );
     }
+#if JVET_M0140_SBT
+    else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+    {
+      CHECK( !bSubdiv, "Not performing the implicit TU split - sbt" );
+    }
+#endif
     else
     {
       CHECK( bSubdiv, "transformsplit not supported" );
@@ -4942,17 +5956,27 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
         if( firstCbfOfCU || TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth - 1 ) )
         {
           const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth );
+#if JVET_M0140_SBT
+          if( !( cu.sbtInfo && currDepth == 1 ) )
+#endif
           m_CABACEstimator->cbf_comp( cs, chroma_cbf, currArea.blocks[COMPONENT_Cb], currDepth );
         }
         if( firstCbfOfCU || TU::getCbfAtDepth( currTU, COMPONENT_Cr, currDepth - 1 ) )
         {
           const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMPONENT_Cr, currDepth );
+#if JVET_M0140_SBT
+          if( !( cu.sbtInfo && currDepth == 1 ) )
+#endif
           m_CABACEstimator->cbf_comp( cs, chroma_cbf, currArea.blocks[COMPONENT_Cr], currDepth, TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth ) );
         }
       }
     }
 
+#if JVET_M0140_SBT
+    if( !bSubdiv && !( cu.sbtInfo && currTU.noResidual ) )
+#else
     if( !bSubdiv )
+#endif
     {
       m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currArea.Y(), currDepth );
     }
@@ -4983,6 +6007,12 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
       {
         partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
       }
+#if JVET_M0140_SBT
+      else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+      {
+        partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
+      }
+#endif
       else
         THROW( "Implicit TU split not available!" );
 
@@ -4996,6 +6026,253 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
   }
 }
 
+#if JVET_M0140_SBT
+void InterSearch::calcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, const uint8_t sbtAllowed )
+{
+  if( !sbtAllowed )
+  {
+    m_estMinDistSbt[NUMBER_SBT_MODE] = 0;
+    for( int comp = 0; comp < getNumberValidTBlocks( *cs.pcv ); comp++ )
+    {
+      const ComponentID compID = ComponentID( comp );
+      CPelBuf pred = cs.getPredBuf( compID );
+      CPelBuf org  = cs.getOrgBuf( compID );
+      m_estMinDistSbt[NUMBER_SBT_MODE] += m_pcRdCost->getDistPart( org, pred, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
+    }
+    return;
+  }
+
+  //SBT fast algorithm 2.1 : estimate a minimum RD cost of a SBT mode based on the luma distortion of uncoded part and coded part (assuming distorted can be reduced to 1/16);
+  //                         if this cost is larger than the best cost, no need to try a specific SBT mode
+  int cuWidth  = cu.lwidth();
+  int cuHeight = cu.lheight();
+  int numPartX = cuWidth  >= 16 ? 4 : ( cuWidth  == 4 ? 1 : 2 );
+  int numPartY = cuHeight >= 16 ? 4 : ( cuHeight == 4 ? 1 : 2 );
+  Distortion dist[4][4];
+  memset( dist, 0, sizeof( Distortion ) * 16 );
+
+  for( uint32_t c = 0; c < getNumberValidTBlocks( *cs.pcv ); c++ )
+  {
+    const ComponentID compID   = ComponentID( c );
+    const CompArea&   compArea = cu.blocks[compID];
+    const CPelBuf orgPel  = cs.getOrgBuf( compArea );
+    const CPelBuf predPel = cs.getPredBuf( compArea );
+    int lengthX = compArea.width / numPartX;
+    int lengthY = compArea.height / numPartY;
+    int strideOrg  = orgPel.stride;
+    int stridePred = predPel.stride;
+    uint32_t   uiShift = DISTORTION_PRECISION_ADJUSTMENT( ( *cs.sps.getBitDepth( toChannelType( compID ) ) - 8 ) << 1 );
+    Intermediate_Int iTemp;
+
+    //calc distY of 16 sub parts
+    for( int j = 0; j < numPartY; j++ )
+    {
+      for( int i = 0; i < numPartX; i++ )
+      {
+        int posX = i * lengthX;
+        int posY = j * lengthY;
+        const Pel* ptrOrg  = orgPel.bufAt( posX, posY );
+        const Pel* ptrPred = predPel.bufAt( posX, posY );
+        Distortion uiSum = 0;
+        for( int n = 0; n < lengthY; n++ )
+        {
+          for( int m = 0; m < lengthX; m++ )
+          {
+            iTemp = ptrOrg[m] - ptrPred[m];
+            uiSum += Distortion( ( iTemp * iTemp ) >> uiShift );
+          }
+          ptrOrg += strideOrg;
+          ptrPred += stridePred;
+        }
+        if( isChroma( compID ) )
+        {
+          uiSum = (Distortion)( uiSum * m_pcRdCost->getChromaWeight() );
+        }
+        dist[j][i] += uiSum;
+      }
+    }
+  }
+
+  //SSE of a CU
+  m_estMinDistSbt[NUMBER_SBT_MODE] = 0;
+  for( int j = 0; j < numPartY; j++ )
+  {
+    for( int i = 0; i < numPartX; i++ )
+    {
+      m_estMinDistSbt[NUMBER_SBT_MODE] += dist[j][i];
+    }
+  }
+  //init per-mode dist
+  for( int i = SBT_VER_H0; i < NUMBER_SBT_MODE; i++ )
+  {
+    m_estMinDistSbt[i] = std::numeric_limits<uint64_t>::max();
+  }
+
+  //SBT fast algorithm 1: not try SBT if the residual is too small to compensate bits for encoding residual info
+  uint64_t minNonZeroResiFracBits = 12 << SCALE_BITS;
+  if( m_pcRdCost->calcRdCost( 0, m_estMinDistSbt[NUMBER_SBT_MODE] ) < m_pcRdCost->calcRdCost( minNonZeroResiFracBits, 0 ) )
+  {
+    m_skipSbtAll = true;
+    return;
+  }
+
+  //derive estimated minDist of SBT = zero-residual part distortion + non-zero residual part distortion / 16
+  int shift = 5;
+  Distortion distResiPart = 0, distNoResiPart = 0;
+
+  if( CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) )
+  {
+    int offsetResiPart = 0;
+    int offsetNoResiPart = numPartX / 2;
+    distResiPart = distNoResiPart = 0;
+    assert( numPartX >= 2 );
+    for( int j = 0; j < numPartY; j++ )
+    {
+      for( int i = 0; i < numPartX / 2; i++ )
+      {
+        distResiPart   += dist[j][i + offsetResiPart];
+        distNoResiPart += dist[j][i + offsetNoResiPart];
+      }
+    }
+    m_estMinDistSbt[SBT_VER_H0] = ( distResiPart >> shift ) + distNoResiPart;
+    m_estMinDistSbt[SBT_VER_H1] = ( distNoResiPart >> shift ) + distResiPart;
+  }
+
+  if( CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed ) )
+  {
+    int offsetResiPart = 0;
+    int offsetNoResiPart = numPartY / 2;
+    assert( numPartY >= 2 );
+    distResiPart = distNoResiPart = 0;
+    for( int j = 0; j < numPartY / 2; j++ )
+    {
+      for( int i = 0; i < numPartX; i++ )
+      {
+        distResiPart   += dist[j + offsetResiPart][i];
+        distNoResiPart += dist[j + offsetNoResiPart][i];
+      }
+    }
+    m_estMinDistSbt[SBT_HOR_H0] = ( distResiPart >> shift ) + distNoResiPart;
+    m_estMinDistSbt[SBT_HOR_H1] = ( distNoResiPart >> shift ) + distResiPart;
+  }
+
+  if( CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) )
+  {
+    assert( numPartX == 4 );
+    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q1] = 0;
+    for( int j = 0; j < numPartY; j++ )
+    {
+      m_estMinDistSbt[SBT_VER_Q0] += dist[j][0] + ( ( dist[j][1] + dist[j][2] + dist[j][3] ) << shift );
+      m_estMinDistSbt[SBT_VER_Q1] += dist[j][3] + ( ( dist[j][0] + dist[j][1] + dist[j][2] ) << shift );
+    }
+    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q0] >> shift;
+    m_estMinDistSbt[SBT_VER_Q1] = m_estMinDistSbt[SBT_VER_Q1] >> shift;
+  }
+
+  if( CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ) )
+  {
+    assert( numPartY == 4 );
+    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q1] = 0;
+    for( int i = 0; i < numPartX; i++ )
+    {
+      m_estMinDistSbt[SBT_HOR_Q0] += dist[0][i] + ( ( dist[1][i] + dist[2][i] + dist[3][i] ) << shift );
+      m_estMinDistSbt[SBT_HOR_Q1] += dist[3][i] + ( ( dist[0][i] + dist[1][i] + dist[2][i] ) << shift );
+    }
+    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q0] >> shift;
+    m_estMinDistSbt[SBT_HOR_Q1] = m_estMinDistSbt[SBT_HOR_Q1] >> shift;
+  }
+
+  //SBT fast algorithm 5: try N SBT modes with the lowest distortion
+  Distortion temp[NUMBER_SBT_MODE];
+  memcpy( temp, m_estMinDistSbt, sizeof( Distortion ) * NUMBER_SBT_MODE );
+  memset( m_sbtRdoOrder, 255, NUMBER_SBT_MODE );
+  int startIdx = 0, numRDO;
+  numRDO = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
+  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
+  for( int i = startIdx; i < startIdx + numRDO; i++ )
+  {
+    Distortion minDist = std::numeric_limits<uint64_t>::max();
+    for( int n = SBT_VER_H0; n <= SBT_HOR_H1; n++ )
+    {
+      if( temp[n] < minDist )
+      {
+        minDist = temp[n];
+        m_sbtRdoOrder[i] = n;
+      }
+    }
+    temp[m_sbtRdoOrder[i]] = std::numeric_limits<uint64_t>::max();
+  }
+
+  startIdx += numRDO;
+  numRDO = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
+  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
+  for( int i = startIdx; i < startIdx + numRDO; i++ )
+  {
+    Distortion minDist = std::numeric_limits<uint64_t>::max();
+    for( int n = SBT_VER_Q0; n <= SBT_HOR_Q1; n++ )
+    {
+      if( temp[n] < minDist )
+      {
+        minDist = temp[n];
+        m_sbtRdoOrder[i] = n;
+      }
+    }
+    temp[m_sbtRdoOrder[i]] = std::numeric_limits<uint64_t>::max();
+  }
+}
+
+uint8_t InterSearch::skipSbtByRDCost( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff )
+{
+  int sbtMode = CU::getSbtMode( sbtIdx, sbtPos );
+
+  //SBT fast algorithm 2.2 : estimate a minimum RD cost of a SBT mode based on the luma distortion of uncoded part and coded part (assuming distorted can be reduced to 1/16);
+  //                         if this cost is larger than the best cost, no need to try a specific SBT mode
+  if( m_pcRdCost->calcRdCost( 11 << SCALE_BITS, m_estMinDistSbt[sbtMode] ) > bestCost )
+  {
+    return 0; //early skip type 0
+  }
+
+  if( costSbtOff != MAX_DOUBLE )
+  {
+    if( !rootCbfSbtOff )
+    {
+      //SBT fast algorithm 3: skip SBT when the residual is too small (estCost is more accurate than fast algorithm 1, counting PU mode bits)
+      uint64_t minNonZeroResiFracBits = 10 << SCALE_BITS;
+      Distortion distResiPart;
+      if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_HOR_HALF )
+      {
+        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 9 ) >> 4 );
+      }
+      else
+      {
+        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 3 ) >> 3 );
+      }
+
+      double estCost = ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) + m_pcRdCost->calcRdCost( minNonZeroResiFracBits, m_estMinDistSbt[sbtMode] + distResiPart );
+      if( estCost > costSbtOff )
+      {
+        return 1;
+      }
+      if( estCost > bestCost )
+      {
+        return 2;
+      }
+    }
+    else
+    {
+      //SBT fast algorithm 4: skip SBT when an estimated RD cost is larger than the bestCost
+      double weight = sbtMode > SBT_HOR_H1 ? 0.4 : 0.6;
+      double estCost = ( ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) * weight ) + m_pcRdCost->calcRdCost( 0 << SCALE_BITS, m_estMinDistSbt[sbtMode] );
+      if( estCost > bestCost )
+      {
+        return 3;
+      }
+    }
+  }
+  return MAX_UCHAR;
+}
+#endif
+
 void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &partitioner, Distortion *puiZeroDist /*= NULL*/
   , const bool luma, const bool chroma
 )
@@ -5011,6 +6288,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
   const unsigned currDepth = partitioner.currTrDepth;
 
   bool bCheckFull  = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
+#if JVET_M0140_SBT
+  if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+  {
+    bCheckFull = false;
+  }
+#endif
   bool bCheckSplit = !bCheckFull;
 
   // get temporary data
@@ -5041,6 +6324,30 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 #else
     tu.emtIdx         = 0;
 #endif
+#if JVET_M0140_SBT
+    tu.checkTuNoResidual( partitioner.currPartIdx() );
+#endif
+
+#if JVET_M0427_INLOOP_RESHAPER
+    const Slice           &slice = *cs.slice;
+    if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+    {
+      const CompArea      &areaY = tu.blocks[COMPONENT_Y];
+      PelBuf              piPredY = cs.getPredBuf(areaY);
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(piPredY);
+#if JVET_M0483_IBC
+      if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (!cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+      const Pel           avgLuma = tmpPred.computeAvg();
+      int                    adj  = m_pcReshape->calculateChromaAdj(avgLuma);
+      tu.setChromaAdj(adj);
+    }
+#endif
 
     double minCost            [MAX_NUM_TBLOCKS];
 #if !JVET_M0464_UNI_MTS
@@ -5106,15 +6413,41 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
       uint8_t nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests
       std::vector<TrMode> trModes;
       trModes.push_back( TrMode( 0, true ) ); //DCT2
+#if JVET_M0140_SBT
+      nNumTransformCands = 1;
+      //for a SBT-no-residual TU, the RDO process should be called once, in order to get the RD cost
+      if( tsAllowed && !tu.noResidual )
+#else
       if( tsAllowed )
+#endif
       {
         trModes.push_back( TrMode( 1, true ) );
+#if JVET_M0140_SBT
+        nNumTransformCands++;
+#endif
       }
+
+#if APPLY_SBT_SL_ON_MTS
+      //skip MTS if DCT2 is the best
+      if( mtsAllowed && ( !tu.cu->slice->getSPS()->getUseSBT() || CU::getSbtIdx( m_histBestSbt ) != SBT_OFF_DCT ) )
+#else
       if( mtsAllowed )
+#endif
       {
         for( int i = 2; i < 6; i++ )
         {
+#if APPLY_SBT_SL_ON_MTS
+          //skip the non-best Mts mode
+          if( !tu.cu->slice->getSPS()->getUseSBT() || ( m_histBestMtsIdx == MAX_UCHAR || m_histBestMtsIdx == i ) )
+          {
+#endif
           trModes.push_back( TrMode( i, true ) );
+#if JVET_M0140_SBT
+          nNumTransformCands++;
+#endif
+#if APPLY_SBT_SL_ON_MTS
+          }
+#endif
         }
       }
 #endif
@@ -5122,7 +6455,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 #if JVET_M0464_UNI_MTS
       const int numTransformCandidates = nNumTransformCands;
 #else
-      const int numEmtTransformCandidates   = isLuma(compID) && tu.cu->emtFlag && sps.getSpsNext().getUseInterEMT() ? 4 : 1;
+      const int numEmtTransformCandidates   = isLuma(compID) && tu.cu->emtFlag && sps.getUseInterEMT() ? 4 : 1;
       const int numTransformCandidates      = checkTransformSkip[compID] ? ( numEmtTransformCandidates + 1 ) : numEmtTransformCandidates;
       int lastTransformModeIndex            = numTransformCandidates - 1; //lastTransformModeIndex is the mode for transformSkip (if transformSkip is active)
 #endif
@@ -5167,7 +6500,13 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 #if RDOQ_CHROMA_LAMBDA
           m_pcTrQuant->selectLambda(compID);
 #endif
-
+#if JVET_M0427_INLOOP_RESHAPER
+          if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+          {
+            double cRescale = round((double)(1 << CSCALE_FP_PREC) / (double)(tu.getChromaAdj()));
+            m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cRescale*cRescale));
+          }
+#endif
           TCoeff     currAbsSum = 0;
           uint64_t   currCompFracBits = 0;
           Distortion currCompDist = 0;
@@ -5181,7 +6520,13 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             PelBuf resiBuf = csFull->getResiBuf( compArea );
             crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, false );
           }
-
+#if JVET_M0427_INLOOP_RESHAPER
+          if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && tu.blocks[compID].width*tu.blocks[compID].height > 4 )
+          {
+            PelBuf resiBuf = csFull->getResiBuf(compArea);
+            resiBuf.scaleSignal(tu.getChromaAdj(), 1, tu.cu->cs->slice->clpRng(compID));
+          }
+#endif
 #if JVET_M0464_UNI_MTS
           if( nNumTransformCands > 1 )
           {
@@ -5216,6 +6561,10 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
               nonCoeffDist = m_pcRdCost->getDistPart( zeroBuf, orgResi, channelBitDepth, compID, DF_SSE ); // initialized with zero residual distortion
             }
 
+#if JVET_M0140_SBT
+            if( !tu.noResidual )
+            {
+#endif
             const bool prevCbf = ( compID == COMPONENT_Cr ? tu.cbf[COMPONENT_Cb] : false );
             m_CABACEstimator->cbf_comp( *csFull, false, compArea, currDepth, prevCbf );
 
@@ -5223,6 +6572,9 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             {
               m_CABACEstimator->cross_comp_pred( tu, compID );
             }
+#if JVET_M0140_SBT
+            }
+#endif
 
             nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
 #if WCG_EXT
@@ -5263,6 +6615,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             CPelBuf orgResiBuf = csFull->getOrgResiBuf(compArea);
 
             m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
+#if JVET_M0427_INLOOP_RESHAPER
+            if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && tu.blocks[compID].width*tu.blocks[compID].height > 4 )
+            {
+              resiBuf.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
+            }
+#endif
 
             if (bUseCrossCPrediction)
             {
@@ -5270,7 +6628,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             }
 
             currCompDist = m_pcRdCost->getDistPart(orgResiBuf, resiBuf, channelBitDepth, compID, DF_SSE);
-            
+
 #if WCG_EXT
             currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false);
 #else
@@ -5342,6 +6700,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 
             isLastBest = isLastMode;
           }
+#if JVET_M0140_SBT
+          if( tu.noResidual )
+          {
+            CHECK( currCompFracBits > 0 || currAbsSum, "currCompFracBits > 0 when tu noResidual" );
+          }
+#endif
         }
       }
 
@@ -5355,7 +6719,10 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 
     m_CABACEstimator->getCtx() = ctxStart;
     m_CABACEstimator->resetBits();
-
+#if JVET_M0140_SBT
+    if( !tu.noResidual )
+    {
+#endif
     static const ComponentID cbf_getComp[3] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y };
     for( unsigned c = 0; c < numTBlocks; c++)
     {
@@ -5370,6 +6737,9 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         m_CABACEstimator->cbf_comp( *csFull, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth, prevCbf );
       }
     }
+#if JVET_M0140_SBT
+    }
+#endif
 
     for (uint32_t ch = 0; ch < numValidComp; ch++)
     {
@@ -5391,6 +6761,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         uiSingleDist += uiSingleDistComp[compID];
       }
     }
+#if JVET_M0140_SBT
+    if( tu.noResidual )
+    {
+      CHECK( m_CABACEstimator->getEstFracBits() > 0, "no residual TU's bits shall be 0" );
+    }
+#endif
 
     csFull->fracBits += m_CABACEstimator->getEstFracBits();
     csFull->dist     += uiSingleDist;
@@ -5416,6 +6792,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
     {
       partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
     }
+#if JVET_M0140_SBT
+    else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs ) )
+    {
+      partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
+    }
+#endif
     else
       THROW( "Implicit TU split not available!" );
 
@@ -5535,9 +6917,22 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
   {
     cu.skip    = true;
     cu.rootCbf = false;
+#if JVET_M0140_SBT
+    CHECK( cu.sbtInfo != 0, "sbtInfo shall be 0 if CU has no residual" );
+#endif
     cs.getResiBuf().fill(0);
     {
       cs.getRecoBuf().copyFrom(cs.getPredBuf() );
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+      if (m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+      {
+        cs.getRecoBuf().Y().rspSignal(m_pcReshape->getFwdLUT());
+      }
+#endif
     }
 
 
@@ -5555,9 +6950,26 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       CPelBuf reco = cs.getRecoBuf (compID);
       CPelBuf org  = cs.getOrgBuf  (compID);
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+        m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper()&& m_pcReshape->getCTUFlag())))
+#else
       if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
       {
         const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
+#if JVET_M0427_INLOOP_RESHAPER
+        if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
+        {
+          const CompArea &areaY = cu.Y();
+          CompArea      tmpArea1(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+          PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+          tmpRecLuma.copyFrom(reco);
+          tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+          distortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+        }
+        else
+#endif
         distortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
       }
       else
@@ -5575,6 +6987,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     PredictionUnit &pu = *cs.getPU( partitioner.chType );
 
     m_CABACEstimator->cu_skip_flag  ( cu );
+#if JVET_M0483_IBC
+    if (CU::isIBC(cu))
+    {
+      m_CABACEstimator->merge_idx(pu);
+    }
+    else
+    {
+#endif
     m_CABACEstimator->subblock_merge_flag( cu );
     m_CABACEstimator->triangle_mode ( cu );
     if (cu.mmvdSkip)
@@ -5583,7 +7003,9 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     }
     else
     m_CABACEstimator->merge_idx     ( pu );
-
+#if JVET_M0483_IBC
+    }
+#endif
 
     cs.dist     = distortion;
     cs.fracBits = m_CABACEstimator->getEstFracBits();
@@ -5596,6 +7018,25 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
   if (luma)
   {
     cs.getResiBuf().bufs[0].copyFrom(cs.getOrgBuf().bufs[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      const CompArea &areaY = cu.Y();
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y));
+
+#if JVET_M0483_IBC
+      if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (!cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+      cs.getResiBuf(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+      cs.getResiBuf(COMPONENT_Y).subtract(tmpPred);
+    }
+    else
+#endif
     cs.getResiBuf().bufs[0].subtract(cs.getPredBuf().bufs[0]);
   }
   if (chroma)
@@ -5649,6 +7090,9 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
 
   if (zeroCost < cs.cost || !cu.rootCbf)
   {
+#if JVET_M0140_SBT
+    cu.sbtInfo = 0;
+#endif
     cu.rootCbf = false;
 
     cs.clearTUs();
@@ -5684,7 +7128,38 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
 
   if (luma)
   {
-    cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cu.rootCbf && cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      const CompArea &areaY = cu.Y();
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y));
+
+#if JVET_M0483_IBC
+      if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (!cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+
+      cs.getRecoBuf(COMPONENT_Y).reconstruct(tmpPred, cs.getResiBuf(COMPONENT_Y), cs.slice->clpRng(COMPONENT_Y));
+    }
+    else
+    {
+#endif
+      cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+#if JVET_M0483_IBC
+      if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
+#else
+      if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.ibc)
+#endif
+      {
+        cs.getRecoBuf().bufs[0].rspSignal(m_pcReshape->getFwdLUT());
+      }
+    }
+#endif
   }
   if (chroma)
   {
@@ -5706,10 +7181,27 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     CPelBuf org  = cs.getOrgBuf  (compID);
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+    if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+      m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ) ) )
+#else
     if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
     {
       const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
-      finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
+#if JVET_M0427_INLOOP_RESHAPER
+      if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) )
+      {
+        const CompArea &areaY = cu.Y();
+        CompArea      tmpArea1(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+        PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+        tmpRecLuma.copyFrom(reco);
+        tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+        finalDistortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+      }
+      else
+#endif
+        finalDistortion += m_pcRdCost->getDistPart(org, reco, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
     }
     else
 #endif
@@ -5804,12 +7296,25 @@ bool InterSearch::xReadBufferedUniMv(PredictionUnit& pu, RefPicList eRefPicList,
   return false;
 }
 
-bool InterSearch::xReadBufferedAffineUniMv(PredictionUnit& pu, RefPicList eRefPicList, int32_t iRefIdx, Mv acMvPred[3], Mv acMv[3], uint32_t& ruiBits, Distortion& ruiCost)
+bool InterSearch::xReadBufferedAffineUniMv(PredictionUnit& pu, RefPicList eRefPicList, int32_t iRefIdx, Mv acMvPred[3], Mv acMv[3], uint32_t& ruiBits, Distortion& ruiCost
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  , int& mvpIdx, const AffineAMVPInfo& aamvpi
+#endif
+)
 {
   if (m_uniMotions.isReadModeAffine((uint32_t)eRefPicList, (uint32_t)iRefIdx, pu.cu->affineType))
   {
-    m_uniMotions.copyAffineMvTo(acMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx, pu.cu->affineType);
+    m_uniMotions.copyAffineMvTo(acMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx, pu.cu->affineType
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                , mvpIdx
+#endif
+    );
     m_pcRdCost->setCostScale(0);
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+    acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
+    acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
+    acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
+#endif
 
     uint32_t uiMvBits = 0;
     for (int iVerIdx = 0; iVerIdx<(pu.cu->affineType ? 3 : 2); iVerIdx++)
@@ -5838,13 +7343,59 @@ void InterSearch::initWeightIdxBits()
   }
 }
 
+void InterSearch::xClipMv( Mv& rcMv, const Position& pos, const struct Size& size, const SPS& sps )
+{
+  int mvShift = MV_FRACTIONAL_BITS_INTERNAL;
+  int offset = 8;
+  int horMax = ( sps.getPicWidthInLumaSamples() + offset - ( int ) pos.x - 1 ) << mvShift;
+  int horMin = ( -( int ) sps.getMaxCUWidth()   - offset - ( int ) pos.x + 1 ) << mvShift;
+
+  int verMax = ( sps.getPicHeightInLumaSamples() + offset - ( int ) pos.y - 1 ) << mvShift;
+  int verMin = ( -( int ) sps.getMaxCUHeight()   - offset - ( int ) pos.y + 1 ) << mvShift;
+
+  if( sps.getWrapAroundEnabledFlag() )
+  {
+    int horMax = ( sps.getPicWidthInLumaSamples() + sps.getMaxCUWidth() - size.width + offset - ( int ) pos.x - 1 ) << mvShift;
+    int horMin = ( -( int ) sps.getMaxCUWidth()                                      - offset - ( int ) pos.x + 1 ) << mvShift;
+    rcMv.setHor( std::min( horMax, std::max( horMin, rcMv.getHor() ) ) );
+    rcMv.setVer( std::min( verMax, std::max( verMin, rcMv.getVer() ) ) );
+    return;
+  }
+
+  rcMv.setHor( std::min( horMax, std::max( horMin, rcMv.getHor() ) ) );
+  rcMv.setVer( std::min( verMax, std::max( verMin, rcMv.getVer() ) ) );
+}
+
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+uint32_t InterSearch::xDetermineBestMvp( PredictionUnit& pu, Mv acMvTemp[3], int& mvpIdx, const AffineAMVPInfo& aamvpi )
+{
+  bool mvpUpdated  = false;
+  uint32_t minBits = std::numeric_limits<uint32_t>::max();
+  for ( int i = 0; i < aamvpi.numCand; i++ )
+  {
+    Mv mvPred[3] = { aamvpi.mvCandLT[i], aamvpi.mvCandRT[i], aamvpi.mvCandLB[i] };
+    uint32_t candBits = m_auiMVPIdxCost[i][aamvpi.numCand];
+    candBits += xCalcAffineMVBits( pu, acMvTemp, mvPred, pu.cu->imv != 1 );
+
+    if ( candBits < minBits )
+    {
+      minBits    = candBits;
+      mvpIdx     = i;
+      mvpUpdated = true;
+    }
+  }
+  CHECK( !mvpUpdated, "xDetermineBestMvp() error" );
+  return minBits;
+}
+#endif
+
 #if JVET_M0444_SMVD
 void InterSearch::symmvdCheckBestMvp(
-  PredictionUnit& pu, 
+  PredictionUnit& pu,
   PelUnitBuf& origBuf,
   Mv curMv,
-  RefPicList curRefList, 
-  AMVPInfo amvpInfo[2][33], 
+  RefPicList curRefList,
+  AMVPInfo amvpInfo[2][33],
   int32_t gbiIdx,
   Mv cMvPredSym[2],
   int32_t mvpIdxSym[2],
@@ -5855,7 +7406,7 @@ void InterSearch::symmvdCheckBestMvp(
   RefPicList tarRefList = (RefPicList)(1 - curRefList);
   int32_t refIdxCur = pu.cu->slice->getSymRefIdx(curRefList);
   int32_t refIdxTar = pu.cu->slice->getSymRefIdx(tarRefList);
-  
+
   MvField cCurMvField, cTarMvField;
   cCurMvField.setMvField(curMv, refIdxCur);
   AMVPInfo& amvpCur = amvpInfo[curRefList][refIdxCur];
@@ -5917,4 +7468,4 @@ void InterSearch::symmvdCheckBestMvp(
     }
   }
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index f9edc9438352622bd17b04cddf91a8c1a235074a..4c5caed57d6d30bb89b7e82e8c2286cdaa1bc187 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -52,8 +52,14 @@
 
 #include "CommonLib/AffineGradientSearch.h"
 #include "CommonLib/IbcHashMap.h"
+#if JVET_M0253_HASH_ME
+#include "CommonLib/Hash.h"
+#endif
 #include <unordered_map>
 #include <vector>
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 //! \ingroup EncoderLib
 //! \{
 
@@ -76,6 +82,20 @@ struct AffineMVInfo
   int x, y, w, h;
 };
 
+#if JVET_M0246_AFFINE_AMVR
+typedef struct
+{
+  Mv acMvAffine4Para[2][2];
+  Mv acMvAffine6Para[2][3];
+  int16_t affine4ParaRefIdx[2];
+  int16_t affine6ParaRefIdx[2];
+  Distortion hevcCost[3];
+  Distortion affineCost[3];
+  bool affine4ParaAvail;
+  bool affine6ParaAvail;
+} EncAffineMotion;
+#endif
+
 /// encoder search class
 class InterSearch : public InterPrediction, CrossComponentPrediction, AffineGradientSearch
 {
@@ -103,13 +123,18 @@ private:
   int             m_affMVListSize;
   int             m_affMVListMaxSize;
   Distortion      m_hevcCost;
-
+#if JVET_M0246_AFFINE_AMVR
+  EncAffineMotion m_affineMotion;
+#endif
 protected:
   // interface to option
   EncCfg*         m_pcEncCfg;
 
   // interface to classes
   TrQuant*        m_pcTrQuant;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*     m_pcReshape;
+#endif
 
   // ME parameters
   int             m_iSearchRange;
@@ -122,6 +147,12 @@ protected:
   CtxCache*       m_CtxCache;
   DistParam       m_cDistParam;
 
+#if JVET_M0253_HASH_ME
+  RefPicList      m_currRefPicList;
+  int             m_currRefPicIndex;
+  bool            m_skipFracME;
+#endif
+
   // Misc.
   Pel            *m_pTempPel;
 
@@ -133,6 +164,14 @@ protected:
   bool            m_isInitialized;
   unsigned int    m_numBVs, m_numBV16s;
   Mv              m_acBVs[IBC_NUM_CANDIDATES];
+#if JVET_M0140_SBT
+  Distortion      m_estMinDistSbt[NUMBER_SBT_MODE + 1]; // estimated minimum SSE value of the PU if using a SBT mode
+  uint8_t         m_sbtRdoOrder[NUMBER_SBT_MODE];       // order of SBT mode in RDO
+  bool            m_skipSbtAll;                         // to skip all SBT modes for the current PU
+  uint8_t         m_histBestSbt;                        // historical best SBT mode for PU of certain SSE values
+  uint8_t         m_histBestMtsIdx;                     // historical best MTS idx  for PU of certain SSE values
+#endif
+
 public:
   InterSearch();
   virtual ~InterSearch();
@@ -148,10 +187,25 @@ public:
                                       RdCost*        pcRdCost,
                                       CABACWriter*   CABACEstimator,
                                       CtxCache*      ctxCache
+#if JVET_M0427_INLOOP_RESHAPER
+                                     , EncReshape*   m_pcReshape
+#endif
                                     );
 
   void destroy                      ();
 
+#if JVET_M0140_SBT
+  void       calcMinDistSbt         ( CodingStructure &cs, const CodingUnit& cu, const uint8_t sbtAllowed );
+  uint8_t    skipSbtByRDCost        ( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff );
+  bool       getSkipSbtAll          ()                 { return m_skipSbtAll; }
+  void       setSkipSbtAll          ( bool skipAll )   { m_skipSbtAll = skipAll; }
+  uint8_t    getSbtRdoOrder         ( uint8_t idx )    { assert( m_sbtRdoOrder[idx] < NUMBER_SBT_MODE ); assert( (uint32_t)( m_estMinDistSbt[m_sbtRdoOrder[idx]] >> 2 ) < ( MAX_UINT >> 1 ) ); return m_sbtRdoOrder[idx]; }
+  Distortion getEstDistSbt          ( uint8_t sbtMode) { return m_estMinDistSbt[sbtMode]; }
+  void       initTuAnalyzer         ()                 { m_estMinDistSbt[NUMBER_SBT_MODE] = std::numeric_limits<uint64_t>::max(); m_skipSbtAll = false; }
+  void       setHistBestTrs         ( uint8_t sbtInfo, uint8_t mtsIdx ) { m_histBestSbt = sbtInfo; m_histBestMtsIdx = mtsIdx; }
+  void       initSbtRdoOrder        ( uint8_t sbtMode ) { m_sbtRdoOrder[0] = sbtMode; m_estMinDistSbt[0] = m_estMinDistSbt[sbtMode]; }
+#endif
+
   void setTempBuffers               (CodingStructure ****pSlitCS, CodingStructure ****pFullCS, CodingStructure **pSaveCS );
   void resetCtuRecord               ()             { m_ctuRecord.clear(); }
 #if ENABLE_SPLIT_PARALLELISM
@@ -190,6 +244,10 @@ public:
       m_affMVListSize = std::min(m_affMVListSize + 1, m_affMVListMaxSize);
     }
   }
+#if JVET_M0246_AFFINE_AMVR
+  void resetSavedAffineMotion();
+  void storeAffineMotion( Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int gbiIdx );
+#endif
 protected:
 
   /// sub-function for motion vector refinement used in fractional-pel accuracy
@@ -241,9 +299,17 @@ public:
   bool  predIBCSearch           ( CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap);
   void  xIntraPatternSearch         ( PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Distortion&  ruiCost, Mv* cMvSrchRngLT, Mv* cMvSrchRngRB, Mv* pcMvPred);
   void  xSetIntraSearchRange        ( PredictionUnit& pu, int iRoiWidth, int iRoiHeight, const int localSearchRangeX, const int localSearchRangeY, Mv& rcMvSrchRngLT, Mv& rcMvSrchRngRB);
+  void  resetIbcSearch() { m_numBVs = m_numBV16s = 0; }
   void  xIBCEstimation   ( PredictionUnit& pu, PelUnitBuf& origBuf, Mv     *pcMvPred, Mv     &rcMv, Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY);
   void  xIBCSearchMVCandUpdate  ( Distortion  uiSad, int x, int y, Distortion* uiSadBestCand, Mv* cMVCand);
   int   xIBCSearchMVChromaRefine( PredictionUnit& pu, int iRoiWidth, int iRoiHeight, int cuPelX, int cuPelY, Distortion* uiSadBestCand, Mv*     cMVCand);
+#if JVET_M0253_HASH_ME
+  void addToSortList(std::list<BlockHash>& listBlockHash, std::list<int>& listCost, int cost, const BlockHash& blockHash);
+  bool predInterHashSearch(CodingUnit& cu, Partitioner& partitioner, bool& isPerfectMatch);
+  bool xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPicList, int& bestRefIndex, Mv& bestMv, Mv& bestMvd, int& bestMVPIndex, bool& isPerfectMatch);
+  int  xHashInterPredME(const PredictionUnit& pu, RefPicList currRefPicList, int currRefPicIndex, Mv bestMv[5]);
+  void selectMatchesInter(const MapIterator& itBegin, int count, std::list<BlockHash>& vecBlockHash, const BlockHash& currBlockHash);
+#endif
 protected:
 
   // -------------------------------------------------------------------------------------------------------------------
@@ -280,7 +346,9 @@ protected:
                                     RefPicList            eRefPicList,
                                     int                   iRefIdx
                                   );
-
+#if JVET_M0246_AFFINE_AMVR
+  uint32_t xCalcAffineMVBits      ( PredictionUnit& pu, Mv mvCand[3], Mv mvPred[3], bool mvHighPrec = false );
+#endif
 
   void xCopyAMVPInfo              ( AMVPInfo*   pSrc, AMVPInfo* pDst );
   uint32_t xGetMvpIdxBits             ( int iIdx, int iNum );
@@ -382,6 +450,10 @@ protected:
                                     Mv              acMv[3],
                                     uint32_t&           ruiBits,
                                     Distortion&     ruiCost,
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                    int&            mvpIdx,
+                                    const AffineAMVPInfo& aamvpi,
+#endif
                                     bool            bBi = false
                                   );
 
@@ -408,9 +480,16 @@ protected:
   void xSymmetricMotionEstimation( PredictionUnit& pu, PelUnitBuf& origBuf, Mv& rcMvCurPred, Mv& rcMvTarPred, RefPicList eRefPicList, MvField& rCurMvField, MvField& rTarMvField, Distortion& ruiCost, int gbiIdx );
 #endif
 
-  bool xReadBufferedAffineUniMv   ( PredictionUnit& pu, RefPicList eRefPicList, int32_t iRefIdx, Mv acMvPred[3], Mv acMv[3], uint32_t& ruiBits, Distortion& ruiCost);
+  bool xReadBufferedAffineUniMv   ( PredictionUnit& pu, RefPicList eRefPicList, int32_t iRefIdx, Mv acMvPred[3], Mv acMv[3], uint32_t& ruiBits, Distortion& ruiCost
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+                                    , int& mvpIdx, const AffineAMVPInfo& aamvpi
+#endif
+  );
   double xGetMEDistortionWeight   ( uint8_t gbiIdx, RefPicList eRefPicList);
   bool xReadBufferedUniMv         ( PredictionUnit& pu, RefPicList eRefPicList, int32_t iRefIdx, Mv& pcMvPred, Mv& rcMv, uint32_t& ruiBits, Distortion& ruiCost);
+
+  void xClipMv                    ( Mv& rcMv, const struct Position& pos, const struct Size& size, const class SPS& sps );
+
 public:
   void resetBufferedUniMotions    () { m_uniMotions.reset(); }
   uint32_t getWeightIdxBits       ( uint8_t gbiIdx ) { return m_estWeightIdxBits[gbiIdx]; }
@@ -433,7 +512,9 @@ protected:
 
   void xExtDIFUpSamplingH         ( CPelBuf* pcPattern );
   void xExtDIFUpSamplingQ         ( CPelBuf* pcPatternKey, Mv halfPelRef );
-
+#if JVET_M0247_AFFINE_AMVR_ENCOPT
+  uint32_t xDetermineBestMvp      ( PredictionUnit& pu, Mv acMvTemp[3], int& mvpIdx, const AffineAMVPInfo& aamvpi );
+#endif
   // -------------------------------------------------------------------------------------------------------------------
   // compute symbol bits
   // -------------------------------------------------------------------------------------------------------------------
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index ac23b0a313c1459a5601ecc27059bbc6c00ab1d0..d4cab58f9f0efe39e92d5b59fcee262e28b6c893 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -60,6 +60,9 @@ IntraSearch::IntraSearch()
   , m_pcEncCfg      (nullptr)
   , m_pcTrQuant     (nullptr)
   , m_pcRdCost      (nullptr)
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_pcReshape     (nullptr)
+#endif
   , m_CABACEstimator(nullptr)
   , m_CtxCache      (nullptr)
   , m_isInitialized (false)
@@ -149,6 +152,9 @@ void IntraSearch::destroy()
     m_pSharedPredTransformSkip[ch] = nullptr;
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU.destroy();
+#endif
   m_isInitialized = false;
 }
 
@@ -168,6 +174,9 @@ void IntraSearch::init( EncCfg*        pcEncCfg,
                         const uint32_t     maxCUWidth,
                         const uint32_t     maxCUHeight,
                         const uint32_t     maxTotalCUDepth
+#if JVET_M0427_INLOOP_RESHAPER
+                       , EncReshape*   pcReshape
+#endif
 )
 {
   CHECK(m_isInitialized, "Already initialized");
@@ -176,10 +185,16 @@ void IntraSearch::init( EncCfg*        pcEncCfg,
   m_pcRdCost                     = pcRdCost;
   m_CABACEstimator               = CABACEstimator;
   m_CtxCache                     = ctxCache;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshape                    = pcReshape;
+#endif
 
   const ChromaFormat cform = pcEncCfg->getChromaFormatIdc();
 
   IntraPrediction::init( cform, pcEncCfg->getBitDepth( CHANNEL_TYPE_LUMA ) );
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU.create(UnitArea(cform, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+#endif
 
   for( uint32_t ch = 0; ch < MAX_NUM_TBLOCKS; ch++ )
   {
@@ -261,7 +276,11 @@ void IntraSearch::init( EncCfg*        pcEncCfg,
 // INTRA PREDICTION
 //////////////////////////////////////////////////////////////////////////
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, const double bestCostSoFar )
+#else
 void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
+#endif
 {
   CodingStructure       &cs            = *cu.cs;
   const SPS             &sps           = *cs.sps;
@@ -275,7 +294,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
   //===== loop over partitions =====
 
   const TempCtx ctxStart          ( m_CtxCache, m_CABACEstimator->getCtx() );
-  const TempCtx ctxStartIntraMode ( m_CtxCache, SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA],        m_CABACEstimator->getCtx() ) );
+  const TempCtx ctxStartIntraMode(m_CtxCache, SubCtx(Ctx::IntraLumaMpmFlag, m_CABACEstimator->getCtx()));
   const TempCtx ctxStartMHIntraMode ( m_CtxCache, SubCtx( Ctx::MHIntraPredMode,        m_CABACEstimator->getCtx() ) );
   const TempCtx ctxStartMrlIdx      ( m_CtxCache, SubCtx( Ctx::MultiRefLineIdx,        m_CABACEstimator->getCtx() ) );
 
@@ -295,7 +314,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
   // 2: EMT is being checked for current CU. Stored results of DCT2 can be utilized for speedup
   uint8_t emtUsageFlag = 0;
   const int maxSizeEMT = EMT_INTRA_MAX_CU_WITH_QTBT;
-  if( width <= maxSizeEMT && height <= maxSizeEMT && sps.getSpsNext().getUseIntraEMT() )
+  if( width <= maxSizeEMT && height <= maxSizeEMT && sps.getUseIntraEMT() )
   {
     emtUsageFlag = cu.emtFlag == 1 ? 2 : 1;
   }
@@ -307,6 +326,63 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
     emtUsageFlag = 0; //this forces the recalculation of the candidates list. Why is this necessary? (to be checked)
   }
 #endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+#if JVET_M0464_UNI_MTS
+  const int width   = partitioner.currArea().lwidth();
+  const int height  = partitioner.currArea().lheight();
+  int nOptionsForISP = NUM_INTRA_SUBPARTITIONS_MODES;
+#else
+  int nOptionsForISP = cu.emtFlag == 0 ? NUM_INTRA_SUBPARTITIONS_MODES : 1;
+#endif
+  double bestCurrentCost = bestCostSoFar;
+
+  int ispOptions[NUM_INTRA_SUBPARTITIONS_MODES] = { 0 };
+  if( nOptionsForISP > 1 )
+  {
+    auto splitsThatCanBeUsedForISP = CU::canUseISPSplit( width, height, cu.cs->sps->getMaxTrSize() );
+    if( splitsThatCanBeUsedForISP == CAN_USE_VER_AND_HORL_SPLITS )
+    {
+      const CodingUnit* cuLeft  = cu.ispMode != NOT_INTRA_SUBPARTITIONS ? cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( -1, 0 ), partitioner.chType ) : nullptr;
+      const CodingUnit* cuAbove = cu.ispMode != NOT_INTRA_SUBPARTITIONS ? cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( 0, -1 ), partitioner.chType ) : nullptr;
+      bool ispHorIsFirstTest = CU::firstTestISPHorSplit( width, height, COMPONENT_Y, cuLeft, cuAbove );
+      if( ispHorIsFirstTest )
+      {
+        ispOptions[1] = HOR_INTRA_SUBPARTITIONS;
+        ispOptions[2] = VER_INTRA_SUBPARTITIONS;
+      }
+      else
+      {
+        ispOptions[1] = VER_INTRA_SUBPARTITIONS;
+        ispOptions[2] = HOR_INTRA_SUBPARTITIONS;
+      }
+    }
+    else if( splitsThatCanBeUsedForISP == HOR_INTRA_SUBPARTITIONS )
+    {
+      nOptionsForISP = 2;
+      ispOptions[1] = HOR_INTRA_SUBPARTITIONS;
+    }
+    else if( splitsThatCanBeUsedForISP == VER_INTRA_SUBPARTITIONS )
+    {
+      nOptionsForISP = 2;
+      ispOptions[1] = VER_INTRA_SUBPARTITIONS;
+    }
+    else
+    {
+      nOptionsForISP = 1;
+    }
+  }
+  if( nOptionsForISP > 1 )
+  {
+    //variables for the full RD list without MRL modes
+    m_rdModeListWithoutMrl      .clear();
+    m_rdModeListWithoutMrlHor   .clear();
+    m_rdModeListWithoutMrlVer   .clear();
+    //variables with data from regular intra used to skip ISP splits
+    m_intraModeDiagRatio        .clear();
+    m_intraModeHorVerRatio      .clear();
+    m_intraModeTestedNormalIntra.clear();
+  }
+#endif
 
   static_vector<uint32_t,   FAST_UDI_MAX_RDMODE_NUM> uiHadModeList;
   static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
@@ -344,8 +420,10 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
     {
       // this should always be true
       CHECK( !pu.Y().valid(), "PU is not valid" );
+#if ENABLE_JVET_L0283_MRL
       bool isFirstLineOfCtu = (((pu.block(COMPONENT_Y).y)&((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
       int numOfPassesExtendRef = (isFirstLineOfCtu ? 1 : MRL_NUM_REF_LINES);
+#endif
       pu.multiRefIdx = 0;
 
       //===== init pattern for luma prediction =====
@@ -363,6 +441,17 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
 
         const bool bUseHadamard = cu.transQuantBypass == 0;
 
+#if JVET_M0427_INLOOP_RESHAPER
+        if (cu.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+        {
+          CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+          PelBuf tmpOrg = m_tmpStorageLCU.getBuf(tmpArea);
+          tmpOrg.copyFrom(piOrg);
+          tmpOrg.rspSignal(m_pcReshape->getFwdLUT());
+          m_pcRdCost->setDistParam(distParam, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+        }
+        else
+#endif
         m_pcRdCost->setDistParam(distParam, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
 
         distParam.applyWeight = false;
@@ -398,7 +487,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
             uiSad += distParam.distFunc(distParam);
 
             // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
-            m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
+            m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
             m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
             m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
 
@@ -452,7 +541,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
                 Distortion sad = distParam.distFunc(distParam);
 
                 // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
-                m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
+                m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
                 m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
                 m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
 
@@ -472,6 +561,15 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
             }
           }
         }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        if( nOptionsForISP > 1 )
+        {
+          //we save the list with no mrl modes to keep only the Hadamard selected modes (no mpms)
+          m_rdModeListWithoutMrl.resize( numModesForFullRD );
+          std::copy_n( uiRdModeList.begin(), numModesForFullRD, m_rdModeListWithoutMrl.begin() );
+        }
+#endif
+#if ENABLE_JVET_L0283_MRL
         pu.multiRefIdx = 1;
         const int  numMPMs = NUM_MOST_PROBABLE_MODES;
         unsigned  multiRefMPM [numMPMs];
@@ -503,7 +601,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
               Distortion sad = distParam.distFunc(distParam);
 
               // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
-              m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
+              m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
               m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
               m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
 
@@ -514,6 +612,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
             }
           }
         }
+#endif
         CandCostList.resize(numModesForFullRD);
         extendRefList.resize(numModesForFullRD);
         if( m_pcEncCfg->getFastUDIUseMPMEnabled() )
@@ -542,6 +641,36 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
               uiRdModeList.push_back( mostProbableMode );
             }
           }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+          if( nOptionsForISP > 1 )
+          {
+            //we add the ISP MPMs to the list without mrl modes
+            m_rdModeListWithoutMrlHor = m_rdModeListWithoutMrl;
+            m_rdModeListWithoutMrlVer = m_rdModeListWithoutMrl;
+            static_vector<uint32_t, FAST_UDI_MAX_RDMODE_NUM>* listPointer;
+            for( int k = 1; k < nOptionsForISP; k++ )
+            {
+              cu.ispMode = ispOptions[k];
+              listPointer = &( cu.ispMode == HOR_INTRA_SUBPARTITIONS ? m_rdModeListWithoutMrlHor : m_rdModeListWithoutMrlVer );
+              const int numCandISP = PU::getIntraMPMs( pu, uiPreds );
+              for( int j = 0; j < numCandISP; j++ )
+              {
+                bool mostProbableModeIncluded = false;
+                int  mostProbableMode = uiPreds[j];
+
+                for( int i = 0; i < listPointer->size(); i++ )
+                {
+                  mostProbableModeIncluded |= ( mostProbableMode == listPointer->at( i ) );
+                }
+                if( !mostProbableModeIncluded )
+                {
+                  listPointer->push_back( mostProbableMode );
+                }
+              }
+            }
+            cu.ispMode = NOT_INTRA_SUBPARTITIONS;
+          }
+#endif
         }
       }
       else
@@ -594,6 +723,44 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
     }
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( nOptionsForISP > 1 ) // we remove the non-MPMs from the ISP lists
+    {
+      static_vector< uint32_t, FAST_UDI_MAX_RDMODE_NUM > uiRdModeListCopyHor = m_rdModeListWithoutMrlHor;
+      m_rdModeListWithoutMrlHor.clear();
+      static_vector< uint32_t, FAST_UDI_MAX_RDMODE_NUM > uiRdModeListCopyVer = m_rdModeListWithoutMrlVer;
+      m_rdModeListWithoutMrlVer.clear();
+      static_vector< uint32_t, FAST_UDI_MAX_RDMODE_NUM > *listPointerCopy, *listPointer;
+      for( int ispOptionIdx = 1; ispOptionIdx < nOptionsForISP; ispOptionIdx++ )
+      {
+        cu.ispMode = ispOptions[ispOptionIdx];
+        //we get the mpm cand list
+        const int numMPMs = NUM_MOST_PROBABLE_MODES;
+        unsigned  uiPreds[numMPMs];
+
+        pu.multiRefIdx = 0;
+
+        PU::getIntraMPMs( pu, uiPreds );
+
+        //we copy only the ISP MPMs
+        listPointerCopy = &( cu.ispMode == HOR_INTRA_SUBPARTITIONS ? uiRdModeListCopyHor : uiRdModeListCopyVer );
+        listPointer     = &( cu.ispMode == HOR_INTRA_SUBPARTITIONS ? m_rdModeListWithoutMrlHor : m_rdModeListWithoutMrlVer );
+        for( int k = 0; k < listPointerCopy->size(); k++ )
+        {
+          for( int q = 0; q < numMPMs; q++ )
+          {
+            if( listPointerCopy->at( k ) == uiPreds[q] )
+            {
+              listPointer->push_back( listPointerCopy->at( k ) );
+              break;
+            }
+          }
+        }
+      }
+      cu.ispMode = NOT_INTRA_SUBPARTITIONS;
+    }
+#endif
+
 
     CHECK( numModesForFullRD != uiRdModeList.size(), "Inconsistent state!" );
 
@@ -609,10 +776,26 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
       if( CandHadList.size() < 3 || CandHadList[2] > cs.interHad * PBINTRA_RATIO )
       {
         uiRdModeList.resize( std::min<size_t>( uiRdModeList.size(), 2 ) );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        extendRefList.resize( std::min<size_t>( extendRefList.size(), 2 ) ); 
+        if( nOptionsForISP > 1 )
+        {
+          m_rdModeListWithoutMrlHor.resize( std::min<size_t>( m_rdModeListWithoutMrlHor.size(), 2 ) );
+          m_rdModeListWithoutMrlVer.resize( std::min<size_t>( m_rdModeListWithoutMrlVer.size(), 2 ) );
+        }
+#endif
       }
       if( CandHadList.size() < 2 || CandHadList[1] > cs.interHad * PBINTRA_RATIO )
       {
         uiRdModeList.resize( std::min<size_t>( uiRdModeList.size(), 1 ) );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        extendRefList.resize( std::min<size_t>( extendRefList.size(), 1 ) );
+        if( nOptionsForISP > 1 )
+        {
+          m_rdModeListWithoutMrlHor.resize( std::min<size_t>( m_rdModeListWithoutMrlHor.size(), 1 ) );
+          m_rdModeListWithoutMrlVer.resize( std::min<size_t>( m_rdModeListWithoutMrlVer.size(), 1 ) );
+        }
+#endif
       }
       if( CandHadList.size() < 1 || CandHadList[0] > cs.interHad * PBINTRA_RATIO )
       {
@@ -620,7 +803,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
         cs.interHad = 0;
 
         //===== reset context models =====
-        m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
+        m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
         m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
         m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
 
@@ -642,6 +825,50 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
 
     // just to be sure
     numModesForFullRD = ( int ) uiRdModeList.size();
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    PartSplit intraSubPartitionsProcOrder = TU_NO_ISP;
+    int       bestNormalIntraModeIndex    = -1;
+    uint8_t   bestIspOption               = NOT_INTRA_SUBPARTITIONS;
+    TUIntraSubPartitioner subTuPartitioner( partitioner );
+#if !JVET_M0464_UNI_MTS
+    if ( !cu.ispMode && !cu.emtFlag )
+    {
+      m_modeCtrl->setEmtFirstPassNoIspCost( MAX_DOUBLE );
+    }
+#endif
+    for( uint32_t ispOptionIdx = 0; ispOptionIdx < nOptionsForISP; ispOptionIdx++ )
+    {
+      cu.ispMode = ispOptions[ispOptionIdx];
+      int numModesForFullRDispOption = cu.ispMode == NOT_INTRA_SUBPARTITIONS ? numModesForFullRD : cu.ispMode == HOR_INTRA_SUBPARTITIONS ? (int)m_rdModeListWithoutMrlHor.size() : (int)m_rdModeListWithoutMrlVer.size();
+      for( uint32_t uiMode = 0; uiMode < numModesForFullRDispOption; uiMode++ )
+      {
+        // set luma prediction mode
+        uint32_t uiOrgMode = cu.ispMode == NOT_INTRA_SUBPARTITIONS ? uiRdModeList[uiMode] : cu.ispMode == HOR_INTRA_SUBPARTITIONS ? m_rdModeListWithoutMrlHor[uiMode] : m_rdModeListWithoutMrlVer[uiMode];
+
+        pu.intraDir[0] = uiOrgMode;
+
+        int multiRefIdx = 0;
+        pu.multiRefIdx = multiRefIdx;
+        if( cu.ispMode )
+        {
+          intraSubPartitionsProcOrder = CU::getISPType( cu, COMPONENT_Y );
+          bool tuIsDividedInRows = CU::divideTuInRows( cu );
+          if( m_intraModeDiagRatio.at( bestNormalIntraModeIndex ) > 1.25 )
+          {
+            continue;
+          }
+          if( ( m_intraModeHorVerRatio.at( bestNormalIntraModeIndex ) > 1.25 && tuIsDividedInRows ) || ( m_intraModeHorVerRatio.at( bestNormalIntraModeIndex ) < 0.8 && !tuIsDividedInRows ) )
+          {
+            continue;
+          }
+        }
+        else
+        {
+          multiRefIdx = extendRefList[uiMode];
+          pu.multiRefIdx = multiRefIdx;
+          CHECK( pu.multiRefIdx && ( pu.intraDir[0] == DC_IDX || pu.intraDir[0] == PLANAR_IDX ), "ERL" );
+        }
+#else
     for (uint32_t uiMode = 0; uiMode < numModesForFullRD; uiMode++)
     {
       // set luma prediction mode
@@ -651,6 +878,7 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
       int multiRefIdx = extendRefList[uiMode];
       pu.multiRefIdx  = multiRefIdx;
       CHECK(pu.multiRefIdx && (pu.intraDir[0] == DC_IDX || pu.intraDir[0] == PLANAR_IDX), "ERL");
+#endif
 
 
       // set context models
@@ -659,10 +887,31 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
       // determine residual for partition
       cs.initSubStructure( *csTemp, partitioner.chType, cs.area, true );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( cu.ispMode )
+      {
+        xRecurIntraCodingLumaQT( *csTemp, subTuPartitioner, bestCurrentCost, 0, intraSubPartitionsProcOrder );
+      }
+      else
+      {
+        xRecurIntraCodingLumaQT( *csTemp, partitioner, MAX_DOUBLE, -1 );
+      }
+
+      if( cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMPONENT_Y] )
+      {
+        csTemp->cost = MAX_DOUBLE;
+      }
+#else
       xRecurIntraCodingLumaQT( *csTemp, partitioner );
+#endif
+
 
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if (emtUsageFlag == 1 && m_pcEncCfg->getFastIntraEMT() && !cu.ispMode)
+#else
       if( emtUsageFlag == 1 && m_pcEncCfg->getFastIntraEMT() )
+#endif
       {
         m_modeCostStore[puIndex][uiMode] = csTemp->cost; //cs.cost;
       }
@@ -677,19 +926,49 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
 
         uiBestPUMode  = uiOrgMode;
         bestExtendRef = multiRefIdx;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        bestIspOption = cu.ispMode;
+#endif
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        if (emtUsageFlag == 1 && m_pcEncCfg->getFastIntraEMT() && !cu.ispMode)
+#else
         if( ( emtUsageFlag == 1 ) && m_pcEncCfg->getFastIntraEMT() )
+#endif
         {
           m_bestModeCostStore[puIndex] = csBest->cost; //cs.cost;
         }
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        if( csBest->cost < bestCurrentCost )
+        {
+          bestCurrentCost = csBest->cost;
+        }
+        if( !cu.ispMode )
+        {
+          bestNormalIntraModeIndex = uiMode;
+        }
 #endif
       }
 
       csTemp->releaseIntermediateData();
     } // Mode loop
+#if JVET_M0102_INTRA_SUBPARTITIONS
+#if !JVET_M0464_UNI_MTS
+    if (!cu.ispMode && !cu.emtFlag)
+    {
+      m_modeCtrl->setEmtFirstPassNoIspCost(csBest->cost);
+    }
+#endif
+    }
+    cu.ispMode = bestIspOption;
+#endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+    cs.useSubStructure(*csBest, partitioner.chType, pu.singleChan(CHANNEL_TYPE_LUMA), true, true, keepResi, keepResi);
+#else
     cs.useSubStructure( *csBest, partitioner.chType, pu.singleChan( CHANNEL_TYPE_LUMA ), KEEP_PRED_AND_RESI_SIGNALS, true, keepResi, keepResi );
-
+#endif
     csBest->releaseIntermediateData();
     //=== update PU data ====
     pu.intraDir[0] = uiBestPUMode;
@@ -700,7 +979,11 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
   m_CABACEstimator->getCtx() = ctxStart;
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner, const double maxCostAllowed )
+#else
 void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
+#endif
 {
   const ChromaFormat format   = cu.chromaFormat;
   const uint32_t    numberValidComponents = getNumberValidComponents(format);
@@ -709,6 +992,13 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
 
   cs.setDecomp( cs.area.Cb(), false );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  double    bestCostSoFar = maxCostAllowed;
+  bool      lumaUsesISP   = !CS::isDualITree( *cu.cs ) && cu.ispMode;
+  PartSplit ispType       = lumaUsesISP ? CU::getISPType( cu, COMPONENT_Y ) : TU_NO_ISP;
+  CHECK( cu.ispMode && bestCostSoFar < 0, "bestCostSoFar must be positive!" );
+#endif
+
   auto &pu = *cu.firstPU;
 
   {
@@ -732,6 +1022,14 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
       saveCS.area.repositionTo( cs.area );
       saveCS.clearTUs();
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( !CS::isDualITree( cs ) && cu.ispMode )
+      {
+        saveCS.clearCUs();
+        saveCS.clearPUs();
+      }
+#endif
+
       if( CS::isDualITree( cs ) )
       {
         if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
@@ -751,17 +1049,37 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
 
       std::vector<TransformUnit*> orgTUs;
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( lumaUsesISP )
+      {
+        CodingUnit& auxCU = saveCS.addCU( cu, partitioner.chType );
+        auxCU.ispMode = cu.ispMode;
+        saveCS.sps = cu.cs->sps;
+        saveCS.addPU( *cu.firstPU, partitioner.chType );
+      }
+#endif
+
 
       // create a store for the TUs
       for( const auto &ptu : cs.tus )
       {
         // for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        if( lumaUsesISP || pu.contains( *ptu, CHANNEL_TYPE_CHROMA ) )
+#else
         if( pu.contains( *ptu, CHANNEL_TYPE_CHROMA ) )
+#endif
         {
           saveCS.addTU( *ptu, partitioner.chType );
           orgTUs.push_back( ptu );
         }
       }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( lumaUsesISP )
+      {
+        saveCS.clearCUs();
+      }
+#endif
       // SATD pre-selecting.
       int satdModeList[NUM_CHROMA_MODE];
       int64_t satdSortedCost[NUM_CHROMA_MODE];
@@ -885,20 +1203,38 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
         //----- chroma coding -----
         pu.intraDir[1] = chromaIntraMode;
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
+        if( lumaUsesISP && cs.dist == MAX_UINT )
+        {
+          continue;
+        }
+#else
         xRecurIntraChromaCodingQT( cs, partitioner );
+#endif
 
         if (cs.pps->getUseTransformSkip())
         {
           m_CABACEstimator->getCtx() = ctxStart;
         }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false, true, -1, ispType );
+#else
         uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false, true );
+#endif
         Distortion uiDist = cs.dist;
         double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
 
         //----- compare -----
         if( dCost < dBestCost )
         {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+          if( lumaUsesISP && dCost < bestCostSoFar )
+          {
+            bestCostSoFar = dCost;
+          }
+#endif
           for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
           {
             const CompArea &area = pu.blocks[i];
@@ -907,6 +1243,10 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
 #if KEEP_PRED_AND_RESI_SIGNALS
             saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
             saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+            saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
+            cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
 #endif
             cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
 
@@ -931,6 +1271,11 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
         cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
         cs.getResiBuf         ( area ).copyFrom( saveCS.getResiBuf( area ) );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+        cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
+        cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf    ( area ) );
+#endif
+
         cs.picture->getRecoBuf( area ).copyFrom( cs.    getRecoBuf( area ) );
 
         for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
@@ -946,6 +1291,12 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
 
   //----- restore context models -----
   m_CABACEstimator->getCtx() = ctxStart;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( lumaUsesISP && bestCostSoFar >= maxCostAllowed )
+  {
+    cu.ispMode = 0;
+  }
+#endif
 }
 
 void IntraSearch::IPCMSearch(CodingStructure &cs, Partitioner& partitioner)
@@ -967,6 +1318,9 @@ void IntraSearch::IPCMSearch(CodingStructure &cs, Partitioner& partitioner)
   cs.cost     = 0;
 
   cs.setDecomp(cs.area);
+#if JVET_M0427_INLOOP_RESHAPER
+  cs.picture->getPredBuf(cs.area).copyFrom(cs.getPredBuf());
+#endif
 }
 
 void IntraSearch::xEncPCM(CodingStructure &cs, Partitioner& partitioner, const ComponentID &compID)
@@ -1001,18 +1355,30 @@ void IntraSearch::xEncPCM(CodingStructure &cs, Partitioner& partitioner, const C
 // Intra search
 // -------------------------------------------------------------------------------------------------------------------
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::xEncIntraHeader( CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma, const int subTuIdx )
+#else
 void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma)
+#endif
 {
   CodingUnit &cu = *cs.getCU( partitioner.chType );
 
   if (bLuma)
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    bool isFirst = cu.ispMode ? subTuIdx == 0 : partitioner.currArea().lumaPos() == cs.area.lumaPos();
+#else
     bool isFirst = partitioner.currArea().lumaPos() == cs.area.lumaPos();
+#endif
 
     // CU header
     if( isFirst )
     {
-      if( !cs.slice->isIntra() 
+#if JVET_M0483_IBC
+      if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag())
+#else
+      if( !cs.slice->isIntra()
+#endif
         && cu.Y().valid()
         )
       {
@@ -1024,6 +1390,9 @@ void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner,
         m_CABACEstimator->pred_mode   ( cu );
       }
       m_CABACEstimator->extend_ref_line(cu);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      m_CABACEstimator->isp_mode      ( cu );
+#endif
       if( CU::isIntra(cu) )
       {
         m_CABACEstimator->pcm_data( cu, partitioner );
@@ -1058,16 +1427,29 @@ void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner,
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma, const int subTuIdx, const PartSplit ispType )
+{
+  const UnitArea &currArea = partitioner.currArea();
+          int subTuCounter = subTuIdx;
+  TransformUnit &currTU = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter );
+  CodingUnit    &currCU = *currTU.cu;
+#else
 void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma)
 {
   const UnitArea &currArea = partitioner.currArea();
   TransformUnit &currTU    = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType );
 #if !JVET_M0464_UNI_MTS
   CodingUnit &currCU       = *currTU.cu;
+#endif
 #endif
   uint32_t currDepth           = partitioner.currTrDepth;
 
   const bool subdiv        = currTU.depth > currDepth;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  ComponentID compID = partitioner.chType == CHANNEL_TYPE_LUMA ? COMPONENT_Y : COMPONENT_Cb;
+  const bool chromaCbfISP = currArea.blocks[COMPONENT_Cb].valid() && currCU.ispMode && !subdiv;
+#endif
 
   if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
   {
@@ -1075,21 +1457,39 @@ void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner,
   }
   else
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    CHECK( subdiv && !currCU.ispMode && isLuma( compID ), "No TU subdivision is allowed with QTBT" );
+  }
+
+  if( bChroma && ( !currCU.ispMode || chromaCbfISP ) )
+#else
     CHECK( subdiv, "No TU subdivision is allowed with QTBT" );
   }
 
   if (bChroma)
+#endif
   {
     const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    const uint32_t cbfDepth = ( chromaCbfISP ? currDepth - 1 : currDepth );
+#endif
 
     for (uint32_t ch = COMPONENT_Cb; ch < numberValidComponents; ch++)
     {
       const ComponentID compID = ComponentID(ch);
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( currDepth == 0 || TU::getCbfAtDepth( currTU, compID, currDepth - 1 ) || chromaCbfISP )
+#else
       if( currDepth == 0 || TU::getCbfAtDepth( currTU, compID, currDepth - 1 ) )
+#endif
       {
         const bool prevCbf = ( compID == COMPONENT_Cr ? TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth ) : false );
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, compID, currDepth ), currArea.blocks[compID], cbfDepth, prevCbf );
+#else
         m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, compID, currDepth ), currArea.blocks[compID], currDepth, prevCbf );
+#endif
 
       }
     }
@@ -1098,19 +1498,34 @@ void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner,
   if (subdiv)
   {
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if (!currCU.ispMode && isLuma( compID ) && currDepth == 0 && bLuma) m_CABACEstimator->emt_cu_flag( currCU );
+#else
     if( currDepth == 0 && bLuma ) m_CABACEstimator->emt_cu_flag( currCU );
+#endif
 #endif
 
     if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
     {
       partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    else if( currCU.ispMode && isLuma( compID ) )
+    {
+      partitioner.splitCurrArea( ispType, cs );
+    }
+#endif
     else
     THROW( "Cannot perform an implicit split!" );
 
     do
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma, subTuCounter, ispType );
+      subTuCounter += subTuCounter != -1 ? 1 : 0;
+#else
       xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma );
+#endif
     } while( partitioner.nextPart( cs ) );
 
     partitioner.exitCurrSplit();
@@ -1118,20 +1533,65 @@ void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner,
   else
   {
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if (!currCU.ispMode && isLuma( compID ) && currDepth == 0 && bLuma && TU::getCbfAtDepth( currTU, COMPONENT_Y, 0) ) m_CABACEstimator->emt_cu_flag( currCU );
+#else
     if( currDepth == 0 && bLuma && TU::getCbfAtDepth( currTU, COMPONENT_Y, 0 ) ) m_CABACEstimator->emt_cu_flag( currCU );
+#endif
 #endif
     //===== Cbfs =====
     if (bLuma)
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      bool previousCbf       = false;
+      bool lastCbfIsInferred = false;
+      if( ispType != TU_NO_ISP )
+      {
+        bool rootCbfSoFar = false;
+        uint32_t nTus = currCU.ispMode == HOR_INTRA_SUBPARTITIONS ? currCU.lheight() >> g_aucLog2[currTU.lheight()] : currCU.lwidth() >> g_aucLog2[currTU.lwidth()];
+        if( subTuCounter == nTus - 1 )
+        {
+          TransformUnit* tuPointer = currCU.firstTU;
+          for( int tuIdx = 0; tuIdx < nTus - 1; tuIdx++ )
+          {
+            rootCbfSoFar |= TU::getCbfAtDepth( *tuPointer, COMPONENT_Y, currDepth );
+            tuPointer = tuPointer->next;
+          }
+          if( !rootCbfSoFar )
+          {
+            lastCbfIsInferred = true;
+          }
+        }
+        if( !lastCbfIsInferred )
+        {
+          previousCbf = TU::getPrevTuCbfAtDepth( currTU, COMPONENT_Y, partitioner.currTrDepth );
+        }
+      }
+      if( !lastCbfIsInferred )
+      {
+        m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currTU.Y(), currTU.depth, previousCbf, currCU.ispMode );
+      }
+#else
       m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currTU.Y(), currTU.depth );
+#endif
     }
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::xEncCoeffQT( CodingStructure &cs, Partitioner &partitioner, const ComponentID compID, const int subTuIdx, const PartSplit ispType )
+#else
 void IntraSearch::xEncCoeffQT(CodingStructure &cs, Partitioner &partitioner, const ComponentID &compID)
+#endif
 {
   const UnitArea &currArea  = partitioner.currArea();
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+       int subTuCounter     = subTuIdx;
+  TransformUnit &currTU     = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType, subTuIdx );
+#else
   TransformUnit &currTU     = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType );
+#endif
   uint32_t      currDepth       = partitioner.currTrDepth;
   const bool subdiv         = currTU.depth > currDepth;
 
@@ -1141,12 +1601,23 @@ void IntraSearch::xEncCoeffQT(CodingStructure &cs, Partitioner &partitioner, con
     {
       partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    else if( currTU.cu->ispMode )
+    {
+      partitioner.splitCurrArea( ispType, cs );
+    }
+#endif
     else
       THROW("Implicit TU split not available!");
 
     do
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      xEncCoeffQT( cs, partitioner, compID, subTuCounter, ispType );
+      subTuCounter += subTuCounter != -1 ? 1 : 0;
+#else
       xEncCoeffQT( cs, partitioner, compID );
+#endif
     } while( partitioner.nextPart( cs ) );
 
     partitioner.exitCurrSplit();
@@ -1166,27 +1637,80 @@ void IntraSearch::xEncCoeffQT(CodingStructure &cs, Partitioner &partitioner, con
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma, const int subTuIdx, const PartSplit ispType )
+#else
 uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma )
+#endif
 {
   m_CABACEstimator->resetBits();
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  xEncIntraHeader( cs, partitioner, bLuma, bChroma, subTuIdx );
+  xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma, subTuIdx, ispType );
+#else
   xEncIntraHeader( cs, partitioner, bLuma, bChroma );
   xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma );
+#endif
+
 
   if( bLuma )
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    xEncCoeffQT( cs, partitioner, COMPONENT_Y, subTuIdx, ispType );
+#else
     xEncCoeffQT( cs, partitioner, COMPONENT_Y );
+#endif
   }
   if( bChroma )
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    xEncCoeffQT( cs, partitioner, COMPONENT_Cb, subTuIdx, ispType );
+    xEncCoeffQT( cs, partitioner, COMPONENT_Cr, subTuIdx, ispType );
+#else
     xEncCoeffQT( cs, partitioner, COMPONENT_Cb );
     xEncCoeffQT( cs, partitioner, COMPONENT_Cr );
+#endif
   }
 
   uint64_t fracBits = m_CABACEstimator->getEstFracBits();
   return fracBits;
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+uint64_t IntraSearch::xGetIntraFracBitsQTSingleChromaComponent( CodingStructure &cs, Partitioner &partitioner, const ComponentID compID )
+{
+  m_CABACEstimator->resetBits();
+
+  if( compID == COMPONENT_Cb )
+  {
+    //intra mode coding
+    PredictionUnit &pu = *cs.getPU( partitioner.currArea().lumaPos(), partitioner.chType );
+    m_CABACEstimator->intra_chroma_pred_mode( pu );
+    //xEncIntraHeader(cs, partitioner, false, true);
+  }
+  CHECK( partitioner.currTrDepth != 1, "error in the depth!" );
+  const UnitArea &currArea = partitioner.currArea();
+
+  TransformUnit &currTU = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType );
+
+  //cbf coding
+  m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, compID, partitioner.currTrDepth ), currArea.blocks[compID], partitioner.currTrDepth - 1 );
+  //coeffs coding and cross comp coding
+  if( TU::hasCrossCompPredInfo( currTU, compID ) )
+  {
+    m_CABACEstimator->cross_comp_pred( currTU, compID );
+  }
+  if( TU::getCbf( currTU, compID ) )
+  {
+    m_CABACEstimator->residual_coding( currTU, compID );
+  }
+
+  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
+  return fracBits;
+}
+#endif
+
 uint64_t IntraSearch::xGetIntraFracBitsQTChroma(TransformUnit& currTU, const ComponentID &compID)
 {
   m_CABACEstimator->resetBits();
@@ -1235,6 +1759,9 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
 
   const bool           bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction;
   const bool           ccUseRecoResi        = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const bool           ispSplitIsAllowed    = CU::canUseISPSplit( *tu.cu, compID );
+#endif
 
 
   //===== init availability pattern =====
@@ -1274,8 +1801,37 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), uiChFinalMode );
   //DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+#if JVET_M0483_IBC
+  bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()));
+#else
+  bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()) || (slice.getSliceType() == P_SLICE && slice.getSPS()->getIBCMode()));
+#endif
+  if (flag && slice.getReshapeInfo().getSliceReshapeChromaAdj() && isChroma(compID))
+  {
+    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
+    const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area );
+    PelBuf piPredY;
+    piPredY = cs.picture->getPredBuf(areaY);
+    const Pel avgLuma = piPredY.computeAvg();
+    int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+    tu.setChromaAdj(adj);
+  }
+#endif
   //===== get residual signal =====
   piResi.copyFrom( piOrg  );
+#if JVET_M0427_INLOOP_RESHAPER
+  if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID==COMPONENT_Y)
+  {
+    CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+    PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+    tmpPred.copyFrom(piPred);
+    piResi.rspSignal(m_pcReshape->getFwdLUT());
+    piResi.subtract(tmpPred);
+  }
+  else
+#endif
   piResi.subtract( piPred );
 
   if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isLuma(compID))
@@ -1303,16 +1859,57 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   m_pcTrQuant->selectLambda(compID);
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  flag =flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
+  if (flag && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
+  {
+    int cResScaleInv = tu.getChromaAdj();
+    double cResScale = round((double)(1 << CSCALE_FP_PREC) / (double)cResScaleInv);
+    m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cResScale*cResScale));
+    piResi.scaleSignal(cResScaleInv, 1, tu.cu->cs->slice->clpRng(compID));
+  }
+#endif
+
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  double diagRatio = 0, horVerRatio = 0;
+#endif
+
 #if JVET_M0464_UNI_MTS
   if( trModes )
   {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    m_pcTrQuant->transformNxN( tu, compID, cQP, trModes, CU::isIntra( *tu.cu ) ? m_pcEncCfg->getIntraMTSMaxCand() : m_pcEncCfg->getInterMTSMaxCand(), ispSplitIsAllowed ? &diagRatio : nullptr, ispSplitIsAllowed ? &horVerRatio : nullptr );
+#else
     m_pcTrQuant->transformNxN( tu, compID, cQP, trModes, CU::isIntra( *tu.cu ) ? m_pcEncCfg->getIntraMTSMaxCand() : m_pcEncCfg->getInterMTSMaxCand() );
+#endif
     tu.mtsIdx = trModes->at(0).first;
   }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  m_pcTrQuant->transformNxN( tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr, &diagRatio, &horVerRatio );
+#else
   m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
+#endif
+#else
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), ispSplitIsAllowed ? &diagRatio : nullptr, ispSplitIsAllowed ? &horVerRatio : nullptr);
 #else
   m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx());
 #endif
+#endif
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if (!tu.cu->ispMode && isLuma(compID) && ispSplitIsAllowed &&
+#if JVET_M0464_UNI_MTS
+    tu.mtsIdx == 0
+#else
+    !tu.cu->emtFlag
+#endif
+    )
+  {
+    m_intraModeDiagRatio        .push_back(diagRatio);
+    m_intraModeHorVerRatio      .push_back(horVerRatio);
+    m_intraModeTestedNormalIntra.push_back((int)uiChFinalMode);
+  }
+#endif
 
 
   DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), compID, uiAbsSum );
@@ -1329,19 +1926,51 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  if (flag && uiAbsSum > 0 && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
+  {
+    piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
+  }
+#endif
   if (bUseCrossCPrediction)
   {
     CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, true);
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y)
+  {
+    CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0,0), area.size());
+    PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+    tmpPred.copyFrom(piPred);
+    piReco.reconstruct(tmpPred, piResi, cs.slice->clpRng(compID));
+  }
+  else
+#endif
   piReco.reconstruct(piPred, piResi, cs.slice->clpRng( compID ));
 
   //===== update distortion =====
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getReshaper()
+    && slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
+#else
   if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
   {
     const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
-    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma );
+#if JVET_M0427_INLOOP_RESHAPER
+    if (compID == COMPONENT_Y  && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
+    {
+      CompArea      tmpArea1(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+      PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+      tmpRecLuma.copyFrom(piReco);
+      tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+      ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+    }
+    else
+#endif
+      ruiDist += m_pcRdCost->getDistPart(piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma);
   }
   else
 #endif
@@ -1350,11 +1979,20 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &partitioner, const double bestCostSoFar, const int subTuIdx, const PartSplit ispType )
+{
+        int   subTuCounter = subTuIdx;
+  const UnitArea &currArea = partitioner.currArea();
+  const CodingUnit     &cu = *cs.getCU( currArea.lumaPos(), partitioner.chType );
+        bool  earlySkipISP = false;
+#else
 void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &partitioner )
 {
   const UnitArea &currArea = partitioner.currArea();
 #if !JVET_M0464_UNI_MTS
   const CodingUnit &cu     = *cs.getCU(currArea.lumaPos(), partitioner.chType);
+#endif
 #endif
   uint32_t currDepth       = partitioner.currTrDepth;
   const PPS &pps           = *cs.pps;
@@ -1364,6 +2002,13 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
   bCheckFull               = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
   bCheckSplit              = partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  if( cu.ispMode )
+  {
+    bCheckSplit = partitioner.canSplit( ispType, cs );
+    bCheckFull = !bCheckSplit;
+  }
+#endif
   uint32_t    numSig           = 0;
 
 #if JVET_M0464_UNI_MTS
@@ -1430,6 +2075,9 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
     checkTransformSkip &= TU::hasTransformSkipFlag( *tu.cs, tu.Y() );
     checkTransformSkip &= !cu.transQuantBypass;
     checkTransformSkip &= !cu.emtFlag;
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    checkTransformSkip &= !cu.ispMode;
+#endif
 
     CHECK( !tu.Y().valid(), "Invalid TU" );
 
@@ -1530,6 +2178,12 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       {
         default0Save1Load2 = 2;
       }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( cu.ispMode )
+      {
+        default0Save1Load2 = 0;
+      }
+#endif
 #if JVET_M0464_UNI_MTS
       if( nNumTransformCands > 1 )
       {
@@ -1579,7 +2233,18 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       }
       else
       {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+        if( cu.ispMode && m_pcRdCost->calcRdCost( csFull->fracBits, csFull->dist + singleDistTmpLuma ) > bestCostSoFar )
+        {
+          earlySkipISP = true;
+        }
+        else
+        {
+          singleTmpFracBits = xGetIntraFracBitsQT( *csFull, partitioner, true, false, subTuCounter, ispType );
+        }
+#else
         singleTmpFracBits = xGetIntraFracBitsQT( *csFull, partitioner, true, false );
+#endif
         singleCostTmp     = m_pcRdCost->calcRdCost( singleTmpFracBits, singleDistTmpLuma );
       }
 
@@ -1602,7 +2267,7 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
 
         if( bestModeId[COMPONENT_Y] != lastCheckId )
         {
-#if KEEP_PRED_AND_RESI_SIGNALS
+#if KEEP_PRED_AND_RESI_SIGNALS || JVET_M0427_INLOOP_RESHAPER
           saveCS.getPredBuf( tu.Y() ).copyFrom( csFull->getPredBuf( tu.Y() ) );
 #endif
           saveCS.getRecoBuf( tu.Y() ).copyFrom( csFull->getRecoBuf( tu.Y() ) );
@@ -1622,7 +2287,7 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
 
     if( bestModeId[COMPONENT_Y] != lastCheckId )
     {
-#if KEEP_PRED_AND_RESI_SIGNALS
+#if KEEP_PRED_AND_RESI_SIGNALS || JVET_M0427_INLOOP_RESHAPER
       csFull->getPredBuf( tu.Y() ).copyFrom( saveCS.getPredBuf( tu.Y() ) );
 #endif
       csFull->getRecoBuf( tu.Y() ).copyFrom( saveCS.getRecoBuf( tu.Y() ) );
@@ -1667,13 +2332,62 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
     }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( cu.ispMode )
+    {
+      partitioner.splitCurrArea( ispType, *csSplit );
+    }
+#endif
     do
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      xRecurIntraCodingLumaQT( *csSplit, partitioner, bestCostSoFar, subTuCounter, ispType );
+      subTuCounter += subTuCounter != -1 ? 1 : 0;
+#else
       xRecurIntraCodingLumaQT( *csSplit, partitioner );
+#endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( !cu.ispMode )
+      {
+        csSplit->setDecomp( partitioner.currArea().Y() );
+      }
+      else if( CU::isISPFirst( cu, partitioner.currArea().Y(), COMPONENT_Y ) )
+      {
+        csSplit->setDecomp( cu.Y() );
+      }
+#else
       csSplit->setDecomp( partitioner.currArea().Y() );
+#endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      uiSplitCbfLuma |= TU::getCbfAtDepth( *csSplit->getTU( partitioner.currArea().lumaPos(), partitioner.chType, subTuCounter - 1 ), COMPONENT_Y, partitioner.currTrDepth );
+      if( cu.ispMode )
+      {
+        //exit condition if the accumulated cost is already larger than the best cost so far (no impact in RD performance)
+        if( csSplit->cost > bestCostSoFar )
+        {
+          earlySkipISP    = true;
+          splitIsSelected = false;
+          break;
+        }
+        else
+        {
+          //more restrictive exit condition
+          bool tuIsDividedInRows = CU::divideTuInRows( cu );
+          int nSubPartitions = tuIsDividedInRows ? cu.lheight() >> g_aucLog2[cu.firstTU->lheight()] : cu.lwidth() >> g_aucLog2[cu.firstTU->lwidth()];
+          double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
+          if( subTuCounter < nSubPartitions && csSplit->cost > bestCostSoFar*threshold )
+          {
+            earlySkipISP    = true;
+            splitIsSelected = false;
+            break;
+          }
+        }
+      }
+#else
       uiSplitCbfLuma |= TU::getCbfAtDepth( *csSplit->getTU( partitioner.currArea().lumaPos(), partitioner.chType ), COMPONENT_Y, partitioner.currTrDepth );
+#endif
 
 
 
@@ -1695,7 +2409,11 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       m_CABACEstimator->getCtx() = ctxStart;
 
       //----- determine rate and r-d cost -----
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      csSplit->fracBits = xGetIntraFracBitsQT( *csSplit, partitioner, true, false, cu.ispMode ? 0 : -1, ispType );
+#else
       csSplit->fracBits = xGetIntraFracBitsQT(*csSplit, partitioner, true, false);
+#endif
 
       //--- update cost ---
       csSplit->cost     = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
@@ -1707,25 +2425,50 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
     {
       // otherwise this would've happened in useSubStructure
       cs.picture->getRecoBuf( currArea.Y() ).copyFrom( cs.getRecoBuf( currArea.Y() ) );
+#if JVET_M0427_INLOOP_RESHAPER
+      cs.picture->getPredBuf( currArea.Y() ).copyFrom( cs.getPredBuf( currArea.Y() ) );
+#endif
     }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( cu.ispMode && earlySkipISP )
+    {
+      cs.cost = MAX_DOUBLE;
+    }
+    else
+    {
+      cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
+    }
+#else
     cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
+#endif
   }
 }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitioner& partitioner, const double bestCostSoFar, const PartSplit ispType )
+#else
 ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partitioner& partitioner)
+#endif
 {
   UnitArea currArea                   = partitioner.currArea();
-  const bool keepResi                 = cs.sps->getSpsNext().getUseLMChroma() || KEEP_PRED_AND_RESI_SIGNALS;
+  const bool keepResi                 = cs.sps->getUseLMChroma() || KEEP_PRED_AND_RESI_SIGNALS;
   if( !currArea.Cb().valid() ) return ChromaCbfs( false );
 
 
   TransformUnit &currTU               = *cs.getTU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
   const PredictionUnit &pu            = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
 #if !JVET_M0464_UNI_MTS
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  const TransformUnit &currTULuma     = CS::isDualITree( cs ) ? *cs.picture->cs->getTU(currArea.lumaPos(), CHANNEL_TYPE_LUMA, 0 ) : currTU;
+#else
   const TransformUnit &currTULuma     = CS::isDualITree( cs ) ? *cs.picture->cs->getTU( currArea.lumaPos(), CHANNEL_TYPE_LUMA ) : currTU;
 #endif
+#endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  bool lumaUsesISP                    = !CS::isDualITree( cs ) && currTU.cu->ispMode;
+#endif
   uint32_t     currDepth                  = partitioner.currTrDepth;
   const PPS &pps                      = *cs.pps;
   ChromaCbfs cbfs                     ( false );
@@ -1767,6 +2510,18 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
     saveCS.area.repositionTo( cs.area );
     saveCS.initStructData( MAX_INT, false, true );
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( !CS::isDualITree( cs ) && currTU.cu->ispMode )
+    {
+      saveCS.clearCUs();
+      CodingUnit& auxCU = saveCS.addCU( *currTU.cu, partitioner.chType );
+      auxCU.ispMode = currTU.cu->ispMode;
+      saveCS.sps = currTU.cs->sps;
+      saveCS.clearPUs();
+      saveCS.addPU( *currTU.cu->firstPU, partitioner.chType );
+    }
+#endif
+
     TransformUnit &tmpTU = saveCS.addTU(currArea, partitioner.chType);
 
 
@@ -1857,6 +2612,17 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
           {
             singleCostTmp = MAX_DOUBLE;
           }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+          else if( lumaUsesISP && bestCostSoFar != MAX_DOUBLE && c == COMPONENT_Cb )
+          {
+            uint64_t fracBitsTmp = xGetIntraFracBitsQTSingleChromaComponent( cs, partitioner, ComponentID( c ) );
+            singleCostTmp = m_pcRdCost->calcRdCost( fracBitsTmp, singleDistCTmp );
+            if( isOneMode || ( !isOneMode && !isLastMode ) )
+            {
+              m_CABACEstimator->getCtx() = ctxStart;
+            }
+          }
+#endif
           else if( !isOneMode )
           {
             uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma( currTU, compID );
@@ -1874,6 +2640,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
 #if KEEP_PRED_AND_RESI_SIGNALS
               saveCS.getPredBuf   (area).copyFrom(cs.getPredBuf   (area));
               saveCS.getOrgResiBuf(area).copyFrom(cs.getOrgResiBuf(area));
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+              saveCS.getPredBuf   (area).copyFrom(cs.getPredBuf   (area));
 #endif
               if( keepResi )
               {
@@ -1889,11 +2658,25 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
         }
       }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( lumaUsesISP && dSingleCost > bestCostSoFar && c == COMPONENT_Cb )
+      {
+        //Luma + Cb cost is already larger than the best cost, so we don't need to test Cr
+        cs.dist = MAX_UINT;
+        m_CABACEstimator->getCtx() = ctxStart;
+        break;
+        //return cbfs;
+      }
+#endif
+
       if (bestModeId < totalModesToTest)
       {
 #if KEEP_PRED_AND_RESI_SIGNALS
         cs.getPredBuf   (area).copyFrom(saveCS.getPredBuf   (area));
         cs.getOrgResiBuf(area).copyFrom(saveCS.getOrgResiBuf(area));
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+        cs.getPredBuf   (area).copyFrom(saveCS.getPredBuf   (area));
 #endif
         if( keepResi )
         {
@@ -1906,6 +2689,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
         m_CABACEstimator->getCtx() = ctxBest;
       }
 
+#if JVET_M0427_INLOOP_RESHAPER
+      cs.picture->getPredBuf(area).copyFrom(cs.getPredBuf(area));
+#endif
       cs.picture->getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
 
       cbfs.cbf(compID) = TU::getCbf(currTU, compID);
@@ -1922,12 +2708,22 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
     {
       partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
     }
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    else if( currTU.cu->ispMode )
+    {
+      partitioner.splitCurrArea( ispType, cs );
+    }
+#endif
     else
       THROW( "Implicit TU split not available" );
 
     do
     {
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      ChromaCbfs subCbfs = xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
+#else
       ChromaCbfs subCbfs = xRecurIntraChromaCodingQT( cs, partitioner );
+#endif
 
       for( uint32_t ch = COMPONENT_Cb; ch < numValidTBlocks; ch++ )
       {
@@ -1938,11 +2734,30 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
 
     partitioner.exitCurrSplit();
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+    if( lumaUsesISP && cs.dist == MAX_UINT )
+    {
+      return cbfs;
+    }
+#endif
     {
 
       cbfs.Cb |= SplitCbfs.Cb;
       cbfs.Cr |= SplitCbfs.Cr;
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+      if( !lumaUsesISP )
+      {
+        for( auto &ptu : cs.tus )
+        {
+          if( currArea.Cb().contains( ptu->Cb() ) || ( !ptu->Cb().valid() && currArea.Y().contains( ptu->Y() ) ) )
+          {
+            TU::setCbfAtDepth( *ptu, COMPONENT_Cb, currDepth, SplitCbfs.Cb );
+            TU::setCbfAtDepth( *ptu, COMPONENT_Cr, currDepth, SplitCbfs.Cr );
+          }
+        }
+      }
+#else
       for( auto &ptu : cs.tus )
       {
         if( currArea.Cb().contains( ptu->Cb() ) || ( !ptu->Cb().valid() && currArea.Y().contains( ptu->Y() ) ) )
@@ -1951,6 +2766,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
           TU::setCbfAtDepth( *ptu, COMPONENT_Cr, currDepth, SplitCbfs.Cr );
         }
       }
+#endif
     }
   }
 
diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h
index 3c1ce2b8137592b7a868bf67ed1d2ee70c9b9003..1879d06c794c87a4c8b36d7a9fee1526e61702bb 100644
--- a/source/Lib/EncoderLib/IntraSearch.h
+++ b/source/Lib/EncoderLib/IntraSearch.h
@@ -48,6 +48,9 @@
 #include "CommonLib/TrQuant.h"
 #include "CommonLib/Unit.h"
 #include "CommonLib/RdCost.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 
 //! \ingroup EncoderLib
 //! \{
@@ -62,6 +65,9 @@ class EncModeCtrl;
 class IntraSearch : public IntraPrediction, CrossComponentPrediction
 {
 private:
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  EncModeCtrl    *m_modeCtrl;
+#endif
   Pel*            m_pSharedPredTransformSkip[MAX_NUM_TBLOCKS];
 
   XUCache         m_unitCache;
@@ -81,7 +87,18 @@ private:
   uint32_t   m_savedRdModeList  [4][NUM_LUMA_MODE], m_savedNumRdModes[4];
   int        m_savedExtendRefList[4][NUM_LUMA_MODE];
 #endif
-
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  static_vector<uint32_t, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrl;
+  static_vector<uint32_t, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrlHor;
+  static_vector<uint32_t, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrlVer;
+
+  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> m_intraModeDiagRatio;
+  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> m_intraModeHorVerRatio;
+  static_vector<int,    FAST_UDI_MAX_RDMODE_NUM> m_intraModeTestedNormalIntra;
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  PelStorage      m_tmpStorageLCU;
+#endif
 protected:
   // interface to option
   EncCfg*         m_pcEncCfg;
@@ -89,6 +106,9 @@ protected:
   // interface to classes
   TrQuant*        m_pcTrQuant;
   RdCost*         m_pcRdCost;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*     m_pcReshape;
+#endif
 
   // RD computation
   CABACWriter*    m_CABACEstimator;
@@ -109,6 +129,9 @@ public:
                                     const uint32_t     maxCUWidth,
                                     const uint32_t     maxCUHeight,
                                     const uint32_t     maxTotalCUDepth
+#if JVET_M0427_INLOOP_RESHAPER
+                                  , EncReshape*   m_pcReshape
+#endif
                                   );
 
   void destroy                    ();
@@ -117,10 +140,19 @@ public:
   CodingStructure****getFullCSBuf () { return m_pFullCS; }
   CodingStructure  **getSaveCSBuf () { return m_pSaveCS; }
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void setModeCtrl                ( EncModeCtrl *modeCtrl ) { m_modeCtrl = modeCtrl; }
+#endif
+
 public:
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void estIntraPredLumaQT         ( CodingUnit &cu, Partitioner& pm, const double bestCostSoFar  = MAX_DOUBLE );
+  void estIntraPredChromaQT       ( CodingUnit &cu, Partitioner& pm, const double maxCostAllowed = MAX_DOUBLE );
+#else
   void estIntraPredLumaQT         ( CodingUnit &cu, Partitioner& pm );
   void estIntraPredChromaQT       (CodingUnit &cu, Partitioner& pm);
+#endif
   void IPCMSearch                 (CodingStructure &cs, Partitioner& partitioner);
   uint64_t xFracModeBitsIntra     (PredictionUnit &pu, const uint32_t &uiMode, const ChannelType &compID);
 
@@ -136,12 +168,23 @@ protected:
   // Intra search
   // -------------------------------------------------------------------------------------------------------------------
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void     xEncIntraHeader                         ( CodingStructure &cs, Partitioner& pm, const bool &luma, const bool &chroma, const int subTuIdx = -1 );
+  void     xEncSubdivCbfQT                         ( CodingStructure &cs, Partitioner& pm, const bool &luma, const bool &chroma, const int subTuIdx = -1, const PartSplit ispType = TU_NO_ISP );
+  uint64_t xGetIntraFracBitsQT                     ( CodingStructure &cs, Partitioner& pm, const bool &luma, const bool &chroma, const int subTuIdx = -1, const PartSplit ispType = TU_NO_ISP );
+  uint64_t xGetIntraFracBitsQTSingleChromaComponent( CodingStructure &cs, Partitioner& pm, const ComponentID compID );
+#else
   void xEncIntraHeader            (CodingStructure &cs, Partitioner& pm, const bool &bLuma, const bool &bChroma);
   void xEncSubdivCbfQT            (CodingStructure &cs, Partitioner& pm, const bool &bLuma, const bool &bChroma);
   uint64_t xGetIntraFracBitsQT      (CodingStructure &cs, Partitioner& pm, const bool &bLuma, const bool &bChroma);
+#endif
 
   uint64_t xGetIntraFracBitsQTChroma(TransformUnit& tu, const ComponentID &compID);
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  void xEncCoeffQT                                 ( CodingStructure &cs, Partitioner& pm, const ComponentID compID, const int subTuIdx = -1, const PartSplit ispType = TU_NO_ISP );
+#else
   void xEncCoeffQT                (CodingStructure &cs, Partitioner& pm, const ComponentID &compID);
+#endif
 
 
 #if JVET_M0464_UNI_MTS
@@ -150,9 +193,14 @@ protected:
   void xIntraCodingTUBlock        (TransformUnit &tu, const ComponentID &compID, const bool &checkCrossCPrediction, Distortion& ruiDist, const int &default0Save1Load2 = 0, uint32_t* numSig = nullptr );
 #endif
 
+#if JVET_M0102_INTRA_SUBPARTITIONS
+  ChromaCbfs xRecurIntraChromaCodingQT( CodingStructure &cs, Partitioner& pm, const double bestCostSoFar = MAX_DOUBLE,                          const PartSplit ispType = TU_NO_ISP );
+  void       xRecurIntraCodingLumaQT  ( CodingStructure &cs, Partitioner& pm, const double bestCostSoFar = MAX_DOUBLE, const int subTuIdx = -1, const PartSplit ispType = TU_NO_ISP );
+#else
   ChromaCbfs xRecurIntraChromaCodingQT  (CodingStructure &cs, Partitioner& pm);
 
   void xRecurIntraCodingLumaQT    ( CodingStructure &cs, Partitioner& pm );
+#endif
 
 
   void encPredIntraDPCM( const ComponentID &compID, PelBuf &pOrg, PelBuf &pDst, const uint32_t &uiDirMode );
diff --git a/source/Lib/EncoderLib/RateCtrl.cpp b/source/Lib/EncoderLib/RateCtrl.cpp
index d88faa991ef244fcecad7dc8d5a8a321cfd4dae9..f70203efe2aa2a9d6827c633b7fd2be693003e4c 100644
--- a/source/Lib/EncoderLib/RateCtrl.cpp
+++ b/source/Lib/EncoderLib/RateCtrl.cpp
@@ -1158,7 +1158,7 @@ double EncRCPic::calAverageLambda()
       if (m_LCUs[i].m_QP > 0 || m_encRCSeq->getAdaptiveBits() != 1)
       {
         m_validPixelsInPic += m_LCUs[i].m_numberOfPixel;
-        
+
         totalLambdas += log(m_LCUs[i].m_lambda);
         numTotalLCUs++;
       }
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 34a8b308db02f6ede5d36002a8614f3214b78a6f..c181e48c19766e116a9aefd18033be5f011183c2 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -524,85 +524,55 @@ void HLSWriter::codeHrdParameters( const HRD *hrd, bool commonInfPresentFlag, ui
   }
 }
 
-
-void HLSWriter::codeSPSNext( const SPSNext& spsNext, const bool usePCM )
+#if JVET_M0427_INLOOP_RESHAPER
+void HLSWriter::codeReshaper(const SliceReshapeInfo& pSliceReshaperInfo, const SPS* pcSPS, const bool isIntra)
 {
-  // tool enabling flags
-  WRITE_FLAG( spsNext.getUseLargeCTU() ? 1 : 0,                                                 "large_ctu_flag" );
-  WRITE_FLAG( spsNext.getUseIMV() ? 1 : 0,                                                      "imv_enable_flag" );
-  WRITE_FLAG( spsNext.getDisableMotCompress() ? 1 : 0,                                          "disable_motion_compression_flag" );
-  WRITE_FLAG( spsNext.getUseLMChroma() ? 1 : 0,                                                 "lm_chroma_enabled_flag" );
-#if JVET_M0142_CCLM_COLLOCATED_CHROMA
-  if ( spsNext.getUseLMChroma() && spsNext.getSPS().getChromaFormatIdc() == CHROMA_420 )
-  {
-    WRITE_FLAG( spsNext.getCclmCollocatedChromaFlag() ? 1 : 0,                                  "sps_cclm_collocated_chroma_flag" );
-  }
-#endif
-#if JVET_M0464_UNI_MTS
-  WRITE_FLAG( spsNext.getUseIntraMTS() ? 1 : 0,                                                 "mts_intra_enabled_flag" );
-  WRITE_FLAG( spsNext.getUseInterMTS() ? 1 : 0,                                                 "mts_inter_enabled_flag" );
-#else
-  WRITE_FLAG( spsNext.getUseIntraEMT() ? 1 : 0,                                                 "emt_intra_enabled_flag" );
-  WRITE_FLAG( spsNext.getUseInterEMT() ? 1 : 0,                                                 "emt_inter_enabled_flag" );
-#endif
-  WRITE_FLAG( spsNext.getUseAffine() ? 1 : 0,                                                   "affine_flag" );
-  if ( spsNext.getUseAffine() )
+  WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeModelPresentFlag() ? 1 : 0, "tile_group_reshaper_model_present_flag");
+  if (pSliceReshaperInfo.getSliceReshapeModelPresentFlag())
   {
-    WRITE_FLAG( spsNext.getUseAffineType() ? 1 : 0,                                             "affine_type_flag" );
-  }
-  WRITE_FLAG( spsNext.getUseGBi() ? 1 : 0,                                                      "gbi_flag" );
-  WRITE_FLAG(spsNext.getIBCMode() ? 1 : 0,                                                      "ibc_flag" );
-  for( int k = 0; k < SPSNext::NumReservedFlags; k++ )
-  {
-    WRITE_FLAG( 0,                                                                              "reserved_flag" );
-  }
-
-  WRITE_FLAG( spsNext.getMTTEnabled() ? 1 : 0,                                                  "mtt_enabled_flag" );
-  WRITE_FLAG( spsNext.getUseMHIntra() ? 1 : 0,                                                  "mhintra_flag" );
-  WRITE_FLAG( spsNext.getUseTriangle() ? 1: 0,                                                  "triangle_flag" );
-#if ENABLE_WPP_PARALLELISM
-  WRITE_FLAG( spsNext.getUseNextDQP(),                                                          "next_dqp_enabled_flag" );
-#else
-  WRITE_FLAG( 0,                                                                                "reserved_flag" );
-#endif
-
-  // additional parameters
+    WRITE_UVLC(pSliceReshaperInfo.reshaperModelMinBinIdx, "reshaper_model_min_bin_idx");
+    WRITE_UVLC(PIC_CODE_CW_BINS - 1 - pSliceReshaperInfo.reshaperModelMaxBinIdx, "reshaper_model_delta_max_bin_idx");
+    assert(pSliceReshaperInfo.maxNbitsNeededDeltaCW > 0);
+    WRITE_UVLC(pSliceReshaperInfo.maxNbitsNeededDeltaCW - 1, "reshaper_model_bin_delta_abs_cw_prec_minus1");
 
-  if( spsNext.getUseIMV() )
-  {
-    WRITE_UVLC( spsNext.getImvMode()-1,                                                         "imv_mode_minus1" );
-  }
-
-  if( spsNext.getMTTEnabled() )
-  {
-    WRITE_UVLC( spsNext.getMTTMode() - 1,                                                       "mtt_mode_minus1" );
-  }
-#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
-  WRITE_FLAG( spsNext.getLadfEnabled() ? 1 : 0,                                                 "sps_ladf_enabled_flag" );
-  if ( spsNext.getLadfEnabled() )
-  {
-    WRITE_CODE( spsNext.getLadfNumIntervals() - 2, 2,                                           "sps_num_ladf_intervals_minus2" );
-    WRITE_SVLC( spsNext.getLadfQpOffset( 0 ),                                                   "sps_ladf_lowest_interval_qp_offset");
-    for ( int k = 1; k< spsNext.getLadfNumIntervals(); k++ )
+    for (int i = pSliceReshaperInfo.reshaperModelMinBinIdx; i <= pSliceReshaperInfo.reshaperModelMaxBinIdx; i++)
     {
-      WRITE_SVLC( spsNext.getLadfQpOffset( k ),                                                 "sps_ladf_qp_offset" );
-      WRITE_UVLC( spsNext.getLadfIntervalLowerBound( k ) - spsNext.getLadfIntervalLowerBound( k - 1 ) - 1, "sps_ladf_delta_threshold_minus1" );
+      int deltaCW = pSliceReshaperInfo.reshaperModelBinCWDelta[i];
+      int signCW = (deltaCW < 0) ? 1 : 0;
+      int absCW = (deltaCW < 0) ? (-deltaCW) : deltaCW;
+      WRITE_CODE(absCW, pSliceReshaperInfo.maxNbitsNeededDeltaCW, "reshaper_model_bin_delta_abs_CW");
+      if (absCW > 0)
+      {
+        WRITE_FLAG(signCW, "reshaper_model_bin_delta_sign_CW_flag");
+      }
     }
   }
-#endif
-  // ADD_NEW_TOOL : (sps extension writer) write tool enabling flags and associated parameters here
-}
+
+  WRITE_FLAG(pSliceReshaperInfo.getUseSliceReshaper() ? 1 : 0, "tile_group_reshaper_enable_flag");
+
+  if (!pSliceReshaperInfo.getUseSliceReshaper())
+    return;
+
+  if (!(pcSPS->getUseDualITree() && isIntra))
+    WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeChromaAdj(), "tile_group_reshaper_chroma_residual_scale_flag");
+};
+#endif // #if JVET_M0427_INLOOP_RESHAPER
 
 void HLSWriter::codeSPS( const SPS* pcSPS )
 {
+#if ENABLE_TRACING
+  xTraceSPSHeader ();
+#endif
+#if HEVC_VPS
+  WRITE_CODE( pcSPS->getVPSId (),          4,       "sps_video_parameter_set_id" );
+#endif
+  WRITE_UVLC( pcSPS->getSPSId (),                   "sps_seq_parameter_set_id" );
 
-  const ChromaFormat format                = pcSPS->getChromaFormatIdc();
-  const bool         chromaEnabled         = isChromaEnabled(format);
   WRITE_FLAG(pcSPS->getIntraOnlyConstraintFlag() ? 1 : 0, "intra_only_constraint_flag");
   WRITE_CODE(pcSPS->getMaxBitDepthConstraintIdc(), 4, "max_bitdepth_constraint_idc");
   WRITE_CODE(pcSPS->getMaxChromaFormatConstraintIdc(), 2, "max_chroma_format_constraint_idc");
-  WRITE_FLAG(pcSPS->getFrameConstraintFlag() ? 1 : 0, "frame_constraint_flag");
-  WRITE_FLAG(pcSPS->getNoQtbttDualTreeIntraConstraintFlag() ? 1 : 0, "no_qtbtt_dual_tree_intra constraint_flag");
+  WRITE_FLAG(pcSPS->getFrameConstraintFlag() ? 1 : 0, "frame_only_constraint_flag");
+  WRITE_FLAG(pcSPS->getNoQtbttDualTreeIntraConstraintFlag() ? 1 : 0, "no_qtbtt_dual_tree_intra_constraint_flag");
   WRITE_FLAG(pcSPS->getNoCclmConstraintFlag() ? 1 : 0, "no_cclm_constraint_flag");
   WRITE_FLAG(pcSPS->getNoSaoConstraintFlag() ? 1 : 0, "no_sao_constraint_flag");
   WRITE_FLAG(pcSPS->getNoAlfConstraintFlag() ? 1 : 0, "no_alf_constraint_flag");
@@ -615,17 +585,17 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_FLAG(pcSPS->getNoLadfConstraintFlag() ? 1 : 0, "no_ladf_constraint_flag");
   WRITE_FLAG(pcSPS->getNoDepQuantConstraintFlag() ? 1 : 0, "no_dep_quant_constraint_flag");
   WRITE_FLAG(pcSPS->getNoSignDataHidingConstraintFlag() ? 1 : 0, "no_sign_data_hiding_constraint_flag");
-#if ENABLE_TRACING
-  xTraceSPSHeader ();
-#endif
-#if HEVC_VPS
-  WRITE_CODE( pcSPS->getVPSId (),          4,       "sps_video_parameter_set_id" );
-#endif
+
+  // KJS: Marakech decision: sub-layers added back
+  CHECK( pcSPS->getMaxTLayers() == 0, "Maximum number of temporal sub-layers is '0'" );
   WRITE_CODE( pcSPS->getMaxTLayers() - 1,  3,       "sps_max_sub_layers_minus1" );
+
   WRITE_FLAG( pcSPS->getTemporalIdNestingFlag() ? 1 : 0, "sps_temporal_id_nesting_flag" );
   codePTL( pcSPS->getPTL(), true, pcSPS->getMaxTLayers() - 1 );
-  WRITE_UVLC( pcSPS->getSPSId (),                   "sps_seq_parameter_set_id" );
+
   WRITE_UVLC( int(pcSPS->getChromaFormatIdc ()),    "chroma_format_idc" );
+
+  const ChromaFormat format                = pcSPS->getChromaFormatIdc();
   if( format == CHROMA_444 )
   {
     WRITE_FLAG( 0,                                  "separate_colour_plane_flag");
@@ -635,6 +605,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_UVLC( pcSPS->getPicHeightInLumaSamples(),   "pic_height_in_luma_samples" );
   Window conf = pcSPS->getConformanceWindow();
 
+  // KJS: not removing yet
   WRITE_FLAG( conf.getWindowEnabledFlag(),          "conformance_window_flag" );
   if (conf.getWindowEnabledFlag())
   {
@@ -645,11 +616,13 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   }
 
   WRITE_UVLC( pcSPS->getBitDepth(CHANNEL_TYPE_LUMA) - 8,                      "bit_depth_luma_minus8" );
-
+  
+  const bool         chromaEnabled         = isChromaEnabled(format);
   WRITE_UVLC( chromaEnabled ? (pcSPS->getBitDepth(CHANNEL_TYPE_CHROMA) - 8):0,  "bit_depth_chroma_minus8" );
 
   WRITE_UVLC( pcSPS->getBitsForPOC()-4,                 "log2_max_pic_order_cnt_lsb_minus4" );
 
+  // KJS: Marakech decision: sub-layers added back
   const bool subLayerOrderingInfoPresentFlag = 1;
   WRITE_FLAG(subLayerOrderingInfoPresentFlag,       "sps_sub_layer_ordering_info_present_flag");
   for(uint32_t i=0; i <= pcSPS->getMaxTLayers()-1; i++)
@@ -663,41 +636,43 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     }
   }
   CHECK( pcSPS->getMaxCUWidth() != pcSPS->getMaxCUHeight(),                          "Rectangular CTUs not supported" );
-  WRITE_FLAG(pcSPS->getUseDualITree(), "qtbt_dual_intra_tree");
-  WRITE_UVLC(g_aucLog2[pcSPS->getCTUSize()] - MIN_CU_LOG2, "log2_CTU_size_minus2");
+  WRITE_FLAG(pcSPS->getUseDualITree(), "qtbtt_dual_tree_intra_flag");
+  WRITE_UVLC(g_aucLog2[pcSPS->getCTUSize()] - MIN_CU_LOG2, "log2_ctu_size_minus2");
   WRITE_UVLC(pcSPS->getLog2MinCodingBlockSize() - 2, "log2_min_luma_coding_block_size_minus2");
-  WRITE_FLAG(pcSPS->getSplitConsOverrideEnabledFlag(), "sps_override_partition_constraints_enable_flag");
-  WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_slice");
-  WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(B_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_inter_slice");
-  WRITE_UVLC(pcSPS->getMaxBTDepth(), "sps_max_mtt_hierarchy_depth_inter_slices");
-  WRITE_UVLC(pcSPS->getMaxBTDepthI(), "sps_max_mtt_hierarchy_depth_intra_slices");
+  WRITE_FLAG(pcSPS->getSplitConsOverrideEnabledFlag(), "partition_constraints_override_enabled_flag");
+  WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_tile_group_luma");
+  WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(B_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_inter_tile_group");
+  WRITE_UVLC(pcSPS->getMaxBTDepth(), "sps_max_mtt_hierarchy_depth_inter_tile_group");
+  WRITE_UVLC(pcSPS->getMaxBTDepthI(), "sps_max_mtt_hierarchy_depth_intra_tile_group_luma");
   if (pcSPS->getMaxBTDepthI() != 0)
   {
-    WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_bt_min_qt_intra_slice");
-    WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_tt_min_qt_intra_slice");
+    WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_bt_min_qt_intra_tile_group_luma");
+    WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_tt_min_qt_intra_tile_group_luma");
   }
   if (pcSPS->getMaxBTDepth() != 0)
   {
-    WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_bt_min_qt_inter_slice");
-    WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_tt_min_qt_inter_slice");
+    WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_bt_min_qt_inter_tile_group");
+    WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_tt_min_qt_inter_tile_group");
   }
   if (pcSPS->getUseDualITree())
   {
-    WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_slice_chroma");
-    WRITE_UVLC(pcSPS->getMaxBTDepthIChroma(), "sps_max_mtt_hierarchy_depth_intra_slices_chroma");
+    WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_tile_group_chroma");
+    WRITE_UVLC(pcSPS->getMaxBTDepthIChroma(), "sps_max_mtt_hierarchy_depth_intra_tile_group_chroma");
     if (pcSPS->getMaxBTDepthIChroma() != 0)
     {
-      WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_bt_min_qt_intra_slice_chroma");
-      WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_tt_min_qt_intra_slice_chroma");
+      WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_bt_min_qt_intra_tile_group_chroma");
+      WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_tt_min_qt_intra_tile_group_chroma");
     }
   }
+  
+  // KJS: does not exist anymore -> remove?
   WRITE_UVLC( pcSPS->getQuadtreeTULog2MinSize() - 2,                                 "log2_min_luma_transform_block_size_minus2" );
-  WRITE_UVLC( pcSPS->getQuadtreeTULog2MaxSize() - pcSPS->getQuadtreeTULog2MinSize(), "log2_diff_max_min_luma_transform_block_size" );
+    WRITE_UVLC( pcSPS->getQuadtreeTULog2MaxSize() - pcSPS->getQuadtreeTULog2MinSize(), "log2_diff_max_min_luma_transform_block_size" );
 
   WRITE_FLAG( pcSPS->getSAOEnabledFlag(),                                            "sps_sao_enabled_flag");
   WRITE_FLAG( pcSPS->getALFEnabledFlag(),                                            "sps_alf_enabled_flag" );
 
-  WRITE_FLAG( pcSPS->getPCMEnabledFlag() ? 1 : 0,                                    "pcm_enabled_flag");
+  WRITE_FLAG( pcSPS->getPCMEnabledFlag() ? 1 : 0,                                    "sps_pcm_enabled_flag");
   if( pcSPS->getPCMEnabledFlag() )
   {
     WRITE_CODE( pcSPS->getPCMBitDepth(CHANNEL_TYPE_LUMA) - 1, 4,                            "pcm_sample_bit_depth_luma_minus1" );
@@ -720,22 +695,92 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     WRITE_FLAG( pcSPS->getSBTMVPEnabledFlag() ? 1 : 0,                               "sps_sbtmvp_enabled_flag");
   }
 
+  WRITE_FLAG( pcSPS->getAMVREnabledFlag() ? 1 : 0,                                   "sps_amvr_enabled_flag" );
+
   WRITE_FLAG( pcSPS->getBDOFEnabledFlag() ? 1 : 0,                                   "sps_bdof_enabled_flag" );
 
-#if HEVC_USE_SCALING_LISTS
-  WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0,                                   "scaling_list_enabled_flag" );
-  if(pcSPS->getScalingListFlag())
+#if JVET_M0246_AFFINE_AMVR
+  WRITE_FLAG( pcSPS->getAffineAmvrEnabledFlag() ? 1 : 0,                             "sps_affine_amvr_enabled_flag" );
+#endif
+
+#if JVET_M0147_DMVR
+  WRITE_FLAG( pcSPS->getUseDMVR() ? 1 : 0,                                            "sps_dmvr_enable_flag" );
+#endif
+
+  // KJS: sps_cclm_enabled_flag
+  WRITE_FLAG( pcSPS->getUseLMChroma() ? 1 : 0,                                                 "lm_chroma_enabled_flag" );
+#if JVET_M0142_CCLM_COLLOCATED_CHROMA
+  if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 )
   {
-    WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0,                          "sps_scaling_list_data_present_flag" );
-    if(pcSPS->getScalingListPresentFlag())
+    WRITE_FLAG( pcSPS->getCclmCollocatedChromaFlag() ? 1 : 0,                                  "sps_cclm_collocated_chroma_flag" );
+  }
+#endif
+
+#if JVET_M0303_IMPLICIT_MTS
+  WRITE_FLAG( pcSPS->getUseMTS() ? 1 : 0,                                                      "mts_enabled_flag" );
+  if ( pcSPS->getUseMTS() )
+  {
+#endif
+#if JVET_M0464_UNI_MTS
+    WRITE_FLAG( pcSPS->getUseIntraMTS() ? 1 : 0,                                               "mts_intra_enabled_flag" );
+    WRITE_FLAG( pcSPS->getUseInterMTS() ? 1 : 0,                                               "mts_inter_enabled_flag" );
+#else
+    WRITE_FLAG( pcSPS->getUseIntraEMT() ? 1 : 0,                                               "emt_intra_enabled_flag" );
+    WRITE_FLAG( pcSPS->getUseInterEMT() ? 1 : 0,                                               "emt_inter_enabled_flag" );
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  }
+#endif
+  // KJS: sps_affine_enabled_flag
+  WRITE_FLAG( pcSPS->getUseAffine() ? 1 : 0,                                                   "affine_flag" );
+  if ( pcSPS->getUseAffine() )
+  {
+    WRITE_FLAG( pcSPS->getUseAffineType() ? 1 : 0,                                             "affine_type_flag" );
+  }
+  WRITE_FLAG( pcSPS->getUseGBi() ? 1 : 0,                                                      "gbi_flag" );
+#if JVET_M0483_IBC
+  WRITE_FLAG(pcSPS->getIBCFlag() ? 1 : 0,                                                      "ibc_flag");
+#else
+  WRITE_FLAG(pcSPS->getIBCMode() ? 1 : 0,                                                      "ibc_flag" );
+#endif
+
+  // KJS: sps_ciip_enabled_flag
+  WRITE_FLAG( pcSPS->getUseMHIntra() ? 1 : 0,                                                  "mhintra_flag" );
+  
+  WRITE_FLAG( pcSPS->getUseTriangle() ? 1: 0,                                                  "triangle_flag" );
+
+  // KJS: not in draft yet
+#if JVET_M0255_FRACMMVD_SWITCH
+  WRITE_FLAG( pcSPS->getDisFracMmvdEnabledFlag() ? 1 : 0,                            "sps_fracmmvd_disabled_flag" );
+#endif
+  // KJS: not in draft yet
+#if JVET_M0140_SBT
+  WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0,                                             "sbt_enable_flag");
+  if( pcSPS->getUseSBT() )
+  {
+    WRITE_FLAG(pcSPS->getMaxSbtSize() == 64 ? 1 : 0,                                  "max_sbt_size_64_flag");
+  }
+#endif
+  // KJS: not in draft yet
+#if JVET_M0427_INLOOP_RESHAPER
+  WRITE_FLAG(pcSPS->getUseReshaper() ? 1 : 0, "sps_reshaper_enable_flag");
+#endif
+  
+#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
+  WRITE_FLAG( pcSPS->getLadfEnabled() ? 1 : 0,                                                 "sps_ladf_enabled_flag" );
+  if ( pcSPS->getLadfEnabled() )
+  {
+    WRITE_CODE( pcSPS->getLadfNumIntervals() - 2, 2,                                           "sps_num_ladf_intervals_minus2" );
+    WRITE_SVLC( pcSPS->getLadfQpOffset( 0 ),                                                   "sps_ladf_lowest_interval_qp_offset");
+    for ( int k = 1; k< pcSPS->getLadfNumIntervals(); k++ )
     {
-      codeScalingList( pcSPS->getScalingList() );
+      WRITE_SVLC( pcSPS->getLadfQpOffset( k ),                                                 "sps_ladf_qp_offset" );
+      WRITE_UVLC( pcSPS->getLadfIntervalLowerBound( k ) - pcSPS->getLadfIntervalLowerBound( k - 1 ) - 1, "sps_ladf_delta_threshold_minus1" );
     }
   }
 #endif
 
-  CHECK( pcSPS->getMaxTLayers() == 0, "Maximum number of T-layers is '0'" );
-
+  // KJS: reference picture sets to be replaced
   const RPSList* rpsList = pcSPS->getRPSList();
 
   WRITE_UVLC(rpsList->getNumberOfReferencePictureSets(), "num_short_term_ref_pic_sets" );
@@ -759,19 +804,31 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_FLAG( pcSPS->getUseStrongIntraSmoothing(),             "strong_intra_smoothing_enable_flag" );
 
 #endif
+
+  // KJS: remove scaling lists?
+#if HEVC_USE_SCALING_LISTS
+  WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0,                                   "scaling_list_enabled_flag" );
+  if(pcSPS->getScalingListFlag())
+  {
+    WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0,                          "sps_scaling_list_data_present_flag" );
+    if(pcSPS->getScalingListPresentFlag())
+    {
+      codeScalingList( pcSPS->getScalingList() );
+    }
+  }
+#endif
+  
+  // KJS: no VUI defined yet
   WRITE_FLAG( pcSPS->getVuiParametersPresentFlag(),            "vui_parameters_present_flag" );
   if (pcSPS->getVuiParametersPresentFlag())
   {
     codeVUI(pcSPS->getVuiParameters(), pcSPS);
   }
 
-  // KTA tools
-
   bool sps_extension_present_flag=false;
   bool sps_extension_flags[NUM_SPS_EXTENSION_FLAGS]={false};
 
   sps_extension_flags[SPS_EXT__REXT] = pcSPS->getSpsRangeExtension().settingsDifferFromDefaults();
-  sps_extension_flags[SPS_EXT__NEXT] = pcSPS->getSpsNext().nextToolsEnabled();
 
   // Other SPS extension flags checked here.
 
@@ -821,11 +878,6 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
           WRITE_FLAG( (spsRangeExtension.getCabacBypassAlignmentEnabledFlag() ? 1 : 0),       "cabac_bypass_alignment_enabled_flag" );
           break;
         }
-        case SPS_EXT__NEXT:
-        {
-          codeSPSNext( pcSPS->getSpsNext(), pcSPS->getPCMEnabledFlag() );
-          break;
-        }
         default:
           CHECK(sps_extension_flags[i]!=false, "Unknown PPS extension signalled"); // Should never get here with an active SPS extension flag.
           break;
@@ -1265,26 +1317,41 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
         }
       }
     }
+#if JVET_M0483_IBC
+    if (!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag())
+    {
+      CHECK(pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported");
+      WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand");
+    }
+#endif
     if( !pcSlice->isIntra() )
     {
+#if JVET_M0483_IBC==0
       CHECK( pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported" );
       WRITE_UVLC( MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand" );
+#endif
 
-      if ( pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getSpsNext().getUseAffine() ) // ATMVP only
+      if ( pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // ATMVP only
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() != 1, "Sub-block merge can number should be 1" );
       }
       else
-      if ( !pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getSpsNext().getUseAffine() ) // both off
+      if ( !pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // both off
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() != 0, "Sub-block merge can number should be 0" );
       }
       else
-      if ( pcSlice->getSPS()->getSpsNext().getUseAffine() )
+      if ( pcSlice->getSPS()->getUseAffine() )
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() > AFFINE_MRG_MAX_NUM_CANDS, "More affine merge candidates signalled than supported" );
         WRITE_UVLC( AFFINE_MRG_MAX_NUM_CANDS - pcSlice->getMaxNumAffineMergeCand(), "five_minus_max_num_affine_merge_cand" );
       }
+#if JVET_M0255_FRACMMVD_SWITCH
+      if ( pcSlice->getSPS()->getDisFracMmvdEnabledFlag() )
+      {
+        WRITE_FLAG( pcSlice->getDisFracMMVD(), "tile_group_fracmmvd_disabled_flag" );
+      }
+#endif
     }
     int iCode = pcSlice->getSliceQp() - ( pcSlice->getPPS()->getPicInitQPMinus26() + 26 );
     WRITE_SVLC( iCode, "slice_qp_delta" );
@@ -1330,6 +1397,13 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
     {
       WRITE_FLAG(pcSlice->getLFCrossSliceBoundaryFlag()?1:0, "slice_loop_filter_across_slices_enabled_flag");
     }
+
+#if JVET_M0427_INLOOP_RESHAPER
+    if (pcSlice->getSPS()->getUseReshaper())
+    {
+      codeReshaper(pcSlice->getReshapeInfo(), pcSlice->getSPS(), pcSlice->isIntra());
+    }
+#endif
 #if HEVC_DEPENDENT_SLICES
   }
 #endif
@@ -1642,7 +1716,7 @@ bool HLSWriter::xFindMatchingLTRP(Slice* pcSlice, uint32_t *ltrpsIndex, int ltrp
 
 void HLSWriter::alf( const AlfSliceParam& alfSliceParam )
 {
-  WRITE_FLAG( alfSliceParam.enabledFlag[COMPONENT_Y], "alf_slice_enable_flag" );
+  WRITE_FLAG( alfSliceParam.enabledFlag[COMPONENT_Y], "tile_group_alf_enabled_flag" );
   if( !alfSliceParam.enabledFlag[COMPONENT_Y] )
   {
     return;
@@ -1699,12 +1773,12 @@ void HLSWriter::alfFilter( const AlfSliceParam& alfSliceParam, const bool isChro
 {
   if( !isChroma )
   {
-    WRITE_FLAG( alfSliceParam.coeffDeltaFlag, "alf_coefficients_delta_flag" );
-    if( !alfSliceParam.coeffDeltaFlag )
+    WRITE_FLAG( alfSliceParam.alfLumaCoeffDeltaFlag, "alf_luma_coeff_delta_flag" );
+    if( !alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       if( alfSliceParam.numLumaFilters > 1 )
       {
-        WRITE_FLAG( alfSliceParam.coeffDeltaPredModeFlag, "coeff_delta_pred_mode_flag" );
+        WRITE_FLAG( alfSliceParam.alfLumaCoeffDeltaPredictionFlag, "alf_luma_coeff_delta_prediction_flag" );
       }
     }
   }
@@ -1719,7 +1793,7 @@ void HLSWriter::alfFilter( const AlfSliceParam& alfSliceParam, const bool isChro
   // vlc for all
   for( int ind = 0; ind < numFilters; ++ind )
   {
-    if( isChroma || !alfSliceParam.coeffDeltaFlag || alfSliceParam.filterCoeffFlag[ind] )
+    if( isChroma || !alfSliceParam.alfLumaCoeffDeltaFlag || alfSliceParam.alfLumaCoeffFlag[ind] )
     {
       for( int i = 0; i < alfShape.numCoeff - 1; i++ )
       {
@@ -1737,23 +1811,23 @@ void HLSWriter::alfFilter( const AlfSliceParam& alfSliceParam, const bool isChro
   int kMin = EncAdaptiveLoopFilter::getGolombKMin( alfShape, numFilters, kMinTab, bitsCoeffScan );
 
   // Golomb parameters
-  WRITE_UVLC( kMin - 1, "min_golomb_order" );
+  WRITE_UVLC( kMin - 1,  isChroma ? "alf_chroma_min_eg_order_minus1" : "alf_luma_min_eg_order_minus1" );
 
   for( int idx = 0; idx < maxGolombIdx; idx++ )
   {
     bool golombOrderIncreaseFlag = ( kMinTab[idx] != kMin ) ? true : false;
     CHECK( !( kMinTab[idx] <= kMin + 1 ), "ALF Golomb parameter not consistent" );
-    WRITE_FLAG( golombOrderIncreaseFlag, "golomb_order_increase_flag" );
+    WRITE_FLAG( golombOrderIncreaseFlag, isChroma ? "alf_chroma_eg_order_increase_flag"  : "alf_luma_eg_order_increase_flag" );
     kMin = kMinTab[idx];
   }
 
   if( !isChroma )
   {
-    if( alfSliceParam.coeffDeltaFlag )
+    if( alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       for( int ind = 0; ind < numFilters; ++ind )
       {
-        WRITE_FLAG( alfSliceParam.filterCoeffFlag[ind], "filter_coefficient_flag[i]" );
+        WRITE_FLAG( alfSliceParam.alfLumaCoeffFlag[ind], "alf_luma_coeff_flag[i]" );
       }
     }
   }
@@ -1761,7 +1835,7 @@ void HLSWriter::alfFilter( const AlfSliceParam& alfSliceParam, const bool isChro
   // Filter coefficients
   for( int ind = 0; ind < numFilters; ++ind )
   {
-    if( !isChroma && !alfSliceParam.filterCoeffFlag[ind] && alfSliceParam.coeffDeltaFlag )
+    if( !isChroma && !alfSliceParam.alfLumaCoeffFlag[ind] && alfSliceParam.alfLumaCoeffDeltaFlag )
     {
       continue;
     }
diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h
index 2e3dd35f9e845131965bed3f3b9706b7fd350f17..b3866e8ab3a78c22f66574ec4eda016167dc362d 100644
--- a/source/Lib/EncoderLib/VLCWriter.h
+++ b/source/Lib/EncoderLib/VLCWriter.h
@@ -120,7 +120,6 @@ public:
   void  setBitstream            ( OutputBitstream* p )  { m_pcBitIf = p;  }
   uint32_t  getNumberOfWrittenBits  ()                      { return m_pcBitIf->getNumberOfWrittenBits();  }
   void  codeVUI                 ( const VUI *pcVUI, const SPS* pcSPS );
-  void  codeSPSNext             ( const SPSNext& spsNext, const bool usePCM );
   void  codeSPS                 ( const SPS* pcSPS );
   void  codePPS                 ( const PPS* pcPPS );
 #if HEVC_VPS
@@ -145,6 +144,9 @@ private:
   void alfGolombEncode( const int coeff, const int k );
   void truncatedUnaryEqProb( int symbol, int maxSymbol );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  void  codeReshaper            ( const SliceReshapeInfo& pSliceReshaperInfo, const SPS* pcSPS, const bool isIntra);
+#endif
 };
 
 //! \}