From cb5cfa44c740194006d5c0b4b8ab353efb61e530 Mon Sep 17 00:00:00 2001
From: Brian Heng <brian.heng@broadcom.com>
Date: Tue, 10 Dec 2019 15:10:36 +0100
Subject: [PATCH] JVET-P1004: Removal of Bricks

  - Remove bricks and related syntax.
  - Add new tile / slice syntax from P1004.
  - Fix cross tile / slice prediction bugs.
  - Update config files and documentation with new tile / slice config options.
---
 cfg/encoder_intra_vtm.cfg                     |  14 +-
 cfg/encoder_lowdelay_P_vtm.cfg                |  14 +-
 cfg/encoder_lowdelay_vtm.cfg                  |  14 +-
 cfg/encoder_randomaccess_vtm.cfg              |  14 +-
 ...coder_randomaccess_vtm_RasterScanSlice.cfg |  38 +-
 ...oder_randomaccess_vtm_RectangularSlice.cfg |  39 +-
 ...omaccess_vtm_RectangularSliceFixedSize.cfg | 163 +++++++
 ...er_randomaccess_vtm_SingleTilePerSlice.cfg |  38 +-
 doc/software-manual.tex                       | 168 ++-----
 source/App/EncoderApp/EncApp.cpp              |  27 ++
 source/App/EncoderApp/EncAppCfg.cpp           | 446 ++++++++++++++++++
 source/App/EncoderApp/EncAppCfg.h             |  22 +
 source/Lib/CommonLib/AdaptiveLoopFilter.cpp   |  64 +++
 source/Lib/CommonLib/CommonDef.h              |   8 +
 source/Lib/CommonLib/ContextModelling.cpp     |   8 +
 source/Lib/CommonLib/IntraPrediction.cpp      |  33 ++
 source/Lib/CommonLib/LoopFilter.cpp           |  42 ++
 source/Lib/CommonLib/MCTS.cpp                 |  20 +
 source/Lib/CommonLib/Picture.cpp              |  10 +
 source/Lib/CommonLib/Picture.h                |   4 +
 source/Lib/CommonLib/Quant.cpp                |   4 +
 source/Lib/CommonLib/SampleAdaptiveOffset.cpp |   4 +
 source/Lib/CommonLib/Slice.cpp                | 354 ++++++++++++++
 source/Lib/CommonLib/Slice.h                  | 201 ++++++++
 source/Lib/CommonLib/TypeDef.h                |   4 +
 source/Lib/CommonLib/UnitPartitioner.cpp      |   4 +
 source/Lib/CommonLib/UnitTools.cpp            |  14 +
 source/Lib/CommonLib/UnitTools.h              |   2 +
 source/Lib/DecoderLib/CABACReader.cpp         | 140 ++++++
 source/Lib/DecoderLib/CABACReader.h           |  16 +
 source/Lib/DecoderLib/DecLib.cpp              |  18 +
 source/Lib/DecoderLib/DecSlice.cpp            |  68 +++
 source/Lib/DecoderLib/VLCReader.cpp           | 197 ++++++++
 source/Lib/EncoderLib/CABACWriter.cpp         |  12 +
 .../Lib/EncoderLib/EncAdaptiveLoopFilter.cpp  |   4 +
 source/Lib/EncoderLib/EncCfg.h                |  47 ++
 source/Lib/EncoderLib/EncCu.cpp               |  78 +++
 source/Lib/EncoderLib/EncGOP.cpp              |  24 +
 source/Lib/EncoderLib/EncHRD.cpp              |   4 +
 source/Lib/EncoderLib/EncLib.cpp              |  57 +++
 source/Lib/EncoderLib/EncLib.h                |   2 +
 .../EncoderLib/EncSampleAdaptiveOffset.cpp    |   8 +
 source/Lib/EncoderLib/EncSlice.cpp            | 230 +++++++++
 source/Lib/EncoderLib/EncSlice.h              |   8 +
 source/Lib/EncoderLib/InterSearch.cpp         |  17 +
 source/Lib/EncoderLib/SEIEncoder.cpp          |   4 +
 source/Lib/EncoderLib/VLCWriter.cpp           | 102 ++++
 47 files changed, 2541 insertions(+), 268 deletions(-)
 create mode 100644 cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSliceFixedSize.cfg

diff --git a/cfg/encoder_intra_vtm.cfg b/cfg/encoder_intra_vtm.cfg
index c6759769a..f413f709f 100644
--- a/cfg/encoder_intra_vtm.cfg
+++ b/cfg/encoder_intra_vtm.cfg
@@ -48,18 +48,8 @@ TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1
 TransformSkipLog2MaxSize      : 5
 SAOLcuBoundary                : 0           # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON)
 
-#============ Slices ================
-SliceMode                : 0                # 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            : 1500             # 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 / Slices ================
+EnablePicPartitioning         : 0           # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/encoder_lowdelay_P_vtm.cfg b/cfg/encoder_lowdelay_P_vtm.cfg
index 0b7152799..e3a15ee59 100644
--- a/cfg/encoder_lowdelay_P_vtm.cfg
+++ b/cfg/encoder_lowdelay_P_vtm.cfg
@@ -65,18 +65,8 @@ TemporalFilter                : 0           # Enable/disable GOP Based Temporal
 TemporalFilterFutureReference : 0           # Enable/disable reading future frames
 TemporalFilterStrengthFrame4  : 0.4         # Enable filter at every 4th frame with strength
 
-#============ Slices ================
-SliceMode                : 0                # 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            : 1500             # 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 / Slices ================
+EnablePicPartitioning         : 0           # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg
index fe8ca9c99..35fe96c08 100644
--- a/cfg/encoder_lowdelay_vtm.cfg
+++ b/cfg/encoder_lowdelay_vtm.cfg
@@ -65,18 +65,8 @@ TemporalFilter                : 0           # Enable/disable GOP Based Temporal
 TemporalFilterFutureReference : 0           # Enable/disable reading future frames
 TemporalFilterStrengthFrame4  : 0.4         # Enable filter at every 4th frame with strength
 
-#============ Slices ================
-SliceMode                : 0                # 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            : 1500             # 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 / Slices ================
+EnablePicPartitioning         : 0           # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg
index 788444ee0..58a684e9e 100644
--- a/cfg/encoder_randomaccess_vtm.cfg
+++ b/cfg/encoder_randomaccess_vtm.cfg
@@ -76,18 +76,8 @@ TemporalFilterFutureReference : 1           # Enable/disable reading future fram
 TemporalFilterStrengthFrame8  : 0.95        # Enable filter at every 8th frame with given strength
 TemporalFilterStrengthFrame16 : 1.5         # Enable filter at every 16th frame with given strength, longer intervals has higher priority
 
-#============ Slices ================
-SliceMode                : 0                # 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            : 1500             # 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 / Slices ================
+EnablePicPartitioning         : 0           # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
index 1df2375be..fb5b259b9 100644
--- a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RasterScanSlice.cfg
@@ -70,34 +70,16 @@ TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1
 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
-UniformTileColsWidthMinus1          : 0                # Width to use if TileUniformSpacing is equal to 1
-UniformTileRowHeightMinus1          : 0                # Height to use if TileUniformSpacing is equal to 1
-
-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
+#============ Tiles / Slices ================
+EnablePicPartitioning         : 1                      # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+
+# Figure 4 - Section 6.3.1 - 12 tiles and 3 raster-scan slices
+TileColumnWidthArray          : 6 6 6                  # Tile column widths in units of CTUs. Last column width will be repeated uniformly to cover any remaining picture width
+TileRowHeightArray            : 3 3 3 3                # Tile row heights in units of CTUs. Last row height will be repeated uniformly to cover any remaining picture height  
+RasterScanSlices              : 1                      # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+RasterSliceSizes              : 2 5 5                  # Raster-scan slice sizes in units of tiles. Last slice size will be repeated uniformly to cover any remaining tiles in the picture
+DisableLoopFilterAcrossTiles  : 0                      # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)
+DisableLoopFilterAcrossSlices : 0                      # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
index a69582afc..952231c63 100644
--- a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSlice.cfg
@@ -70,35 +70,16 @@ TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1
 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
-UniformTileColsWidthMinus1          : 0                # Width to use if TileUniformSpacing is equal to 1
-UniformTileRowHeightMinus1          : 0                # Height to use if TileUniformSpacing is equal to 1
-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
+#============ Tiles / Slices ================
+EnablePicPartitioning         : 1                         # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+
+# Figure 6 - Section 6.3.1 - 4 tiles and 4 rectangular slices
+TileColumnWidthArray          : 9 9                       # Tile column widths in units of CTUs. Last column width will be repeated uniformly to cover any remaining picture width
+TileRowHeightArray            : 6 6                       # Tile row heights in units of CTUs. Last row height will be repeated uniformly to cover any remaining picture height  
+RasterScanSlices              : 0                         # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+RectSlicePositions            : 0 206 9 35 45 107 117 215 # Rectangular slice positions. List containing pairs of top-left CTU RS address followed by bottom-right CTU RS address
+DisableLoopFilterAcrossTiles  : 0                         # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)
+DisableLoopFilterAcrossSlices : 0                         # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSliceFixedSize.cfg b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSliceFixedSize.cfg
new file mode 100644
index 000000000..d939ef937
--- /dev/null
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_RectangularSliceFixedSize.cfg
@@ -0,0 +1,163 @@
+#======== 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_L0 #ref_pics_L0   reference_pictures_L0 #ref_pics_active_L1 #ref_pics_L1   reference_pictures_L1
+Frame1:   B   16   1        0.0                      0.0            0          0          1.0      0            0              0             2                3          16 32 24                    2                2           16 32
+Frame2:   B    8   1       -4.8848                   0.2061         0          0          1.0      0            0              1             2                2          8 16                        2                2           -8 8
+Frame3:   B    4   4       -5.7476                   0.2286         0          0          1.0      0            0              2             2                2          4 12                        2                2           -4 -12
+Frame4:   B    2   5       -5.90                     0.2333         0          0          1.0      0            0              3             2                2          2 10                        2                3           -2 -6 -14
+Frame5:   B    1   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                2          1 -1                        2                4           -1 -3 -7 -15
+Frame6:   B    3   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                2          1 3                         2                3           -1 -5 -13
+Frame7:   B    6   5       -5.90                     0.2333         0          0          1.0      0            0              3             2                2          2 6                         2                2           -2 -10
+Frame8:   B    5   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                2          1 5                         2                3           -1 -3 -11
+Frame9:   B    7   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                3          1 3 7                       2                2           -1 -9
+Frame10:  B   12   4       -5.7476                   0.2286         0          0          1.0      0            0              2             2                2          4 12                        2                2           -4 4
+Frame11:  B   10   5       -5.90                     0.2333         0          0          1.0      0            0              3             2                2          2 10                        2                2           -2 -6
+Frame12:  B    9   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                2          1 9                         2                3           -1 -3 -7
+Frame13:  B   11   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                3          1 3 11                      2                2           -1 -5
+Frame14:  B   14   5       -5.90                     0.2333         0          0          1.0      0            0              3             2                3          2 6 14                      2                2           -2 2
+Frame15:  B   13   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                3          1 5 13                      2                2           -1 -3
+Frame16:  B   15   6       -7.1444                   0.3            0          0          1.0      0            0              4             2                4          1 3 7 15                    2                2           -1 1
+
+#=========== 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)
+
+#============ Tiles / Slices ================
+EnablePicPartitioning         : 1                         # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+
+# 24 tiles and 6 rectangular slices
+TileColumnWidthArray          : 3 3 3 3 3 3               # Tile column widths in units of CTUs. Last column width will be repeated uniformly to cover any remaining picture width
+TileRowHeightArray            : 3 3 3 3                   # Tile row heights in units of CTUs. Last row height will be repeated uniformly to cover any remaining picture height  
+RasterScanSlices              : 0                         # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+RectSliceFixedWidth           : 2                         # Fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead)
+RectSliceFixedHeight          : 2                         # Fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead)
+DisableLoopFilterAcrossTiles  : 0                         # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)
+DisableLoopFilterAcrossSlices : 0                         # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)
+
+#============ 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
+MaxMTTHierarchyDepth         : 3
+MaxMTTHierarchyDepthISliceL  : 3
+MaxMTTHierarchyDepthISliceC  : 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
+LMCSEnable                   : 1      # LMCS: 0: disable, 1:enable
+LMCSSignalType               : 0      # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG
+LMCSUpdateCtrl               : 0      # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP
+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
index 0aeccf23b..4dabdcdb8 100644
--- a/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg
+++ b/cfg/nonCTC-SliceConfigExamples/encoder_randomaccess_vtm_SingleTilePerSlice.cfg
@@ -70,36 +70,14 @@ TransformSkipFast             : 1           # Fast Transform skipping (0: OFF, 1
 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                  : 1                # 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
-UniformTileColsWidthMinus1          : 1                # Width to use if TileUniformSpacing is equal to 1
-UniformTileRowHeightMinus1          : 0                # Height to use if TileUniformSpacing is equal to 1
-
-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
+#============ Tiles / Slices ================
+EnablePicPartitioning         : 1                      # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+TileColumnWidthArray          : 1 2 3 4                # Tile column widths in units of CTUs. Last column width will be repeated uniformly to cover any remaining picture width
+TileRowHeightArray            : 1 2 3 4                # Tile row heights in units of CTUs. Last row height will be repeated uniformly to cover any remaining picture height  
+RasterScanSlices              : 1                      # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+RasterSliceSizes              : 1                      # Raster-scan slice sizes in units of tiles. Last slice size will be repeated uniformly to cover any remaining tiles in the picture
+DisableLoopFilterAcrossTiles  : 0                      # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)
+DisableLoopFilterAcrossSlices : 0                      # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)
 
 #============ Lossless ================
 TransquantBypassEnable     : 0                         # Value of PPS flag.
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index d75a76205..3e305d9bc 100755
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -1707,167 +1707,82 @@ Specifies the maximum depth for CU chroma QP adjustment; if negative, CU chroma
 
 
 %%
-%% Slice/Tile/Brick coding parameters
+%% Slice/Tile coding parameters
 %%
-\begin{OptionTableNoShorthand}{Slice, tile and brick coding parameters}{tab:slice-coding}
-%\Option{SliceGranularity} &
-%\ShortOption{\None} &
-%\Default{0} &
-%Determines the depth in an LCU at which slices may begin and end.
-%\par
-%\begin{tabular}{cp{0.45\textwidth}}
-% 0   & Slice addresses are LCU aligned \\
-% $1 \leq n \leq 3$
-%     & Slice start addresses are aligned to CUs at depth $n$ \\
-%\end{tabular}
-%
-%Note: The smallest permissible alignment is 16x16 CUs.
-%Values of $n$ must satisfy this constraint, for example, with a 64x64
-%LCU, $n$ must be less than or equal to 2.
-%\\
+\begin{OptionTableNoShorthand}{Slice and tile coding parameters}{tab:slice-coding}
 
-\Option{SliceMode} &
+\Option{EnablePicPartitioning} &
 %\ShortOption{\None} &
 \Default{0} &
-Controls the slice partitioning method in conjunction with
-SliceArgument.
-\par
-\begin{tabular}{cp{0.45\textwidth}}
- 0 & Single slice \\
- 1 & (deprecated) Maximum number of CTUs per slice \\
- 2 & (deprecated) Maximum number of bytes per slice \\
- 3 & Maximum number of tiles per slice \\
- 4 & One slice per brick
-\end{tabular}
+Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used).
 \\
 
-\Option{SliceArgument} &
+\Option{TileColumnWidthArray} &
 %\ShortOption{\None} &
 \Default{\NotSet} &
-(deprecated)
-Specifies the maximum number of CTUs, bytes or tiles in a slice depending on the
-SliceMode setting.
+Tile column widths in units of CTUs. Last column width in list will be repeated uniformly to cover any remaining picture width.
 \\
 
-\Option{RectSliceFlag} &
+\Option{TileRowHeightArray} &
 %\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}
+\Default{\NotSet} &
+Tile row heights in units of CTUs. Last row height in list will be repeated uniformly to cover any remaining picture height.
 \\
 
-\Option{NumRecSlicesInPicMinus1} &
+\Option{RasterScanSlices} &
 %\ShortOption{\None} &
 \Default{0} &
-Specifies the number of rectangular slices in the picture.
+Use raster-scan or rectangular slices (0: rectangular, 1: raster-scan).
 \\
 
-\Option{RectSlicesBoundaryArray} &
+\Option{RectSlicePositions} &
 %\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}
+Rectangular slice positions. List containing pairs of top-left CTU RS address followed by bottom-right CTU RS address.
 \\
 
-\Option{IDRRefParamList} &
+\Option{RectSliceFixedWidth} &
 %\ShortOption{\None} &
-\Default{false} &
-Enables the signalling of reference picture list syntax elements in slice headers of IDR pictures
+\Default{0} &
+Fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead).
 \\
 
-\Option{WaveFrontSynchro} &
+\Option{RectSliceFixedHeight} &
 %\ShortOption{\None} &
-\Default{false} &
-Enables the use of specific CABAC probabilities synchronization at the
-beginning of each line of CTBs in order to produce a bitstream that can
-be encoded or decoded using one or more cores.
+\Default{0} &
+Fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead).
 \\
 
-\Option{TileUniformSpacing} &
+\Option{RasterSliceSizes} &
 %\ShortOption{\None} &
-\Default{false} &
-Controls the mode used to determine per row and column tile sizes.
-\par
-\begin{tabular}{cp{0.45\textwidth}}
- 0 & Each tile column width and tile row height is explicitly set
-     by TileColumnWidthArray and TileRowHeightArray respectively \\
- 1 & Tile columns and tile rows are uniformly spaced. \\
-\end{tabular}
+\Default{\NotSet} &
+Raster-scan slice sizes in units of tiles. Last size in list will be repeated uniformly to cover any remaining tiles in the picture.
 \\
 
-\Option{UniformTileColsWidthMinus1}%
-\Option{UniformTileRowHeightMinus1} &
+\Option{DisableLoopFilterAcrossTiles} &
 %\ShortOption{\None} &
-\Default{-1} &
-Specifies the tile width and height to use if TileUniformSpacing is set to 1.
+\Default{0} &
+Loop filtering applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries).
 \\
 
-\Option{NumTileColumnsMinus1}%
-\Option{NumTileRowsMinus1} &
+\Option{DisableLoopFilterAcrossSlices} &
 %\ShortOption{\None} &
 \Default{0} &
-Specifies the tile based picture partitioning geometry as
-$\mathrm{NumTileColumnsMinus1} + 1 \times \mathrm{NumTileRowsMinus1} + 1$
-columns and rows.
+Loop filtering applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries).
 \\
 
-\Option{TileColumnWidthArray}%
-\Option{TileRowHeightArray} &
+\Option{IDRRefParamList} &
 %\ShortOption{\None} &
-\Default{\NotSet} &
-Specifies a space or comma separated list of widths and heights,
-respectively, of each tile column or tile row.  The first value in the
-list corresponds to the leftmost tile column or topmost tile row.
+\Default{false} &
+Enables the signalling of reference picture list syntax elements in slice headers of IDR pictures
 \\
 
-\Option{BrickSplit1}%
-\Option{BrickSplit2} %
-\Option{BrickSplitN} &
-%\ShortOption{\None} &
-\Default{\NotSet} &
-Specifies the splitting of tiles into bricks, N can be in the range of 1 to 128 and has no further meaning except to distinguish different splitting parameters.
-
-The following options are supported:
-
-BrickSplitN tileIdx uniform (numsplits) heights
-
-\begin{tabular}{cp{0.45\textwidth}}
- tileIdx & the index of the tile to be split in raster scan order starting with zero \\
- uniform & specifies whether uniform splitting shall be used (1 for uniform, 0 non-uniform) \\
- numsplits & specifies the number of splits, if uniform is not used \\
- heights & specifies the height of the uniform splits or a list of heights for non-uniform splits \\
-\end{tabular}
- 
-\\
-\Option{TileRowHeightArray} &
+\Option{WaveFrontSynchro} &
 %\ShortOption{\None} &
-\Default{\NotSet} &
-Specifies a space or comma separated list of widths and heights,
-respectively, of each tile column or tile row.  The first value in the
-list corresponds to the leftmost tile column or topmost tile row.
+\Default{false} &
+Enables the use of specific CABAC probabilities synchronization at the
+beginning of each line of CTBs in order to produce a bitstream that can
+be encoded or decoded using one or more cores.
 \\
 
 
@@ -1885,13 +1800,6 @@ list corresponds to the leftmost tile column or topmost tile row.
 Enables or disables the in-loop deblocking filter.
 \\
 
-\Option{LFCrossSliceBoundaryFlag} &
-%\ShortOption{\None} &
-\Default{true} &
-Enables or disables the use of in-loop filtering across slice
-boundaries.
-\\
-
 \Option{LoopFilterOffsetInPPS}&
 %\ShortOption{\None}&
 \Default{false}&
@@ -1926,12 +1834,6 @@ Specifies the use of a deblocking filter metric to evaluate the suitability of d
 LoopFilterOffsetInPPS and LoopFilterDisable must be 0. Currently excepted values are 0, 1 and 2.
 \\
 
-\Option{LFCrossSliceBoundaryFlag}&
-%\ShortOption{\None}&
-\Default{true}&
-Enables or disables the use of a deblocking across tile boundaries.
-\\
-
 \Option{LoopFilterAcrossVirtualBoundariesDisabledFlag}&
 %\ShortOption{\None}&
 \Default{false}&
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 4a61240e4..7f65ed862 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -440,6 +440,30 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setUseWP                                             ( m_useWeightedPred     );
   m_cEncLib.setWPBiPred                                          ( m_useWeightedBiPred   );
 
+#if JVET_P1004_REMOVE_BRICKS
+  //====== Tiles and Slices ========
+  m_cEncLib.setNoPicPartitionFlag( !m_picPartitionFlag );
+  if( m_picPartitionFlag )
+  {
+    m_cEncLib.setTileColWidths( m_tileColumnWidth );
+    m_cEncLib.setTileRowHeights( m_tileRowHeight );
+    m_cEncLib.setRectSliceFlag( !m_rasterSliceFlag );
+    m_cEncLib.setNumSlicesInPic( m_numSlicesInPic );
+    m_cEncLib.setTileIdxDeltaPresentFlag( m_tileIdxDeltaPresentFlag );
+    m_cEncLib.setRectSlices( m_rectSlices );
+    m_cEncLib.setRasterSliceSizes( m_rasterSliceSize );
+    m_cEncLib.setLFCrossTileBoundaryFlag( !m_disableLFCrossTileBoundaryFlag );
+    m_cEncLib.setLFCrossSliceBoundaryFlag( !m_disableLFCrossSliceBoundaryFlag );
+  }
+  else
+  {
+    m_cEncLib.setRectSliceFlag( true );
+    m_cEncLib.setNumSlicesInPic( 1 );
+    m_cEncLib.setTileIdxDeltaPresentFlag( 0 );
+    m_cEncLib.setLFCrossTileBoundaryFlag( true );
+    m_cEncLib.setLFCrossSliceBoundaryFlag( true );
+  }
+#else
   //====== Slice ========
   m_cEncLib.setSliceMode                                         ( m_sliceMode );
   m_cEncLib.setSliceArgument                                     ( m_sliceArgument );
@@ -450,6 +474,7 @@ void EncApp::xInitLibCfg()
     m_bLFCrossSliceBoundaryFlag = true;
   }
   m_cEncLib.setLFCrossSliceBoundaryFlag                          ( m_bLFCrossSliceBoundaryFlag );
+#endif
   m_cEncLib.setUseSAO                                            ( m_bUseSAO );
   m_cEncLib.setTestSAODisableAtPictureLevel                      ( m_bTestSAODisableAtPictureLevel );
   m_cEncLib.setSaoEncodingRate                                   ( m_saoEncodingRate );
@@ -550,6 +575,7 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setSEIXSDMetricType                                  ( uint8_t(m_xsdMetricType) );
 #endif
 
+#if !JVET_P1004_REMOVE_BRICKS
   m_cEncLib.setTileUniformSpacingFlag                            ( m_tileUniformSpacingFlag );
   if (m_tileUniformSpacingFlag)
   {
@@ -580,6 +606,7 @@ void EncApp::xInitLibCfg()
     m_bLFCrossTileBoundaryFlag = true;
   }
   m_cEncLib.setLFCrossTileBoundaryFlag                           ( m_bLFCrossTileBoundaryFlag );
+#endif
   m_cEncLib.setEntropyCodingSyncEnabledFlag                      ( m_entropyCodingSyncEnabledFlag );
   m_cEncLib.setTMVPModeId                                        ( m_TMVPModeId );
 #if JVET_P1006_PICTURE_HEADER
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index c4115fa9e..a3c1abdfc 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -231,6 +231,7 @@ std::istringstream &operator>>(std::istringstream &in, GOPEntry &entry)     //in
   return in;
 }
 
+#if !JVET_P1004_REMOVE_BRICKS
 std::istringstream &operator>>(std::istringstream &in, BrickSplit &entry)     //input
 {
   in>>entry.m_tileIdx;
@@ -249,6 +250,7 @@ std::istringstream &operator>>(std::istringstream &in, BrickSplit &entry)     //
   }
   return in;
 }
+#endif
 
 
 bool confirmPara(bool bflag, const char* message);
@@ -715,6 +717,91 @@ automaticallySelectRExtProfile(const bool bUsingGeneralRExtTools,
     }
   }
 }
+#if JVET_P1004_REMOVE_BRICKS
+
+static uint32_t getMaxTileColsByLevel( Level::Name level )
+{
+  switch( level ) 
+  {
+    case Level::LEVEL1:
+    case Level::LEVEL2:
+    case Level::LEVEL2_1:
+      return 1;
+    case Level::LEVEL3:
+      return 2;
+    case Level::LEVEL3_1:
+      return 3;
+    case Level::LEVEL4:
+    case Level::LEVEL4_1:
+      return 5;
+    case Level::LEVEL5:
+    case Level::LEVEL5_1:
+    case Level::LEVEL5_2:
+      return 10;
+    case Level::LEVEL6:
+    case Level::LEVEL6_1:
+    case Level::LEVEL6_2:
+    default:
+      return 20;
+  }
+}
+
+static uint32_t getMaxTileRowsByLevel( Level::Name level )
+{
+  switch( level ) 
+  {
+    case Level::LEVEL1:
+    case Level::LEVEL2:
+    case Level::LEVEL2_1:
+      return 1;
+    case Level::LEVEL3:
+      return 2;
+    case Level::LEVEL3_1:
+      return 3;
+    case Level::LEVEL4:
+    case Level::LEVEL4_1:
+      return 5;
+    case Level::LEVEL5:
+    case Level::LEVEL5_1:
+    case Level::LEVEL5_2:
+      return 11;
+    case Level::LEVEL6:
+    case Level::LEVEL6_1:
+    case Level::LEVEL6_2:
+    default:
+      return 21;
+  }
+}
+
+static uint32_t getMaxSlicesByLevel( Level::Name level )
+{
+  switch( level ) 
+  {
+    case Level::LEVEL1:
+    case Level::LEVEL2:
+      return 16;
+    case Level::LEVEL2_1:
+      return 20;
+    case Level::LEVEL3:
+      return 30;
+    case Level::LEVEL3_1:
+      return 40;
+    case Level::LEVEL4:
+    case Level::LEVEL4_1:
+      return 75;
+    case Level::LEVEL5:
+    case Level::LEVEL5_1:
+    case Level::LEVEL5_2:
+      return 200;
+    case Level::LEVEL6:
+    case Level::LEVEL6_1:
+    case Level::LEVEL6_2:
+    default:
+      return 600;
+  }
+}
+
+#endif
 // ====================================================================================================================
 // Public member functions
 // ====================================================================================================================
@@ -733,7 +820,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   int tmpWeightedPredictionMethod;
   int tmpFastInterSearchMode;
   int tmpMotionEstimationSearchMethod;
+#if !JVET_P1004_REMOVE_BRICKS 
   int tmpSliceMode;
+#endif
   int tmpDecodedPictureHashSEIMappedType;
   string inputColourSpaceConvert;
   string inputPathPrefix;
@@ -741,14 +830,23 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   int saoOffsetBitShift[MAX_NUM_CHANNEL_TYPE];
 
   // Multi-value input fields:                                // minval, maxval (incl), min_entries, max_entries (incl) [, default values, number of default values]
