From 84a593afe58ff429f5cd9a96c26aa22ff2c101c7 Mon Sep 17 00:00:00 2001
From: Hendry <fhendry@futurewei.com>
Date: Tue, 18 Jun 2019 11:36:05 +0200
Subject: [PATCH] - Implementation of rectangular slice as JVET-M0853 &
 JVET-N0857 - Fix the entry points - Put some validation for rectangular slice
 - Bug fix for N0124 signalling for number of bits to signal bottomrightidx

---
 ...coder_randomaccess_vtm_RasterScanSlice.cfg | 182 +++++++++++++++++
 ...oder_randomaccess_vtm_RectangularSlice.cfg | 184 ++++++++++++++++++
 ...er_randomaccess_vtm_SingleTilePerSlice.cfg | 184 ++++++++++++++++++
 doc/software-manual.tex                       |  43 ++++
 source/App/EncoderApp/EncApp.cpp              |   5 +
 source/App/EncoderApp/EncAppCfg.cpp           | 146 ++++++++++++++
 source/App/EncoderApp/EncAppCfg.h             |   5 +
 source/App/Parcat/parcat.cpp                  |  45 +++++
 source/Lib/CommonLib/Slice.cpp                |   4 +
 source/Lib/CommonLib/Slice.h                  |  36 ++++
 source/Lib/CommonLib/TypeDef.h                |   1 +
 source/Lib/DecoderLib/DecLib.cpp              |  29 +++
 source/Lib/DecoderLib/DecSlice.cpp            |  24 ++-
 source/Lib/DecoderLib/VLCReader.cpp           | 121 +++++++++++-
 source/Lib/EncoderLib/EncCfg.h                |  12 ++
 source/Lib/EncoderLib/EncGOP.cpp              |  33 ++++
 source/Lib/EncoderLib/EncLib.cpp              |  21 +-
 source/Lib/EncoderLib/EncSlice.cpp            |  89 ++++++++-
 source/Lib/EncoderLib/VLCWriter.cpp           |  66 ++++++-
 19 files changed, 1222 insertions(+), 8 deletions(-)
 create mode 100644 cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
 create mode 100644 cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
 create mode 100644 cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg

diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
new file mode 100644
index 000000000..696b74021
--- /dev/null
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
@@ -0,0 +1,182 @@
+#======== File I/O =====================
+BitstreamFile                 : str.bin
+ReconFile                     : rec.yuv
+
+#======== Profile ================
+Profile                       : next
+
+#======== Unit definition ================
+MaxCUWidth                    : 64          # Maximum coding unit width in pixel
+MaxCUHeight                   : 64          # Maximum coding unit height in pixel
+MaxPartitionDepth             : 4           # Maximum coding unit depth
+
+#======== Coding Structure =============
+IntraPeriod                   : 32          # Period of I-Frame ( -1 = only first)
+DecodingRefreshType           : 1           # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI
+GOPSize                       : 16          # GOP Size (number of B slice = GOPSize-1)
+
+IntraQPOffset                 : -3
+LambdaFromQpEnable            : 1           # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled
+#        Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures     predict deltaRPS #ref_idcs reference idcs
+Frame1:  B   16   1        0.0                      0.0            0          0          1.0      0            0              0           2                3         -16 -24 -32            0
+Frame2:  B    8   1       -4.8848                   0.2061         0          0          1.0      0            0              1           2                3         -8  -16   8            1       8        4         1 1 0 1
+Frame3:  B    4   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                4         -4  -12   4  12        1       4        4         1 1 1 1
+Frame4:  B    2   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                5         -2  -10   2   6  14    1       2        5         1 1 1 1 1
+Frame5:  B    1   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1    1  3    7  15    1       1        6         1 0 1 1 1 1
+Frame6:  B    3   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3   1   5  13    1      -2        6         1 1 1 1 1 0
+Frame7:  B    6   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6   2  10        1      -3        6         0 1 1 1 1 0
+Frame8:  B    5   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5   1   3  11    1       1        5         1 1 1 1 1
+Frame9:  B    7   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3  -7   1   9    1      -2        6         1 1 1 1 1 0
+Frame10: B   12   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                3         -4  -12   4            1      -5        6         0 0 1 1 1 0
+Frame11: B   10   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2  -10   2   6        1       2        4         1 1 1 1
+Frame12: B    9   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -9   1   3   7    1       1        5         1 1 1 1 1
+Frame13: B   11   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -11   1   5    1      -2        6         1 1 1 1 1 0
+Frame14: B   14   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6 -14   2        1      -3        6         0 1 1 1 1 0
+Frame15: B   13   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5 -13   1   3    1       1        5         1 1 1 1 1
+Frame16: B   15   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -7  -15   1    1      -2        6         1 1 1 1 1 0
+
+#=========== Motion Search =============
+FastSearch                    : 1           # 0:Full search  1:TZ search
+SearchRange                   : 384         # (0: Search range is a Full frame)
+ASR                           : 1           # Adaptive motion search range
+MinSearchWindow               : 96          # Minimum motion search window size for the adaptive window ME
+BipredSearchRange             : 4           # Search range for bi-prediction refinement
+HadamardME                    : 1           # Use of hadamard measure for fractional ME
+FEN                           : 1           # Fast encoder decision
+FDM                           : 1           # Fast Decision for Merge RD cost
+
+#======== Quantization =============
+QP                            : 32          # Quantization parameter(0-51)
+MaxDeltaQP                    : 0           # CU-based multi-QP optimization
+MaxCuDQPSubdiv                : 0           # Maximum subdiv for CU luma Qp adjustment
+DeltaQpRD                     : 0           # Slice-based multi-QP optimization
+RDOQ                          : 1           # RDOQ
+RDOQTS                        : 1           # RDOQ for transform skip
+
+#=========== Deblock Filter ============
+LoopFilterOffsetInPPS         : 1           # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param)
+LoopFilterDisable             : 0           # Disable deblocking filter (0=Filter, 1=No Filter)
+LoopFilterBetaOffset_div2     : 0           # base_param: -6 ~ 6
+LoopFilterTcOffset_div2       : 0           # base_param: -6 ~ 6
+DeblockingFilterMetric        : 0           # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0)
+
+#=========== Misc. ============
+InternalBitDepth              : 10          # codec operating bit-depth
+
+#=========== Coding Tools =================
+SAO                           : 1           # Sample adaptive offset  (0: OFF, 1: ON)
+TransformSkip                 : 1           # Transform skipping (0: OFF, 1: ON)
+TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1: ON)
+TransformSkipLog2MaxSize      : 5
+SAOLcuBoundary                : 0           # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON)
+
+#============ Slices ================
+SliceMode                : 3                # 0: Disable all slice options.
+                                            # 1: Enforce maximum number of LCU in an slice,
+                                            # 2: Enforce maximum number of bytes in an 'slice'
+                                            # 3: Enforce maximum number of tiles in a slice
+SliceArgument            : 4                # Argument for 'SliceMode'.
+                                            # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice.
+                                            # If SliceMode==2 it represents max. bytes per slice.
+                                            # If SliceMode==3 it represents max. tiles per slice.
+
+LFCrossSliceBoundaryFlag : 1                # In-loop filtering, including ALF and DB, is across or not across slice boundary.
+                                            # 0:not across, 1: across
+
+#============ Tiles ================
+TileUniformSpacing                  : 0                # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array
+                                                       # 1: the column and row boundaries are distributed uniformly
+NumTileColumnsMinus1                : 1                # Number of tile columns in a picture minus 1
+TileColumnWidthArray                : 2                # Array containing tile column width values in units of CTU (from left to right in picture)   
+NumTileRowsMinus1                   : 1                # Number of tile rows in a picture minus 1
+TileRowHeightArray                  : 1                # Array containing tile row height values in units of CTU (from top to bottom in picture)
+
+LFCrossTileBoundaryFlag             : 0                # In-loop filtering is across or not across tile boundary.
+                                                       # 0:not across, 1: across 
+                                                       
+RectSliceFlag                       : 0
+
+#============ PCM ================
+PCMEnabledFlag                      : 0                # 0: No PCM mode
+PCMLog2MaxSize                      : 5                # Log2 of maximum PCM block size.
+PCMLog2MinSize                      : 3                # Log2 of minimum PCM block size.
+PCMInputBitDepthFlag                : 1                # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth.
+PCMFilterDisableFlag                : 0                # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples.
+
+#============ Lossless ================
+TransquantBypassEnable     : 0                         # Value of PPS flag.
+CUTransquantBypassFlagForce: 0                         # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled
+
+#============ Rate Control ======================
+RateControl                         : 0                # Rate control: enable rate control
+TargetBitrate                       : 1000000          # Rate control: target bitrate, in bps
+KeepHierarchicalBit                 : 2                # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation
+LCULevelRateControl                 : 1                # Rate control: 1: LCU level RC; 0: picture level RC
+RCLCUSeparateModel                  : 1                # Rate control: use LCU level separate R-lambda model
+InitialQP                           : 0                # Rate control: initial QP
+RCForceIntraQP                      : 0                # Rate control: force intra QP to be equal to initial QP
+
+#============ VTM settings ======================
+LoopFilterTcOffset_div2             : 0
+SEIDecodedPictureHash               : 0
+CbQpOffset                          : 1
+CrQpOffset                          : 1
+
+ReWriteParamSets                    : 1
+#============ NEXT ====================
+
+# General
+CTUSize                      : 128
+LCTUFast                     : 1
+
+DualITree                    : 1      # separate partitioning of luma and chroma channels for I-slices
+MinQTLumaISlice              : 8
+MinQTChromaISlice            : 4
+MinQTNonISlice               : 8
+MaxBTDepth                   : 3
+MaxBTDepthISliceL            : 3
+MaxBTDepthISliceC            : 3
+
+MTS                          : 1
+MTSIntraMaxCand              : 3
+MTSInterMaxCand              : 4
+SBT                          : 1
+LFNST			     : 1
+ISP                          : 1
+MMVD                         : 1
+Affine                       : 1
+SubPuMvp                     : 1
+MaxNumMergeCand              : 6
+LMChroma                     : 1      # use CCLM only
+DepQuant                     : 1
+IMV                          : 1
+ALF                          : 1
+GBi                          : 1 
+GBiFast                      : 1
+BIO                          : 1 
+MHIntra                      : 1
+Triangle                     : 1
+IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 1
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
+MIP                          : 1
+DMVR                         : 1
+SMVD                         : 1
+
+# Fast tools
+PBIntraFast                  : 1
+ISPFast                      : 1
+FastMrg                      : 1
+AMaxBT                       : 1
+FastMIP                      : 0
+FastLFNST		     : 0
+
+# Encoder optimization tools
+AffineAmvrEncOpt             : 1
+MmvdDisNum		     : 6
+### DO NOT ADD ANYTHING BELOW THIS LINE ###
+### DO NOT DELETE THE EMPTY LINE BELOW ###
+
+
+
diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
new file mode 100644
index 000000000..06ddb38c3
--- /dev/null
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
@@ -0,0 +1,184 @@
+#======== File I/O =====================
+BitstreamFile                 : str.bin
+ReconFile                     : rec.yuv
+
+#======== Profile ================
+Profile                       : next
+
+#======== Unit definition ================
+MaxCUWidth                    : 64          # Maximum coding unit width in pixel
+MaxCUHeight                   : 64          # Maximum coding unit height in pixel
+MaxPartitionDepth             : 4           # Maximum coding unit depth
+
+#======== Coding Structure =============
+IntraPeriod                   : 32          # Period of I-Frame ( -1 = only first)
+DecodingRefreshType           : 1           # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI
+GOPSize                       : 16          # GOP Size (number of B slice = GOPSize-1)
+
+IntraQPOffset                 : -3
+LambdaFromQpEnable            : 1           # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled
+#        Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures     predict deltaRPS #ref_idcs reference idcs
+Frame1:  B   16   1        0.0                      0.0            0          0          1.0      0            0              0           2                3         -16 -24 -32            0
+Frame2:  B    8   1       -4.8848                   0.2061         0          0          1.0      0            0              1           2                3         -8  -16   8            1       8        4         1 1 0 1
+Frame3:  B    4   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                4         -4  -12   4  12        1       4        4         1 1 1 1
+Frame4:  B    2   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                5         -2  -10   2   6  14    1       2        5         1 1 1 1 1
+Frame5:  B    1   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1    1  3    7  15    1       1        6         1 0 1 1 1 1
+Frame6:  B    3   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3   1   5  13    1      -2        6         1 1 1 1 1 0
+Frame7:  B    6   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6   2  10        1      -3        6         0 1 1 1 1 0
+Frame8:  B    5   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5   1   3  11    1       1        5         1 1 1 1 1
+Frame9:  B    7   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3  -7   1   9    1      -2        6         1 1 1 1 1 0
+Frame10: B   12   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                3         -4  -12   4            1      -5        6         0 0 1 1 1 0
+Frame11: B   10   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2  -10   2   6        1       2        4         1 1 1 1
+Frame12: B    9   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -9   1   3   7    1       1        5         1 1 1 1 1
+Frame13: B   11   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -11   1   5    1      -2        6         1 1 1 1 1 0
+Frame14: B   14   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6 -14   2        1      -3        6         0 1 1 1 1 0
+Frame15: B   13   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5 -13   1   3    1       1        5         1 1 1 1 1
+Frame16: B   15   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -7  -15   1    1      -2        6         1 1 1 1 1 0
+
+#=========== Motion Search =============
+FastSearch                    : 1           # 0:Full search  1:TZ search
+SearchRange                   : 384         # (0: Search range is a Full frame)
+ASR                           : 1           # Adaptive motion search range
+MinSearchWindow               : 96          # Minimum motion search window size for the adaptive window ME
+BipredSearchRange             : 4           # Search range for bi-prediction refinement
+HadamardME                    : 1           # Use of hadamard measure for fractional ME
+FEN                           : 1           # Fast encoder decision
+FDM                           : 1           # Fast Decision for Merge RD cost
+
+#======== Quantization =============
+QP                            : 32          # Quantization parameter(0-51)
+MaxDeltaQP                    : 0           # CU-based multi-QP optimization
+MaxCuDQPSubdiv                : 0           # Maximum subdiv for CU luma Qp adjustment
+DeltaQpRD                     : 0           # Slice-based multi-QP optimization
+RDOQ                          : 1           # RDOQ
+RDOQTS                        : 1           # RDOQ for transform skip
+
+#=========== Deblock Filter ============
+LoopFilterOffsetInPPS         : 1           # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param)
+LoopFilterDisable             : 0           # Disable deblocking filter (0=Filter, 1=No Filter)
+LoopFilterBetaOffset_div2     : 0           # base_param: -6 ~ 6
+LoopFilterTcOffset_div2       : 0           # base_param: -6 ~ 6
+DeblockingFilterMetric        : 0           # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0)
+
+#=========== Misc. ============
+InternalBitDepth              : 10          # codec operating bit-depth
+
+#=========== Coding Tools =================
+SAO                           : 1           # Sample adaptive offset  (0: OFF, 1: ON)
+TransformSkip                 : 1           # Transform skipping (0: OFF, 1: ON)
+TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1: ON)
+TransformSkipLog2MaxSize      : 5
+SAOLcuBoundary                : 0           # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON)
+
+#============ Slices ================
+SliceMode                : 3                # 0: Disable all slice options.
+                                            # 1: Enforce maximum number of LCU in an slice,
+                                            # 2: Enforce maximum number of bytes in an 'slice'
+                                            # 3: Enforce maximum number of tiles in a slice
+SliceArgument            : 2                # Argument for 'SliceMode'.
+                                            # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice.
+                                            # If SliceMode==2 it represents max. bytes per slice.
+                                            # If SliceMode==3 it represents max. tiles per slice.
+
+LFCrossSliceBoundaryFlag : 1                # In-loop filtering, including ALF and DB, is across or not across slice boundary.
+                                            # 0:not across, 1: across
+
+#============ Tiles ================
+TileUniformSpacing                  : 0                # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array
+                                                       # 1: the column and row boundaries are distributed uniformly
+NumTileColumnsMinus1                : 3                # Number of tile columns in a picture minus 1
+TileColumnWidthArray                : 1 1 1            # Array containing tile column width values in units of CTU (from left to right in picture)   
+NumTileRowsMinus1                   : 1                # Number of tile rows in a picture minus 1
+TileRowHeightArray                  : 1                # Array containing tile row height values in units of CTU (from top to bottom in picture)
+
+LFCrossTileBoundaryFlag             : 0                # In-loop filtering is across or not across tile boundary.
+                                                       # 0:not across, 1: across 
+                                                       
+RectSliceFlag                       : 1                                                      
+NumRectSlicesInPicMinus1            : 3  
+RectSlicesBoundaryArray             : 0 4 1 5 2 6 3 7
+
+#============ PCM ================
+PCMEnabledFlag                      : 0                # 0: No PCM mode
+PCMLog2MaxSize                      : 5                # Log2 of maximum PCM block size.
+PCMLog2MinSize                      : 3                # Log2 of minimum PCM block size.
+PCMInputBitDepthFlag                : 1                # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth.
+PCMFilterDisableFlag                : 0                # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples.
+
+#============ Lossless ================
+TransquantBypassEnable     : 0                         # Value of PPS flag.
+CUTransquantBypassFlagForce: 0                         # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled
+
+#============ Rate Control ======================
+RateControl                         : 0                # Rate control: enable rate control
+TargetBitrate                       : 1000000          # Rate control: target bitrate, in bps
+KeepHierarchicalBit                 : 2                # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation
+LCULevelRateControl                 : 1                # Rate control: 1: LCU level RC; 0: picture level RC
+RCLCUSeparateModel                  : 1                # Rate control: use LCU level separate R-lambda model
+InitialQP                           : 0                # Rate control: initial QP
+RCForceIntraQP                      : 0                # Rate control: force intra QP to be equal to initial QP
+
+#============ VTM settings ======================
+LoopFilterTcOffset_div2             : 0
+SEIDecodedPictureHash               : 0
+CbQpOffset                          : 1
+CrQpOffset                          : 1
+
+ReWriteParamSets                    : 1
+#============ NEXT ====================
+
+# General
+CTUSize                      : 128
+LCTUFast                     : 1
+
+DualITree                    : 1      # separate partitioning of luma and chroma channels for I-slices
+MinQTLumaISlice              : 8
+MinQTChromaISlice            : 4
+MinQTNonISlice               : 8
+MaxBTDepth                   : 3
+MaxBTDepthISliceL            : 3
+MaxBTDepthISliceC            : 3
+
+MTS                          : 1
+MTSIntraMaxCand              : 3
+MTSInterMaxCand              : 4
+SBT                          : 1
+LFNST			     : 1
+ISP                          : 1
+MMVD                         : 1
+Affine                       : 1
+SubPuMvp                     : 1
+MaxNumMergeCand              : 6
+LMChroma                     : 1      # use CCLM only
+DepQuant                     : 1
+IMV                          : 1
+ALF                          : 1
+GBi                          : 1 
+GBiFast                      : 1
+BIO                          : 1 
+MHIntra                      : 1
+Triangle                     : 1
+IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 1
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
+MIP                          : 1
+DMVR                         : 1
+SMVD                         : 1
+
+# Fast tools
+PBIntraFast                  : 1
+ISPFast                      : 1
+FastMrg                      : 1
+AMaxBT                       : 1
+FastMIP                      : 0
+FastLFNST		     : 0
+
+# Encoder optimization tools
+AffineAmvrEncOpt             : 1
+MmvdDisNum		     : 6
+### DO NOT ADD ANYTHING BELOW THIS LINE ###
+### DO NOT DELETE THE EMPTY LINE BELOW ###
+
+
+
diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg
new file mode 100644
index 000000000..24ee96ef3
--- /dev/null
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg
@@ -0,0 +1,184 @@
+#======== File I/O =====================
+BitstreamFile                 : str.bin
+ReconFile                     : rec.yuv
+
+#======== Profile ================
+Profile                       : next
+
+#======== Unit definition ================
+MaxCUWidth                    : 64          # Maximum coding unit width in pixel
+MaxCUHeight                   : 64          # Maximum coding unit height in pixel
+MaxPartitionDepth             : 4           # Maximum coding unit depth
+
+#======== Coding Structure =============
+IntraPeriod                   : 32          # Period of I-Frame ( -1 = only first)
+DecodingRefreshType           : 1           # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI
+GOPSize                       : 16          # GOP Size (number of B slice = GOPSize-1)
+
+IntraQPOffset                 : -3
+LambdaFromQpEnable            : 1           # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled
+#        Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures     predict deltaRPS #ref_idcs reference idcs
+Frame1:  B   16   1        0.0                      0.0            0          0          1.0      0            0              0           2                3         -16 -24 -32            0
+Frame2:  B    8   1       -4.8848                   0.2061         0          0          1.0      0            0              1           2                3         -8  -16   8            1       8        4         1 1 0 1
+Frame3:  B    4   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                4         -4  -12   4  12        1       4        4         1 1 1 1
+Frame4:  B    2   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                5         -2  -10   2   6  14    1       2        5         1 1 1 1 1
+Frame5:  B    1   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1    1  3    7  15    1       1        6         1 0 1 1 1 1
+Frame6:  B    3   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3   1   5  13    1      -2        6         1 1 1 1 1 0
+Frame7:  B    6   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6   2  10        1      -3        6         0 1 1 1 1 0
+Frame8:  B    5   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5   1   3  11    1       1        5         1 1 1 1 1
+Frame9:  B    7   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3  -7   1   9    1      -2        6         1 1 1 1 1 0
+Frame10: B   12   4       -5.7476                   0.2286         0          0          1.0      0            0              2           2                3         -4  -12   4            1      -5        6         0 0 1 1 1 0
+Frame11: B   10   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2  -10   2   6        1       2        4         1 1 1 1
+Frame12: B    9   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -9   1   3   7    1       1        5         1 1 1 1 1
+Frame13: B   11   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -11   1   5    1      -2        6         1 1 1 1 1 0
+Frame14: B   14   5       -5.90                     0.2333         0          0          1.0      0            0              3           2                4         -2   -6 -14   2        1      -3        6         0 1 1 1 1 0
+Frame15: B   13   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -5 -13   1   3    1       1        5         1 1 1 1 1
+Frame16: B   15   6       -7.1444                   0.3            0          0          1.0      0            0              4           2                5         -1   -3 -7  -15   1    1      -2        6         1 1 1 1 1 0
+
+#=========== Motion Search =============
+FastSearch                    : 1           # 0:Full search  1:TZ search
+SearchRange                   : 384         # (0: Search range is a Full frame)
+ASR                           : 1           # Adaptive motion search range
+MinSearchWindow               : 96          # Minimum motion search window size for the adaptive window ME
+BipredSearchRange             : 4           # Search range for bi-prediction refinement
+HadamardME                    : 1           # Use of hadamard measure for fractional ME
+FEN                           : 1           # Fast encoder decision
+FDM                           : 1           # Fast Decision for Merge RD cost
+
+#======== Quantization =============
+QP                            : 32          # Quantization parameter(0-51)
+MaxDeltaQP                    : 0           # CU-based multi-QP optimization
+MaxCuDQPSubdiv                : 0           # Maximum subdiv for CU luma Qp adjustment
+DeltaQpRD                     : 0           # Slice-based multi-QP optimization
+RDOQ                          : 1           # RDOQ
+RDOQTS                        : 1           # RDOQ for transform skip
+
+#=========== Deblock Filter ============
+LoopFilterOffsetInPPS         : 1           # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param)
+LoopFilterDisable             : 0           # Disable deblocking filter (0=Filter, 1=No Filter)
+LoopFilterBetaOffset_div2     : 0           # base_param: -6 ~ 6
+LoopFilterTcOffset_div2       : 0           # base_param: -6 ~ 6
+DeblockingFilterMetric        : 0           # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0)
+
+#=========== Misc. ============
+InternalBitDepth              : 10          # codec operating bit-depth
+
+#=========== Coding Tools =================
+SAO                           : 1           # Sample adaptive offset  (0: OFF, 1: ON)
+TransformSkip                 : 1           # Transform skipping (0: OFF, 1: ON)
+TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1: ON)
+TransformSkipLog2MaxSize      : 5
+SAOLcuBoundary                : 0           # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON)
+
+#============ Slices ================
+SliceMode                : 3                # 0: Disable all slice options.
+                                            # 1: Enforce maximum number of LCU in an slice,
+                                            # 2: Enforce maximum number of bytes in an 'slice'
+                                            # 3: Enforce maximum number of tiles in a slice
+SliceArgument            : 1                # Argument for 'SliceMode'.
+                                            # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice.
+                                            # If SliceMode==2 it represents max. bytes per slice.
+                                            # If SliceMode==3 it represents max. tiles per slice.
+
+LFCrossSliceBoundaryFlag : 1                # In-loop filtering, including ALF and DB, is across or not across slice boundary.
+                                            # 0:not across, 1: across
+
+#============ Tiles ================
+TileUniformSpacing                  : 0                # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array
+                                                       # 1: the column and row boundaries are distributed uniformly
+NumTileColumnsMinus1                : 1                # Number of tile columns in a picture minus 1
+TileColumnWidthArray                : 2                # Array containing tile column width values in units of CTU (from left to right in picture)   
+NumTileRowsMinus1                   : 1                # Number of tile rows in a picture minus 1
+TileRowHeightArray                  : 1                # Array containing tile row height values in units of CTU (from top to bottom in picture)
+
+LFCrossTileBoundaryFlag             : 0                # In-loop filtering is across or not across tile boundary.
+                                                       # 0:not across, 1: across 
+                                                       
+RectSliceFlag                       : 1                                                      
+NumRectSlicesInPicMinus1            : 3  
+RectSlicesBoundaryArray             : 0 0 1 1 2 2 3 3
+
+#============ PCM ================
+PCMEnabledFlag                      : 0                # 0: No PCM mode
+PCMLog2MaxSize                      : 5                # Log2 of maximum PCM block size.
+PCMLog2MinSize                      : 3                # Log2 of minimum PCM block size.
+PCMInputBitDepthFlag                : 1                # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth.
+PCMFilterDisableFlag                : 0                # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples.
+
+#============ Lossless ================
+TransquantBypassEnable     : 0                         # Value of PPS flag.
+CUTransquantBypassFlagForce: 0                         # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled
+
+#============ Rate Control ======================
+RateControl                         : 0                # Rate control: enable rate control
+TargetBitrate                       : 1000000          # Rate control: target bitrate, in bps
+KeepHierarchicalBit                 : 2                # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation
+LCULevelRateControl                 : 1                # Rate control: 1: LCU level RC; 0: picture level RC
+RCLCUSeparateModel                  : 1                # Rate control: use LCU level separate R-lambda model
+InitialQP                           : 0                # Rate control: initial QP
+RCForceIntraQP                      : 0                # Rate control: force intra QP to be equal to initial QP
+
+#============ VTM settings ======================
+LoopFilterTcOffset_div2             : 0
+SEIDecodedPictureHash               : 0
+CbQpOffset                          : 1
+CrQpOffset                          : 1
+
+ReWriteParamSets                    : 1
+#============ NEXT ====================
+
+# General
+CTUSize                      : 128
+LCTUFast                     : 1
+
+DualITree                    : 1      # separate partitioning of luma and chroma channels for I-slices
+MinQTLumaISlice              : 8
+MinQTChromaISlice            : 4
+MinQTNonISlice               : 8
+MaxBTDepth                   : 3
+MaxBTDepthISliceL            : 3
+MaxBTDepthISliceC            : 3
+
+MTS                          : 1
+MTSIntraMaxCand              : 3
+MTSInterMaxCand              : 4
+SBT                          : 1
+LFNST			     : 1
+ISP                          : 1
+MMVD                         : 1
+Affine                       : 1
+SubPuMvp                     : 1
+MaxNumMergeCand              : 6
+LMChroma                     : 1      # use CCLM only
+DepQuant                     : 1
+IMV                          : 1
+ALF                          : 1
+GBi                          : 1 
+GBiFast                      : 1
+BIO                          : 1 
+MHIntra                      : 1
+Triangle                     : 1
+IBC                          : 0      # turned off in CTC
+AllowDisFracMMVD             : 1
+AffineAmvr                   : 1
+LumaReshapeEnable            : 1      # luma reshaping. 0: disable 1:enable 
+MIP                          : 1
+DMVR                         : 1
+SMVD                         : 1
+
+# Fast tools
+PBIntraFast                  : 1
+ISPFast                      : 1
+FastMrg                      : 1
+AMaxBT                       : 1
+FastMIP                      : 0
+FastLFNST		     : 0
+
+# Encoder optimization tools
+AffineAmvrEncOpt             : 1
+MmvdDisNum		     : 6
+### DO NOT ADD ANYTHING BELOW THIS LINE ###
+### DO NOT DELETE THE EMPTY LINE BELOW ###
+
+
+
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index a2d25b91f..74f61785a 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -1662,6 +1662,49 @@ Specifies the maximum number of CTUs, bytes or tiles in a slice depending on the
 SliceMode setting.
 \\
 
