CodingStructure.cpp 88.48 KiB
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2022, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file CodingStructure.h
* \brief A class managing the coding information for a specific image part
*/
#include "CodingStructure.h"
#include "Unit.h"
#include "Slice.h"
#include "Picture.h"
#include "UnitTools.h"
#include "UnitPartitioner.h"
XUCache g_globalUnitCache = XUCache();
const UnitScale UnitScaleArray[NUM_CHROMA_FORMAT][MAX_NUM_COMPONENT] =
{
{ {2,2}, {0,0}, {0,0} }, // 4:0:0
{ {2,2}, {1,1}, {1,1} }, // 4:2:0
{ {2,2}, {1,2}, {1,2} }, // 4:2:2
{ {2,2}, {2,2}, {2,2} } // 4:4:4
};
// ---------------------------------------------------------------------------
// coding structure method definitions
// ---------------------------------------------------------------------------
CodingStructure::CodingStructure(CUCache& cuCache, PUCache& puCache, TUCache& tuCache)
: area ()
, picture ( nullptr )
, parent ( nullptr )
, bestCS ( nullptr )
, m_isTuEnc ( false )
, m_cuCache ( cuCache )
, m_puCache ( puCache )
, m_tuCache ( tuCache )
, bestParent ( nullptr )
, tmpColorSpaceCost(MAX_DOUBLE)
, firstColorSpaceSelected(true)
#if JVET_Z0153_IBC_EXT_REF
, resetIBCBuffer (true)
#else
, resetIBCBuffer (false)
#endif
{
for( uint32_t i = 0; i < MAX_NUM_COMPONENT; i++ )
{
m_coeffs[ i ] = nullptr;
#if SIGN_PREDICTION
m_coeffSigns[ i ] = nullptr;
#if JVET_Y0141_SIGN_PRED_IMPROVE
m_coeffSignsIdx[i] = nullptr;
#endif
#endif
#if !REMOVE_PCM
m_pcmbuf[ i ] = nullptr;
#endif
m_offsets[ i ] = 0;
}
for (uint32_t i = 0; i < MAX_NUM_CHANNEL_TYPE; i++)
{
#if REMOVE_PCM
m_pltIdx[i] = nullptr;
#endif
m_runType[i] = nullptr;
}
for( uint32_t i = 0; i < MAX_NUM_CHANNEL_TYPE; i++ )
{
m_cuIdx [ i ] = nullptr;
m_puIdx [ i ] = nullptr;
m_tuIdx [ i ] = nullptr;
m_isDecomp[ i ] = nullptr;
}
#if JVET_Z0118_GDR
m_motionBuf0 = nullptr;
m_motionBuf1 = nullptr;
picHeader = nullptr;
#else
m_motionBuf = nullptr;
#endif
#if JVET_W0123_TIMD_FUSION
#if JVET_Z0118_GDR
m_ipmBuf0 = nullptr;
m_ipmBuf1 = nullptr;
#else
m_ipmBuf = nullptr;
#endif
#endif
#if JVET_Z0136_OOB
for (uint32_t i = 0; i < 2; i++)
{
mcMask[i] = nullptr;
mcMaskChroma[i] = nullptr;
}
#endif
features.resize( NUM_ENC_FEATURES );
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
treeType = TREE_D;
modeType = MODE_TYPE_ALL;
#endif
tmpColorSpaceIntraCost[0] = MAX_DOUBLE;
tmpColorSpaceIntraCost[1] = MAX_DOUBLE;
firstColorSpaceTestOnly = false;
#if JVET_Z0118_GDR
picHeader = nullptr;
m_gdrEnabled = false;
#endif
}
void CodingStructure::destroy()
{
picture = nullptr;
parent = nullptr;
m_pred.destroy();
m_resi.destroy();
#if JVET_Z0118_GDR
m_reco0.destroy();
if (m_gdrEnabled)
{
m_reco1.destroy();
}
#else
m_reco.destroy();
#endif
m_orgr.destroy();
destroyCoeffs();
for( uint32_t i = 0; i < MAX_NUM_CHANNEL_TYPE; i++ )
{
delete[] m_isDecomp[ i ];
m_isDecomp[ i ] = nullptr;
delete[] m_cuIdx[ i ];
m_cuIdx[ i ] = nullptr;
delete[] m_puIdx[ i ];
m_puIdx[ i ] = nullptr;
delete[] m_tuIdx[ i ];
m_tuIdx[ i ] = nullptr;
}
#if JVET_Z0118_GDR
delete[] m_motionBuf0;
if (m_gdrEnabled)
{
delete[] m_motionBuf1;
}
m_motionBuf0 = nullptr;
m_motionBuf1 = nullptr;
if (picHeader && m_gdrEnabled)
{
delete picHeader;
}
picHeader = nullptr;
#else
delete[] m_motionBuf;
m_motionBuf = nullptr;
#endif
#if JVET_W0123_TIMD_FUSION
#if JVET_Z0118_GDR
delete[] m_ipmBuf0;
if (m_gdrEnabled)
{
delete[] m_ipmBuf1;
}
m_ipmBuf0 = nullptr;
m_ipmBuf1 = nullptr;
#else
delete[] m_ipmBuf;
m_ipmBuf = nullptr;
#endif
#endif
#if JVET_Z0136_OOB
for (uint32_t i = 0; i < 2; i++)
{
if (mcMask[i])
{
xFree(mcMask[i]);
mcMask[i] = nullptr;
}
if (mcMaskChroma[i])
{
xFree(mcMaskChroma[i]);
mcMaskChroma[i] = nullptr;
}
}
#endif
m_tuCache.cache( tus );
m_puCache.cache( pus );
m_cuCache.cache( cus );
}
void CodingStructure::releaseIntermediateData()
{
clearTUs();
clearPUs();
clearCUs();
}
#if JVET_Z0118_GDR
bool CodingStructure::isCuCrossIRA(int begX) const
{
if ((area.lx() < begX) && (begX < (area.lx() + area.lwidth())))
{
return true;
}
return false;
}
bool CodingStructure::isCuCrossVB(int endX) const
{
if ((area.lx() < endX) && (endX < (area.lx() + area.lwidth())))
{
return true;
}
return false;
}
bool CodingStructure::containRefresh(int begX, int endX) const
{
if (begX == endX)
{
return false;
}
if ((area.lx() <= begX) && (endX <= (area.lx() + area.lwidth())))
{
return true;
}
return false;
}
bool CodingStructure::overlapRefresh(int begX, int endX) const
{
if (begX == endX)
{
return false;
}
if ((begX < (area.lx() + area.lwidth())) || (area.lx() < endX))
{
return true;
}
return false;
}
bool CodingStructure::withinRefresh(int begX, int endX) const
{
if (begX == endX)
{
return false;
}
if ((begX <= area.lx()) && ((area.lx() + area.lwidth()) <= endX))
{
return true;
}
return false;
}
Area CodingStructure::findOverlappedArea(const Area &a1, const Area &a2) const
{
Area intersectArea = Area(Position(0, 0), Size(0, 0));
if (
((a1.x <= a2.x && a2.x <= a1.topRight().x) || (a2.x <= a1.x && a1.x <= a2.topRight().x)) &&
((a1.y <= a2.y && a2.y <= a1.bottomRight().y) || (a2.y <= a1.y && a1.y <= a2.bottomRight().y))
)
{
int xArray[4] = { a1.x, a1.topRight().x, a2.x, a2.topRight().x };
int yArray[4] = { a1.y, a1.bottomRight().y, a2.y, a2.bottomRight().y };
std::sort(xArray, xArray + 4);
std::sort(yArray, yArray + 4);
intersectArea = Area(Position(xArray[1], yArray[1]), Size(xArray[2] - xArray[1] + 1, yArray[2] - yArray[1] + 1));
}
return intersectArea;
}
#endif
#if JVET_Z0118_GDR
bool CodingStructure::isInGdrIntervalOrRecoveryPoc() const
{
if( !m_gdrEnabled )
{
return false;
}
PicHeader *curPh = picHeader;
bool isCurGdrIntervalPic = curPh->getInGdrInterval();
bool isCurGdrRecoveryPocPic = curPh->getIsGdrRecoveryPocPic();
if (isCurGdrIntervalPic || isCurGdrRecoveryPocPic)
{
return true;
}
return false;
}
bool CodingStructure::isClean(const ChannelType effChType) const
{
if( !m_gdrEnabled )
{
return false;
}
bool ret = isClean(area.Y(), effChType);
return ret;
}
bool CodingStructure::isClean(const Position &IntPos, RefPicList e, int refIdx) const
{
if (!m_gdrEnabled)
{
return false;
}
/*
1. non gdr picture --> false;
2. gdr picture
pos in clean area -> true
pos in dirty area -> false
*/
const Picture* const refPic = slice->getRefPic(e, refIdx);
if (!refPic || refIdx < 0)
{
return false;
}
PicHeader *refPh = refPic->cs->picHeader;
bool isRefGdrIntervalPic = refPh->getInGdrInterval();
bool isRefGdrRecoveryPocPic = refPh->getIsGdrRecoveryPocPic();
if (isInGdrIntervalOrRecoveryPoc())
{
int virboundaryEndx = 0;
if (isRefGdrIntervalPic)
{
virboundaryEndx = refPh->getVirtualBoundariesPosX(0);
}
if (isRefGdrRecoveryPocPic)
{
virboundaryEndx = slice->getPPS()->getPicWidthInLumaSamples();
}
if (IntPos.x < virboundaryEndx)
{
return true;
}
else
{
return false;
}
}
else
{
// refPic is normal picture
bool isCurGdrPicture = (slice->getPicHeader()->getNumVerVirtualBoundaries() > 0);
if (isCurGdrPicture)
{
return false;
}
else
{
return true;
}
}
}
bool CodingStructure::isClean(const Position &IntPos, const Picture* const refPic) const
{
if (!m_gdrEnabled)
{
return false;
}
if (!refPic)
{
return false;
}
PicHeader *refPh = refPic->cs->picHeader;
bool isRefGdrIntervalPic = refPh->getInGdrInterval();
bool isRefGdrRecoveryPocPic = refPh->getIsGdrRecoveryPocPic();
if (isInGdrIntervalOrRecoveryPoc())
{
int virboundaryEndx = 0;
if (isRefGdrIntervalPic)
{
virboundaryEndx = refPh->getVirtualBoundariesPosX(0);
}
if (isRefGdrRecoveryPocPic)
{
virboundaryEndx = slice->getPPS()->getPicWidthInLumaSamples();
}
if (IntPos.x < virboundaryEndx)
{
return true;
}
else
{
return false;
}
}
else
{
// refPic is normal picture
bool isCurGdrPicture = (slice->getPicHeader()->getNumVerVirtualBoundaries() > 0);
if (isCurGdrPicture)
{
return false;
}
else
{
return true;
}
}
}
bool CodingStructure::isClean(const int Intx, const int Inty, const ChannelType effChType) const
{
if (!m_gdrEnabled)
{
return false;
}
/*
1. non gdr picture --> false;
2. gdr picture
pos in clean area -> true
pos in dirty area -> false
*/
PicHeader *curPh = picHeader;
bool isCurGdrIntervalPic = curPh->getInGdrInterval();
bool isCurGdrRecoveryPocPic = curPh->getIsGdrRecoveryPocPic();
if (isInGdrIntervalOrRecoveryPoc())
{
int virboundaryEndx = 0;
if (isCurGdrIntervalPic)
{
virboundaryEndx = curPh->getVirtualBoundariesPosX(0);
}
if (isCurGdrRecoveryPocPic)
{
virboundaryEndx = slice->getPPS()->getPicWidthInLumaSamples();
}
virboundaryEndx = virboundaryEndx >> effChType;
if (Intx < virboundaryEndx)
{
return true;
}
else
{
return false;
}
}
return true;
}
bool CodingStructure::isClean(const Position &IntPos, const ChannelType effChType) const
{
if( !m_gdrEnabled)
{
return false;
}
bool ret = isClean(IntPos.x, IntPos.y, effChType);
return ret;
}
bool CodingStructure::isClean(const Area &area, const ChannelType effChType) const
{
if (!m_gdrEnabled)
{
return false;
}
Position pTopLeft = area.topLeft();
Position pTopRight = area.topRight();
Position pBotLeft = area.bottomLeft();
Position pBotRight = area.bottomRight();
bool bTopLeft = isClean(pTopLeft, effChType);
bool bTopRight = isClean(pTopRight, effChType);
bool bBotLeft = isClean(pBotLeft, effChType);
bool bBotRight = isClean(pBotRight, effChType);
return bTopLeft && bTopRight && bBotLeft && bBotRight;
}
bool CodingStructure::isClean(const CodingUnit &cu) const
{
if (!m_gdrEnabled)
{
return false;
}
bool ret = cu.Y().valid() ? isClean(cu.Y().bottomRight(), CHANNEL_TYPE_LUMA) : isClean(cu.Cb().bottomRight(), CHANNEL_TYPE_CHROMA);
return ret;
}
bool CodingStructure::isClean(const PredictionUnit &pu) const
{
if (!m_gdrEnabled)
{
return false;
}
bool ret = pu.Y().valid() ? isClean(pu.Y().bottomRight(), CHANNEL_TYPE_LUMA) : isClean(pu.Cb().bottomRight(), CHANNEL_TYPE_CHROMA);
return ret;
}
bool CodingStructure::isClean(const TransformUnit &tu) const
{
if (!m_gdrEnabled)
{
return false;
}
bool ret = tu.Y().valid() ? isClean(tu.Y().bottomRight(), CHANNEL_TYPE_LUMA) : isClean(tu.Cb().bottomRight(), CHANNEL_TYPE_CHROMA);
return ret;
}
#endif
#if JVET_Z0118_GDR
void CodingStructure::updateReconMotIPM(const UnitArea &uarea) const
{
if (!m_gdrEnabled)
{
picture->getRecoBuf(uarea).copyFrom(getRecoBuf(uarea));
return;
}
updateReconMotIPM(uarea, getRecoBuf(uarea));
}
void CodingStructure::updateReconMotIPM(const CompArea &carea) const
{
if (!m_gdrEnabled)
{
picture->getRecoBuf(carea).copyFrom(getRecoBuf(carea));
return;
}
updateReconMotIPM(carea, getRecoBuf(carea));
}
void CodingStructure::updateReconMotIPM(const UnitArea &uarea, const CPelUnitBuf &pbuf) const
{
if (!m_gdrEnabled)
{
picture->getRecoBuf(uarea).copyFrom(pbuf);
return;
}
for (int i = 0; i < MAX_NUM_COMPONENT; i++)
{
ComponentID compID = (ComponentID)i;
if (uarea.block(compID).valid())
{
updateReconMotIPM(uarea.block(compID), pbuf.get(compID));
}
}
}
void CodingStructure::updateReconMotIPM(const CompArea &carea, const CPelBuf &pbuf) const
{
if (!m_gdrEnabled)
{
picture->getRecoBuf(carea).copyFrom(pbuf);
return;
}
const ComponentID compID = carea.compID;
if (!isInGdrIntervalOrRecoveryPoc())
{
picture->getRecoBuf(carea).copyFrom(pbuf);
if (compID == COMPONENT_Y)
{
#if JVET_W0123_TIMD_FUSION
picture->cs->getIpmBuf(carea).copyFrom(getIpmBuf(carea));
#endif
picture->cs->getMotionBuf(carea).copyFrom(getMotionBuf(carea));
}
return;
}
picture->getBuf(carea, PIC_RECONSTRUCTION_0).copyFrom(pbuf);
if (compID == COMPONENT_Y)
{
#if JVET_W0123_TIMD_FUSION
picture->cs->getIpmBuf(carea, PIC_RECONSTRUCTION_0).copyFrom(getIpmBuf(carea));
#endif
picture->cs->getMotionBuf(carea, PIC_RECONSTRUCTION_0).copyFrom(getMotionBuf(carea));
}
ChromaFormat chromaFormat = sps->getChromaFormatIdc();
int gdrEndX = picHeader->getGdrEndX() >> getComponentScaleX((ComponentID)compID, chromaFormat);
int gdrEndY = pps->getPicHeightInLumaSamples() >> getComponentScaleY((ComponentID)compID, chromaFormat);;
CompArea cleanArea = CompArea((ComponentID)compID, chromaFormat, Area(Position(0, 0), Size(gdrEndX, gdrEndY)));
CompArea overlappedArea = CompArea((ComponentID)compID, chromaFormat, findOverlappedArea(cleanArea, carea));
CompArea subArea = CompArea((ComponentID)compID, chromaFormat, Area(overlappedArea.pos() - carea.pos(), overlappedArea.size()));
if (subArea.area() > 0)
{
picture->getBuf(overlappedArea, PIC_RECONSTRUCTION_1).copyFrom(pbuf.subBuf(subArea.pos(), subArea.size()));
if (compID == COMPONENT_Y)
{
#if JVET_W0123_TIMD_FUSION
picture->cs->getIpmBuf(overlappedArea, PIC_RECONSTRUCTION_1).copyFrom(getIpmBuf(overlappedArea));
#endif
picture->cs->getMotionBuf(overlappedArea, PIC_RECONSTRUCTION_1).copyFrom(getMotionBuf(overlappedArea));
}
}
}
#endif
#if JVET_Z0118_GDR
void CodingStructure::rspSignalPicture(const UnitArea &uarea, std::vector<Pel>& pLUT, bool usePred) const
{
for (int i = 0; i < MAX_NUM_COMPONENT; i++)
{
ComponentID compID = (ComponentID) i;
if (uarea.block(compID).valid())
{
CompArea carea = uarea.block(compID);
rspSignalPicture(carea, pLUT, usePred);
}
}
}
void CodingStructure::rspSignalPicture(const CompArea &carea, std::vector<Pel>& pLUT, bool usePred) const
{
ComponentID compID = carea.compID;
// 1. normal picture
if (!isInGdrIntervalOrRecoveryPoc())
{
PelBuf picRecoBuff = picture->getRecoBuf(carea);
CPelBuf predBuf = usePred ? getPredBuf(carea) : picture->getRecoBuf(carea);
picRecoBuff.rspSignal(predBuf, pLUT);
return;
}
// 2.1. gdr interval dirty picture
PelBuf picRecoBuff0 = picture->getBuf(carea, PIC_RECONSTRUCTION_0);
CPelBuf predBuf0 = usePred ? getPredBuf(carea) : picture->getBuf(carea, PIC_RECONSTRUCTION_0);
picRecoBuff0.rspSignal(predBuf0, pLUT);
// 2.2. gdr interval clean picture
ChromaFormat chromaFormat = sps->getChromaFormatIdc();
int gdrEndX = picHeader->getGdrEndX() >> getComponentScaleX((ComponentID)compID, chromaFormat);
int gdrEndY = pps->getPicHeightInLumaSamples() >> getComponentScaleY((ComponentID)compID, chromaFormat);;
CompArea cleanArea = CompArea((ComponentID)compID, chromaFormat, Area(Position(0, 0), Size(gdrEndX, gdrEndY)));
CompArea overlappedArea = CompArea((ComponentID)compID, chromaFormat, findOverlappedArea(cleanArea, carea));
if (overlappedArea.area() > 0)
{
PelBuf picRecoBuff1 = picture->getBuf(overlappedArea, PIC_RECONSTRUCTION_1);
CPelBuf predBuf1 = usePred ? getPredBuf(overlappedArea) : picture->getBuf(overlappedArea, PIC_RECONSTRUCTION_1);
picRecoBuff1.rspSignal(predBuf1, pLUT);
}
}
void CodingStructure::reconstructPicture(const CompArea &carea, std::vector<Pel>& pLUT, CodingStructure *resiCS, bool lmcsEnable) const
{
ComponentID compID = carea.compID;
// 1. normal picture
if (!isInGdrIntervalOrRecoveryPoc())
{
PelBuf picRecoBuff = picture->getRecoBuf(carea);
if (lmcsEnable)
{
picRecoBuff.rspSignal(getPredBuf(carea), pLUT);
picRecoBuff.reconstruct(picRecoBuff, resiCS->getResiBuf(carea), slice->clpRng(compID));
}
else
{
picRecoBuff.reconstruct(getPredBuf(carea), resiCS->getResiBuf(carea), slice->clpRng(compID));
}
return;
}
// 2.1. gdr interval dirty picture
PelBuf picRecoBuff0 = picture->getBuf(carea, PIC_RECONSTRUCTION_0);
if (lmcsEnable)
{
picRecoBuff0.rspSignal(getPredBuf(carea), pLUT);
picRecoBuff0.reconstruct(picRecoBuff0, resiCS->getResiBuf(carea), slice->clpRng(compID));
}
else
{
picRecoBuff0.reconstruct(getPredBuf(carea), resiCS->getResiBuf(carea), slice->clpRng(compID));
}
// 2.2. gdr interval clean picture
ChromaFormat chromaFormat = sps->getChromaFormatIdc();
int gdrEndX = picHeader->getGdrEndX() >> getComponentScaleX((ComponentID)compID, chromaFormat);
int gdrEndY = pps->getPicHeightInLumaSamples() >> getComponentScaleY((ComponentID)compID, chromaFormat);;
CompArea cleanArea = CompArea((ComponentID)compID, chromaFormat, Area(Position(0, 0), Size(gdrEndX, gdrEndY)));
CompArea overlappedArea = CompArea((ComponentID)compID, chromaFormat, findOverlappedArea(cleanArea, carea));
if (overlappedArea.area() > 0)
{
PelBuf picRecoBuff1 = picture->getBuf(overlappedArea, PIC_RECONSTRUCTION_1);
if (lmcsEnable)
{
picRecoBuff1.rspSignal(getPredBuf(overlappedArea), pLUT);
picRecoBuff1.reconstruct(picRecoBuff1, resiCS->getResiBuf(overlappedArea), slice->clpRng(compID));
}
else
{
picRecoBuff1.reconstruct(getPredBuf(overlappedArea), resiCS->getResiBuf(overlappedArea), slice->clpRng(compID));
}
}
}
#endif
bool CodingStructure::isDecomp( const Position &pos, const ChannelType effChType )
{
if( area.blocks[effChType].contains( pos ) )
{
return m_isDecomp[effChType][rsAddr( pos, area.blocks[effChType], area.blocks[effChType].width, unitScale[effChType] )];
}
else if( parent )
{
return parent->isDecomp( pos, effChType );
}
else
{
return false;
}
}
bool CodingStructure::isDecomp( const Position &pos, const ChannelType effChType ) const
{
if( area.blocks[effChType].contains( pos ) )
{
return m_isDecomp[effChType][rsAddr( pos, area.blocks[effChType], area.blocks[effChType].width, unitScale[effChType] )];
}
else if( parent )
{
return parent->isDecomp( pos, effChType );
}
else
{
return false;
}
}
void CodingStructure::setDecomp(const CompArea &_area, const bool _isCoded /*= true*/)
{
const UnitScale& scale = unitScale[_area.compID];
AreaBuf<bool> isCodedBlk( m_isDecomp[toChannelType( _area.compID )] + rsAddr( _area, area.blocks[_area.compID].pos(), area.blocks[_area.compID].width, scale ),
area.blocks[_area.compID].width >> scale.posx,
_area.width >> scale.posx,
_area.height >> scale.posy);
isCodedBlk.fill( _isCoded );
}
void CodingStructure::setDecomp(const UnitArea &_area, const bool _isCoded /*= true*/)
{
for( uint32_t i = 0; i < _area.blocks.size(); i++ )
{
if (_area.blocks[i].valid())
{
setDecomp(_area.blocks[i], _isCoded);
}
}
}
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
const int CodingStructure::signalModeCons( const PartSplit split, Partitioner &partitioner, const ModeType modeTypeParent ) const
{
if (CS::isDualITree(*this) || modeTypeParent != MODE_TYPE_ALL || partitioner.currArea().chromaFormat == CHROMA_444 || partitioner.currArea().chromaFormat == CHROMA_400 )
{
return LDT_MODE_TYPE_INHERIT;
}
int minLumaArea = partitioner.currArea().lumaSize().area();
if (split == CU_QUAD_SPLIT || split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT) // the area is split into 3 or 4 parts
{
minLumaArea = minLumaArea >> 2;
}
else if (split == CU_VERT_SPLIT || split == CU_HORZ_SPLIT) // the area is split into 2 parts
{
minLumaArea = minLumaArea >> 1;
}
int minChromaBlock = minLumaArea >> (getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, partitioner.currArea().chromaFormat) + getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, partitioner.currArea().chromaFormat));
bool is2xNChroma = (partitioner.currArea().chromaSize().width == 4 && split == CU_VERT_SPLIT) || (partitioner.currArea().chromaSize().width == 8 && split == CU_TRIV_SPLIT);
return minChromaBlock >= 16 && !is2xNChroma ? LDT_MODE_TYPE_INHERIT : ((minLumaArea < 32) || slice->isIntra()) ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
}
void CodingStructure::clearCuPuTuIdxMap(const UnitArea &_area, uint32_t numCu, uint32_t numPu, uint32_t numTu, uint32_t* pOffset )
{
UnitArea clippedArea = clipArea( _area, *picture );
uint32_t numCh = ::getNumberValidChannels( _area.chromaFormat );
for( uint32_t i = 0; i < numCh; i++ )
{
const CompArea &_selfBlk = area.blocks[i];
const CompArea &_blk = clippedArea.blocks[i];
const UnitScale& scale = unitScale[_blk.compID];
const Area scaledSelf = scale.scale( _selfBlk );
const Area scaledBlk = scale.scale( _blk );
const size_t offset = rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
unsigned *idxPtrCU = m_cuIdx[i] + offset;
AreaBuf<uint32_t>( idxPtrCU, scaledSelf.width, scaledBlk.size() ).fill( 0 );
unsigned *idxPtrPU = m_puIdx[i] + offset;
AreaBuf<uint32_t>( idxPtrPU, scaledSelf.width, scaledBlk.size() ).fill( 0 );
unsigned *idxPtrTU = m_tuIdx[i] + offset;
AreaBuf<uint32_t>( idxPtrTU, scaledSelf.width, scaledBlk.size() ).fill( 0 );
}
//pop cu/pu/tus
for( int i = m_numTUs; i > numTu; i-- )
{
m_tuCache.cache( tus.back() );
tus.pop_back();
m_numTUs--;
}
for( int i = m_numPUs; i > numPu; i-- )
{
m_puCache.cache( pus.back() );
pus.pop_back();
m_numPUs--;
}
for( int i = m_numCUs; i > numCu; i-- )
{
m_cuCache.cache( cus.back() );
cus.pop_back();
m_numCUs--;
}
for( int i = 0; i < 3; i++ )
{
m_offsets[i] = pOffset[i];
}
}
CodingUnit* CodingStructure::getLumaCU( const Position &pos )
{
const ChannelType effChType = CHANNEL_TYPE_LUMA;
const CompArea &_blk = area.blocks[effChType];
CHECK( !_blk.contains( pos ), "must contain the pos" );
const unsigned idx = m_cuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if (idx != 0)
{
return cus[idx - 1];
}
else
{
return nullptr;
}
}
#endif
CodingUnit* CodingStructure::getCU( const Position &pos, const ChannelType effChType )
{
const CompArea &_blk = area.blocks[effChType];
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (!_blk.contains(pos))
#else
if( !_blk.contains( pos ) || (treeType == TREE_C && effChType == CHANNEL_TYPE_LUMA) )
#endif
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
//keep this check, which is helpful to identify bugs
if( treeType == TREE_C && effChType == CHANNEL_TYPE_LUMA )
{
CHECK( parent == nullptr, "parent shall be valid; consider using function getLumaCU()" );
CHECK( parent->treeType != TREE_D, "wrong parent treeType " );
}
#endif
if (parent)
{
return parent->getCU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_cuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if (idx != 0)
{
return cus[idx - 1];
}
else
{
return nullptr;
}
}
}
const CodingUnit* CodingStructure::getCU( const Position &pos, const ChannelType effChType ) const
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
Size lumaSize = slice->getPic()->Y().lumaSize();
if( area.lumaSize() != lumaSize )
{
const Position posRB = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().bottomRight() : area.Cb().bottomRight();
const Position posTL = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().topLeft() : area.Cb().topLeft();
bool isTLClean = isClean( posTL, effChType );
bool isRBClean = isClean( posRB, effChType );
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean( pos, effChType );
if( isSrcClean && !isTarClean )
{
return nullptr;
}
}
}
#endif
const CompArea &_blk = area.blocks[effChType];
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (!_blk.contains(pos))
#else
if( !_blk.contains( pos ) || (treeType == TREE_C && effChType == CHANNEL_TYPE_LUMA) )
#endif
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( treeType == TREE_C && effChType == CHANNEL_TYPE_LUMA )
{
CHECK( parent == nullptr, "parent shall be valid; consider using function getLumaCU()" );
CHECK( parent->treeType != TREE_D, "wrong parent treeType" );
}
#endif
if (parent)
{
return parent->getCU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_cuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if (idx != 0)
{
return cus[idx - 1];
}
else
{
return nullptr;
}
}
}
PredictionUnit* CodingStructure::getPU( const Position &pos, const ChannelType effChType )
{
const CompArea &_blk = area.blocks[effChType];
if( !_blk.contains( pos ) )
{
if (parent)
{
return parent->getPU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_puIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if (idx != 0)
{
return pus[idx - 1];
}
else
{
return nullptr;
}
}
}
const PredictionUnit * CodingStructure::getPU( const Position &pos, const ChannelType effChType ) const
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
Size lumaSize = slice->getPic()->Y().lumaSize();
if( area.lumaSize() != lumaSize )
{
const Position posRB = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().bottomRight() : area.Cb().bottomRight();
const Position posTL = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().topLeft() : area.Cb().topLeft();
bool isTLClean = isClean( posTL, effChType );
bool isRBClean = isClean( posRB, effChType );
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean( pos, effChType );
if( isSrcClean && !isTarClean )
{
return nullptr;
}
}
}
#endif
const CompArea &_blk = area.blocks[effChType];
if( !_blk.contains( pos ) )
{
if (parent)
{
return parent->getPU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_puIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if (idx != 0)
{
return pus[idx - 1];
}
else
{
return nullptr;
}
}
}
TransformUnit* CodingStructure::getTU( const Position &pos, const ChannelType effChType, const int subTuIdx )
{
const CompArea &_blk = area.blocks[effChType];
if( !_blk.contains( pos ) )
{
if (parent)
{
return parent->getTU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_tuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if( idx != 0 )
{
unsigned extraIdx = 0;
if( isLuma( effChType ) )
{
const TransformUnit& tu = *tus[idx - 1];
if( tu.cu->ispMode ) // Intra SubPartitions mode
{
//we obtain the offset to index the corresponding sub-partition
if( subTuIdx != -1 )
{
extraIdx = subTuIdx;
}
else
{
while( !tus[idx - 1 + extraIdx]->blocks[getFirstComponentOfChannel( effChType )].contains( pos ) )
{
extraIdx++;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
CHECK( tus[idx - 1 + extraIdx]->cu->treeType == TREE_C, "tu searched by position points to a chroma tree CU" );
CHECK( extraIdx > 3, "extraIdx > 3" );
#endif
}
}
}
}
return tus[idx - 1 + extraIdx];
}
else if (m_isTuEnc)
{
return parent->getTU(pos, effChType);
}
else
{
return nullptr;
}
}
}
const TransformUnit * CodingStructure::getTU( const Position &pos, const ChannelType effChType, const int subTuIdx ) const
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
Size lumaSize = slice->getPic()->Y().lumaSize();
if( area.lumaSize() != lumaSize )
{
const Position posRB = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().bottomRight() : area.Cb().bottomRight();
const Position posTL = ( effChType == CHANNEL_TYPE_LUMA ) ? area.Y().topLeft() : area.Cb().topLeft();
bool isTLClean = isClean( posTL, effChType );
bool isRBClean = isClean( posRB, effChType );
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean( pos, effChType );
if( isSrcClean && !isTarClean )
{
return nullptr;
}
}
}
#endif
const CompArea &_blk = area.blocks[effChType];
if( !_blk.contains( pos ) )
{
if (parent)
{
return parent->getTU(pos, effChType);
}
else
{
return nullptr;
}
}
else
{
const unsigned idx = m_tuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if( idx != 0 )
{
unsigned extraIdx = 0;
if( isLuma( effChType ) )
{
const TransformUnit& tu = *tus[idx - 1];
if( tu.cu->ispMode ) // Intra SubPartitions mode
{
//we obtain the offset to index the corresponding sub-partition
if( subTuIdx != -1 )
{
extraIdx = subTuIdx;
}
else
{
while ( !tus[idx - 1 + extraIdx]->blocks[getFirstComponentOfChannel( effChType )].contains(pos) )
{
extraIdx++;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
CHECK( tus[idx - 1 + extraIdx]->cu->treeType == TREE_C, "tu searched by position points to a chroma tree CU" );
CHECK( extraIdx > 3, "extraIdx > 3" );
#endif
}
}
}
}
return tus[idx - 1 + extraIdx];
}
else if (m_isTuEnc)
{
return parent->getTU(pos, effChType);
}
else
{
return nullptr;
}
}
}
CodingUnit& CodingStructure::addCU( const UnitArea &unit, const ChannelType chType )
{
CodingUnit *cu = m_cuCache.get();
cu->UnitArea::operator=( unit );
cu->initData();
cu->cs = this;
cu->slice = nullptr;
cu->next = nullptr;
cu->firstPU = nullptr;
cu->lastPU = nullptr;
cu->firstTU = nullptr;
cu->lastTU = nullptr;
cu->chType = chType;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
cu->treeType = treeType;
cu->modeType = modeType;
#endif
CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr;
if( prevCU )
{
prevCU->next = cu;
#if ENABLE_SPLIT_PARALLELISM
CHECK( prevCU->cacheId != cu->cacheId, "Inconsintent cacheId between previous and current CU" );
#endif
}
cus.push_back( cu );
uint32_t idx = ++m_numCUs;
cu->idx = idx;
uint32_t numCh = ::getNumberValidChannels( area.chromaFormat );
for( uint32_t i = 0; i < numCh; i++ )
{
if( !cu->blocks[i].valid() )
{
continue;
}
const CompArea &_selfBlk = area.blocks[i];
const CompArea &_blk = cu-> blocks[i];
const UnitScale& scale = unitScale[_blk.compID];
const Area scaledSelf = scale.scale( _selfBlk );
const Area scaledBlk = scale.scale( _blk );
unsigned *idxPtr = m_cuIdx[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
CHECK( *idxPtr, "Overwriting a pre-existing value, should be '0'!" );
AreaBuf<uint32_t>( idxPtr, scaledSelf.width, scaledBlk.size() ).fill( idx );
}
return *cu;
}
PredictionUnit& CodingStructure::addPU( const UnitArea &unit, const ChannelType chType )
{
PredictionUnit *pu = m_puCache.get();
pu->UnitArea::operator=( unit );
pu->initData();
pu->next = nullptr;
pu->cs = this;
pu->cu = m_isTuEnc ? cus[0] : getCU( unit.blocks[chType].pos(), chType );
pu->chType = chType;
#if ENABLE_SPLIT_PARALLELISM
CHECK( pu->cacheId != pu->cu->cacheId, "Inconsintent cacheId between the PU and assigned CU" );
CHECK( pu->cu->firstPU != nullptr, "Without an RQT the firstPU should be null" );
#endif
PredictionUnit *prevPU = m_numPUs > 0 ? pus.back() : nullptr;
if( prevPU && prevPU->cu == pu->cu )
{
prevPU->next = pu;
#if ENABLE_SPLIT_PARALLELISM
CHECK( prevPU->cacheId != pu->cacheId, "Inconsintent cacheId between previous and current PU" );
#endif
}
pus.push_back( pu );
if( pu->cu->firstPU == nullptr )
{
pu->cu->firstPU = pu;
}
pu->cu->lastPU = pu;
uint32_t idx = ++m_numPUs;
pu->idx = idx;
uint32_t numCh = ::getNumberValidChannels( area.chromaFormat );
for( uint32_t i = 0; i < numCh; i++ )
{
if( !pu->blocks[i].valid() )
{
continue;
}
const CompArea &_selfBlk = area.blocks[i];
const CompArea &_blk = pu-> blocks[i];
const UnitScale& scale = unitScale[_blk.compID];
const Area scaledSelf = scale.scale( _selfBlk );
const Area scaledBlk = scale.scale( _blk );
unsigned *idxPtr = m_puIdx[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
CHECK( *idxPtr, "Overwriting a pre-existing value, should be '0'!" );
AreaBuf<uint32_t>( idxPtr, scaledSelf.width, scaledBlk.size() ).fill( idx );
}
return *pu;
}
TransformUnit& CodingStructure::addTU( const UnitArea &unit, const ChannelType chType )
{
TransformUnit *tu = m_tuCache.get();
tu->UnitArea::operator=( unit );
tu->initData();
tu->next = nullptr;
tu->prev = nullptr;
tu->cs = this;
tu->cu = m_isTuEnc ? cus[0] : getCU( unit.blocks[chType].pos(), chType );
tu->chType = chType;
#if ENABLE_SPLIT_PARALLELISM
if( tu->cu )
{
CHECK(tu->cacheId != tu->cu->cacheId, "Inconsintent cacheId between the TU and assigned CU");
}
#endif
TransformUnit *prevTU = m_numTUs > 0 ? tus.back() : nullptr;
if( prevTU && prevTU->cu == tu->cu )
{
prevTU->next = tu;
tu->prev = prevTU;
#if ENABLE_SPLIT_PARALLELISM
CHECK( prevTU->cacheId != tu->cacheId, "Inconsintent cacheId between previous and current TU" );
#endif
}
tus.push_back( tu );
if( tu->cu )
{
if( tu->cu->firstTU == nullptr )
{
tu->cu->firstTU = tu;
}
tu->cu->lastTU = tu;
}
uint32_t idx = ++m_numTUs;
tu->idx = idx;
TCoeff *coeffs[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
#if SIGN_PREDICTION
TCoeff *signs[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
#if JVET_Y0141_SIGN_PRED_IMPROVE
unsigned *signsScanIdx[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
#endif
#endif
#if REMOVE_PCM
Pel *pltIdx[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
#else
Pel *pcmbuf[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
#endif
bool *runType[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
uint32_t numCh = ::getNumberValidComponents( area.chromaFormat );
for (uint32_t i = 0; i < numCh; i++)
{
if (!tu->blocks[i].valid())
{
continue;
}
if (i < ::getNumberValidChannels(area.chromaFormat))
{
const CompArea &_selfBlk = area.blocks[i];
const CompArea &_blk = tu->blocks[i];
bool isIspTu = tu->cu != nullptr && tu->cu->ispMode && isLuma(_blk.compID);
bool isFirstIspTu = false;
if (isIspTu)
{
isFirstIspTu = CU::isISPFirst(*tu->cu, _blk, getFirstComponentOfChannel(ChannelType(i)));
}
if (!isIspTu || isFirstIspTu)
{
const UnitScale& scale = unitScale[_blk.compID];
const Area scaledSelf = scale.scale(_selfBlk);
const Area scaledBlk = isIspTu ? scale.scale(tu->cu->blocks[i]) : scale.scale(_blk);
unsigned *idxPtr = m_tuIdx[i] + rsAddr(scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width);
CHECK(*idxPtr, "Overwriting a pre-existing value, should be '0'!");
AreaBuf<uint32_t>(idxPtr, scaledSelf.width, scaledBlk.size()).fill(idx);
}
}
coeffs[i] = m_coeffs[i] + m_offsets[i];
#if SIGN_PREDICTION
signs[i] = m_coeffSigns[i] + m_offsets[i];
#if JVET_Y0141_SIGN_PRED_IMPROVE
signsScanIdx[i] = m_coeffSignsIdx[i] + m_offsets[i];
#endif
#endif
#if !REMOVE_PCM
pcmbuf[i] = m_pcmbuf[i] + m_offsets[i];
#endif
if (i < MAX_NUM_CHANNEL_TYPE)
{
#if REMOVE_PCM
if (m_pltIdx[i] != nullptr)
{
pltIdx[i] = m_pltIdx[i] + m_offsets[i];
}
#endif
if (m_runType[i] != nullptr)
{
runType[i] = m_runType[i] + m_offsets[i];
}
}
unsigned areaSize = tu->blocks[i].area();
m_offsets[i] += areaSize;
}
#if REMOVE_PCM
#if SIGN_PREDICTION
#if JVET_Y0141_SIGN_PRED_IMPROVE
tu->init(coeffs, signs, signsScanIdx, pltIdx, runType);
#else
tu->init(coeffs, signs, pltIdx, runType);
#endif
#else
tu->init(coeffs, pltIdx, runType);
#endif
#else
#if SIGN_PREDICTION
#if JVET_Y0141_SIGN_PRED_IMPROVE
tu->init(coeffs, signs, signsScanIdx, pcmbuf, runType);
#else
tu->init(coeffs, signs, pcmbuf, runType);
#endif
#else
tu->init(coeffs, pcmbuf, runType);
#endif
#endif
return *tu;
}
void CodingStructure::addEmptyTUs( Partitioner &partitioner )
{
const UnitArea& area = partitioner.currArea();
bool split = partitioner.canSplit(TU_MAX_TR_SPLIT, *this);
const unsigned trDepth = partitioner.currTrDepth;
if( split )
{
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, *this );
do
{
addEmptyTUs( partitioner );
} while( partitioner.nextPart( *this ) );
partitioner.exitCurrSplit();
}
else
{
TransformUnit &tu = this->addTU( CS::getArea( *this, area, partitioner.chType ), partitioner.chType );
unsigned numBlocks = ::getNumberValidTBlocks( *this->pcv );
for( unsigned compID = COMPONENT_Y; compID < numBlocks; compID++ )
{
if( tu.blocks[compID].valid() )
{
tu.getCoeffs( ComponentID( compID ) ).fill( 0 );
#if !REMOVE_PCM
tu.getPcmbuf( ComponentID( compID ) ).fill( 0 );
#endif
}
}
tu.depth = trDepth;
}
}
CUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType )
{
CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
CodingUnit* lastCU = firstCU;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( !CS::isDualITree( *this ) ) //for a more generalized separate tree
{
bool bContinue = true;
CodingUnit* currCU = firstCU;
while( bContinue )
{
if( currCU == nullptr )
{
bContinue = false;
lastCU = currCU;
}
else if( currCU->chType != effChType )
{
lastCU = currCU;
currCU = currCU->next;
}
else
{
if( unit.contains( *currCU ) )
{
lastCU = currCU;
currCU = currCU->next;
}
else
{
bContinue = false;
lastCU = currCU;
}
}
}
}
else
{
#endif
do
{
} while (lastCU && (lastCU = lastCU->next) && unit.contains(*lastCU));
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
}
#endif
return CUTraverser( firstCU, lastCU );
}
PUTraverser CodingStructure::traversePUs( const UnitArea& unit, const ChannelType effChType )
{
PredictionUnit* firstPU = getPU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
PredictionUnit* lastPU = firstPU;
do { } while( lastPU && ( lastPU = lastPU->next ) && unit.contains( *lastPU ) );
return PUTraverser( firstPU, lastPU );
}
TUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType )
{
TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
TransformUnit* lastTU = firstTU;
do { } while( lastTU && ( lastTU = lastTU->next ) && unit.contains( *lastTU ) );
return TUTraverser( firstTU, lastTU );
}
cCUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType ) const
{
const CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
const CodingUnit* lastCU = firstCU;
do { } while( lastCU && ( lastCU = lastCU->next ) && unit.contains( *lastCU ) );
return cCUTraverser( firstCU, lastCU );
}
cPUTraverser CodingStructure::traversePUs( const UnitArea& unit, const ChannelType effChType ) const
{
const PredictionUnit* firstPU = getPU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
const PredictionUnit* lastPU = firstPU;
do { } while( lastPU && ( lastPU = lastPU->next ) && unit.contains( *lastPU ) );
return cPUTraverser( firstPU, lastPU );
}
cTUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType ) const
{
const TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
const TransformUnit* lastTU = firstTU;
do { } while( lastTU && ( lastTU = lastTU->next ) && unit.contains( *lastTU ) );
return cTUTraverser( firstTU, lastTU );
}
// coding utilities
void CodingStructure::allocateVectorsAtPicLevel()
{
const int twice = ( !pcv->ISingleTree && slice->isIRAP() && pcv->chrFormat != CHROMA_400 ) ? 2 : 1;
size_t allocSize = twice * unitScale[0].scale( area.blocks[0].size() ).area();
cus.reserve( allocSize );
pus.reserve( allocSize );
tus.reserve( allocSize );
}
#if JVET_Z0118_GDR
void CodingStructure::create(const ChromaFormat &_chromaFormat, const Area& _area, const bool isTopLayer, const bool isPLTused, const bool isGdrEnabled)
#else
void CodingStructure::create(const ChromaFormat &_chromaFormat, const Area& _area, const bool isTopLayer, const bool isPLTused)
#endif
{
#if JVET_Z0118_GDR
m_gdrEnabled = isGdrEnabled;
#endif
createInternals(UnitArea(_chromaFormat, _area), isTopLayer, isPLTused);
if (isTopLayer)
{
return;
}
#if JVET_Z0118_GDR
m_pt = PIC_RECONSTRUCTION_0;
m_reco0.create(area);
if (m_gdrEnabled)
{
m_reco1.create(area);
picHeader = new PicHeader();
picHeader->initPicHeader();
}
#else
m_reco.create( area );
#endif
m_pred.create( area );
m_resi.create( area );
m_orgr.create( area );
}
#if JVET_Z0118_GDR
void CodingStructure::create(const UnitArea& _unit, const bool isTopLayer, const bool isPLTused, const bool isGdrEnabled)
#else
void CodingStructure::create(const UnitArea& _unit, const bool isTopLayer, const bool isPLTused)
#endif
{
#if JVET_Z0118_GDR
m_gdrEnabled = isGdrEnabled;
#endif
createInternals(_unit, isTopLayer, isPLTused);
if (isTopLayer)
{
return;
}
#if JVET_Z0118_GDR
m_pt = PIC_RECONSTRUCTION_0;
m_reco0.create(area);
if (m_gdrEnabled)
{
m_reco1.create(area);
picHeader = new PicHeader();
picHeader->initPicHeader();
}
#else
m_reco.create( area );
#endif
m_pred.create( area );
m_resi.create( area );
m_orgr.create( area );
}
void CodingStructure::createInternals(const UnitArea& _unit, const bool isTopLayer, const bool isPLTused)
{
area = _unit;
memcpy( unitScale, UnitScaleArray[area.chromaFormat], sizeof( unitScale ) );
picture = nullptr;
parent = nullptr;
unsigned numCh = ::getNumberValidChannels(area.chromaFormat);
for (unsigned i = 0; i < numCh; i++)
{
unsigned _area = unitScale[i].scale( area.blocks[i].size() ).area();
m_cuIdx[i] = _area > 0 ? new unsigned[_area] : nullptr;
m_puIdx[i] = _area > 0 ? new unsigned[_area] : nullptr;
m_tuIdx[i] = _area > 0 ? new unsigned[_area] : nullptr;
m_isDecomp[i] = _area > 0 ? new bool [_area] : nullptr;
}
numCh = getNumberValidComponents(area.chromaFormat);
for (unsigned i = 0; i < numCh; i++)
{
m_offsets[i] = 0;
}
if( !isTopLayer ) createCoeffs(isPLTused);
unsigned _lumaAreaScaled = g_miScaling.scale( area.lumaSize() ).area();
#if JVET_Z0118_GDR
m_motionBuf0 = new MotionInfo[_lumaAreaScaled];
if (m_gdrEnabled)
{
m_motionBuf1 = new MotionInfo[_lumaAreaScaled];
}
#else
m_motionBuf = new MotionInfo[_lumaAreaScaled];
#endif
#if JVET_W0123_TIMD_FUSION
#if JVET_Z0118_GDR
m_ipmBuf0 = new uint8_t[_lumaAreaScaled];
if (m_gdrEnabled)
{
m_ipmBuf1 = new uint8_t[_lumaAreaScaled];
}
#else
m_ipmBuf = new uint8_t[_lumaAreaScaled];
#endif
#endif // JVET_W0123_TIMD_FUSION
#if JVET_Z0136_OOB
int extendLumaArea = area.lumaSize().area();
for (unsigned i = 0; i < 2; i++)
{
mcMask[i] = (bool*)xMalloc(bool, extendLumaArea);
mcMaskChroma[i] = (bool*)xMalloc(bool, extendLumaArea);
}
#endif
initStructData();
}
void CodingStructure::addMiToLut(static_vector<MotionInfo, MAX_NUM_HMVP_CANDS> &lut, const MotionInfo &mi)
{
size_t currCnt = lut.size();
bool pruned = false;
int sameCandIdx = 0;
for (int idx = 0; idx < currCnt; idx++)
{
if (lut[idx] == mi)
{
sameCandIdx = idx;
pruned = true;
break;
}
}
if (pruned || currCnt == lut.capacity())
{
lut.erase(lut.begin() + sameCandIdx);
}
lut.push_back(mi);
}
#if JVET_Z0139_HIST_AFF
void CodingStructure::addAffMiToLut(static_vector<AffineMotionInfo, MAX_NUM_AFF_HMVP_CANDS>* lutSet, const AffineMotionInfo addMi[2], int refIdx[2])
{
for (int reflist = 0; reflist < 2; reflist++)
{
if (refIdx[reflist] != -1 && addMi[reflist].oneSetAffineParametersPattern != 0)
{
int idxInLUT = reflist * MAX_NUM_AFFHMVP_ENTRIES_ONELIST + std::min(refIdx[reflist], MAX_NUM_AFFHMVP_ENTRIES_ONELIST - 1);
static_vector<AffineMotionInfo, MAX_NUM_AFF_HMVP_CANDS>& lut = lutSet[idxInLUT];
size_t currCnt = lut.size();
bool pruned = false;
int sameCandIdx = 0;
for (int idx = 0; idx < currCnt; idx++)
{
if (lut[idx] == addMi[reflist])
{
sameCandIdx = idx;
pruned = true;
break;
}
}
if (pruned || currCnt == lut.capacity())
{
lut.erase(lut.begin() + sameCandIdx);
}
lut.push_back(addMi[reflist]);
}
}
}
void CodingStructure::addAffInheritToLut(static_vector<AffineInheritInfo, MAX_NUM_AFF_INHERIT_HMVP_CANDS>& lut, const AffineInheritInfo& mi)
{
size_t currCnt = lut.size();
bool pruned = false;
int sameCandIdx = 0;
for (int idx = 0; idx < currCnt; idx++)
{
if (lut[idx] == mi)
{
sameCandIdx = idx;
pruned = true;
break;
}
}
if (pruned || currCnt == lut.capacity())
{
lut.erase(lut.begin() + sameCandIdx);
}
lut.push_back(mi);
}
#endif
#if JVET_Z0075_IBC_HMVP_ENLARGE
void CodingStructure::addMiToLutIBC(static_vector<MotionInfo, MAX_NUM_HMVP_IBC_CANDS> &lut, const MotionInfo &mi)
{
size_t currCnt = lut.size();
bool pruned = false;
int sameCandIdx = 0;
for (int idx = 0; idx < currCnt; idx++)
{
if (lut[idx] == mi)
{
sameCandIdx = idx;
pruned = true;
break;
}
}
if (pruned || currCnt == lut.capacity())
{
lut.erase(lut.begin() + sameCandIdx);
}
lut.push_back(mi);
}
#endif
void CodingStructure::resetPrevPLT(PLTBuf& prevPLT)
{
for (int comp = 0; comp < MAX_NUM_CHANNEL_TYPE; comp++)
{
prevPLT.curPLTSize[comp] = 0;
}
for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
{
memset(prevPLT.curPLT[comp], 0, MAXPLTPREDSIZE * sizeof(Pel));
}
}
void CodingStructure::reorderPrevPLT(PLTBuf& prevPLT, uint8_t curPLTSize[MAX_NUM_CHANNEL_TYPE], Pel curPLT[MAX_NUM_COMPONENT][MAXPLTSIZE], bool reuseflag[MAX_NUM_CHANNEL_TYPE][MAXPLTPREDSIZE], uint32_t compBegin, uint32_t numComp, bool jointPLT)
{
Pel stuffedPLT[MAX_NUM_COMPONENT][MAXPLTPREDSIZE];
uint8_t tempCurPLTsize[MAX_NUM_CHANNEL_TYPE];
uint8_t stuffPLTsize[MAX_NUM_COMPONENT];
uint32_t maxPredPltSize = jointPLT ? MAXPLTPREDSIZE : MAXPLTPREDSIZE_DUALTREE;
for (int i = compBegin; i < (compBegin + numComp); i++)
{
ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);
tempCurPLTsize[comID] = curPLTSize[comID];
stuffPLTsize[i] = 0;
memcpy(stuffedPLT[i], curPLT[i], curPLTSize[comID] * sizeof(Pel));
}
for (int ch = compBegin; ch < (compBegin + numComp); ch++)
{
ComponentID comID = jointPLT ? (ComponentID)compBegin : ((ch > 0) ? COMPONENT_Cb : COMPONENT_Y);
if (ch > 1) break;
for (int i = 0; i < prevPLT.curPLTSize[comID]; i++)
{
if (tempCurPLTsize[comID] + stuffPLTsize[ch] >= maxPredPltSize)
{
break;
}
if (!reuseflag[comID][i])
{
if (ch == COMPONENT_Y)
{
stuffedPLT[0][tempCurPLTsize[comID] + stuffPLTsize[ch]] = prevPLT.curPLT[0][i];
}
else
{
stuffedPLT[1][tempCurPLTsize[comID] + stuffPLTsize[ch]] = prevPLT.curPLT[1][i];
stuffedPLT[2][tempCurPLTsize[comID] + stuffPLTsize[ch]] = prevPLT.curPLT[2][i];
}
stuffPLTsize[ch]++;
}
}
}
for (int i = compBegin; i < (compBegin + numComp); i++)
{
ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);
prevPLT.curPLTSize[comID] = curPLTSize[comID] + stuffPLTsize[comID];
memcpy(prevPLT.curPLT[i], stuffedPLT[i], prevPLT.curPLTSize[comID] * sizeof(Pel));
CHECK(prevPLT.curPLTSize[comID] > maxPredPltSize, " Maximum palette predictor size exceed limit");
}
}
void CodingStructure::setPrevPLT(PLTBuf predictor)
{
for (int comp = 0; comp < MAX_NUM_CHANNEL_TYPE; comp++)
{
prevPLT.curPLTSize[comp] = predictor.curPLTSize[comp];
}
for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
{
memcpy(prevPLT.curPLT[comp], predictor.curPLT[comp], MAXPLTPREDSIZE * sizeof(Pel));
}
}
void CodingStructure::storePrevPLT(PLTBuf& predictor)
{
for (int comp = 0; comp < MAX_NUM_CHANNEL_TYPE; comp++)
{
predictor.curPLTSize[comp] = prevPLT.curPLTSize[comp];
}
for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
{
memcpy(predictor.curPLT[comp], prevPLT.curPLT[comp], MAXPLTPREDSIZE * sizeof(Pel));
}
}
void CodingStructure::rebindPicBufs()
{
CHECK( parent, "rebindPicBufs can only be used for the top level CodingStructure" );
#if JVET_Z0118_GDR
if (!picture->M_BUFS(0, PIC_RECONSTRUCTION).bufs.empty())
{
m_pt = PIC_RECONSTRUCTION_0;
m_reco0.createFromBuf(picture->M_BUFS(0, PIC_RECONSTRUCTION_0));
if (m_gdrEnabled)
{
m_reco1.createFromBuf(picture->M_BUFS(0, PIC_RECONSTRUCTION_1));
}
}
else
{
m_reco0.destroy();
if (m_gdrEnabled)
{
m_reco1.destroy();
}
}
#else
if (!picture->M_BUFS(0, PIC_RECONSTRUCTION).bufs.empty())
{
m_reco.createFromBuf(picture->M_BUFS(0, PIC_RECONSTRUCTION));
}
else
{
m_reco.destroy();
}
#endif
if (!picture->M_BUFS(0, PIC_PREDICTION).bufs.empty())
{
m_pred.createFromBuf(picture->M_BUFS(0, PIC_PREDICTION));
}
else
{
m_pred.destroy();
}
if (!picture->M_BUFS(0, PIC_RESIDUAL).bufs.empty())
{
m_resi.createFromBuf(picture->M_BUFS(0, PIC_RESIDUAL));
}
else
{
m_resi.destroy();
}
if( pcv->isEncoder )
{
if (!picture->M_BUFS(0, PIC_RESIDUAL).bufs.empty())
{
m_orgr.create(area.chromaFormat, area.blocks[0], pcv->maxCUWidth);
}
else
{
m_orgr.destroy();
}
}
}
void CodingStructure::createCoeffs(const bool isPLTused)
{
const unsigned numCh = getNumberValidComponents( area.chromaFormat );
for( unsigned i = 0; i < numCh; i++ )
{
unsigned _area = area.blocks[i].area();
m_coeffs[i] = _area > 0 ? ( TCoeff* ) xMalloc( TCoeff, _area ) : nullptr;
#if SIGN_PREDICTION
m_coeffSigns[i] = _area > 0 ? ( TCoeff* ) xMalloc( TCoeff, _area ) : nullptr;
#if JVET_Y0141_SIGN_PRED_IMPROVE
m_coeffSignsIdx[i] = _area > 0 ? (unsigned*)xMalloc(unsigned, _area) : nullptr;
#endif
#endif
#if !REMOVE_PCM
m_pcmbuf[i] = _area > 0 ? ( Pel* ) xMalloc( Pel, _area ) : nullptr;
#endif
}
if (isPLTused)
{
for (unsigned i = 0; i < (isChromaEnabled(area.chromaFormat) ? 2 : 1); i++)
{
unsigned _area = area.blocks[i].area();
#if REMOVE_PCM
m_pltIdx[i] = _area > 0 ? (Pel*)xMalloc(Pel, _area) : nullptr;
#endif
m_runType[i] = _area > 0 ? (bool*)xMalloc(bool, _area) : nullptr;
}
}
}
void CodingStructure::destroyCoeffs()
{
for( uint32_t i = 0; i < MAX_NUM_COMPONENT; i++ )
{
if (m_coeffs[i])
{
xFree(m_coeffs[i]);
m_coeffs[i] = nullptr;
}
#if SIGN_PREDICTION
if( m_coeffSigns[i] )
{
xFree( m_coeffSigns[i] );
m_coeffSigns[i] = nullptr;
}
#if JVET_Y0141_SIGN_PRED_IMPROVE
if (m_coeffSignsIdx[i])
{
xFree(m_coeffSignsIdx[i]);
m_coeffSignsIdx[i] = nullptr;
}
#endif
#endif
#if !REMOVE_PCM
if (m_pcmbuf[i])
{
xFree(m_pcmbuf[i]);
m_pcmbuf[i] = nullptr;
}
#endif
}
for (uint32_t i = 0; i < MAX_NUM_CHANNEL_TYPE; i++)
{
#if REMOVE_PCM
if (m_pltIdx[i])
{
xFree(m_pltIdx[i]);
m_pltIdx[i] = nullptr;
}
#endif
if (m_runType[i])
{
xFree(m_runType[i]);
m_runType[i] = nullptr;
}
}
}
void CodingStructure::initSubStructure( CodingStructure& subStruct, const ChannelType _chType, const UnitArea &subArea, const bool &isTuEnc )
{
CHECK( this == &subStruct, "Trying to init self as sub-structure" );
subStruct.useDbCost = false;
subStruct.costDbOffset = 0;
for( uint32_t i = 0; i < subStruct.area.blocks.size(); i++ )
{
CHECKD( subStruct.area.blocks[i].size() != subArea.blocks[i].size(), "Trying to init sub-structure of incompatible size" );
subStruct.area.blocks[i].pos() = subArea.blocks[i].pos();
}
if( parent )
{
// allow this to be false at the top level (need for edge CTU's)
CHECKD( !area.contains( subStruct.area ), "Trying to init sub-structure not contained in the parent" );
}
subStruct.parent = this;
subStruct.picture = picture;
subStruct.sps = sps;
subStruct.vps = vps;
subStruct.pps = pps;
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
if (!subStruct.picHeader)
{
subStruct.picHeader = new PicHeader;
subStruct.picHeader->initPicHeader();
}
*subStruct.picHeader = *picHeader;
}
else
{
subStruct.picHeader = picHeader;
}
#else
subStruct.picHeader = picHeader;
#endif
memcpy(subStruct.alfApss, alfApss, sizeof(alfApss));
subStruct.lmcsAps = lmcsAps;
subStruct.scalinglistAps = scalinglistAps;
subStruct.slice = slice;
subStruct.baseQP = baseQP;
subStruct.prevQP[_chType]
= prevQP[_chType];
subStruct.pcv = pcv;
subStruct.m_isTuEnc = isTuEnc;
subStruct.motionLut = motionLut;
subStruct.prevPLT = prevPLT;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
subStruct.treeType = treeType;
subStruct.modeType = modeType;
#endif
subStruct.initStructData( currQP[_chType] );
if( isTuEnc )
{
CHECKD( area != subStruct.area, "Trying to init sub-structure for TU-encoding of incompatible size" );
for( const auto &pcu : cus )
{
CodingUnit &cu = subStruct.addCU( *pcu, _chType );
cu = *pcu;
}
for( const auto &ppu : pus )
{
PredictionUnit &pu = subStruct.addPU( *ppu, _chType );
pu = *ppu;
}
unsigned numComp = ::getNumberValidChannels( area.chromaFormat );
for( unsigned i = 0; i < numComp; i++)
{
::memcpy( subStruct.m_isDecomp[i], m_isDecomp[i], (unitScale[i].scale( area.blocks[i].size() ).area() * sizeof( bool ) ) );
}
}
#if JVET_Z0118_GDR
subStruct.m_pt = m_pt;
#endif
}
void CodingStructure::useSubStructure( const CodingStructure& subStruct, const ChannelType chType, const UnitArea &subArea, const bool cpyPred /*= true*/, const bool cpyReco /*= true*/, const bool cpyOrgResi /*= true*/, const bool cpyResi /*= true*/, const bool updateCost /*= true*/ )
{
UnitArea clippedArea = clipArea( subArea, *picture );
setDecomp( clippedArea );
CPelUnitBuf subPredBuf = cpyPred ? subStruct.getPredBuf( clippedArea ) : CPelUnitBuf();
CPelUnitBuf subResiBuf = cpyResi ? subStruct.getResiBuf( clippedArea ) : CPelUnitBuf();
CPelUnitBuf subRecoBuf = cpyReco ? subStruct.getRecoBuf( clippedArea ) : CPelUnitBuf();
if( parent )
{
// copy data to picture
if( cpyPred ) getPredBuf ( clippedArea ).copyFrom( subPredBuf );
#if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
if (cpyResi)
{
getResiBuf(clippedArea).copyFrom(subResiBuf);
}
else
{
getResiBuf(clippedArea).copyFrom(subStruct.getResiBuf(clippedArea), true);
}
#else
if( cpyResi ) getResiBuf ( clippedArea ).copyFrom( subResiBuf );
#endif
if( cpyReco ) getRecoBuf ( clippedArea ).copyFrom( subRecoBuf );
if( cpyOrgResi ) getOrgResiBuf( clippedArea ).copyFrom( subStruct.getOrgResiBuf( clippedArea ) );
}
if( cpyPred ) picture->getPredBuf( clippedArea ).copyFrom( subPredBuf );
#if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
if (cpyResi)
{
picture->getResiBuf(clippedArea).copyFrom(subResiBuf);
}
else
{
picture->getResiBuf(clippedArea).copyFrom(subStruct.getResiBuf(clippedArea), true);
}
#else
if( cpyResi ) picture->getResiBuf( clippedArea ).copyFrom( subResiBuf );
#endif
#if JVET_Z0118_GDR
if (isInGdrIntervalOrRecoveryPoc())
{
if (cpyReco)
{
updateReconMotIPM(clippedArea, subRecoBuf); // xcomrpessCU - need
}
}
else
{
if (cpyReco)
{
picture->getRecoBuf(clippedArea).copyFrom(subRecoBuf);
}
}
#else
if (cpyReco)
{
picture->getRecoBuf(clippedArea).copyFrom(subRecoBuf);
}
#endif
#if JVET_AB0061_ITMP_BV_FOR_IBC
if (!subStruct.m_isTuEnc && ((!slice->isIntra() || slice->getSPS()->getIBCFlag() || slice->getSPS()->getUseIntraTMP()) && chType != CHANNEL_TYPE_CHROMA))
#else
if (!subStruct.m_isTuEnc && ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && chType != CHANNEL_TYPE_CHROMA))
#endif
{
// copy motion buffer
MotionBuf ownMB = getMotionBuf ( clippedArea );
CMotionBuf subMB = subStruct.getMotionBuf( clippedArea );
ownMB.copyFrom( subMB );
motionLut = subStruct.motionLut;
}
#if JVET_W0123_TIMD_FUSION
if (!subStruct.m_isTuEnc && chType != CHANNEL_TYPE_CHROMA)
{
IpmBuf ownIB = getIpmBuf ( clippedArea );
CIpmBuf subIB = subStruct.getIpmBuf( clippedArea );
ownIB.copyFrom( subIB );
}
#endif
prevPLT = subStruct.prevPLT;
if ( updateCost )
{
fracBits += subStruct.fracBits;
dist += subStruct.dist;
cost += subStruct.cost;
costDbOffset += subStruct.costDbOffset;
}
if( parent )
{
// allow this to be false at the top level
CHECKD( !area.contains( subArea ), "Trying to use a sub-structure not contained in self" );
}
// copy the CUs over
if( subStruct.m_isTuEnc )
{
// don't copy if the substruct was created for encoding of the TUs
}
else
{
for( const auto &pcu : subStruct.cus )
{
// add an analogue CU into own CU store
const UnitArea &cuPatch = *pcu;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
CodingUnit &cu = addCU( cuPatch, pcu->chType );
#else
CodingUnit &cu = addCU(cuPatch, chType);
#endif
// copy the CU info from subPatch
cu = *pcu;
}
}
// copy the PUs over
if( subStruct.m_isTuEnc )
{
// don't copy if the substruct was created for encoding of the TUs
}
else
{
for( const auto &ppu : subStruct.pus )
{
// add an analogue PU into own PU store
const UnitArea &puPatch = *ppu;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
PredictionUnit &pu = addPU( puPatch, ppu->chType );
#else
PredictionUnit &pu = addPU(puPatch, chType);
#endif
// copy the PU info from subPatch
pu = *ppu;
}
}
// copy the TUs over
for( const auto &ptu : subStruct.tus )
{
// add an analogue TU into own TU store
const UnitArea &tuPatch = *ptu;
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
TransformUnit &tu = addTU( tuPatch, ptu->chType );
#else
TransformUnit &tu = addTU(tuPatch, chType);
#endif
// copy the TU info from subPatch
tu = *ptu;
}
}
void CodingStructure::copyStructure( const CodingStructure& other, const ChannelType chType, const bool copyTUs, const bool copyRecoBuf )
{
fracBits = other.fracBits;
dist = other.dist;
cost = other.cost;
costDbOffset = other.costDbOffset;
CHECKD( area != other.area, "Incompatible sizes" );
const UnitArea dualITreeArea = CS::getArea( *this, this->area, chType );
#if JVET_Z0118_GDR
m_pt = other.m_pt;
#endif
// copy the CUs over
for (const auto &pcu : other.cus)
{
if( !dualITreeArea.contains( *pcu ) )
{
continue;
}
// add an analogue CU into own CU store
const UnitArea &cuPatch = *pcu;
CodingUnit &cu = addCU(cuPatch, pcu->chType);
// copy the CU info from subPatch
cu = *pcu;
}
// copy the PUs over
for (const auto &ppu : other.pus)
{
if( !dualITreeArea.contains( *ppu ) )
{
continue;
}
// add an analogue PU into own PU store
const UnitArea &puPatch = *ppu;
PredictionUnit &pu = addPU(puPatch, ppu->chType);
// copy the PU info from subPatch
pu = *ppu;
}
#if JVET_AB0061_ITMP_BV_FOR_IBC
if (!other.slice->isIntra() || other.slice->getSPS()->getIBCFlag() || other.slice->getSPS()->getUseIntraTMP() )
#else
if (!other.slice->isIntra() || other.slice->getSPS()->getIBCFlag())
#endif
{
// copy motion buffer
MotionBuf ownMB = getMotionBuf();
CMotionBuf subMB = other.getMotionBuf();
ownMB.copyFrom( subMB );
motionLut = other.motionLut;
}
#if JVET_W0123_TIMD_FUSION
IpmBuf ownIB = getIpmBuf();
CIpmBuf subIB = other.getIpmBuf();
ownIB.copyFrom( subIB );
#endif
prevPLT = other.prevPLT;
if( copyTUs )
{
// copy the TUs over
for( const auto &ptu : other.tus )
{
if( !dualITreeArea.contains( *ptu ) )
{
continue;
}
// add an analogue TU into own TU store
const UnitArea &tuPatch = *ptu;
TransformUnit &tu = addTU( tuPatch, ptu->chType );
// copy the TU info from subPatch
tu = *ptu;
}
}
if( copyRecoBuf )
{
CPelUnitBuf recoBuf = other.getRecoBuf( area );
if( parent )
{
// copy data to self for neighbors
getRecoBuf( area ).copyFrom( recoBuf );
}
// copy data to picture
#if JVET_Z0118_GDR
if (isInGdrIntervalOrRecoveryPoc())
{
updateReconMotIPM(area, recoBuf); // xcomrpessCU - need
}
else
{
picture->getRecoBuf(area).copyFrom(recoBuf);
}
#else
picture->getRecoBuf(area).copyFrom(recoBuf);
#endif
if (other.pcv->isEncoder)
{
CPelUnitBuf predBuf = other.getPredBuf(area);
if (parent)
{
getPredBuf(area).copyFrom(predBuf);
}
picture->getPredBuf(area).copyFrom(predBuf);
}
// required for DebugCTU
int numCh = ::getNumberValidChannels( area.chromaFormat );
for( int i = 0; i < numCh; i++ )
{
const size_t _area = unitScale[i].scaleArea( area.blocks[i].area() );
memcpy( m_isDecomp[i], other.m_isDecomp[i], sizeof( *m_isDecomp[0] ) * _area );
}
}
}
void CodingStructure::initStructData( const int &QP, const bool &skipMotBuf )
{
clearPUs();
clearTUs();
clearCUs();
if( QP < MAX_INT )
{
currQP[0] = currQP[1] = QP;
}
#if JVET_AB0061_ITMP_BV_FOR_IBC
if (!skipMotBuf && (!parent || ((!slice->isIntra() || slice->getSPS()->getIBCFlag() || slice->getSPS()->getUseIntraTMP()) && !m_isTuEnc)))
#else
if (!skipMotBuf && (!parent || ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && !m_isTuEnc)))
#endif
{
#if JVET_Z0118_GDR
getMotionBuf(PIC_RECONSTRUCTION_0).memset(0);
if (m_gdrEnabled)
{
getMotionBuf(PIC_RECONSTRUCTION_1).memset(0);
}
#else
getMotionBuf().memset(0);
#endif
}
#if JVET_W0123_TIMD_FUSION
#if JVET_Z0118_GDR
getIpmBuf(PIC_RECONSTRUCTION_0).memset(0);
if (m_gdrEnabled)
{
getIpmBuf(PIC_RECONSTRUCTION_1).memset(0);
}
#else
getIpmBuf().memset(0);
#endif
#endif
fracBits = 0;
dist = 0;
cost = MAX_DOUBLE;
lumaCost = MAX_DOUBLE;
costDbOffset = 0;
useDbCost = false;
interHad = std::numeric_limits<Distortion>::max();
#if JVET_Z0118_GDR
m_pt = PIC_RECONSTRUCTION_0;
#endif
#if MULTI_HYP_PRED
m_meResults.clear();
#endif
}
void CodingStructure::clearTUs()
{
int numCh = ::getNumberValidChannels( area.chromaFormat );
for( int i = 0; i < numCh; i++ )
{
size_t _area = ( area.blocks[i].area() >> unitScale[i].area );
memset( m_isDecomp[i], false, sizeof( *m_isDecomp[0] ) * _area );
memset( m_tuIdx [i], 0, sizeof( *m_tuIdx [0] ) * _area );
}
numCh = getNumberValidComponents( area.chromaFormat );
for( int i = 0; i < numCh; i++ )
{
m_offsets[i] = 0;
}
for( auto &pcu : cus )
{
pcu->firstTU = pcu->lastTU = nullptr;
}
m_tuCache.cache( tus );
m_numTUs = 0;
}
void CodingStructure::clearPUs()
{
int numCh = ::getNumberValidChannels( area.chromaFormat );
for( int i = 0; i < numCh; i++ )
{
memset( m_puIdx[i], 0, sizeof( *m_puIdx[0] ) * unitScale[i].scaleArea( area.blocks[i].area() ) );
}
m_puCache.cache( pus );
m_numPUs = 0;
for( auto &pcu : cus )
{
pcu->firstPU = pcu->lastPU = nullptr;
}
}
void CodingStructure::clearCUs()
{
int numCh = ::getNumberValidChannels( area.chromaFormat );
for( int i = 0; i < numCh; i++ )
{
memset( m_cuIdx[i], 0, sizeof( *m_cuIdx[0] ) * unitScale[i].scaleArea( area.blocks[i].area() ) );
}
m_cuCache.cache( cus );
m_numCUs = 0;
}
MotionBuf CodingStructure::getMotionBuf( const Area& _area )
{
#if JVET_Z0118_GDR
return getMotionBuf(_area, m_pt);
#else
const CompArea& _luma = area.Y();
CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
const Area miArea = g_miScaling.scale( _area );
const Area selfArea = g_miScaling.scale( _luma );
return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
#endif
}
const CMotionBuf CodingStructure::getMotionBuf( const Area& _area ) const
{
#if JVET_Z0118_GDR
return getMotionBuf(_area, m_pt);
#else
const CompArea& _luma = area.Y();
CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
const Area miArea = g_miScaling.scale( _area );
const Area selfArea = g_miScaling.scale( _luma );
return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
#endif
}
#if JVET_W0123_TIMD_FUSION && RPR_ENABLE
bool CodingStructure::picContain(const Position _pos)
{
#if JVET_Z0118_GDR
if (!picture)
{
return false;
}
#endif
const Picture* pic = picture->unscaledPic;
const int width = pic->getPicWidthInLumaSamples();
const int height = pic->getPicHeightInLumaSamples();
return (_pos.x >= 0) && (_pos.x < width) && (_pos.y >= 0) && (_pos.y < height);
}
#endif
MotionInfo& CodingStructure::getMotionInfo( const Position& pos )
{
#if JVET_Z0118_GDR
return getMotionInfo(pos, m_pt);
#else
#if JVET_W0123_TIMD_FUSION && RPR_ENABLE
CHECKD( !picContain( pos ), "Trying to access motion information outside of this coding structure");
#else
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
#endif
//return getMotionBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the motion buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *( m_motionBuf + miPos.y * stride + miPos.x );
#endif
}
const MotionInfo& CodingStructure::getMotionInfo( const Position& pos ) const
{
#if JVET_Z0118_GDR
return getMotionInfo(pos, m_pt);;
#else
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
//return getMotionBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the motion buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *( m_motionBuf + miPos.y * stride + miPos.x );
#endif
}
#if JVET_Z0118_GDR
MotionBuf CodingStructure::getMotionBuf(const Area& _area, PictureType pt)
{
const CompArea& _luma = area.Y();
CHECKD(!_luma.contains(_area), "Trying to access motion information outside of this coding structure");
const Area miArea = g_miScaling.scale(_area);
const Area selfArea = g_miScaling.scale(_luma);
return MotionBuf(((pt == PIC_RECONSTRUCTION_0) ? m_motionBuf0 : m_motionBuf1) + rsAddr(miArea.pos(), selfArea.pos(), selfArea.width), selfArea.width, miArea.size());
}
const CMotionBuf CodingStructure::getMotionBuf(const Area& _area, PictureType pt) const
{
const CompArea& _luma = area.Y();
CHECKD(!_luma.contains(_area), "Trying to access motion information outside of this coding structure");
const Area miArea = g_miScaling.scale(_area);
const Area selfArea = g_miScaling.scale(_luma);
return MotionBuf(((pt == PIC_RECONSTRUCTION_0) ? m_motionBuf0 : m_motionBuf1) + rsAddr(miArea.pos(), selfArea.pos(), selfArea.width), selfArea.width, miArea.size());
}
MotionInfo& CodingStructure::getMotionInfo(const Position& pos, PictureType pt)
{
CHECKD(!area.Y().contains(pos), "Trying to access motion information outside of this coding structure");
//return getMotionBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the motion buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor(area.lumaSize().width);
const Position miPos = g_miScaling.scale(pos - area.lumaPos());
return *(((pt == PIC_RECONSTRUCTION_0) ? m_motionBuf0 : m_motionBuf1) + miPos.y * stride + miPos.x);
}
const MotionInfo& CodingStructure::getMotionInfo(const Position& pos, PictureType pt) const
{
CHECKD(!area.Y().contains(pos), "Trying to access motion information outside of this coding structure");
//return getMotionBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the motion buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor(area.lumaSize().width);
const Position miPos = g_miScaling.scale(pos - area.lumaPos());
return *(((pt == PIC_RECONSTRUCTION_0) ? m_motionBuf0 : m_motionBuf1) + miPos.y * stride + miPos.x);
}
#endif
#if JVET_W0123_TIMD_FUSION
IpmBuf CodingStructure::getIpmBuf( const Area& _area )
{
#if JVET_Z0118_GDR
return getIpmBuf(_area, m_pt);
#else
const CompArea& _luma = area.Y();
CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
const Area miArea = g_miScaling.scale( _area );
const Area selfArea = g_miScaling.scale( _luma );
return IpmBuf( m_ipmBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
#endif
}
const CIpmBuf CodingStructure::getIpmBuf( const Area& _area ) const
{
#if JVET_Z0118_GDR
return getIpmBuf(_area, m_pt);
#else
const CompArea& _luma = area.Y();
CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
const Area miArea = g_miScaling.scale( _area );
const Area selfArea = g_miScaling.scale( _luma );
return IpmBuf( m_ipmBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
#endif
}
uint8_t& CodingStructure::getIpmInfo( const Position& pos )
{
#if JVET_Z0118_GDR
return getIpmInfo(pos, m_pt);
#else
#if RPR_ENABLE
CHECKD( !picContain( pos ), "Trying to access motion information outside of this coding structure");
#else
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
#endif
//return getIpmBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the intra prediction mode buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *( m_ipmBuf + miPos.y * stride + miPos.x );
#endif
}
const uint8_t& CodingStructure::getIpmInfo( const Position& pos ) const
{
#if JVET_Z0118_GDR
return getIpmInfo(pos, m_pt);
#else
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
//return getIpmBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the intra prediction mode buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *( m_ipmBuf + miPos.y * stride + miPos.x );
#endif
}
#endif
#if JVET_W0123_TIMD_FUSION && JVET_Z0118_GDR
IpmBuf CodingStructure::getIpmBuf(const Area& _area, PictureType pt)
{
const CompArea& _luma = area.Y();
CHECKD(!_luma.contains(_area), "Trying to access motion information outside of this coding structure");
const Area miArea = g_miScaling.scale(_area);
const Area selfArea = g_miScaling.scale(_luma);
return IpmBuf(((pt == PIC_RECONSTRUCTION_0) ? m_ipmBuf0 : m_ipmBuf1) + rsAddr(miArea.pos(), selfArea.pos(), selfArea.width), selfArea.width, miArea.size());
}
const CIpmBuf CodingStructure::getIpmBuf(const Area& _area, PictureType pt) const
{
const CompArea& _luma = area.Y();
CHECKD(!_luma.contains(_area), "Trying to access motion information outside of this coding structure");
const Area miArea = g_miScaling.scale(_area);
const Area selfArea = g_miScaling.scale(_luma);
return IpmBuf(((pt == PIC_RECONSTRUCTION_0) ? m_ipmBuf0 : m_ipmBuf1) + rsAddr(miArea.pos(), selfArea.pos(), selfArea.width), selfArea.width, miArea.size());
}
uint8_t& CodingStructure::getIpmInfo(const Position& pos, PictureType pt)
{
#if JVET_Z0118_GDR
static uint8_t constIpm = 0;
if (!picContain(pos))
{
return constIpm;
}
#endif
#if RPR_ENABLE
CHECKD( !picContain( pos ), "Trying to access motion information outside of this coding structure");
#else
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
#endif
//return getIpmBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the intra prediction mode buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *(((pt == PIC_RECONSTRUCTION_0) ? m_ipmBuf0 : m_ipmBuf1) + miPos.y * stride + miPos.x);
}
const uint8_t& CodingStructure::getIpmInfo(const Position& pos, PictureType pt) const
{
CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
//return getIpmBuf().at( g_miScaling.scale( pos - area.lumaPos() ) );
// bypass the intra prediction mode buf calling and get the value directly
const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
const Position miPos = g_miScaling.scale( pos - area.lumaPos() );
return *(((pt == PIC_RECONSTRUCTION_0) ? m_ipmBuf0 : m_ipmBuf1) + miPos.y * stride + miPos.x);
}
#endif
// data accessors
PelBuf CodingStructure::getPredBuf(const CompArea &blk) { return getBuf(blk, PIC_PREDICTION); }
const CPelBuf CodingStructure::getPredBuf(const CompArea &blk) const { return getBuf(blk, PIC_PREDICTION); }
PelUnitBuf CodingStructure::getPredBuf(const UnitArea &unit) { return getBuf(unit, PIC_PREDICTION); }
const CPelUnitBuf CodingStructure::getPredBuf(const UnitArea &unit) const { return getBuf(unit, PIC_PREDICTION); }
PelBuf CodingStructure::getResiBuf(const CompArea &blk) { return getBuf(blk, PIC_RESIDUAL); }
const CPelBuf CodingStructure::getResiBuf(const CompArea &blk) const { return getBuf(blk, PIC_RESIDUAL); }
PelUnitBuf CodingStructure::getResiBuf(const UnitArea &unit) { return getBuf(unit, PIC_RESIDUAL); }
const CPelUnitBuf CodingStructure::getResiBuf(const UnitArea &unit) const { return getBuf(unit, PIC_RESIDUAL); }
#if JVET_Z0118_GDR
PelBuf CodingStructure::getRecoBuf(const CompArea &blk) { return getBuf(blk, m_pt); }
const CPelBuf CodingStructure::getRecoBuf(const CompArea &blk) const { return getBuf(blk, m_pt); }
PelUnitBuf CodingStructure::getRecoBuf(const UnitArea &unit) { return getBuf(unit, m_pt); }
const CPelUnitBuf CodingStructure::getRecoBuf(const UnitArea &unit) const { return getBuf(unit, m_pt); }
#else
PelBuf CodingStructure::getRecoBuf(const CompArea &blk) { return getBuf(blk, PIC_RECONSTRUCTION); }
const CPelBuf CodingStructure::getRecoBuf(const CompArea &blk) const { return getBuf(blk, PIC_RECONSTRUCTION); }
PelUnitBuf CodingStructure::getRecoBuf(const UnitArea &unit) { return getBuf(unit, PIC_RECONSTRUCTION); }
const CPelUnitBuf CodingStructure::getRecoBuf(const UnitArea &unit) const { return getBuf(unit, PIC_RECONSTRUCTION); }
#endif
PelBuf CodingStructure::getOrgResiBuf(const CompArea &blk) { return getBuf(blk, PIC_ORG_RESI); }
const CPelBuf CodingStructure::getOrgResiBuf(const CompArea &blk) const { return getBuf(blk, PIC_ORG_RESI); }
PelUnitBuf CodingStructure::getOrgResiBuf(const UnitArea &unit) { return getBuf(unit, PIC_ORG_RESI); }
const CPelUnitBuf CodingStructure::getOrgResiBuf(const UnitArea &unit) const { return getBuf(unit, PIC_ORG_RESI); }
PelBuf CodingStructure::getOrgBuf(const CompArea &blk) { return getBuf(blk, PIC_ORIGINAL); }
const CPelBuf CodingStructure::getOrgBuf(const CompArea &blk) const { return getBuf(blk, PIC_ORIGINAL); }
PelUnitBuf CodingStructure::getOrgBuf(const UnitArea &unit) { return getBuf(unit, PIC_ORIGINAL); }
const CPelUnitBuf CodingStructure::getOrgBuf(const UnitArea &unit) const { return getBuf(unit, PIC_ORIGINAL); }
PelBuf CodingStructure::getOrgBuf(const ComponentID &compID) { return picture->getBuf(area.blocks[compID], PIC_ORIGINAL); }
const CPelBuf CodingStructure::getOrgBuf(const ComponentID &compID)const { return picture->getBuf(area.blocks[compID], PIC_ORIGINAL); }
PelUnitBuf CodingStructure::getOrgBuf() { return picture->getBuf(area, PIC_ORIGINAL); }
const CPelUnitBuf CodingStructure::getOrgBuf() const { return picture->getBuf(area, PIC_ORIGINAL); }
#if ALF_SAO_TRUE_ORG
PelUnitBuf CodingStructure::getTrueOrgBuf() { return picture->getBuf(area, PIC_TRUE_ORIGINAL); }
const CPelUnitBuf CodingStructure::getTrueOrgBuf() const { return picture->getBuf(area, PIC_TRUE_ORIGINAL); }
#endif
PelBuf CodingStructure::getBuf( const CompArea &blk, const PictureType &type )
{
if (!blk.valid())
{
return PelBuf();
}
if (type == PIC_ORIGINAL)
{
return picture->getBuf(blk, type);
}
const ComponentID compID = blk.compID;
#if JVET_Z0118_GDR
PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : (type == PIC_RECONSTRUCTION_0 ? &m_reco0 : (type == PIC_RECONSTRUCTION_1 ? &m_reco1 : (type == PIC_ORG_RESI ? &m_orgr : nullptr ))));
#else
PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : ( type == PIC_ORG_RESI ? &m_orgr : nullptr ) ) );
#endif
CHECK( !buf, "Unknown buffer requested" );
CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
CompArea cFinal = blk;
cFinal.relativeTo( area.blocks[compID] );
#if !KEEP_PRED_AND_RESI_SIGNALS
#if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
if (!parent && (type == PIC_PREDICTION))
{
cFinal.x &= (pcv->maxCUWidthMask >> getComponentScaleX(blk.compID, blk.chromaFormat));
cFinal.y &= (pcv->maxCUHeightMask >> getComponentScaleY(blk.compID, blk.chromaFormat));
}
#else
if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
{
cFinal.x &= ( pcv->maxCUWidthMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
cFinal.y &= ( pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
}
#endif
#endif
return buf->getBuf( cFinal );
}
const CPelBuf CodingStructure::getBuf( const CompArea &blk, const PictureType &type ) const
{
if (!blk.valid())
{
return PelBuf();
}
if (type == PIC_ORIGINAL)
{
return picture->getBuf(blk, type);
}
const ComponentID compID = blk.compID;
#if JVET_Z0118_GDR
const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : (type == PIC_RECONSTRUCTION_0 ? &m_reco0 : (type == PIC_RECONSTRUCTION_1 ? &m_reco1 : (type == PIC_ORG_RESI ? &m_orgr : nullptr ))));
#else
const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : ( type == PIC_ORG_RESI ? &m_orgr : nullptr ) ) );
#endif
CHECK( !buf, "Unknown buffer requested" );
CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
CompArea cFinal = blk;
cFinal.relativeTo( area.blocks[compID] );
#if !KEEP_PRED_AND_RESI_SIGNALS
#if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
if (!parent && (type == PIC_PREDICTION))
{
cFinal.x &= (pcv->maxCUWidthMask >> getComponentScaleX(blk.compID, blk.chromaFormat));
cFinal.y &= (pcv->maxCUHeightMask >> getComponentScaleY(blk.compID, blk.chromaFormat));
}
#else
if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
{
cFinal.x &= ( pcv->maxCUWidthMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
cFinal.y &= ( pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
}
#endif
#endif
return buf->getBuf( cFinal );
}
PelUnitBuf CodingStructure::getBuf( const UnitArea &unit, const PictureType &type )
{
// no parent fetching for buffers
if( area.chromaFormat == CHROMA_400 )
{
return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
}
else
{
return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
}
}
const CPelUnitBuf CodingStructure::getBuf( const UnitArea &unit, const PictureType &type ) const
{
// no parent fetching for buffers
if( area.chromaFormat == CHROMA_400 )
{
return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
}
else
{
return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
}
}
const CodingUnit* CodingStructure::getCURestricted( const Position &pos, const CodingUnit& curCu, const ChannelType _chType ) const
{
const CodingUnit* cu = getCU( pos, _chType );
// exists same slice and tile cu precedes curCu in encoding order
// (thus, is either from parent CS in RD-search or its index is lower)
const bool wavefrontsEnabled = curCu.slice->getSPS()->getEntropyCodingSyncEnabledFlag();
int ctuSizeBit = floorLog2(curCu.cs->sps->getMaxCUWidth());
int xNbY = pos.x << getChannelTypeScaleX( _chType, curCu.chromaFormat );
int xCurr = curCu.blocks[_chType].x << getChannelTypeScaleX( _chType, curCu.chromaFormat );
bool addCheck = (wavefrontsEnabled && (xNbY >> ctuSizeBit) >= (xCurr >> ctuSizeBit) + 1 ) ? false : true;
if( cu && CU::isSameSliceAndTile( *cu, curCu ) && ( cu->cs != curCu.cs || cu->idx <= curCu.idx ) && addCheck)
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
const Position posRB = (_chType == CHANNEL_TYPE_LUMA) ? curCu.Y().bottomRight() : curCu.Cb().bottomRight();
const Position posTL = (_chType == CHANNEL_TYPE_LUMA) ? curCu.Y().topLeft() : curCu.Cb().topLeft();
bool isTLClean = isClean(posTL, _chType);
bool isRBClean = isClean(posRB, _chType);
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean(pos, _chType);
if (isSrcClean && !isTarClean)
{
return nullptr;
}
}
#endif
return cu;
}
else
{
return nullptr;
}
}
const CodingUnit* CodingStructure::getCURestricted(const Position &pos, const Position curPos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType) const
{
const CodingUnit* cu = getCU(pos, _chType);
const bool wavefrontsEnabled = this->slice->getSPS()->getEntropyCodingSyncEnabledFlag();
int ctuSizeBit = floorLog2(this->sps->getMaxCUWidth());
int xNbY = pos.x << getChannelTypeScaleX(_chType, this->area.chromaFormat);
int xCurr = curPos.x << getChannelTypeScaleX(_chType, this->area.chromaFormat);
bool addCheck = (wavefrontsEnabled && (xNbY >> ctuSizeBit) >= (xCurr >> ctuSizeBit) + 1) ? false : true;
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
bool isSrcClean = isClean(curPos, _chType);
bool isTarClean = isClean(pos, _chType);
if (isSrcClean && !isTarClean)
{
return nullptr;
}
}
#endif
return ( cu && cu->slice->getIndependentSliceIdx() == curSliceIdx && cu->tileIdx == curTileIdx && addCheck ) ? cu : nullptr;
}
const PredictionUnit* CodingStructure::getPURestricted( const Position &pos, const PredictionUnit& curPu, const ChannelType _chType ) const
{
const PredictionUnit* pu = getPU( pos, _chType );
// exists same slice and tile pu precedes curPu in encoding order
// (thus, is either from parent CS in RD-search or its index is lower)
const bool wavefrontsEnabled = curPu.cu->slice->getSPS()->getEntropyCodingSyncEnabledFlag();
int ctuSizeBit = floorLog2(curPu.cs->sps->getMaxCUWidth());
int xNbY = pos.x << getChannelTypeScaleX( _chType, curPu.chromaFormat );
int xCurr = curPu.blocks[_chType].x << getChannelTypeScaleX( _chType, curPu.chromaFormat );
bool addCheck = (wavefrontsEnabled && (xNbY >> ctuSizeBit) >= (xCurr >> ctuSizeBit) + 1 ) ? false : true;
if (pu && CU::isSameSliceAndTile(*pu->cu, *curPu.cu) && (pu->cs != curPu.cs || pu->idx <= curPu.idx) && addCheck)
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
const Position posRB = (_chType == CHANNEL_TYPE_LUMA) ? curPu.Y().bottomRight() : curPu.Cb().bottomRight();
const Position posTL = (_chType == CHANNEL_TYPE_LUMA) ? curPu.Y().topLeft() : curPu.Cb().topLeft();
bool isTLClean = isClean(posTL, _chType);
bool isRBClean = isClean(posRB, _chType);
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean(pos, _chType);
if (isSrcClean && !isTarClean)
{
return nullptr;
}
}
#endif
return pu;
}
else
{
return nullptr;
}
}
const TransformUnit* CodingStructure::getTURestricted( const Position &pos, const TransformUnit& curTu, const ChannelType _chType ) const
{
const TransformUnit* tu = getTU( pos, _chType );
// exists same slice and tile tu precedes curTu in encoding order
// (thus, is either from parent CS in RD-search or its index is lower)
const bool wavefrontsEnabled = curTu.cu->slice->getSPS()->getEntropyCodingSyncEnabledFlag();
int ctuSizeBit = floorLog2(curTu.cs->sps->getMaxCUWidth());
int xNbY = pos.x << getChannelTypeScaleX( _chType, curTu.chromaFormat );
int xCurr = curTu.blocks[_chType].x << getChannelTypeScaleX( _chType, curTu.chromaFormat );
bool addCheck = (wavefrontsEnabled && (xNbY >> ctuSizeBit) >= (xCurr >> ctuSizeBit) + 1 ) ? false : true;
if (tu && CU::isSameSliceAndTile(*tu->cu, *curTu.cu) && (tu->cs != curTu.cs || tu->idx <= curTu.idx) && addCheck)
{
#if JVET_Z0118_GDR
if (m_gdrEnabled)
{
const Position posRB = (_chType == CHANNEL_TYPE_LUMA) ? curTu.Y().bottomRight() : curTu.Cb().bottomRight();
const Position posTL = (_chType == CHANNEL_TYPE_LUMA) ? curTu.Y().topLeft() : curTu.Cb().topLeft();
bool isTLClean = isClean(posTL, _chType);
bool isRBClean = isClean(posRB, _chType);
bool isSrcClean = isTLClean || isRBClean;
bool isTarClean = isClean(pos, _chType);
if (isSrcClean && !isTarClean)
{
return nullptr;
}
}
#endif
return tu;
}
else
{
return nullptr;
}
}