+#if JVET_P1004_REMOVE_BRICKS  
+  SMultiValueInput<uint32_t>  cfgTileColumnWidth              (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+  SMultiValueInput<uint32_t>  cfgTileRowHeight                (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+  SMultiValueInput<uint32_t>  cfgRectSlicePos                 (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+  SMultiValueInput<uint32_t>  cfgRasterSliceSize              (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+#else  
   SMultiValueInput<uint32_t> cfg_ColumnWidth                     (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
   SMultiValueInput<uint32_t> cfg_RowHeight                       (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+#endif
   SMultiValueInput<int>  cfg_startOfCodedInterval            (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
   SMultiValueInput<int>  cfg_codedPivotValue                 (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
   SMultiValueInput<int>  cfg_targetPivotValue                (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
 
+#if !JVET_P1004_REMOVE_BRICKS 
   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());
+#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.
 
@@ -1179,6 +1277,18 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("MaxNumOffsetsPerPic",                             m_maxNumOffsetsPerPic,                             2048, "Max number of SAO offset per picture (Default: 2048)")
   ("SAOLcuBoundary",                                  m_saoCtuBoundary,                                 false, "0: right/bottom CTU boundary areas skipped from SAO parameter estimation, 1: non-deblocked pixels are used for those areas")
   ("SAOGreedyEnc",                                    m_saoGreedyMergeEnc,                              false, "SAO greedy merge encoding algorithm")
+#if JVET_P1004_REMOVE_BRICKS    
+  ("EnablePicPartitioning",                           m_picPartitionFlag,                               false, "Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)")
+  ("TileColumnWidthArray",                            cfgTileColumnWidth,                  cfgTileColumnWidth, "Tile column widths in units of CTUs. Last column width in list will be repeated uniformly to cover any remaining picture width")
+  ("TileRowHeightArray",                              cfgTileRowHeight,                      cfgTileRowHeight, "Tile row heights in units of CTUs. Last row height in list will be repeated uniformly to cover any remaining picture height")
+  ("RasterScanSlices",                                m_rasterSliceFlag,                                false, "Indicates if using raster-scan or rectangular slices (0: rectangular, 1: raster-scan)")
+  ("RectSlicePositions",                              cfgRectSlicePos,                        cfgRectSlicePos, "Rectangular slice positions. List containing pairs of top-left CTU RS address followed by bottom-right CTU RS address")
+  ("RectSliceFixedWidth",                             m_rectSliceFixedWidth,                                0, "Fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead)")
+  ("RectSliceFixedHeight",                            m_rectSliceFixedHeight,                               0, "Fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead)")
+  ("RasterSliceSizes",                                cfgRasterSliceSize,                  cfgRasterSliceSize, "Raster-scan slice sizes in units of tiles. Last size in list will be repeated uniformly to cover any remaining tiles in the picture")
+  ("DisableLoopFilterAcrossTiles",                    m_disableLFCrossTileBoundaryFlag,                 false, "Loop filtering applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)")
+  ("DisableLoopFilterAcrossSlices",                   m_disableLFCrossSliceBoundaryFlag,                false, "Loop filtering applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)")
+#else
   ("SliceMode",                                       tmpSliceMode,                            int(NO_SLICES), "0: Disable all Recon slice limits, 1: (deprecated #CTU), 2: (deprecated #bytes), 3:specify tiles per slice, 4: one brick per slice")
   ("SliceArgument",                                   m_sliceArgument,                                      0, "Depending on SliceMode being:"
                                                                                                                "\t1: max number of CTUs per slice"
@@ -1186,6 +1296,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
                                                                                                                "\t3: max number of tiles per slice")
   ("LFCrossSliceBoundaryFlag",                        m_bLFCrossSliceBoundaryFlag,                       true)
 
+#endif
   ("FastUDIUseMPMEnabled",                            m_bFastUDIUseMPMEnabled,                           true, "If enabled, adapt intra direction search, accounting for MPM")
   ("FastMEForGenBLowDelayEnabled",                    m_bFastMEForGenBLowDelayEnabled,                   true, "If enabled use a fast ME for generalised B Low Delay slices")
   ("UseBLambdaForNonKeyLowDelayPictures",             m_bUseBLambdaForNonKeyLowDelayPictures,            true, "Enables use of B-Lambda for non-key low-delay pictures")
@@ -1193,6 +1304,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("WeightedPredP,-wpP",                              m_useWeightedPred,                                false, "Use weighted prediction in P slices")
   ("WeightedPredB,-wpB",                              m_useWeightedBiPred,                              false, "Use weighted (bidirectional) prediction in B slices")
   ("WeightedPredMethod,-wpM",                         tmpWeightedPredictionMethod, int(WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT), "Weighted prediction method")
+#if !JVET_P1004_REMOVE_BRICKS
     //deprecated copies of renamed tile parameters
   ("UniformSpacingIdc",                               m_tileUniformSpacingFlag,                         false,      "deprecated alias of TileUniformSpacing")
   ("TileUniformSpacing",                              m_tileUniformSpacingFlag,                         false,      "Indicates that tile columns and rows are distributed uniformly")
@@ -1203,7 +1315,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("TileColumnWidthArray",                            cfg_ColumnWidth,                        cfg_ColumnWidth, "Array containing tile column width values in units of CTU")
   ("TileRowHeightArray",                              cfg_RowHeight,                            cfg_RowHeight, "Array containing tile row height values in units of CTU")
   ("LFCrossTileBoundaryFlag",                         m_bLFCrossTileBoundaryFlag,                        true, "1: cross-tile-boundary loop filtering. 0:non-cross-tile-boundary loop filtering")
+#endif
   ("WaveFrontSynchro",                                m_entropyCodingSyncEnabledFlag,                   false, "0: entropy coding sync disabled; 1 entropy coding sync enabled")
+#if !JVET_P1004_REMOVE_BRICKS
 
   ("RectSliceFlag",                                   m_rectSliceFlag,                                  true, "Rectangular slice flag")
   ("NumRectSlicesInPicMinus1",                        m_numSlicesInPicMinus1,                              0, "Number slices in pic minus 1")
@@ -1213,6 +1327,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("RectSlicesBoundaryArray",                         cfg_SliceIdx,                              cfg_SliceIdx, "Rectangular slices boundaries in Pic")
   ("SignalledSliceId",                                cfg_SignalledSliceId,                       cfg_SliceIdx, "Signalled rectangular slice ID")
 
+#endif
   ("ScalingList",                                     m_useScalingListId,                    SCALING_LIST_OFF, "0/off: no scaling list, 1/default: default scaling lists, 2/file: scaling lists specified in ScalingListFile")
   ("ScalingListFile",                                 m_scalingListFileName,                       string(""), "Scaling list file name. Use an empty string to produce help.")
 #if JVET_P0365_SCALING_MATRIX_LFNST
@@ -1458,6 +1573,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     opts.addOptions()(cOSS.str(), m_GOPList[i-1], GOPEntry());
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   for(int i=1; i<MAX_TILES+1; i++)
   {
     std::ostringstream cOSS;
@@ -1465,6 +1581,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     opts.addOptions()(cOSS.str(), m_brickSplits[i-1], BrickSplit());
   }
 
+#endif
   po::setDefaults(opts);
   po::ErrorReporter err;
   const list<const char*>& argv_unhandled = po::scanArgv(opts, argc, (const char**) argv, err);
@@ -1614,6 +1731,54 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     m_framesToBeEncoded *= 2;
   }
 
+#if JVET_P1004_REMOVE_BRICKS
+  if( m_picPartitionFlag ) 
+  {
+    // store tile column widths
+    m_tileColumnWidth.resize(cfgTileColumnWidth.values.size());
+    for(uint32_t i=0; i<cfgTileColumnWidth.values.size(); i++)
+    {
+      m_tileColumnWidth[i]=cfgTileColumnWidth.values[i];
+    }
+
+    // store tile row heights
+    m_tileRowHeight.resize(cfgTileRowHeight.values.size());
+    for(uint32_t i=0; i<cfgTileRowHeight.values.size(); i++)
+    {
+      m_tileRowHeight[i]=cfgTileRowHeight.values[i];
+    }
+
+    // store rectangular slice positions
+    if( !m_rasterSliceFlag ) 
+    {
+      m_rectSlicePos.resize(cfgRectSlicePos.values.size());
+      for(uint32_t i=0; i<cfgRectSlicePos.values.size(); i++)
+      {
+        m_rectSlicePos[i]=cfgRectSlicePos.values[i];
+      }
+    }
+
+    // store raster-scan slice sizes
+    else 
+    {
+      m_rasterSliceSize.resize(cfgRasterSliceSize.values.size());
+      for(uint32_t i=0; i<cfgRasterSliceSize.values.size(); i++)
+      {
+        m_rasterSliceSize[i]=cfgRasterSliceSize.values[i];
+      }
+    }
+  }
+  else 
+  {
+    m_tileColumnWidth.clear();
+    m_tileRowHeight.clear();
+    m_rectSlicePos.clear();
+    m_rasterSliceSize.clear();
+    m_rectSliceFixedWidth = 0;
+    m_rectSliceFixedHeight = 0;
+  }
+
+#else
   if( !m_tileUniformSpacingFlag && m_numTileColumnsMinus1 > 0 )
   {
     if (cfg_ColumnWidth.values.size() > m_numTileColumnsMinus1)
@@ -1661,6 +1826,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   {
     m_tileRowHeight.clear();
   }
+#endif
   m_numSubProfile = (uint8_t) cfg_SubProfile.values.size();
   m_subProfile.resize(m_numSubProfile);
   for (uint8_t i = 0; i < m_numSubProfile; ++i)
@@ -1668,6 +1834,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     m_subProfile[i] = cfg_SubProfile.values[i];
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   if (m_tileUniformSpacingFlag)
   {
     int uniformTileHeight = ((m_uniformTileRowHeightMinus1 + 1) * m_uiCTUSize);
@@ -1675,6 +1842,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     m_numTileRowsMinus1 = ((m_iSourceHeight + uniformTileHeight - 1) / uniformTileHeight) - 1;
     m_numTileColumnsMinus1 = ((m_iSourceWidth + uniformTileWidth - 1) / uniformTileWidth) - 1;
   }
+#endif
   /* rules for input, output and internal bitdepths as per help text */
   if (m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA  ] == 0)
   {
@@ -1876,6 +2044,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     }
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   if (tmpSliceMode<0 || tmpSliceMode>=int(NUMBER_OF_SLICE_CONSTRAINT_MODES))
   {
     EXIT( "Error: bad slice mode");
@@ -2024,6 +2193,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
       m_sliceId[i] = i;
     }
   }
+#endif
 
   if (tmpDecodedPictureHashSEIMappedType<0 || tmpDecodedPictureHashSEIMappedType>=int(NUMBER_OF_HASHTYPES))
   {
@@ -2881,17 +3051,21 @@ bool EncAppCfg::xCheckParameter()
     xConfirmPara(!m_useTransformSkip, "BDPCM cannot be used when transform skip is disabled.");
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   if (m_sliceMode!=NO_SLICES)
   {
     xConfirmPara( m_sliceArgument < 1 ,         "SliceArgument should be larger than or equal to 1" );
   }
+#endif
 
 
+#if !JVET_P1004_REMOVE_BRICKS
   bool tileFlag = (m_numTileColumnsMinus1 > 0 || m_numTileRowsMinus1 > 0 );
   if (m_profile!=Profile::HIGHTHROUGHPUTREXT)
   {
     xConfirmPara( tileFlag && m_entropyCodingSyncEnabledFlag, "Tiles and entropy-coding-sync (Wavefronts) can not be applied together, except in the High Throughput Intra 4:4:4 16 profile");
   }
+#endif
 
   xConfirmPara( m_iSourceWidth  % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Picture width must be an integer multiple of the specified chroma subsampling");
   xConfirmPara( m_iSourceHeight % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Picture height must be an integer multiple of the specified chroma subsampling");
@@ -3318,6 +3492,264 @@ bool EncAppCfg::xCheckParameter()
     m_maxDecPicBuffering[MAX_TLAYER-1] = m_numReorderPics[MAX_TLAYER-1] + 1;
   }
 
+#if JVET_P1004_REMOVE_BRICKS
+  if( m_picPartitionFlag ) 
+  {
+    PPS pps;
+    uint32_t colIdx, rowIdx;
+    uint32_t remSize;
+ 
+    pps.setPicWidthInLumaSamples( m_iSourceWidth );
+    pps.setPicHeightInLumaSamples( m_iSourceHeight );
+    pps.setLog2CtuSize( floorLog2(m_uiCTUSize) );
+
+    // set default tile column if not provided
+    if( m_tileColumnWidth.size() == 0 ) 
+    {
+      m_tileColumnWidth.push_back( pps.getPicWidthInCtu() );
+    }
+    // set default tile row if not provided
+    if( m_tileRowHeight.size() == 0 ) 
+    {
+      m_tileRowHeight.push_back( pps.getPicHeightInCtu() );
+    }
+
+    // remove any tile columns that can be specified implicitly
+    while( m_tileColumnWidth.size() > 1 && m_tileColumnWidth.end()[-1] == m_tileColumnWidth.end()[-2] )
+    {
+      m_tileColumnWidth.pop_back();
+    }
+
+    // remove any tile rows that can be specified implicitly
+    while( m_tileRowHeight.size() > 1 && m_tileRowHeight.end()[-1] == m_tileRowHeight.end()[-2] )
+    {
+      m_tileRowHeight.pop_back();
+    }
+
+    // setup tiles in temporary PPS structure
+    remSize = pps.getPicWidthInCtu();
+    for( colIdx=0; remSize > 0 && colIdx<m_tileColumnWidth.size(); colIdx++ )
+    {
+      xConfirmPara(m_tileColumnWidth[ colIdx ] == 0, "Tile column widths cannot be equal to 0");
+      m_tileColumnWidth[ colIdx ] = std::min( remSize, m_tileColumnWidth[ colIdx ]);
+      pps.addTileColumnWidth( m_tileColumnWidth[ colIdx ] );
+      remSize -= m_tileColumnWidth[ colIdx ];
+    }
+    m_tileColumnWidth.resize( colIdx );
+    pps.setNumExpTileColumns( (uint32_t)m_tileColumnWidth.size() );    
+    remSize = pps.getPicHeightInCtu();
+    for( rowIdx=0; remSize > 0 && rowIdx<m_tileRowHeight.size(); rowIdx++ )
+    {
+      xConfirmPara(m_tileRowHeight[ rowIdx ] == 0, "Tile row heights cannot be equal to 0");
+      m_tileRowHeight[ rowIdx ] = std::min( remSize, m_tileRowHeight[ rowIdx ]);
+      pps.addTileRowHeight( m_tileRowHeight[ rowIdx ] );
+      remSize -= m_tileRowHeight[ rowIdx ];
+    }
+    m_tileRowHeight.resize( rowIdx );
+    pps.setNumExpTileRows( (uint32_t)m_tileRowHeight.size() );
+    pps.initTiles();
+    xConfirmPara(pps.getNumTileColumns() > getMaxTileColsByLevel( m_level ), "Number of tile columns exceeds maximum number allowed according to specified level");
+    xConfirmPara(pps.getNumTileRows()    > getMaxTileRowsByLevel( m_level ), "Number of tile rows exceeds maximum number allowed according to specified level");
+    m_numTileCols = pps.getNumTileColumns();
+    m_numTileRows = pps.getNumTileRows();
+
+    // rectangular slices
+    if( !m_rasterSliceFlag )
+    {
+      uint32_t sliceIdx;
+      bool     needTileIdxDelta = false;
+
+      // generate slice list for the simplified fixed-rectangular-slice-size config option
+      if( m_rectSliceFixedWidth > 0 && m_rectSliceFixedHeight > 0 )
+      {
+        int tileIdx = 0;
+        m_rectSlicePos.clear();
+        while( tileIdx < pps.getNumTiles() ) 
+        {
+          uint32_t startTileX = tileIdx % pps.getNumTileColumns();
+          uint32_t startTileY = tileIdx / pps.getNumTileColumns();
+          uint32_t startCtuX  = pps.getTileColumnBd( startTileX );
+          uint32_t startCtuY  = pps.getTileRowBd( startTileY );
+          uint32_t stopCtuX   = (startTileX + m_rectSliceFixedWidth)  >= pps.getNumTileColumns() ? pps.getPicWidthInCtu() - 1  : pps.getTileColumnBd( startTileX + m_rectSliceFixedWidth ) - 1;
+          uint32_t stopCtuY   = (startTileY + m_rectSliceFixedHeight) >= pps.getNumTileRows()    ? pps.getPicHeightInCtu() - 1 : pps.getTileRowBd( startTileY + m_rectSliceFixedHeight ) - 1;
+          uint32_t stopTileX  = pps.ctuToTileCol( stopCtuX );
+          uint32_t stopTileY  = pps.ctuToTileRow( stopCtuY );
+          
+          // add rectangular slice to list
+          m_rectSlicePos.push_back( startCtuY * pps.getPicWidthInCtu() + startCtuX );          
+          m_rectSlicePos.push_back( stopCtuY  * pps.getPicWidthInCtu() + stopCtuX  );
+          
+          // get slice size in tiles
+          uint32_t sliceWidth  = stopTileX - startTileX + 1;
+          uint32_t sliceHeight = stopTileY - startTileY + 1;
+
+          // move to next tile in raster scan order
+          tileIdx += sliceWidth;
+          if( tileIdx % pps.getNumTileColumns() == 0 )
+          {
+            tileIdx += (sliceHeight - 1) * pps.getNumTileColumns();
+          }
+        }
+      }
+
+      xConfirmPara( m_rectSlicePos.size() & 1, "Odd number of rectangular slice positions provided. Rectangular slice positions must be specified in pairs of (top-left / bottom-right) raster-scan CTU addresses.");
+      
+      // set default slice size if not provided
+      if( m_rectSlicePos.size() == 0 ) 
+      {
+        m_rectSlicePos.push_back( 0 );
+        m_rectSlicePos.push_back( pps.getPicWidthInCtu() * pps.getPicHeightInCtu() - 1 );
+      }
+      pps.setNumSlicesInPic( (uint32_t)(m_rectSlicePos.size() >> 1) );
+      xConfirmPara(pps.getNumSlicesInPic() > getMaxSlicesByLevel( m_level ), "Number of rectangular slices exceeds maximum number allowed according to specified level");
+      pps.initRectSlices();
+
+      // set slice parameters from CTU addresses
+      for( sliceIdx = 0; sliceIdx < pps.getNumSlicesInPic(); sliceIdx++ )
+      {
+        xConfirmPara( m_rectSlicePos[2*sliceIdx]     >= pps.getPicWidthInCtu() * pps.getPicHeightInCtu(), "Rectangular slice position exceeds total number of CTU in picture.");
+        xConfirmPara( m_rectSlicePos[2*sliceIdx + 1] >= pps.getPicWidthInCtu() * pps.getPicHeightInCtu(), "Rectangular slice position exceeds total number of CTU in picture.");
+
+        // map raster scan CTU address to X/Y position
+        uint32_t startCtuX = m_rectSlicePos[2*sliceIdx]     % pps.getPicWidthInCtu();
+        uint32_t startCtuY = m_rectSlicePos[2*sliceIdx]     / pps.getPicWidthInCtu();
+        uint32_t stopCtuX  = m_rectSlicePos[2*sliceIdx + 1] % pps.getPicWidthInCtu();
+        uint32_t stopCtuY  = m_rectSlicePos[2*sliceIdx + 1] / pps.getPicWidthInCtu();
+        
+        // get corresponding tile index
+        uint32_t startTileX = pps.ctuToTileCol( startCtuX );
+        uint32_t startTileY = pps.ctuToTileRow( startCtuY );
+        uint32_t stopTileX  = pps.ctuToTileCol( stopCtuX );
+        uint32_t stopTileY  = pps.ctuToTileRow( stopCtuY );
+        uint32_t tileIdx    = startTileY * pps.getNumTileColumns() + startTileX;
+
+        // get slice size in tiles
+        uint32_t sliceWidth  = stopTileX - startTileX + 1;
+        uint32_t sliceHeight = stopTileY - startTileY + 1;
+        
+        // check for slice / tile alignment
+        xConfirmPara( startCtuX != pps.getTileColumnBd( startTileX ), "Rectangular slice position does not align with a left tile edge.");
+        xConfirmPara( stopCtuX  != (pps.getTileColumnBd( stopTileX + 1 ) - 1), "Rectangular slice position does not align with a right tile edge.");
+        if( sliceWidth > 1 || sliceHeight > 1 )
+        {
+          xConfirmPara( startCtuY != pps.getTileRowBd( startTileY ), "Rectangular slice position does not align with a top tile edge.");
+          xConfirmPara( stopCtuY  != (pps.getTileRowBd( stopTileY + 1 ) - 1), "Rectangular slice position does not align with a bottom tile edge.");
+        }
+
+        // set slice size and tile index
+        pps.setSliceWidthInTiles( sliceIdx, sliceWidth );
+        pps.setSliceHeightInTiles( sliceIdx, sliceHeight );
+        pps.setSliceTileIdx( sliceIdx, tileIdx );
+        if( sliceIdx > 0 && !needTileIdxDelta )
+        {
+          uint32_t lastTileIdx = pps.getSliceTileIdx( sliceIdx-1 );
+          lastTileIdx += pps.getSliceWidthInTiles( sliceIdx-1 );
+          if( lastTileIdx % pps.getNumTileColumns() == 0)
+          {
+            lastTileIdx += (pps.getSliceHeightInTiles( sliceIdx-1 ) - 1) * pps.getNumTileColumns();
+          }
+          if( lastTileIdx != tileIdx )
+          {
+            needTileIdxDelta = true;
+          }
+        }
+
+        // special case for multiple slices within a single tile
+        if( sliceWidth == 1 && sliceHeight == 1 )
+        {
+          uint32_t firstSliceIdx = sliceIdx;
+          uint32_t numSlicesInTile = 1;
+          pps.setSliceHeightInCtu( sliceIdx, stopCtuY - startCtuY + 1 );
+          
+          while( sliceIdx < pps.getNumSlicesInPic()-1 ) 
+          {
+            uint32_t nextTileIdx;
+            startCtuX   = m_rectSlicePos[2*(sliceIdx+1)]     % pps.getPicWidthInCtu();
+            startCtuY   = m_rectSlicePos[2*(sliceIdx+1)]     / pps.getPicWidthInCtu();
+            stopCtuX    = m_rectSlicePos[2*(sliceIdx+1) + 1] % pps.getPicWidthInCtu();
+            stopCtuY    = m_rectSlicePos[2*(sliceIdx+1) + 1] / pps.getPicWidthInCtu();          
+            startTileX  = pps.ctuToTileCol( startCtuX );
+            startTileY  = pps.ctuToTileRow( startCtuY );
+            stopTileX   = pps.ctuToTileCol( stopCtuX );
+            stopTileY   = pps.ctuToTileRow( stopCtuY );
+            nextTileIdx = startTileY * pps.getNumTileColumns() + startTileX;
+            sliceWidth  = stopTileX - startTileX + 1;
+            sliceHeight = stopTileY - startTileY + 1;
+            if(nextTileIdx != tileIdx || sliceWidth != 1 || sliceHeight != 1) 
+            {
+              break;
+            }
+            numSlicesInTile++;
+            sliceIdx++;
+            pps.setSliceWidthInTiles( sliceIdx, 1 );
+            pps.setSliceHeightInTiles( sliceIdx, 1 );
+            pps.setSliceTileIdx( sliceIdx, tileIdx );    
+            pps.setSliceHeightInCtu( sliceIdx, stopCtuY - startCtuY + 1 );
+          }
+          pps.setNumSlicesInTile( firstSliceIdx, numSlicesInTile );
+        }
+      }
+      pps.setTileIdxDeltaPresentFlag( needTileIdxDelta );
+      m_tileIdxDeltaPresentFlag = needTileIdxDelta;
+      
+      // check rectangular slice mapping and full picture CTU coverage
+      pps.initRectSliceMap();
+
+      // store rectangular slice parameters from temporary PPS structure
+      m_numSlicesInPic = pps.getNumSlicesInPic();
+      m_rectSlices.resize( pps.getNumSlicesInPic() );
+      for( sliceIdx = 0; sliceIdx < pps.getNumSlicesInPic(); sliceIdx++ )
+      {
+        m_rectSlices[sliceIdx].setSliceWidthInTiles( pps.getSliceWidthInTiles(sliceIdx) );
+        m_rectSlices[sliceIdx].setSliceHeightInTiles( pps.getSliceHeightInTiles(sliceIdx) );
+        m_rectSlices[sliceIdx].setNumSlicesInTile( pps.getNumSlicesInTile(sliceIdx) );
+        m_rectSlices[sliceIdx].setSliceHeightInCtu( pps.getSliceHeightInCtu(sliceIdx) );
+        m_rectSlices[sliceIdx].setTileIdx( pps.getSliceTileIdx(sliceIdx) );
+      }
+    }
+    // raster-scan slices
+    else
+    {
+      uint32_t listIdx = 0;
+      uint32_t remTiles = pps.getNumTiles();
+
+      // set default slice size if not provided
+      if( m_rasterSliceSize.size() == 0 ) 
+      {
+        m_rasterSliceSize.push_back( remTiles );
+      }
+
+      // set raster slice sizes
+      while( remTiles > 0 )
+      {
+        // truncate if size exceeds number of remaining tiles
+        if( listIdx < m_rasterSliceSize.size() )
+        {
+          m_rasterSliceSize[listIdx] = std::min( remTiles, m_rasterSliceSize[listIdx] );
+          remTiles -= m_rasterSliceSize[listIdx];
+        }
+        // replicate last size uniformly as needed to cover the remainder of the picture
+        else
+        {
+          m_rasterSliceSize.push_back( std::min( remTiles, m_rasterSliceSize.back() ) );
+          remTiles -= m_rasterSliceSize.back();
+        }
+        listIdx++;
+      }
+      // shrink list if too many sizes were provided
+      m_rasterSliceSize.resize( listIdx );
+      
+      m_numSlicesInPic = (uint32_t)m_rasterSliceSize.size();
+      xConfirmPara(m_rasterSliceSize.size() > getMaxSlicesByLevel( m_level ), "Number of raster-scan slices exceeds maximum number allowed according to specified level");
+    }
+  }
+  else 
+  {
+    m_numTileCols = 1;
+    m_numTileRows = 1;
+    m_numSlicesInPic = 1;
+  }
+#else
 
   for (int i=0; i<MAX_TILES; i++)
   {
@@ -3327,11 +3759,20 @@ bool EncAppCfg::xCheckParameter()
       // ToDo: check that brick dimensions don't exceed tile dimensions
     }
   }
+#endif
 
+#if JVET_P1004_REMOVE_BRICKS
+  if ((m_MCTSEncConstraint) && (!m_disableLFCrossTileBoundaryFlag))
+#else
   if ((m_MCTSEncConstraint) && (m_bLFCrossTileBoundaryFlag))
+#endif
   {
     printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling filtering across tile boundaries!\n");
+#if JVET_P1004_REMOVE_BRICKS
+    m_disableLFCrossTileBoundaryFlag = true;
+#else
     m_bLFCrossTileBoundaryFlag = false;
+#endif
   }
   if ((m_MCTSEncConstraint) && (m_TMVPModeId))
   {
@@ -3715,12 +4156,17 @@ void EncAppCfg::xPrintParameter()
   msg(VERBOSE, "ChromaTS:%d ", m_useChromaTS);
 #endif
   msg( VERBOSE, "BDPCM:%d ", m_useBDPCM                         );
+#if JVET_P1004_REMOVE_BRICKS
+  msg( VERBOSE, "Tiles: %dx%d ", m_numTileCols, m_numTileRows );
+  msg( VERBOSE, "Slices: %d ", m_numSlicesInPic);
+#else
   msg( VERBOSE, "Slice: M=%d ", int(m_sliceMode));
   if (m_sliceMode!=NO_SLICES)
   {
     msg( VERBOSE, "A=%d ", m_sliceArgument);
   }
   msg( VERBOSE, "Tiles:%dx%d ", m_numTileColumnsMinus1 + 1, m_numTileRowsMinus1 + 1 );
+#endif
   msg( VERBOSE, "MCTS:%d ", m_MCTSEncConstraint );
   msg( VERBOSE, "SAO:%d ", (m_bUseSAO)?(1):(0));
   msg( VERBOSE, "ALF:%d ", m_alf ? 1 : 0 );
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index c6e9d8e9c..2c79f19fe 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -200,8 +200,10 @@ protected:
   RPLEntry  m_RPLList1[MAX_GOP];                               ///< the RPL entries from the config file
   bool      m_idrRefParamList;                                ///< indicates if reference picture list syntax elements are present in slice headers of IDR pictures
   GOPEntry  m_GOPList[MAX_GOP];                               ///< the coding structure entries from the config file
+#if !JVET_P1004_REMOVE_BRICKS
   BrickSplit    m_brickSplits[MAX_TILES];
   BrickSplitMap m_brickSplitMap;
+#endif
   int       m_numReorderPics[MAX_TLAYER];                     ///< total number of reorder pictures
   int       m_maxDecPicBuffering[MAX_TLAYER];                 ///< total number of pictures in the decoded picture buffer
   bool      m_crossComponentPredictionEnabledFlag;            ///< flag enabling the use of cross-component prediction
@@ -435,6 +437,23 @@ protected:
   bool      m_useFastDecisionForMerge;                        ///< flag for using Fast Decision Merge RD-Cost
   bool      m_bUseCbfFastMode;                                ///< flag for using Cbf Fast PU Mode Decision
   bool      m_useEarlySkipDetection;                          ///< flag for using Early SKIP Detection
+#if JVET_P1004_REMOVE_BRICKS
+  bool      m_picPartitionFlag;                               ///< enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+  std::vector<uint32_t> m_tileColumnWidth;                    ///< tile column widths in units of CTUs (last column width will be repeated uniformly to cover any remaining picture width)
+  std::vector<uint32_t> m_tileRowHeight;                      ///< tile row heights in units of CTUs (last row height will be repeated uniformly to cover any remaining picture height)
+  bool      m_rasterSliceFlag;                                ///< indicates if using raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+  std::vector<uint32_t> m_rectSlicePos;                       ///< rectangular slice positions (pairs of top-left CTU address followed by bottom-right CTU address)
+  int       m_rectSliceFixedWidth;                            ///< fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead)
+  int       m_rectSliceFixedHeight;                           ///< fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead)
+  std::vector<uint32_t> m_rasterSliceSize;                    ///< raster-scan slice sizes in units of tiles (last size will be repeated uniformly to cover any remaining tiles in the picture)
+  bool      m_disableLFCrossTileBoundaryFlag;                 ///< 0: filter across tile boundaries  1: do not filter across tile boundaries
+  bool      m_disableLFCrossSliceBoundaryFlag;                ///< 0: filter across slice boundaries 1: do not filter across slice boundaries
+  uint32_t  m_numSlicesInPic;                                 ///< derived number of rectangular slices in the picture (raster-scan slice specified at slice level)
+  bool      m_tileIdxDeltaPresentFlag;                        ///< derived tile index delta present flag
+  std::vector<RectSlice> m_rectSlices;                        ///< derived list of rectangular slice signalling parameters
+  uint32_t  m_numTileCols;                                    ///< derived number of tile columns
+  uint32_t  m_numTileRows;                                    ///< derived number of tile rows
+#else
   SliceConstraint m_sliceMode;
   int             m_sliceArgument;                            ///< argument according to selected slice mode
 
@@ -448,8 +467,10 @@ protected:
   int       m_uniformTileRowHeightMinus1;
   std::vector<int> m_tileColumnWidth;
   std::vector<int> m_tileRowHeight;
+#endif
   bool      m_entropyCodingSyncEnabledFlag;
 
+#if !JVET_P1004_REMOVE_BRICKS
   bool      m_rectSliceFlag;
   int       m_numSlicesInPicMinus1;
   std::vector<int> m_topLeftBrickIdx;
@@ -458,6 +479,7 @@ protected:
   bool      m_signalledSliceIdFlag;
   int       m_signalledSliceIdLengthMinus1;
   std::vector<int> m_sliceId;
+#endif
 
   bool      m_bFastUDIUseMPMEnabled;
   bool      m_bFastMEForGenBLowDelayEnabled;
diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
index a082870b7..e70d54002 100644
--- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
+++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
@@ -103,7 +103,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in
       topBry = posY;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    if ( !pps.getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile( *currCtu, *prevCtu ) )
+#else
     if ( !pps.getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameBrick( *currCtu, *prevCtu ) )
+#endif
     {
       topBry = posY;
     }
@@ -124,7 +128,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in
       botBry = posY + ctuSize;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    if ( !pps.getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile( *currCtu, *nextCtu ) )
+#else
     if ( !pps.getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameBrick( *currCtu, *nextCtu ) )
+#endif
     {
       botBry = posY + ctuSize;
     }
@@ -145,7 +153,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in
       leftBry = posX;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    if ( !pps.getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile( *currCtu, *prevCtu ) )
+#else
     if ( !pps.getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameBrick( *currCtu, *prevCtu ) )
+#endif
     {
       leftBry = posX;
     }
@@ -166,7 +178,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in
       rightBry = posX + ctuSize;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    if ( !pps.getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile( *currCtu, *nextCtu ) )
+#else
     if ( !pps.getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameBrick( *currCtu, *nextCtu ) )
+#endif
     {
       rightBry = posX + ctuSize;
     }
@@ -381,7 +397,12 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int
     const Position prevCtuPos(xPos, yPos - ctuSize);
     const CodingUnit *prevCtu = cs.getCU(prevCtuPos, CHANNEL_TYPE_LUMA);
 #if JVET_P1006_PICTURE_HEADER
+#if JVET_P1004_REMOVE_BRICKS
+    if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu)) || 
+        (!pps->getLoopFilterAcrossTilesEnabledFlag()  && !CU::isSameTile(*currCtu,  *prevCtu)))
+#else
     if (!pps->getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu))
+#endif
 #else
     if ((!slice.getLFCrossSliceBoundaryFlag() || !pps->getLoopFilterAcrossBricksEnabledFlag()) && !CU::isSameSlice(*currCtu, *prevCtu))
 #endif
@@ -396,7 +417,12 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int
     const Position nextCtuPos(xPos, yPos + ctuSize);
     const CodingUnit *nextCtu = cs.getCU(nextCtuPos, CHANNEL_TYPE_LUMA);
 #if JVET_P1006_PICTURE_HEADER
+#if JVET_P1004_REMOVE_BRICKS
+    if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu)) || 
+        (!pps->getLoopFilterAcrossTilesEnabledFlag()  && !CU::isSameTile(*currCtu,  *nextCtu)))
+#else
     if (!pps->getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu))