+\Option{RectSliceFlag} &
+%\ShortOption{\None} &
+\Default{1} &
+Controls the slice shape method in conjunction with SliceMode,
+SliceArgument, and Tile/Brick configurations.
+\par
+\begin{tabular}{cp{0.45\textwidth}}
+ 0 & Raster scan slice. Bricks within slice are in raster scan order  \\
+ 1 & Rectangular slice. Bricks within slice form rectangular shape \\
+ NOTE: When SliceMode is equal to 3, RectSliceFlag is equal to 1, 
+ and there is more than one tiles/bricks in the pic, 
+ NumRecSliceInPicMinus1 must be greater than 0
+\end{tabular}
+\\
+
+\Option{NumRecSlicesInPicMinus1} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies the number of rectangular slices in the picture.
+\\
+
+\Option{RectSlicesBoundaryArray} &
+%\ShortOption{\None} &
+\Default{\NotSet} &
+Specifies a space or comma separated list of top-left brick index and 
+bottom-right brick index of rectangular slices.
+The top-left brick index and bottom-right brick index corresponds to the top left 
+rectangular slice in the picture. The rest of indices corresponds to the each rectangular slices
+in the picture in the rectangular slice raster scan in the picture, respectively.
+
+For example, when the picture is partitioned into 16 tiles (4 tile columns and 4 tile rows), 
+each tile is not further partitioned into bricks, SliceMode is equal to 3, SliceArgument is equal to 4, 
+and NumRecSlicesInPicMinus1 is equal to 3, the values of RectSlicesBoundaryArray shall be as followss: 
+0 5 2 7 8 13 10 15.
+\par
+\begin{tabular}{cp{0.45\textwidth}}
+ First  slice has top-left brick index 0  and bottom-right brick index 5 \\
+ Second slice has top-left brick index 2  and bottom-right brick index 7 \\
+ Third  slice has top-left brick index 8  and bottom-right brick index 13 \\
+ Fourth slice has top-left brick index 10 and bottom-right brick index 15
+\end{tabular}
+\\
+
 \Option{WaveFrontSynchro} &
 %\ShortOption{\None} &
 \Default{false} &
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index bfa865126..7f6b2add4 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -538,8 +538,13 @@ void EncApp::xInitLibCfg()
 #if JVET_N0857_TILES_BRICKS
   m_cEncLib.setRectSliceFlag                                     ( m_rectSliceFlag );
   m_cEncLib.setNumSlicesInPicMinus1                              ( m_numSlicesInPicMinus1 );
+#if JVET_N0857_RECT_SLICES
+  m_cEncLib.setTopLeftBrickIdx                                   ( m_topLeftBrickIdx );
+  m_cEncLib.setBottomRightBrickIdx                               ( m_bottomRightBrickIdx);
+#else
   m_cEncLib.setTopLeftTileIdx                                    ( m_topLeftTileIdx );
   m_cEncLib.setBottomRightTileIdx                                ( m_bottomRightTileIdx );
