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