+#endif
 #else
     if ((!slice.getLFCrossSliceBoundaryFlag() || !pps->getLoopFilterAcrossBricksEnabledFlag()) && !CU::isSameSlice(*currCtu, *nextCtu))
 #endif
@@ -411,7 +437,12 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int
     const Position prevCtuPos(xPos - ctuSize, yPos);
     const CodingUnit *prevCtu = cs.getCU(prevCtuPos, CHANNEL_TYPE_LUMA);
 #if JVET_P1006_PICTURE_HEADER
+#if JVET_P1004_REMOVE_BRICKS
+    if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu)) || 
+        (!pps->getLoopFilterAcrossTilesEnabledFlag()  && !CU::isSameTile(*currCtu,  *prevCtu)))
+#else
     if (!pps->getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu))
+#endif
 #else
     if ((!slice.getLFCrossSliceBoundaryFlag() || !pps->getLoopFilterAcrossBricksEnabledFlag()) && !CU::isSameSlice(*currCtu, *prevCtu))
 #endif
@@ -426,7 +457,12 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int
     const Position nextCtuPos(xPos + ctuSize, yPos);
     const CodingUnit *nextCtu = cs.getCU(nextCtuPos, CHANNEL_TYPE_LUMA);
 #if JVET_P1006_PICTURE_HEADER
+#if JVET_P1004_REMOVE_BRICKS
+    if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu)) || 
+        (!pps->getLoopFilterAcrossTilesEnabledFlag()  && !CU::isSameTile(*currCtu,  *nextCtu)))
+#else
     if (!pps->getLoopFilterAcrossBricksEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu))
+#endif
 #else
     if ((!slice.getLFCrossSliceBoundaryFlag() || !pps->getLoopFilterAcrossBricksEnabledFlag()) && !CU::isSameSlice(*currCtu, *nextCtu))
 #endif
@@ -528,11 +564,13 @@ const int AdaptiveLoopFilter::m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_
 
 void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
 {
+#if !JVET_P1004_REMOVE_BRICKS
   if (!cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y) && !cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) && !cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr))
   {
     return;
   }
 
+#endif
 
   // set clipping range
   m_clpRngs = cs.slice->getClpRngs();
@@ -543,8 +581,13 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
     m_ctuEnableFlag[compIdx] = cs.picture->getAlfCtuEnableFlag( compIdx );
     m_ctuAlternative[compIdx] = cs.picture->getAlfCtuAlternativeData( compIdx );
   }
+#if JVET_P1004_REMOVE_BRICKS
+  short* alfCtuFilterIndex = nullptr;
+  uint32_t lastSliceIdx = 0xFFFFFFFF;
+#else
   reconstructCoeffAPSs(cs, true, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) || cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr), false);
   short* alfCtuFilterIndex = cs.slice->getPic()->getAlfCtbFilterIndex();
+#endif
 
   PelUnitBuf recYuv = cs.getRecoBuf();
   m_tempBuf.copyFrom( recYuv );
@@ -568,6 +611,27 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
   {
     for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth )
     {
+#if JVET_P1004_REMOVE_BRICKS
+      // get first CU in CTU
+      const CodingUnit *cu = cs.getCU( Position(xPos, yPos), CHANNEL_TYPE_LUMA );
+
+      // skip this CTU if ALF is disabled
+      if (!cu->slice->getTileGroupAlfEnabledFlag(COMPONENT_Y) && !cu->slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) && !cu->slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr))
+      {
+        ctuIdx++;
+        continue;
+      }
+
+      // reload ALF APS each time the slice changes during raster scan filtering
+      if(ctuIdx == 0 || lastSliceIdx != cu->slice->getSliceID() || alfCtuFilterIndex==nullptr)
+      {
+        cs.slice = cu->slice;
+        reconstructCoeffAPSs(cs, true, cu->slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) || cu->slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr), false);
+        alfCtuFilterIndex = cu->slice->getPic()->getAlfCtbFilterIndex();
+      }
+      lastSliceIdx = cu->slice->getSliceID();
+
+#endif
       const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth;
       const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight;
       bool ctuEnableFlag = m_ctuEnableFlag[COMPONENT_Y][ctuIdx];
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 34ff09077..163b72e96 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -145,8 +145,10 @@ static const int MAX_NUM_REF =                                     16; ///< max.
 static const int MAX_QP =                                          63;
 static const int NOT_VALID =                                       -1;
 
+#if !JVET_P1004_REMOVE_BRICKS
 static const int MAX_TILES =                                      128; ///< max. number of tiles for which a brick configuration can be read
 static const int MAX_NUM_BRICKS_PER_TILE =                          8; ///< max. number brick per tile, for which a configuration can be read
+#endif
 
 static const int AMVP_MAX_NUM_CANDS =                               2; ///< AMVP: advanced motion vector prediction - max number of final candidates
 static const int AMVP_MAX_NUM_CANDS_MEM =                           3; ///< AMVP: advanced motion vector prediction - max number of candidates
@@ -214,6 +216,12 @@ static const int MAX_NUM_APS =                                     32;  //Curren
 static const int NUM_APS_TYPE_LEN =                                 3;  //Currently APS Type has 3 bits
 static const int MAX_NUM_APS_TYPE =                                 8;  //Currently APS Type has 3 bits so the max type is 8
 
+#if JVET_P1004_REMOVE_BRICKS
+static const int MAX_TILE_COLS =                                   20;  ///< Maximum number of tile columns
+static const int MAX_TILE_ROWS =                                   22;  ///< Maximum number of tile rows
+static const int MAX_TILES =            MAX_TILE_COLS * MAX_TILE_ROWS;  ///< Maximum number of tiles
+static const int MAX_SLICES =                                     600;  ///< Maximum number of slices per picture
+#endif
 static const int MLS_GRP_NUM =                                   1024; ///< Max number of coefficient groups, max(16, 256)
 
 static const int MLS_CG_SIZE =                                      4; ///< Coefficient group size of 4x4; = MLS_CG_LOG2_WIDTH + MLS_CG_LOG2_HEIGHT
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index f1cad5688..bbd174e5f 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -141,7 +141,11 @@ unsigned DeriveCtx::CtxModeConsFlag( const CodingStructure& cs, Partitioner& par
   assert( partitioner.chType == CHANNEL_TYPE_LUMA );
   const Position pos = partitioner.currArea().blocks[partitioner.chType];
   const unsigned curSliceIdx = cs.slice->getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+  const unsigned curTileIdx = cs.pps->getTileIdx( partitioner.currArea().lumaPos() );
+#else
   const unsigned curTileIdx = cs.picture->brickMap->getBrickIdxRsMap( partitioner.currArea().lumaPos() );
+#endif
 
   const CodingUnit* cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), pos, curSliceIdx, curTileIdx, partitioner.chType );
   const CodingUnit* cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), pos, curSliceIdx, curTileIdx, partitioner.chType );
@@ -155,7 +159,11 @@ void DeriveCtx::CtxSplit( const CodingStructure& cs, Partitioner& partitioner, u
 {
   const Position pos         = partitioner.currArea().blocks[partitioner.chType];
   const unsigned curSliceIdx = cs.slice->getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+  const unsigned curTileIdx  = cs.pps->getTileIdx( partitioner.currArea().lumaPos() );
+#else
   const unsigned curTileIdx  = cs.picture->brickMap->getBrickIdxRsMap( partitioner.currArea().lumaPos() );
+#endif
 
   // get left depth
   const CodingUnit* cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), pos, curSliceIdx, curTileIdx, partitioner.chType );
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index ed8e3da57..1914b2da6 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -890,8 +890,13 @@ void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const Comp
   }
 
   const Position posLT = area;
+#if JVET_P1004_REMOVE_BRICKS
+  bool           isLeftAvail  = (cs.getCURestricted(posLT.offset(-1, 0), cu, CHANNEL_TYPE_LUMA) != NULL) && cs.isDecomp(posLT.offset(-1, 0), CHANNEL_TYPE_LUMA);
+  bool           isAboveAvail = (cs.getCURestricted(posLT.offset(0, -1), cu, CHANNEL_TYPE_LUMA) != NULL) && cs.isDecomp(posLT.offset(0, -1), CHANNEL_TYPE_LUMA);
+#else
   bool           isLeftAvail = cs.isDecomp(posLT.offset(-1, 0), CHANNEL_TYPE_LUMA);
   bool           isAboveAvail = cs.isDecomp(posLT.offset(0, -1), CHANNEL_TYPE_LUMA);
+#endif
   // ----- Step 1: unfiltered reference samples -----
   if (cu.blocks[area.compID].x == area.x && cu.blocks[area.compID].y == area.y)
   {
@@ -1290,7 +1295,11 @@ bool isAboveLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const
     return false;
   }
 
+#if JVET_P1004_REMOVE_BRICKS
+  return (cs.getCURestricted(refPos, cu, chType) != NULL);
+#else
   return true;
+#endif
 }
 
 int isAboveAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *bValidFlags)
@@ -1310,8 +1319,14 @@ int isAboveAvailable(const CodingUnit &cu, const ChannelType &chType, const Posi
       break;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
+    numIntra += valid ? 1 : 0;
+    *validFlags = valid;
+#else
     ++numIntra;
     *validFlags = true;
+#endif
 
     validFlags++;
   }
@@ -1336,8 +1351,14 @@ int isLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const Posit
       break;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
+    numIntra += valid ? 1 : 0;
+    *validFlags = valid;
+#else
     ++numIntra;
     *validFlags = true;
+#endif
 
     validFlags--;
   }
@@ -1362,8 +1383,14 @@ int isAboveRightAvailable(const CodingUnit &cu, const ChannelType &chType, const
       break;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
+    numIntra += valid ? 1 : 0;
+    *validFlags = valid;
+#else
     ++numIntra;
     *validFlags = true;
+#endif
 
     validFlags++;
   }
@@ -1388,8 +1415,14 @@ int isBelowLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const
       break;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
+    numIntra += valid ? 1 : 0;
+    *validFlags = valid;
+#else
     ++numIntra;
     *validFlags = true;
+#endif
 
     validFlags--;
   }
diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp
index c75c3dff8..2d21dfd4b 100644
--- a/source/Lib/CommonLib/LoopFilter.cpp
+++ b/source/Lib/CommonLib/LoopFilter.cpp
@@ -700,6 +700,15 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu )
   const Position& pos = cu.blocks[cu.chType].pos();
 
   m_stLFCUParam.internalEdge = true;
+#if JVET_P1004_REMOVE_BRICKS
+#if JVET_P1006_PICTURE_HEADER
+  m_stLFCUParam.leftEdge     = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1,  0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() );
+  m_stLFCUParam.topEdge      = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset(  0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() );
+#else
+  m_stLFCUParam.leftEdge     = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1,  0 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() );
+  m_stLFCUParam.topEdge      = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset(  0, -1 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() );
+#endif
+#else
 #if JVET_P1006_PICTURE_HEADER
   m_stLFCUParam.leftEdge     = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1,  0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() );
   m_stLFCUParam.topEdge      = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset(  0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() );
@@ -707,6 +716,7 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu )
   m_stLFCUParam.leftEdge     = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1,  0 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() );
   m_stLFCUParam.topEdge      = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset(  0, -1 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() );
 #endif
+#endif
 }
 
 unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const Position& localPos ) const
@@ -972,10 +982,18 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg
       // Derive neighboring PU index
       if (edgeDir == EDGE_VER)
       {
+#if JVET_P1004_REMOVE_BRICKS
+#if JVET_P1006_PICTURE_HEADER
+        if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()))
+#else
+        if (!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()))
+#endif
+#else
 #if JVET_P1006_PICTURE_HEADER
         if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()))
 #else
         if (!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()))
+#endif
 #endif
         {
           m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0;
@@ -984,10 +1002,18 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg
       }
       else  // (iDir == EDGE_HOR)
       {
+#if JVET_P1004_REMOVE_BRICKS
+#if JVET_P1006_PICTURE_HEADER
+        if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()))
+#else
+        if (!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()))
+#endif
+#else
 #if JVET_P1006_PICTURE_HEADER
         if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()))
 #else
         if (!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()))