+#endif
   m_cEncLib.setLoopFilterAcrossSlicesEnabledFlag                 ( m_loopFilterAcrossSlicesEnabledFlag );
   m_cEncLib.setSignalledSliceIdFlag                              ( m_signalledSliceIdFlag ),
   m_cEncLib.setSignalledSliceIdLengthMinus1                      ( m_signalledSliceIdLengthMinus1 );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index ccfd68e26..89f69c9ea 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -729,8 +729,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   SMultiValueInput<int>  cfg_targetPivotValue                (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
 
 #if JVET_N0857_TILES_BRICKS
+#if JVET_N0857_RECT_SLICES
+  SMultiValueInput<uint32_t> cfg_SliceIdx                    (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+  SMultiValueInput<uint32_t> cfg_SignalledSliceId            (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+#else
   SMultiValueInput<uint32_t> cfg_TileGroupIdx                (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
   SMultiValueInput<uint32_t> cfg_SignalledTileGroupId        (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+#endif
 #endif
 
   SMultiValueInput<double> cfg_adIntraLambdaModifier         (0, std::numeric_limits<double>::max(), 0, MAX_TLAYER); ///< Lambda modifier for Intra pictures, one for each temporal layer. If size>temporalLayer, then use [temporalLayer], else if size>0, use [size()-1], else use m_adLambdaModifier.
@@ -1164,14 +1169,24 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("WaveFrontSynchro",                                m_entropyCodingSyncEnabledFlag,                   false, "0: entropy coding sync disabled; 1 entropy coding sync enabled")
 
 #if JVET_N0857_TILES_BRICKS
+#if JVET_N0857_RECT_SLICES
+  ("RectSliceFlag",                                   m_rectSliceFlag,                                  true, "Rectangular slice flag")
+  ("NumRectSlicesInPicMinus1",                        m_numSlicesInPicMinus1,                              0, "Number slices in pic minus 1")
+#else
   ("RectTileGroupFlag",                               m_rectSliceFlag,                                  true, "Rectangular tile group flag")
   ("SlicesInPicMinus1",                               m_numSlicesInPicMinus1,                               0, "Number tile groups in pic minus 1")
+#endif
   ("LoopFilterAcrossTileGroupsEnabledFlag",           m_loopFilterAcrossSlicesEnabledFlag,              false, "Loop Filter Across Tile Groups Flag")
   ("SignalledIdFlag",                                 m_signalledSliceIdFlag,                           false, "Signalled Slice ID Flag")
   ("SignalledSliceIdLengthMinus1",                    m_signalledSliceIdLengthMinus1,                       0, "Signalled Tile Group Length minus 1")
+#if JVET_N0857_RECT_SLICES
+  ("RectSlicesBoundaryArray",                         cfg_SliceIdx,                              cfg_SliceIdx, "Rectangular slices boundaries in Pic")
+  ("SignalledSliceId",                                cfg_SignalledSliceId,                       cfg_SliceIdx, "Signalled rectangular slice ID")
+#else
   ("TileGroupsInPic",                                 cfg_TileGroupIdx,                      cfg_TileGroupIdx, "Tile Groups In Pic")
   ("SignalledTileGroupId",                            cfg_SignalledTileGroupId,              cfg_TileGroupIdx, "Signalled Tile Group ID")
 #endif
+#endif
 
 #if HEVC_USE_SCALING_LISTS
   ("ScalingList",                                     m_useScalingListId,                    SCALING_LIST_OFF, "0/off: no scaling list, 1/default: default scaling lists, 2/file: scaling lists specified in ScalingListFile")
@@ -1760,8 +1775,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 
 
 #if JVET_N0857_TILES_BRICKS
+#if JVET_N0857_RECT_SLICES
+  m_topLeftBrickIdx.clear();
+  m_bottomRightBrickIdx.clear();
+#else
   m_topLeftTileIdx.clear();
   m_bottomRightTileIdx.clear();
+#endif
   m_sliceId.clear();
 
   bool singleTileInPicFlag = (m_numTileRowsMinus1 == 0 && m_numTileColumnsMinus1 == 0);
@@ -1771,6 +1791,18 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     //if (!m_singleBrickPerSliceFlag && m_rectSliceFlag)
     if (m_sliceMode != 0 && m_sliceMode != 4 && m_rectSliceFlag)
     {
+#if JVET_N0857_RECT_SLICES
+      int numSlicesInPic = m_numSlicesInPicMinus1 + 1;
+
+      if (cfg_SliceIdx.values.size() > numSlicesInPic * 2)
+      {
+        EXIT("Error: The number of slice indices (RectSlicesBoundaryInPic) is greater than the NumSlicesInPicMinus1.");
+      }
+      else if (cfg_SliceIdx.values.size() < numSlicesInPic * 2)
+      {
+        EXIT("Error: The number of slice indices (RectSlicesBoundaryInPic) is less than the NumSlicesInPicMinus1.");
+      }
+#else
       int numTileGroupsInPic = m_numSlicesInPicMinus1 + 1;
 
       if (cfg_TileGroupIdx.values.size() > numTileGroupsInPic * 2)
@@ -1781,19 +1813,132 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
       {
         EXIT("Error: The number of Tile group indexs are less than the numTileGroupsInPicMinus1.");
       }
+#endif
       else
       {
+#if JVET_N0857_RECT_SLICES
+        m_topLeftBrickIdx.resize(numSlicesInPic);
+        m_bottomRightBrickIdx.resize(numSlicesInPic);
+        for (uint32_t i = 0; i < numSlicesInPic; ++i)
+        {
+          m_topLeftBrickIdx[i] = cfg_SliceIdx.values[i * 2];
+          m_bottomRightBrickIdx[i] = cfg_SliceIdx.values[i * 2 + 1];
+#else
         m_topLeftTileIdx.resize(numTileGroupsInPic);
         m_bottomRightTileIdx.resize(numTileGroupsInPic);
         for (uint32_t i = 0; i < numTileGroupsInPic; ++i)
         {
           m_topLeftTileIdx[i] = cfg_TileGroupIdx.values[i * 2];
           m_bottomRightTileIdx[i] = cfg_TileGroupIdx.values[i * 2 + 1];
+#endif
         }
+#if JVET_N0857_RECT_SLICES
+        //Validating the correctness of rectangular slice structure
+        int **brickToSlice = (int **)malloc(sizeof(int *) * (m_numTileRowsMinus1 + 1));
+        for (int i = 0; i <= m_numTileRowsMinus1; i++)
+        {
+          brickToSlice[i] = (int *)malloc(sizeof(int) * (m_numTileColumnsMinus1 + 1));
+          memset(brickToSlice[i], -1, sizeof(int) * ((m_numTileColumnsMinus1 + 1)));
+        }
+
+        //Check overlap case
+        for (int sliceIdx = 0; sliceIdx < numSlicesInPic; sliceIdx++)
+        {
+          int sliceStartRow = m_topLeftBrickIdx[sliceIdx] / (m_numTileColumnsMinus1 + 1);
+          int sliceEndRow   = m_bottomRightBrickIdx[sliceIdx] / (m_numTileColumnsMinus1 + 1);
+          int sliceStartCol = m_topLeftBrickIdx[sliceIdx] % (m_numTileColumnsMinus1 + 1);
+          int sliceEndCol   = m_bottomRightBrickIdx[sliceIdx] % (m_numTileColumnsMinus1 + 1);
+          for (int i = 0; i <= m_numTileRowsMinus1; i++)
+          {
+            for (int j = 0; j <= m_numTileColumnsMinus1; j++)
+            {
+              if (i >= sliceStartRow && i <= sliceEndRow && j >= sliceStartCol && j <= sliceEndCol)
+              {
+                if (brickToSlice[i][j] != -1)
+                {
+                  msg(ERROR, "Error: Values given in RectSlicesBoundaryInPic have conflict! Rectangular slice shall not have overlapped tile(s)\n");
+                  EXIT(1);
+                }
+                else
+                {
+                  brickToSlice[i][j] = sliceIdx;
+                }
+              }
+            }
+          }
+          //Check violation to number of tiles per slice
+          if (m_sliceMode == 3 && m_rectSliceFlag)
+          {
+            if ((sliceEndRow - sliceStartRow + 1) * (sliceEndCol - sliceStartCol + 1) > m_sliceArgument)
+            {
+              EXIT("Error: One or more slices contain more tiles than the defined number of tiles per slice");
+            }
+            if ((sliceEndRow - sliceStartRow + 1) * (sliceEndCol - sliceStartCol + 1) < m_sliceArgument)
+            {
+              //Allow less number of tiles only when the rectangular slice is at the right most or bottom most of the picture
+              if (sliceEndRow != m_numTileRowsMinus1 || sliceEndCol != m_numTileColumnsMinus1)
+              {
+                EXIT("Error: One or more slices that is not at the picture boundary contain less tiles than the defined number of tiles per slice");
+              }
+            }
+          }
+        }
+        //Check gap case
+        for (int i = 0; i <= m_numTileRowsMinus1; i++)
+        {
+          for (int j = 0; j <= m_numTileColumnsMinus1; j++)
+          {
+            if (brickToSlice[i][j] == -1)
+            {
+              EXIT("Error: Values given in RectSlicesBoundaryInPic have conflict! Rectangular slice shall not have gap");
+            }
+          }
+        }
+
+        for (int i = 0; i <= m_numTileRowsMinus1; i++)
+        {
+          free(brickToSlice[i]);
+          brickToSlice[i] = 0;
+        }
+        free(brickToSlice);
+        brickToSlice = 0;
+#endif
       }
     }      // (!m_singleBrickPerSliceFlag && m_rectSliceFlag)
   }        // !singleTileInPicFlag
 
+#if JVET_N0857_RECT_SLICES
+  if (m_rectSliceFlag && m_signalledSliceIdFlag)
+  {
+    int numSlicesInPic = m_numSlicesInPicMinus1 + 1;
+
+    if (cfg_SignalledSliceId.values.size() > numSlicesInPic)
+    {
+      EXIT("Error: The number of Slice Ids are greater than the m_signalledTileGroupIdLengthMinus1.");
+    }
+    else if (cfg_SignalledSliceId.values.size() < numSlicesInPic)
+    {
+      EXIT("Error: The number of Slice Ids are less than the m_signalledTileGroupIdLengthMinus1.");
+    }
+    else
+    {
+      m_sliceId.resize(numSlicesInPic);
+      for (uint32_t i = 0; i < cfg_SignalledSliceId.values.size(); ++i)
+      {
+        m_sliceId[i] = cfg_SignalledSliceId.values[i];
+      }
+    }
+  }
+  else if (m_rectSliceFlag)
+  {
+    int numSlicesInPic = m_numSlicesInPicMinus1 + 1;
+    m_sliceId.resize(numSlicesInPic);
+    for (uint32_t i = 0; i < numSlicesInPic; ++i)
+    {
+      m_sliceId[i] = i;
+    }
+  }
+#else
   if (m_rectSliceFlag && m_signalledSliceIdFlag)
   {
     int numTileGroupsInPic = m_numSlicesInPicMinus1 + 1;
@@ -1815,6 +1960,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
       }
     }
   }
+#endif
 #endif
 
   if (tmpDecodedPictureHashSEIMappedType<0 || tmpDecodedPictureHashSEIMappedType>=int(NUMBER_OF_HASHTYPES))
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 3845bb4c0..07789ce25 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -444,8 +444,13 @@ protected:
 #if JVET_N0857_TILES_BRICKS
   bool      m_rectSliceFlag;
   int       m_numSlicesInPicMinus1;
+#if JVET_N0857_RECT_SLICES
+  std::vector<int> m_topLeftBrickIdx;
+  std::vector<int> m_bottomRightBrickIdx;
+#else
   std::vector<int> m_topLeftTileIdx;
   std::vector<int> m_bottomRightTileIdx;
+#endif
   bool      m_loopFilterAcrossSlicesEnabledFlag;
   bool      m_signalledSliceIdFlag;
   int       m_signalledSliceIdLengthMinus1;
diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp
index bb6f019df..de8e1bff9 100644
--- a/source/App/Parcat/parcat.cpp
+++ b/source/App/Parcat/parcat.cpp
@@ -59,7 +59,9 @@ bool ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parame
   SPS* sps = NULL;
 
   uint32_t firstSliceSegmentInPic;
+#if !JVET_N0857_RECT_SLICES
   READ_FLAG( firstSliceSegmentInPic, "first_slice_segment_in_pic_flag" );
+#endif
   if( isRapPic )
   {
     READ_FLAG( uiCode, "no_output_of_prior_pics_flag" );  //ignored -- updated already
@@ -72,6 +74,7 @@ bool ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parame
   //!KS: need to add error handling code here, if SPS is not available
   CHECK(sps==0, "Invalid SPS");
 
+#if !JVET_N0857_RECT_SLICES
   int numCTUs = ((sps->getPicWidthInLumaSamples()+sps->getMaxCUWidth()-1)/sps->getMaxCUWidth())*((sps->getPicHeightInLumaSamples()+sps->getMaxCUHeight()-1)/sps->getMaxCUHeight());
   uint32_t sliceSegmentAddress = 0;
   int bitsSliceSegmentAddress = 0;
@@ -84,6 +87,48 @@ bool ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parame
   {
     READ_CODE( bitsSliceSegmentAddress, sliceSegmentAddress, "slice_segment_address" );
   }
+#endif
+#if JVET_N0857_RECT_SLICES
+  int bitsSliceAddress = 1;
+  if (!pps->getRectSliceFlag())
+  {
+    while (pps->getNumTilesInPic() > (1 << bitsSliceAddress))
+    {
+      bitsSliceAddress++;
+    }
+  }
+  else
+  {
+    if (pps->getSignalledSliceIdFlag())
+    {
+      bitsSliceAddress = pps->getSignalledSliceIdLengthMinus1() + 1;
+    }
+    else
+    {
+      while ((pps->getNumSlicesInPicMinus1() + 1) > (1 << bitsSliceAddress))
+      {
+        bitsSliceAddress++;
+      }
+    }
+  }
+  uiCode = 0;
+  if (pps->getRectSliceFlag() || pps->getNumTilesInPic() > 1)   //TODO: change it to getNumBricksInPic when Tile/Brick is updated.
+  {
+    if (pps->getRectSliceFlag())
+    {
+      READ_CODE(bitsSliceAddress, uiCode, "slice_address");
+    }
+    else
+    {
+      READ_CODE(bitsSliceAddress, uiCode, "slice_address");
+    }
+  }
+  firstSliceSegmentInPic = (uiCode == 0) ? 1 : 0;       //May not work when sliceID is not the same as sliceIdx
+  if (!pps->getRectSliceFlag() && !pps->getSingleBrickPerSliceFlag())
+  {
+    READ_UVLC(uiCode, "num_bricks_in_slice_minus1");
+  }
+#endif
   //set uiCode to equal slice start address (or dependent slice start address)
   for (int i = 0; i < pps->getNumExtraSliceHeaderBits(); i++)
   {
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 503a0780b..4ed925063 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1978,6 +1978,10 @@ PPS::PPS()
 , m_singleBrickPerSliceFlag          (true)
 , m_rectSliceFlag                    (true)
 , m_numSlicesInPicMinus1             (0)
+#if JVET_N0857_RECT_SLICES
+, m_numTilesInPic                    (1)
+, m_numBricksInPic                   (1)
+#endif
 , m_signalledSliceIdFlag             (false)
 ,m_signalledSliceIdLengthMinus1      (0)
 #endif
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 978d223b4..826a9c22b 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1685,8 +1685,16 @@ private:
   bool             m_singleBrickPerSliceFlag;
   bool             m_rectSliceFlag;
   int              m_numSlicesInPicMinus1;
+#if JVET_N0857_RECT_SLICES
+  std::vector<int> m_topLeftBrickIdx;
+  std::vector<int> m_bottomRightBrickIdx;
+
+  int              m_numTilesInPic;
+  int              m_numBricksInPic;
+#else
   std::vector<int> m_topLeftTileIdx;
   std::vector<int> m_bottomRightTileIdx;
+#endif
   bool             m_signalledSliceIdFlag;
   int              m_signalledSliceIdLengthMinus1;
   std::vector<int> m_sliceId;
@@ -1836,10 +1844,21 @@ public:
   void                   setRectSliceFlag(bool val)                                       { m_rectSliceFlag = val;                        }
   int                    getNumSlicesInPicMinus1() const                                  { return m_numSlicesInPicMinus1;                }
   void                   setNumSlicesInPicMinus1(int val)                                 { m_numSlicesInPicMinus1 = val;                 }
+#if JVET_N0857_RECT_SLICES
+  int                    getTopLeftBrickIdx(uint32_t columnIdx) const                     { return  m_topLeftBrickIdx[columnIdx];         }
+  void                   setTopLeftBrickIdx(const std::vector<int>& val)                  { m_topLeftBrickIdx = val;                      }
+  int                    getBottomRightBrickIdx(uint32_t columnIdx) const                 { return  m_bottomRightBrickIdx[columnIdx];     }
+  void                   setBottomRightBrickIdx(const std::vector<int>& val)              { m_bottomRightBrickIdx = val;                  }
+  int                    getNumTilesInPic() const                                         { return m_numTilesInPic;                       }
+  void                   setNumTilesInPic(int val)                                        { m_numTilesInPic = val;                        }
+  int                    getNumBricksInPic() const                                        { return m_numBricksInPic;                      }
+  void                   setNumBricksInPic(int val)                                       { m_numBricksInPic = val;                       }
+#else
   int                    getTopLeftTileIdx(uint32_t columnIdx) const                      { return  m_topLeftTileIdx[columnIdx];          }
   void                   setTopLeftTileIdx(const std::vector<int>& val)                   { m_topLeftTileIdx = val;                       }
   int                    getBottomeRightTileIdx(uint32_t columnIdx) const                 { return  m_bottomRightTileIdx[columnIdx];      }
   void                   setBottomRightTileIdx(const std::vector<int>& val)               { m_bottomRightTileIdx = val;                   }
+#endif
   bool                   getSignalledSliceIdFlag() const                                  { return m_signalledSliceIdFlag;                }
   void                   setSignalledSliceIdFlag(bool val)                                { m_signalledSliceIdFlag = val;                 }
   int                    getSignalledSliceIdLengthMinus1() const                          { return m_signalledSliceIdLengthMinus1;        }
@@ -2029,6 +2048,13 @@ private:
   uint32_t                       m_sliceBits;
   bool                       m_bFinalized;
 
+#if JVET_N0857_RECT_SLICES
+  uint32_t                   m_sliceCurStartBrickIdx;
+  uint32_t                   m_sliceCurEndBrickIdx;
+  uint32_t                   m_sliceNumBricks;
+  uint32_t                   m_sliceIdx;
+#endif
+
   bool                       m_bTestWeightPred;
   bool                       m_bTestWeightBiPred;
   WPScalingParam             m_weightPredTable[NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_COMPONENT]; // [REF_PIC_LIST_0 or REF_PIC_LIST_1][refIdx][0:Y, 1:U, 2:V]
@@ -2304,6 +2330,16 @@ public:
   uint32_t                        getSliceBits() const                                   { return m_sliceBits;                                           }
   void                        setFinalized( bool uiVal )                             { m_bFinalized = uiVal;                                         }
   bool                        getFinalized() const                                   { return m_bFinalized;                                          }
+#if JVET_N0857_RECT_SLICES
+  void                        setSliceCurStartBrickIdx(uint32_t brickIdx)            { m_sliceCurStartBrickIdx = brickIdx;                           }
+  uint32_t                    getSliceCurStartBrickIdx() const                       { return m_sliceCurStartBrickIdx;                               }
+  void                        setSliceCurEndBrickIdx(uint32_t brickIdx)              { m_sliceCurEndBrickIdx = brickIdx;                             }
+  uint32_t                    getSliceCurEndBrickIdx() const                         { return m_sliceCurEndBrickIdx;                                 }
+  void                        setSliceNumBricks(uint32_t numBricks)                  { m_sliceNumBricks = numBricks;                                 }
+  uint32_t                    getSliceNumBricks() const                              { return m_sliceNumBricks;                                      }
+  void                        setSliceIndex(uint32_t idx)                            { m_sliceIdx = idx;                                             }
+  uint32_t                    setSliceIndex() const                                  { return m_sliceIdx;                                            }
+#endif
   bool                        testWeightPred( ) const                                { return m_bTestWeightPred;                                     }
   void                        setTestWeightPred( bool bValue )                       { m_bTestWeightPred = bValue;                                   }
   bool                        testWeightBiPred( ) const                              { return m_bTestWeightBiPred;                                   }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index fa95f52ee..ac6881bb3 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -98,6 +98,7 @@
 #define JVET_N0308_MAX_CU_SIZE_FOR_ISP                    1
 
 #define JVET_N0857_TILES_BRICKS                           1 // VTM-5 basic Slices/Tiles/Bricks design, rectangular slices not supported yet
+#define JVET_N0857_RECT_SLICES                            1 // Support for rectangular slices and raster-scan slices (i.e., multiple tiles/brick in a slice)
 
 #if JVET_N0857_TILES_BRICKS
 #define JVET_N0124_PROPOSAL1                              1   // JVET-N0124 Proposal 1
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 5794de442..6fa1888a8 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -833,6 +833,9 @@ void DecLib::xActivateParameterSets()
     m_apcSlicePilot->applyReferencePictureSet(m_cListPic, m_apcSlicePilot->getRPS());
 #if JVET_N0415_CTB_ALF
     m_pcPic->finalInit(*sps, *pps, apss);
+#if JVET_N0857_RECT_SLICES
+    m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size());
+#endif
 #else
     m_pcPic->finalInit(*sps, *pps, *aps);
 #endif
@@ -1224,6 +1227,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 #else
   const TileMap& tileMap = *(m_pcPic->tileMap);
 #endif
+#if !JVET_N0857_RECT_SLICES
 #if JVET_N0857_TILES_BRICKS
     pcSlice->setSliceCurStartCtuTsAddr( tileMap.getCtuRsToBsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()) );
     pcSlice->setSliceCurEndCtuTsAddr( tileMap.getCtuRsToBsAddrMap(pcSlice->getSliceCurEndCtuTsAddr()) );
@@ -1231,7 +1235,32 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     pcSlice->setSliceCurStartCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()) );
     pcSlice->setSliceCurEndCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceCurEndCtuTsAddr()) );
 #endif
