-
Luong Pham Van authoredLuong Pham Van authored
DecCu.cpp 30.36 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-2019, 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 DecCu.cpp
\brief CU decoder class
*/
#include "DecCu.h"
#include "CommonLib/CrossCompPrediction.h"
#include "CommonLib/InterPrediction.h"
#include "CommonLib/IntraPrediction.h"
#include "CommonLib/Picture.h"
#include "CommonLib/UnitTools.h"
#include "CommonLib/dtrace_buffer.h"
#if RExt__DECODER_DEBUG_TOOL_STATISTICS
#include "CommonLib/CodingStatistics.h"
#endif
#if K0149_BLOCK_STATISTICS
#include "CommonLib/ChromaFormat.h"
#include "CommonLib/dtrace_blockstatistics.h"
#endif
//! \ingroup DecoderLib
//! \{
// ====================================================================================================================
// Constructor / destructor / create / destroy
// ====================================================================================================================
DecCu::DecCu()
{
m_tmpStorageLCU = NULL;
}
DecCu::~DecCu()
{
}
void DecCu::init( TrQuant* pcTrQuant, IntraPrediction* pcIntra, InterPrediction* pcInter)
{
m_pcTrQuant = pcTrQuant;
m_pcIntraPred = pcIntra;
m_pcInterPred = pcInter;
}
void DecCu::initDecCuReshaper (Reshape* pcReshape, ChromaFormat chromaFormatIDC)
{
m_pcReshape = pcReshape;
if (m_tmpStorageLCU == NULL)
{
m_tmpStorageLCU = new PelStorage;
m_tmpStorageLCU->create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
}
}
void DecCu::destoryDecCuReshaprBuf()
{
if (m_tmpStorageLCU)
{
m_tmpStorageLCU->destroy();
delete m_tmpStorageLCU;
m_tmpStorageLCU = NULL;
}
}
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
{
const int maxNumChannelType = cs.pcv->chrFormat != CHROMA_400 && CS::isDualITree( cs ) ? 2 : 1;
#if !JVET_P0400_REMOVE_SHARED_MERGE_LIST
if (!cs.pcv->isEncoder)
{
m_shareStateDec = NO_SHARE;
}
bool sharePrepareCondition = ((!cs.pcv->isEncoder) && (!(cs.slice->isIntra()) || cs.slice->getSPS()->getIBCFlag()));
#endif
if (cs.resetIBCBuffer)
{
m_pcInterPred->resetIBCBuffer(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight());
cs.resetIBCBuffer = false;
}
for( int ch = 0; ch < maxNumChannelType; ch++ )
{
const ChannelType chType = ChannelType( ch );
Position prevTmpPos;
prevTmpPos.x = -1; prevTmpPos.y = -1;
for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) )
{
if(currCU.Y().valid())
{
const int vSize = cs.slice->getSPS()->getMaxCUHeight() > 64 ? 64 : cs.slice->getSPS()->getMaxCUHeight();
if((currCU.Y().x % vSize) == 0 && (currCU.Y().y % vSize) == 0)
{
m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight(), vSize, currCU.Y().x, currCU.Y().y);
}
}
#if !JVET_P0400_REMOVE_SHARED_MERGE_LIST
if(sharePrepareCondition)
{
if ((currCU.shareParentPos.x >= 0) && (!(currCU.shareParentPos.x == prevTmpPos.x && currCU.shareParentPos.y == prevTmpPos.y)))
{
m_shareStateDec = GEN_ON_SHARED_BOUND;
}
if (currCU.shareParentPos.x < 0)
{
m_shareStateDec = 0;
}
prevTmpPos = currCU.shareParentPos;
}
#endif
if (currCU.predMode != MODE_INTRA && currCU.predMode != MODE_PLT && currCU.Y().valid())
{
xDeriveCUMV(currCU);
}
switch( currCU.predMode )
{
case MODE_INTER:
case MODE_IBC:
xReconInter( currCU );
break;
case MODE_PLT:
case MODE_INTRA:
xReconIntraQT( currCU );
break;
default:
THROW( "Invalid prediction mode" );
break;
}
if( CU::isLosslessCoded( currCU ) )
{
xFillPCMBuffer( currCU );
}
m_pcInterPred->xFillIBCBuffer(currCU);
DTRACE_BLOCK_REC( cs.picture->getRecoBuf( currCU ), currCU, currCU.predMode );
}
}
#if K0149_BLOCK_STATISTICS
getAndStoreBlockStatistics(cs, ctuArea);
#endif
}
// ====================================================================================================================
// Protected member functions
// ====================================================================================================================
void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
{
if( !tu.blocks[ compID ].valid() )
{
return;
}
CodingStructure &cs = *tu.cs;
const CompArea &area = tu.blocks[compID];
const ChannelType chType = toChannelType( compID );
PelBuf piPred = cs.getPredBuf( area );
const PredictionUnit &pu = *tu.cs->getPU( area.pos(), chType );
const uint32_t uiChFinalMode = PU::getFinalIntraMode( pu, chType );
PelBuf pReco = cs.getRecoBuf(area);
//===== init availability pattern =====
bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID);
bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area);
CompArea areaPredReg(COMPONENT_Y, tu.chromaFormat, area);
if (tu.cu->ispMode && isLuma(compID))
{
if (predRegDiffFromTB)
{
if (firstTBInPredReg)
{
CU::adjustPredArea(areaPredReg);
m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, areaPredReg, pReco);
}
}
else
{
m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, area, pReco);
}
}
else
{
m_pcIntraPred->initIntraPatternChType(*tu.cu, area);
}
//===== get prediction signal =====
if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
{
const PredictionUnit& pu = *tu.cu->firstPU;
m_pcIntraPred->xGetLumaRecPixels( pu, area );
m_pcIntraPred->predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );
}
else
{
if( PU::isMIP( pu, chType ) )
{
m_pcIntraPred->initIntraMip( pu );
m_pcIntraPred->predIntraMip( compID, piPred, pu );
}
else
{
if (predRegDiffFromTB)
{
if (firstTBInPredReg)
{
PelBuf piPredReg = cs.getPredBuf(areaPredReg);
m_pcIntraPred->predIntraAng(compID, piPredReg, pu);
}
}
else
m_pcIntraPred->predIntraAng(compID, piPred, pu);
}
}
const Slice &slice = *cs.slice;
bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()));
if (flag && slice.getLmcsChromaResidualScaleFlag() && (compID != COMPONENT_Y) && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr]))
{
const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY);
tu.setChromaAdj(adj);
}
//===== inverse transform =====
PelBuf piResi = cs.getResiBuf( area );
const QpParam cQP( tu, compID );
if( tu.jointCbCr && isChroma(compID) )
{
if( compID == COMPONENT_Cb )
{
PelBuf resiCr = cs.getResiBuf( tu.blocks[ COMPONENT_Cr ] );
if( tu.jointCbCr >> 1 )
{
m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, cQP );
}
else
{
const QpParam qpCr( tu, COMPONENT_Cr );
m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
}
m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
}
}
else
if( TU::getCbf( tu, compID ) )
{
m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
}
else
{
piResi.fill( 0 );
}
//===== reconstruction =====
flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag())
{
piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
}
if( isChroma(compID) && tu.compAlpha[compID] != 0 )
{
CrossComponentPrediction::crossComponentPrediction( tu, compID, cs.getResiBuf( tu.Y() ), piResi, piResi, true );
}
if( !tu.cu->ispMode || !isLuma( compID ) )
{
cs.setDecomp( area );
}
else if( tu.cu->ispMode && isLuma( compID ) && CU::isISPFirst( *tu.cu, tu.blocks[compID], compID ) )
{
cs.setDecomp( tu.cu->blocks[compID] );
}
#if REUSE_CU_RESULTS
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpPred;
#endif
if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
{
#if REUSE_CU_RESULTS
{
tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
tmpPred.copyFrom(piPred);
}
#endif
}
#if KEEP_PRED_AND_RESI_SIGNALS
pReco.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );
#else
piPred.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );
#endif
#if !KEEP_PRED_AND_RESI_SIGNALS
pReco.copyFrom( piPred );
#endif
if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
{
#if REUSE_CU_RESULTS
{
piPred.copyFrom(tmpPred);
}
#endif
}
#if REUSE_CU_RESULTS
if( cs.pcv->isEncoder )
{
cs.picture->getRecoBuf( area ).copyFrom( pReco );
cs.picture->getPredBuf(area).copyFrom(piPred);
}
#endif
}
void DecCu::xReconIntraQT( CodingUnit &cu )
{
if (CU::isPLT(cu))
{
if (cu.isSepTree())
{
if (cu.chType == CHANNEL_TYPE_LUMA)
{
xReconPLT(cu, COMPONENT_Y, 1);
}
if (cu.chromaFormat != CHROMA_400 && (cu.chType == CHANNEL_TYPE_CHROMA))
{
xReconPLT(cu, COMPONENT_Cb, 2);
}
}
else
{
xReconPLT(cu, COMPONENT_Y, 3);
}
return;
}
const uint32_t numChType = ::getNumberValidChannels( cu.chromaFormat );
for( uint32_t chType = CHANNEL_TYPE_LUMA; chType < numChType; chType++ )
{
if( cu.blocks[chType].valid() )
{
xIntraRecQT( cu, ChannelType( chType ) );
}
}
}
void DecCu::xReconPLT(CodingUnit &cu, ComponentID compBegin, uint32_t numComp)
{
const SPS& sps = *(cu.cs->sps);
TransformUnit& tu = *cu.firstTU;
PelBuf curPLTIdx = tu.getcurPLTIdx(compBegin);
uint32_t height = cu.block(compBegin).height;
uint32_t width = cu.block(compBegin).width;
//recon. pixels
uint32_t scaleX = getComponentScaleX(COMPONENT_Cb, sps.getChromaFormatIdc());
uint32_t scaleY = getComponentScaleY(COMPONENT_Cb, sps.getChromaFormatIdc());
for (uint32_t y = 0; y < height; y++)
{
for (uint32_t x = 0; x < width; x++)
{
for (uint32_t compID = compBegin; compID < (compBegin + numComp); compID++)
{
const int channelBitDepth = cu.cs->sps->getBitDepth(toChannelType((ComponentID)compID));
const CompArea &area = cu.blocks[compID];
PelBuf picReco = cu.cs->getRecoBuf(area);
PLTescapeBuf escapeValue = tu.getescapeValue((ComponentID)compID);
if (curPLTIdx.at(x, y) == cu.curPLTSize[compBegin])
{
Pel value;
QpParam cQP(tu, (ComponentID)compID);
#if JVET_P0460_PLT_TS_MIN_QP
int qp = cQP.Qp(true);
#else
int qp = cQP.Qp(false);
#endif
int qpRem = qp % 6;
int qpPer = qp / 6;
if (compBegin != COMPONENT_Y || compID == COMPONENT_Y)
{
int invquantiserRightShift = IQUANT_SHIFT;
int add = 1 << (invquantiserRightShift - 1);
value = ((((escapeValue.at(x, y)*g_invQuantScales[0][qpRem]) << qpPer) + add) >> invquantiserRightShift);
value = Pel(ClipBD<int>(value, channelBitDepth));
picReco.at(x, y) = value;
}
else if (compBegin == COMPONENT_Y && compID != COMPONENT_Y && y % (1 << scaleY) == 0 && x % (1 << scaleX) == 0)
{
uint32_t posYC = y >> scaleY;
uint32_t posXC = x >> scaleX;
int invquantiserRightShift = IQUANT_SHIFT;
int add = 1 << (invquantiserRightShift - 1);
value = ((((escapeValue.at(posXC, posYC)*g_invQuantScales[0][qpRem]) << qpPer) + add) >> invquantiserRightShift);
value = Pel(ClipBD<int>(value, channelBitDepth));
picReco.at(posXC, posYC) = value;
}
}
else
{
uint32_t curIdx = curPLTIdx.at(x, y);
if (compBegin != COMPONENT_Y || compID == COMPONENT_Y)
{
picReco.at(x, y) = cu.curPLT[compID][curIdx];
}
else if (compBegin == COMPONENT_Y && compID != COMPONENT_Y && y % (1 << scaleY) == 0 && x % (1 << scaleX) == 0)
{
uint32_t posYC = y >> scaleY;
uint32_t posXC = x >> scaleX;
picReco.at(posXC, posYC) = cu.curPLT[compID][curIdx];
}
}
}
}
}
for (uint32_t compID = compBegin; compID < (compBegin + numComp); compID++)
{
const CompArea &area = cu.blocks[compID];
PelBuf picReco = cu.cs->getRecoBuf(area);
cu.cs->picture->getRecoBuf(area).copyFrom(picReco);
cu.cs->setDecomp(area);
}
}
/** Function for deriving reconstructed PU/CU chroma samples with QTree structure
* \param pcRecoYuv pointer to reconstructed sample arrays
* \param pcPredYuv pointer to prediction sample arrays
* \param pcResiYuv pointer to residue sample arrays
* \param chType texture channel type (luma/chroma)
* \param rTu reference to transform data
*
\ This function derives reconstructed PU/CU chroma samples with QTree recursive structure
*/
void
DecCu::xIntraRecQT(CodingUnit &cu, const ChannelType chType)
{
for( auto &currTU : CU::traverseTUs( cu ) )
{
if( isLuma( chType ) )
{
xIntraRecBlk( currTU, COMPONENT_Y );
}
else
{
const uint32_t numValidComp = getNumberValidComponents( cu.chromaFormat );
for( uint32_t compID = COMPONENT_Cb; compID < numValidComp; compID++ )
{
xIntraRecBlk( currTU, ComponentID( compID ) );
}
}
}
}
/** Function for filling the PCM buffer of a CU using its reconstructed sample array
* \param pCU pointer to current CU
* \param depth CU Depth
*/
void DecCu::xFillPCMBuffer(CodingUnit &cu)
{
for( auto &currTU : CU::traverseTUs( cu ) )
{
for (const CompArea &area : currTU.blocks)
{
if( !area.valid() ) continue;;
CPelBuf source = cu.cs->getRecoBuf(area);
PelBuf destination = currTU.getPcmbuf(area.compID);
destination.copyFrom(source);
}
}
}
#include "CommonLib/dtrace_buffer.h"
void DecCu::xReconInter(CodingUnit &cu)
{
if( cu.triangle )
{
const bool splitDir = cu.firstPU->triangleSplitDir;
const uint8_t candIdx0 = cu.firstPU->triangleMergeIdx0;
const uint8_t candIdx1 = cu.firstPU->triangleMergeIdx1;
m_pcInterPred->motionCompensation4Triangle( cu, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
}
else
{
m_pcIntraPred->geneIntrainterPred(cu);
// inter prediction
CHECK(CU::isIBC(cu) && cu.firstPU->mhIntraFlag, "IBC and MHIntra cannot be used together");
CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together");
CHECK(CU::isIBC(cu) && cu.triangle, "IBC and triangle cannot be used together");
CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together");
const bool luma = cu.Y().valid();
const bool chroma = cu.Cb().valid();
if (luma && chroma)
{
m_pcInterPred->motionCompensation(cu);
}
else
{
m_pcInterPred->motionCompensation(cu, REF_PIC_LIST_0, luma, chroma);
}
}
if (cu.Y().valid())
{
const PredictionUnit &pu = *cu.firstPU;
#if JVET_P0400_REMOVE_SHARED_MERGE_LIST
bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16);
if (!cu.affine && !cu.triangle && !isIbcSmallBlk)
#else
bool isShare = ((CU::isIBC(cu) && (cu.shareParentSize.width != cu.Y().lumaSize().width || cu.shareParentSize.height != cu.Y().lumaSize().height)) ? true : false);
if (!cu.affine && !cu.triangle && !isShare)
#endif
{
MotionInfo mi = pu.getMotionInfo();
mi.GBiIdx = (mi.interDir == 3) ? cu.GBiIdx : GBI_DEFAULT;
cu.cs->addMiToLut(CU::isIBC(cu) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut, mi );
}
}
if (cu.firstPU->mhIntraFlag)
{
if (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
{
cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT());
}
m_pcIntraPred->geneWeightedPred(COMPONENT_Y, cu.cs->getPredBuf(*cu.firstPU).Y(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Y, 0));
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
if (cu.chromaSize().width > 2)
{
#endif
m_pcIntraPred->geneWeightedPred(COMPONENT_Cb, cu.cs->getPredBuf(*cu.firstPU).Cb(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cb, 0));
m_pcIntraPred->geneWeightedPred(COMPONENT_Cr, cu.cs->getPredBuf(*cu.firstPU).Cr(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cr, 0));
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
}
#endif
}
DTRACE ( g_trace_ctx, D_TMP, "pred " );
DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getPredBuf( cu ), &cu.Y() );
// inter recon
xDecodeInterTexture(cu);
// clip for only non-zero cbf case
CodingStructure &cs = *cu.cs;
if (cu.rootCbf)
{
#if REUSE_CU_RESULTS
const CompArea &area = cu.blocks[COMPONENT_Y];
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpPred;
#endif
if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
{
#if REUSE_CU_RESULTS
if (cs.pcv->isEncoder)
{
tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
tmpPred.copyFrom(cs.getPredBuf(cu).get(COMPONENT_Y));
}
#endif
if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
cs.getPredBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
}
#if KEEP_PRED_AND_RESI_SIGNALS
cs.getRecoBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
#else
cs.getResiBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
cs.getRecoBuf( cu ).copyFrom ( cs.getResiBuf( cu ) );
#endif
if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
{
#if REUSE_CU_RESULTS
if (cs.pcv->isEncoder)
{
cs.getPredBuf(cu).get(COMPONENT_Y).copyFrom(tmpPred);
}
#endif
}
}
else
{
cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs());
if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu))
{
cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
}
}
DTRACE ( g_trace_ctx, D_TMP, "reco " );
DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cu ), &cu.Y() );
cs.setDecomp(cu);
}
void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
{
if( !currTU.blocks[compID].valid() ) return;
const CompArea &area = currTU.blocks[compID];
CodingStructure& cs = *currTU.cs;
//===== inverse transform =====
PelBuf resiBuf = cs.getResiBuf(area);
const QpParam cQP(currTU, compID);
if( currTU.jointCbCr && isChroma(compID) )
{
if( compID == COMPONENT_Cb )
{
PelBuf resiCr = cs.getResiBuf( currTU.blocks[ COMPONENT_Cr ] );
if( currTU.jointCbCr >> 1 )
{
m_pcTrQuant->invTransformNxN( currTU, COMPONENT_Cb, resiBuf, cQP );
}
else
{
const QpParam qpCr( currTU, COMPONENT_Cr );
m_pcTrQuant->invTransformNxN( currTU, COMPONENT_Cr, resiCr, qpCr );
}
m_pcTrQuant->invTransformICT( currTU, resiBuf, resiCr );
}
}
else
if( TU::getCbf( currTU, compID ) )
{
m_pcTrQuant->invTransformNxN( currTU, compID, resiBuf, cQP );
}
else
{
resiBuf.fill( 0 );
}
//===== reconstruction =====
const Slice &slice = *cs.slice;
if (slice.getLmcsEnabledFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr)
&& slice.getLmcsChromaResidualScaleFlag() && currTU.blocks[compID].width * currTU.blocks[compID].height > 4)
{
resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID));
}
if( isChroma( compID ) && currTU.compAlpha[compID] != 0 )
{
CrossComponentPrediction::crossComponentPrediction( currTU, compID, cs.getResiBuf( currTU.Y() ), resiBuf, resiBuf, true );
}
}
void DecCu::xDecodeInterTexture(CodingUnit &cu)
{
if( !cu.rootCbf )
{
return;
}
const uint32_t uiNumVaildComp = getNumberValidComponents(cu.chromaFormat);
for (uint32_t ch = 0; ch < uiNumVaildComp; ch++)
{
const ComponentID compID = ComponentID(ch);
for( auto& currTU : CU::traverseTUs( cu ) )
{
CodingStructure &cs = *cu.cs;
const Slice &slice = *cs.slice;
if (slice.getLmcsEnabledFlag() && slice.getLmcsChromaResidualScaleFlag() && (compID == COMPONENT_Y) && (currTU.cbf[COMPONENT_Cb] || currTU.cbf[COMPONENT_Cr]))
{
const CompArea &areaY = currTU.blocks[COMPONENT_Y];
int adj = m_pcReshape->calculateChromaAdjVpduNei(currTU, areaY);
currTU.setChromaAdj(adj);
}
xDecodeInterTU( currTU, compID );
}
}
}
void DecCu::xDeriveCUMV( CodingUnit &cu )
{
for( auto &pu : CU::traversePUs( cu ) )
{
MergeCtx mrgCtx;
#if RExt__DECODER_DEBUG_TOOL_STATISTICS
if( pu.cu->affine )
{
CodingStatistics::IncrementStatisticTool( CodingStatisticsClassType{ STATS__TOOL_AFF, pu.Y().width, pu.Y().height } );
}
#endif
if( pu.mergeFlag )
{
if (pu.mmvdMergeFlag || pu.cu->mmvdSkip)
{
CHECK(pu.mhIntraFlag == true, "invalid MHIntra");
if (pu.cs->sps->getSBTMVPEnabledFlag())
{
Size bufSize = g_miScaling.scale(pu.lumaSize());
mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
}
int fPosBaseIdx = pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM;
#if !JVET_P0400_REMOVE_SHARED_MERGE_LIST
pu.shareParentPos = cu.shareParentPos;
pu.shareParentSize = cu.shareParentSize;
#endif
PU::getInterMergeCandidates(pu, mrgCtx, 1, fPosBaseIdx + 1);
PU::getInterMMVDMergeCandidates(pu, mrgCtx,
pu.mmvdMergeIdx
);
mrgCtx.setMmvdMergeCandiInfo(pu, pu.mmvdMergeIdx);
PU::spanMotionInfo(pu, mrgCtx);
}
else
{
{
if( pu.cu->triangle )
{
PU::getTriangleMergeCandidates( pu, m_triangleMrgCtx );
}
else
{
if( pu.cu->affine )
{
AffineMergeCtx affineMergeCtx;
if ( pu.cs->sps->getSBTMVPEnabledFlag() )
{
Size bufSize = g_miScaling.scale( pu.lumaSize() );
mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );
affineMergeCtx.mrgCtx = &mrgCtx;
}
PU::getAffineMergeCand( pu, affineMergeCtx, pu.mergeIdx );
pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx];
pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx];
pu.cu->GBiIdx = affineMergeCtx.GBiIdx[pu.mergeIdx];
pu.mergeType = affineMergeCtx.mergeType[pu.mergeIdx];
if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )
{
pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + 0][0].refIdx;
pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + 1][0].refIdx;
}
else
{
for( int i = 0; i < 2; ++i )
{
if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 )
{
MvField* mvField = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + i];
pu.mvpIdx[i] = 0;
pu.mvpNum[i] = 0;
pu.mvd[i] = Mv();
PU::setAllAffineMvField( pu, mvField, RefPicList( i ) );
}
}
}
PU::spanMotionInfo( pu, mrgCtx );
}
else
{
#if !JVET_P0400_REMOVE_SHARED_MERGE_LIST
pu.shareParentPos = cu.shareParentPos;
pu.shareParentSize = cu.shareParentSize;
#endif
if (CU::isIBC(*pu.cu))
PU::getIBCMergeCandidates(pu, mrgCtx, pu.mergeIdx);
else
PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx);
mrgCtx.setMergeInfo( pu, pu.mergeIdx );
PU::spanMotionInfo( pu, mrgCtx );
}
}
}
}
}
else
{
#if !JVET_P0400_REMOVE_SHARED_MERGE_LIST
pu.shareParentPos = cu.shareParentPos;
pu.shareParentSize = cu.shareParentSize;
#endif
#if REUSE_CU_RESULTS
if ( cu.imv && !pu.cu->affine && !cu.cs->pcv->isEncoder )
#else
if (cu.imv && !pu.cu->affine)
#endif
{
PU::applyImv(pu, mrgCtx, m_pcInterPred);
}
else
{
if( pu.cu->affine )
{
for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
{
RefPicList eRefList = RefPicList( uiRefListIdx );
if ( pu.cs->slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir & ( 1 << uiRefListIdx ) ) )
{
AffineAMVPInfo affineAMVPInfo;
PU::fillAffineMvpCand( pu, eRefList, pu.refIdx[eRefList], affineAMVPInfo );
const unsigned mvp_idx = pu.mvpIdx[eRefList];
pu.mvpNum[eRefList] = affineAMVPInfo.numCand;
// Mv mv[3];
CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
if (!cu.cs->pcv->isEncoder)
{
pu.mvdAffi[eRefList][0].changeAffinePrecAmvr2Internal(pu.cu->imv);
pu.mvdAffi[eRefList][1].changeAffinePrecAmvr2Internal(pu.cu->imv);
if (cu.affineType == AFFINEMODEL_6PARAM)
{
pu.mvdAffi[eRefList][2].changeAffinePrecAmvr2Internal(pu.cu->imv);
}
}
Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
mvRT += pu.mvdAffi[eRefList][0];
Mv mvLB;
if ( cu.affineType == AFFINEMODEL_6PARAM )
{
mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + pu.mvdAffi[eRefList][2];
mvLB += pu.mvdAffi[eRefList][0];
}
PU::setAllAffineMv(pu, mvLT, mvRT, mvLB, eRefList, true);
}
}
}
else if (CU::isIBC(*pu.cu) && pu.interDir == 1)
{
AMVPInfo amvpInfo;
PU::fillIBCMvpCand(pu, amvpInfo);
pu.mvpNum[REF_PIC_LIST_0] = amvpInfo.numCand;
Mv mvd = pu.mvd[REF_PIC_LIST_0];
#if REUSE_CU_RESULTS
if (!cu.cs->pcv->isEncoder)
#endif
{
mvd.changeIbcPrecAmvr2Internal(pu.cu->imv);
}
if ( pu.cu->slice->getMaxNumIBCMergeCand() == 1 )
{
CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" );
}
pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd;
pu.mv[REF_PIC_LIST_0].mvCliptoStorageBitDepth();
}
else
{
for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
{
RefPicList eRefList = RefPicList( uiRefListIdx );
if ((pu.cs->slice->getNumRefIdx(eRefList) > 0 || (eRefList == REF_PIC_LIST_0 && CU::isIBC(*pu.cu))) && (pu.interDir & (1 << uiRefListIdx)))
{
AMVPInfo amvpInfo;
PU::fillMvpCand(pu, eRefList, pu.refIdx[eRefList], amvpInfo);
pu.mvpNum [eRefList] = amvpInfo.numCand;
if (!cu.cs->pcv->isEncoder)
{
pu.mvd[eRefList].changeTransPrecAmvr2Internal(pu.cu->imv);
}
pu.mv[eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + pu.mvd[eRefList];
pu.mv[eRefList].mvCliptoStorageBitDepth();
}
}
}
PU::spanMotionInfo( pu, mrgCtx );
}
}
if( !cu.triangle )
{
if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) )
{
printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() );
}
}
if (CU::isIBC(cu))
{
const int cuPelX = pu.Y().x;
const int cuPelY = pu.Y().y;
int roiWidth = pu.lwidth();
int roiHeight = pu.lheight();
const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
int xPred = pu.mv[0].getHor() >> MV_FRACTIONAL_BITS_INTERNAL;
int yPred = pu.mv[0].getVer() >> MV_FRACTIONAL_BITS_INTERNAL;
CHECK(!m_pcInterPred->isLumaBvValid(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected.");
}
}
}
//! \}