Commit a375e85c authored by Shelly Chiang's avatar Shelly Chiang

merge MHIntra into VTM

parent 8fa61a05
......@@ -127,6 +127,7 @@ LMChroma : 1 # use CCLM only
DepQuant : 1
IMV : 2
ALF : 1
MHIntra : 1
# Fast tools
PBIntraFast : 1
......
......@@ -129,6 +129,7 @@ IMV : 2
ALF : 1
GBi : 1
GBiFast : 1
MHIntra : 1
# Fast tools
PBIntraFast : 1
......
......@@ -143,6 +143,7 @@ IMV : 2
ALF : 1
GBi : 1
GBiFast : 1
MHIntra : 1
# Fast tools
PBIntraFast : 1
......
......@@ -242,6 +242,9 @@ void EncApp::xInitLibCfg()
#if JVET_L0646_GBI
m_cEncLib.setUseGBi ( m_GBi );
m_cEncLib.setUseGBiFast ( m_GBiFast );
#endif
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
m_cEncLib.setUseMHIntra ( m_MHIntra );
#endif
// ADD_NEW_TOOL : (encoder app) add setting of tool enabling flags and associated parameters here
......
......@@ -847,6 +847,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
#if JVET_L0646_GBI
("GBi", m_GBi, false, "Enable Generalized Bi-prediction(GBi)")
("GBiFast", m_GBiFast, false, "Fast methods for Generalized Bi-prediction(GBi)\n")
#endif
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
("MHIntra", m_MHIntra, false, "Enable MHIntra mode")
#endif
// ADD_NEW_TOOL : (encoder app) add parsing parameters here
......@@ -3122,6 +3125,9 @@ void EncAppCfg::xPrintParameter()
#if JVET_L0646_GBI
msg( VERBOSE, "GBi:%d ", m_GBi );
msg( VERBOSE, "GBiFast:%d ", m_GBiFast );
#endif
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
msg(VERBOSE, "MHIntra:%d ", m_MHIntra);
#endif
}
// ADD_NEW_TOOL (add some output indicating the usage of tools)
......
......@@ -225,6 +225,10 @@ protected:
bool m_GBi;
bool m_GBiFast;
#endif
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
bool m_MHIntra;
#endif
// ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
unsigned m_uiMaxCUWidth; ///< max. CU width in pixel
......
......@@ -106,6 +106,9 @@ enum CodingStatisticsType
STATS__CABAC_BITS__EMT_CU_FLAG,
STATS__CABAC_BITS__EMT_TU_INDEX,
STATS__TOOL_EMT,
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
STATS__CABAC_BITS__MH_INTRA_FLAG,
#endif
STATS__TOOL_TOTAL,
STATS__NUM_STATS
};
......@@ -178,6 +181,9 @@ static inline const char* getName(CodingStatisticsType name)
#endif
"CABAC_BITS__EMT_CU_FLAG",
"CABAC_BITS__EMT_TU_INDX",
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
"CABAC_BITS__MH_INTRA_FLAG",
#endif
"CABAC_BITS__OTHER",
"CABAC_BITS__INVALID",
"TOOL_FRAME",
......
......@@ -777,6 +777,21 @@ const CtxSet ContextSetCfg::ctbAlfFlag =
} )
};
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
const CtxSet ContextSetCfg::MHIntraFlag = ContextSetCfg::addCtxSet
({
{ 154, },
{ 110, },
{ CNU, },
});
const CtxSet ContextSetCfg::MHIntraPredMode = ContextSetCfg::addCtxSet
({
{ 183, CNU, CNU, CNU, },
{ 154, CNU, CNU, CNU, },
{ 184, CNU, CNU, CNU, },
});
#endif
const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size();
......
......@@ -195,6 +195,10 @@ public:
static const CtxSet GBiIdx;
#endif
static const CtxSet ctbAlfFlag;
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
static const CtxSet MHIntraFlag;
static const CtxSet MHIntraPredMode;
#endif
static const unsigned NumberOfContexts;
// combined sets for less complex copying
......
......@@ -141,6 +141,15 @@ IntraPrediction::IntraPrediction()
m_piYuvExt[ch][buf] = nullptr;
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
m_yuvExt2[ch][buf] = nullptr;
}
}
#endif
m_piTemp = nullptr;
}
......@@ -160,6 +169,16 @@ void IntraPrediction::destroy()
m_piYuvExt[ch][buf] = nullptr;
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
delete[] m_yuvExt2[ch][buf];
m_yuvExt2[ch][buf] = nullptr;
}
}
#endif
delete[] m_piTemp;
m_piTemp = nullptr;
......@@ -173,6 +192,13 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth
destroy();
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (m_yuvExt2[COMPONENT_Y][0] != nullptr && m_currChromaFormat != chromaFormatIDC)
{
destroy();
}
#endif
m_currChromaFormat = chromaFormatIDC;
if (m_piYuvExt[COMPONENT_Y][PRED_BUF_UNFILTERED] == nullptr) // check if first is null (in which case, nothing initialised yet)
......@@ -188,6 +214,21 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (m_yuvExt2[COMPONENT_Y][0] == nullptr) // check if first is null (in which case, nothing initialised yet)
{
m_yuvExtSize2 = (MAX_CU_SIZE) * (MAX_CU_SIZE);
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
m_yuvExt2[ch][buf] = new Pel[m_yuvExtSize2];
}
}
}
#endif
int shift = bitDepthY + 4;
for (int i = 32; i < 64; i++)
{
......@@ -796,6 +837,133 @@ bool IntraPrediction::useDPCMForFirstPassIntraEstimation(const PredictionUnit &p
return CU::isRDPCMEnabled(*pu.cu) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
void IntraPrediction::geneWeightedPred(const ComponentID compId, PelBuf &pred, const PredictionUnit &pu, Pel *srcBuf)
{
const int width = pred.width;
const int height = pred.height;
const int srcStride = width;
const int dstStride = pred.stride;
const uint32_t dirMode = PU::getFinalIntraMode(pu, toChannelType(compId));
const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compId));
Pel* dstBuf = pred.buf;
int k, l;
bool modeDC = (dirMode <= DC_IDX);
Pel wIntra1 = 6, wInter1 = 2, wIntra2 = 5, wInter2 = 3, wIntra3 = 3, wInter3 = 5, wIntra4 = 2, wInter4 = 6;
if (modeDC || width < 4 || height < 4)
{
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * 4) + (srcBuf[k*srcStride + l] * 4)) >> 3), clpRng);
}
}
}
else
{
if (dirMode <= DIA_IDX)
{
int interval = (width >> 2);
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
if (l<interval)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter1) + (srcBuf[k*srcStride + l] * wIntra1)) >> 3), clpRng);
}
else if (l >= interval && l < (2 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter2) + (srcBuf[k*srcStride + l] * wIntra2)) >> 3), clpRng);
}
else if (l >= (interval * 2) && l < (3 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter3) + (srcBuf[k*srcStride + l] * wIntra3)) >> 3), clpRng);
}
else
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter4) + (srcBuf[k*srcStride + l] * wIntra4)) >> 3), clpRng);
}
}
}
}
else
{
int interval = (height >> 2);
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
if (k<interval)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter1) + (srcBuf[k*srcStride + l] * wIntra1)) >> 3), clpRng);
}
else if (k >= interval && k < (2 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter2) + (srcBuf[k*srcStride + l] * wIntra2)) >> 3), clpRng);
}
else if (k >= (interval * 2) && k < (3 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter3) + (srcBuf[k*srcStride + l] * wIntra3)) >> 3), clpRng);
}
else
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter4) + (srcBuf[k*srcStride + l] * wIntra4)) >> 3), clpRng);
}
}
}
}
}
}
void IntraPrediction::switchBuffer(const PredictionUnit &pu, ComponentID compID, PelBuf srcBuff, Pel *dst)
{
Pel *src = srcBuff.bufAt(0, 0);
int compWidth = compID == COMPONENT_Y ? pu.Y().width : pu.Cb().width;
int compHeight = compID == COMPONENT_Y ? pu.Y().height : pu.Cb().height;
for (int i = 0; i < compHeight; i++)
{
for (int j = 0; j < compWidth; j++)
{
dst[j] = src[j];
}
src += srcBuff.stride;
dst += compWidth;
}
}
void IntraPrediction::geneIntrainterPred(const CodingUnit &cu)
{
if (!cu.firstPU->MHIntraFlag)
{
return;
}
const PredictionUnit* pu = cu.firstPU;
bool isUseFilter = IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, *pu, true, *pu);
initIntraPatternChType(cu, pu->Y(), isUseFilter);
predIntraAng(COMPONENT_Y, cu.cs->getPredBuf(*pu).Y(), *pu, isUseFilter);
isUseFilter = IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Cb, *pu, true, *pu);
initIntraPatternChType(cu, pu->Cb(), isUseFilter);
predIntraAng(COMPONENT_Cb, cu.cs->getPredBuf(*pu).Cb(), *pu, isUseFilter);
isUseFilter = IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Cr, *pu, true, *pu);
initIntraPatternChType(cu, pu->Cr(), isUseFilter);
predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu, isUseFilter);
for (int currCompID = 0; currCompID < 3; currCompID++)
{
ComponentID currCompID2 = (ComponentID)currCompID;
PelBuf tmpBuf = currCompID == 0 ? cu.cs->getPredBuf(*pu).Y() : (currCompID == 1 ? cu.cs->getPredBuf(*pu).Cb() : cu.cs->getPredBuf(*pu).Cr());
switchBuffer(*pu, currCompID2, tmpBuf, getPredictorPtr2(currCompID2, 0));
}
}
#endif
inline bool isAboveLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT );
inline int isAboveAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags );
inline int isLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags );
......
......@@ -69,6 +69,10 @@ private:
Pel* m_piYuvExt[MAX_NUM_COMPONENT][NUM_PRED_BUF];
int m_iYuvExtSize;
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
Pel* m_yuvExt2[MAX_NUM_COMPONENT][4];
int m_yuvExtSize2;
#endif
static const uint8_t m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS];
......@@ -126,6 +130,13 @@ public:
static bool useFilteredIntraRefSamples( const ComponentID &compID, const PredictionUnit &pu, bool modeSpecific, const UnitArea &tuArea );
static bool useDPCMForFirstPassIntraEstimation(const PredictionUnit &pu, const uint32_t &uiDirMode);
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
void geneWeightedPred (const ComponentID compId, PelBuf &pred, const PredictionUnit &pu, Pel *srcBuf);
Pel* getPredictorPtr2 (const ComponentID compID, uint32_t idx) { return m_yuvExt2[compID][idx]; }
void switchBuffer (const PredictionUnit &pu, ComponentID compID, PelBuf srcBuff, Pel *dst);
void geneIntrainterPred (const CodingUnit &cu);
#endif
};
//! \}
......
......@@ -353,7 +353,11 @@ void initROM()
// g_aucLog2[ x ]: log2(x), if x=1 -> 0, x=2 -> 1, x=4 -> 2, x=8 -> 3, x=16 -> 4, ...
::memset(g_aucLog2, 0, sizeof(g_aucLog2));
c = 0;
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
for( int i = 0, n = 0; i <= (1 << (MAX_CU_DEPTH + 1)); i++ )
#else
for( int i = 0, n = 0; i <= MAX_CU_SIZE; i++ )
#endif
{
g_aucNextLog2[i] = i <= 1 ? 0 : c + 1;
......@@ -697,9 +701,15 @@ const DecisionTreeTemplate g_mtSplitDTT = compile(
// ====================================================================================================================
SizeIndexInfo* gp_sizeIdxInfo = NULL;
int g_BlockSizeTrafoScale[MAX_CU_SIZE + 1][MAX_CU_SIZE + 1][2];
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
int8_t g_aucLog2 [(1 << (MAX_CU_DEPTH + 1)) + 1];
int8_t g_aucNextLog2[(1 << (MAX_CU_DEPTH + 1)) + 1];
int8_t g_aucPrevLog2[(1 << (MAX_CU_DEPTH + 1)) + 1];
#else
int8_t g_aucLog2 [MAX_CU_SIZE + 1];
int8_t g_aucNextLog2[MAX_CU_SIZE + 1];
int8_t g_aucPrevLog2[MAX_CU_SIZE + 1];
#endif
UnitScale g_miScaling( MIN_CU_LOG2, MIN_CU_LOG2 );
......
......@@ -165,9 +165,15 @@ extern const DecisionTreeTemplate g_qtbtSplitDTT;
// ====================================================================================================================
extern SizeIndexInfo* gp_sizeIdxInfo;
extern int g_BlockSizeTrafoScale [MAX_CU_SIZE + 1][MAX_CU_SIZE + 1][2];
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
extern int8_t g_aucLog2 [(1 << (MAX_CU_DEPTH + 1)) + 1];
extern int8_t g_aucNextLog2 [(1 << (MAX_CU_DEPTH + 1)) + 1];
extern int8_t g_aucPrevLog2 [(1 << (MAX_CU_DEPTH + 1)) + 1];
#else
extern int8_t g_aucLog2 [MAX_CU_SIZE + 1];
extern int8_t g_aucNextLog2 [MAX_CU_SIZE + 1];
extern int8_t g_aucPrevLog2 [MAX_CU_SIZE + 1];
#endif
extern const int8_t i2Log2Tab[257];
inline bool is34( const SizeType& size )
......
......@@ -1640,6 +1640,9 @@ SPSNext::SPSNext( SPS& sps )
, m_Affine ( false )
, m_AffineType ( false )
, m_MTTEnabled ( false )
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
, m_MHIntra ( false )
#endif
#if ENABLE_WPP_PARALLELISM
, m_NextDQP ( false )
#endif
......
......@@ -814,6 +814,9 @@ private:
bool m_GBi; //
#endif
bool m_MTTEnabled; //
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
bool m_MHIntra;
#endif
#if ENABLE_WPP_PARALLELISM
bool m_NextDQP;
#endif
......@@ -921,6 +924,11 @@ public:
void setUseCompositeRef(bool b) { m_compositeRefEnabled = b; }
bool getUseCompositeRef() const { return m_compositeRefEnabled; }
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
void setUseMHIntra ( bool b ) { m_MHIntra = b; }
bool getUseMHIntra () const { return m_MHIntra; }
#endif
// ADD_NEW_TOOL : (sps extension) add access functions for tool enabling flags and associated parameters here
};
......
......@@ -50,6 +50,8 @@
#include <assert.h>
#include <cassert>
#define JVET_L0100_MULTI_HYPOTHESIS_INTRA 1 // Combine intra mode with an extra merge indexed prediction
#define JVET_L0553_FIX_INITQP 1
#define JVET_L0147_ALF_SUBSAMPLED_LAPLACIAN 1 // Subsampled Laplacian calculation
......
......@@ -331,6 +331,11 @@ void PredictionUnit::initData()
mvdAffi[i][j].setZero();
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
MHIntraFlag = false;
intraDir2[0] = PLANAR_IDX;
intraDir2[1] = DM_CHROMA_IDX;
#endif
}
PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData)
......@@ -361,6 +366,11 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
mvdAffi[i][j] = predData.mvdAffi[i][j];
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
MHIntraFlag = predData.MHIntraFlag;
intraDir2[0] = predData.intraDir2[0];
intraDir2[1] = predData.intraDir2[1];
#endif
return *this;
}
......@@ -388,6 +398,11 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
mvdAffi[i][j] = other.mvdAffi[i][j];
}
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
MHIntraFlag = other.MHIntraFlag;
intraDir2[0] = other.intraDir2[0];
intraDir2[1] = other.intraDir2[1];
#endif
return *this;
}
......
......@@ -357,6 +357,10 @@ struct InterPredictionData
int16_t refIdx [NUM_REF_PIC_LIST_01];
MergeType mergeType;
Mv mvdAffi [NUM_REF_PIC_LIST_01][3];
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
bool MHIntraFlag;
uint32_t intraDir2[MAX_NUM_CHANNEL_TYPE];
#endif
};
struct PredictionUnit : public UnitArea, public IntraPredictionData, public InterPredictionData
......
......@@ -309,22 +309,42 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
// Get intra direction of left PU
const PredictionUnit *puLeft = pu.cs->getPURestricted(pos.offset(-1, 0), pu, channelType);
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (puLeft && (CU::isIntra(*puLeft->cu) || (channelType == CHANNEL_TYPE_LUMA && puLeft->MHIntraFlag)))
#else
if (puLeft && CU::isIntra(*puLeft->cu))
#endif
{
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
leftIntraDir = puLeft->MHIntraFlag ? puLeft->intraDir2[channelType] : puLeft->intraDir[channelType];
#else
leftIntraDir = puLeft->intraDir[channelType];
#endif
if (isChroma(channelType) && leftIntraDir == DM_CHROMA_IDX)
{
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
leftIntraDir = puLeft->MHIntraFlag ? puLeft->intraDir2[0] : puLeft->intraDir[0];
#else
leftIntraDir = puLeft->intraDir[0];
#endif
}
}
// Get intra direction of above PU
const PredictionUnit *puAbove = pu.cs->getPURestricted(pos.offset(0, -1), pu, channelType);
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (puAbove && (CU::isIntra(*puAbove->cu) || (channelType == CHANNEL_TYPE_LUMA && puAbove->MHIntraFlag)) && CU::isSameCtu(*pu.cu, *puAbove->cu))
#else
if (puAbove && CU::isIntra(*puAbove->cu) && CU::isSameCtu(*pu.cu, *puAbove->cu))
#endif
{
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
aboveIntraDir = puAbove->MHIntraFlag ? puAbove->intraDir2[channelType] : puAbove->intraDir[channelType];
#else
aboveIntraDir = puAbove->intraDir[channelType];
#endif
if (isChroma(channelType) && aboveIntraDir == DM_CHROMA_IDX)
{
......@@ -478,14 +498,168 @@ bool PU::isChromaIntraModeCrossCheckMode( const PredictionUnit &pu )
return pu.intraDir[CHANNEL_TYPE_CHROMA] == DM_CHROMA_IDX;
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
int PU::getMHIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/, const bool isChromaMDMS /*= false*/, const unsigned startIdx /*= 0*/)
{
const unsigned numMPMs = 3;
{
int numCand = -1;
uint32_t leftIntraDir = DC_IDX, aboveIntraDir = DC_IDX;
const CompArea& area = pu.block(getFirstComponentOfChannel(channelType));
const Position& pos = area.pos();
// Get intra direction of left PU
const PredictionUnit *puLeft = pu.cs->getPURestricted(pos.offset(-1, 0), pu, channelType);
if (puLeft && (CU::isIntra(*puLeft->cu) || puLeft->MHIntraFlag))
{
leftIntraDir = puLeft->MHIntraFlag ? puLeft->intraDir2[channelType] : puLeft->intraDir[channelType];
if (isChroma(channelType) && leftIntraDir == DM_CHROMA_IDX)
{
leftIntraDir = puLeft->MHIntraFlag ? puLeft->intraDir2[0] : puLeft->intraDir[0];
}
}
// Get intra direction of above PU
const PredictionUnit* puAbove = pu.cs->getPURestricted(pos.offset(0, -1), pu, channelType);
if (puAbove && (CU::isIntra(*puAbove->cu) || puAbove->MHIntraFlag) && CU::isSameCtu(*pu.cu, *puAbove->cu))
{
aboveIntraDir = puAbove->MHIntraFlag ? puAbove->intraDir2[channelType] : puAbove->intraDir[channelType];
if (isChroma(channelType) && aboveIntraDir == DM_CHROMA_IDX)
{
aboveIntraDir = puAbove->MHIntraFlag ? puAbove->intraDir2[0] : puAbove->intraDir[0];
}
}
CHECK(2 >= numMPMs, "Invalid number of most probable modes");
uint32_t leftIntraDir2 = leftIntraDir;
uint32_t aboveIntraDir2 = aboveIntraDir;
leftIntraDir2 = (leftIntraDir2 > DC_IDX) ? ((leftIntraDir2 <= DIA_IDX) ? HOR_IDX : VER_IDX) : leftIntraDir2;
aboveIntraDir2 = (aboveIntraDir2 > DC_IDX) ? ((aboveIntraDir2 <= DIA_IDX) ? HOR_IDX : VER_IDX) : aboveIntraDir2;
if (leftIntraDir2 == aboveIntraDir2)
{
numCand = 1;
if (leftIntraDir2 > DC_IDX) // angular modes
{
mpm[0] = leftIntraDir2;
mpm[1] = PLANAR_IDX;
mpm[2] = DC_IDX;
}
else //non-angular
{
mpm[0] = PLANAR_IDX;
mpm[1] = DC_IDX;
mpm[2] = VER_IDX;
}
}
else
{
numCand = 2;
mpm[0] = leftIntraDir2;
mpm[1] = aboveIntraDir2;
if (leftIntraDir2 && aboveIntraDir2) //both modes are non-planar
{
mpm[2] = PLANAR_IDX;
}
else
{
mpm[2] = (leftIntraDir2 + aboveIntraDir2) < 2 ? VER_IDX : DC_IDX;
}
}
int narrowCase = getNarrowShape(pu.lwidth(), pu.lheight());
if (narrowCase > 0)
{
bool isMPM[NUM_LUMA_MODE];
for (int idx = 0; idx < NUM_LUMA_MODE; idx++)
{
isMPM[idx] = false;
}
for (int idx = 0; idx < numMPMs; idx++)
{
isMPM[mpm[idx]] = true;
}
if (narrowCase == 1 && isMPM[HOR_IDX])
{
for (int idx = 0; idx < numMPMs; idx++)
{
if (mpm[idx] == HOR_IDX)
{
if (!isMPM[PLANAR_IDX])
mpm[idx] = PLANAR_IDX;
else if (!isMPM[DC_IDX])
mpm[idx] = DC_IDX;
else if (!isMPM[VER_IDX])
mpm[idx] = VER_IDX;
break;
}
}
}
if (narrowCase == 2 && isMPM[VER_IDX])
{
for (int idx = 0; idx < numMPMs; idx++)
{
if (mpm[idx] == VER_IDX)
{
if (!isMPM[PLANAR_IDX])
mpm[idx] = PLANAR_IDX;
else if (!isMPM[DC_IDX])
mpm[idx] = DC_IDX;
else if (!isMPM[HOR_IDX])
mpm[idx] = HOR_IDX;
break;
}
}
}
}
CHECK(numCand == 0, "No candidates found");
CHECK(mpm[0] == mpm[1] || mpm[0] == mpm[2] || mpm[2] == mpm[1], "redundant MPM");
return numCand;
}
}
int PU::getNarrowShape(const int width, const int height)
{
int longSide = (width > height) ? width : height;
int shortSide = (width > height) ? height : width;
if (longSide > (2 * shortSide))
{
if (longSide == width)
return 1;
else
return 2;
}
else
{
return 0;
}
}
#endif
uint32_t PU::getFinalIntraMode( const PredictionUnit &pu, const ChannelType &chType )
{
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
uint32_t uiIntraMode = pu.MHIntraFlag ? pu.intraDir2[chType] : pu.intraDir[chType];
#else
uint32_t uiIntraMode = pu.intraDir[chType];
#endif
if( uiIntraMode == DM_CHROMA_IDX && !isLuma( chType ) )
{
const PredictionUnit &lumaPU = CS::isDualITree( *pu.cs ) ? *pu.cs->picture->cs->getPU( pu.blocks[chType].lumaPos(), CHANNEL_TYPE_LUMA ) : *pu.cs->getPU( pu.blocks[chType].lumaPos(), CHANNEL_TYPE_LUMA );
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
uiIntraMode = pu.MHIntraFlag ? pu.intraDir2[0] : lumaPU.intraDir[0];
#else
uiIntraMode = lumaPU.intraDir[0];
#endif
}
if( pu.chromaFormat == CHROMA_422 && !isLuma( chType ) )
{
......