+#else
+  const uint32_t numberOfCtusInFrame = m_pcPic->cs->pcv->sizeInCtus;
 
+  uint32_t startCtuIdx = 0;
+  while (pcSlice->getSliceCurStartBrickIdx() != tileMap.getBrickIdxBsMap(startCtuIdx) && startCtuIdx < numberOfCtusInFrame)
+  {
+    startCtuIdx++;
+  }
+  uint32_t endCtuIdx = startCtuIdx;
+  while (pcSlice->getSliceCurEndBrickIdx() != tileMap.getBrickIdxBsMap(endCtuIdx) && endCtuIdx < numberOfCtusInFrame)
+  {
+    endCtuIdx++;
+  }
+  if (endCtuIdx == numberOfCtusInFrame)
+    EXIT("Cannot find the last CTU index of the current slice");
+
+  while (pcSlice->getSliceCurEndBrickIdx() == tileMap.getBrickIdxBsMap(endCtuIdx) && endCtuIdx < numberOfCtusInFrame)
+  {
+    endCtuIdx++;
+  }
+  if (pcSlice->getSliceCurEndBrickIdx() != tileMap.getBrickIdxBsMap(endCtuIdx - 1))
+    EXIT("Cannot find the last CTU index of the current slice");
+
+  pcSlice->setSliceCurStartCtuTsAddr(startCtuIdx);
+  pcSlice->setSliceCurEndCtuTsAddr(endCtuIdx);
+#endif
 
     pcSlice->checkCRA(pcSlice->getRPS(), m_pocCRA, m_associatedIRAPType, m_cListPic );
     // Set reference list
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index 908ee6439..e4fd15237 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -121,9 +121,7 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
   }
 
   const int       startCtuTsAddr          = slice->getSliceCurStartCtuTsAddr();
-#if JVET_N0857_TILES_BRICKS
-  const int       startCtuRsAddr          = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr);
-#else
+#if !JVET_N0857_TILES_BRICKS
   const int       startCtuRsAddr          = tileMap.getCtuTsToRsAddrMap(startCtuTsAddr);
 #endif
 
@@ -140,12 +138,21 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 
   DTRACE( g_trace_ctx, D_HEADER, "=========== POC: %d ===========\n", slice->getPOC() );
 
+#if !JVET_N0857_RECT_SLICES
   // The first CTU of the slice is the first coded substream, but the global substream number, as calculated by getSubstreamForCtuAddr may be higher.
   // This calculates the common offset for all substreams in this slice.
   const unsigned  subStreamOffset         = tileMap.getSubstreamForCtuAddr(startCtuRsAddr, true, slice);
+#endif
 
   // for every CTU in the slice segment...
   bool isLastCtuOfSliceSegment = false;