+#endif
 #endif
         {
           m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0;
@@ -1255,18 +1281,34 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
 
       if (edgeDir == EDGE_VER)
       {
+#if JVET_P1004_REMOVE_BRICKS
+#if JVET_P1006_PICTURE_HEADER
+        CHECK(!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available");
+#else
+        CHECK(!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available");
+#endif
+#else
 #if JVET_P1006_PICTURE_HEADER
         CHECK(!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available");
 #else
         CHECK(!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available");
+#endif
 #endif
       }
       else  // (iDir == EDGE_HOR)
       {
+#if JVET_P1004_REMOVE_BRICKS
+#if JVET_P1006_PICTURE_HEADER
+        CHECK(!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available");
+#else
+        CHECK(!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available");
+#endif
+#else
 #if JVET_P1006_PICTURE_HEADER
         CHECK(!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available");
 #else
         CHECK(!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available");
+#endif
 #endif
       }
 
diff --git a/source/Lib/CommonLib/MCTS.cpp b/source/Lib/CommonLib/MCTS.cpp
index a8eb00149..0e5855bf4 100644
--- a/source/Lib/CommonLib/MCTS.cpp
+++ b/source/Lib/CommonLib/MCTS.cpp
@@ -90,6 +90,25 @@ void MCTSHelper::clipMvToArea( Mv& rcMv, const Area& block, const Area& clipArea
 
 Area MCTSHelper::getTileArea( const CodingStructure* cs, const int ctuAddr )
 {
+#if JVET_P1004_REMOVE_BRICKS
+  const PPS *pps = cs->pps;
+  const int  maxCUWidth  = cs->pcv->maxCUWidth;
+  const int  maxCUHeight = cs->pcv->maxCUHeight;
+
+  const uint32_t tileIdx = pps->getTileIdx( (uint32_t)ctuAddr );
+  const uint32_t tileX = tileIdx % pps->getNumTileColumns();
+  const uint32_t tileY = tileIdx / pps->getNumTileColumns();
+  
+  const int tileWidthtInCtus = pps->getTileColumnWidth( tileX );
+  const int tileHeightInCtus = pps->getTileRowHeight  ( tileY );  
+  const int tileXPosInCtus   = pps->getTileColumnBd( tileX );
+  const int tileYPosInCtus   = pps->getTileRowBd( tileY );
+
+  const int tileLeftTopPelPosX = maxCUWidth * tileXPosInCtus;
+  const int tileLeftTopPelPosY = maxCUHeight * tileYPosInCtus;
+  const int tileRightBottomPelPosX = std::min<int>( ( ( tileWidthtInCtus + tileXPosInCtus ) * maxCUWidth ), (int)cs->picture->lwidth() ) - 1;
+  const int tileRightBottomPelPosY = std::min<int>( ( ( tileHeightInCtus + tileYPosInCtus ) * maxCUHeight ), (int)cs->picture->lheight() ) - 1;
+#else
   const BrickMap* tileMap = cs->picture->brickMap;
   const int       tileIdx = tileMap->getBrickIdxRsMap( ctuAddr );
   const Brick&  currentTile = tileMap->bricks[tileIdx];
@@ -109,6 +128,7 @@ Area MCTSHelper::getTileArea( const CodingStructure* cs, const int ctuAddr )
   const int tileLeftTopPelPosY = maxCUHeight * tileYPosInCtus;
   const int tileRightBottomPelPosX = std::min<int>( ( ( tileWidthtInCtus + tileXPosInCtus ) * maxCUWidth ), (int)cs->picture->lwidth() ) - 1;
   const int tileRightBottomPelPosY = std::min<int>( ( ( tileHeightInCtus + tileYPosInCtus ) * maxCUHeight ), (int)cs->picture->lheight() ) - 1;
+#endif
 
   return Area( tileLeftTopPelPosX, tileLeftTopPelPosY, tileRightBottomPelPosX - tileLeftTopPelPosX + 1, tileRightBottomPelPosY - tileLeftTopPelPosY + 1 );
 }
diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index 277d192b4..4be2aea8f 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -438,6 +438,7 @@ bool Scheduler::getNextCtu( Position& pos, int ctuLine, int offset)
 // ---------------------------------------------------------------------------
 
 
+#if !JVET_P1004_REMOVE_BRICKS
 Brick::Brick()
 : m_widthInCtus     (0)
 , m_heightInCtus    (0)
@@ -781,10 +782,13 @@ uint32_t BrickMap::getSubstreamForCtuAddr(const uint32_t ctuAddr, const bool add
   return subStrm;
 }
 
+#endif
 
 Picture::Picture()
 {
+#if !JVET_P1004_REMOVE_BRICKS
   brickMap             = nullptr;
+#endif
   cs                   = nullptr;
   m_bIsBorderExtended  = false;
   usedByCurr           = false;
@@ -867,12 +871,14 @@ void Picture::destroy()
   }
   SEIs.clear();
 
+#if !JVET_P1004_REMOVE_BRICKS
   if ( brickMap )
   {
     brickMap->destroy();
     delete brickMap;
     brickMap = nullptr;
   }
+#endif
   if (m_spliceIdx)
   {
     delete[] m_spliceIdx;
@@ -967,12 +973,14 @@ void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmc
   SEIs.clear();
   clearSliceBuffer();
 
+#if !JVET_P1004_REMOVE_BRICKS
   if( brickMap )
   {
     brickMap->destroy();
     delete brickMap;
     brickMap = nullptr;
   }
+#endif
 
   const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc();
   const int          iWidth = pps.getPicWidthInLumaSamples();
@@ -1003,8 +1011,10 @@ void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmc
   cs->pcv     = pps.pcv;
   m_conformanceWindow = pps.getConformanceWindow();
 
+#if !JVET_P1004_REMOVE_BRICKS
   brickMap = new BrickMap;
   brickMap->create( sps, pps );
+#endif
   if (m_spliceIdx == NULL)
   {
     m_ctuNums = cs->pcv->sizeInCtus;
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 720940148..9645be4a9 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -116,6 +116,7 @@ class AQpLayer;
 typedef std::list<SEI*> SEIMessages;
 
 
+#if !JVET_P1004_REMOVE_BRICKS
 class Brick
 {
 private:
@@ -183,6 +184,7 @@ struct BrickMap
   void initBrickMap( const SPS& sps, const PPS& pps );
   void initCtuBsRsAddrMap();
 };
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
 #define M_BUFS(JID,PID) m_bufs[JID][PID]
@@ -322,7 +324,9 @@ public:
   Slice        *swapSliceObject(Slice * p, uint32_t i);
   void         clearSliceBuffer();
 
+#if !JVET_P1004_REMOVE_BRICKS
   BrickMap*     brickMap;
+#endif
   MCTSInfo     mctsInfo;
   std::vector<AQpLayer*> aqlayer;
 
diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp
index 9886fc514..fcb7966dc 100644
--- a/source/Lib/CommonLib/Quant.cpp
+++ b/source/Lib/CommonLib/Quant.cpp
@@ -115,7 +115,11 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int
     const bool useJQP = ( abs(TU::getICTMode(tu)) == 2 );
 
     chromaQpOffset += tu.cs->pps->getQpOffset            ( useJQP ? JOINT_CbCr : compID );
+#if JVET_P1004_REMOVE_BRICKS
+    chromaQpOffset += tu.cu->slice->getSliceChromaQpDelta( useJQP ? JOINT_CbCr : compID );
+#else
     chromaQpOffset += tu.cs->slice->getSliceChromaQpDelta( useJQP ? JOINT_CbCr : compID );
+#endif
 
     chromaQpOffset += tu.cs->pps->getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).u.offset[int( useJQP ? JOINT_CbCr : compID ) - 1];
   }
diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp
index eb5a89edc..0abfb4994 100644
--- a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp
+++ b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp
@@ -839,7 +839,11 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure&
 #endif
 
   // check cross tile flags
+#if JVET_P1004_REMOVE_BRICKS
+  const bool isLoopFilterAcrossTilePPS = cs.pps->getLoopFilterAcrossTilesEnabledFlag();
+#else
   const bool isLoopFilterAcrossTilePPS = cs.pps->getLoopFilterAcrossBricksEnabledFlag();
+#endif
   if (!isLoopFilterAcrossTilePPS)
   {
     isLeftAvail       = (!isLeftAvail)       ? false : CU::isSameTile(*cuCurr, *cuLeft);
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 9d7bb24c8..d7b09f030 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -80,6 +80,9 @@ Slice::Slice()
 , m_pcSPS                         ( NULL )
 , m_pcPPS                         ( NULL )
 , m_pcPic                         ( NULL )
+#if JVET_P1006_PICTURE_HEADER
+, m_pcPicHeader                   ( NULL )
+#endif
 , m_colFromL0Flag                 ( true )
 #if !JVET_P1006_PICTURE_HEADER
 , m_noOutputPriorPicsFlag         ( false )
@@ -97,21 +100,28 @@ Slice::Slice()
 #endif
 , m_uiTLayer                      ( 0 )
 , m_bTLayerSwitchingFlag          ( false )
+#if !JVET_P1004_REMOVE_BRICKS
 , m_sliceMode                     ( NO_SLICES )
 , m_sliceArgument                 ( 0 )
 , m_sliceCurStartCtuTsAddr        ( 0 )
 , m_sliceCurEndCtuTsAddr          ( 0 )
+#endif
 , m_independentSliceIdx           ( 0 )
 , m_nextSlice                     ( false )
 , m_sliceBits                     ( 0 )
 , m_bFinalized                    ( false )
+#if !JVET_P1004_REMOVE_BRICKS
 , m_sliceCurStartBrickIdx         ( 0 )
 , m_sliceCurEndBrickIdx           ( 0 )
 , m_sliceNumBricks                ( 0 )
 , m_sliceIdx                      ( 0 )
+#endif
 , m_bTestWeightPred               ( false )
 , m_bTestWeightBiPred             ( false )
 , m_substreamSizes                ( )
+#if JVET_P1004_REMOVE_BRICKS
+, m_numEntryPoints                ( 0 )
+#endif
 , m_cabacInitFlag                 ( false )
 #if !JVET_P1006_PICTURE_HEADER
 , m_jointCbCrSignFlag             ( false )
@@ -179,10 +189,17 @@ Slice::Slice()
   }
 
   memset(m_alfApss, 0, sizeof(m_alfApss));
+#if JVET_P1004_REMOVE_BRICKS
+
+  m_sliceMap.initSliceMap();
+#endif
 }
 
 Slice::~Slice()
 {
+#if JVET_P1004_REMOVE_BRICKS
+  m_sliceMap.initSliceMap();
+#endif
 }
 
 
@@ -277,6 +294,27 @@ void Slice::inheritFromPicHeader( PicHeader *picHeader, const PPS *pps, const SP
   setTileGroupApsIdChroma(picHeader->getAlfApsIdChroma());   
 }
 
+#endif
+#if JVET_P1004_REMOVE_BRICKS
+void  Slice::setNumEntryPoints( const PPS *pps ) 
+{
+  uint32_t ctuAddr, ctuX, ctuY;
+  m_numEntryPoints = 0;
+
+  // count the number of CTUs that align with either the start of a tile, or with an entropy coding sync point
+  // ignore the first CTU since it doesn't count as an entry point
+  for( uint32_t i = 1; i < m_sliceMap.getNumCtuInSlice(); i++ ) 
+  {
+    ctuAddr = m_sliceMap.getCtuAddrInSlice( i );
+    ctuX = ( ctuAddr % pps->getPicWidthInCtu() );
+    ctuY = ( ctuAddr / pps->getPicWidthInCtu() );
+    if( pps->ctuIsTileColBd( ctuX ) && (pps->ctuIsTileRowBd( ctuY ) || pps->getEntropyCodingSyncEnabledFlag() ) ) 
+    {
+      m_numEntryPoints++;
+    }
+  }
+}
+
 #endif
 void Slice::setDefaultClpRng( const SPS& sps )
 {
@@ -815,6 +853,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
 
   if( cpyAlmostAll ) m_pcPic  = pSrc->m_pcPic;
 
+#if JVET_P1006_PICTURE_HEADER
+  m_pcPicHeader          = pSrc->m_pcPicHeader;
+#endif
   m_colFromL0Flag        = pSrc->m_colFromL0Flag;
   m_colRefIdx            = pSrc->m_colRefIdx;
 
@@ -834,10 +875,14 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_uiTLayer                      = pSrc->m_uiTLayer;
   m_bTLayerSwitchingFlag          = pSrc->m_bTLayerSwitchingFlag;
 
+#if JVET_P1004_REMOVE_BRICKS
+  m_sliceMap                      = pSrc->m_sliceMap;
+#else
   m_sliceMode                     = pSrc->m_sliceMode;
   m_sliceArgument                 = pSrc->m_sliceArgument;
   m_sliceCurStartCtuTsAddr        = pSrc->m_sliceCurStartCtuTsAddr;
   m_sliceCurEndCtuTsAddr          = pSrc->m_sliceCurEndCtuTsAddr;
+#endif
   m_independentSliceIdx           = pSrc->m_independentSliceIdx;
   m_nextSlice                     = pSrc->m_nextSlice;
   m_clpRngs                       = pSrc->m_clpRngs;
@@ -2202,6 +2247,35 @@ void ChromaQpMappingTable::derivedChromaQPMappingTables()
   }
 }
 
+#if JVET_P1004_REMOVE_BRICKS
+SliceMap::SliceMap()
+: m_sliceID              (0)
+, m_numTilesInSlice      (0)
+, m_numCtuInSlice        (0)
+{
+  m_ctuAddrInSlice.clear();
+}
+
+SliceMap::~SliceMap()
+{
+  m_numCtuInSlice = 0;
+  m_ctuAddrInSlice.clear();
+}
+
+RectSlice::RectSlice()
+: m_tileIdx            (0)
+, m_sliceWidthInTiles  (0)
+, m_sliceHeightInTiles (0)
+, m_numSlicesInTile    (0)
+, m_sliceHeightInCtu   (0)
+{
+}
+
+RectSlice::~RectSlice()
+{
+}
+
+#endif
 PPSRExt::PPSRExt()
 : m_crossComponentPredictionEnabledFlag(false)
 // m_log2SaoOffsetScale initialized below
@@ -2236,9 +2310,24 @@ PPS::PPS()
 , m_subPicIdSignallingPresentFlag    (0)
 , m_subPicIdLen                      (16)
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+, m_noPicPartitionFlag               (1)
+, m_log2CtuSize                      (0)
+, m_ctuSize                          (0)
+, m_picWidthInCtu                    (0)
+, m_picHeightInCtu                   (0)
+, m_numTileCols                      (1)
+, m_numTileRows                      (1)
+, m_rectSliceFlag                    (1)  
+, m_numSlicesInPic                   (1)
+, m_tileIdxDeltaPresentFlag          (0)
+, m_loopFilterAcrossTilesEnabledFlag (1)
+, m_loopFilterAcrossSlicesEnabledFlag(0)
+#endif
 , m_TransquantBypassEnabledFlag      (false)
 , m_log2MaxTransformSkipBlockSize    (2)
 , m_entropyCodingSyncEnabledFlag     (false)
+#if !JVET_P1004_REMOVE_BRICKS
 , m_loopFilterAcrossBricksEnabledFlag (true)
 , m_uniformTileSpacingFlag           (false)
 , m_numTileColumnsMinus1             (0)
@@ -2254,6 +2343,7 @@ PPS::PPS()
 , m_numBricksInPic                   (1)
 , m_signalledSliceIdFlag             (false)
 ,m_signalledSliceIdLengthMinus1      (0)
+#endif
 , m_constantSliceHeaderParamsEnabledFlag (false)
 , m_PPSDepQuantEnabledIdc            (0)
 , m_PPSRefPicListSPSIdc0             (0)
@@ -2273,7 +2363,9 @@ PPS::PPS()
 , m_pictureHeaderExtensionPresentFlag(0)
 #endif
 , m_sliceHeaderExtensionPresentFlag  (false)
+#if !JVET_P1004_REMOVE_BRICKS
 , m_loopFilterAcrossSlicesEnabledFlag(false)
+#endif
 , m_listsModificationPresentFlag     (0)
 #if !JVET_P1006_PICTURE_HEADER
 , m_loopFilterAcrossVirtualBoundariesDisabledFlag(false)
@@ -2292,13 +2384,275 @@ PPS::PPS()
   ::memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX));
   ::memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY));
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  m_tileColWidth.clear();
+  m_tileRowHeight.clear();
+  m_tileColBd.clear();
+  m_tileRowBd.clear();
+  m_ctuToTileCol.clear();
+  m_ctuToTileRow.clear();
+  m_rectSlices.clear();
+  m_sliceMap.clear();
+#endif
 }
 
 PPS::~PPS()
 {
+#if JVET_P1004_REMOVE_BRICKS
+  m_tileColWidth.clear();
+  m_tileRowHeight.clear();
+  m_tileColBd.clear();
+  m_tileRowBd.clear();
+  m_ctuToTileCol.clear();
+  m_ctuToTileRow.clear();
+  m_rectSlices.clear();
+  m_sliceMap.clear();
+
+#endif
   delete pcv;
 }
 
+#if JVET_P1004_REMOVE_BRICKS
+/**
+ - reset tile and slice parameters and lists
+ */
+void PPS::resetTileSliceInfo()
+{
+  m_numExpTileCols = 0;
+  m_numExpTileRows = 0;
+  m_numTileCols    = 0;
+  m_numTileRows    = 0;
+  m_numSlicesInPic = 0;
+  m_tileColWidth.clear();
+  m_tileRowHeight.clear();
+  m_tileColBd.clear();
+  m_tileRowBd.clear();
+  m_ctuToTileCol.clear();
+  m_ctuToTileRow.clear();
+  m_rectSlices.clear();
+  m_sliceMap.clear();
+}
+
+/**
+ - initialize tile row/column sizes and boundaries
+ */
+void PPS::initTiles()
+{
+  int       colIdx, rowIdx;
+  int       ctuX, ctuY;
+  
+  // check explicit tile column sizes
+  uint32_t  remainingWidthInCtu  = m_picWidthInCtu;
+  for( colIdx = 0; colIdx < m_numExpTileCols; colIdx++ )
+  {
+    CHECK(m_tileColWidth[colIdx] > remainingWidthInCtu,    "Tile column width exceeds picture width");
+    remainingWidthInCtu -= m_tileColWidth[colIdx];
+  }
+
+  // divide remaining picture width into uniform tile columns
+  uint32_t  uniformTileColWidth = m_tileColWidth[colIdx-1];
+  while( remainingWidthInCtu > 0 ) 
+  {
+    CHECK(colIdx >= MAX_TILE_COLS, "Number of tile columns exceeds valid range");
+    uniformTileColWidth = std::min(remainingWidthInCtu, uniformTileColWidth);
+    m_tileColWidth.push_back( uniformTileColWidth );
+    remainingWidthInCtu -= uniformTileColWidth;
+    colIdx++;
+  }
+  m_numTileCols = colIdx;
+    
+  // check explicit tile row sizes
+  uint32_t  remainingHeightInCtu  = m_picHeightInCtu;
+  for( rowIdx = 0; rowIdx < m_numExpTileRows; rowIdx++ )
+  {
+    CHECK(m_tileRowHeight[rowIdx] > remainingHeightInCtu,     "Tile row height exceeds picture height");
+    remainingHeightInCtu -= m_tileRowHeight[rowIdx];
+  }
+    
+  // divide remaining picture height into uniform tile rows
+  uint32_t  uniformTileRowHeight = m_tileRowHeight[rowIdx - 1];
+  while( remainingHeightInCtu > 0 ) 
+  {
+    CHECK(rowIdx >= MAX_TILE_ROWS, "Number of tile rows exceeds valid range");
+    uniformTileRowHeight = std::min(remainingHeightInCtu, uniformTileRowHeight);
+    m_tileRowHeight.push_back( uniformTileRowHeight );
+    remainingHeightInCtu -= uniformTileRowHeight;
+    rowIdx++;
+  }
+  m_numTileRows = rowIdx;
+
+  // set left column bounaries
+  m_tileColBd.push_back( 0 );
+  for( colIdx = 0; colIdx < m_numTileCols; colIdx++ )
+  {
+    m_tileColBd.push_back( m_tileColBd[ colIdx ] + m_tileColWidth[ colIdx ] );
+  }
+  
+  // set top row bounaries
+  m_tileRowBd.push_back( 0 );
+  for( rowIdx = 0; rowIdx < m_numTileRows; rowIdx++ )
+  {
+    m_tileRowBd.push_back( m_tileRowBd[ rowIdx ] + m_tileRowHeight[ rowIdx ] );
+  }
+
+  // set mapping between horizontal CTU address and tile column index
+  colIdx = 0;
+  for( ctuX = 0; ctuX <= m_picWidthInCtu; ctuX++ ) 
+  {
+    if( ctuX == m_tileColBd[ colIdx + 1 ] )
+    {
+      colIdx++;
+    }
+    m_ctuToTileCol.push_back( colIdx );
+  }
+  
+  // set mapping between vertical CTU address and tile row index
+  rowIdx = 0;
+  for( ctuY = 0; ctuY <= m_picHeightInCtu; ctuY++ ) 
+  {
+    if( ctuY == m_tileRowBd[ rowIdx + 1 ] )
+    {
+      rowIdx++;
+    }
+    m_ctuToTileRow.push_back( rowIdx );
+  }
+}
+
+/**
+ - initialize memory for rectangular slice parameters
+ */
+void PPS::initRectSlices()
+{ 
+  CHECK(m_numSlicesInPic > MAX_SLICES, "Number of slices in picture exceeds valid range");
+  m_rectSlices.resize(m_numSlicesInPic);
+}
+
+/**
+ - initialize mapping between rectangular slices and CTUs
+ */
+void PPS::initRectSliceMap()
+{
+  uint32_t  ctuY;
+  uint32_t  tileX, tileY;
+    
+  // allocate new memory for slice list
+  CHECK(m_numSlicesInPic > MAX_SLICES, "Number of slices in picture exceeds valid range");
+  m_sliceMap.resize( m_numSlicesInPic );
+
+  // generate CTU maps for all rectangular slices in picture
+  for( uint32_t i = 0; i < m_numSlicesInPic; i++ )
+  {
+    m_sliceMap[ i ].initSliceMap();
+
+    // get position of first tile in slice
+    tileX =  m_rectSlices[ i ].getTileIdx() % m_numTileCols;
+    tileY =  m_rectSlices[ i ].getTileIdx() / m_numTileCols;
+    
+    // infer slice size for last slice in picture
+    if( i == m_numSlicesInPic-1 ) 
+    {
+      m_rectSlices[ i ].setSliceWidthInTiles ( m_numTileCols - tileX );
+      m_rectSlices[ i ].setSliceHeightInTiles( m_numTileRows - tileY );
+      m_rectSlices[ i ].setNumSlicesInTile( 1 );
+    }
+
+    // set slice index
+    m_sliceMap[ i ].setSliceID(i);
+    
+    // complete tiles within a single slice case
+    if( m_rectSlices[ i ].getSliceWidthInTiles( ) > 1 || m_rectSlices[ i ].getSliceHeightInTiles( ) > 1)
+    {
+      for( uint32_t j = 0; j < m_rectSlices[ i ].getSliceHeightInTiles( ); j++ )
+      {
+        for( uint32_t k = 0; k < m_rectSlices[ i ].getSliceWidthInTiles( ); k++ )
+        {
+          m_sliceMap[ i ].addCtusToSlice( getTileColumnBd(tileX + k), getTileColumnBd(tileX + k +1),
+                                          getTileRowBd(tileY + j), getTileRowBd(tileY + j +1), m_picWidthInCtu);
+        }
+      }
+    }
+    // multiple slices within a single tile case
+    else 
+    {
+      uint32_t  numSlicesInTile = m_rectSlices[ i ].getNumSlicesInTile( );
+
+      ctuY = getTileRowBd( tileY );
+      for( uint32_t j = 0; j < numSlicesInTile-1; j++ ) 
+      {
+        m_sliceMap[ i ].addCtusToSlice( getTileColumnBd(tileX), getTileColumnBd(tileX+1),
+                                        ctuY, ctuY + m_rectSlices[ i ].getSliceHeightInCtu(), m_picWidthInCtu);
+        ctuY += m_rectSlices[ i ].getSliceHeightInCtu();
+        i++;
+        m_sliceMap[ i ].setSliceID(i);
+      }
+
+      // infer slice height for last slice in tile
+      CHECK( ctuY >= getTileRowBd( tileY + 1 ), "Invalid rectangular slice signalling");
+      m_rectSlices[ i ].setSliceHeightInCtu( getTileRowBd( tileY + 1 ) - ctuY );
+      m_sliceMap[ i ].addCtusToSlice( getTileColumnBd(tileX), getTileColumnBd(tileX+1),
+                                      ctuY, getTileRowBd( tileY + 1 ), m_picWidthInCtu);
+    } 
+  }
+
+  // check for valid rectangular slice map
+  checkSliceMap();
+}
+
+void PPS::initRasterSliceMap( std::vector<uint32_t> numTilesInSlice )
+{
+  uint32_t tileIdx = 0;
+  setNumSlicesInPic( (uint32_t) numTilesInSlice.size() );
+
+  // allocate new memory for slice list
+  CHECK(m_numSlicesInPic > MAX_SLICES, "Number of slices in picture exceeds valid range");
+  m_sliceMap.resize( m_numSlicesInPic );
+
+  for( uint32_t sliceIdx = 0; sliceIdx < numTilesInSlice.size(); sliceIdx++ ) 
+  {
+    m_sliceMap[sliceIdx].initSliceMap();
+    m_sliceMap[sliceIdx].setSliceID( tileIdx );
+    m_sliceMap[sliceIdx].setNumTilesInSlice( numTilesInSlice[sliceIdx] );
+    for( uint32_t idx = 0; idx < numTilesInSlice[sliceIdx]; idx++ )
+    {
+      uint32_t tileX = tileIdx % getNumTileColumns();
+      uint32_t tileY = tileIdx / getNumTileColumns();
+      CHECK(tileY >= getNumTileRows(), "Number of tiles in slice exceeds the remaining number of tiles in picture");
+
+      m_sliceMap[sliceIdx].addCtusToSlice(getTileColumnBd(tileX), getTileColumnBd(tileX + 1),
+                                          getTileRowBd(tileY), getTileRowBd(tileY + 1), 
+                                          getPicWidthInCtu());
+      tileIdx++;
+    }
+  }
+
+  // check for valid raster-scan slice map
+  checkSliceMap();
+}
+
+/**
+ - check if slice map covers the entire picture without skipping or duplicating any CTU positions
+ */
+void PPS::checkSliceMap()
+{
+  uint32_t i;
+  std::vector<uint32_t>  ctuList, sliceList;
+  uint32_t picSizeInCtu = getPicWidthInCtu() * getPicHeightInCtu();
+  for( i = 0; i < m_numSlicesInPic; i++ )
+  {
+    sliceList = m_sliceMap[ i ].getCtuAddrList();
+    ctuList.insert( ctuList.end(), sliceList.begin(), sliceList.end() );
+  }  
+  CHECK( ctuList.size() < picSizeInCtu, "Slice map contains too few CTUs");
+  CHECK( ctuList.size() > picSizeInCtu, "Slice map contains too many CTUs");
+  std::sort( ctuList.begin(), ctuList.end() );   
+  for( i = 1; i < ctuList.size(); i++ )
+  {
+    CHECK( ctuList[i] > ctuList[i-1]+1, "CTU missing in slice map");
+    CHECK( ctuList[i] == ctuList[i-1],  "CTU duplicated in slice map");
+  }
+}
+
+#endif
 APS::APS()
 : m_APSId(0)
 , m_temporalId( 0 )
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 589b64eb7..71521b3e9 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -633,6 +633,78 @@ struct ChromaQpMappingTable : ChromaQpMappingTableParams
   void      derivedChromaQPMappingTables();
   void      setParams(const ChromaQpMappingTableParams &params, const int qpBdOffset);
 };
+#if JVET_P1004_REMOVE_BRICKS
+
+class SliceMap
+{
+private:
+  uint32_t               m_sliceID;                           //!< slice identifier (slice index for rectangular slices, slice address for raser-scan slices)
+  uint32_t               m_numTilesInSlice;                   //!< number of tiles in slice (raster-scan slices only)
+  uint32_t               m_numCtuInSlice;                     //!< number of CTUs in the slice
+  std::vector<uint32_t>  m_ctuAddrInSlice;                    //!< raster-scan addresses of all the CTUs in the slice
+
+public:
+  SliceMap();
+  virtual ~SliceMap();
+
+  void                   setSliceID( uint32_t u )             { m_sliceID = u;            }
+  uint32_t               getSliceID() const                   { return m_sliceID;         }
+  void                   setNumTilesInSlice( uint32_t u )     { m_numTilesInSlice = u;    }
+  uint32_t               getNumTilesInSlice() const           { return m_numTilesInSlice; }
+  void                   setNumCtuInSlice( uint32_t u )       { m_numCtuInSlice = u;      }
+  uint32_t               getNumCtuInSlice() const             { return m_numCtuInSlice;   }
+  std::vector<uint32_t>  getCtuAddrList( ) const              { return m_ctuAddrInSlice;  }
+  uint32_t               getCtuAddrInSlice( int idx ) const   { CHECK(idx >= m_ctuAddrInSlice.size(), "CTU index exceeds number of CTUs in slice."); return m_ctuAddrInSlice[idx]; }
+
+  void  initSliceMap() 
+  {
+    m_sliceID = 0;
+    m_numTilesInSlice = 0;
+    m_numCtuInSlice = 0;
+    m_ctuAddrInSlice.clear();
+  }
+
+  void  addCtusToSlice( uint32_t startX, uint32_t stopX, uint32_t startY, uint32_t stopY, uint32_t picWidthInCtbsY ) 
+  {
+    CHECK( startX >= stopX || startY >= stopY, "Invalid slice definition");
+    for( uint32_t ctbY = startY; ctbY < stopY; ctbY++ ) 
+    {
+      for( uint32_t ctbX = startX; ctbX < stopX; ctbX++ ) 
+      {
+        m_ctuAddrInSlice.push_back( ctbY * picWidthInCtbsY + ctbX );
+        m_numCtuInSlice++;
+      }
+    }
+  }
+};
+
+class RectSlice
+{
+private:
+  uint32_t         m_tileIdx;                           //!< tile index corresponding to the first CTU in the slice
+  uint32_t         m_sliceWidthInTiles;                 //!< slice width in units of tiles
+  uint32_t         m_sliceHeightInTiles;                //!< slice height in units of tiles
+  uint32_t         m_numSlicesInTile;                   //!< number of slices in current tile for the special case of multiple slices inside a single tile
+  uint32_t         m_sliceHeightInCtu;                  //!< slice height in units of CTUs for the special case of multiple slices inside a single tile
+  
+public:
+  RectSlice();
+  virtual ~RectSlice();
+  
+  void             setSliceWidthInTiles( uint32_t u )   { m_sliceWidthInTiles = u;      }
+  uint32_t         getSliceWidthInTiles( ) const        { return  m_sliceWidthInTiles;  }
+  void             setSliceHeightInTiles( uint32_t u )  { m_sliceHeightInTiles = u;     }
+  uint32_t         getSliceHeightInTiles( ) const       { return  m_sliceHeightInTiles; }
+  void             setNumSlicesInTile( uint32_t u )     { m_numSlicesInTile = u;        }
+  uint32_t         getNumSlicesInTile( ) const          { return  m_numSlicesInTile;    }
+  void             setSliceHeightInCtu( uint32_t u )    { m_sliceHeightInCtu = u;       }
+  uint32_t         getSliceHeightInCtu( ) const         { return  m_sliceHeightInCtu;   }
+  void             setTileIdx( uint32_t u )             { m_tileIdx = u;                }
+  uint32_t         getTileIdx( ) const                  { return  m_tileIdx;            }
+
+};
+#endif
+
 class DPS
 {
 private:
@@ -1420,11 +1492,36 @@ private:
   bool             m_subPicIdSignallingPresentFlag;     //!< indicates the presence of sub-picture ID signalling in the PPS
   uint32_t         m_subPicIdLen;                       //!< sub-picture ID length in bits
   uint8_t          m_subPicId[MAX_NUM_SUB_PICS];        //!< sub-picture ID for each sub-picture in the sequence
+#endif
+#if JVET_P1004_REMOVE_BRICKS
+  bool             m_noPicPartitionFlag;                //!< no picture partitioning flag - single slice, single tile
+  uint8_t          m_log2CtuSize;                       //!< log2 of the CTU size - required to match corresponding value in SPS
+  uint8_t          m_ctuSize;                           //!< CTU size
+  uint32_t         m_picWidthInCtu;                     //!< picture width in units of CTUs
+  uint32_t         m_picHeightInCtu;                    //!< picture height in units of CTUs
+  uint32_t         m_numExpTileCols;                    //!< number of explicitly specified tile columns
+  uint32_t         m_numExpTileRows;                    //!< number of explicitly specified tile rows
+  uint32_t         m_numTileCols;                       //!< number of tile columns
+  uint32_t         m_numTileRows;                       //!< number of tile rows
+  std::vector<uint32_t> m_tileColWidth;                 //!< tile column widths in units of CTUs
+  std::vector<uint32_t> m_tileRowHeight;                //!< tile row heights in units of CTUs
+  std::vector<uint32_t> m_tileColBd;                    //!< tile column left-boundaries in units of CTUs
+  std::vector<uint32_t> m_tileRowBd;                    //!< tile row top-boundaries in units of CTUs  
+  std::vector<uint32_t> m_ctuToTileCol;                 //!< mapping between CTU horizontal address and tile column index
+  std::vector<uint32_t> m_ctuToTileRow;                 //!< mapping between CTU vertical address and tile row index
+  bool             m_rectSliceFlag;                     //!< rectangular slice flag  
+  uint32_t         m_numSlicesInPic;                    //!< number of rectangular slices in the picture (raster-scan slice specified at slice level)
+  bool             m_tileIdxDeltaPresentFlag;           //!< tile index delta present flag
+  std::vector<RectSlice> m_rectSlices;                  //!< list of rectangular slice signalling parameters
+  std::vector<SliceMap>  m_sliceMap;                    //!< list of CTU maps for each slice in the picture
+  bool             m_loopFilterAcrossTilesEnabledFlag;  //!< loop filtering applied across tiles flag
+  bool             m_loopFilterAcrossSlicesEnabledFlag; //!< loop filtering applied across slices flag
 #endif
   bool             m_TransquantBypassEnabledFlag;       //!< Indicates presence of cu_transquant_bypass_flag in CUs.
   int              m_log2MaxTransformSkipBlockSize;
   bool             m_entropyCodingSyncEnabledFlag;      //!< Indicates the presence of wavefronts
 
+#if !JVET_P1004_REMOVE_BRICKS
   bool             m_loopFilterAcrossBricksEnabledFlag;
   bool             m_uniformTileSpacingFlag;
   int              m_numTileColumnsMinus1;
@@ -1454,6 +1551,7 @@ private:
   int              m_signalledSliceIdLengthMinus1;
   std::vector<int> m_sliceId;
 
+#endif
   bool              m_constantSliceHeaderParamsEnabledFlag;
   int               m_PPSDepQuantEnabledIdc;
   int               m_PPSRefPicListSPSIdc0;
@@ -1475,7 +1573,9 @@ private:
   bool             m_pictureHeaderExtensionPresentFlag;   //< picture header extension flags present in picture headers or not
 #endif
   bool             m_sliceHeaderExtensionPresentFlag;
+#if !JVET_P1004_REMOVE_BRICKS
   bool             m_loopFilterAcrossSlicesEnabledFlag;
+#endif
   bool             m_deblockingFilterControlPresentFlag;
   bool             m_deblockingFilterOverrideEnabledFlag;
   bool             m_ppsDeblockingFilterDisabledFlag;
@@ -1603,6 +1703,71 @@ public:
   uint32_t               getSubPicIdLen() const                                           { return  m_subPicIdLen;                        }
   void                   setSubPicId( int i, uint8_t u )                                  { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u;     }
   uint8_t                getSubPicId( int i ) const                                       { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicId[i]; }
+#endif
+#if JVET_P1004_REMOVE_BRICKS
+  void                   setNoPicPartitionFlag( bool b )                                  { m_noPicPartitionFlag = b;                     }
+  bool                   getNoPicPartitionFlag( ) const                                   { return  m_noPicPartitionFlag;                 }
+  void                   setLog2CtuSize( uint8_t u )                                      { m_log2CtuSize = u; m_ctuSize = 1 << m_log2CtuSize; 
+                                                                                            m_picWidthInCtu = (m_picWidthInLumaSamples  + m_ctuSize - 1) / m_ctuSize;  
+                                                                                            m_picHeightInCtu = (m_picHeightInLumaSamples  + m_ctuSize - 1) / m_ctuSize; }
+  uint8_t                getLog2CtuSize( ) const                                          { return  m_log2CtuSize;                        }
+  uint8_t                getCtuSize( ) const                                              { return  m_ctuSize;                            }
+  uint8_t                getPicWidthInCtu( ) const                                        { return  m_picWidthInCtu;                      }
+  uint8_t                getPicHeightInCtu( ) const                                       { return  m_picHeightInCtu;                     }
+  void                   setNumExpTileColumns( uint32_t u )                               { m_numExpTileCols = u;                         }
+  uint32_t               getNumExpTileColumns( ) const                                    { return  m_numExpTileCols;                     }
+  void                   setNumExpTileRows( uint32_t u )                                  { m_numExpTileRows = u;                         }
+  uint32_t               getNumExpTileRows( ) const                                       { return  m_numExpTileRows;                     }
+  void                   setNumTileColumns( uint32_t u )                                  { m_numTileCols = u;                            }
+  uint32_t               getNumTileColumns( ) const                                       { return  m_numTileCols;                        }
+  void                   setNumTileRows( uint32_t u )                                     { m_numTileRows = u;                            }
+  uint32_t               getNumTileRows( ) const                                          { return  m_numTileRows;                        }
+  uint32_t               getNumTiles( ) const                                             { return  m_numTileCols * m_numTileRows;        }
+  void                   setTileColumnWidths( std::vector<uint32_t> widths )              { m_tileColWidth = widths;                      }
+  void                   setTileRowHeights( std::vector<uint32_t> heights )               { m_tileRowHeight = heights;                    }
+  void                   addTileColumnWidth( uint32_t u )                                 { CHECK( m_tileColWidth.size()  >= MAX_TILE_COLS, "Number of tile columns exceeds valid range" ); m_tileColWidth.push_back(u);    }
+  void                   addTileRowHeight( uint32_t u )                                   { CHECK( m_tileRowHeight.size() >= MAX_TILE_ROWS, "Number of tile rows exceeds valid range" );    m_tileRowHeight.push_back(u);   }
+  uint32_t               getTileColumnWidth( int idx ) const                              { CHECK( idx >= m_tileColWidth.size(), "Tile column index exceeds valid range" );                 return  m_tileColWidth[idx];    }
+  uint32_t               getTileRowHeight( int idx ) const                                { CHECK( idx >= m_tileRowHeight.size(), "Tile row index exceeds valid range" );                   return  m_tileRowHeight[idx];   }  
+  uint32_t               getTileColumnBd( int idx ) const                                 { CHECK( idx >= m_tileColBd.size(), "Tile column index exceeds valid range" );                    return  m_tileColBd[idx];       }
+  uint32_t               getTileRowBd( int idx ) const                                    { CHECK( idx >= m_tileRowBd.size(), "Tile row index exceeds valid range" );                       return  m_tileRowBd[idx];       }
+  uint32_t               ctuToTileCol( int ctuX ) const                                   { CHECK( ctuX >= m_ctuToTileCol.size(), "CTU address index exceeds valid range" ); return  m_ctuToTileCol[ctuX];                  }
+  uint32_t               ctuToTileRow( int ctuY ) const                                   { CHECK( ctuY >= m_ctuToTileRow.size(), "CTU address index exceeds valid range" ); return  m_ctuToTileRow[ctuY];                  }
+  uint32_t               ctuToTileColBd( int ctuX ) const                                 { return  getTileColumnBd(ctuToTileCol( ctuX ));                                                                                  }
+  uint32_t               ctuToTileRowBd( int ctuY ) const                                 { return  getTileRowBd(ctuToTileRow( ctuY ));                                                                                     }
+  bool                   ctuIsTileColBd( int ctuX ) const                                 { return  ctuX == ctuToTileColBd( ctuX );                                                                                         }
+  bool                   ctuIsTileRowBd( int ctuY ) const                                 { return  ctuY == ctuToTileRowBd( ctuY );                                                                                         }
+  uint32_t               getTileIdx( uint32_t ctuX, uint32_t ctuY ) const                 { return (ctuToTileRow( ctuY ) * getNumTileColumns()) + ctuToTileCol( ctuX );                                                     }
+  uint32_t               getTileIdx( uint32_t ctuRsAddr) const                            { return getTileIdx( ctuRsAddr % m_picWidthInCtu,  ctuRsAddr / m_picWidthInCtu );                                                 }
+  uint32_t               getTileIdx( const Position& pos ) const                          { return getTileIdx( pos.x / m_ctuSize, pos.y / m_ctuSize );                                                                      }
+  void                   setRectSliceFlag( bool b )                                       { m_rectSliceFlag = b;                                                                                                            }
+  bool                   getRectSliceFlag( ) const                                        { return  m_rectSliceFlag;                                                                                                        }
+  void                   setNumSlicesInPic( uint32_t u )                                  { CHECK( u > MAX_SLICES, "Number of slices in picture exceeds valid range" ); m_numSlicesInPic = u;                               }
+  uint32_t               getNumSlicesInPic( ) const                                       { return  m_numSlicesInPic;                                                                                                       }
+  void                   setTileIdxDeltaPresentFlag( bool b )                             { m_tileIdxDeltaPresentFlag = b;                                                                                                  }
+  bool                   getTileIdxDeltaPresentFlag( ) const                              { return  m_tileIdxDeltaPresentFlag;                                                                                              }
+  void                   setSliceWidthInTiles( int idx, uint32_t u )                      { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    m_rectSlices[idx].setSliceWidthInTiles( u );            }
+  uint32_t               getSliceWidthInTiles( int idx ) const                            { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return  m_rectSlices[idx].getSliceWidthInTiles( );      }
+  void                   setSliceHeightInTiles( int idx, uint32_t u )                     { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    m_rectSlices[idx].setSliceHeightInTiles( u );           }
+  uint32_t               getSliceHeightInTiles( int idx ) const                           { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return  m_rectSlices[idx].getSliceHeightInTiles( );     }
+  void                   setNumSlicesInTile( int idx, uint32_t u )                        { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    m_rectSlices[idx].setNumSlicesInTile( u );              }
+  uint32_t               getNumSlicesInTile( int idx ) const                              { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return  m_rectSlices[idx].getNumSlicesInTile( );        }
+  void                   setSliceHeightInCtu( int idx, uint32_t u )                       { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    m_rectSlices[idx].setSliceHeightInCtu( u );             }
+  uint32_t               getSliceHeightInCtu( int idx ) const                             { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return  m_rectSlices[idx].getSliceHeightInCtu( );       }
+  void                   setSliceTileIdx(  int idx, uint32_t u )                          { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    m_rectSlices[idx].setTileIdx( u );                      }
+  uint32_t               getSliceTileIdx( int idx ) const                                 { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return  m_rectSlices[idx].getTileIdx( );                }
+  void                   setRectSlices( std::vector<RectSlice> rectSlices )               { m_rectSlices = rectSlices;                                                                                                      }
+  void                   setLoopFilterAcrossTilesEnabledFlag( bool b )                    { m_loopFilterAcrossTilesEnabledFlag = b;                                                                                         }
+  bool                   getLoopFilterAcrossTilesEnabledFlag( ) const                     { return  m_loopFilterAcrossTilesEnabledFlag;                                                                                     }
+  void                   setLoopFilterAcrossSlicesEnabledFlag( bool b )                   { m_loopFilterAcrossSlicesEnabledFlag = b;                                                                                        }
+  bool                   getLoopFilterAcrossSlicesEnabledFlag( ) const                    { return  m_loopFilterAcrossSlicesEnabledFlag;                                                                                    }
+  void                   resetTileSliceInfo();
+  void                   initTiles();
+  void                   initRectSlices();
+  void                   initRectSliceMap();
+  void                   initRasterSliceMap( std::vector<uint32_t> sizes );
+  void                   checkSliceMap(); 
+  SliceMap               getSliceMap( int idx ) const                                     { CHECK( idx >= m_numSlicesInPic, "Slice index exceeds valid range" );    return m_sliceMap[idx];                             }
 #endif
   void                   setTransquantBypassEnabledFlag( bool b )                         { m_TransquantBypassEnabledFlag = b;            }
   bool                   getTransquantBypassEnabledFlag() const                           { return m_TransquantBypassEnabledFlag;         }
@@ -1610,11 +1775,14 @@ public:
   uint32_t               getLog2MaxTransformSkipBlockSize() const                         { return m_log2MaxTransformSkipBlockSize; }
   void                   setLog2MaxTransformSkipBlockSize(uint32_t u)                     { m_log2MaxTransformSkipBlockSize = u; }
 
+#if !JVET_P1004_REMOVE_BRICKS
   void                   setLoopFilterAcrossBricksEnabledFlag(bool b)                     { m_loopFilterAcrossBricksEnabledFlag = b;      }
   bool                   getLoopFilterAcrossBricksEnabledFlag() const                     { return m_loopFilterAcrossBricksEnabledFlag;   }
+#endif
   bool                   getEntropyCodingSyncEnabledFlag() const                          { return m_entropyCodingSyncEnabledFlag;        }
   void                   setEntropyCodingSyncEnabledFlag(bool val)                        { m_entropyCodingSyncEnabledFlag = val;         }
 
+#if !JVET_P1004_REMOVE_BRICKS
   void                   setUniformTileSpacingFlag(bool b)                                { m_uniformTileSpacingFlag = b;                 }
   bool                   getUniformTileSpacingFlag() const                                { return m_uniformTileSpacingFlag;              }
   void                   setNumTileColumnsMinus1(int i)                                   { m_numTileColumnsMinus1 = i;                   }
@@ -1668,6 +1836,7 @@ public:
   void                   setSignalledSliceIdLengthMinus1(int val)                         { m_signalledSliceIdLengthMinus1 = val;         }
   int                    getSliceId(uint32_t columnIdx) const                             { return  m_sliceId[columnIdx];                 }
   void                   setSliceId(const std::vector<int>& val)                          { m_sliceId = val;                              }
+#endif
 
   bool                    getConstantSliceHeaderParamsEnabledFlag() const                 { return m_constantSliceHeaderParamsEnabledFlag; }
   void                    setConstantSliceHeaderParamsEnabledFlag(bool b)                 { m_constantSliceHeaderParamsEnabledFlag = b;   }
@@ -1711,8 +1880,10 @@ public:
   int                    getDeblockingFilterTcOffsetDiv2() const                          { return m_deblockingFilterTcOffsetDiv2;        } //!< get tc offset for deblocking filter
   bool                   getListsModificationPresentFlag() const                          { return m_listsModificationPresentFlag;        }
   void                   setListsModificationPresentFlag( bool b )                        { m_listsModificationPresentFlag = b;           }
+#if !JVET_P1004_REMOVE_BRICKS
   void                   setLoopFilterAcrossSlicesEnabledFlag( bool bValue )              { m_loopFilterAcrossSlicesEnabledFlag = bValue; }
   bool                   getLoopFilterAcrossSlicesEnabledFlag() const                     { return m_loopFilterAcrossSlicesEnabledFlag;   }
+#endif
 #if JVET_P1006_PICTURE_HEADER
   bool                   getPictureHeaderExtensionPresentFlag() const                     { return m_pictureHeaderExtensionPresentFlag;     }
   void                   setPictureHeaderExtensionPresentFlag(bool val)                   { m_pictureHeaderExtensionPresentFlag = val;      }
@@ -2143,19 +2314,25 @@ private:
   uint32_t                       m_uiTLayer;
   bool                       m_bTLayerSwitchingFlag;
 
+#if JVET_P1004_REMOVE_BRICKS
+  SliceMap                   m_sliceMap;                     //!< list of CTUs in current slice - raster scan CTU addresses
+#else
   SliceConstraint            m_sliceMode;
   uint32_t                       m_sliceArgument;
   uint32_t                       m_sliceCurStartCtuTsAddr;
   uint32_t                       m_sliceCurEndCtuTsAddr;
+#endif
   uint32_t                       m_independentSliceIdx;
   bool                       m_nextSlice;
   uint32_t                       m_sliceBits;
   bool                       m_bFinalized;
 
+#if !JVET_P1004_REMOVE_BRICKS
   uint32_t                   m_sliceCurStartBrickIdx;
   uint32_t                   m_sliceCurEndBrickIdx;
   uint32_t                   m_sliceNumBricks;
   uint32_t                   m_sliceIdx;
+#endif
 
   bool                       m_bTestWeightPred;
   bool                       m_bTestWeightBiPred;
@@ -2163,6 +2340,9 @@ private:
   WPACDCParam                m_weightACDCParam[MAX_NUM_COMPONENT];
   ClpRngs                    m_clpRngs;
   std::vector<uint32_t>          m_substreamSizes;
+#if JVET_P1004_REMOVE_BRICKS
+  uint32_t                   m_numEntryPoints;
+#endif
 
   bool                       m_cabacInitFlag;
 
@@ -2461,6 +2641,20 @@ public:
   void                        setHandleCraAsCvsStartFlag( bool val )                 { m_handleCraAsCvsStartFlag = val;                                   }
   bool                        getHandleCraAsCvsStartFlag() const                     { return m_handleCraAsCvsStartFlag;                                  }
 
+#if JVET_P1004_REMOVE_BRICKS
+  void                        setNumTilesInSlice( uint32_t u )                       { m_sliceMap.setNumTilesInSlice( u );                                       }
+  uint32_t                    getNumTilesInSlice() const                             { return m_sliceMap.getNumTilesInSlice();                                   }
+  void                        setSliceMap( SliceMap map )                            { m_sliceMap = map;                                                         }
+  uint32_t                    getFirstCtuRsAddrInSlice() const                       { return m_sliceMap.getCtuAddrInSlice(0);                                   }
+  void                        setSliceID( uint32_t u )                               { m_sliceMap.setSliceID( u );                                               }
+  uint32_t                    getSliceID() const                                     { return m_sliceMap.getSliceID();                                           }
+  uint32_t                    getNumCtuInSlice() const                               { return m_sliceMap.getNumCtuInSlice();                                     }
+  uint32_t                    getCtuAddrInSlice( int idx ) const                     { return m_sliceMap.getCtuAddrInSlice( idx );                               }
+  void                        initSliceMap()                                         { m_sliceMap.initSliceMap();                                                }
+  void                        addCtusToSlice( uint32_t startX, uint32_t stopX, 
+                                              uint32_t startY, uint32_t stopY, 
+                                              uint32_t picWidthInCtbsY )             { m_sliceMap.addCtusToSlice(startX, stopX, startY, stopY, picWidthInCtbsY); }
+#else
   void                        setSliceMode( SliceConstraint mode )                   { m_sliceMode = mode;                                           }
   SliceConstraint             getSliceMode() const                                   { return m_sliceMode;                                           }
   void                        setSliceArgument( uint32_t uiArgument )                    { m_sliceArgument = uiArgument;                                 }
@@ -2469,6 +2663,7 @@ public:
   uint32_t                        getSliceCurStartCtuTsAddr() const                      { return m_sliceCurStartCtuTsAddr;                              } // CTU Tile-scan address (as opposed to raster-scan)
   void                        setSliceCurEndCtuTsAddr( uint32_t ctuTsAddr )              { m_sliceCurEndCtuTsAddr = ctuTsAddr;                           } // CTU Tile-scan address (as opposed to raster-scan)
   uint32_t                        getSliceCurEndCtuTsAddr() const                        { return m_sliceCurEndCtuTsAddr;                                } // CTU Tile-scan address (as opposed to raster-scan)
+#endif
   void                        setIndependentSliceIdx( uint32_t i)                        { m_independentSliceIdx = i;                                    }
   uint32_t                        getIndependentSliceIdx() const                         { return  m_independentSliceIdx;                                }
   void                        copySliceInfo(Slice *pcSliceSrc, bool cpyAlmostAll = true);
@@ -2476,6 +2671,7 @@ public:
   uint32_t                        getSliceBits() const                                   { return m_sliceBits;                                           }
   void                        setFinalized( bool uiVal )                             { m_bFinalized = uiVal;                                         }
   bool                        getFinalized() const                                   { return m_bFinalized;                                          }
+#if !JVET_P1004_REMOVE_BRICKS
   void                        setSliceCurStartBrickIdx(uint32_t brickIdx)            { m_sliceCurStartBrickIdx = brickIdx;                           }
   uint32_t                    getSliceCurStartBrickIdx() const                       { return m_sliceCurStartBrickIdx;                               }
   void                        setSliceCurEndBrickIdx(uint32_t brickIdx)              { m_sliceCurEndBrickIdx = brickIdx;                             }
@@ -2484,6 +2680,7 @@ public:
   uint32_t                    getSliceNumBricks() const                              { return m_sliceNumBricks;                                      }
   void                        setSliceIndex(uint32_t idx)                            { m_sliceIdx = idx;                                             }
   uint32_t                    getSliceIndex() const                                  { return m_sliceIdx;                                            }
+#endif
   bool                        testWeightPred( ) const                                { return m_bTestWeightPred;                                     }
   void                        setTestWeightPred( bool bValue )                       { m_bTestWeightPred = bValue;                                   }
   bool                        testWeightBiPred( ) const                              { return m_bTestWeightBiPred;                                   }
@@ -2572,6 +2769,10 @@ public:
   void                        setNonRefPictFlag(bool value) { m_nonReferencePicFlag = value; }
   bool                        getNonRefPictFlag() const { return m_nonReferencePicFlag;  }
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  void                        setNumEntryPoints( const PPS *pps );
+  uint32_t                    getNumEntryPoints( ) const { return m_numEntryPoints;  }
+#endif
 
 protected:
 #if JVET_N0278_FIXES
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index c9b72c627..2d305845a 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_P1004_REMOVE_BRICKS                          1 // JVET-P1004: Removal of bricks
+
 #define JVET_P0202_P0203_FIX_HRD_RELATED_SEI              1 // JVET-P0202 and JVET-P0203: CPB timing for sub-layers with DU and parsing independency to SPS
 
 #define JVET_P0551_ALF_SLICE_BOUNDARY                     1 // JVET-P0053/P0157/P0551: Applying picturce boundary padding to slice boundaries
@@ -817,6 +819,7 @@ enum ScalingList1dStartIdx
   SCALING_LIST_1D_START_64x64  = 26,
 };
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
 // Slice / Slice segment encoding modes
 enum SliceConstraint
 {
@@ -827,6 +830,7 @@ enum SliceConstraint
   SINGLE_BRICK_PER_SLICE = 4,          ///< each brick is coded as separate NAL unit (slice)
   NUMBER_OF_SLICE_CONSTRAINT_MODES = 5
 };
+#endif
 
 // For use with decoded picture hash SEI messages, generated by encoder.
 enum HashType
diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp
index 7714d436e..798859c78 100644
--- a/source/Lib/CommonLib/UnitPartitioner.cpp
+++ b/source/Lib/CommonLib/UnitPartitioner.cpp
@@ -169,7 +169,11 @@ void AdaptiveDepthPartitioner::setMaxMinDepth( unsigned& minDepth, unsigned& max
   unsigned          stdMaxDepth = ( floorLog2(cs.sps->getCTUSize()) - floorLog2(cs.sps->getMinQTSize( cs.slice->getSliceType(), chType )));
   const Position    pos         = currArea().blocks[chType].pos();
   const unsigned    curSliceIdx = cs.slice->getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+  const unsigned    curTileIdx  = cs.pps->getTileIdx( currArea().lumaPos() );
+#else
   const unsigned    curTileIdx  = cs.picture->brickMap->getBrickIdxRsMap( currArea().lumaPos() );
+#endif
 
   const CodingUnit* cuLeft        = cs.getCURestricted( pos.offset( -1,                               0 ), pos, curSliceIdx, curTileIdx, chType );
   const CodingUnit* cuBelowLeft   = cs.getCURestricted( pos.offset( -1, currArea().blocks[chType].height), pos, curSliceIdx, curTileIdx, chType );
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 62ff927ba..afe71bc74 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -155,6 +155,7 @@ bool CU::isSameTile(const CodingUnit& cu, const CodingUnit& cu2)
   return cu.tileIdx == cu2.tileIdx;
 }
 
+#if !JVET_P1004_REMOVE_BRICKS
 #if JVET_O0625_ALF_PADDING
 bool CU::isSameBrick( const CodingUnit& cu, const CodingUnit& cu2 )
 {
@@ -166,6 +167,7 @@ bool CU::isSameBrick( const CodingUnit& cu, const CodingUnit& cu2 )
   return brickIdx == brickIdx2;
 }
 #endif
+#endif
 
 bool CU::isSameSliceAndTile(const CodingUnit& cu, const CodingUnit& cu2)
 {
@@ -200,7 +202,19 @@ int CU::predictQP( const CodingUnit& cu, const int prevQP )
 {
   const CodingStructure &cs = *cu.cs;
 
+#if JVET_P1004_REMOVE_BRICKS
+  uint32_t  ctuRsAddr       = getCtuAddr( cu );
+  uint32_t  ctuXPosInCtus   = ctuRsAddr % cs.pcv->widthInCtus;
+  uint32_t  tileColIdx      = cu.slice->getPPS()->ctuToTileCol( ctuXPosInCtus );
+  uint32_t  tileXPosInCtus  = cu.slice->getPPS()->getTileColumnBd( tileColIdx );
+  if( ctuXPosInCtus == tileXPosInCtus &&
+      !( cu.blocks[cu.chType].x & ( cs.pcv->maxCUWidthMask  >> getChannelTypeScaleX( cu.chType, cu.chromaFormat ) ) ) &&
+      !( cu.blocks[cu.chType].y & ( cs.pcv->maxCUHeightMask >> getChannelTypeScaleY( cu.chType, cu.chromaFormat ) ) ) && 
+      ( cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType) != NULL ) && 
+      CU::isSameSliceAndTile( *cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType), cu ) )
+#else
   if ( !cu.blocks[cu.chType].x && !( cu.blocks[cu.chType].y & ( cs.pcv->maxCUHeightMask >> getChannelTypeScaleY( cu.chType, cu.chromaFormat ) ) ) && ( cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType) != NULL ) && CU::isSameSliceAndTile( *cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType), cu ) )
