H.266/VVC代码学习9:xIntraCodingTUBlock函数
时间:2019-03-18
本文章向大家介绍H.266/VVC代码学习9:xIntraCodingTUBlock函数,主要包括H.266/VVC代码学习9:xIntraCodingTUBlock函数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
这个函数将确定的帧内预测模式进行残差计算、变换量化和反变换重建等操作。具体含义可见代码中注释:
#if JVET_M0464_UNI_MTS
void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &compID, const bool &checkCrossCPrediction, Distortion& ruiDist, const int &default0Save1Load2, uint32_t* numSig, std::vector<TrMode>* trModes, const bool loadTr)
#else
void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &compID, const bool &checkCrossCPrediction, Distortion& ruiDist, const int &default0Save1Load2, uint32_t* numSig )
#endif
{
if (!tu.blocks[compID].valid())
{
return;
}
/****************************************** 初始化 ***************************************/
CodingStructure &cs = *tu.cs;
const CompArea &area = tu.blocks[compID];
const SPS &sps = *cs.sps;
const PPS &pps = *cs.pps;
const ChannelType chType = toChannelType(compID);
const int bitDepth = sps.getBitDepth(chType);
PelBuf piOrg = cs.getOrgBuf (area);//原始
PelBuf piPred = cs.getPredBuf (area);//预测
PelBuf piResi = cs.getResiBuf (area);//残差
PelBuf piOrgResi = cs.getOrgResiBuf(area);
PelBuf piReco = cs.getRecoBuf (area);//重建
const PredictionUnit &pu = *cs.getPU(area.pos(), chType);
const uint32_t uiChFinalMode = PU::getFinalIntraMode(pu, chType);//编码模式,1.DM获取模式的入口,得到预测角度
const bool bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction;
const bool ccUseRecoResi = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();
#if JVET_M0102_INTRA_SUBPARTITIONS
const bool ispSplitIsAllowed = CU::canUseISPSplit( *tu.cu, compID );
#endif
//===== init availability pattern 初始化 =====
PelBuf sharedPredTS( m_pSharedPredTransformSkip[compID], area );
if( default0Save1Load2 != 2 )//如果是不是2个预测值(2个预测值条件:1.不是LM模式 2. 允许使用CCP 3. Y分量的cbf不为0)
{
const bool bUseFilteredPredictions = IntraPrediction::useFilteredIntraRefSamples( compID, pu, true, tu );
initIntraPatternChType( *tu.cu, area, bUseFilteredPredictions );
//===== get prediction signal 计算预测值 =====
if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )//2.LM模式预测,得到预测角度
{
{
xGetLumaRecPixels( pu, area );//获取重建像素
}
predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );//LM模式
}
else//2.角度模式预测
{
predIntraAng( compID, piPred, pu, bUseFilteredPredictions );//正常角度模式
}
// save prediction 保存预测值
if( default0Save1Load2 == 1 )//如果是1个预测值
{
sharedPredTS.copyFrom( piPred );
}
}
else//如果是2个预测值
{
// load prediction 加载预测值
piPred.copyFrom( sharedPredTS );
}
DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), uiChFinalMode );
//DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y );
#if JVET_M0427_INLOOP_RESHAPER
const Slice &slice = *cs.slice;
#if JVET_M0483_IBC
bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()));
#else
bool flag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()) || (slice.getSliceType() == P_SLICE && slice.getSPS()->getIBCMode()));
#endif
/******* 色度模式时 *******/
if (flag && slice.getReshapeInfo().getSliceReshapeChromaAdj() && isChroma(compID))
{
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 );//亮度块
PelBuf piPredY;
piPredY = cs.picture->getPredBuf(areaY);//获取亮度预测缓存
const Pel avgLuma = piPredY.computeAvg();//平均亮度预测值
int adj = m_pcReshape->calculateChromaAdj(avgLuma);//色度预测值
tu.setChromaAdj(adj);//设置色度预测值
}
#endif
//===== get residual signal 计算残差 =====
piResi.copyFrom( piOrg );// 暂时给残差赋值为原始值
#if JVET_M0427_INLOOP_RESHAPER
if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID==COMPONENT_Y)
{
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
tmpPred.copyFrom(piPred);
piResi.rspSignal(m_pcReshape->getFwdLUT());
piResi.subtract(tmpPred);
}
else
#endif
piResi.subtract( piPred );// 残差 = 原始 - 预测
if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isLuma(compID))
{
piOrgResi.copyFrom (piResi);
}
if (bUseCrossCPrediction)
{
if (xCalcCrossComponentPredictionAlpha(tu, compID, ccUseRecoResi) == 0)
{
return;
}
CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, false);
}
//===== transform and quantization 变换量化 =====
//--- init rate estimation arrays for RDOQ ---
//--- transform and quantization ---
TCoeff uiAbsSum = 0;
const QpParam cQP(tu, compID);
#if RDOQ_CHROMA_LAMBDA
m_pcTrQuant->selectLambda(compID);//确定lambda
#endif
/****** 色度块不小时,调整lambda *******/
#if JVET_M0427_INLOOP_RESHAPER
flag =flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);//TU的 宽*高>4 时flag为true
if (flag && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
{
int cResScaleInv = tu.getChromaAdj();
double cResScale = round((double)(1 << CSCALE_FP_PREC) / (double)cResScaleInv);
m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cResScale*cResScale));//调整lambda
piResi.scaleSignal(cResScaleInv, 1, tu.cu->cs->slice->clpRng(compID));
}
#endif
#if JVET_M0102_INTRA_SUBPARTITIONS
double diagRatio = 0, horVerRatio = 0;
#endif
#if JVET_M0464_UNI_MTS
if( trModes )//残差的变换:transformNxN是残差信号变换量化的入口函数:重点!!
{
#if JVET_M0102_INTRA_SUBPARTITIONS
m_pcTrQuant->transformNxN( tu, compID, cQP, trModes, CU::isIntra( *tu.cu ) ? m_pcEncCfg->getIntraMTSMaxCand() : m_pcEncCfg->getInterMTSMaxCand(), ispSplitIsAllowed ? &diagRatio : nullptr, ispSplitIsAllowed ? &horVerRatio : nullptr );
#else
m_pcTrQuant->transformNxN( tu, compID, cQP, trModes, CU::isIntra( *tu.cu ) ? m_pcEncCfg->getIntraMTSMaxCand() : m_pcEncCfg->getInterMTSMaxCand() );
#endif
tu.mtsIdx = trModes->at(0).first;
}
#if JVET_M0102_INTRA_SUBPARTITIONS
m_pcTrQuant->transformNxN( tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr, &diagRatio, &horVerRatio );
#else
m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
#endif
#else
#if JVET_M0102_INTRA_SUBPARTITIONS
m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), ispSplitIsAllowed ? &diagRatio : nullptr, ispSplitIsAllowed ? &horVerRatio : nullptr);
#else
m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx());
#endif
#endif
#if JVET_M0102_INTRA_SUBPARTITIONS
if (!tu.cu->ispMode && isLuma(compID) && ispSplitIsAllowed &&
#if JVET_M0464_UNI_MTS
tu.mtsIdx == 0
#else
!tu.cu->emtFlag
#endif
)
{
m_intraModeDiagRatio .push_back(diagRatio);
m_intraModeHorVerRatio .push_back(horVerRatio);
m_intraModeTestedNormalIntra.push_back((int)uiChFinalMode);
}
#endif
DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), compID, uiAbsSum );
//--- inverse transform 反变换---
if (uiAbsSum > 0)
{
m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);//invtransformNxN是残差信号反变换的入口函数:重点!!
}
else
{
piResi.fill(0);
}
//===== reconstruction 重建 =====
#if JVET_M0427_INLOOP_RESHAPER
if (flag && uiAbsSum > 0 && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
{
piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
}
#endif
if (bUseCrossCPrediction)
{
CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, true);
}
#if JVET_M0427_INLOOP_RESHAPER
if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y)
{
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0,0), area.size());
PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
tmpPred.copyFrom(piPred);
piReco.reconstruct(tmpPred, piResi, cs.slice->clpRng(compID));
}
else
#endif
piReco.reconstruct(piPred, piResi, cs.slice->clpRng( compID ));
//===== update distortion 更新失真值 =====
#if WCG_EXT
#if JVET_M0427_INLOOP_RESHAPER
if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getReshaper()
&& slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
#else
if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
#endif
{
const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
#if JVET_M0427_INLOOP_RESHAPER
if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
{
CompArea tmpArea1(COMPONENT_Y, area.chromaFormat, Position(0, 0
- 浅谈PHP 5中垃圾回收算法的演化
- POJ 2484 A Funny Game(智商博弈)
- php pathinfo()的用法
- BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏(SG函数)
- 微信公众平台开发
- BZOJ 1115: [POI2009]石子游戏Kam (阶梯nim)
- php性能监测模块XHProf
- BZOJ 1022: [SHOI2008]小约翰的游戏John (Anti-nim)
- 洛谷P2252 取石子游戏(威佐夫博弈)
- HDU 3032 Nim or not Nim?(Multi-Nim)
- POJ 2311 Cutting Game(二维SG+Multi-Nim)
- js去掉html标签和去掉字符串文本的所有的空格
- php操作memcache的使用测试总结
- linux awk命令详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Theme preview
- “抽象类”到底抽不抽象?实例对比一看便知!
- C#索引器的实现、索引器和属性的异同对比,这些技能你get到了嘛?
- 我竟然用它搞懂了王者荣耀的技能释放机制!【C#委托】
- 使用docker-compose 搭建 lnmp
- Java接口也有坑?不容忽视!
- 值得练手的JavaGUI项目——色彩调节器的实现【附完整源码】
- 自定义短标签
- Python简单又好玩的项目推荐!【持续更新】
- 使用 JsDelivr作为CDN 加速服务
- Java利用TCP协议实现客户端与服务器通信【附通信源码】
- 增加标签云代替原有标签和分类效果
- 新增搜索功能
- 利用实例巧妙区分“抽象方法”和“虚方法”!
- windows 右键菜单的添加和移除