+#if JVET_N0857_RECT_SLICES
+  uint32_t startSliceRsRow = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) / widthInCtus;
+  uint32_t startSliceRsCol = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) % widthInCtus;
+  uint32_t endSliceRsRow = tileMap.getCtuBsToRsAddrMap(slice->getSliceCurEndCtuTsAddr() - 1) / widthInCtus;
+  uint32_t endSliceRsCol = tileMap.getCtuBsToRsAddrMap(slice->getSliceCurEndCtuTsAddr() - 1) % widthInCtus;
+  unsigned subStrmId = 0;
+#endif
   for( unsigned ctuTsAddr = startCtuTsAddr; !isLastCtuOfSliceSegment && ctuTsAddr < numCtusInFrame; ctuTsAddr++ )
   {
 #if JVET_N0857_TILES_BRICKS
@@ -154,13 +161,21 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 #else
     const unsigned  ctuRsAddr             = tileMap.getCtuTsToRsAddrMap(ctuTsAddr);
     const Tile&     currentTile           = tileMap.tiles[ tileMap.getTileIdxMap(ctuRsAddr) ];
+#endif
+#if JVET_N0857_RECT_SLICES
+    if (slice->getPPS()->getRectSliceFlag() &&
+      ((ctuRsAddr / widthInCtus) < startSliceRsRow || (ctuRsAddr / widthInCtus) > endSliceRsRow ||
+      (ctuRsAddr % widthInCtus) < startSliceRsCol || (ctuRsAddr % widthInCtus) > endSliceRsCol))
+      continue;
 #endif
     const unsigned  firstCtuRsAddrOfTile  = currentTile.getFirstCtuRsAddr();
     const unsigned  tileXPosInCtus        = firstCtuRsAddrOfTile % widthInCtus;
     const unsigned  tileYPosInCtus        = firstCtuRsAddrOfTile / widthInCtus;
     const unsigned  ctuXPosInCtus         = ctuRsAddr % widthInCtus;
     const unsigned  ctuYPosInCtus         = ctuRsAddr / widthInCtus;
+#if !JVET_N0857_RECT_SLICES
     const unsigned  subStrmId             = tileMap.getSubstreamForCtuAddr( ctuRsAddr, true, slice ) - subStreamOffset;
+#endif
     const unsigned  maxCUSize             = sps->getMaxCUWidth();
     Position pos( ctuXPosInCtus*maxCUSize, ctuYPosInCtus*maxCUSize) ;
     UnitArea ctuArea(cs.area.chromaFormat, Area( pos.x, pos.y, maxCUSize, maxCUSize ) );
@@ -266,6 +281,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
       CHECK( !binVal, "Expecting a terminating bit" );
 #if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES
       cabacReader.remaining_bytes( true );
+#endif
+#if JVET_N0857_RECT_SLICES
+      subStrmId++;
 #endif
     }
   }
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index b4c43fb88..2d4bf4c3b 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -497,6 +497,9 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
     READ_FLAG( uiCode, "brick_splitting_present_flag" );                 pcPPS->setBrickSplittingPresentFlag(uiCode == 1);
 
     int numTilesInPic = pcPPS->getUniformTileSpacingFlag() ? 0 : (pcPPS->getNumTileColumnsMinus1() + 1) * (pcPPS->getNumTileRowsMinus1() + 1);
+#if JVET_N0857_RECT_SLICES
+    pcPPS->setNumTilesInPic(numTilesInPic);
+#endif
 
     if (pcPPS->getBrickSplittingPresentFlag())
     {
@@ -571,7 +574,11 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
             READ_CODE( codeLength, uiCode, "top_left_brick_idx" );
             topLeft[i] = uiCode;
 #if JVET_N0124_PROPOSAL2
+#if JVET_N0857_RECT_SLICES
+            codeLength2 = (int)ceil(log2((numTilesInPic - topLeft[i] < 2) ? 2 : numTilesInPic - topLeft[i]));  //Bugfix
+#else
             codeLength2 = (int)ceil(log2(numTilesInPic - topLeft[i]));
+#endif
 #endif
           }
 #if JVET_N0124_PROPOSAL2
@@ -581,10 +588,29 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
 #endif
           bottomRight[i] = topLeft[i] + uiCode;
         }
+#if JVET_N0857_RECT_SLICES
+        pcPPS->setTopLeftBrickIdx(topLeft);
+        pcPPS->setBottomRightBrickIdx(bottomRight);
+#else
         pcPPS->setTopLeftTileIdx(topLeft);
         pcPPS->setBottomRightTileIdx(bottomRight);
+#endif
+      }
+    }
+#if JVET_N0857_RECT_SLICES
+    if (pcPPS->getRectSliceFlag() && pcPPS->getSingleBrickPerSliceFlag())
+    {
+      std::vector<int> topLeft(numTilesInPic);  //TODO: this should be numBricksInPic. Fix it when the bricks codes have been updated
+      std::vector<int> bottomRight(numTilesInPic);
+      for (uint32_t i = 0; i < numTilesInPic; i++)
+      {
+        topLeft[i] = i;
+        bottomRight[i] = i;
       }
+      pcPPS->setTopLeftBrickIdx(topLeft);
+      pcPPS->setBottomRightBrickIdx(bottomRight);
     }
+#endif
 
     READ_FLAG( uiCode, "loop_filter_across_bricks_enabled_flag ");        pcPPS->setLoopFilterAcrossBricksEnabledFlag(uiCode ? true : false);
     if (pcPPS->getLoopFilterAcrossBricksEnabledFlag())
@@ -598,6 +624,14 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
     pcPPS->setSingleBrickPerSliceFlag(true);
 #endif
     pcPPS->setRectSliceFlag(true);
+#if JVET_N0857_RECT_SLICES
+    std::vector<int> topLeft(1);
+    topLeft[0] = 0;
+    std::vector<int> bottomRight(1);
+    bottomRight[0] = 0;
+    pcPPS->setTopLeftBrickIdx(topLeft);
+    pcPPS->setBottomRightBrickIdx(bottomRight);
+#endif
   }
 
   if (pcPPS->getRectSliceFlag())
@@ -606,6 +640,20 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
     if (pcPPS->getSignalledSliceIdFlag())
     {
       READ_UVLC( uiCode, "signalled_slice_id_length_minus1" );             pcPPS->setSignalledSliceIdLengthMinus1(uiCode);
+#if JVET_N0857_RECT_SLICES
+      const uint32_t numSlices = pcPPS->getNumSlicesInPicMinus1() + 1;
+      int codeLength = pcPPS->getSignalledSliceIdLengthMinus1() + 1;
+      if (numSlices > 0)
+      {
+        std::vector<int> sliceID(numSlices);
+        for (uint32_t i = 0; i < numSlices; i++)
+        {
+          READ_CODE(codeLength, uiCode, "slice_id");
+          sliceID[i] = uiCode;
+        }
+        pcPPS->setSliceId(sliceID);
+      }
+#else
       const uint32_t numTileGroups = pcPPS->getNumSlicesInPicMinus1() + 1;
       int codeLength = pcPPS->getSignalledSliceIdLengthMinus1() + 1;
       if (numTileGroups > 0)
@@ -618,7 +666,19 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
         }
         pcPPS->setSliceId(tileGroupID);
       }
+#endif
+    }
+#if JVET_N0857_RECT_SLICES
+    else
+    {
+      std::vector<int> sliceID(pcPPS->getNumSlicesInPicMinus1() + 1);
+      for (uint32_t i = 0; i <= pcPPS->getNumSlicesInPicMinus1(); i++)
+      {
+        sliceID[i] = i;
+      }
+      pcPPS->setSliceId(sliceID);
     }
+#endif
   }
 #endif
 
@@ -1750,8 +1810,10 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
   PPS* pps = NULL;
   SPS* sps = NULL;
 
+#if !JVET_N0857_RECT_SLICES
   uint32_t firstSliceSegmentInPic;
   READ_FLAG( firstSliceSegmentInPic, "first_slice_segment_in_pic_flag" );