+#endif
   {
     return ( ( cs.getCU( cu.blocks[cu.chType].pos().offset( 0, -1 ), cu.chType ) )->qp );
   }
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 590d7c599..d2ff1fcff 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -70,7 +70,9 @@ namespace CU
   bool isLastSubCUOfCtu               (const CodingUnit &cu);
   uint32_t getCtuAddr                     (const CodingUnit &cu);
 #if JVET_O0625_ALF_PADDING || JVET_P0551_ALF_SLICE_BOUNDARY
+#if !JVET_P1004_REMOVE_BRICKS
   bool isSameBrick                    ( const CodingUnit& cu, const CodingUnit& cu2 );
+#endif
 #endif
   int  predictQP                      (const CodingUnit& cu, const int prevQP );
 
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index ae2554ab2..ec7a33c8c 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -130,10 +130,18 @@ void CABACReader::remaining_bytes( bool noTrailingBytesExpected )
 //================================================================================
 //  clause 7.3.8.2
 //--------------------------------------------------------------------------------
+#if JVET_P1004_REMOVE_BRICKS
+//    void  coding_tree_unit( cs, area, qpL, qpC, ctuRsAddr )
+#else
 //    bool  coding_tree_unit( cs, area, qpL, qpC, ctuRsAddr )
+#endif
 //================================================================================
 
+#if JVET_P1004_REMOVE_BRICKS
+void CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, int (&qps)[2], unsigned ctuRsAddr )
+#else
 bool CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, int (&qps)[2], unsigned ctuRsAddr )
