今天來學習一下幀內預測函數predIntraAng
,用於生成幀內預測圖像。
輸入參數:
const ComponentID compId //In 顏色分量
PelBuf &piPred //In/Out 預測圖像
const PredictionUnit &pu //In 當前PU
const bool useFilteredPredSamples //In 是否進行濾波
相比HEVC新加入的技術:
1.幀內多參考行
2.PDPC
主要流程
1.初始化。
2.根據傳入角度值調用對應預測函數:xPredIntraPlanar(PLANAR模式)、xPredIntraDc(DC模式)、xPredIntraAng(角度模式)。
3.PLANAR、DC、HOR、VER角度和參考行索引爲0時,進行PDPC。
代碼:
//角度預測
void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu, const bool useFilteredPredSamples )
{
const ComponentID compID = MAP_CHROMA( compId );
const ChannelType channelType = toChannelType( compID );
const int iWidth = piPred.width;
const int iHeight = piPred.height;
const uint32_t uiDirMode = PU::getFinalIntraMode( pu, channelType );
CHECK( g_aucLog2[iWidth] < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
CHECK( g_aucLog2[iWidth] > 7, "Size not allowed" );
CHECK( iWidth != iHeight && !pu.cs->pcv->rectCUs, "Rectangular block are only allowed with QTBT" );
#if JVET_L0283_MULTI_REF_LINE
const int multiRefIdx = (compID == COMPONENT_Y) ? pu.multiRefIdx : 0; //多參考行,只在亮度分量啓用
#if JVET_L0279_WAIP_CLEANUP
int whRatio = std::max(1, iWidth / iHeight);
int hwRatio = std::max(1, iHeight / iWidth);
const int srcStride = m_topRefLength + 1 + (whRatio + 1) * multiRefIdx;
const int srcHStride = m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx;
#else
const int srcStride = m_topRefLength + 1 + 5 * multiRefIdx;
const int srcHStride = m_leftRefLength + 1 + 5 * multiRefIdx;
#endif
#else
const int srcStride = m_topRefLength + 1;
const int srcHStride = m_leftRefLength + 1;
#endif
Pel *ptrSrc = getPredictorPtr(compID, useFilteredPredSamples); //參考樣本,單獨開闢buf,在預測之前提前存入
const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compID));
/*****************************************************************************************************************/
switch (uiDirMode) //角度預測,此時沒有進行寬角度擴展
{
//PLANAR
case(PLANAR_IDX): xPredIntraPlanar(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, *pu.cs->sps); break;
//DC
case(DC_IDX): xPredIntraDc(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, false); break;
#if JVET_L0628_4TAP_INTRA
//對角模式2、34、66
case(2):
case(DIA_IDX):
case(VDIA_IDX):
if (getWideAngle(iWidth, iHeight, uiDirMode) == static_cast<int>(uiDirMode)) // check if uiDirMode is not wide-angle
{
xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps
#if JVET_L0283_MULTI_REF_LINE
, multiRefIdx
#endif
, useFilteredPredSamples);
break;
}
//其他角度
default: xPredIntraAng(CPelBuf(getPredictorPtr(compID, false), srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps
#if JVET_L0283_MULTI_REF_LINE
, multiRefIdx
#endif
, useFilteredPredSamples); break;
#else //JVET_L0628_4TAP_INTRA
default: xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps
#if JVET_L0283_MULTI_REF_LINE
, multiRefIdx
#endif
, false); break;
#endif //JVET_L0628_4TAP_INTRA
}
/*****************************************************************************************************************/
//PLANAR、DC、HOR、VER,且參考行索引爲0,進行PDPC
bool pdpcCondition = (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX || uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
#if JVET_L0283_MULTI_REF_LINE
if (pdpcCondition && multiRefIdx == 0)
#else
if (pdpcCondition)
#endif
{
const CPelBuf srcBuf = CPelBuf(ptrSrc, srcStride, srcStride);
PelBuf dstBuf = piPred;
const int scale = ((g_aucLog2[iWidth] - 2 + g_aucLog2[iHeight] - 2 + 2) >> 2);
CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
if (uiDirMode == PLANAR_IDX)
{
//省略具體處理
}
else if (uiDirMode == DC_IDX)
{
//省略具體處理
}
else if (uiDirMode == HOR_IDX)
{
//省略具體處理
}
else if (uiDirMode == VER_IDX)
{
//省略具體處理
}
}
}