+#endif
   if( pcSlice->getRapPicFlag())
   {
     READ_FLAG( uiCode, "no_output_of_prior_pics_flag" );  //ignored -- updated already
@@ -1769,6 +1831,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
   const uint32_t numValidComp=getNumberValidComponents(chFmt);
   const bool bChroma=(chFmt!=CHROMA_400);
 
+#if !JVET_N0857_RECT_SLICES
   int numCTUs = ((sps->getPicWidthInLumaSamples()+sps->getMaxCUWidth()-1)/sps->getMaxCUWidth())*((sps->getPicHeightInLumaSamples()+sps->getMaxCUHeight()-1)/sps->getMaxCUHeight());
   uint32_t sliceSegmentAddress = 0;
   int bitsSliceSegmentAddress = 0;
@@ -1784,6 +1847,58 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
   //set uiCode to equal slice start address (or dependent slice start address)
     pcSlice->setSliceCurStartCtuTsAddr(sliceSegmentAddress); // this is actually a Raster-Scan (RS) address, but we do not have the RS->TS conversion table defined yet.
     pcSlice->setSliceCurEndCtuTsAddr(numCTUs);
+#endif
+#if JVET_N0857_RECT_SLICES
+    int bitsSliceAddress = 1;
+    if (!pps->getRectSliceFlag())
+    {
+      while (pps->getNumTilesInPic() > (1 << bitsSliceAddress))  //TODO: use the correct one
+      {
+        bitsSliceAddress++;
+      }
+    }
+    else
+    {
+      if (pps->getSignalledSliceIdFlag())
+      {
+        bitsSliceAddress = pps->getSignalledSliceIdLengthMinus1() + 1;
+      }
+      else
+      {
+        while ((pps->getNumSlicesInPicMinus1() + 1) > (1 << bitsSliceAddress))
+        {
+          bitsSliceAddress++;
+        }
+      }
+    }
+    if (pps->getRectSliceFlag() || pps->getNumTilesInPic() > 1)   //TODO: change it to getNumBricksInPic when Tile/Brick is updated.
+    {
+      if (pps->getRectSliceFlag())
+      {
+        READ_CODE(bitsSliceAddress, uiCode, "slice_address");
+        int sliceIdx = 0;
+        while (pps->getSliceId(sliceIdx) != uiCode && sliceIdx <= pps->getNumSlicesInPicMinus1())
+        {
+          sliceIdx++;
+        }
+        pcSlice->setSliceCurStartBrickIdx(pps->getTopLeftBrickIdx(sliceIdx));
+        pcSlice->setSliceCurEndBrickIdx(pps->getBottomRightBrickIdx(sliceIdx));
+      }
+      else
+      {
+        READ_CODE(bitsSliceAddress, uiCode, "slice_address");
+        pcSlice->setSliceCurStartBrickIdx(uiCode);
+      }
+    }
+    if (!pps->getRectSliceFlag() && !pps->getSingleBrickPerSliceFlag())
+    {
+      READ_UVLC(uiCode, "num_bricks_in_slice_minus1");
+      pcSlice->setSliceNumBricks(uiCode + 1);
+      pcSlice->setSliceCurEndBrickIdx(pcSlice->getSliceCurStartBrickIdx() + uiCode);
+    }
+    pcSlice->setSliceCurStartCtuTsAddr(pcSlice->getSliceCurStartBrickIdx());
+#endif
+
     for (int i = 0; i < pps->getNumExtraSliceHeaderBits(); i++)
     {
       READ_FLAG(uiCode, "slice_reserved_flag[]"); // ignored
@@ -2408,7 +2523,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       parseReshaper(pcSlice->getReshapeInfo(), sps, pcSlice->isIntra());
     }
 
-  if( firstSliceSegmentInPic )
+#if JVET_N0857_RECT_SLICES
+    if( pcSlice->getSliceCurStartBrickIdx() == 0 )
+#else
+    if( firstSliceSegmentInPic )
+#endif
   {
     pcSlice->setDefaultClpRng( *sps );
 
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 68134e2c6..ae9c66a0f 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -478,8 +478,13 @@ protected:
 #if JVET_N0857_TILES_BRICKS
   bool      m_rectSliceFlag;
   int       m_numSlicesInPicMinus1;
+#if JVET_N0857_RECT_SLICES
+  std::vector<int> m_topLeftBrickIdx;
+  std::vector<int> m_bottomRightBrickIdx;
+#else
   std::vector<int> m_topLeftTileIdx;
   std::vector<int> m_bottomRightTileIdx;
+#endif
   bool      m_loopFilterAcrossSlicesEnabledFlag;
   bool      m_signalledSliceIdFlag;
   int       m_signalledSliceIdLengthMinus1;
@@ -1296,10 +1301,17 @@ public:
   void  setRectSliceFlag(bool val)                                   { m_rectSliceFlag = val; }
   int   getNumSlicesInPicMinus1() const                              { return m_numSlicesInPicMinus1; }
   void  setNumSlicesInPicMinus1(int val)                             { m_numSlicesInPicMinus1 = val; }
+#if JVET_N0857_RECT_SLICES
+  int   getTopLeftBrickIdx(uint32_t columnIdx) const                 { return  m_topLeftBrickIdx[columnIdx]; }
+  void  setTopLeftBrickIdx(const std::vector<int>& val)              { m_topLeftBrickIdx = val; }
+  int   getBottomeRightBrickIdx(uint32_t columnIdx) const            { return  m_bottomRightBrickIdx[columnIdx]; }
+  void  setBottomRightBrickIdx(const std::vector<int>& val)          { m_bottomRightBrickIdx = val; }
+#else
   int   getTopLeftTileIdx(uint32_t columnIdx) const                  { return  m_topLeftTileIdx[columnIdx]; }
   void  setTopLeftTileIdx(const std::vector<int>& val)               { m_topLeftTileIdx = val; }
   int   getBottomeRightTileIdx(uint32_t columnIdx) const             { return  m_bottomRightTileIdx[columnIdx]; }
   void  setBottomRightTileIdx(const std::vector<int>& val)           { m_bottomRightTileIdx = val; }
+#endif
   bool  getLoopFilterAcrossSlicesEnabledFlag() const                 { return m_loopFilterAcrossSlicesEnabledFlag; }
   void  setLoopFilterAcrossSlicesEnabledFlag(bool val)               { m_loopFilterAcrossSlicesEnabledFlag = val; }
   bool  getSignalledSliceIdFlag() const                              { return m_signalledSliceIdFlag; }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 186a71e1a..fb63c8ca3 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2352,12 +2352,19 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
       pcSlice->setSliceCurStartCtuTsAddr( 0 );
 
+#if JVET_N0857_RECT_SLICES
+      uint32_t sliceIdx = 0;
+      const BrickMap& tileMap = *(pcPic->brickMap);
+#endif
       for(uint32_t nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
       {
         m_pcSliceEncoder->precompressSlice( pcPic );
         m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
 
         const uint32_t curSliceEnd = pcSlice->getSliceCurEndCtuTsAddr();
+#if JVET_N0857_RECT_SLICES
+        pcSlice->setSliceIndex(sliceIdx);
+#endif
         if(curSliceEnd < numberOfCtusInFrame)
         {
           uint32_t independentSliceIdx = pcSlice->getIndependentSliceIdx();
@@ -2367,7 +2374,27 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
           pcSlice = pcPic->slices[uiNumSliceSegments];
           CHECK(!(pcSlice->getPPS() != 0), "Unspecified error");
           pcSlice->copySliceInfo(pcPic->slices[uiNumSliceSegments - 1]);
+#if JVET_N0857_RECT_SLICES
+          sliceIdx++;
+          if (pcSlice->getPPS()->getRectSliceFlag())
+          {
+            uint32_t startTileIdx = pcSlice->getPPS()->getTopLeftBrickIdx(sliceIdx);
+            uint32_t nextCtu = 0;
+            uint32_t tmpSliceIdx = 0;
+            while (tmpSliceIdx != startTileIdx)
+            {
+              nextCtu++;
+              tmpSliceIdx = tileMap.getBrickIdxBsMap(nextCtu);
+            }
+            pcSlice->setSliceCurStartCtuTsAddr(nextCtu);
+          }
+          else
+          {
+            pcSlice->setSliceCurStartCtuTsAddr(curSliceEnd);
+          }
+#else
           pcSlice->setSliceCurStartCtuTsAddr(curSliceEnd);
+#endif
           pcSlice->setSliceBits(0);
           independentSliceIdx++;
           pcSlice->setIndependentSliceIdx(independentSliceIdx);
@@ -2663,15 +2690,21 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
           // Append substreams...
           OutputBitstream *pcOut = pcBitstreamRedirect;
+#if !JVET_N0857_RECT_SLICES   //This seems not needed for tile/brick. Please check if this affects WPP
 #if JVET_N0857_TILES_BRICKS
           const int numZeroSubstreamsAtStartOfSlice  = pcPic->brickMap->getSubstreamForCtuAddr(pcSlice->getSliceCurStartCtuTsAddr(), false, pcSlice);
 #else
           const int numZeroSubstreamsAtStartOfSlice  = pcPic->tileMap->getSubstreamForCtuAddr(pcSlice->getSliceCurStartCtuTsAddr(), false, pcSlice);
+#endif
 #endif
           const int numSubstreamsToCode  = pcSlice->getNumberOfSubstreamSizes()+1;
           for ( uint32_t ui = 0 ; ui < numSubstreamsToCode; ui++ )
           {
+#if JVET_N0857_RECT_SLICES
+            pcOut->addSubstream(&(substreamsOut[ui]));
+#else
             pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice]));
+#endif
           }
         }
 
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 4dea49e55..a9f109888 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -423,6 +423,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
     picBg->getRecoBuf().fill(0);
 #if JVET_N0415_CTB_ALF
     picBg->finalInit(sps0, pps0, m_apss);
+#if JVET_N0857_RECT_SLICES
+    pps0.setNumBricksInPic((int)picBg->brickMap->bricks.size());
+#endif
 #else
     picBg->finalInit(sps0, pps0, aps0);
 #endif
@@ -652,6 +655,10 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
 #else
       APS *pAPS = m_apsMap.getPS(0);
       pcPicCurr->finalInit(*pSPS, *pPPS, *pAPS);
+#endif
+#if JVET_N0857_RECT_SLICES
+      PPS *ptrPPS = (ppsID<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsID);
+      ptrPPS->setNumBricksInPic((int)pcPicCurr->brickMap->bricks.size());
 #endif
     }
 
@@ -1824,6 +1831,10 @@ void  EncLib::xInitPPSforTiles(PPS &pps)
     pps.setSingleTileInPicFlag(false);
     pps.setSingleBrickPerSliceFlag( m_sliceMode==SINGLE_BRICK_PER_SLICE );
     pps.setRectSliceFlag( m_sliceMode==SINGLE_BRICK_PER_SLICE );
+#if JVET_N0857_RECT_SLICES
+    if (m_rectSliceFlag)
+      pps.setRectSliceFlag(m_rectSliceFlag);
+#endif
   }
 #endif
   pps.setUniformTileSpacingFlag( m_tileUniformSpacingFlag );
@@ -1839,8 +1850,13 @@ void  EncLib::xInitPPSforTiles(PPS &pps)
 #if JVET_N0857_TILES_BRICKS
   //pps.setRectSliceFlag( m_rectSliceFlag );
   pps.setNumSlicesInPicMinus1( m_numSlicesInPicMinus1 );
+#if JVET_N0857_RECT_SLICES
+  pps.setTopLeftBrickIdx(m_topLeftBrickIdx);
+  pps.setBottomRightBrickIdx(m_bottomRightBrickIdx);
+#else
   pps.setTopLeftTileIdx( m_topLeftTileIdx );
   pps.setBottomRightTileIdx( m_bottomRightTileIdx );
+#endif
   pps.setLoopFilterAcrossBricksEnabledFlag( m_loopFilterAcrossBricksEnabledFlag );
   pps.setLoopFilterAcrossSlicesEnabledFlag( m_loopFilterAcrossSlicesEnabledFlag );
   pps.setSignalledSliceIdFlag( m_signalledSliceIdFlag );
@@ -1850,7 +1866,10 @@ void  EncLib::xInitPPSforTiles(PPS &pps)
   pps.setSliceId( m_sliceId );
 
   int numTiles= (m_iNumColumnsMinus1 + 1) * (m_iNumRowsMinus1 + 1);
-  
+#if JVET_N0857_RECT_SLICES
+  pps.setNumTilesInPic(numTiles);
+#endif
+
   if (m_brickSplitMap.empty())
   {
     pps.setBrickSplittingPresentFlag(false);
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 67ce98080..b49240c0f 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1591,6 +1591,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
   }
   checkDisFracMmvd( pcPic, startCtuTsAddr, boundingCtuTsAddr );
   // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment)
+#if JVET_N0857_RECT_SLICES
+  uint32_t startSliceRsRow = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) / widthInCtus;
+  uint32_t startSliceRsCol = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) % widthInCtus;
+  uint32_t endSliceRsRow = tileMap.getCtuBsToRsAddrMap(boundingCtuTsAddr - 1) / widthInCtus;
+  uint32_t endSliceRsCol = tileMap.getCtuBsToRsAddrMap(boundingCtuTsAddr - 1) % widthInCtus;
+#endif
   for( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
   {
 #if JVET_N0857_TILES_BRICKS
@@ -1598,6 +1604,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
 #else
     const int32_t ctuRsAddr = tileMap.getCtuTsToRsAddrMap( ctuTsAddr );
 #endif
+#if JVET_N0857_RECT_SLICES
+    if (pcSlice->getPPS()->getRectSliceFlag() &&
+      ((ctuRsAddr / widthInCtus) < startSliceRsRow || (ctuRsAddr / widthInCtus) > endSliceRsRow ||
+      (ctuRsAddr % widthInCtus) < startSliceRsCol || (ctuRsAddr % widthInCtus) > endSliceRsCol))
+      continue;
+#endif
 
     // update CABAC state
 #if JVET_N0857_TILES_BRICKS
@@ -1908,6 +1920,13 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 
   const PreCalcValues& pcv = *cs.pcv;
   const uint32_t widthInCtus   = pcv.widthInCtus;
+#if JVET_N0857_RECT_SLICES
+  uint32_t startSliceRsRow = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) / widthInCtus;
+  uint32_t startSliceRsCol = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) % widthInCtus;
+  uint32_t endSliceRsRow = tileMap.getCtuBsToRsAddrMap(boundingCtuTsAddr - 1) / widthInCtus;
+  uint32_t endSliceRsCol = tileMap.getCtuBsToRsAddrMap(boundingCtuTsAddr - 1) % widthInCtus;
+  uint32_t uiSubStrm = 0;
+#endif
 
   // for every CTU in the slice segment...
 
@@ -1919,13 +1938,23 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 #else
     const uint32_t ctuRsAddr            = tileMap.getCtuTsToRsAddrMap(ctuTsAddr);
     const Tile& currentTile         = tileMap.tiles[tileMap.getTileIdxMap(ctuRsAddr)];
+#endif
+#if JVET_N0857_RECT_SLICES
+    if (pcSlice->getPPS()->getRectSliceFlag() &&
+      ((ctuRsAddr / widthInCtus) < startSliceRsRow || (ctuRsAddr / widthInCtus) > endSliceRsRow ||
+      (ctuRsAddr % widthInCtus) < startSliceRsCol || (ctuRsAddr % widthInCtus) > endSliceRsCol))
+      continue;
 #endif
     const uint32_t firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr();
     const uint32_t tileXPosInCtus       = firstCtuRsAddrOfTile % widthInCtus;
