Commit 84a593af authored by Hendry's avatar Hendry Committed by Karsten Suehring

- 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
parent 04d626a0
......@@ -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} &
......
......@@ -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 );
......
......@@ -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))
......
......@@ -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;
......
......@@ -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++)
{
......
......@@ -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
......
......@@ -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; }
......
......@@ -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
......
......@@ -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
......
......@@ -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
}
}
......
......@@ -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
{