From ba1e2bc706911db05cf651988c2de582bc9a4a97 Mon Sep 17 00:00:00 2001 From: biaowang <biao.wang@huawei.com> Date: Fri, 31 Jan 2020 22:31:28 +0100 Subject: [PATCH 1/5] JVET-O1143: motion and in-loop filter low-level operations adaptation when subpic boundaries are treated as pic boundaries --- .../subpicture_4Slice2VerSubPic.cfg | 4 +- source/App/DecoderApp/DecApp.cpp | 2 +- source/App/DecoderApp/DecAppCfg.cpp | 2 +- source/App/DecoderApp/DecAppCfg.h | 2 +- source/Lib/CommonLib/AdaptiveLoopFilter.cpp | 28 +- source/Lib/CommonLib/LoopFilter.cpp | 57 +++- source/Lib/CommonLib/Mv.cpp | 10 + source/Lib/CommonLib/Picture.cpp | 300 ++++++++++++++++++ source/Lib/CommonLib/Picture.h | 15 + source/Lib/CommonLib/SampleAdaptiveOffset.cpp | 16 + source/Lib/CommonLib/Slice.cpp | 26 +- source/Lib/CommonLib/Slice.h | 27 ++ source/Lib/CommonLib/TypeDef.h | 4 +- source/Lib/CommonLib/UnitTools.cpp | 73 +++++ source/Lib/CommonLib/UnitTools.h | 3 + source/Lib/DecoderLib/DecLib.cpp | 3 +- source/Lib/DecoderLib/DecLib.h | 2 +- source/Lib/DecoderLib/DecSlice.cpp | 49 +++ .../EncoderLib/EncSampleAdaptiveOffset.cpp | 10 + source/Lib/EncoderLib/EncSlice.cpp | 54 ++++ source/Lib/EncoderLib/InterSearch.cpp | 10 + 21 files changed, 676 insertions(+), 21 deletions(-) diff --git a/cfg/nonCTC-SliceConfigExamples/subpicture_4Slice2VerSubPic.cfg b/cfg/nonCTC-SliceConfigExamples/subpicture_4Slice2VerSubPic.cfg index 9079e764fa..abb87dbf7c 100644 --- a/cfg/nonCTC-SliceConfigExamples/subpicture_4Slice2VerSubPic.cfg +++ b/cfg/nonCTC-SliceConfigExamples/subpicture_4Slice2VerSubPic.cfg @@ -34,5 +34,5 @@ TileRowHeightArray : 2 # Tile row heights in un RasterScanSlices : 0 # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan) RectSliceFixedWidth : 1 # Fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead) RectSliceFixedHeight : 1 # Fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead) -DisableLoopFilterAcrossTiles : 1 # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries 1: do not filter across tile boundaries) -DisableLoopFilterAcrossSlices : 1 # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries) +DisableLoopFilterAcrossTiles : 0 # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries 1: do not filter across tile boundaries) +DisableLoopFilterAcrossSlices : 0 # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries) diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index b6584f0754..704a9c3d84 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -681,7 +681,7 @@ void DecApp::xCreateDecLib() std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout; m_cDecLib.setDecodedSEIMessageOutputStream(&os); } -#if SUBPIC_DECCHECK +#if JVET_O1143_SUBPIC_DECCHECK m_cDecLib.m_targetSubPicIdx = this->m_targetSubPicIdx; #endif m_cDecLib.initScalingList(); diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp index 310251e87e..c3c9d55a27 100644 --- a/source/App/DecoderApp/DecAppCfg.cpp +++ b/source/App/DecoderApp/DecAppCfg.cpp @@ -113,7 +113,7 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] ) "\t3: enable bit and tool statistic\n") #endif ("MCTSCheck", m_mctsCheck, false, "If enabled, the decoder checks for violations of mc_exact_sample_value_match_flag in Temporal MCTS ") -#if SUBPIC_DECCHECK +#if JVET_O1143_SUBPIC_DECCHECK ("targetSubPicIdx", m_targetSubPicIdx, 0, "Specify which subpicture shall be written to output, using subpic index\n" ) #endif ( "UpscaledOutput", m_upscaledOutput, 0, "Upscaled output for RPR" ) diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h index cc45bfdd88..601504dc0c 100644 --- a/source/App/DecoderApp/DecAppCfg.h +++ b/source/App/DecoderApp/DecAppCfg.h @@ -76,7 +76,7 @@ protected: bool m_mctsCheck; int m_upscaledOutput; ////< Output upscaled (2), decoded but in full resolution buffer (1) or decoded cropped (0, default) picture for RPR. -#if SUBPIC_DECCHECK +#if JVET_O1143_SUBPIC_DECCHECK int m_targetSubPicIdx; ///< Specify which subpicture shall be write to output, using subpicture index #endif public: diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp index 4d862ff950..04a4a5019c 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp @@ -121,13 +121,21 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs int ctuSize = slice.getSPS()->getCTUSize(); const Position currCtuPos(xPos, yPos); const CodingUnit *currCtu = cs.getCU(currCtuPos, CHANNEL_TYPE_LUMA); +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = slice.getPPS()->getSubPicFromPos(currCtuPos); + bool loopFilterAcrossSubPicEnabledFlag = curSubPic.getloopFilterAcrossEnabledFlag(); +#endif //top if (yPos >= ctuSize && clipTop == false) { const Position prevCtuPos(xPos, yPos - ctuSize); const CodingUnit *prevCtu = cs.getCU(prevCtuPos, CHANNEL_TYPE_LUMA); if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu)) || - (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *prevCtu))) + (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *prevCtu)) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + || (!loopFilterAcrossSubPicEnabledFlag && !CU::isSameSubPic(*currCtu, *prevCtu)) +#endif + ) { clipTop = true; } @@ -139,7 +147,11 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs const Position nextCtuPos(xPos, yPos + ctuSize); const CodingUnit *nextCtu = cs.getCU(nextCtuPos, CHANNEL_TYPE_LUMA); if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu)) || - (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *nextCtu))) + (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *nextCtu)) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + || (!loopFilterAcrossSubPicEnabledFlag && !CU::isSameSubPic(*currCtu, *nextCtu)) +#endif + ) { clipBottom = true; } @@ -151,7 +163,11 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs const Position prevCtuPos(xPos - ctuSize, yPos); const CodingUnit *prevCtu = cs.getCU(prevCtuPos, CHANNEL_TYPE_LUMA); if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *prevCtu)) || - (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *prevCtu))) + (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *prevCtu)) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + || (!loopFilterAcrossSubPicEnabledFlag && !CU::isSameSubPic(*currCtu, *prevCtu)) +#endif + ) { clipLeft = true; } @@ -163,7 +179,11 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs const Position nextCtuPos(xPos + ctuSize, yPos); const CodingUnit *nextCtu = cs.getCU(nextCtuPos, CHANNEL_TYPE_LUMA); if ((!pps->getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice(*currCtu, *nextCtu)) || - (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *nextCtu))) + (!pps->getLoopFilterAcrossTilesEnabledFlag() && !CU::isSameTile(*currCtu, *nextCtu)) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + || (!loopFilterAcrossSubPicEnabledFlag && !CU::isSameSubPic(*currCtu, *nextCtu)) +#endif + ) { clipRight = true; } diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index a9e3a60c8e..7541b5de90 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -82,14 +82,30 @@ inline static uint32_t getRasterIdx(const Position& pos, const PreCalcValues& pc // utility functions // ==================================================================================================================== -static bool isAvailableLeft( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction ) +static bool isAvailableLeft( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , const bool bEnforceSubPicRestriction +#endif +) { - return ( ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) ); + return ( ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2)) +#endif + ); } -static bool isAvailableAbove( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction ) +static bool isAvailableAbove( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , const bool bEnforceSubPicRestriction +#endif +) { - return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ); + return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2)) +#endif + ; } @@ -680,8 +696,17 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu ) const Position& pos = cu.blocks[cu.chType].pos(); m_stLFCUParam.internalEdge = true; - m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() ); - m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() ); + + m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() +#endif + ); + m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() +#endif + ); } unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const Position& localPos ) const @@ -937,7 +962,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg // Derive neighboring PU index if (edgeDir == EDGE_VER) { - if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag())) + if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() +#endif + )) { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; @@ -945,7 +974,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg } else // (iDir == EDGE_HOR) { - if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag())) + if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() +#endif + )) { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; @@ -1205,11 +1238,19 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed if (edgeDir == EDGE_VER) { +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + CHECK(!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag()), "Neighbour not available"); +#else CHECK(!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available"); +#endif } else // (iDir == EDGE_HOR) { +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + CHECK(!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag()), "Neighbour not available"); +#else CHECK(!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()), "Neighbour not available"); +#endif } bPartPNoFilter = bPartQNoFilter = false; diff --git a/source/Lib/CommonLib/Mv.cpp b/source/Lib/CommonLib/Mv.cpp index 386d087468..598a26433c 100644 --- a/source/Lib/CommonLib/Mv.cpp +++ b/source/Lib/CommonLib/Mv.cpp @@ -66,7 +66,17 @@ void clipMv( Mv& rcMv, const Position& pos, const struct Size& size, const SPS& int iVerMax = ( pps.getPicHeightInLumaSamples() + iOffset - (int)pos.y - 1 ) << iMvShift; int iVerMin = ( -( int ) sps.getMaxCUHeight() - iOffset - ( int ) pos.y + 1 ) << iMvShift; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = pps.getSubPicFromPos(pos); + if (curSubPic.getTreatedAsPicFlag()) + { + iHorMax = (curSubPic.getSubPicWidthInLumaSample() + iOffset - (int)pos.x - 1 ) << iMvShift; + iHorMin = (-(int)sps.getMaxCUWidth() - iOffset - ((int)pos.x - curSubPic.getSubPicLeft()) + 1) << iMvShift; + iVerMax = (curSubPic.getSubPicHeightInLumaSample()+ iOffset - (int)pos.y - 1) << iMvShift; + iVerMin = (-(int)sps.getMaxCUHeight() - iOffset - ((int)pos.y - curSubPic.getSubPicTop()) + 1) << iMvShift; + } +#endif rcMv.setHor( std::min( iHorMax, std::max( iHorMin, rcMv.getHor() ) ) ); rcMv.setVer( std::min( iVerMax, std::max( iVerMin, rcMv.getVer() ) ) ); } diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 2821a7ef36..f69d5bd64b 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -173,6 +173,9 @@ int Scheduler::getNumPicInstances() const Picture::Picture() { cs = nullptr; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + m_bIsSubPicBorderSaved = false; +#endif m_bIsBorderExtended = false; usedByCurr = false; longTerm = false; @@ -734,6 +737,303 @@ void Picture::rescalePicture( const std::pair<int, int> scalingRatio, } } +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY +void Picture::saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) +{ + // 1.0 check border was extended + if (getSubPicSaved()) + { + return; + } + + // 1.1 set up margin for back up memory allocation + int xMargin = margin >> getComponentScaleX(COMPONENT_Y, cs->area.chromaFormat); + int yMargin = margin >> getComponentScaleY(COMPONENT_Y, cs->area.chromaFormat); + + // 1.2 measure the size of back up memory + Area areaAboveBelow(0, 0, subPicWidth + 2 * xMargin, yMargin); + Area areaLeftRight(0, 0, xMargin, subPicHeight); + UnitArea unitAreaAboveBelow(cs->area.chromaFormat, areaAboveBelow); + UnitArea unitAreaLeftRight(cs->area.chromaFormat, areaLeftRight); + + // 1.3 create back up memory + m_bufSubPicAbove.create(unitAreaAboveBelow); + m_bufSubPicBelow.create(unitAreaAboveBelow); + m_bufSubPicLeft.create(unitAreaLeftRight); + m_bufSubPicRight.create(unitAreaLeftRight); + + Pel *ss0; + Pel *ss1; + Pel *dd0; + Pel *dd1; + int copylen; + + for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) + { + ComponentID compID = ComponentID(comp); + + // 2.1 measure the margin for each component + int xmargin = margin >> getComponentScaleX(compID, cs->area.chromaFormat); + int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.2 calculate the origin of the subpicture + int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.3 calculate the width/height of the subPic + int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + + + // 3.1.1 set reconstructed picture + PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); + Pel *siTxt = s.bufAt(tx0, ty0); + Pel* si = siTxt; + + // 3.2.1 set back up buffer for left + PelBuf d0 = m_bufSubPicLeft.getBuf(compID); + Pel *diTxt0 = d0.bufAt(0, 0); + Pel *di0 = diTxt0; + + // 3.2.2 set back up buffer for right + PelBuf d1 = m_bufSubPicRight.getBuf(compID); + Pel *diTxt1 = d1.bufAt(0, 0); + Pel *di1 = diTxt1; + + + // 3.2.3 copy to recon picture to back up buffer + ss0 = si - xmargin; + ss1 = si + tww; + dd0 = di0; + dd1 = di1; + copylen = sizeof(Pel) * xmargin; + for (int y = 0; y < thh; y++) + { + ::memcpy(dd0, ss0, copylen); + ::memcpy(dd1, ss1, copylen); + ss0 += s.stride; + ss1 += s.stride; + dd0 += d0.stride; + dd1 += d1.stride; + } + + + // 3.3.1 set back up buffer for above + d0 = m_bufSubPicAbove.getBuf(compID); + diTxt0 = d0.bufAt(0, 0); + di0 = diTxt0; + + // 3.3.2 set back up buffer for below + d1 = m_bufSubPicBelow.getBuf(compID); + diTxt1 = d1.bufAt(0, 0); + di1 = diTxt1; + + // 3.3.3 copy to recon picture to back up buffer + ss0 = si - xmargin - ymargin * s.stride; + ss1 = si - xmargin + thh * s.stride; + dd0 = di0; + dd1 = di1; + copylen = sizeof(Pel) * (2 * xmargin + tww); + for (int y = 0; y < ymargin; y++) + { + ::memcpy(dd0, ss0, copylen); + ::memcpy(dd1, ss1, copylen); + ss0 += s.stride; + ss1 += s.stride; + dd0 += d0.stride; + dd1 += d1.stride; + } + } +} + +void Picture::extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) +{ + // 1.0 check border was extended + if (getSubPicSaved()) + { + return; + } + + Pel *ss0 = 0; + Pel *ss1 = 0; + Pel *dd0 = 0; + Pel *dd1 = 0; + int copylen; + + for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) + { + ComponentID compID = ComponentID(comp); + + // 2.1 measure the margin for each component + int xmargin = margin >> getComponentScaleX(compID, cs->area.chromaFormat); + int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.2 calculate the origin of the Subpicture + int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.3 calculate the width/height of the Subpicture + int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 3.1 set reconstructed picture + PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); + Pel *siTxt = s.bufAt(tx0, ty0); + Pel* si = siTxt; + + // 4.1 apply padding for left and right + { + Pel *xx0, *xx1; + ss0 = si - xmargin; + ss1 = si + tww; + xx0 = si + 0; + xx1 = si + tww - 1; + + for (int y = 0; y < thh; y++) + { + dd0 = ss0; + dd1 = ss1; + for (int x = 0; x < xmargin; x++) + { + *dd0++ = *xx0; + *dd1++ = *xx1; + } + + ss0 += s.stride; + ss1 += s.stride; + xx0 += s.stride; + xx1 += s.stride; + } + } + + // 4.2 apply padding on bottom + // si is now the (0, SubpictureHeight) (bottom left of image within bigger picture + si += s.stride * (thh - 1) - xmargin; + + // si is now the (-marginX, SubpictureHeight-1) + ss0 = si + s.stride; + copylen = sizeof(Pel)*(tww + (xmargin << 1)); + for (int y = 0; y < ymargin; y++) + { + ::memcpy(ss0, si, copylen); + ss0 += s.stride; + } + + // 4.3 apply padding for top + // si is still (-marginX, SubpictureHeight-1) + si -= ((thh - 1) * s.stride); + + // si is now (-marginX, 0) + ss0 = si - s.stride; + copylen = sizeof(Pel)*(tww + (xmargin << 1)); + for (int y = 0; y < ymargin; y++) + { + ::memcpy(ss0, si, copylen); + ss0 -= s.stride; + } + } // end of for +} + +void Picture::restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) +{ + // 1.0 check border was extended + if (!getSubPicSaved()) + { + return; + } + + Pel *ss0; + Pel *ss1; + Pel *dd0; + Pel *dd1; + int copylen; + + for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) + { + ComponentID compID = ComponentID(comp); + + // 2.1 measure the margin for each component + int xmargin = margin >> getComponentScaleX(compID, cs->area.chromaFormat); + int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.2 calculate the origin of the subpicture + int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 2.3 calculate the width/height of the subpicture + int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + + // 3.1 set reconstructed picture + PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); + Pel *siTxt = s.bufAt(tx0, ty0); + Pel* si = siTxt; + + + // 4.2.1 copy from back up buffer to recon picture + PelBuf d0 = m_bufSubPicLeft.getBuf(compID); + Pel *diTxt0 = d0.bufAt(0, 0); + Pel *di0 = diTxt0; + + // 4.2.2 set back up buffer for right + PelBuf d1 = m_bufSubPicRight.getBuf(compID); + Pel *diTxt1 = d1.bufAt(0, 0); + Pel *di1 = diTxt1; + + // 4.2.3 copy to recon picture to back up buffer + ss0 = si - xmargin; + ss1 = si + tww; + dd0 = di0; + dd1 = di1; + copylen = sizeof(Pel) * xmargin; + + for (int y = 0; y < thh; y++) + { + ::memcpy(ss0, dd0, copylen); + ::memcpy(ss1, dd1, copylen); + ss0 += s.stride; + ss1 += s.stride; + dd0 += d0.stride; + dd1 += d1.stride; + } + + + // 4.3.1 copy from back up buffer to recon picture + d0 = m_bufSubPicAbove.getBuf(compID); + diTxt0 = d0.bufAt(0, 0); + di0 = diTxt0; + + // 4.3.2 set back up buffer for below + d1 = m_bufSubPicBelow.getBuf(compID); + diTxt1 = d1.bufAt(0, 0); + di1 = diTxt1; + + // 4.3.3 copy to recon picture to back up buffer + ss0 = si - xmargin - ymargin * s.stride; + ss1 = si - xmargin + thh * s.stride; + dd0 = di0; + dd1 = di1; + copylen = sizeof(Pel) * (2 * xmargin + tww); + + for (int y = 0; y < ymargin; y++) + { + ::memcpy(ss0, dd0, copylen); + ::memcpy(ss1, dd1, copylen); + ss0 += s.stride; + ss1 += s.stride; + dd0 += d0.stride; + dd1 += d1.stride; + } + } + + // 5.0 destroy the back up memory + m_bufSubPicAbove.destroy(); + m_bufSubPicBelow.destroy(); + m_bufSubPicLeft.destroy(); + m_bufSubPicRight.destroy(); +} +#endif + void Picture::extendPicBorder() { if ( m_bIsBorderExtended ) diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index 1c259541cd..b1d8ca6f45 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -172,6 +172,21 @@ private: Window m_scalingWindow; public: +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + bool m_bIsSubPicBorderSaved; + + PelStorage m_bufSubPicAbove; + PelStorage m_bufSubPicBelow; + PelStorage m_bufSubPicLeft; + PelStorage m_bufSubPicRight; + + void saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight); + void extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight); + void restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight); + + bool getSubPicSaved() { return m_bIsSubPicBorderSaved; } + void setSubPicSaved(bool bVal) { m_bIsSubPicBorderSaved = bVal; } +#endif bool m_bIsBorderExtended; bool referenced; bool reconstructed; diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp index 0953b569a4..a910f8a468 100644 --- a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp +++ b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp @@ -726,6 +726,22 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& isBelowLeftAvail = (!isBelowLeftAvail) ? false : CU::isSameTile(*cuCurr, *cuBelowLeft); isBelowRightAvail = (!isBelowRightAvail) ? false : CU::isSameTile(*cuCurr, *cuBelowRight); } + +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + // check cross subpic flags + SubPic curSubPic = cs.pps->getSubPicFromCU(*cuCurr); + if (!curSubPic.getloopFilterAcrossEnabledFlag()) + { + isLeftAvail = (!isLeftAvail) ? false : CU::isSameSubPic(*cuCurr, *cuLeft); + isAboveAvail = (!isAboveAvail) ? false : CU::isSameSubPic(*cuCurr, *cuAbove); + isRightAvail = (!isRightAvail) ? false : CU::isSameSubPic(*cuCurr, *cuRight); + isBelowAvail = (!isBelowAvail) ? false : CU::isSameSubPic(*cuCurr, *cuBelow); + isAboveLeftAvail = (!isAboveLeftAvail) ? false : CU::isSameSubPic(*cuCurr, *cuAboveLeft); + isAboveRightAvail = (!isAboveRightAvail) ? false : CU::isSameSubPic(*cuCurr, *cuAboveRight); + isBelowLeftAvail = (!isBelowLeftAvail) ? false : CU::isSameSubPic(*cuCurr, *cuBelowLeft); + isBelowRightAvail = (!isBelowRightAvail) ? false : CU::isSameSubPic(*cuCurr, *cuBelowRight); + } +#endif } bool SampleAdaptiveOffset::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader ) diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index df9936f98b..a2b6fb6d4a 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -2378,6 +2378,7 @@ void PPS::initSubPic(const SPS &sps) m_subPics.resize(getNumSubPics()); for (int i=0; i< getNumSubPics(); i++) { + m_subPics[i].setSubPicIdx(i); m_subPics[i].setSubPicCtuTopLeftX(sps.getSubPicCtuTopLeftX(i)); m_subPics[i].setSubPicCtuTopLeftY(sps.getSubPicCtuTopLeftY(i)); m_subPics[i].setSubPicWidthInCTUs(sps.getSubPicWidth(i)); @@ -2394,10 +2395,15 @@ void PPS::initSubPic(const SPS &sps) uint32_t right = std::min(m_picWidthInLumaSamples - 1, (sps.getSubPicCtuTopLeftX(i) + sps.getSubPicWidth(i)) * m_ctuSize - 1); m_subPics[i].setSubPicRight(right); + m_subPics[i].setSubPicWidthInLumaSample(right - left + 1); + uint32_t top = sps.getSubPicCtuTopLeftY(i) * m_ctuSize; m_subPics[i].setSubPicTop(top); uint32_t bottom = std::min(m_picHeightInLumaSamples - 1, (sps.getSubPicCtuTopLeftY(i) + sps.getSubPicHeight(i)) * m_ctuSize - 1); + + m_subPics[i].setSubPicHeightInLumaSample(bottom - top + 1); + m_subPics[i].setSubPicBottom(bottom); for (int j = 0; j < m_numSlicesInPic; j++) @@ -2410,7 +2416,7 @@ void PPS::initSubPic(const SPS &sps) ctu_y >= sps.getSubPicCtuTopLeftY(i) && ctu_y < (sps.getSubPicCtuTopLeftY(i) + sps.getSubPicHeight(i))) { - // slice in the subpicture + // add ctus in a slice to the subpicture it belongs to m_subPics[i].addCTUsToSubPic(m_sliceMap[j].getCtuAddrList()); } } @@ -2418,6 +2424,24 @@ void PPS::initSubPic(const SPS &sps) m_subPics[i].setloopFilterAcrossEnabledFlag(sps.getLoopFilterAcrossSubpicEnabledFlag(i)); } } + +SubPic PPS::getSubPicFromPos(const Position& pos) const +{ + for (int i = 0; i< m_numSubPics; i++) + { + if (m_subPics[i].isContainingPos(pos)) + { + return m_subPics[i]; + } + } + return m_subPics[0]; +} + +SubPic PPS::getSubPicFromCU(const CodingUnit& cu) const +{ + const Position lumaPos = cu.Y().valid() ? cu.Y().pos() : recalcPosition(cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].pos()); + return getSubPicFromPos(lumaPos); +} #endif void PPS::initRasterSliceMap( std::vector<uint32_t> numTilesInSlice ) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 4fb4fb24d5..fc1f1aa271 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -689,11 +689,14 @@ class SubPic { private: uint32_t m_subPicID; //!< ID of subpicture + uint32_t m_subPicIdx; //!< Index of subpicture uint32_t m_numCTUsInSubPic; //!< number of CTUs contained in this sub-picture uint32_t m_subPicCtuTopLeftX; //!< horizontal position of top left CTU of the subpicture in unit of CTU uint32_t m_subPicCtuTopLeftY; //!< vertical position of top left CTU of the subpicture in unit of CTU uint32_t m_subPicWidth; //!< the width of subpicture in units of CTU uint32_t m_subPicHeight; //!< the height of subpicture in units of CTU + uint32_t m_subPicWidthInLumaSample; //!< the width of subpicture in units of luma sample + uint32_t m_subPicHeightInLumaSample; //!< the height of subpicture in units of luma sample uint32_t m_firstCtuInSubPic; //!< the raster scan index of the first CTU in a subpicture uint32_t m_lastCtuInSubPic; //!< the raster scan index of the last CTU in a subpicture uint32_t m_subPicLeft; //!< the position of left boundary @@ -711,6 +714,8 @@ public: void setSubPicID (uint32_t u) { m_subPicID = u; } uint32_t getSubPicID () const { return m_subPicID; } + void setSubPicIdx (uint32_t u) { m_subPicIdx = u; } + uint32_t getSubPicIdx () const { return m_subPicIdx; } void setNumCTUsInSubPic (uint32_t u) { m_numCTUsInSubPic = u; } uint32_t getNumCTUsInSubPic () const { return m_numCTUsInSubPic; } void setSubPicCtuTopLeftX (uint32_t u) { m_subPicCtuTopLeftX = u; } @@ -734,16 +739,32 @@ public: void setSubPicBottom (uint32_t u) { m_subPicBottom = u; } uint32_t getSubPicBottom () const { return m_subPicBottom; } + void setSubPicWidthInLumaSample (uint32_t u) { m_subPicWidthInLumaSample = u; } + uint32_t getSubPicWidthInLumaSample() const { return m_subPicWidthInLumaSample; } + void setSubPicHeightInLumaSample(uint32_t u) { m_subPicHeightInLumaSample = u; } + uint32_t getSubPicHeightInLumaSample() const { return m_subPicHeightInLumaSample; } + std::vector<uint32_t> getCtuAddrList () const { return m_ctuAddrInSubPic; } void addCTUsToSubPic(std::vector<uint32_t> ctuAddrInSlice) { for (auto ctu:ctuAddrInSlice) m_ctuAddrInSubPic.push_back(ctu); } + bool isContainingPos(const Position& pos) const + { + if (pos.x >= m_subPicLeft && pos.x <= m_subPicRight && + pos.y >= m_subPicTop && pos.y <= m_subPicBottom) + return true; + else + return false; + } void setTreatedAsPicFlag (bool u) { m_treatedAsPicFlag = u; } bool getTreatedAsPicFlag () const { return m_treatedAsPicFlag; } void setloopFilterAcrossEnabledFlag(bool u) { m_loopFilterAcrossSubPicEnabledFlag = u; } bool getloopFilterAcrossEnabledFlag() const { return m_loopFilterAcrossSubPicEnabledFlag; } + + bool isFirstCTUinSubPic(uint32_t ctuAddr) { return ctuAddr == m_firstCtuInSubPic; } + bool isLastCTUinSubPic(uint32_t ctuAddr) { return ctuAddr == m_lastCtuInSubPic; } }; #endif class DPS @@ -1814,6 +1835,8 @@ public: #if JVET_O1143_SUBPIC_BOUNDARY std::vector<SubPic> getSubPics() const {return m_subPics; }; void initSubPic(const SPS &sps); + SubPic getSubPicFromPos(const Position& pos) const; + SubPic getSubPicFromCU (const CodingUnit& cu) const; #endif void initRasterSliceMap( std::vector<uint32_t> sizes ); void checkSliceMap(); @@ -2427,7 +2450,11 @@ public: int getNumRefIdx( RefPicList e ) const { return m_aiNumRefIdx[e]; } Picture* getPic() { return m_pcPic; } const Picture* getPic() const { return m_pcPic; } +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + Picture* getRefPic( RefPicList e, int iRefIdx) const { return m_apcRefPicList[e][iRefIdx]; } +#else const Picture* getRefPic( RefPicList e, int iRefIdx) const { return m_apcRefPicList[e][iRefIdx]; } +#endif int getRefPOC( RefPicList e, int iRefIdx) const { return m_aiRefPOCList[e][iRefIdx]; } int getDepth() const { return m_iDepth; } bool getColFromL0Flag() const { return m_colFromL0Flag; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 7ad29c25d9..82b938fe38 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -92,7 +92,9 @@ #define JVET_O1143_SUBPIC_BOUNDARY 1 // treat subpicture boundary as piucture boundary #if JVET_O1143_SUBPIC_BOUNDARY -#define SUBPIC_DECCHECK 0 +#define JVET_O1143_SUBPIC_DECCHECK 1 +#define JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY 1 +#define JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY 1 #endif #define JVET_Q0495_NLALF_CLIP_CLEANUP 1 // JVET-Q0495: Cleanup of clipping table for NL-ALF diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index ece0dcac64..ce845522c6 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -172,6 +172,13 @@ bool CU::isSameSliceAndTile(const CodingUnit& cu, const CodingUnit& cu2) return ( cu.slice->getIndependentSliceIdx() == cu2.slice->getIndependentSliceIdx() ) && ( cu.tileIdx == cu2.tileIdx ); } +#if JVET_O1143_SUBPIC_BOUNDARY +bool CU::isSameSubPic(const CodingUnit& cu, const CodingUnit& cu2) +{ + return (cu.slice->getPPS()->getSubPicFromCU(cu).getSubPicIdx() == cu2.slice->getPPS()->getSubPicFromCU(cu2).getSubPicIdx()) ; +} +#endif + bool CU::isSameCtu(const CodingUnit& cu, const CodingUnit& cu2) { uint32_t ctuSizeBit = floorLog2(cu.cs->sps->getMaxCUWidth()); @@ -1069,7 +1076,18 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, Position posC0; Position posC1 = pu.Y().center(); bool C0Avail = false; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + SubPic curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) +#else if (((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight)) +#endif { int posYInCtu = posRB.y & pcv.maxCUHeightMask; if (posYInCtu + 4 < pcv.maxCUHeight) @@ -1402,6 +1420,15 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList return false; } +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + // Check the position of colocated block is within a subpicture + SubPic curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + if (!curSubPic.isContainingPos(pos)) + return false; + } +#endif RefPicList eColRefPicList = slice.getCheckLDC() ? eRefPicList : RefPicList(slice.getColFromL0Flag()); const MotionInfo& mi = pColPic->cs->getMotionInfo( pos ); @@ -1778,7 +1805,18 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in Position posC1 = pu.Y().center(); Mv cColMv; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + SubPic curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) +#else if( ( ( posRB.x + pcv.minCUWidth ) < pcv.lumaWidth ) && ( ( posRB.y + pcv.minCUHeight ) < pcv.lumaHeight ) ) +#endif { int posYInCtu = posRB.y & pcv.maxCUHeightMask; if (posYInCtu + 4 < pcv.maxCUHeight) @@ -2093,7 +2131,18 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co bool C0Avail = false; Position posC1 = pu.Y().center(); Mv cColMv; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + SubPic curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) +#else if ( ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight) ) +#endif { int posYInCtu = posRB.y & pcv.maxCUHeightMask; if (posYInCtu + 4 < pcv.maxCUHeight) @@ -2670,7 +2719,18 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx Position posC0; bool C0Avail = false; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + SubPic curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) +#else if ( ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight) ) +#endif { int posYInCtu = posRB.y & pcv.maxCUHeightMask; if (posYInCtu + 4 < pcv.maxCUHeight) @@ -2860,7 +2920,20 @@ void clipColPos(int& posX, int& posY, const PredictionUnit& pu) int log2CtuSize = floorLog2(pu.cs->sps->getCTUSize()); int ctuX = ((puPos.x >> log2CtuSize) << log2CtuSize); int ctuY = ((puPos.y >> log2CtuSize) << log2CtuSize); +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + int horMax; + SubPic curSubPic = pu.cu->slice->getPPS()->getSubPicFromPos(puPos); + if (curSubPic.getTreatedAsPicFlag()) + { + horMax = std::min((int)curSubPic.getSubPicRight(), ctuX + (int)pu.cs->sps->getCTUSize() + 3); + } + else + { + horMax = std::min((int)pu.cs->pps->getPicWidthInLumaSamples() - 1, ctuX + (int)pu.cs->sps->getCTUSize() + 3); + } +#else int horMax = std::min( (int)pu.cs->pps->getPicWidthInLumaSamples() - 1, ctuX + (int)pu.cs->sps->getCTUSize() + 3 ); +#endif int horMin = std::max((int)0, ctuX); int verMax = std::min( (int)pu.cs->pps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1 ); int verMin = std::max((int)0, ctuY); diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index e13475ef6c..3807321f85 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -66,6 +66,9 @@ namespace CU bool isSameSlice (const CodingUnit &cu, const CodingUnit &cu2); bool isSameTile (const CodingUnit &cu, const CodingUnit &cu2); bool isSameSliceAndTile (const CodingUnit &cu, const CodingUnit &cu2); +#if JVET_O1143_SUBPIC_BOUNDARY + bool isSameSubPic (const CodingUnit &cu, const CodingUnit &cu2); +#endif bool isLastSubCUOfCtu (const CodingUnit &cu); uint32_t getCtuAddr (const CodingUnit &cu); int predictQP (const CodingUnit& cu, const int prevQP ); diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 253f8dda0f..7c6721fe3f 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -594,7 +594,7 @@ void DecLib::executeLoopFilters() m_cALF.ALFProcess(cs); } -#if SUBPIC_DECCHECK +#if JVET_O1143_SUBPIC_DECCHECK for (int i = 0; i < cs.pps->getNumSubPics(); i++) { // keep target subpic samples untouched, for other subpics mask their output sample value to 0 @@ -605,6 +605,7 @@ void DecLib::executeLoopFilters() uint32_t right = SubPicNoUse.getSubPicRight(); uint32_t top = SubPicNoUse.getSubPicTop(); uint32_t bottom= SubPicNoUse.getSubPicBottom(); + printf("left %d right %d, top %d bottom %d\n", left, right, top, bottom); for (uint32_t row = top; row <= bottom; row++) { for (uint32_t col = left; col <= right; col++) diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 7c9e0fa6b4..8ce3c0c24e 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -137,7 +137,7 @@ private: bool m_scalingListUpdateFlag; int m_PreScalingListAPSId; -#if SUBPIC_DECCHECK +#if JVET_O1143_SUBPIC_DECCHECK public: int m_targetSubPicIdx; #endif diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index 9e4d1360f7..5393538dd4 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -143,6 +143,31 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb const unsigned maxCUSize = sps->getMaxCUWidth(); Position pos( ctuXPosInCtus*maxCUSize, ctuYPosInCtus*maxCUSize) ; UnitArea ctuArea(cs.area.chromaFormat, Area( pos.x, pos.y, maxCUSize, maxCUSize ) ); +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = slice->getPPS()->getSubPicFromPos(pos); + // padding/restore at slice level + if (curSubPic.getTreatedAsPicFlag() && ctuIdx==0) + { + int subPicX = (int)curSubPic.getSubPicLeft(); + int subPicY = (int)curSubPic.getSubPicTop(); + int subPicWidth = (int)curSubPic.getSubPicWidthInLumaSample(); + int subPicHeight = (int)curSubPic.getSubPicHeightInLumaSample(); + for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) + { + int n = slice->getNumRefIdx((RefPicList)rlist); + for (int idx = 0; idx < n; idx++) + { + Picture *refPic = slice->getRefPic((RefPicList)rlist, idx); + refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + if (!refPic->getSubPicSaved()) + { + refPic->setSubPicSaved(true); + } + } + } + } +#endif DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) ); @@ -232,6 +257,30 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb #endif subStrmId++; } +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + if (curSubPic.getTreatedAsPicFlag() && ctuIdx == (slice->getNumCtuInSlice() - 1)) + // for last Ctu in the slice + { + int subPicX = (int)curSubPic.getSubPicLeft(); + int subPicY = (int)curSubPic.getSubPicTop(); + int subPicWidth = (int)curSubPic.getSubPicWidthInLumaSample(); + int subPicHeight = (int)curSubPic.getSubPicHeightInLumaSample(); + for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) + { + int n = slice->getNumRefIdx((RefPicList)rlist); + for (int idx = 0; idx < n; idx++) + { + Picture *refPic = slice->getRefPic((RefPicList)rlist, idx); + refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + + if (refPic->getSubPicSaved()) + { + refPic->setSubPicSaved(false); + } + } + } + } +#endif } // deallocate all created substreams, including internal buffers. diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp index 15ed5b0e24..44e214ff81 100644 --- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp +++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp @@ -1569,6 +1569,16 @@ void EncSampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructu isAboveAvail = (!isAboveAvail) ? false : CU::isSameTile(*cuCurr, *cuAbove); isAboveLeftAvail = (!isAboveLeftAvail) ? false : CU::isSameTile(*cuCurr, *cuAboveLeft); } + +#if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = cs.pps->getSubPicFromCU(*cuCurr); + if (!curSubPic.getloopFilterAcrossEnabledFlag()) + { + isLeftAvail = (!isLeftAvail) ? false : CU::isSameSubPic(*cuCurr, *cuLeft); + isAboveAvail = (!isAboveAvail) ? false : CU::isSameSubPic(*cuCurr, *cuAbove); + isAboveLeftAvail = (!isAboveLeftAvail) ? false : CU::isSameSubPic(*cuCurr, *cuAboveLeft); + } +#endif } //! \} diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 979743ec46..cb0d820903 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1452,7 +1452,36 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons cs.motionLut.lutIbc.resize(0); } +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = pcSlice->getPPS()->getSubPicFromPos(pos); + // padding/restore at slice level + if (curSubPic.getTreatedAsPicFlag() && ctuIdx == 0) + { + int subPicX = (int)curSubPic.getSubPicLeft(); + int subPicY = (int)curSubPic.getSubPicTop(); + int subPicWidth = (int)curSubPic.getSubPicWidthInLumaSample(); + int subPicHeight = (int)curSubPic.getSubPicHeightInLumaSample(); + + for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) + { + int n = pcSlice->getNumRefIdx((RefPicList)rlist); + for (int idx = 0; idx < n; idx++) + { + Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx); + + refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + if (!refPic->getSubPicSaved()) + { + refPic->setSubPicSaved(true); + } + // Save only at the beginning of the tile + // refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + } + } + } +#endif if (cs.pps->ctuIsTileColBd( ctuXPosInCtus ) && cs.pps->ctuIsTileRowBd( ctuYPosInCtus )) { pCABACWriter->initCtxModels( *pcSlice ); @@ -1649,6 +1678,31 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons m_uiPicTotalBits += actualBits; m_uiPicDist = cs.dist; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + // for last Ctu in the slice + if (curSubPic.getTreatedAsPicFlag() && ctuIdx == (pcSlice->getNumCtuInSlice() - 1)) + { + + int subPicX = (int)curSubPic.getSubPicLeft(); + int subPicY = (int)curSubPic.getSubPicTop(); + int subPicWidth = (int)curSubPic.getSubPicWidthInLumaSample(); + int subPicHeight = (int)curSubPic.getSubPicHeightInLumaSample(); + + for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) + { + int n = pcSlice->getNumRefIdx((RefPicList)rlist); + for (int idx = 0; idx < n; idx++) + { + Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx); + refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + if (refPic->getSubPicSaved()) + { + refPic->setSubPicSaved(false); + } + } + } + } +#endif } // this is wpp exclusive section diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 51ff99a786..91fcfd1333 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -7984,7 +7984,17 @@ void InterSearch::xClipMv( Mv& rcMv, const Position& pos, const struct Size& siz int verMax = ( pps.getPicHeightInLumaSamples() + offset - (int)pos.y - 1 ) << mvShift; int verMin = ( -( int ) sps.getMaxCUHeight() - offset - ( int ) pos.y + 1 ) << mvShift; +#if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY + SubPic curSubPic = pps.getSubPicFromPos(pos); + if (curSubPic.getTreatedAsPicFlag()) + { + horMax = (curSubPic.getSubPicWidthInLumaSample() + offset - (int)pos.x - 1) << mvShift; + horMin = (-(int)sps.getMaxCUWidth() - offset - ((int)pos.x - curSubPic.getSubPicLeft()) + 1) << mvShift; + verMax = (curSubPic.getSubPicHeightInLumaSample()+ offset - (int)pos.y - 1) << mvShift; + verMin = (-(int)sps.getMaxCUHeight() - offset - ((int)pos.y - curSubPic.getSubPicTop()) + 1) << mvShift; + } +#endif if( sps.getWrapAroundEnabledFlag() ) { int horMax = ( pps.getPicWidthInLumaSamples() + sps.getMaxCUWidth() - size.width + offset - (int)pos.x - 1 ) << mvShift; -- GitLab From fbfebee1be692161b6ebb9766bdbca74d599ceda Mon Sep 17 00:00:00 2001 From: biaowang <biao.wang@huawei.com> Date: Sat, 1 Feb 2020 11:04:27 +0100 Subject: [PATCH 2/5] JVET-O1143: motion and in-loop filter operations adaptation when subpic boundaries are treated as pic boundaries, check disabled --- source/Lib/CommonLib/TypeDef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 82b938fe38..01db04b185 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -92,7 +92,7 @@ #define JVET_O1143_SUBPIC_BOUNDARY 1 // treat subpicture boundary as piucture boundary #if JVET_O1143_SUBPIC_BOUNDARY -#define JVET_O1143_SUBPIC_DECCHECK 1 +#define JVET_O1143_SUBPIC_DECCHECK 0 #define JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY 1 #define JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY 1 #endif -- GitLab From ceb8ecbd5496c041e18f59d3f6b2ca93c9b8af70 Mon Sep 17 00:00:00 2001 From: biaowang <biao.wang@huawei.com> Date: Wed, 5 Feb 2020 14:58:10 +0100 Subject: [PATCH 3/5] improve variable namings and code clean to address software coordinates concerns --- source/Lib/CommonLib/LoopFilter.cpp | 55 ++++---- source/Lib/CommonLib/Picture.cpp | 212 ++++++++++------------------ source/Lib/CommonLib/Picture.h | 6 +- source/Lib/CommonLib/Slice.h | 6 +- 4 files changed, 104 insertions(+), 175 deletions(-) diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index 7541b5de90..ba4ff56166 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -81,31 +81,30 @@ inline static uint32_t getRasterIdx(const Position& pos, const PreCalcValues& pc // ==================================================================================================================== // utility functions // ==================================================================================================================== - -static bool isAvailableLeft( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , const bool bEnforceSubPicRestriction +static bool isAvailableLeft( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction, const bool bEnforceSubPicRestriction) +#else +static bool isAvailableLeft( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction) #endif -) { - return ( ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2)) -#endif - ); + return ((!bEnforceSliceRestriction || CU::isSameSlice(cu, cu2)) && (!bEnforceTileRestriction || CU::isSameTile(cu, cu2)) && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2))); +#else + return ((!bEnforceSliceRestriction || CU::isSameSlice(cu, cu2)) && (!bEnforceTileRestriction || CU::isSameTile(cu, cu2))); +#endif } -static bool isAvailableAbove( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , const bool bEnforceSubPicRestriction +static bool isAvailableAbove( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction, const bool bEnforceSubPicRestriction) +#else +static bool isAvailableAbove( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction) #endif -) { - return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2)) + return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) && (!bEnforceSubPicRestriction || CU::isSameSubPic(cu, cu2)); +#else + return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) ) && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) ) ; #endif - ; } @@ -697,16 +696,18 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu ) m_stLFCUParam.internalEdge = true; - m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() + m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() ); +#else + m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()); #endif - ); - m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() + #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() + m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() ); +#else + m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag()); #endif - ); + } unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const Position& localPos ) const @@ -962,11 +963,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg // Derive neighboring PU index if (edgeDir == EDGE_VER) { - if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() -#endif - )) + if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag())) +#else + if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag())) +#endif { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; @@ -974,11 +975,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg } else // (iDir == EDGE_HOR) { - if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag() #if JVET_O1143_LPF_ACROSS_SUBPIC_BOUNDARY - , !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag() + if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag(), !pps.getSubPicFromCU(cu).getloopFilterAcrossEnabledFlag())) +#else + if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossTilesEnabledFlag())) #endif - )) { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index f69d5bd64b..40e26ba561 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -174,7 +174,7 @@ Picture::Picture() { cs = nullptr; #if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY - m_bIsSubPicBorderSaved = false; + m_isSubPicBorderSaved = false; #endif m_bIsBorderExtended = false; usedByCurr = false; @@ -762,12 +762,6 @@ void Picture::saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWi m_bufSubPicLeft.create(unitAreaLeftRight); m_bufSubPicRight.create(unitAreaLeftRight); - Pel *ss0; - Pel *ss1; - Pel *dd0; - Pel *dd1; - int copylen; - for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) { ComponentID compID = ComponentID(comp); @@ -777,71 +771,51 @@ void Picture::saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWi int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.2 calculate the origin of the subpicture - int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); - int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + int left = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int top = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.3 calculate the width/height of the subPic - int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); - int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + int width = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int height = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); // 3.1.1 set reconstructed picture PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); - Pel *siTxt = s.bufAt(tx0, ty0); - Pel* si = siTxt; + Pel *src = s.bufAt(left, top); // 3.2.1 set back up buffer for left - PelBuf d0 = m_bufSubPicLeft.getBuf(compID); - Pel *diTxt0 = d0.bufAt(0, 0); - Pel *di0 = diTxt0; + PelBuf dBufLeft = m_bufSubPicLeft.getBuf(compID); + Pel *dstLeft = dBufLeft.bufAt(0, 0); - // 3.2.2 set back up buffer for right - PelBuf d1 = m_bufSubPicRight.getBuf(compID); - Pel *diTxt1 = d1.bufAt(0, 0); - Pel *di1 = diTxt1; + // 3.2.2 set back up buffer for right + PelBuf dBufRight = m_bufSubPicRight.getBuf(compID); + Pel *dstRight = dBufRight.bufAt(0, 0); // 3.2.3 copy to recon picture to back up buffer - ss0 = si - xmargin; - ss1 = si + tww; - dd0 = di0; - dd1 = di1; - copylen = sizeof(Pel) * xmargin; - for (int y = 0; y < thh; y++) + Pel *srcLeft = src - xmargin; + Pel *srcRight = src + width; + for (int y = 0; y < height; y++) { - ::memcpy(dd0, ss0, copylen); - ::memcpy(dd1, ss1, copylen); - ss0 += s.stride; - ss1 += s.stride; - dd0 += d0.stride; - dd1 += d1.stride; + ::memcpy(dstLeft + y * dBufLeft.stride, srcLeft + y * s.stride, sizeof(Pel) * xmargin); + ::memcpy(dstRight + y * dBufRight.stride, srcRight + y * s.stride, sizeof(Pel) * xmargin); } - // 3.3.1 set back up buffer for above - d0 = m_bufSubPicAbove.getBuf(compID); - diTxt0 = d0.bufAt(0, 0); - di0 = diTxt0; + PelBuf dBufTop = m_bufSubPicAbove.getBuf(compID); + Pel *dstTop = dBufTop.bufAt(0, 0); // 3.3.2 set back up buffer for below - d1 = m_bufSubPicBelow.getBuf(compID); - diTxt1 = d1.bufAt(0, 0); - di1 = diTxt1; + PelBuf dBufBottom = m_bufSubPicBelow.getBuf(compID); + Pel *dstBottom = dBufBottom.bufAt(0, 0); // 3.3.3 copy to recon picture to back up buffer - ss0 = si - xmargin - ymargin * s.stride; - ss1 = si - xmargin + thh * s.stride; - dd0 = di0; - dd1 = di1; - copylen = sizeof(Pel) * (2 * xmargin + tww); + Pel *srcTop = src - xmargin - ymargin * s.stride; + Pel *srcBottom = src - xmargin + height * s.stride; for (int y = 0; y < ymargin; y++) { - ::memcpy(dd0, ss0, copylen); - ::memcpy(dd1, ss1, copylen); - ss0 += s.stride; - ss1 += s.stride; - dd0 += d0.stride; - dd1 += d1.stride; + ::memcpy(dstTop + y * dBufTop.stride, srcTop + y * s.stride, sizeof(Pel) * (2 * xmargin + width)); + ::memcpy(dstBottom + y * dBufBottom.stride, srcBottom + y * s.stride, sizeof(Pel) * (2 * xmargin + width)); } } } @@ -854,12 +828,6 @@ void Picture::extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPic return; } - Pel *ss0 = 0; - Pel *ss1 = 0; - Pel *dd0 = 0; - Pel *dd1 = 0; - int copylen; - for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) { ComponentID compID = ComponentID(comp); @@ -869,67 +837,56 @@ void Picture::extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPic int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.2 calculate the origin of the Subpicture - int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); - int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + int left = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int top = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.3 calculate the width/height of the Subpicture - int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); - int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + int width = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int height = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); // 3.1 set reconstructed picture PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); - Pel *siTxt = s.bufAt(tx0, ty0); - Pel* si = siTxt; + Pel *src = s.bufAt(left, top); // 4.1 apply padding for left and right { - Pel *xx0, *xx1; - ss0 = si - xmargin; - ss1 = si + tww; - xx0 = si + 0; - xx1 = si + tww - 1; + Pel *dstLeft = src - xmargin; + Pel *dstRight = src + width; + Pel *srcLeft = src + 0; + Pel *srcRight = src + width - 1; - for (int y = 0; y < thh; y++) + for (int y = 0; y < height; y++) { - dd0 = ss0; - dd1 = ss1; for (int x = 0; x < xmargin; x++) { - *dd0++ = *xx0; - *dd1++ = *xx1; + dstLeft[x] = *srcLeft; + dstRight[x] = *srcRight; } - - ss0 += s.stride; - ss1 += s.stride; - xx0 += s.stride; - xx1 += s.stride; + dstLeft += s.stride; + dstRight += s.stride; + srcLeft += s.stride; + srcRight += s.stride; } } // 4.2 apply padding on bottom - // si is now the (0, SubpictureHeight) (bottom left of image within bigger picture - si += s.stride * (thh - 1) - xmargin; - - // si is now the (-marginX, SubpictureHeight-1) - ss0 = si + s.stride; - copylen = sizeof(Pel)*(tww + (xmargin << 1)); + Pel *srcBottom = src + s.stride * (height - 1) - xmargin; + Pel *dstBottom = srcBottom + s.stride; for (int y = 0; y < ymargin; y++) { - ::memcpy(ss0, si, copylen); - ss0 += s.stride; + ::memcpy(dstBottom, srcBottom, sizeof(Pel)*(2 * xmargin + width)); + dstBottom += s.stride; } // 4.3 apply padding for top // si is still (-marginX, SubpictureHeight-1) - si -= ((thh - 1) * s.stride); - + Pel *srcTop = src - xmargin; + Pel *dstTop = srcTop - s.stride; // si is now (-marginX, 0) - ss0 = si - s.stride; - copylen = sizeof(Pel)*(tww + (xmargin << 1)); for (int y = 0; y < ymargin; y++) { - ::memcpy(ss0, si, copylen); - ss0 -= s.stride; + ::memcpy(dstTop, srcTop, sizeof(Pel)*(2 * xmargin + width)); + dstTop -= s.stride; } } // end of for } @@ -942,12 +899,6 @@ void Picture::restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPi return; } - Pel *ss0; - Pel *ss1; - Pel *dd0; - Pel *dd1; - int copylen; - for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) { ComponentID compID = ComponentID(comp); @@ -957,72 +908,53 @@ void Picture::restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPi int ymargin = margin >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.2 calculate the origin of the subpicture - int tx0 = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); - int ty0 = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); + int left = subPicX0 >> getComponentScaleX(compID, cs->area.chromaFormat); + int top = subPicY0 >> getComponentScaleY(compID, cs->area.chromaFormat); // 2.3 calculate the width/height of the subpicture - int tww = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); - int thh = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); + int width = subPicWidth >> getComponentScaleX(compID, cs->area.chromaFormat); + int height = subPicHeight >> getComponentScaleY(compID, cs->area.chromaFormat); // 3.1 set reconstructed picture PelBuf s = M_BUFS(0, PIC_RECONSTRUCTION).get(compID); - Pel *siTxt = s.bufAt(tx0, ty0); - Pel* si = siTxt; - + Pel *src = s.bufAt(left, top); // 4.2.1 copy from back up buffer to recon picture - PelBuf d0 = m_bufSubPicLeft.getBuf(compID); - Pel *diTxt0 = d0.bufAt(0, 0); - Pel *di0 = diTxt0; + PelBuf dBufLeft = m_bufSubPicLeft.getBuf(compID); + Pel *dstLeft = dBufLeft.bufAt(0, 0); // 4.2.2 set back up buffer for right - PelBuf d1 = m_bufSubPicRight.getBuf(compID); - Pel *diTxt1 = d1.bufAt(0, 0); - Pel *di1 = diTxt1; + PelBuf dBufRight = m_bufSubPicRight.getBuf(compID); + Pel *dstRight = dBufRight.bufAt(0, 0); // 4.2.3 copy to recon picture to back up buffer - ss0 = si - xmargin; - ss1 = si + tww; - dd0 = di0; - dd1 = di1; - copylen = sizeof(Pel) * xmargin; + Pel *srcLeft = src - xmargin; + Pel *srcRight = src + width; - for (int y = 0; y < thh; y++) + for (int y = 0; y < height; y++) { - ::memcpy(ss0, dd0, copylen); - ::memcpy(ss1, dd1, copylen); - ss0 += s.stride; - ss1 += s.stride; - dd0 += d0.stride; - dd1 += d1.stride; + // the destination and source position is reversed on purpose + ::memcpy(srcLeft + y * s.stride, dstLeft + y * dBufLeft.stride, sizeof(Pel) * xmargin); + ::memcpy(srcRight + y * s.stride, dstRight + y * dBufRight.stride, sizeof(Pel) * xmargin); } - // 4.3.1 copy from back up buffer to recon picture - d0 = m_bufSubPicAbove.getBuf(compID); - diTxt0 = d0.bufAt(0, 0); - di0 = diTxt0; + // 4.3.1 set back up buffer for above + PelBuf dBufTop = m_bufSubPicAbove.getBuf(compID); + Pel *dstTop = dBufTop.bufAt(0, 0); // 4.3.2 set back up buffer for below - d1 = m_bufSubPicBelow.getBuf(compID); - diTxt1 = d1.bufAt(0, 0); - di1 = diTxt1; + PelBuf dBufBottom = m_bufSubPicBelow.getBuf(compID); + Pel *dstBottom = dBufBottom.bufAt(0, 0); // 4.3.3 copy to recon picture to back up buffer - ss0 = si - xmargin - ymargin * s.stride; - ss1 = si - xmargin + thh * s.stride; - dd0 = di0; - dd1 = di1; - copylen = sizeof(Pel) * (2 * xmargin + tww); + Pel *srcTop = src - xmargin - ymargin * s.stride; + Pel *srcBottom = src - xmargin + height * s.stride; for (int y = 0; y < ymargin; y++) { - ::memcpy(ss0, dd0, copylen); - ::memcpy(ss1, dd1, copylen); - ss0 += s.stride; - ss1 += s.stride; - dd0 += d0.stride; - dd1 += d1.stride; + ::memcpy(srcTop + y * s.stride, dstTop + y * dBufTop.stride, sizeof(Pel) * (2 * xmargin + width)); + ::memcpy(srcBottom + y * s.stride, dstBottom + y * dBufBottom.stride, sizeof(Pel) * (2 * xmargin + width)); } } diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index b1d8ca6f45..5cc6a41611 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -173,7 +173,7 @@ private: public: #if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY - bool m_bIsSubPicBorderSaved; + bool m_isSubPicBorderSaved; PelStorage m_bufSubPicAbove; PelStorage m_bufSubPicBelow; @@ -184,8 +184,8 @@ public: void extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight); void restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight); - bool getSubPicSaved() { return m_bIsSubPicBorderSaved; } - void setSubPicSaved(bool bVal) { m_bIsSubPicBorderSaved = bVal; } + bool getSubPicSaved() { return m_isSubPicBorderSaved; } + void setSubPicSaved(bool bVal) { m_isSubPicBorderSaved = bVal; } #endif bool m_bIsBorderExtended; bool referenced; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index fc1f1aa271..ce6efa00c3 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -752,11 +752,7 @@ public: } bool isContainingPos(const Position& pos) const { - if (pos.x >= m_subPicLeft && pos.x <= m_subPicRight && - pos.y >= m_subPicTop && pos.y <= m_subPicBottom) - return true; - else - return false; + return pos.x >= m_subPicLeft && pos.x <= m_subPicRight && pos.y >= m_subPicTop && pos.y <= m_subPicBottom; } void setTreatedAsPicFlag (bool u) { m_treatedAsPicFlag = u; } bool getTreatedAsPicFlag () const { return m_treatedAsPicFlag; } -- GitLab From 3d074ac6766a3c3a9f0ceba61e3e1c123335017e Mon Sep 17 00:00:00 2001 From: biaowang <biao.wang@huawei.com> Date: Wed, 5 Feb 2020 18:55:44 +0100 Subject: [PATCH 4/5] improve readability of save and restore subpicture boundaries functionality --- source/Lib/CommonLib/Picture.cpp | 16 ---------------- source/Lib/DecoderLib/DecSlice.cpp | 7 +++---- source/Lib/EncoderLib/EncSlice.cpp | 10 +++------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 40e26ba561..a74e5ed1e1 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -740,11 +740,6 @@ void Picture::rescalePicture( const std::pair<int, int> scalingRatio, #if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY void Picture::saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) { - // 1.0 check border was extended - if (getSubPicSaved()) - { - return; - } // 1.1 set up margin for back up memory allocation int xMargin = margin >> getComponentScaleX(COMPONENT_Y, cs->area.chromaFormat); @@ -822,11 +817,6 @@ void Picture::saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWi void Picture::extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) { - // 1.0 check border was extended - if (getSubPicSaved()) - { - return; - } for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) { @@ -893,12 +883,6 @@ void Picture::extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPic void Picture::restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight) { - // 1.0 check border was extended - if (!getSubPicSaved()) - { - return; - } - for (int comp = 0; comp < getNumberValidComponents(cs->area.chromaFormat); comp++) { ComponentID compID = ComponentID(comp); diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index 5393538dd4..762ddf16bc 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -158,10 +158,10 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb for (int idx = 0; idx < n; idx++) { Picture *refPic = slice->getRefPic((RefPicList)rlist, idx); - refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); - refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); if (!refPic->getSubPicSaved()) { + refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); refPic->setSubPicSaved(true); } } @@ -271,10 +271,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb for (int idx = 0; idx < n; idx++) { Picture *refPic = slice->getRefPic((RefPicList)rlist, idx); - refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); - if (refPic->getSubPicSaved()) { + refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); refPic->setSubPicSaved(false); } } diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index cb0d820903..98c5bd9ec2 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1468,16 +1468,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons for (int idx = 0; idx < n; idx++) { Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx); - - refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); - refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); - if (!refPic->getSubPicSaved()) { + refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); + refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); refPic->setSubPicSaved(true); } - // Save only at the beginning of the tile - // refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); } } } @@ -1694,9 +1690,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons for (int idx = 0; idx < n; idx++) { Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx); - refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); if (refPic->getSubPicSaved()) { + refPic->restoreSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight); refPic->setSubPicSaved(false); } } -- GitLab From 6a371ffdc796e31e79b5c5c39345f33b478f1cde Mon Sep 17 00:00:00 2001 From: biaowang <biao.wang@huawei.com> Date: Wed, 5 Feb 2020 21:56:09 +0100 Subject: [PATCH 5/5] remove debug code --- source/Lib/DecoderLib/DecLib.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 7c6721fe3f..66ea5461a2 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -605,7 +605,6 @@ void DecLib::executeLoopFilters() uint32_t right = SubPicNoUse.getSubPicRight(); uint32_t top = SubPicNoUse.getSubPicTop(); uint32_t bottom= SubPicNoUse.getSubPicBottom(); - printf("left %d right %d, top %d bottom %d\n", left, right, top, bottom); for (uint32_t row = top; row <= bottom; row++) { for (uint32_t col = left; col <= right; col++) -- GitLab