+#endif
 {
   CUCtx cuCtx( qps[CH_L] );
   QTBTPartitioner partitioner;
@@ -152,7 +160,11 @@ bool CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, i
     int                 rx = ctuRsAddr - ry * frame_width_in_ctus;
     const Position      pos( rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight );
     const uint32_t          curSliceIdx = cs.slice->getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+    const uint32_t          curTileIdx = cs.pps->getTileIdx( pos );
+#else
     const uint32_t          curTileIdx = cs.picture->brickMap->getBrickIdxRsMap( pos );
+#endif
     bool                leftAvail = cs.getCURestricted( pos.offset( -(int)pcv.maxCUWidth, 0 ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
     bool                aboveAvail = cs.getCURestricted( pos.offset( 0, -(int)pcv.maxCUHeight ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
 
@@ -195,26 +207,44 @@ bool CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, i
     }
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   bool isLast = false;
+#endif
 
   if ( CS::isDualITree(cs) && cs.pcv->chrFormat != CHROMA_400 && cs.pcv->maxCUWidth > 64 )
   {
     QTBTPartitioner chromaPartitioner;
     chromaPartitioner.initCtu(area, CH_C, *cs.slice);
     CUCtx cuCtxChroma(qps[CH_C]);
+#if JVET_P1004_REMOVE_BRICKS
+    coding_tree(cs, partitioner, cuCtx, &chromaPartitioner, &cuCtxChroma);
+#else
     isLast    = coding_tree(cs, partitioner, cuCtx, &chromaPartitioner, &cuCtxChroma);
+#endif
     qps[CH_L] = cuCtx.qp;
     qps[CH_C] = cuCtxChroma.qp;
   }
   else
   {
+#if JVET_P1004_REMOVE_BRICKS
+    coding_tree(cs, partitioner, cuCtx);
+#else
     isLast    = coding_tree(cs, partitioner, cuCtx);
+#endif
     qps[CH_L] = cuCtx.qp;
+#if JVET_P1004_REMOVE_BRICKS
+    if( CS::isDualITree( cs ) && cs.pcv->chrFormat != CHROMA_400 )
+#else
     if( !isLast && CS::isDualITree( cs ) && cs.pcv->chrFormat != CHROMA_400 )
+#endif
     {
       CUCtx cuCtxChroma( qps[CH_C] );
       partitioner.initCtu(area, CH_C, *cs.slice);
+#if JVET_P1004_REMOVE_BRICKS
+      coding_tree(cs, partitioner, cuCtxChroma);
+#else
       isLast    = coding_tree(cs, partitioner, cuCtxChroma);
+#endif
       qps[CH_C] = cuCtxChroma.qp;
     }
   }
@@ -222,7 +252,9 @@ bool CABACReader::coding_tree_unit( CodingStructure& cs, const UnitArea& area, i
   DTRACE_COND( ctuRsAddr == 0, g_trace_ctx, D_QP_PER_CTU, "\n%4d %2d", cs.picture->poc, cs.slice->getSliceQpBase() );
   DTRACE     (                 g_trace_ctx, D_QP_PER_CTU, " %3d",           qps[CH_L] - cs.slice->getSliceQpBase() );
 
+#if !JVET_P1004_REMOVE_BRICKS
   return isLast;
+#endif
 }
 
 void CABACReader::readAlfCtuFilterIndex(CodingStructure& cs, unsigned ctuRsAddr)
@@ -321,7 +353,11 @@ void CABACReader::sao( CodingStructure& cs, unsigned ctuRsAddr )
 
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SAO );
 
+#if JVET_P1004_REMOVE_BRICKS
+  const unsigned  curTileIdx  = cs.pps->getTileIdx( pos );
+#else
   const unsigned  curTileIdx  = cs.picture->brickMap->getBrickIdxRsMap( pos );
+#endif
   if( cs.getCURestricted( pos.offset(-(int)cs.pcv->maxCUWidth, 0), pos, curSliceIdx, curTileIdx, CH_L ) )
   {
     // sao_merge_left_flag
@@ -436,16 +472,26 @@ void CABACReader::sao( CodingStructure& cs, unsigned ctuRsAddr )
 //================================================================================
 //  clause 7.3.8.4
 //--------------------------------------------------------------------------------
+#if JVET_P1004_REMOVE_BRICKS
+//    void  coding_tree       ( cs, partitioner, cuCtx )
+#else
 //    bool  coding_tree       ( cs, partitioner, cuCtx )
+#endif
 //    bool  split_cu_flag     ( cs, partitioner )
 //    split split_cu_mode_mt  ( cs, partitioner )
 //================================================================================
 
+#if JVET_P1004_REMOVE_BRICKS
+void CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, Partitioner* pPartitionerChroma, CUCtx* pCuCtxChroma)
+#else
 bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, Partitioner* pPartitionerChroma, CUCtx* pCuCtxChroma)
+#endif
 {
   const PPS      &pps         = *cs.pps;
   const UnitArea &currArea    = partitioner.currArea();
+#if !JVET_P1004_REMOVE_BRICKS
   bool           lastSegment  = false;
+#endif
 
   // Reset delta QP coding flag and ChromaQPAdjustemt coding flag
   //Note: do not reset qg at chroma CU
@@ -516,15 +562,25 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
         bool beContinue = true;
         bool lumaContinue = true;
         bool chromaContinue = true;
+#if !JVET_P1004_REMOVE_BRICKS
         bool lastSegmentC = false;
+#endif
 
         while (beContinue)
         {
           if (partitioner.currArea().lwidth() > 64 || partitioner.currArea().lheight() > 64)
           {
+#if JVET_P1004_REMOVE_BRICKS
+            if (cs.area.blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
+#else
             if (!lastSegmentC && cs.area.blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
+#endif
             {
+#if JVET_P1004_REMOVE_BRICKS
+              coding_tree(cs, partitioner, cuCtx, pPartitionerChroma, pCuCtxChroma);
+#else
               lastSegmentC = coding_tree(cs, partitioner, cuCtx, pPartitionerChroma, pCuCtxChroma);
+#endif
             }
             lumaContinue = partitioner.nextPart(cs);
             chromaContinue = pPartitionerChroma->nextPart(cs);
@@ -534,18 +590,36 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
           else
           {
             //dual tree coding under 64x64 block
+#if JVET_P1004_REMOVE_BRICKS
+            if (cs.area.blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
+#else
             if (!lastSegment && cs.area.blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
+#endif
             {
+#if JVET_P1004_REMOVE_BRICKS
+              coding_tree(cs, partitioner, cuCtx);
+#else
               lastSegment = coding_tree(cs, partitioner, cuCtx);
+#endif
             }
             lumaContinue = partitioner.nextPart(cs);
+#if JVET_P1004_REMOVE_BRICKS
+            if (cs.area.blocks[pPartitionerChroma->chType].contains(pPartitionerChroma->currArea().blocks[pPartitionerChroma->chType].pos()))
+#else
             if (!lastSegmentC && cs.area.blocks[pPartitionerChroma->chType].contains(pPartitionerChroma->currArea().blocks[pPartitionerChroma->chType].pos()))
+#endif
             {
+#if JVET_P1004_REMOVE_BRICKS
+              coding_tree(cs, *pPartitionerChroma, *pCuCtxChroma);
+#else
               lastSegmentC = coding_tree(cs, *pPartitionerChroma, *pCuCtxChroma);
+#endif
             }
             chromaContinue = pPartitionerChroma->nextPart(cs);
             CHECK(lumaContinue != chromaContinue, "luma chroma partition should be matched");
+#if !JVET_P1004_REMOVE_BRICKS
             CHECK(lastSegment == true, "luma should not be the last segment");
+#endif
             beContinue = lumaContinue;
           }
         }
@@ -584,7 +658,9 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
         CodingUnit* chromaFirstCu = cs.getCU(pPartitionerChroma->currArea().chromaPos(), CHANNEL_TYPE_CHROMA);
         tempLastLumaCu->next = chromaFirstCu;
 
+#if !JVET_P1004_REMOVE_BRICKS
         lastSegment = lastSegmentC;
+#endif
       }
       else
       {
@@ -600,9 +676,17 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
       partitioner.splitCurrArea( splitMode, cs );
       do
       {
+#if JVET_P1004_REMOVE_BRICKS
+        if( cs.area.blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
+#else
         if( !lastSegment && cs.area.blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
+#endif
         {
+#if JVET_P1004_REMOVE_BRICKS
+          coding_tree( cs, partitioner, cuCtx );
+#else
           lastSegment = coding_tree( cs, partitioner, cuCtx );
+#endif
         }
       } while( partitioner.nextPart( cs ) );
 
@@ -613,9 +697,17 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
         partitioner.chType = CHANNEL_TYPE_CHROMA;
         cs.treeType = partitioner.treeType = TREE_C;
 
+#if JVET_P1004_REMOVE_BRICKS
+        if( cs.picture->blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
+#else
         if( !lastSegment && cs.picture->blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
+#endif
         {
+#if JVET_P1004_REMOVE_BRICKS
+          coding_tree( cs, partitioner, cuCtx );
+#else
           lastSegment = coding_tree( cs, partitioner, cuCtx );
+#endif
         }
 
         //recover treeType
@@ -630,14 +722,22 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
       if (startShareThisLevel == 1)
         shareStateDec = NO_SHARE;
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+      return;
+#else
       return lastSegment;
+#endif
   }
 
   CodingUnit& cu = cs.addCU( CS::getArea( cs, currArea, partitioner.chType ), partitioner.chType );
 
   partitioner.setCUData( cu );
   cu.slice   = cs.slice;
+#if JVET_P1004_REMOVE_BRICKS
+  cu.tileIdx = cs.pps->getTileIdx( currArea.lumaPos() );
+#else
   cu.tileIdx = cs.picture->brickMap->getBrickIdxRsMap( currArea.lumaPos() );
+#endif
   CHECK( cu.cs->treeType != partitioner.treeType, "treeType mismatch" );
   int lumaQPinLocalDualTree = -1;
 
@@ -670,7 +770,11 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
     cu.shareParentSize = (shareStateDec == SHARING) ? shareParentSize : partitioner.currArea().lumaSize();
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+  coding_unit( cu, partitioner, cuCtx );
+#else
   bool isLastCtu = coding_unit( cu, partitioner, cuCtx );
+#endif
   //recover cuCtx.qp to luma qp after decoding the chroma CU
   if( pps.getUseDQP() && partitioner.isSepTree( cs ) && isChroma( cu.chType ) )
   {
@@ -715,7 +819,9 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
   if (startShareThisLevel == 1)
     shareStateDec = NO_SHARE;
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
   return isLastCtu;
+#endif
 }
 
 ModeType CABACReader::mode_constraint( CodingStructure& cs, Partitioner &partitioner, PartSplit splitMode )
@@ -811,7 +917,11 @@ PartSplit CABACReader::split_cu_mode( CodingStructure& cs, Partitioner &partitio
 //================================================================================
 //  clause 7.3.8.5
 //--------------------------------------------------------------------------------
+#if JVET_P1004_REMOVE_BRICKS
+//    void  coding_unit               ( cu, partitioner, cuCtx )
+#else
 //    bool  coding_unit               ( cu, partitioner, cuCtx )
+#endif
 //    void  cu_transquant_bypass_flag ( cu )
 //    void  cu_skip_flag              ( cu )
 //    void  pred_mode                 ( cu )
@@ -822,10 +932,18 @@ PartSplit CABACReader::split_cu_mode( CodingStructure& cs, Partitioner &partitio
 //    void  intra_chroma_pred_mode    ( pu )
 //    void  cu_residual               ( cu, partitioner, cuCtx )
 //    void  rqt_root_cbf              ( cu )
+#if JVET_P1004_REMOVE_BRICKS
+//    void  end_of_ctu                ( cu, cuCtx )
+#else
 //    bool  end_of_ctu                ( cu, cuCtx )
+#endif
 //================================================================================
 
+#if JVET_P1004_REMOVE_BRICKS
+void CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx& cuCtx )
+#else
 bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx& cuCtx )
+#endif
 {
   CodingStructure& cs = *cu.cs;
   CHECK( cu.treeType != partitioner.treeType || cu.modeType != partitioner.modeType, "treeType or modeType mismatch" );
@@ -855,7 +973,12 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
 #endif
     MergeCtx           mrgCtx;
     prediction_unit  ( pu, mrgCtx );
+#if JVET_P1004_REMOVE_BRICKS
+    end_of_ctu( cu, cuCtx );
+    return;
+#else
     return end_of_ctu( cu, cuCtx );
+#endif
   }
 
   // prediction mode and partitioning data
@@ -887,7 +1010,12 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
     {
       cu_palette_info(cu, COMPONENT_Y, 3, cuCtx);
     }
+#if JVET_P1004_REMOVE_BRICKS
+    end_of_ctu(cu, cuCtx);
+    return;
+#else
     return end_of_ctu(cu, cuCtx);
+#endif
   }
   bdpcm_mode( cu, ComponentID( partitioner.chType ) );
 #if JVET_P0059_CHROMA_BDPCM
@@ -904,7 +1032,11 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
   cu_residual( cu, partitioner, cuCtx );
 
   // check end of cu
+#if JVET_P1004_REMOVE_BRICKS
+  end_of_ctu( cu, cuCtx );
+#else
   return end_of_ctu( cu, cuCtx );
+#endif
 }
 
 
@@ -1711,7 +1843,11 @@ void CABACReader::sbt_mode( CodingUnit& cu )
 }
 
 
+#if JVET_P1004_REMOVE_BRICKS
+void CABACReader::end_of_ctu( CodingUnit& cu, CUCtx& cuCtx )
+#else
 bool CABACReader::end_of_ctu( CodingUnit& cu, CUCtx& cuCtx )
+#endif
 {
   const Position rbPos = recalcPosition( cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].bottomRight().offset( 1, 1 ) );
 
@@ -1722,10 +1858,14 @@ bool CABACReader::end_of_ctu( CodingUnit& cu, CUCtx& cuCtx )
   {
     cuCtx.isDQPCoded = ( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded );
 
+#if !JVET_P1004_REMOVE_BRICKS
     return terminating_bit();
+#endif
   }
+#if !JVET_P1004_REMOVE_BRICKS
 
   return false;
+#endif
 }
 
 void CABACReader::cu_palette_info(CodingUnit& cu, ComponentID compBegin, uint32_t numComp, CUCtx& cuCtx)
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index 190794e65..5fe581c30 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -67,7 +67,11 @@ public:
   void        remaining_bytes           ( bool                          noTrailingBytesExpected );
 
   // coding tree unit (clause 7.3.8.2)
+#if JVET_P1004_REMOVE_BRICKS
+  void        coding_tree_unit          ( CodingStructure&              cs,     const UnitArea& area,     int (&qps)[2],   unsigned  ctuRsAddr );
+#else
   bool        coding_tree_unit          ( CodingStructure&              cs,     const UnitArea& area,     int (&qps)[2],   unsigned  ctuRsAddr );
+#endif
 
   // sao (clause 7.3.8.3)
   void        sao                       ( CodingStructure&              cs,     unsigned        ctuRsAddr );
@@ -75,12 +79,20 @@ public:
   void        readAlfCtuFilterIndex(CodingStructure&              cs, unsigned        ctuRsAddr);
 
   // coding (quad)tree (clause 7.3.8.4)
+#if JVET_P1004_REMOVE_BRICKS
+  void        coding_tree               ( CodingStructure&              cs,     Partitioner&    pm,       CUCtx& cuCtx, Partitioner* pPartitionerChroma = nullptr, CUCtx* pCuCtxChroma = nullptr);
+#else
   bool        coding_tree               ( CodingStructure&              cs,     Partitioner&    pm,       CUCtx& cuCtx, Partitioner* pPartitionerChroma = nullptr, CUCtx* pCuCtxChroma = nullptr);
+#endif
   PartSplit   split_cu_mode             ( CodingStructure&              cs,     Partitioner&    pm );
   ModeType    mode_constraint           ( CodingStructure&              cs,     Partitioner&    pm,       const PartSplit splitMode );
 
   // coding unit (clause 7.3.8.5)
+#if JVET_P1004_REMOVE_BRICKS
+  void        coding_unit               ( CodingUnit&                   cu,     Partitioner&    pm,       CUCtx& cuCtx );
+#else
   bool        coding_unit               ( CodingUnit&                   cu,     Partitioner&    pm,       CUCtx& cuCtx );
+#endif
   void        cu_transquant_bypass_flag ( CodingUnit&                   cu );
   void        cu_skip_flag              ( CodingUnit&                   cu );
   void        pred_mode                 ( CodingUnit&                   cu );
@@ -98,7 +110,11 @@ public:
   void        adaptive_color_transform(CodingUnit&             cu);
 #endif 
   void        sbt_mode                  ( CodingUnit&                   cu );
+#if JVET_P1004_REMOVE_BRICKS
+  void        end_of_ctu                ( CodingUnit&                   cu,     CUCtx&          cuCtx );
+#else
   bool        end_of_ctu                ( CodingUnit&                   cu,     CUCtx&          cuCtx );
+#endif
   void        mip_flag                  ( CodingUnit&                   cu );
   void        mip_pred_modes            ( CodingUnit&                   cu );
   void        mip_pred_mode             ( PredictionUnit&               pu );
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index fab6ddc44..e5be6204b 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -601,13 +601,17 @@ void DecLib::executeLoopFilters()
 
   if( cs.sps->getALFEnabledFlag() )
   {
+#if !JVET_P1004_REMOVE_BRICKS
     if (cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y))
     {
+#endif
       // ALF decodes the differentially coded coefficients and stores them in the parameters structure.
       // Code could be restructured to do directly after parsing. So far we just pass a fresh non-const
       // copy in case the APS gets used more than once.
       m_cALF.ALFProcess(cs);
+#if !JVET_P1004_REMOVE_BRICKS
     }
+#endif
 
   }
 
@@ -1098,10 +1102,12 @@ void DecLib::xActivateParameterSets()
 #else
     m_pcPic->finalInit( *sps, *pps, apss, lmcsAPS, scalinglistAPS );
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
 #if JVET_P1006_PICTURE_HEADER
     m_parameterSetManager.getPPS(m_picHeader.getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size());
 #else
     m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size());
+#endif
 #endif
     m_pcPic->createTempBuffers( m_pcPic->cs->pps->pcv->maxCUWidth );
     m_pcPic->cs->createCoeffs((bool)m_pcPic->cs->sps->getPLTMode());
@@ -1341,10 +1347,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     m_apcSlicePilot->copySliceInfo( m_pcPic->slices[m_uiSliceSegmentIdx-1] );
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   m_apcSlicePilot->setSliceCurStartCtuTsAddr(0);
   m_apcSlicePilot->setSliceCurEndCtuTsAddr(0);
   m_apcSlicePilot->setSliceCurStartBrickIdx(0);
   m_apcSlicePilot->setSliceCurEndBrickIdx(0);
+#endif
   m_apcSlicePilot->setNalUnitType(nalu.m_nalUnitType);
   m_apcSlicePilot->setTLayer(nalu.m_temporalId);
 
@@ -1502,7 +1510,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   m_prevSliceSkipped = false;
 
   //we should only get a different poc for a new picture (with CTU address==0)
+#if JVET_P1004_REMOVE_BRICKS
+  if(m_apcSlicePilot->getPOC() != m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getFirstCtuRsAddrInSlice() != 0))
+#else
   if(m_apcSlicePilot->getPOC() != m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() != 0))
+#endif
   {
     msg( WARNING, "Warning, the first slice of a picture might have been lost!\n");
   }
@@ -1511,7 +1523,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 #endif
 
   // leave when a new picture is found
+#if JVET_P1004_REMOVE_BRICKS
+  if(m_apcSlicePilot->getFirstCtuRsAddrInSlice() == 0 && !m_bFirstSliceInPicture)
+#else
   if(m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture)
+#endif
   {
     if (m_prevPOC >= m_pocRandomAccess)
     {
@@ -1601,6 +1617,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     m_pcPic->subLayerNonReferencePictureDueToSTSA = false;
   #endif
 
+#if !JVET_P1004_REMOVE_BRICKS
   if (pcSlice->getPPS()->getRectSliceFlag())
   {
     int sliceIdx = pcSlice->getSliceIndex();
@@ -1639,6 +1656,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
   pcSlice->setSliceCurStartCtuTsAddr(startCtuIdx);
   pcSlice->setSliceCurEndCtuTsAddr(endCtuIdx);
+#endif
 
   pcSlice->checkCRA(pcSlice->getRPL0(), pcSlice->getRPL1(), m_pocCRA, m_associatedIRAPType, m_cListPic);
   pcSlice->constructRefPicList(m_cListPic);
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index ff0b2c915..75d9c56fd 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -77,7 +77,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 
   const SPS*     sps          = slice->getSPS();
   Picture*       pic          = slice->getPic();
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap& tileMap     = *pic->brickMap;
+#endif
   CABACReader&   cabacReader  = *m_CABACDecoder->getCABACReader( 0 );
 
   // setup coding structure
@@ -102,7 +104,11 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 
   cs.resetPrevPLT(cs.prevPLT);
 
+#if JVET_P1004_REMOVE_BRICKS
+  if (slice->getFirstCtuRsAddrInSlice() == 0)
+#else
   if (slice->getSliceCurStartCtuTsAddr() == 0)
+#endif
   {
     cs.picture->resizeAlfCtuEnableFlag( cs.pcv->sizeInCtus );
     cs.picture->resizeAlfCtbFilterIndex(cs.pcv->sizeInCtus);
@@ -119,9 +125,11 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
     ppcSubstreams[idx] = bitstream->extractSubstream( idx+1 < numSubstreams ? ( slice->getSubstreamSize(idx) << 3 ) : bitstream->getNumBitsLeft() );
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
   const int       startCtuTsAddr          = slice->getSliceCurStartCtuTsAddr();
 
   const unsigned  numCtusInFrame          = cs.pcv->sizeInCtus;
+#endif
   const unsigned  widthInCtus             = cs.pcv->widthInCtus;
   const bool      wavefrontsEnabled       = cs.pps->getEntropyCodingSyncEnabledFlag();
 
@@ -136,14 +144,32 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 
 
   // for every CTU in the slice segment...
+#if !JVET_P1004_REMOVE_BRICKS
   bool isLastCtuOfSliceSegment = false;
   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;
+#endif
   unsigned subStrmId = 0;
+#if JVET_P1004_REMOVE_BRICKS
+  for( unsigned ctuIdx = 0; ctuIdx < slice->getNumCtuInSlice(); ctuIdx++ )
+#else
   for( unsigned ctuTsAddr = startCtuTsAddr; !isLastCtuOfSliceSegment && ctuTsAddr < numCtusInFrame; ctuTsAddr++ )
+#endif
   {
+#if JVET_P1004_REMOVE_BRICKS
+    const unsigned  ctuRsAddr       = slice->getCtuAddrInSlice(ctuIdx);
+    const unsigned  ctuXPosInCtus   = ctuRsAddr % widthInCtus;
+    const unsigned  ctuYPosInCtus   = ctuRsAddr / widthInCtus;    
+    const unsigned  tileColIdx      = slice->getPPS()->ctuToTileCol( ctuXPosInCtus );
+    const unsigned  tileRowIdx      = slice->getPPS()->ctuToTileRow( ctuYPosInCtus );
+    const unsigned  tileXPosInCtus  = slice->getPPS()->getTileColumnBd( tileColIdx );
+    const unsigned  tileYPosInCtus  = slice->getPPS()->getTileRowBd( tileRowIdx );
+    const unsigned  tileColWidth    = slice->getPPS()->getTileColumnWidth( tileColIdx );
+    const unsigned  tileRowHeight   = slice->getPPS()->getTileRowHeight( tileRowIdx );
+    const unsigned  tileIdx         = slice->getPPS()->getTileIdx( ctuXPosInCtus, ctuYPosInCtus);
+#else
     const unsigned  ctuRsAddr             = tileMap.getCtuBsToRsAddrMap(ctuTsAddr);
     const Brick&  currentTile             = tileMap.bricks[ tileMap.getBrickIdxRsMap(ctuRsAddr) ];
     if (slice->getPPS()->getRectSliceFlag() &&
@@ -155,6 +181,7 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
     const unsigned  tileYPosInCtus        = firstCtuRsAddrOfTile / widthInCtus;
     const unsigned  ctuXPosInCtus         = ctuRsAddr % widthInCtus;
     const unsigned  ctuYPosInCtus         = ctuRsAddr / widthInCtus;
+#endif
     const unsigned  maxCUSize             = sps->getMaxCUWidth();
     Position pos( ctuXPosInCtus*maxCUSize, ctuYPosInCtus*maxCUSize) ;
     UnitArea ctuArea(cs.area.chromaFormat, Area( pos.x, pos.y, maxCUSize, maxCUSize ) );
@@ -164,9 +191,15 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
     cabacReader.initBitstream( ppcSubstreams[subStrmId] );
 
     // set up CABAC contexts' state for this CTU
+#if JVET_P1004_REMOVE_BRICKS
+    if( ctuXPosInCtus == tileXPosInCtus && ctuYPosInCtus == tileYPosInCtus )
+    {
+      if( ctuIdx != 0 ) // if it is the first CTU, then the entropy coder has already been reset
+#else
     if( ctuRsAddr == firstCtuRsAddrOfTile )
     {
       if( ctuTsAddr != startCtuTsAddr ) // if it is the first CTU, then the entropy coder has already been reset
+#endif
       {
         cabacReader.initCtxModels( *slice );
         cs.resetPrevPLT(cs.prevPLT);
@@ -176,12 +209,20 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
     else if( ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled )
     {
       // Synchronize cabac probabilities with top CTU if it's available and at the start of a line.
+#if JVET_P1004_REMOVE_BRICKS
+      if( ctuIdx != 0 ) // if it is the first CTU, then the entropy coder has already been reset
+#else
       if( ctuTsAddr != startCtuTsAddr ) // if it is the first CTU, then the entropy coder has already been reset
+#endif
       {
         cabacReader.initCtxModels( *slice );
         cs.resetPrevPLT(cs.prevPLT);
       }
+#if JVET_P1004_REMOVE_BRICKS
+      if( cs.getCURestricted( pos.offset(0, -1), pos, slice->getIndependentSliceIdx(), tileIdx, CH_L ) )
+#else
       if( cs.getCURestricted( pos.offset(0, -1), pos, slice->getIndependentSliceIdx(), tileMap.getBrickIdxRsMap( pos ), CH_L ) )
+#endif
       {
         // Top is available, so use it.
         cabacReader.getCtx() = m_entropyCodingSyncContextState;
@@ -189,7 +230,11 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
       pic->m_prevQP[0] = pic->m_prevQP[1] = slice->getSliceQp();
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuIdx == 0;
+#else
     bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuTsAddr == startCtuTsAddr;
+#endif
     if(updateGbiCodingOrder)
     {
       resetGbiCodingOrder(true, cs);
@@ -209,10 +254,16 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
 
     if( ctuRsAddr == debugCTU )
     {
+#if !JVET_P1004_REMOVE_BRICKS
       isLastCtuOfSliceSegment = true; // get out here
+#endif
       break;
     }
+#if JVET_P1004_REMOVE_BRICKS
+    cabacReader.coding_tree_unit( cs, ctuArea, pic->m_prevQP, ctuRsAddr );
+#else
     isLastCtuOfSliceSegment = cabacReader.coding_tree_unit( cs, ctuArea, pic->m_prevQP, ctuRsAddr );
+#endif
 
     m_pcCuDecoder->decompressCtu( cs, ctuArea );
 
@@ -222,15 +273,30 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
     }
 
 
+#if JVET_P1004_REMOVE_BRICKS
+    if( ctuIdx == slice->getNumCtuInSlice()-1 )
+#else
     if( isLastCtuOfSliceSegment )
+#endif
     {
+#if JVET_P1004_REMOVE_BRICKS
+      unsigned binVal = cabacReader.terminating_bit();
+      CHECK( !binVal, "Expecting a terminating bit" );
+#endif
 #if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES
       cabacReader.remaining_bytes( false );
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
         slice->setSliceCurEndCtuTsAddr( ctuTsAddr+1 );
+#endif
     }
+#if JVET_P1004_REMOVE_BRICKS
+    else if( ( ctuXPosInCtus + 1 == tileXPosInCtus + tileColWidth ) &&
+             ( ctuYPosInCtus + 1 == tileYPosInCtus + tileRowHeight || wavefrontsEnabled ) )
+#else
     else if( ( ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getWidthInCtus () ) &&
              ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getHeightInCtus() || wavefrontsEnabled ) )
+#endif
     {
       // The sub-stream/stream should be terminated after this CTU.
       // (end of slice-segment, end of tile, end of wavefront-CTU-row)
@@ -242,7 +308,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
       subStrmId++;
     }
   }
+#if !JVET_P1004_REMOVE_BRICKS
   CHECK( !isLastCtuOfSliceSegment, "Last CTU of slice segment not signalled as such" );
+#endif
 
   // deallocate all created substreams, including internal buffers.
   for( auto substr: ppcSubstreams )
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 00d56c245..f9f05a0c6 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -412,7 +412,102 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana
   }
 
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  READ_FLAG( uiCode, "no_pic_partition_flag" );                       pcPPS->setNoPicPartitionFlag( uiCode == 1 );
+  if(!pcPPS->getNoPicPartitionFlag())
+  {
+    int colIdx, rowIdx;
+    pcPPS->resetTileSliceInfo();
+
+    // CTU size - required to match size in SPS
+    READ_CODE(2, uiCode, "log2_pps_ctu_size_minus5");                 pcPPS->setLog2CtuSize(uiCode + 5);  
+    CHECK(uiCode > 2, "log2_pps_ctu_size_minus5 must be less than or equal to 2");
+    
+    // number of explicit tile columns/rows
+    READ_UVLC( uiCode, "num_exp_tile_columns_minus1" );               pcPPS->setNumExpTileColumns( uiCode + 1 );
+    READ_UVLC( uiCode, "num_exp_tile_rows_minus1" );                  pcPPS->setNumExpTileRows( uiCode + 1 );
+    CHECK(pcPPS->getNumExpTileColumns() > MAX_TILE_COLS,              "Number of explicit tile columns exceeds valid range");
+    CHECK(pcPPS->getNumExpTileRows() > MAX_TILE_ROWS,                 "Number of explicit tile rows exceeds valid range");
+    
+    // tile sizes
+    for( colIdx = 0; colIdx < pcPPS->getNumExpTileColumns(); colIdx++ )
+    {
+      READ_UVLC( uiCode, "tile_column_width_minus1[i]" );             pcPPS->addTileColumnWidth( uiCode + 1 );
+    }
+    for( rowIdx = 0; rowIdx < pcPPS->getNumExpTileRows(); rowIdx++ )
+    {
+      READ_UVLC( uiCode, "tile_row_height_minus1[i]" );               pcPPS->addTileRowHeight( uiCode + 1 );
+    }
+    pcPPS->initTiles();
+     
+    // rectangular slice signalling
+    READ_CODE(1, uiCode, "rect_slice_flag");                          pcPPS->setRectSliceFlag( uiCode == 1 );
+    if( pcPPS->getRectSliceFlag() ) 
+    {
+      int32_t tileIdx = 0;
+
+      READ_UVLC( uiCode, "num_slices_in_pic_minus1" );                pcPPS->setNumSlicesInPic( uiCode + 1 );
+      CHECK(pcPPS->getNumSlicesInPic() > MAX_SLICES,                  "Number of slices in picture exceeds valid range");
+      READ_CODE(1, uiCode, "tile_idx_delta_present_flag");            pcPPS->setTileIdxDeltaPresentFlag( uiCode == 1 );
+      pcPPS->initRectSlices();
+      
+      // read rectangular slice parameters
+      for( int i = 0; i < pcPPS->getNumSlicesInPic()-1; i++ )
+      {
+        pcPPS->setSliceTileIdx( i, tileIdx );
+
+        // complete tiles within a single slice
+        READ_UVLC( uiCode, "slice_width_in_tiles_minus1[i]" );        pcPPS->setSliceWidthInTiles ( i, uiCode + 1 );
+        READ_UVLC( uiCode, "slice_height_in_tiles_minus1[i]" );       pcPPS->setSliceHeightInTiles( i, uiCode + 1 );
+
+        // multiple slices within a single tile special case
+        if( pcPPS->getSliceWidthInTiles( i ) == 1 && pcPPS->getSliceHeightInTiles( i ) == 1 ) 
+        {
+          READ_UVLC( uiCode, "num_slices_in_tile_minus1[i]" );        pcPPS->setNumSlicesInTile( i, uiCode + 1 );
+          uint32_t numSlicesInTile = pcPPS->getNumSlicesInTile( i );
+          for( int j = 0; j < numSlicesInTile-1; j++ )
+          {
+            READ_UVLC( uiCode, "slice_height_in_ctu_minus1[i]" );     pcPPS->setSliceHeightInCtu( i, uiCode + 1 );
+            i++;
+            pcPPS->setSliceWidthInTiles ( i, 1 );
+            pcPPS->setSliceHeightInTiles( i, 1 );
+            pcPPS->setNumSlicesInTile   ( i, numSlicesInTile );
+            pcPPS->setSliceTileIdx      ( i, tileIdx );
+          }
+        }
+
+        // tile index offset to start of next slice
+        if( i < pcPPS->getNumSlicesInPic()-1 )
+        {
+          if( pcPPS->getTileIdxDeltaPresentFlag() ) 
+          {
+            int32_t  tileIdxDelta;
+            READ_SVLC( tileIdxDelta, "tile_idx_delta[i]" );
+            tileIdx += tileIdxDelta;
+            CHECK( tileIdx < 0 || tileIdx >= pcPPS->getNumTiles(), "Invalid tile_idx_delta.");
+          }
+          else
+          {
+            tileIdx += pcPPS->getSliceWidthInTiles( i );
+            if( tileIdx % pcPPS->getNumTileColumns() == 0)
+            {
+              tileIdx += (pcPPS->getSliceHeightInTiles( i ) - 1) * pcPPS->getNumTileColumns();
+            }
+          }
+        }
+      }
+      pcPPS->setSliceTileIdx(pcPPS->getNumSlicesInPic()-1, tileIdx );
+      
+      // initialize mapping between rectangular slices and CTUs
+      pcPPS->initRectSliceMap();
+    }
+
+    // loop filtering across slice/tile controls
+    READ_CODE(1, uiCode, "loop_filter_across_tiles_enabled_flag");    pcPPS->setLoopFilterAcrossTilesEnabledFlag( uiCode == 1 );
+    READ_CODE(1, uiCode, "loop_filter_across_slices_enabled_flag");   pcPPS->setLoopFilterAcrossSlicesEnabledFlag( uiCode == 1 );
+  }
 
+#endif
   READ_FLAG( uiCode,   "cabac_init_present_flag" );            pcPPS->setCabacInitPresentFlag( uiCode ? true : false );
 
   READ_UVLC(uiCode, "num_ref_idx_l0_default_active_minus1");
@@ -566,6 +661,7 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana
   READ_FLAG( uiCode, "transquant_bypass_enabled_flag");
   pcPPS->setTransquantBypassEnabledFlag(uiCode ? true : false);
 
+#if !JVET_P1004_REMOVE_BRICKS
   READ_FLAG( uiCode, "single_tile_in_pic_flag" );                 pcPPS->setSingleTileInPicFlag(uiCode == 1);
 
   if(!pcPPS->getSingleTileInPicFlag())
@@ -826,6 +922,7 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana
     }
   }
 
+#endif
   READ_FLAG(uiCode, "entropy_coding_sync_enabled_flag");         pcPPS->setEntropyCodingSyncEnabledFlag(uiCode == 1);
 
   READ_FLAG( uiCode, "deblocking_filter_control_present_flag" );       pcPPS->setDeblockingFilterControlPresentFlag( uiCode ? true : false );
@@ -1879,6 +1976,30 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag
   sps = parameterSetManager->getSPS(picHeader->getSPSId());
   CHECK(sps==0, "Invalid SPS");
   
+#if JVET_P1004_REMOVE_BRICKS
+  // initialize tile/slice info for no partitioning case
+  if( pps->getNoPicPartitionFlag() )
+  {
+    pps->resetTileSliceInfo();
+    pps->setLog2CtuSize( ceilLog2(sps->getCTUSize()) );
+    pps->setNumExpTileColumns(1);
+    pps->setNumExpTileRows(1);
+    pps->addTileColumnWidth( pps->getPicWidthInCtu( ) );
+    pps->addTileRowHeight( pps->getPicHeightInCtu( ) );
+    pps->initTiles();
+    pps->setRectSliceFlag( 1 );
+    pps->setNumSlicesInPic( 1 );
+    pps->initRectSlices( );
+    pps->setTileIdxDeltaPresentFlag( 0 );
+    pps->setSliceTileIdx( 0, 0 );
+    pps->initRectSliceMap( );
+  }
+  else 
+  {
+    CHECK(pps->getCtuSize() != sps->getCTUSize(), "PPS CTU size does not match CTU size in SPS");
+  }
+
+#endif
   // sub-picture IDs
   if( sps->getSubPicIdPresentFlag() ) 
   {
@@ -2607,6 +2728,58 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
     pcSlice->setPOC(iPOCmsb + iPOClsb);
   }
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+
+  // raster scan slices
+  if(pps->getRectSliceFlag() == 0) 
+  {
+    uint32_t sliceAddr, numTilesInSlice;
+
+    // slice address is the raster scan tile index of first tile in slice
+    if( pps->getNumTiles() > 1 ) 
+    {      
+      int bitsSliceAddress = ceilLog2(pps->getNumTiles());
+      READ_CODE(bitsSliceAddress, uiCode, "slice_address");  sliceAddr = uiCode;
+      READ_UVLC(uiCode, "num_tiles_in_slice_minus1");        numTilesInSlice = uiCode + 1;      
+    }
+    else {
+      sliceAddr = 0;
+      numTilesInSlice = 1;
+    }
+    CHECK(sliceAddr >= pps->getNumTiles(), "Invalid slice address");
+    pcSlice->initSliceMap();
+    pcSlice->setSliceID(sliceAddr);
+    
+    for( uint32_t tileIdx = sliceAddr; tileIdx < sliceAddr + numTilesInSlice; tileIdx++ )
+    {
+      uint32_t tileX = tileIdx % pps->getNumTileColumns();
+      uint32_t tileY = tileIdx / pps->getNumTileColumns();
+      CHECK(tileY >= pps->getNumTileRows(), "Number of tiles in slice exceeds the remaining number of tiles in picture");
+
+      pcSlice->addCtusToSlice(pps->getTileColumnBd(tileX), pps->getTileColumnBd(tileX + 1),
+                              pps->getTileRowBd(tileY), pps->getTileRowBd(tileY + 1), pps->getPicWidthInCtu());
+   }
+  }
+  // rectangular slices
+  else 
+  {
+    uint32_t sliceAddr;
+
+    // slice address is the index of the slice within the current sub-picture
+    if( pps->getNumSlicesInPic() > 1 ) 
+    {
+      int bitsSliceAddress = ceilLog2(pps->getNumSlicesInPic());  // change to NumSlicesInSubPic when available
+      READ_CODE(bitsSliceAddress, uiCode, "slice_address");  sliceAddr = uiCode;
+      CHECK(sliceAddr >= pps->getNumSlicesInPic(), "Invalid slice address");
+    }
+    else {
+      sliceAddr = 0;
+    }
+    pcSlice->setSliceMap( pps->getSliceMap(sliceAddr) );
+    pcSlice->setSliceID(sliceAddr);
+  }
+
+#else
     int bitsSliceAddress = 1;
     if (!pps->getRectSliceFlag())
     {
@@ -2667,6 +2840,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
     }
     pcSlice->setSliceCurStartCtuTsAddr(pcSlice->getSliceCurStartBrickIdx());
 
+#endif
 #if !JVET_P1006_PICTURE_HEADER
     READ_FLAG(uiCode, "non_reference_picture_flag");  pcSlice->setNonRefPictFlag(uiCode);
 #endif
@@ -3483,7 +3657,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       }
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+  if( pcSlice->getFirstCtuRsAddrInSlice() == 0 )
+#else
     if( pcSlice->getSliceCurStartBrickIdx() == 0 )
+#endif
   {
     pcSlice->setDefaultClpRng( *sps );
 
@@ -3500,6 +3678,20 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
   }
 
   std::vector<uint32_t> entryPointOffset;
+#if JVET_P1004_REMOVE_BRICKS
+  pcSlice->setNumEntryPoints( pps );
+  if( pcSlice->getNumEntryPoints() > 0 )
+  {
+    uint32_t offsetLenMinus1;
+    READ_UVLC( offsetLenMinus1, "offset_len_minus1" );
+    entryPointOffset.resize( pcSlice->getNumEntryPoints() );
+    for( uint32_t idx = 0; idx < pcSlice->getNumEntryPoints(); idx++ )
+    {
+      READ_CODE( offsetLenMinus1 + 1, uiCode, "entry_point_offset_minus1" );
+      entryPointOffset[idx] = uiCode + 1;
+    }
+  }
+#else
   if( !pps->getSingleTileInPicFlag() || pps->getEntropyCodingSyncEnabledFlag() )
   {
     uint32_t numEntryPointOffsets;
@@ -3535,6 +3727,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       }
     }
   }
+#endif
 
 #if RExt__DECODER_DEBUG_BIT_STATISTICS
   CodingStatistics::IncrementStatisticEP(STATS__BYTE_ALIGNMENT_BITS,m_pcBitstream->readByteAlignment(),0);
@@ -3544,7 +3737,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
 
   pcSlice->clearSubstreamSizes();
 
+#if JVET_P1004_REMOVE_BRICKS
+  if( pcSlice->getNumEntryPoints() > 0 )
+#else
   if( !pps->getSingleTileInPicFlag() || pps->getEntropyCodingSyncEnabledFlag() )
+#endif
   {
     int endOfSliceHeaderLocation = m_pcBitstream->getByteLocation();
 
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 68859306b..344de27c5 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -246,7 +246,11 @@ void CABACWriter::sao( const Slice& slice, unsigned ctuRsAddr )
   int                 rx                      = ctuRsAddr - ry * frame_width_in_ctus;
   const Position      pos                     ( rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight );
   const unsigned      curSliceIdx             = slice.getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+  const unsigned      curTileIdx              = cs.pps->getTileIdx( pos );
+#else
   const unsigned      curTileIdx              = cs.picture->brickMap->getBrickIdxRsMap( pos );
+#endif
   bool                leftMergeAvail          = cs.getCURestricted( pos.offset( -(int)pcv.maxCUWidth, 0  ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
   bool                aboveMergeAvail         = cs.getCURestricted( pos.offset( 0, -(int)pcv.maxCUHeight ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
   sao_block_pars( sao_ctu_pars, sps.getBitDepths(), sliceEnabled, leftMergeAvail, aboveMergeAvail, false );
@@ -1448,8 +1452,10 @@ void CABACWriter::sbt_mode( const CodingUnit& cu )
 
 void CABACWriter::end_of_ctu( const CodingUnit& cu, CUCtx& cuCtx )
 {
+ #if !JVET_P1004_REMOVE_BRICKS
   const Slice*  slice             = cu.cs->slice;
   const int     currentCTUTsAddr  = cu.cs->picture->brickMap->getCtuRsToBsAddrMap( CU::getCtuAddr( cu ) );
+#endif
   const bool    isLastSubCUOfCtu  = CU::isLastSubCUOfCtu( cu );
 
   if ( isLastSubCUOfCtu
@@ -1458,12 +1464,14 @@ void CABACWriter::end_of_ctu( const CodingUnit& cu, CUCtx& cuCtx )
   {
     cuCtx.isDQPCoded = ( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded );
 
+ #if !JVET_P1004_REMOVE_BRICKS
     // The 1-terminating bit is added to all streams, so don't add it here when it's 1.
     // i.e. when the slice segment CurEnd CTU address is the current CTU address+1.
     if(slice->getSliceCurEndCtuTsAddr() != currentCTUTsAddr + 1)
     {
       m_BinEncoder.encodeBinTrm( 0 );
     }
+#endif
   }
 }
 
@@ -3983,7 +3991,11 @@ void CABACWriter::codeAlfCtuEnableFlag( CodingStructure& cs, uint32_t ctuRsAddr,
     int                 rx = ctuRsAddr - ry * frame_width_in_ctus;
     const Position      pos( rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight );
     const uint32_t          curSliceIdx = cs.slice->getIndependentSliceIdx();
+#if JVET_P1004_REMOVE_BRICKS
+    const uint32_t      curTileIdx = cs.pps->getTileIdx( pos );
+#else
     const uint32_t      curTileIdx = cs.picture->brickMap->getBrickIdxRsMap( pos );
+#endif
     bool                leftAvail = cs.getCURestricted( pos.offset( -(int)pcv.maxCUWidth, 0 ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
     bool                aboveAvail = cs.getCURestricted( pos.offset( 0, -(int)pcv.maxCUHeight ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
 
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index 463536022..591c45cd7 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -850,7 +850,11 @@ double EncAdaptiveLoopFilter::deriveCtbAlfEnableFlags( CodingStructure& cs, cons
 
   setEnableFlag(m_alfParamTemp, channel, true);
 #if ENABLE_QPA
+#if JVET_P1004_REMOVE_BRICKS
+  CHECK ((chromaWeight > 0.0) && (cs.slice->getFirstCtuRsAddrInSlice() != 0), "incompatible start CTU address, must be 0");
+#else
   CHECK ((chromaWeight > 0.0) && (cs.slice->getSliceCurStartCtuTsAddr() != 0), "incompatible start CTU address, must be 0");
+#endif
 #endif
 
   reconstructCoeff(m_alfParamTemp, channel, true, isLuma(channel));
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 07a9f2df6..635c3f0fb 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -133,6 +133,7 @@ struct RPLEntry
 
 std::istringstream &operator>>(std::istringstream &in, GOPEntry &entry);     //input
 
+#if !JVET_P1004_REMOVE_BRICKS
 struct BrickSplit
 {
   int     m_tileIdx;
@@ -154,6 +155,7 @@ typedef std::map<int, BrickSplit> BrickSplitMap;
 
 std::istringstream &operator>>(std::istringstream &in, BrickSplit &entry);     //input
 
+#endif
 
 //! \ingroup EncoderLib
 //! \{
@@ -480,6 +482,18 @@ protected:
 #if JVET_O0549_ENCODER_ONLY_FILTER
   bool      m_gopBasedTemporalFilterEnabled;
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  bool      m_noPicPartitionFlag;                             ///< no picture partitioning flag (single tile, single slice)
+  std::vector<uint32_t> m_tileColumnWidth;                    ///< tile column widths in units of CTUs (last column width will be repeated uniformly to cover any remaining picture width)
+  std::vector<uint32_t> m_tileRowHeight;                      ///< tile row heights in units of CTUs (last row height will be repeated uniformly to cover any remaining picture height)
+  bool      m_rectSliceFlag;                                  ///< indicates if using rectangular or raster-scan slices
+  uint32_t  m_numSlicesInPic;                                 ///< number of rectangular slices in the picture (raster-scan slice specified at slice level)
+  bool      m_tileIdxDeltaPresentFlag;                        ///< rectangular slice tile index delta present flag
+  std::vector<RectSlice> m_rectSlices;                        ///< list of rectanglar slice syntax parameters
+  std::vector<uint32_t> m_rasterSliceSize;                    ///< raster-scan slice sizes in units of tiles
+  bool      m_bLFCrossTileBoundaryFlag;                       ///< 1: filter across tile boundaries  0: do not filter across tile boundaries
+  bool      m_bLFCrossSliceBoundaryFlag;                      ///< 1: filter across slice boundaries 0: do not filter across slice boundaries
+#else
   //====== Slice ========
   SliceConstraint m_sliceMode;
   int       m_sliceArgument;
@@ -487,8 +501,10 @@ protected:
   SliceConstraint m_sliceSegmentMode;
   int       m_sliceSegmentArgument;
   bool      m_bLFCrossSliceBoundaryFlag;
+#endif
 
   bool      m_intraSmoothingDisabledFlag;
+#if !JVET_P1004_REMOVE_BRICKS
   bool      m_loopFilterAcrossBricksEnabledFlag;
   bool      m_tileUniformSpacingFlag;
   int       m_iNumColumnsMinus1;
@@ -497,9 +513,11 @@ protected:
   int       m_uniformTileRowHeightMinus1;
   std::vector<int> m_tileColumnWidth;
   std::vector<int> m_tileRowHeight;
+#endif
 
   bool      m_entropyCodingSyncEnabledFlag;
 
+#if !JVET_P1004_REMOVE_BRICKS
   bool      m_rectSliceFlag;
   int       m_numSlicesInPicMinus1;
   std::vector<int> m_topLeftBrickIdx;
@@ -509,6 +527,7 @@ protected:
   int       m_signalledSliceIdLengthMinus1;
   std::vector<int> m_sliceId;
   BrickSplitMap m_brickSplitMap;
+#endif
 
   HashType  m_decodedPictureHashSEIType;
   bool      m_bufferingPeriodSEIEnabled;
@@ -727,8 +746,10 @@ protected:
 
 public:
   EncCfg()
+#if !JVET_P1004_REMOVE_BRICKS
   : m_tileColumnWidth()
   , m_tileRowHeight()
+#endif
   {
   }
 
@@ -1319,6 +1340,29 @@ public:
   uint32_t      getDeltaQpRD                    () const { return m_uiDeltaQpRD; }
   bool      getFastDeltaQp                  () const { return m_bFastDeltaQP; }
 
+#if JVET_P1004_REMOVE_BRICKS
+  //====== Tiles and Slices ========
+  void      setNoPicPartitionFlag( bool b )                                { m_noPicPartitionFlag = b;              }
+  bool      getNoPicPartitionFlag()                                        { return m_noPicPartitionFlag;           }
+  void      setTileColWidths( std::vector<uint32_t> tileColWidths )        { m_tileColumnWidth = tileColWidths;     }
+  const     std::vector<uint32_t>*   getTileColWidths() const              { return &m_tileColumnWidth;             }
+  void      setTileRowHeights( std::vector<uint32_t> tileRowHeights )      { m_tileRowHeight = tileRowHeights;      }
+  const     std::vector<uint32_t>*   getTileRowHeights() const             { return &m_tileRowHeight;               }
+  void      setRectSliceFlag( bool b )                                     { m_rectSliceFlag = b;                   }
+  bool      getRectSliceFlag()                                             { return m_rectSliceFlag;                }
+  void      setNumSlicesInPic( uint32_t u )                                { m_numSlicesInPic = u;                  }
+  uint32_t  getNumSlicesInPic()                                            { return m_numSlicesInPic;               }
+  void      setTileIdxDeltaPresentFlag( bool b )                           { m_tileIdxDeltaPresentFlag = b;         }
+  bool      getTileIdxDeltaPresentFlag()                                   { return m_tileIdxDeltaPresentFlag;      }
+  void      setRectSlices( std::vector<RectSlice> rectSlices )             { m_rectSlices = rectSlices;             }
+  const     std::vector<RectSlice>*   getRectSlices() const                { return &m_rectSlices;                  }
+  void      setRasterSliceSizes( std::vector<uint32_t> rasterSliceSizes )  { m_rasterSliceSize = rasterSliceSizes;  }
+  const     std::vector<uint32_t>*   getRasterSliceSizes() const           { return &m_rasterSliceSize;             }
+  void      setLFCrossTileBoundaryFlag( bool b )                           { m_bLFCrossTileBoundaryFlag = b;        }
+  bool      getLFCrossTileBoundaryFlag()                                   { return m_bLFCrossTileBoundaryFlag;     }
+  void      setLFCrossSliceBoundaryFlag( bool b )                          { m_bLFCrossSliceBoundaryFlag = b;       }
+  bool      getLFCrossSliceBoundaryFlag()                                  { return m_bLFCrossSliceBoundaryFlag;    }
+#else
   //====== Slice ========
   void  setSliceMode                   ( SliceConstraint  i )        { m_sliceMode = i;              }
   void  setSliceArgument               ( int  i )                    { m_sliceArgument = i;          }
@@ -1331,6 +1375,7 @@ public:
   int   getSliceSegmentArgument        ()                            { return m_sliceSegmentArgument;}
   void      setLFCrossSliceBoundaryFlag     ( bool   bValue  )       { m_bLFCrossSliceBoundaryFlag = bValue; }
   bool      getLFCrossSliceBoundaryFlag     ()                       { return m_bLFCrossSliceBoundaryFlag;   }
+#endif
 
   void      setUseSAO                  (bool bVal)                   { m_bUseSAO = bVal; }
   bool      getUseSAO                  ()                            { return m_bUseSAO; }
@@ -1348,6 +1393,7 @@ public:
 
   void  setSaoGreedyMergeEnc           (bool val)                    { m_saoGreedyMergeEnc = val; }
   bool  getSaoGreedyMergeEnc           ()                            { return m_saoGreedyMergeEnc; }
+#if !JVET_P1004_REMOVE_BRICKS
   void  setLFCrossTileBoundaryFlag               ( bool   val  )     { m_loopFilterAcrossBricksEnabledFlag = val; }
   bool  getLFCrossTileBoundaryFlag               ()                  { return m_loopFilterAcrossBricksEnabledFlag;   }
   void  setTileUniformSpacingFlag      ( bool b )                    { m_tileUniformSpacingFlag = b; }
@@ -1385,6 +1431,7 @@ public:
   void  setBrickSplitMap(const BrickSplitMap& val)                   { m_brickSplitMap = val; }
 
   void  xCheckGSParameters();
+#endif
   void  setEntropyCodingSyncEnabledFlag(bool b)                      { m_entropyCodingSyncEnabledFlag = b; }
   bool  getEntropyCodingSyncEnabledFlag() const                      { return m_entropyCodingSyncEnabledFlag; }
   void  setDecodedPictureHashSEIType(HashType m)                     { m_decodedPictureHashSEIType = m; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 9a3db3edc..d37f058c4 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1049,7 +1049,11 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par
 #endif
   if (bestCS->cus.size() == 1) // no partition
   {
+#if JVET_P1004_REMOVE_BRICKS
+    CHECK(bestCS->cus[0]->tileIdx != bestCS->pps->getTileIdx(bestCS->area.lumaPos()), "Wrong tile index!");
+#else
     CHECK(bestCS->cus[0]->tileIdx != bestCS->picture->brickMap->getBrickIdxRsMap(bestCS->area.lumaPos()), "Wrong tile index!");
+#endif
     if (bestCS->cus[0]->predMode == MODE_PLT)
     {
       for (int i = compBegin; i < (compBegin + numComp); i++)
@@ -1711,6 +1715,7 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
   // The exception is each slice / slice-segment must have at least one CTU.
   if (bestCS->cost != MAX_DOUBLE)
   {
+#if !JVET_P1004_REMOVE_BRICKS
     const BrickMap& tileMap = *tempCS->picture->brickMap;
     const uint32_t CtuAddr  = CU::getCtuAddr( *bestCS->getCU( partitioner.chType ) );
     const bool isEndOfSlice = slice.getSliceMode() == FIXED_NUMBER_OF_BYTES
@@ -1722,6 +1727,7 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
       bestCS->cost = MAX_DOUBLE;
       bestCS->costDbOffset = 0;
     }
+#endif
   }
   else
   {
@@ -1860,7 +1866,11 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
 
           partitioner.setCUData( cu );
           cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+          cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
           cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
           cu.skip             = false;
           cu.mmvdSkip = false;
           cu.predMode         = MODE_INTRA;
@@ -2211,7 +2221,11 @@ void EncCu::xCheckPLT(CodingStructure *&tempCS, CodingStructure *&bestCS, Partit
   CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
   partitioner.setCUData(cu);
   cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+  cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos());
+#else
   cu.tileIdx = tempCS->picture->brickMap->getBrickIdxRsMap(tempCS->area.lumaPos());
+#endif
   cu.skip = false;
   cu.mmvdSkip = false;
   cu.predMode = MODE_PLT;
@@ -2409,7 +2423,11 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b
 
   partitioner.setCUData(cu);
   cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+  cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos());
+#else
   cu.tileIdx = tempCS->picture->brickMap->getBrickIdxRsMap(tempCS->area.lumaPos());
+#endif
   cu.skip = false;
   cu.predMode = MODE_INTER;
   cu.transQuantBypass = encTestMode.lossless;
@@ -2470,7 +2488,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     cu.cs       = tempCS;
     cu.predMode = MODE_INTER;
     cu.slice    = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx  = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx  = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
 
     PredictionUnit pu( tempCS->area );
     pu.cu = &cu;
@@ -2590,7 +2612,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda(cu.transQuantBypass) * FRAC_BITS_SCALE;
       partitioner.setCUData( cu );
       cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+      cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
       cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
       cu.skip             = false;
       cu.mmvdSkip = false;
       cu.triangle         = false;
@@ -2871,7 +2897,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
       partitioner.setCUData( cu );
       cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+      cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
       cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
       cu.skip             = false;
       cu.mmvdSkip = false;
       cu.triangle         = false;
@@ -3095,7 +3125,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     cu.cs       = tempCS;
     cu.predMode = MODE_INTER;
     cu.slice    = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
     cu.triangle = true;
     cu.mmvdSkip = false;
     cu.GBiIdx   = GBI_DEFAULT;
@@ -3133,7 +3167,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
     partitioner.setCUData( cu );
     cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
     cu.skip             = false;
     cu.predMode         = MODE_INTER;
     cu.transQuantBypass = encTestMode.lossless;
@@ -3247,7 +3285,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
         partitioner.setCUData(cu);
         cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+        cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
         cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
         cu.skip = false;
         cu.predMode = MODE_INTER;
         cu.transQuantBypass = encTestMode.lossless;
@@ -3323,7 +3365,11 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     cu.cs = tempCS;
     cu.predMode = MODE_INTER;
     cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
     cu.mmvdSkip = false;
 
     PredictionUnit pu( tempCS->area );
@@ -3378,7 +3424,11 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
 
       partitioner.setCUData( cu );
       cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+      cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
       cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
       cu.skip = false;
       cu.affine = true;
       cu.predMode = MODE_INTER;
@@ -3491,7 +3541,11 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
 
       partitioner.setCUData( cu );
       cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+      cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
       cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
       cu.skip = false;
       cu.affine = true;
       cu.predMode = MODE_INTER;
@@ -3614,7 +3668,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
     cu.cs = tempCS;
     cu.predMode = MODE_IBC;
     cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
     PredictionUnit pu(tempCS->area);
     pu.cu = &cu;
     pu.cs = tempCS;
@@ -3653,7 +3711,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
       partitioner.setCUData(cu);
       cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+      cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
       cu.tileIdx = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
       cu.skip = false;
       cu.predMode = MODE_IBC;
       cu.transQuantBypass = encTestMode.lossless;
@@ -3772,7 +3834,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
             partitioner.setCUData(cu);
             cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+            cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
             cu.tileIdx = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
             cu.skip = false;
             cu.predMode = MODE_IBC;
             cu.transQuantBypass = encTestMode.lossless;
@@ -3856,7 +3922,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
 
     partitioner.setCUData(cu);
     cu.slice = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+    cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
     cu.tileIdx = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
     cu.skip = false;
     cu.predMode = MODE_IBC;
     cu.transQuantBypass = encTestMode.lossless;
@@ -3994,7 +4064,11 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
 
   partitioner.setCUData( cu );
   cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+  cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
   cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
   cu.skip             = false;
   cu.mmvdSkip = false;
 //cu.affine
@@ -4131,7 +4205,11 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
 
   partitioner.setCUData( cu );
   cu.slice            = tempCS->slice;
+#if JVET_P1004_REMOVE_BRICKS
+  cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#else
   cu.tileIdx          = tempCS->picture->brickMap->getBrickIdxRsMap( tempCS->area.lumaPos() );
+#endif
   cu.skip             = false;
   cu.mmvdSkip = false;
 //cu.affine
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 4040bfe13..ea632aa70 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2784,9 +2784,15 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
     // Allocate some coders, now the number of tiles are known.
     const uint32_t numberOfCtusInFrame = pcPic->cs->pcv->sizeInCtus;
+#if JVET_P1004_REMOVE_BRICKS
+    const int numSubstreamsColumns = pcSlice->getPPS()->getNumTileColumns();
+    const int numSubstreamRows     = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->cs->pcv->heightInCtus : (pcSlice->getPPS()->getNumTileRows());
+    const int numSubstreams        = std::max<int> (numSubstreamRows * numSubstreamsColumns, (int) pcPic->cs->pps->getNumSlicesInPic());
+#else
     const int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1);
     const int numSubstreamRows     = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->cs->pcv->heightInCtus : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1);
     const int numSubstreams        = std::max<int> (numSubstreamRows * numSubstreamsColumns, (int) pcPic->brickMap->bricks.size());
+#endif
     std::vector<OutputBitstream> substreamsOut(numSubstreams);
 
 #if ENABLE_QPA
@@ -2896,18 +2902,28 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     {
       DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );
 
+#if JVET_P1004_REMOVE_BRICKS
+      for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ )
+      {
+        pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) );
+#else
       pcSlice->setSliceCurStartCtuTsAddr( 0 );
 
       uint32_t sliceIdx = 0;
       const BrickMap& tileMap = *(pcPic->brickMap);
       for(uint32_t nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
       {
+#endif
         m_pcSliceEncoder->precompressSlice( pcPic );
         m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
 
+#if JVET_P1004_REMOVE_BRICKS
+        if(sliceIdx < pcPic->cs->pps->getNumSlicesInPic() - 1)
+#else
         const uint32_t curSliceEnd = pcSlice->getSliceCurEndCtuTsAddr();
         pcSlice->setSliceIndex(sliceIdx);
         if(curSliceEnd < numberOfCtusInFrame)
+#endif
         {
           uint32_t independentSliceIdx = pcSlice->getIndependentSliceIdx();
           pcPic->allocateNewSlice();
@@ -2916,6 +2932,7 @@ 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_P1004_REMOVE_BRICKS
           sliceIdx++;
           if (pcSlice->getPPS()->getRectSliceFlag())
           {
@@ -2933,12 +2950,15 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
           {
             pcSlice->setSliceCurStartCtuTsAddr(curSliceEnd);
           }
+#endif
           pcSlice->setSliceBits(0);
           independentSliceIdx++;
           pcSlice->setIndependentSliceIdx(independentSliceIdx);
           uiNumSliceSegments++;
         }
+#if !JVET_P1004_REMOVE_BRICKS
         nextCtuTsAddr = curSliceEnd;
+#endif
       }
 
       duData.clear();
@@ -3307,7 +3327,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       std::size_t binCountsInNalUnits   = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
       std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
 
+#if JVET_P1004_REMOVE_BRICKS
+      for(uint32_t sliceSegmentIdxCount = 0; sliceSegmentIdxCount < pcPic->cs->pps->getNumSlicesInPic(); sliceSegmentIdxCount++ )
+#else
       for(uint32_t sliceSegmentStartCtuTsAddr = 0, sliceSegmentIdxCount = 0; sliceSegmentStartCtuTsAddr < numberOfCtusInFrame; sliceSegmentIdxCount++, sliceSegmentStartCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr())
+#endif
       {
         pcSlice = pcPic->slices[sliceSegmentIdxCount];
         if(sliceSegmentIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE)
diff --git a/source/Lib/EncoderLib/EncHRD.cpp b/source/Lib/EncoderLib/EncHRD.cpp
index 5ed238f8f..794b63748 100644
--- a/source/Lib/EncoderLib/EncHRD.cpp
+++ b/source/Lib/EncoderLib/EncHRD.cpp
@@ -57,7 +57,11 @@ int EncHRD::xCalcScale(int x)
 
 void EncHRD::initHRDParameters (EncCfg* encCfg)
 {
+#if JVET_P1004_REMOVE_BRICKS
+  bool useSubCpbParams = encCfg->getNoPicPartitionFlag() == false;
+#else
   bool useSubCpbParams = (encCfg->getSliceMode() > 0) || (encCfg->getSliceSegmentMode() > 0);
+#endif
   int  bitRate         = encCfg->getTargetBitrate();
 # if U0132_TARGET_BITS_SATURATION
   int cpbSize          = encCfg->getCpbSize();
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index fe589b7c7..f08f77741 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -309,6 +309,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
 
     conformanceWindow.setWindow( 0, ( width - scaledWidth ) / SPS::getWinUnitX( sps0.getChromaFormatIdc() ), 0, ( height - scaledHeight ) / SPS::getWinUnitY( sps0.getChromaFormatIdc() ) );
 
+#if JVET_P1004_REMOVE_BRICKS
+    // disable picture partitioning for scaled RPR pictures (slice/tile config only provided for the original resolution)
+    m_noPicPartitionFlag = true;
+
+#endif
     pps.setConformanceWindow( conformanceWindow );
 
     xInitPPS( pps, sps0 ); // will allocate memory for and initialize pps.pcv inside
@@ -457,7 +462,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
 #else
     picBg->finalInit( sps0, pps0, m_apss, m_lmcsAPS, m_scalinglistAPS );
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
     pps0.setNumBricksInPic((int)picBg->brickMap->bricks.size());
+#endif
     picBg->allocateNewSlice();
     picBg->createSpliceIdx(pps0.pcv->sizeInCtus);
     m_cGOPEncoder.setPicBg(picBg);
@@ -708,8 +715,10 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu
 #else
     pcPicCurr->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS );
 #endif
+#if !JVET_P1004_REMOVE_BRICKS
     PPS *ptrPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID );
     ptrPPS->setNumBricksInPic( (int)pcPicCurr->brickMap->bricks.size() );
+#endif
 
     pcPicCurr->poc = m_iPOCLast;
 
@@ -1761,7 +1770,51 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps)
 
   pps.setEntropyCodingSyncEnabledFlag( m_entropyCodingSyncEnabledFlag );
 
+#if JVET_P1004_REMOVE_BRICKS
+  pps.setNoPicPartitionFlag( m_noPicPartitionFlag );
+  if( m_noPicPartitionFlag == false )
+  {
+    pps.setLog2CtuSize( ceilLog2( sps.getCTUSize()) );
+    pps.setNumExpTileColumns( (uint32_t) m_tileColumnWidth.size() );
+    pps.setNumExpTileRows( (uint32_t) m_tileRowHeight.size() );
+    pps.setTileColumnWidths( m_tileColumnWidth );
+    pps.setTileRowHeights( m_tileRowHeight );
+    pps.initTiles();
+    pps.setRectSliceFlag( m_rectSliceFlag );
+    if( m_rectSliceFlag ) 
+    {
+      pps.setNumSlicesInPic( m_numSlicesInPic );
+      pps.setTileIdxDeltaPresentFlag( m_tileIdxDeltaPresentFlag );
+      pps.setRectSlices( m_rectSlices );
+      pps.initRectSliceMap( );
+    }
+    else
+    {
+      pps.initRasterSliceMap( m_rasterSliceSize );
+    }
+    pps.setLoopFilterAcrossTilesEnabledFlag( m_bLFCrossTileBoundaryFlag );
+    pps.setLoopFilterAcrossSlicesEnabledFlag( m_bLFCrossSliceBoundaryFlag );
+  }
+  else
+  {
+    pps.setLog2CtuSize( ceilLog2( sps.getCTUSize()) );
+    pps.setNumExpTileColumns(1);
+    pps.setNumExpTileRows(1);
+    pps.addTileColumnWidth( pps.getPicWidthInCtu( ) );
+    pps.addTileRowHeight( pps.getPicHeightInCtu( ) );
+    pps.initTiles();
+    pps.setRectSliceFlag( 1 );
+    pps.setNumSlicesInPic( 1 );
+    pps.initRectSlices( );
+    pps.setTileIdxDeltaPresentFlag( 0 );
+    pps.setSliceTileIdx( 0, 0 );
+    pps.initRectSliceMap( );
+    pps.setLoopFilterAcrossTilesEnabledFlag( true );
+    pps.setLoopFilterAcrossSlicesEnabledFlag( true );
+  }
+#else
   pps.setSingleTileInPicFlag((m_iNumColumnsMinus1 == 0 && m_iNumRowsMinus1 == 0));
+#endif
 
   pps.setUseWP( m_useWeightedPred );
   pps.setWPBiPred( m_useWeightedBiPred );
@@ -1827,10 +1880,12 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps)
   pps.setNumRefIdxL1DefaultActive(bestPos);
   pps.setTransquantBypassEnabledFlag(getTransquantBypassEnabledFlag());
   pps.setLog2MaxTransformSkipBlockSize(m_log2MaxTransformSkipBlockSize);
+#if !JVET_P1004_REMOVE_BRICKS
 
 
   xInitPPSforTiles(pps);
 
+#endif
 #if JVET_P1006_PICTURE_HEADER
   pps.setPictureHeaderExtensionPresentFlag(false);
 #else
@@ -2150,6 +2205,7 @@ void EncLib::selectReferencePictureList(Slice* slice, int POCCurr, int GOPid, in
   slice->setRPL1(rpl1);
 }
 
+#if !JVET_P1004_REMOVE_BRICKS
 void  EncLib::xInitPPSforTiles(PPS &pps)
 {
   if ( (m_iNumColumnsMinus1==0) && (m_iNumRowsMinus1==0) )
@@ -2380,6 +2436,7 @@ void  EncCfg::xCheckGSParameters()
     }
   }
 }
+#endif
 
 void EncLib::setParamSetChanged(int spsId, int ppsId)
 {
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index 8045eb45b..ad7db2fae 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -193,7 +193,9 @@ protected:
   void  xInitPPSforLT(PPS& pps);
   void  xInitHrdParameters(SPS &sps);                 ///< initialize HRDParameters parameters
 
+#if !JVET_P1004_REMOVE_BRICKS
   void  xInitPPSforTiles  (PPS &pps);
+#endif
   void  xInitRPL(SPS &sps, bool isFieldCoding);           ///< initialize SPS from encoder options
 
 public:
diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
index 4755f9c8a..8f01f19d0 100644
--- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
+++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
@@ -838,7 +838,11 @@ void EncSampleAdaptiveOffset::decideBlkParams(CodingStructure& cs, bool* sliceEn
 
   int ctuRsAddr = 0;
 #if ENABLE_QPA
+#if JVET_P1004_REMOVE_BRICKS
+  CHECK ((chromaWeight > 0.0) && (cs.slice->getFirstCtuRsAddrInSlice() != 0), "incompatible start CTU address, must be 0");
+#else
   CHECK ((chromaWeight > 0.0) && (cs.slice->getSliceCurStartCtuTsAddr() != 0), "incompatible start CTU address, must be 0");
+#endif
 #endif
 
   for( uint32_t yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight )
@@ -1548,7 +1552,11 @@ void EncSampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructu
 #if JVET_P1006_PICTURE_HEADER
   bool isLoopFiltAcrossSlicePPS = cs.pps->getLoopFilterAcrossSlicesEnabledFlag();
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  bool isLoopFiltAcrossTilePPS = cs.pps->getLoopFilterAcrossTilesEnabledFlag();
+#else
   bool isLoopFiltAcrossTilePPS = cs.pps->getLoopFilterAcrossBricksEnabledFlag();
+#endif
 
   const int width = cs.pcv->maxCUWidth;
   const int height = cs.pcv->maxCUHeight;
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 0da1160a5..0fa4a2105 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -203,7 +203,11 @@ static double getAveragePictureEnergy (const CPelBuf picOrig, const uint32_t uBi
 }
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+static int getGlaringColorQPOffset (Picture* const pcPic, const int ctuAddr, Slice* const pcSlice,
+#else
 static int getGlaringColorQPOffset (Picture* const pcPic, const int ctuAddr, const uint32_t startAddr, const uint32_t boundingAddr,
+#endif
                                     const int bitDepth,   uint32_t &avgLumaValue)
 {
   const PreCalcValues& pcv  = *pcPic->cs->pcv;
@@ -212,20 +216,38 @@ static int getGlaringColorQPOffset (Picture* const pcPic, const int ctuAddr, con
   const uint32_t chrHeight  = pcv.maxCUHeight >> getChannelTypeScaleY (CH_C, chrFmt);
   const int      midLevel   = 1 << (bitDepth - 1);
   int chrValue = MAX_INT;
+#if JVET_P1004_REMOVE_BRICKS
+  avgLumaValue = (pcSlice != nullptr) ? 0 : (uint32_t)pcPic->getOrigBuf().Y().computeAvg();
+#else
   avgLumaValue = (startAddr < boundingAddr) ? 0 : (uint32_t)pcPic->getOrigBuf().Y().computeAvg();
+#endif
 
   if (ctuAddr >= 0) // luma
   {
     avgLumaValue = (uint32_t)pcPic->m_iOffsetCtu[ctuAddr];
   }
+#if JVET_P1004_REMOVE_BRICKS
+  else if (pcSlice != nullptr)
+#else
   else if (startAddr < boundingAddr)
+#endif
   {
+#if JVET_P1004_REMOVE_BRICKS
+    for (uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++)
+    {
+      uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
     for (uint32_t ctuTsAddr = startAddr; ctuTsAddr < boundingAddr; ctuTsAddr++)
     {
       const uint32_t ctuRsAddr = pcPic->brickMap->getCtuBsToRsAddrMap (ctuTsAddr);
+#endif
       avgLumaValue += pcPic->m_iOffsetCtu[ctuRsAddr];
     }
+#if JVET_P1004_REMOVE_BRICKS
+    avgLumaValue = (avgLumaValue + (pcSlice->getNumCtuInSlice() >> 1)) / pcSlice->getNumCtuInSlice();
+#else
     avgLumaValue = (avgLumaValue + ((boundingAddr - startAddr) >> 1)) / (boundingAddr - startAddr);
+#endif
   }
 
   for (uint32_t comp = COMPONENT_Cb; comp < MAX_NUM_COMPONENT; comp++)
@@ -279,7 +301,11 @@ static int applyQPAdaptationChroma (Picture* const pcPic, Slice* const pcSlice,
         int     averageAdaptedLumaQP = Clip3 (0, MAX_QP, sliceQP); // mean slice QP
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+        averageAdaptedLumaQP += getGlaringColorQPOffset (pcPic, -1 /*ctuRsAddr*/, nullptr /*pcSlice*/, bitDepth, meanLuma);
+#else
         averageAdaptedLumaQP += getGlaringColorQPOffset (pcPic, -1 /*ctuRsAddr*/, 0 /*startAddr*/, 0 /*boundingAddr*/, bitDepth, meanLuma);
+#endif
 
         if (averageAdaptedLumaQP > MAX_QP
 #if SHARP_LUMA_DELTA_QP
@@ -659,8 +685,10 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
   }
   rpcSlice->setTLayer( pcPic->layer );
 
+#if !JVET_P1004_REMOVE_BRICKS
   rpcSlice->setSliceMode            ( m_pcCfg->getSliceMode()            );
   rpcSlice->setSliceArgument        ( m_pcCfg->getSliceArgument()        );
+#endif
 #if !JVET_P1006_PICTURE_HEADER
   rpcSlice->setMaxNumMergeCand      ( m_pcCfg->getMaxNumMergeCand()      );
   rpcSlice->setMaxNumAffineMergeCand( m_pcCfg->getMaxNumAffineMergeCand() );
@@ -794,12 +822,18 @@ void EncSlice::resetQP( Picture* pic, int sliceQP, double lambda )
 
 #if ENABLE_QPA
 static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,        const PreCalcValues& pcv,
+#if JVET_P1004_REMOVE_BRICKS
+                               const bool useSharpLumaDQP,
+#else
                                const uint32_t startAddr,   const uint32_t boundingAddr, const bool useSharpLumaDQP,
+#endif
                                const bool useFrameWiseQPA, const int previouslyAdaptedLumaQP = -1)
 {
   const int  bitDepth    = pcSlice->getSPS()->getBitDepth (CHANNEL_TYPE_LUMA);
   const int  iQPIndex    = pcSlice->getSliceQp(); // initial QP index for current slice, used in following loops
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap& tileMap = *pcPic->brickMap;
+#endif
   bool   sliceQPModified = false;
   uint32_t   meanLuma    = MAX_UINT;
   double     hpEnerAvg   = 0.0;
@@ -808,9 +842,15 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
   if (!useFrameWiseQPA || previouslyAdaptedLumaQP < 0)  // mean visual activity value and luma value in each CTU
 #endif
   {
+#if JVET_P1004_REMOVE_BRICKS
+    for (uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++)
+    {
+      uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
     for (uint32_t ctuTsAddr = startAddr; ctuTsAddr < boundingAddr; ctuTsAddr++)
     {
       const uint32_t ctuRsAddr  = tileMap.getCtuBsToRsAddrMap (ctuTsAddr);
+#endif
       const Position pos ((ctuRsAddr % pcv.widthInCtus) * pcv.maxCUWidth, (ctuRsAddr / pcv.widthInCtus) * pcv.maxCUHeight);
       const CompArea ctuArea    = clipArea (CompArea (COMPONENT_Y, pcPic->chromaFormat, Area (pos.x, pos.y, pcv.maxCUWidth, pcv.maxCUHeight)), pcPic->Y());
       const CompArea fltArea    = clipArea (CompArea (COMPONENT_Y, pcPic->chromaFormat, Area (pos.x > 0 ? pos.x - 1 : 0, pos.y > 0 ? pos.y - 1 : 0, pcv.maxCUWidth + (pos.x > 0 ? 2 : 1), pcv.maxCUHeight + (pos.y > 0 ? 2 : 1))), pcPic->Y());
@@ -824,7 +864,11 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
       pcPic->m_iOffsetCtu[ctuRsAddr] = pcPic->getOrigBuf (ctuArea).computeAvg();
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    hpEnerAvg /= double (pcSlice->getNumCtuInSlice());
+#else
     hpEnerAvg /= double (boundingAddr - startAddr);
+#endif
   }
 #if GLOBAL_AVERAGING
   const double hpEnerPic = 1.0 / getAveragePictureEnergy (pcPic->getOrigBuf().Y(), bitDepth);  // inverse, speed
@@ -838,7 +882,11 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
 
     if (isChromaEnabled (pcPic->chromaFormat) && (iQPIndex < MAX_QP) && (previouslyAdaptedLumaQP < 0))
     {
+#if JVET_P1004_REMOVE_BRICKS
+      iQPFixed += getGlaringColorQPOffset (pcPic, -1 /*ctuRsAddr*/, pcSlice, bitDepth, meanLuma);
+#else
       iQPFixed += getGlaringColorQPOffset (pcPic, -1 /*ctuRsAddr*/, startAddr, boundingAddr, bitDepth, meanLuma);
+#endif
 
       if (iQPFixed > MAX_QP
 #if SHARP_LUMA_DELTA_QP
@@ -855,13 +903,23 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
       {
         meanLuma = 0;
 
+#if JVET_P1004_REMOVE_BRICKS
+        for (uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++)
+        {
+          uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
         for (uint32_t ctuTsAddr = startAddr; ctuTsAddr < boundingAddr; ctuTsAddr++)
         {
           const uint32_t ctuRsAddr = tileMap.getCtuBsToRsAddrMap (ctuTsAddr);
+#endif
 
           meanLuma += pcPic->m_iOffsetCtu[ctuRsAddr];  // CTU mean
         }
+#if JVET_P1004_REMOVE_BRICKS
+        meanLuma = (meanLuma + (pcSlice->getNumCtuInSlice() >> 1)) / pcSlice->getNumCtuInSlice();
+#else
         meanLuma = (meanLuma + ((boundingAddr - startAddr) >> 1)) / (boundingAddr - startAddr);
+#endif
       }
       iQPFixed = Clip3 (0, MAX_QP, iQPFixed + lumaDQPOffset (meanLuma, bitDepth));
     }
@@ -883,18 +941,30 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
       sliceQPModified = true;
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    for (uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++)
+    {
+      uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
     for (uint32_t ctuTsAddr = startAddr; ctuTsAddr < boundingAddr; ctuTsAddr++)
     {
       const uint32_t ctuRsAddr = tileMap.getCtuBsToRsAddrMap (ctuTsAddr);
+#endif
 
       pcPic->m_iOffsetCtu[ctuRsAddr] = (Pel)iQPFixed; // fixed QPs
     }
   }
   else // CTU-wise QPA
   {
+#if JVET_P1004_REMOVE_BRICKS
+    for (uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++)
+    {
+      uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
     for (uint32_t ctuTsAddr = startAddr; ctuTsAddr < boundingAddr; ctuTsAddr++)
     {
       const uint32_t ctuRsAddr = tileMap.getCtuBsToRsAddrMap (ctuTsAddr);
+#endif
 
       int iQPAdapt = Clip3 (0, MAX_QP, iQPIndex + apprI3Log2 (pcPic->m_uEnerHpCtu[ctuRsAddr] * hpEnerPic));
 
@@ -904,7 +974,11 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
 
         if (isChromaEnabled (pcPic->chromaFormat))
         {
+#if JVET_P1004_REMOVE_BRICKS
+          iQPAdapt += getGlaringColorQPOffset (pcPic, (int)ctuRsAddr, nullptr, bitDepth, meanLuma);
+#else
           iQPAdapt += getGlaringColorQPOffset (pcPic, (int)ctuRsAddr, startAddr, boundingAddr, bitDepth, meanLuma);
+#endif
 
           if (iQPAdapt > MAX_QP
 #if SHARP_LUMA_DELTA_QP
@@ -993,7 +1067,11 @@ static bool applyQPAdaptation (Picture* const pcPic,       Slice* const pcSlice,
         {
           pcPic->m_iOffsetCtu[ctuRsAddr - 1] = (Pel)iQPAdapt;
         }
+#if JVET_P1004_REMOVE_BRICKS
+        if ((ctuIdx == pcSlice->getNumCtuInSlice() - 1) && (ctuRsAddr > pcv.widthInCtus)) // last CTU in the given slice
+#else
         if ((ctuTsAddr == boundingAddr - 1) && (ctuRsAddr > pcv.widthInCtus)) // last CTU in the given slice
+#endif
         {
           iQPAdapt = std::min (pcPic->m_iOffsetCtu[ctuRsAddr - 1], pcPic->m_iOffsetCtu[ctuRsAddr - pcv.widthInCtus]);
           if (pcPic->m_iOffsetCtu[ctuRsAddr] < (Pel)iQPAdapt)
@@ -1157,11 +1235,13 @@ void EncSlice::precompressSlice( Picture* pcPic )
   Slice* pcSlice        = pcPic->slices[getSliceSegmentIdx()];
 
 
+#if !JVET_P1004_REMOVE_BRICKS
   if (pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES)
   {
     // TODO: investigate use of average cost per CTU so that this Slice Mode can be used.
     THROW( "Unable to optimise Slice-level QP if Slice Mode is set to FIXED_NUMBER_OF_BYTES\n" );
   }
+#endif
 
   double     dPicRdCostBest = MAX_DOUBLE;
   uint32_t       uiQpIdxBest = 0;
@@ -1218,19 +1298,27 @@ void EncSlice::calCostSliceI(Picture* pcPic) // TODO: this only analyses the fir
 {
   double         iSumHadSlice      = 0;
   Slice * const  pcSlice           = pcPic->slices[getSliceSegmentIdx()];
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap &tileMap          = *pcPic->brickMap;
+#endif
   const PreCalcValues& pcv         = *pcPic->cs->pcv;
   const SPS     &sps               = *(pcSlice->getSPS());
   const int      shift             = sps.getBitDepth(CHANNEL_TYPE_LUMA)-8;
   const int      offset            = (shift>0)?(1<<(shift-1)):0;
 
 
+#if JVET_P1004_REMOVE_BRICKS
+  for( uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++ )
+  {
+    uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
   uint32_t startCtuTsAddr, boundingCtuTsAddr;
   xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic );
   for( uint32_t ctuTsAddr = startCtuTsAddr, ctuRsAddr = tileMap.getCtuBsToRsAddrMap( startCtuTsAddr);
        ctuTsAddr < boundingCtuTsAddr;
        ctuRsAddr = tileMap.getCtuBsToRsAddrMap(++ctuTsAddr) )
   {
+#endif
     Position pos( (ctuRsAddr % pcv.widthInCtus) * pcv.maxCUWidth, (ctuRsAddr / pcv.widthInCtus) * pcv.maxCUHeight);
 
     const int height  = std::min( pcv.maxCUHeight, pcv.lumaHeight - pos.y );
@@ -1253,6 +1341,7 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   //   effectively disabling the slice-segment-mode.
 
   Slice* const pcSlice    = pcPic->slices[getSliceSegmentIdx()];
+#if !JVET_P1004_REMOVE_BRICKS
   uint32_t  startCtuTsAddr;
   uint32_t  boundingCtuTsAddr;
 
@@ -1261,6 +1350,7 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   {
     boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr();
   }
+#endif
 
   // initialize cost values - these are used by precompressSlice (they should be parameters).
   m_uiPicTotalBits  = 0;
@@ -1294,6 +1384,7 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
 
   if ( bWp_explicit )
   {
+#if !JVET_P1004_REMOVE_BRICKS
     //------------------------------------------------------------------------------
     //  Weighted Prediction implemented at Slice level. SliceMode=2 is not supported yet.
     //------------------------------------------------------------------------------
@@ -1301,6 +1392,7 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
     {
       EXIT("Weighted Prediction is not yet supported with slice mode determined by max number of bins.");
     }
+#endif
 
     xEstimateWPParamSlice( pcSlice, m_pcCfg->getWeightedPredictionMethod() );
     pcSlice->initWpScaling(pcSlice->getSPS());
@@ -1320,16 +1412,29 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   cs.pcv      = pcSlice->getPPS()->pcv;
   cs.fracBits = 0;
 
+#if JVET_P1004_REMOVE_BRICKS
+  if( pcSlice->getFirstCtuRsAddrInSlice() == 0 && ( pcSlice->getPOC() != m_pcCfg->getSwitchPOC() || -1 == m_pcCfg->getDebugCTU() ) )
+#else
   if( startCtuTsAddr == 0 && ( pcSlice->getPOC() != m_pcCfg->getSwitchPOC() || -1 == m_pcCfg->getDebugCTU() ) )
+#endif
   {
     cs.initStructData (pcSlice->getSliceQp(), pcSlice->getPPS()->getTransquantBypassEnabledFlag());
   }
 
 #if ENABLE_QPA
+#if JVET_P1004_REMOVE_BRICKS
+  if (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl())
+#else
   if (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && (boundingCtuTsAddr > startCtuTsAddr))
+#endif
   {
+#if JVET_P1004_REMOVE_BRICKS
+    if (applyQPAdaptation (pcPic, pcSlice, *cs.pcv, m_pcCfg->getLumaLevelToDeltaQPMapping().mode == LUMALVL_TO_DQP_NUM_MODES,
+                           (m_pcCfg->getBaseQP() >= 38) || (m_pcCfg->getSourceWidth() <= 512 && m_pcCfg->getSourceHeight() <= 320), m_adaptedLumaQP))
+#else
     if (applyQPAdaptation (pcPic, pcSlice, *cs.pcv, startCtuTsAddr, boundingCtuTsAddr, m_pcCfg->getLumaLevelToDeltaQPMapping().mode == LUMALVL_TO_DQP_NUM_MODES,
                            (m_pcCfg->getBaseQP() >= 38) || (m_pcCfg->getSourceWidth() <= 512 && m_pcCfg->getSourceHeight() <= 320), m_adaptedLumaQP))
+#endif
     {
       m_CABACEstimator->initCtxModels (*pcSlice);
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
@@ -1340,7 +1445,11 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
       }
 #endif
         pcPic->m_prevQP[0] = pcPic->m_prevQP[1] = pcSlice->getSliceQp();
+#if JVET_P1004_REMOVE_BRICKS
+      if (pcSlice->getFirstCtuRsAddrInSlice() == 0)
+#else
       if (startCtuTsAddr == 0)
+#endif
       {
         cs.currQP[0] = cs.currQP[1] = pcSlice->getSliceQp(); // cf code above
       }
@@ -1363,21 +1472,33 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   bool bUseThreads = m_pcCfg->getNumWppThreads() > 1;
   if( bUseThreads )
   {
+#if JVET_P1004_REMOVE_BRICKS
+    CHECK( pcSlice->getFirstCtuRsAddrInSlice() != 0 || pcSlice->getNumCtuInSlice() != pcPic->cs->pcv->sizeInCtus, "not intended" );
+#else
     CHECK( startCtuTsAddr != 0 || boundingCtuTsAddr != pcPic->cs->pcv->sizeInCtus, "not intended" );
+#endif
 
     pcPic->cs->allocateVectorsAtPicLevel();
 
     omp_set_num_threads( m_pcCfg->getNumWppThreads() + m_pcCfg->getNumWppExtraLines() );
 
     #pragma omp parallel for schedule(static,1) if(bUseThreads)
+#if JVET_P1004_REMOVE_BRICKS
+    for( int ctuTsAddr = 0; ctuTsAddr < pcSlice->getNumCtuInSlice(); ctuTsAddr += pcPic->cs->pcv->widthInCtus )
+#else
     for( int ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr += widthInCtus )
+#endif
     {
       // wpp thread start
       pcPic->scheduler.setWppThreadId();
 #if ENABLE_SPLIT_PARALLELISM
       pcPic->scheduler.setSplitThreadId( 0 );
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+      encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, m_pcLib );
+#else
       encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, ctuTsAddr, ctuTsAddr + widthInCtus, m_pcLib );
+#endif
       // wpp thread stop
     }
   }
@@ -1391,7 +1512,11 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c
   m_pcInterSearch->resetAffineMVList();
   m_pcInterSearch->resetUniMvList();
   ::memset(g_isReusedUniMVsFilled, 0, sizeof(g_isReusedUniMVsFilled));
+#if JVET_P1004_REMOVE_BRICKS
+  encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, m_pcLib );
+#else
   encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, startCtuTsAddr, boundingCtuTsAddr, m_pcLib );
+#endif
   if (checkPLTRatio) m_pcLib->checkPltStats( pcPic );
 }
 
@@ -1401,7 +1526,9 @@ void EncSlice::checkDisFracMmvd( Picture* pcPic, uint32_t startCtuTsAddr, uint32
   Slice* pcSlice                  = cs.slice;
   const PreCalcValues& pcv        = *cs.pcv;
   const uint32_t    widthInCtus   = pcv.widthInCtus;
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap&  tileMap         = *pcPic->brickMap;
+#endif
   const uint32_t hashThreshold    = 20;
   uint32_t totalCtu               = 0;
   uint32_t hashRatio              = 0;
@@ -1411,9 +1538,15 @@ void EncSlice::checkDisFracMmvd( Picture* pcPic, uint32_t startCtuTsAddr, uint32
     return;
   }
 
+#if JVET_P1004_REMOVE_BRICKS
+  for ( uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++ )
+  {
+    const uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
   for ( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
   {
     const uint32_t ctuRsAddr = tileMap.getCtuBsToRsAddrMap( ctuTsAddr );
+#endif
     const uint32_t ctuXPosInCtus        = ctuRsAddr % widthInCtus;
     const uint32_t ctuYPosInCtus        = ctuRsAddr / widthInCtus;
 
@@ -1492,13 +1625,19 @@ void setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const S
 }
 
 
+#if JVET_P1004_REMOVE_BRICKS
+void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, EncLib* pEncLib )
+#else
 void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr, EncLib* pEncLib )
+#endif
 {
   CodingStructure&  cs            = *pcPic->cs;
   Slice* pcSlice                  = cs.slice;
   const PreCalcValues& pcv        = *cs.pcv;
   const uint32_t        widthInCtus   = pcv.widthInCtus;
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap&  tileMap        = *pcPic->brickMap;
+#endif
 #if ENABLE_QPA
   const int iQPIndex              = pcSlice->getSliceQpBase();
 #endif
@@ -1555,6 +1694,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
   }
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+  // for every CTU in the slice
+  for( uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++ )
+  {
+    const int32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
   // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment)
   uint32_t startSliceRsRow = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) / widthInCtus;
   uint32_t startSliceRsCol = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) % widthInCtus;
@@ -1567,10 +1712,13 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       ((ctuRsAddr / widthInCtus) < startSliceRsRow || (ctuRsAddr / widthInCtus) > endSliceRsRow ||
       (ctuRsAddr % widthInCtus) < startSliceRsCol || (ctuRsAddr % widthInCtus) > endSliceRsCol))
       continue;
+#endif
 
     // update CABAC state
+#if !JVET_P1004_REMOVE_BRICKS
     const uint32_t firstCtuRsAddrOfTile = tileMap.bricks[tileMap.getBrickIdxRsMap(ctuRsAddr)].getFirstCtuRsAddr();
     const uint32_t tileXPosInCtus       = firstCtuRsAddrOfTile % widthInCtus;
+#endif
     const uint32_t ctuXPosInCtus        = ctuRsAddr % widthInCtus;
     const uint32_t ctuYPosInCtus        = ctuRsAddr / widthInCtus;
 
@@ -1579,7 +1727,11 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
 
     if( pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU() )
+#if JVET_P1004_REMOVE_BRICKS
+    if ((cs.slice->getSliceType() != I_SLICE || cs.sps->getIBCFlag()) && cs.pps->ctuIsTileColBd( ctuXPosInCtus ))
+#else
     if ((cs.slice->getSliceType() != I_SLICE || cs.sps->getIBCFlag()) && ctuXPosInCtus == tileXPosInCtus)
+#endif
     {
       cs.motionLut.lut.resize(0);
       cs.motionLut.lutIbc.resize(0);
@@ -1589,18 +1741,30 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     pcPic->scheduler.wait( ctuXPosInCtus, ctuYPosInCtus );
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+    if (cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && cs.pps->ctuIsTileRowBd( ctuYPosInCtus ))
+#else
     if (ctuRsAddr == firstCtuRsAddrOfTile)
+#endif
     {
       pCABACWriter->initCtxModels( *pcSlice );
       cs.resetPrevPLT(cs.prevPLT);
       prevQP[0] = prevQP[1] = pcSlice->getSliceQp();
     }
+#if JVET_P1004_REMOVE_BRICKS
+    else if (cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && pEncLib->getEntropyCodingSyncEnabledFlag())
+#else
     else if (ctuXPosInCtus == tileXPosInCtus && pEncLib->getEntropyCodingSyncEnabledFlag())
+#endif
     {
       // reset and then update contexts to the state at the end of the top CTU (if within current slice and tile).
       pCABACWriter->initCtxModels( *pcSlice );
       cs.resetPrevPLT(cs.prevPLT);
+#if JVET_P1004_REMOVE_BRICKS
+      if( cs.getCURestricted( pos.offset(0, -1), pos, pcSlice->getIndependentSliceIdx(), cs.pps->getTileIdx( pos ), CH_L ) )
+#else
       if( cs.getCURestricted( pos.offset(0, -1), pos, pcSlice->getIndependentSliceIdx(), tileMap.getBrickIdxRsMap( pos ), CH_L ) )
+#endif
       {
         // Top is available, we use it.
         pCABACWriter->getCtx() = pEncLib->m_entropyCodingSyncContextState;
@@ -1688,7 +1852,11 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     }
 #endif
 
+#if JVET_P1004_REMOVE_BRICKS
+    bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuIdx == 0;
+#else
     bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuTsAddr == startCtuTsAddr;
+#endif
     if( updateGbiCodingOrder )
     {
       resetGbiCodingOrder(false, cs);
@@ -1725,6 +1893,7 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
     pCABACWriter->coding_tree_unit( cs, ctuArea, prevQP, ctuRsAddr, true, true );
     const int numberOfWrittenBits = int( pCABACWriter->getEstFracBits() >> SCALE_BITS );
 
+#if !JVET_P1004_REMOVE_BRICKS
     // Calculate if this CTU puts us over slice bit size.
     // cannot terminate if current slice/slice-segment would be 0 Ctu in size,
     const uint32_t validEndOfSliceCtuTsAddr = ctuTsAddr + (ctuTsAddr == startCtuTsAddr ? 1 : 0);
@@ -1739,6 +1908,7 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       break;
     }
 
+#endif
 #if ENABLE_WPP_PARALLELISM || ENABLE_SPLIT_PARALLELISM
 #pragma omp critical
 #endif
@@ -1748,7 +1918,11 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
 #endif
 
     // Store probabilities of first CTU in line into buffer - used only if wavefront-parallel-processing is enabled.
+#if JVET_P1004_REMOVE_BRICKS
+    if( cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && pEncLib->getEntropyCodingSyncEnabledFlag() )
+#else
     if( ctuXPosInCtus == tileXPosInCtus && pEncLib->getEntropyCodingSyncEnabledFlag() )
+#endif
     {
       pEncLib->m_entropyCodingSyncContextState = pCABACWriter->getCtx();
     }
@@ -1834,9 +2008,11 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 {
 
   Slice *const pcSlice               = pcPic->slices[getSliceSegmentIdx()];
+#if !JVET_P1004_REMOVE_BRICKS
   const BrickMap& tileMap            = *pcPic->brickMap;
   const uint32_t startCtuTsAddr          = pcSlice->getSliceCurStartCtuTsAddr();
   const uint32_t boundingCtuTsAddr       = pcSlice->getSliceCurEndCtuTsAddr();
+#endif
   const bool wavefrontsEnabled       = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag();
 
 
@@ -1852,12 +2028,20 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 
   const PreCalcValues& pcv = *cs.pcv;
   const uint32_t widthInCtus   = pcv.widthInCtus;
+#if !JVET_P1004_REMOVE_BRICKS
   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
   uint32_t uiSubStrm = 0;
 
+#if JVET_P1004_REMOVE_BRICKS
+  // for every CTU in the slice...
+  for( uint32_t ctuIdx = 0; ctuIdx < pcSlice->getNumCtuInSlice(); ctuIdx++ )
+  {
+    const uint32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx );
+#else
   // for every CTU in the slice segment...
 
   for( uint32_t ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr++ )
@@ -1870,6 +2054,7 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
       continue;
     const uint32_t firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr();
     const uint32_t tileXPosInCtus       = firstCtuRsAddrOfTile % widthInCtus;
+#endif
     const uint32_t ctuXPosInCtus        = ctuRsAddr % widthInCtus;
     const uint32_t ctuYPosInCtus        = ctuRsAddr / widthInCtus;
 
@@ -1880,30 +2065,54 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
     m_CABACWriter->initBitstream( &pcSubstreams[uiSubStrm] );
 
     // set up CABAC contexts' state for this CTU
+#if JVET_P1004_REMOVE_BRICKS
+    if ( cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && cs.pps->ctuIsTileRowBd( ctuYPosInCtus ) )
+#else
     if (ctuRsAddr == firstCtuRsAddrOfTile)
+#endif
     {
+#if JVET_P1004_REMOVE_BRICKS
+      if (ctuIdx != 0) // if it is the first CTU, then the entropy coder has already been reset
+#else
       if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
+#endif
       {
         m_CABACWriter->initCtxModels( *pcSlice );
         cs.resetPrevPLT(cs.prevPLT);
       }
     }
+#if JVET_P1004_REMOVE_BRICKS
+    else if (cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && wavefrontsEnabled)
+#else
     else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled)
+#endif
     {
       // Synchronize cabac probabilities with upper CTU if it's available and at the start of a line.
+#if JVET_P1004_REMOVE_BRICKS
+      if (ctuIdx != 0) // if it is the first CTU, then the entropy coder has already been reset
+#else
       if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
+#endif
       {
         m_CABACWriter->initCtxModels( *pcSlice );
         cs.resetPrevPLT(cs.prevPLT);
       }
+#if JVET_P1004_REMOVE_BRICKS
+      if( cs.getCURestricted( pos.offset( 0, -1 ), pos, pcSlice->getIndependentSliceIdx(), cs.pps->getTileIdx( pos ), CH_L ) )
+#else
       if( cs.getCURestricted( pos.offset( 0, -1 ), pos, pcSlice->getIndependentSliceIdx(), tileMap.getBrickIdxRsMap( pos ), CH_L ) )
+#endif
       {
         // Top is available, so use it.
         m_CABACWriter->getCtx() = m_entropyCodingSyncContextState;
       }
     }
 
+#if JVET_P1004_REMOVE_BRICKS
+    bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuIdx == 0;
+#else
     bool updateGbiCodingOrder = cs.slice->getSliceType() == B_SLICE && ctuTsAddr == startCtuTsAddr;
+#endif
     if( updateGbiCodingOrder )
     {
       resetGbiCodingOrder(false, cs);
@@ -1912,23 +2121,42 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
     m_CABACWriter->coding_tree_unit( cs, ctuArea, pcPic->m_prevQP, ctuRsAddr );
 
     // store probabilities of first CTU in line into buffer
+#if JVET_P1004_REMOVE_BRICKS
+    if( cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && wavefrontsEnabled )
+#else
     if( ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled )
+#endif
     {
       m_entropyCodingSyncContextState = m_CABACWriter->getCtx();
     }
 
     // terminate the sub-stream, if required (end of slice-segment, end of tile, end of wavefront-CTU-row):
+#if JVET_P1004_REMOVE_BRICKS
+    bool isLastCTUsinSlice = ctuIdx == pcSlice->getNumCtuInSlice()-1;
+    bool isLastCTUinTile  = !isLastCTUsinSlice && cs.pps->getTileIdx( ctuRsAddr ) != cs.pps->getTileIdx( pcSlice->getCtuAddrInSlice( ctuIdx + 1 ) );
+    bool isLastCTUinWPP    = !isLastCTUsinSlice && !isLastCTUinTile && wavefrontsEnabled && cs.pps->ctuIsTileColBd( pcSlice->getCtuAddrInSlice( ctuIdx + 1 ) % cs.pps->getPicWidthInCtu() );
+    if (isLastCTUsinSlice || isLastCTUinTile || isLastCTUinWPP )         // this the the last CTU of the slice, tile, or WPP
+#else
     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
+#endif
     {
+#if JVET_P1004_REMOVE_BRICKS
+      m_CABACWriter->end_of_slice();  // end_of_slice_one_bit, end_of_tile_one_bit, or end_of_subset_one_bit
+#else
       m_CABACWriter->end_of_slice();  //This is actually end_of_brick_one_bit or end_of_subset_one_bit
+#endif
 
       // Byte-alignment in slice_data() when new tile
       pcSubstreams[uiSubStrm].writeByteAlignment();
 
+#if JVET_P1004_REMOVE_BRICKS
+      if (!isLastCTUsinSlice) //Byte alignment only when it is not the last substream in the slice
+#else
       if (isMoreCTUsinSlice) //Byte alignment only when it is not the last substream in the slice
+#endif
       {
         // write sub-stream size
         pcSlice->addSubstreamSize((pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations());
@@ -1950,6 +2178,7 @@ void EncSlice::encodeSlice   ( Picture* pcPic, OutputBitstream* pcSubstreams, ui
 
 }
 
+#if !JVET_P1004_REMOVE_BRICKS
 void EncSlice::calculateBoundingCtuTsAddrForSlice(uint32_t &startCtuTSAddrSlice, uint32_t &boundingCtuTSAddrSlice, bool &haveReachedTileBoundary,
                                                    Picture* pcPic, const int sliceMode, const int sliceArgument)
 {
@@ -2119,6 +2348,7 @@ void EncSlice::xDetermineStartAndBoundingCtuTsAddr  ( uint32_t& startCtuTsAddr,
   startCtuTsAddr = startCtuTsAddrSlice;
   boundingCtuTsAddr = boundingCtuTsAddrSlice;
 }
+#endif
 
 double EncSlice::xGetQPValueAccordingToLambda ( double lambda )
 {
diff --git a/source/Lib/EncoderLib/EncSlice.h b/source/Lib/EncoderLib/EncSlice.h
index 07f157a91..869219471 100644
--- a/source/Lib/EncoderLib/EncSlice.h
+++ b/source/Lib/EncoderLib/EncSlice.h
@@ -104,11 +104,13 @@ public:
 #endif
   void    setUpLambda( Slice* slice, const double dLambda, int iQP );
 
+#if !JVET_P1004_REMOVE_BRICKS
 private:
   void    calculateBoundingCtuTsAddrForSlice( uint32_t &startCtuTSAddrSlice, uint32_t &boundingCtuTSAddrSlice, bool &haveReachedTileBoundary, Picture* pcPic, const int sliceMode, const int sliceArgument );
 
 
 public:
+#endif
 #if ENABLE_QPA
   int                     m_adaptedLumaQP;
 
@@ -137,7 +139,11 @@ public:
 #if ENABLE_WPP_PARALLELISM
   static
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  void    encodeCtus          ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, EncLib* pcEncLib );
+#else
   void    encodeCtus          ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr, EncLib* pcEncLib );
+#endif
   void    checkDisFracMmvd    ( Picture* pcPic, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr );
 #if JVET_P1006_PICTURE_HEADER
   void    setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const Size sizeLuma );
@@ -147,7 +153,9 @@ public:
   void    setSearchRange      ( Slice* pcSlice  );                                  ///< set ME range adaptively
 
   EncCu*  getCUEncoder        ()                    { return m_pcCuEncoder; }                        ///< CU encoder
+#if !JVET_P1004_REMOVE_BRICKS
   void    xDetermineStartAndBoundingCtuTsAddr  ( uint32_t& startCtuTsAddr, uint32_t& boundingCtuTsAddr, Picture* pcPic );
+#endif
   uint32_t    getSliceSegmentIdx  ()                    { return m_uiSliceSegmentIdx;       }
   void    setSliceSegmentIdx  (uint32_t i)              { m_uiSliceSegmentIdx = i;          }
 
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index c667b2810..e997f9d81 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -8259,23 +8259,40 @@ bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, in
     return false;
   }
 
+#if JVET_P1004_REMOVE_BRICKS
+  unsigned curTileIdx = pu.cs->pps->getTileIdx(pu.lumaPos());
+  unsigned refTileIdx = pu.cs->pps->getTileIdx(Position(refLeftX, refTopY));
+#else
   unsigned curTileIdx = pu.cs->picture->brickMap->getBrickIdxRsMap(pu.lumaPos());
   unsigned refTileIdx = pu.cs->picture->brickMap->getBrickIdxRsMap(Position(refLeftX, refTopY));
+#endif
   if (curTileIdx != refTileIdx)
   {
     return false;
   }
+#if JVET_P1004_REMOVE_BRICKS
+  refTileIdx = pu.cs->pps->getTileIdx(Position(refLeftX, refBottomY));
+#else
   refTileIdx = pu.cs->picture->brickMap->getBrickIdxRsMap(Position(refLeftX, refBottomY));
+#endif
   if (curTileIdx != refTileIdx)
   {
     return false;
   }
+#if JVET_P1004_REMOVE_BRICKS
+  refTileIdx = pu.cs->pps->getTileIdx(Position(refRightX, refTopY));
+#else
   refTileIdx = pu.cs->picture->brickMap->getBrickIdxRsMap(Position(refRightX, refTopY));
+#endif
   if (curTileIdx != refTileIdx)
   {
     return false;
   }
+#if JVET_P1004_REMOVE_BRICKS
+  refTileIdx = pu.cs->pps->getTileIdx(Position(refRightX, refBottomY));
+#else
   refTileIdx = pu.cs->picture->brickMap->getBrickIdxRsMap(Position(refRightX, refBottomY));
+#endif
   if (curTileIdx != refTileIdx)
   {
     return false;
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index fa64ac94e..4aaee611a 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -221,7 +221,11 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI,
   }
 
 #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI
+#if JVET_P1004_REMOVE_BRICKS
+  bufferingPeriodSEI->m_bpDecodingUnitHrdParamsPresentFlag = m_pcCfg->getNoPicPartitionFlag() == false;
+#else
   bufferingPeriodSEI->m_bpDecodingUnitHrdParamsPresentFlag = (m_pcCfg->getSliceMode() > 0) || (m_pcCfg->getSliceSegmentMode() > 0);
+#endif
   bufferingPeriodSEI->m_decodingUnitCpbParamsInPicTimingSeiFlag = !m_pcCfg->getDecodingUnitInfoSEIEnabled();
 #endif
 
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 8ba07f50c..d3d0f8f36 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -242,6 +242,74 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS )
       WRITE_CODE( pcPPS->getSubPicId(picIdx), pcPPS->getSubPicIdLen( ), "pps_subpic_id[i]" );
     }
   }
+#endif
+#if JVET_P1004_REMOVE_BRICKS
+
+  WRITE_FLAG( pcPPS->getNoPicPartitionFlag( ) ? 1 : 0, "no_pic_partition_flag" );
+  if( !pcPPS->getNoPicPartitionFlag() )
+  {
+    int colIdx, rowIdx;
+
+    // CTU size - required to match size in SPS
+    WRITE_CODE( pcPPS->getLog2CtuSize() - 5, 2, "log2_pps_ctu_size_minus5" );
+    
+    // number of explicit tile columns/rows
+    WRITE_UVLC( pcPPS->getNumExpTileColumns() - 1, "num_exp_tile_columns_minus1" );
+    WRITE_UVLC( pcPPS->getNumExpTileRows() - 1,    "num_exp_tile_rows_minus1" );
+        
+    // tile sizes
+    for( colIdx = 0; colIdx < pcPPS->getNumExpTileColumns(); colIdx++ )
+    {
+      WRITE_UVLC( pcPPS->getTileColumnWidth( colIdx ) - 1, "tile_column_width_minus1[i]" );
+    }
+    for( rowIdx = 0; rowIdx < pcPPS->getNumExpTileRows(); rowIdx++ )
+    {
+      WRITE_UVLC( pcPPS->getTileRowHeight( rowIdx ) - 1, "tile_row_height_minus1[i]" );
+    }
+     
+    // rectangular slice signalling
+    WRITE_FLAG( pcPPS->getRectSliceFlag( ) ? 1 : 0, "rect_slice_flag");
+    if( pcPPS->getRectSliceFlag() ) 
+    {      
+      WRITE_UVLC( pcPPS->getNumSlicesInPic( ) - 1, "num_slices_in_pic_minus1" );
+      WRITE_FLAG( pcPPS->getTileIdxDeltaPresentFlag( ) ? 1 : 0, "tile_idx_delta_present_flag");
+      
+      // write rectangular slice parameters
+      for( int i = 0; i < pcPPS->getNumSlicesInPic()-1; i++ )
+      {
+        // complete tiles within a single slice
+        WRITE_UVLC( pcPPS->getSliceWidthInTiles( i ) - 1,  "slice_width_in_tiles_minus1[i]" );
+        WRITE_UVLC( pcPPS->getSliceHeightInTiles( i ) - 1, "slice_height_in_tiles_minus1[i]" );
+
+        // multiple slices within a single tile special case
+        if( pcPPS->getSliceWidthInTiles( i ) == 1 && pcPPS->getSliceHeightInTiles( i ) == 1 ) 
+        {
+          WRITE_UVLC( pcPPS->getNumSlicesInTile( i ) - 1,  "num_slices_in_tile_minus1[i]" );
+          uint32_t numSlicesInTile = pcPPS->getNumSlicesInTile( i );
+          for( int j = 0; j < numSlicesInTile-1; j++ )
+          {
+            WRITE_UVLC( pcPPS->getSliceHeightInCtu( i ) - 1,  "slice_height_in_ctu_minus1[i]" );
+            i++;
+          }
+        }
+
+        // tile index offset to start of next slice
+        if( i < pcPPS->getNumSlicesInPic()-1 ) 
+        {
+          if( pcPPS->getTileIdxDeltaPresentFlag() ) 
+          {
+            int32_t  tileIdxDelta = pcPPS->getSliceTileIdx( i + 1 ) - pcPPS->getSliceTileIdx( i );
+            WRITE_SVLC( tileIdxDelta,  "tile_idx_delta[i]" );
+          }
+        }
+      }
+    }
+
+    // loop filtering across slice/tile controls
+    WRITE_FLAG( pcPPS->getLoopFilterAcrossTilesEnabledFlag(), "loop_filter_across_tiles_enabled_flag");
+    WRITE_FLAG( pcPPS->getLoopFilterAcrossSlicesEnabledFlag(), "loop_filter_across_slices_enabled_flag");
+  }
+
 #endif
   WRITE_FLAG( pcPPS->getCabacInitPresentFlag() ? 1 : 0,   "cabac_init_present_flag" );
   WRITE_UVLC( pcPPS->getNumRefIdxL0DefaultActive()-1,     "num_ref_idx_l0_default_active_minus1");
@@ -323,6 +391,7 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS )
   WRITE_FLAG( pcPPS->getWPBiPred() ? 1 : 0, "weighted_bipred_flag" );  // Use of Weighting Bi-Prediction (B_SLICE)
   WRITE_FLAG( pcPPS->getTransquantBypassEnabledFlag()  ? 1 : 0, "transquant_bypass_enabled_flag" );
 
+#if !JVET_P1004_REMOVE_BRICKS
   WRITE_FLAG( pcPPS->getSingleTileInPicFlag() ? 1 : 0, "single_tile_in_pic_flag" );
   if (!pcPPS->getSingleTileInPicFlag())
   {
@@ -439,6 +508,7 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS )
   }
 
 
+#endif
   WRITE_FLAG( pcPPS->getEntropyCodingSyncEnabledFlag() ? 1 : 0, "entropy_coding_sync_enabled_flag" );
 
   WRITE_FLAG( pcPPS->getDeblockingFilterControlPresentFlag()?1 : 0,       "deblocking_filter_control_present_flag");
@@ -1803,6 +1873,30 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #if !JVET_P1006_PICTURE_HEADER
   WRITE_UVLC( pcSlice->getPPS()->getPPSId(), "slice_pic_parameter_set_id" );
 #endif
+#if JVET_P1004_REMOVE_BRICKS
+  // raster scan slices
+  if( pcSlice->getPPS()->getRectSliceFlag() == 0 ) 
+  {
+    // slice address is the raster scan tile index of first tile in slice
+    if( pcSlice->getPPS()->getNumTiles() > 1 ) 
+    {      
+      int bitsSliceAddress = ceilLog2(pcSlice->getPPS()->getNumTiles());
+      WRITE_CODE( pcSlice->getSliceID(), bitsSliceAddress, "slice_address");
+      WRITE_UVLC( pcSlice->getNumTilesInSlice() - 1, "num_tiles_in_slice_minus1");
+    }
+  }
+  // rectangular slices
+  else 
+  {
+    // slice address is the index of the slice within the current sub-picture
+    if( pcSlice->getPPS()->getNumSlicesInPic() > 1 ) 
+    {
+      int bitsSliceAddress = ceilLog2(pcSlice->getPPS()->getNumSlicesInPic());  // change to NumSlicesInSubPic when available
+      WRITE_CODE( pcSlice->getSliceID(), bitsSliceAddress, "slice_address");
+    }
+  }
+
+#else
   int bitsSliceAddress = 1;
   if (!pcSlice->getPPS()->getRectSliceFlag())
   {
@@ -1841,6 +1935,7 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
     WRITE_UVLC(pcSlice->getSliceNumBricks() - 1, "num_bricks_in_slice_minus1");
   }
 
+#endif
 #if !JVET_P1006_PICTURE_HEADER
     WRITE_FLAG(pcSlice->getNonRefPictFlag() ? 1 : 0, "non_reference_picture_flag");
 #endif
@@ -2444,7 +2539,12 @@ void  HLSWriter::codeProfileTierLevel    ( const ProfileTierLevel* ptl, int maxN
 */
 void  HLSWriter::codeTilesWPPEntryPoint( Slice* pSlice )
 {
+#if JVET_P1004_REMOVE_BRICKS
+  pSlice->setNumEntryPoints( pSlice->getPPS() );
+  if( pSlice->getNumEntryPoints() == 0 )
+#else
   if (pSlice->getPPS()->getSingleTileInPicFlag() && !pSlice->getPPS()->getEntropyCodingSyncEnabledFlag())
+#endif
   {
     return;
   }
@@ -2466,8 +2566,10 @@ void  HLSWriter::codeTilesWPPEntryPoint( Slice* pSlice )
     CHECK(offsetLenMinus1 + 1 >= 32, "Invalid offset length minus 1");
   }
 
+#if !JVET_P1004_REMOVE_BRICKS
 #if !JVET_O0145_ENTRYPOINT_SIGNALLING
   WRITE_UVLC(pSlice->getNumberOfSubstreamSizes(), "num_entry_point_offsets");
+#endif
 #endif
   if (pSlice->getNumberOfSubstreamSizes()>0)
   {
-- 
GitLab