+#if !JVET_N0857_RECT_SLICES
     const uint32_t tileYPosInCtus       = firstCtuRsAddrOfTile / widthInCtus;
+#endif
     const uint32_t ctuXPosInCtus        = ctuRsAddr % widthInCtus;
     const uint32_t ctuYPosInCtus        = ctuRsAddr / widthInCtus;
+#if !JVET_N0857_RECT_SLICES
     const uint32_t uiSubStrm            = tileMap.getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice);
+#endif
 
     DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
 
@@ -1987,10 +2016,17 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 
     // terminate the sub-stream, if required (end of slice-segment, end of tile, end of wavefront-CTU-row):
 #if JVET_N0857_TILES_BRICKS
+#if JVET_N0857_RECT_SLICES
+    bool isLastCTUinBrick = tileMap.getBrickIdxBsMap(ctuTsAddr) != tileMap.getBrickIdxBsMap(ctuTsAddr + 1);
+    bool isLastCTUinWPP = wavefrontsEnabled && ((ctuRsAddr + 1 % widthInCtus) == tileXPosInCtus);
+    bool isMoreCTUsinSlice = ctuRsAddr != tileMap.getCtuBsToRsAddrMap(boundingCtuTsAddr - 1);
+    if (isLastCTUinBrick || isLastCTUinWPP || !isMoreCTUsinSlice)         // this the the last CTU of either tile/brick/WPP/slice
+#else
     if( ctuTsAddr + 1 == boundingCtuTsAddr ||
         (  ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getWidthInCtus () &&
         ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getHeightInCtus() || wavefrontsEnabled ) )
       )
+#endif
 #else
     if( ctuTsAddr + 1 == boundingCtuTsAddr ||
          (  ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus () &&
@@ -1999,16 +2035,25 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
        )
 #endif
     {
-      m_CABACWriter->end_of_slice();
+      m_CABACWriter->end_of_slice();  //This is actually end_of_brick_one_bit or end_of_subset_one_bit
 
       // Byte-alignment in slice_data() when new tile
       pcSubstreams[uiSubStrm].writeByteAlignment();
 
+#if JVET_N0857_RECT_SLICES
+      if (isMoreCTUsinSlice) //Byte alignment only when it is not the last substream in the slice
+      {
+        // write sub-stream size
+        pcSlice->addSubstreamSize((pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations());
+      }
+      uiSubStrm++;
+#else
       // write sub-stream size
       if( ctuTsAddr + 1 != boundingCtuTsAddr )
       {
         pcSlice->addSubstreamSize( (pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations() );
       }
+#endif
     }
   } // CTU-loop
 
@@ -2052,6 +2097,38 @@ void EncSlice::calculateBoundingCtuTsAddrForSlice(uint32_t &startCtuTSAddrSlice,
       break;
     case FIXED_NUMBER_OF_TILES:
       {
+#if JVET_N0857_RECT_SLICES
+      const uint32_t startBrickIdx = tileMap.getBrickIdxBsMap(startCtuTSAddrSlice);
+      uint32_t endBrickIdx = -1;
+      if (pps.getRectSliceFlag())  //rectangular slice
+      {
+        uint32_t sliceIdx = 0;
+        while (endBrickIdx == -1 && sliceIdx <= pps.getNumSlicesInPicMinus1())
+        {
+          if (pps.getTopLeftBrickIdx(sliceIdx) == startBrickIdx)
+            endBrickIdx = pps.getBottomRightBrickIdx(sliceIdx);
+          sliceIdx++;
+        }
+        if (endBrickIdx == -1)
+          EXIT("Incorrect rectangular slice definition");
+    }
+      else   //raster-scan slice
+      {
+        endBrickIdx = startBrickIdx + sliceArgument - 1;
+      }
+
+      uint32_t currentTileIdx = startBrickIdx;
+      int tmpAddr = -1;
+      for (int i = startCtuTSAddrSlice; i < numberOfCtusInFrame; i++)
+      {
+        currentTileIdx = tileMap.getBrickIdxBsMap(i);
+        if (currentTileIdx == endBrickIdx)
+          tmpAddr = i;
+      }
+      boundingCtuTSAddrSlice = (tmpAddr != -1) ? tmpAddr : numberOfCtusInFrame - 1;
+      boundingCtuTSAddrSlice++;
+      break;
+#else
 #if JVET_N0857_TILES_BRICKS
       const uint32_t tileIdx        = tileMap.getBrickIdxRsMap( tileMap.getCtuBsToRsAddrMap(startCtuTSAddrSlice) );
       const uint32_t tileTotalCount = (uint32_t) tileMap.bricks.size();
@@ -2077,6 +2154,7 @@ void EncSlice::calculateBoundingCtuTsAddrForSlice(uint32_t &startCtuTSAddrSlice,
         }
 
         boundingCtuTSAddrSlice  = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame;
+#endif
       }
       break;
 #if JVET_N0857_TILES_BRICKS
@@ -2164,6 +2242,15 @@ void EncSlice::xDetermineStartAndBoundingCtuTsAddr  ( uint32_t& startCtuTsAddr,
   pcSlice->setSliceCurEndCtuTsAddr(   boundingCtuTsAddrSlice );
   pcSlice->setSliceCurStartCtuTsAddr( startCtuTsAddrSlice    );
 
+#if JVET_N0857_RECT_SLICES
+  const BrickMap& tileMap = *(pcPic->brickMap);
+  pcSlice->setSliceCurStartBrickIdx(tileMap.getBrickIdxBsMap(startCtuTsAddrSlice));
+  if (pcSlice->getPPS()->getRectSliceFlag())
+    pcSlice->setSliceCurEndBrickIdx(tileMap.getBrickIdxBsMap(boundingCtuTsAddrSlice - 1));
+  else
+    pcSlice->setSliceNumBricks(tileMap.getBrickIdxBsMap(boundingCtuTsAddrSlice - 1) - tileMap.getBrickIdxBsMap(startCtuTsAddrSlice) + 1);
+#endif
+
   startCtuTsAddr = startCtuTsAddrSlice;
   boundingCtuTsAddr = boundingCtuTsAddrSlice;
 }
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index b57fbc86c..e603aae24 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -316,17 +316,35 @@ void HLSWriter::codePPS( const PPS* pcPPS )
       {
         if (i > 0)
         {
+#if JVET_N0857_RECT_SLICES
+          WRITE_CODE(pcPPS->getTopLeftBrickIdx(i), codeLength, "top_left_brick_idx ");
+#if JVET_N0124_PROPOSAL2
+#if JVET_N0857_RECT_SLICES
+          codeLength2 = (int)ceil(log2((numTilesInPic - pcPPS->getTopLeftBrickIdx(i) < 2) ? 2 : numTilesInPic - pcPPS->getTopLeftBrickIdx(i)));
+#else
+          codeLength2 = (int)ceil(log2(numTilesInPic - pcPPS->getTopLeftBrickIdx(i)));
+#endif
+#endif
+#else
           WRITE_CODE( pcPPS->getTopLeftTileIdx(i), codeLength, "top_left_brick_idx ");
 #if JVET_N0124_PROPOSAL2
-          codeLength2 = (int) ceil(log2(numTilesInPic - pcPPS->getTopLeftTileIdx(i)));
+          codeLength2 = (int)ceil(log2(numTilesInPic - pcPPS->getTopLeftTileIdx(i)));
+#endif
 #endif
         }
+#if JVET_N0857_RECT_SLICES
+#if JVET_N0124_PROPOSAL2
+        WRITE_CODE(pcPPS->getBottomRightBrickIdx(i) - pcPPS->getTopLeftBrickIdx(i), codeLength2, "bottom_right_brick_idx_delta");
+#else
+        WRITE_CODE(pcPPS->getBottomRightBrickIdx(i) - pcPPS->getTopLeftBrickIdx(i), codeLength, "bottom_right_brick_idx_delta");
+#endif
+#else
 #if JVET_N0124_PROPOSAL2
         WRITE_CODE(pcPPS->getBottomeRightTileIdx(i) - pcPPS->getTopLeftTileIdx(i), codeLength2, "bottom_right_brick_idx_delta");
 #else
         WRITE_CODE(pcPPS->getBottomeRightTileIdx(i) - pcPPS->getTopLeftTileIdx(i), codeLength, "bottom_right_brick_idx_delta");
 #endif
-
+#endif
       }
     }
 
@@ -1284,6 +1302,7 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
   const uint32_t         numberValidComponents = getNumberValidComponents(format);
   const bool         chromaEnabled         = isChromaEnabled(format);
 
+#if !JVET_N0857_RECT_SLICES
   //calculate number of bits required for slice address
   int maxSliceSegmentAddress = cs.pcv->sizeInCtus;
   int bitsSliceSegmentAddress = 0;
@@ -1301,15 +1320,58 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #endif
 
   WRITE_FLAG( sliceSegmentRsAddress==0, "first_slice_segment_in_pic_flag" );
+#endif
   if ( pcSlice->getRapPicFlag() )
   {
     WRITE_FLAG( pcSlice->getNoOutputPriorPicsFlag() ? 1 : 0, "no_output_of_prior_pics_flag" );
   }
   WRITE_UVLC( pcSlice->getPPS()->getPPSId(), "slice_pic_parameter_set_id" );
+#if !JVET_N0857_RECT_SLICES
   if(sliceSegmentRsAddress>0)
   {
     WRITE_CODE( sliceSegmentRsAddress, bitsSliceSegmentAddress, "slice_segment_address" );
   }
+#endif
+#if JVET_N0857_RECT_SLICES
+  int bitsSliceAddress = 1;
+  if (!pcSlice->getPPS()->getRectSliceFlag())
+  {
+    while (pcSlice->getPPS()->getNumBricksInPic() > (1 << bitsSliceAddress))
+    {
+      bitsSliceAddress++;
+    }
+  }
+  else
+  {
+    if (pcSlice->getPPS()->getSignalledSliceIdFlag())
+    {
+      bitsSliceAddress = pcSlice->getPPS()->getSignalledSliceIdLengthMinus1() + 1;
+    }
+    else
+    {
+      while ((pcSlice->getPPS()->getNumSlicesInPicMinus1() + 1) > (1 << bitsSliceAddress))
+      {
+        bitsSliceAddress++;
+      }
+    }
+  }
+  if (pcSlice->getPPS()->getRectSliceFlag() || pcSlice->getPPS()->getNumBricksInPic() > 1)
+  {
+    if (pcSlice->getPPS()->getRectSliceFlag())
+    {
+      WRITE_CODE(pcSlice->getPPS()->getSliceId(pcSlice->setSliceIndex()), bitsSliceAddress, "slice_address");
+    }
+    else
+    {
+      WRITE_CODE(pcSlice->getSliceCurStartBrickIdx(), bitsSliceAddress, "slice_address");
+    }
+  }
+  if (!pcSlice->getPPS()->getRectSliceFlag() && !pcSlice->getPPS()->getSingleBrickPerSliceFlag())
+  {
+    WRITE_UVLC(pcSlice->getSliceNumBricks() - 1, "num_bricks_in_slice_minus1");
+  }
+#endif
+  
     for( int i = 0; i < pcSlice->getPPS()->getNumExtraSliceHeaderBits(); i++ )
     {
       WRITE_FLAG( 0, "slice_reserved_flag[]" );
-- 
GitLab