Commit 836a1b71 authored by Liang Zhao's avatar Liang Zhao Committed by Frank Bossen

JVET-L0283 multi-line intra prediction

parent aa5b45ca
......@@ -196,6 +196,12 @@ static const int ADJ_DEQUANT_SHIFT = ( ADJ_QUANT_SHIFT + 1 );
static const int RVM_VCEGAM10_M = 4;
#if JVET_L0283_MULTI_REF_LINE
static const int MAX_REF_LINE_IDX = 3; //highest refLine offset in the list
static const int MRL_NUM_REF_LINES = 3; //number of candidates in the array
static const int MULTI_REF_LINE_IDX[4] = { 0, 1, 3, 0 };
#endif
static const int NUM_LUMA_MODE = 67; ///< Planar + DC + 65 directional mode (4*16 + 1)
#if JVET_L0338_MDLM
static const int NUM_LMC_MODE = 1 + 2; ///< LMC + MDLM_T + MDLM_L
......
......@@ -349,6 +349,15 @@ const CtxSet ContextSetCfg::PredMode = ContextSetCfg::addCtxSet
{ CNU,},
});
#if JVET_L0283_MULTI_REF_LINE
const CtxSet ContextSetCfg::MultiRefLineIdx = ContextSetCfg::addCtxSet
({
{ 154, 154, 154 },
{ 154, 154, 154 },
{ CNU, CNU, CNU },
});
#endif
const CtxSet ContextSetCfg::IPredMode[] =
{
ContextSetCfg::addCtxSet
......
......@@ -161,6 +161,9 @@ public:
static const CtxSet MergeIdx;
static const CtxSet PartSize;
static const CtxSet PredMode;
#if JVET_L0283_MULTI_REF_LINE
static const CtxSet MultiRefLineIdx;
#endif
static const CtxSet IPredMode [2]; // [ ChannelType ]
static const CtxSet PdpcFlag;
static const CtxSet DeltaQP;
......
This diff is collapsed.
......@@ -92,18 +92,34 @@ protected:
void xPredIntraPlanar ( const CPelBuf &pSrc, PelBuf &pDst, const SPS& sps );
void xPredIntraDc ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const bool enableBoundaryFilter = true );
#if HEVC_USE_HOR_VER_PREDFILTERING
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const bool bEnableEdgeFilters, const SPS& sps, const bool enableBoundaryFilter = true );
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const bool bEnableEdgeFilters, const SPS& sps
#if JVET_L0283_MULTI_REF_LINE
, int multiRefIdx
#endif
, const bool enableBoundaryFilter = true );
#else
#if JVET_L0628_4TAP_INTRA
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool useFilteredPredSamples );
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps
#if JVET_L0283_MULTI_REF_LINE
, int multiRefIdx
#endif
, const bool useFilteredPredSamples );
#else
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool enableBoundaryFilter = true );
void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps
#if JVET_L0283_MULTI_REF_LINE
, int multiRefIdx
#endif
, const bool enableBoundaryFilter = true );
#endif //JVET_L0628_4TAP_INTRA
#endif
Pel xGetPredValDc ( const CPelBuf &pSrc, const Size &dstSize );
void xFillReferenceSamples ( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu );
void xFilterReferenceSamples ( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps );
void xFilterReferenceSamples ( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps
#if JVET_L0283_MULTI_REF_LINE
, int multiRefIdx
#endif
);
#if HEVC_USE_DC_PREDFILTERING
// dc filtering
......
......@@ -107,6 +107,8 @@
#define JVET_L0260_AFFINE_ME 1
#define JVET_L0283_MULTI_REF_LINE 1
#define JVET_L0256_BIO 1
#define JVET_L0646_GBI 1 // Generalized bi-prediction (GBi)
......
......@@ -329,6 +329,9 @@ void PredictionUnit::initData()
// intra data - need this default initialization for PCM
intraDir[0] = DC_IDX;
intraDir[1] = PLANAR_IDX;
#if JVET_L0283_MULTI_REF_LINE
multiRefIdx = 0;
#endif
// inter data
mergeFlag = false;
......@@ -368,6 +371,9 @@ PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData)
{
intraDir[i] = predData.intraDir[i];
}
#if JVET_L0283_MULTI_REF_LINE
multiRefIdx = predData.multiRefIdx;
#endif
return *this;
}
......@@ -413,6 +419,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
{
intraDir[ i ] = other.intraDir[ i ];
}
#if JVET_L0283_MULTI_REF_LINE
multiRefIdx = other.multiRefIdx;
#endif
mergeFlag = other.mergeFlag;
mergeIdx = other.mergeIdx;
......
......@@ -349,6 +349,9 @@ struct CodingUnit : public UnitArea
struct IntraPredictionData
{
uint32_t intraDir[MAX_NUM_CHANNEL_TYPE];
#if JVET_L0283_MULTI_REF_LINE
int multiRefIdx;
#endif
};
struct InterPredictionData
......
......@@ -299,6 +299,9 @@ cTUTraverser CU::traverseTUs( const CodingUnit& cu )
int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/ )
{
const unsigned numMPMs = pu.cs->pcv->numMPMs;
#if JVET_L0283_MULTI_REF_LINE
const int extendRefLine = (channelType == CHANNEL_TYPE_LUMA) ? pu.multiRefIdx : 0;
#endif
{
int numCand = -1;
#if JVET_L0165_6MPM
......@@ -327,56 +330,130 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
const int offset = (int)NUM_LUMA_MODE - 6;
const int mod = offset + 3;
mpm[0] = leftIntraDir;
mpm[1] = (mpm[0] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
mpm[2] = VER_IDX;
mpm[3] = HOR_IDX;
mpm[4] = VER_IDX - 4;
mpm[5] = VER_IDX + 4;
if (leftIntraDir == aboveIntraDir)
#if JVET_L0283_MULTI_REF_LINE
if (extendRefLine)
{
numCand = 1;
int modeIdx = 0;
int angularMode[2] = { 0, 0 };
if (leftIntraDir > DC_IDX)
{
mpm[0] = leftIntraDir;
mpm[1] = PLANAR_IDX;
mpm[2] = DC_IDX;
mpm[3] = ((leftIntraDir + offset) % mod) + 2;
mpm[4] = ((leftIntraDir - 1) % mod) + 2;
mpm[5] = ((leftIntraDir + offset - 1) % mod) + 2;
angularMode[modeIdx++] = leftIntraDir;
}
if (aboveIntraDir > DC_IDX)
{
angularMode[modeIdx++] = aboveIntraDir;
}
if (modeIdx == 0)
{
mpm[0] = VER_IDX;
mpm[1] = HOR_IDX;
mpm[2] = 2;
mpm[3] = DIA_IDX;
mpm[4] = VDIA_IDX;
mpm[5] = 26;
}
else if (modeIdx == 1)
{
mpm[0] = angularMode[0];
mpm[1] = ((angularMode[0] + offset) % mod) + 2;
mpm[2] = ((angularMode[0] - 1) % mod) + 2;
mpm[3] = ((angularMode[0] + offset - 1) % mod) + 2;
mpm[4] = (angularMode[0] % mod) + 2;
mpm[5] = ((angularMode[0] + offset - 2) % mod) + 2;
}
else
{
mpm[0] = angularMode[0];
mpm[1] = angularMode[1];
int maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
int minCandModeIdx = 1 - maxCandModeIdx;
if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 1)
{
mpm[2] = ((angularMode[minCandModeIdx] + offset) % mod) + 2;
mpm[3] = ((angularMode[maxCandModeIdx] - 1) % mod) + 2;
mpm[4] = ((angularMode[minCandModeIdx] + offset - 1) % mod) + 2;
mpm[5] = ( angularMode[maxCandModeIdx] % mod) + 2;
}
else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] >= 62)
{
mpm[2] = ((angularMode[minCandModeIdx] - 1) % mod) + 2;
mpm[3] = ((angularMode[maxCandModeIdx] + offset) % mod) + 2;
mpm[4] = ((angularMode[minCandModeIdx]) % mod) + 2;
mpm[5] = ((angularMode[maxCandModeIdx] + offset - 1) % mod) + 2;
}
else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 2)
{
mpm[2] = ((angularMode[minCandModeIdx] - 1) % mod) + 2;
mpm[3] = ((angularMode[minCandModeIdx] + offset) % mod) + 2;
mpm[4] = ((angularMode[maxCandModeIdx] - 1) % mod) + 2;
mpm[5] = ((angularMode[minCandModeIdx] + offset - 1) % mod) + 2;
}
else
{
mpm[2] = ((angularMode[minCandModeIdx] + offset) % mod) + 2;
mpm[3] = ((angularMode[minCandModeIdx] - 1) % mod) + 2;
mpm[4] = ((angularMode[maxCandModeIdx] + offset) % mod) + 2;
mpm[5] = ((angularMode[maxCandModeIdx] - 1) % mod) + 2;
}
}
}
else //L!=A
else
{
numCand = 2;
#endif
mpm[0] = leftIntraDir;
mpm[1] = aboveIntraDir;
bool maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
mpm[1] = (mpm[0] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
mpm[2] = VER_IDX;
mpm[3] = HOR_IDX;
mpm[4] = VER_IDX - 4;
mpm[5] = VER_IDX + 4;
if ((leftIntraDir > DC_IDX) && (aboveIntraDir > DC_IDX))
if (leftIntraDir == aboveIntraDir)
{
mpm[2] = PLANAR_IDX;
mpm[3] = DC_IDX;
if ((mpm[maxCandModeIdx] - mpm[!maxCandModeIdx] < 63) && (mpm[maxCandModeIdx] - mpm[!maxCandModeIdx] > 1))
numCand = 1;
if (leftIntraDir > DC_IDX)
{
mpm[4] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx] - 1) % mod) + 2;
}
else
{
mpm[4] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx] ) % mod) + 2;
mpm[0] = leftIntraDir;
mpm[1] = PLANAR_IDX;
mpm[2] = DC_IDX;
mpm[3] = ((leftIntraDir + offset) % mod) + 2;
mpm[4] = ((leftIntraDir - 1) % mod) + 2;
mpm[5] = ((leftIntraDir + offset - 1) % mod) + 2;
}
}
else if (leftIntraDir + aboveIntraDir >= 2)
else //L!=A
{
mpm[2] = (mpm[!maxCandModeIdx] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
mpm[3] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
mpm[4] = ((mpm[maxCandModeIdx] - 1) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
numCand = 2;
mpm[0] = leftIntraDir;
mpm[1] = aboveIntraDir;
bool maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
if ((leftIntraDir > DC_IDX) && (aboveIntraDir > DC_IDX))
{
mpm[2] = PLANAR_IDX;
mpm[3] = DC_IDX;
if ((mpm[maxCandModeIdx] - mpm[!maxCandModeIdx] < 63) && (mpm[maxCandModeIdx] - mpm[!maxCandModeIdx] > 1))
{
mpm[4] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx] - 1) % mod) + 2;
}
else
{
mpm[4] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx]) % mod) + 2;
}
}
else if (leftIntraDir + aboveIntraDir >= 2)
{
mpm[2] = (mpm[!maxCandModeIdx] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
mpm[3] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
mpm[4] = ((mpm[maxCandModeIdx] - 1) % mod) + 2;
mpm[5] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
}
}
#if JVET_L0283_MULTI_REF_LINE
}
#endif
#else
int leftIntraDir = DC_IDX, aboveIntraDir = DC_IDX;
......@@ -422,6 +499,71 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
const int offset = 61;
const int mod = 64;
#if JVET_L0283_MULTI_REF_LINE
if (extendRefLine)
{
if (leftIntraDir == aboveIntraDir)
{
numCand = 1;
if (leftIntraDir > DC_IDX) // angular modes
{
mpm[0] = leftIntraDir;
mpm[1] = ((leftIntraDir + offset) % mod) + 2;
mpm[2] = ((leftIntraDir - 1) % mod) + 2;
}
else // non-angular
{
mpm[0] = 2;
mpm[1] = HOR_IDX;
mpm[2] = VER_IDX;
}
}
else
{
numCand = 2;
if (leftIntraDir <= DC_IDX && aboveIntraDir <= DC_IDX) // both non-angular
{
mpm[0] = 2;
mpm[1] = HOR_IDX;
mpm[2] = VER_IDX;
}
else if (leftIntraDir <= DC_IDX) // left non-angular
{
mpm[0] = aboveIntraDir;
mpm[1] = ((aboveIntraDir + offset) % mod) + 2;
mpm[2] = ((aboveIntraDir - 1) % mod) + 2;
}
else if (aboveIntraDir <= DC_IDX) // above non-angular
{
mpm[0] = leftIntraDir;
mpm[1] = ((leftIntraDir + offset) % mod) + 2;
mpm[2] = ((leftIntraDir - 1) % mod) + 2;
}
else // both angular
{
mpm[0] = leftIntraDir;
mpm[1] = aboveIntraDir;
if (leftIntraDir == VER_IDX)
{
mpm[2] = aboveIntraDir == HOR_IDX ? 2 : HOR_IDX;
}
else if (leftIntraDir == HOR_IDX)
{
mpm[2] = aboveIntraDir == VER_IDX ? 2 : VER_IDX;
}
else
{
mpm[2] = aboveIntraDir == VER_IDX ? HOR_IDX : VER_IDX;
}
}
}
}
else
{
#endif
if (leftIntraDir == aboveIntraDir)
{
numCand = 1;
......@@ -455,6 +597,9 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType
mpm[2] = (leftIntraDir + aboveIntraDir) < 2 ? VER_IDX : DC_IDX;
}
}
#if JVET_L0283_MULTI_REF_LINE
}
#endif
#endif
for (int i = 0; i < numMPMs; i++)
{
......
......@@ -216,9 +216,17 @@ uint32_t getCtuAddr (const Position& pos, const PreCalcValues &pcv);
template<typename T, size_t N>
#if JVET_L0054_MMVD
uint32_t updateCandList(T uiMode, double uiCost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, size_t uiFastCandNum = N, int* iserttPos = nullptr)
uint32_t updateCandList(T uiMode, double uiCost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList
#if JVET_L0283_MULTI_REF_LINE
, static_vector<int, N>& extendRefList, int extendRef
#endif
, size_t uiFastCandNum = N, int* iserttPos = nullptr)
#else
uint32_t updateCandList( T uiMode, double uiCost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, size_t uiFastCandNum = N )
uint32_t updateCandList( T uiMode, double uiCost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList
#if JVET_L0283_MULTI_REF_LINE
, static_vector<int, N>& extendRefList, int extendRef
#endif
, size_t uiFastCandNum = N )
#endif
{
CHECK( std::min( uiFastCandNum, candModeList.size() ) != std::min( uiFastCandNum, candCostList.size() ), "Sizes do not match!" );
......@@ -239,9 +247,21 @@ uint32_t updateCandList( T uiMode, double uiCost, static_vector<T, N>& candModeL
{
candModeList[currSize - i] = candModeList[currSize - 1 - i];
candCostList[currSize - i] = candCostList[currSize - 1 - i];
#if JVET_L0283_MULTI_REF_LINE
if (extendRef != -1)
{
extendRefList[currSize - i] = extendRefList[currSize - 1 - i];
}
#endif
}
candModeList[currSize - shift] = uiMode;
candCostList[currSize - shift] = uiCost;
#if JVET_L0283_MULTI_REF_LINE
if (extendRef != -1)
{
extendRefList[currSize - shift] = extendRef;
}
#endif
#if JVET_L0054_MMVD
if (iserttPos != nullptr)
{
......@@ -254,6 +274,12 @@ uint32_t updateCandList( T uiMode, double uiCost, static_vector<T, N>& candModeL
{
candModeList.insert( candModeList.end() - shift, uiMode );
candCostList.insert( candCostList.end() - shift, uiCost );
#if JVET_L0283_MULTI_REF_LINE
if (extendRef != -1)
{
extendRefList.insert(extendRefList.end() - shift, extendRef);
}
#endif
#if JVET_L0054_MMVD
if (iserttPos != nullptr)
{
......@@ -318,7 +344,7 @@ uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candMode
#if JVET_L0054_MMVD
if (iserttPos != nullptr)
{
*iserttPos = int(candModeList.size() - shift - 1);
*iserttPos = int(candModeList.size() - shift - 1);
}
#endif
return 1;
......@@ -335,5 +361,4 @@ uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candMode
#endif
#endif
#endif
\ No newline at end of file
......@@ -708,6 +708,10 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
// --> create PUs
CU::addPUs( cu );
#if JVET_L0283_MULTI_REF_LINE
extend_ref_line( cu );
#endif
// pcm samples
if( CU::isIntra(cu) && cu.partSize == SIZE_2Nx2N )
{
......@@ -929,6 +933,46 @@ void CABACReader::xReadTruncBinCode(uint32_t& symbol, uint32_t maxSymbol)
}
}
#endif
#if JVET_L0283_MULTI_REF_LINE
void CABACReader::extend_ref_line(CodingUnit& cu)
{
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
cu.firstPU->multiRefIdx = 0;
return;
}
const int numBlocks = CU::getNumPUs(cu);
PredictionUnit* pu = cu.firstPU;
for (int k = 0; k < numBlocks; k++)
{
bool isFirstLineOfCtu = (((cu.block(COMPONENT_Y).y)&((cu.cs->sps)->getMaxCUWidth() - 1)) == 0);
if (isFirstLineOfCtu)
{
pu->multiRefIdx = 0;
continue;
}
int multiRefIdx = 0;
if (MRL_NUM_REF_LINES > 1)
{
multiRefIdx = m_BinDecoder.decodeBin(Ctx::MultiRefLineIdx(0)) == 1 ? MULTI_REF_LINE_IDX[1] : MULTI_REF_LINE_IDX[0];
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
multiRefIdx = m_BinDecoder.decodeBin(Ctx::MultiRefLineIdx(1)) == 1 ? MULTI_REF_LINE_IDX[2] : MULTI_REF_LINE_IDX[1];
if (MRL_NUM_REF_LINES > 3 && multiRefIdx != MULTI_REF_LINE_IDX[1])
{
multiRefIdx = m_BinDecoder.decodeBin(Ctx::MultiRefLineIdx(2)) == 1 ? MULTI_REF_LINE_IDX[3] : MULTI_REF_LINE_IDX[2];
}
}
}
pu->multiRefIdx = multiRefIdx;
pu = pu->next;
}
}
#endif
void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
{
......@@ -946,6 +990,14 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
int mpmFlag[4];
for( int k = 0; k < numBlocks; k++ )
{
#if JVET_L0283_MULTI_REF_LINE
CHECK(numBlocks != 1, "not supported yet");
if (cu.firstPU->multiRefIdx)
{
mpmFlag[0] = true;
}
else
#endif
mpmFlag[k] = m_BinDecoder.decodeBin( Ctx::IPredMode[0]() );
}
......
......@@ -82,6 +82,9 @@ public:
void cu_pred_data ( CodingUnit& cu );
#if JVET_L0646_GBI
void cu_gbi_flag ( CodingUnit& cu );
#endif
#if JVET_L0283_MULTI_REF_LINE
void extend_ref_line (CodingUnit& cu);
#endif
void intra_luma_pred_modes ( CodingUnit& cu );
void intra_chroma_pred_modes ( CodingUnit& cu );
......
......@@ -634,6 +634,10 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C
// prediction mode and partitioning data
pred_mode ( cu );
#if JVET_L0283_MULTI_REF_LINE
extend_ref_line(cu);
#endif
// pcm samples
if( CU::isIntra(cu) && cu.partSize == SIZE_2Nx2N )
{
......@@ -815,6 +819,70 @@ void CABACWriter::xWriteTruncBinCode(uint32_t symbol, uint32_t maxSymbol)
}
#endif
#if JVET_L0283_MULTI_REF_LINE
void CABACWriter::extend_ref_line(const PredictionUnit& pu)
{
const CodingUnit& cu = *pu.cu;
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
return;
}
bool isFirstLineOfCtu = (((cu.block(COMPONENT_Y).y)&((cu.cs->sps)->getMaxCUWidth() - 1)) == 0);
if (isFirstLineOfCtu)
{
return;
}
int multiRefIdx = pu.multiRefIdx;
if (MRL_NUM_REF_LINES > 1)
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
if (MRL_NUM_REF_LINES > 3 && multiRefIdx != MULTI_REF_LINE_IDX[1])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[2], Ctx::MultiRefLineIdx(2));
}
}
}
}
void CABACWriter::extend_ref_line(const CodingUnit& cu)
{
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
return;
}
const int numBlocks = CU::getNumPUs(cu);
const PredictionUnit* pu = cu.firstPU;
for (int k = 0; k < numBlocks; k++)
{
bool isFirstLineOfCtu = (((cu.block(COMPONENT_Y).y)&((cu.cs->sps)->getMaxCUWidth() - 1)) == 0);
if (isFirstLineOfCtu)
{
return;
}
int multiRefIdx = pu->multiRefIdx;
if (MRL_NUM_REF_LINES > 1)
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
if (MRL_NUM_REF_LINES > 3 && multiRefIdx != MULTI_REF_LINE_IDX[1])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[2], Ctx::MultiRefLineIdx(2));
}