Введение в принцип технологии MIP: https://blog.csdn.net/BigDream123/article/details/104939645
Связанный код функции MIP вызывается в первый раз в функции estIntraPredLumaQT, как показано в следующем коде, где
- Функция initIntraMip используется для субдискретизации опорных пикселей и подготовки входных данных для умножения матрицы MIP.
- Функция getNumModesMip получает количество различных режимов MIP в соответствии с размером текущего блока.
- Функция predIntraMip выполняет матричные операции и интерполяцию с повышением частоты дискретизации для получения прогнозируемого значения всего блока.
Примечание. Для использования MIP существует ограничение на размер блока: соотношение сторон не может превышать 1: 8/8: 1.
//MIP允许使用标志
const bool mipAllowed = sps.getUseMIP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.firstPU->lumaSize()));
//MIP模式测试标志:宽高比不能超过1:8/8:1
const bool testMip = mipAllowed && !(cu.lwidth() > (8 * cu.lheight()) || cu.lheight() > (8 * cu.lwidth()));
//MIP支持的最大块尺寸为64
const bool supportedMipBlkSize = pu.lwidth() <= MIP_MAX_WIDTH && pu.lheight() <= MIP_MAX_HEIGHT;
...
...
...
// 初始化Mip模式
initIntraPatternChType(cu, pu.Y());//获取参考像素并滤波
initIntraMip(pu, pu.Y());
// getNumModesMip函数根据当前CU的块尺寸获取不同的Mip模式数量16 8 6
const int transpOff = getNumModesMip(pu.Y());
const int numModesFull = (transpOff << 1);//MIP模式总数分别是32 16 12
for (uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++)
{
//对于另一半MIP模式,其需要进行转置
const bool isTransposed = (uiModeFull >= transpOff ? true : false);
const uint32_t uiMode = (isTransposed ? uiModeFull - transpOff : uiModeFull);
pu.mipTransposedFlag = isTransposed;
pu.intraDir[CHANNEL_TYPE_LUMA] = uiMode;
// Mip预测模式的函数入口,进行MIP预测
predIntraMip(COMPONENT_Y, piPred, pu);
// Use the min between SAD and HAD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);
double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
mipHadCost[uiModeFull] = cost;
DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost,
uiModeFull);
// 更新候选列表,将最优的Mip模式加入到RDCost的候选列表中
updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList,
CandCostList, numModesForFullRD + 1);
updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode),
0.8 * double(minSadHad), uiHadModeList, CandHadList, numHadCand);
}
MIP можно разделить на следующие три случая в зависимости от размера блока:
Размер блока | MIP режим | |
mipSizeId = 0 | 4x4 | 32 |
mipSizeId = 1 | 4xN, Nx4, 8x8 | 16 |
mipSizeId = 2 | Блок отдыха | 12 |
Среди них метка транспонирования MIP связана с номером режима MIP:
- Когда mipSizdId = 0, mipTransposedFlag первых 16 режимов равен 0, а mipTransposedFlag последних 16 режимов равен 1.
- Когда mipSizeId = 1, mipTransposedFlag первых 8 режимов равен 0, а mipTransposedFlag последних 8 режимов равен 1
- Когда mipSizeId = 2, mipTransposedFlag = 0 для первых 6 режимов и mipTransposedFlag = 1 для последних 6 режимов.
Код функции getNumModesMip выглядит следующим образом:
int getNumModesMip(const Size& block)
{
switch( getMipSizeId(block) )
{
case 0: return 16;
case 1: return 8;
case 2: return 6;
default: THROW( "Invalid mipSizeId" );
}
}
Ссылка на код, связанный с функцией InitIntraMip: https://blog.csdn.net/BigDream123/article/details/107018446
Ссылка на код, связанный с функцией PredIntraMip: https://blog.csdn.net/BigDream123/article/details/107019458