/*对当前CU当前深度的四叉树递归进行帧内预测压缩分析,得到当前CU的最优预测,返回其rdcost过程:1.得到当前深度depth,以及当前深度下的modeDepth2.判断当前CU是否可以split?是否可以不split?若是CU是叶子节点,则不可以split;若CU强行split,则不可以不split3.判断当前CU是否已经decided,或深度已经decided。1.若intraRefine等级!=4,且当前CU加载的IPM方向不是ALL_IDX,且bAnalysisType!=HEVC,则bAlreadyDecided为真2.若intraRefine等级!=4,且当前CU深度已经达到了加载的load,则bDecidedDepth为真4.若intraRefine在1~3之间,则更新split和bAlreadyDecided标记5.进行非split模式的计算·若bAlreadyDecided,则1.若深度已经确定且可以不split,则1.初始化CU2.判断是否使用加载的数据3.若使用加载的数据,则加载4.针对加载的数据进行预测计算,得到rdcost5.若尝试lossless,则计算lossless模式下的rdcost,更新当前深度下的bestMode6.若可以split,则计算添加splitFlag编码开销的rdcost·若当前CUsize!=64x64,且可以不split,则计算INTRA_2Nx2N的开销1.初始化INTRA_2Nx2N2.计算INTRA_2Nx2N的最优预测,得到其rdcost3.更新当前深度下的bestMode4.若CUsize=8x8,且TU允许小于8x8,则计算INTRA_NxN的开销1.初始化INTRA_NxN2.计算INTRA_NxN的最优预测,得到其rdcost3.更新当前深度下的bestMode5.若尝试lossless,则计算lossless模式下的rdcost,更新当前深度下的bestMode6.若可以split,则计算添加splitFlag编码开销的rdcost6.更新是否可以split的标志,7.若可以split1.初始化cost以及CU2.取下一层的深度nextDepth及其modeDepth3.标记从nextDepth起到最深一层的熵编码上下文为无效4.遍历split出来的四个subCU1.计算subCU的几何信息2.对subCU递归执行压缩·若subCU没有完全在帧外,即会被显示出来,则1.取原始帧像素fencYUV2.加载熵编码上下文3.若允许CU独立QP,则计算QP4.递归对subCU执行当前compressIntraCU函数进行压缩5.保存subCU的最优预测数据、重建帧reconYUV数据,并累加该subCU的cost到总cost中6.更新熵编码上下文·若subCU完全在帧外,即一点都不会被现实出来,则标记当前subCU为空3.存储当前CU被split后的熵编码上下文4.更新整个CU的rdcost5.更新当前深度的bestMode8.保存当前深度bestMode的数据9.若当前深度的bestMode并不是split,则需要将bestMode的reconYUV存储下来10.返回当前深度的bestMode的rdcost
*/
uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp)
{//当前CU的深度uint32_t depth = cuGeom.depth;//当前CU深度的modeDepthModeDepth& md = m_modeDepth[depth];//初始化深度的bestmode = nullmd.bestMode = NULL;//可以split,非叶节点都可以splitbool mightSplit = !(cuGeom.flags & CUGeom::LEAF);//可以不split,即不强制split的CU都可以不splitbool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);//初始化split = false,即不再splitint split = 0;//若intraRefine != 4 && 当前CU的帧内预测方向不是all && bAnalysisType != HEVC_INFObool bAlreadyDecided = m_param->intraRefine != 4 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] != (uint8_t)ALL_IDX && !(m_param->bAnalysisType == HEVC_INFO);//intraRefine != 4 && 当前深度达到了载入的CU深度bool bDecidedDepth = m_param->intraRefine != 4 && parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth;//若intraRefine在 1, 2, 3之中,即使用load的数据但会进行适当修正if (m_param->intraRefine && m_param->intraRefine != 4){/*  若开启了scale analysis save && 已经决定了深度 && (一定要split || 当前CU的大小比允许的最小CU大小大一级)则要split */split = m_param->scaleFactor && bDecidedDepth // depth已经decided&& (!mightNotSplit // 一定要split || 深度在最小CU尺寸深度的上一级|| ((cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param->minCUSize] + 1))));//若当前CU的大小达到了允许的最小大小 && depth还没decidedif (cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param->minCUSize]) && !bDecidedDepth)bAlreadyDecided = false;}if (bAlreadyDecided) //已经决定{//depth已经decided && 可以不splitif (bDecidedDepth && mightNotSplit){Mode& mode = md.pred[0];md.bestMode = &mode;//初始化CUmode.cu.initSubCU(parentCTU, cuGeom, qp);//是否使用加载的预测信息,即 既不intraRefine == 3,也不(intraRefine == 3 && 加载的CU帧内预测方向为angle类型)bool reuseModes = !((m_param->intraRefine == 3) ||(m_param->intraRefine == 2 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] > DC_IDX));//若使用加载的预测信息,则加载它们if (reuseModes){//拷贝luma和chroma的intra directionmemcpy(mode.cu.m_lumaIntraDir, parentCTU.m_lumaIntraDir + cuGeom.absPartIdx, cuGeom.numPartitions);memcpy(mode.cu.m_chromaIntraDir, parentCTU.m_chromaIntraDir + cuGeom.absPartIdx, cuGeom.numPartitions);}//计算开销checkIntra(mode, cuGeom, (PartSize)parentCTU.m_partSize[cuGeom.absPartIdx]);//若bTryLossless,则尝试无损编码if (m_bTryLossless)tryLossless(cuGeom);//可以split,则计算添加splitFlag后的rdcostif (mightSplit)addSplitFlagCost(*md.bestMode, cuGeom.depth);}}//若不是64x64 && 可以不splitelse if (cuGeom.log2CUSize != MAX_LOG2_CU_SIZE && mightNotSplit){/*计算不split的Intra2Nx2N开销*///初始化intramd.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);//计算Intra2Nx2N的rdcostcheckIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N);//更新bestModecheckBestMode(md.pred[PRED_INTRA], depth);//若是CU是8x8 && TU允许小于8x8if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3){/*计算8x8CU中的4x4PU模式*///初始化intra NxNmd.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);//计算intra NxN的rdcostcheckIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN);//更新bestModecheckBestMode(md.pred[PRED_INTRA_NxN], depth);}//若bTryLossless,则计算lossless模式,并更新bestModeif (m_bTryLossless)tryLossless(cuGeom);//可以split,则计算添加splitFlag后的rdcostif (mightSplit)addSplitFlagCost(*md.bestMode, cuGeom.depth);}/* stop recursion if we reach the depth of previous analysis decision如果我们达到之前分析的深度,停止递归split没有decided || 没有决定深度 || 可以split*/mightSplit &= !(bAlreadyDecided && bDecidedDepth) || split;//若可以split,则递归对subBlock进行压缩分析if (mightSplit){//取split的modeMode* splitPred = &md.pred[PRED_SPLIT];//初始化split模式下的costsplitPred->initCosts();//取split模式下的CUdataCUData* splitCU = &splitPred->cu;//初始化子CUsplitCU->initSubCU(parentCTU, cuGeom, qp);//nextDepthuint32_t nextDepth = depth + 1;//根据nextDepth得到ModeDepthModeDepth& nd = m_modeDepth[nextDepth];//无效nextDepth深度一直到最深的四叉树上下文invalidateContexts(nextDepth);//将当前四叉树的上下文作为下一深度的上下文Entropy* nextContext = &m_rqt[depth].cur;//当前qp作为下一深度的qpint32_t nextQP = qp;//初始化curCost为0,curCost累加四个subBlock的costuint64_t curCost = 0;//初始化skipSplitCheck为0int skipSplitCheck = 0;//进行四个subCU遍历for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)   //遍历4个subCU{//得到subCU的CUGeomconst CUGeom& childGeom = *(&cuGeom + cuGeom.childOffset + subPartIdx);//若subCU没有完全在帧外if (childGeom.flags & CUGeom::PRESENT){//取fencYUVm_modeDepth[0].fencYuv.copyPartToYuv(nd.fencYuv, childGeom.absPartIdx);//加载上下文m_rqt[nextDepth].cur.load(*nextContext);//若使用DQP(CU独立QP),且深度在最大的允许DQP深度内,则进行独立QPif (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth)nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom));/*递归进行CU压缩*///若允许bEnableSplitRdSkip,即累加subCU过程中一旦超过bestMode,立马停止if (m_param->bEnableSplitRdSkip){//累加subBlock的rdCostcurCost += compressIntraCU(parentCTU, childGeom, nextQP);//若累加的rdCost > 当前bestMode的rdCost,则break停止计算,标记skipSplitCheckif (m_modeDepth[depth].bestMode && curCost > m_modeDepth[depth].bestMode->rdCost){skipSplitCheck = 1;break;}}else //不允许bEnableSplitRdSkip,则老老实实计算所有子CUcompressIntraCU(parentCTU, childGeom, nextQP);// Save best CU and pred data for this sub CU 记录下subBlock的最优预测数据splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);//添加其costsplitPred->addSubCosts(*nd.bestMode);//将bestMode下的reconYUV保存下来nd.bestMode->reconYuv.copyToPartYuv(splitPred->reconYuv, childGeom.numPartitions * subPartIdx);//更新上下文nextContext = &nd.bestMode->contexts;}else //subCU完全在帧外,则不用进行计算了{/* record the depth of this non-present sub-CU 记录深度,该subBlock不显示,设置为空*/splitCU->setEmptyPart(childGeom, subPartIdx);/* Set depth of non-present CU to 0 to ensure that correct CU is fetched as reference to code deltaQP 将它们的cuDepth置0 */if (bAlreadyDecided)memset(parentCTU.m_cuDepth + childGeom.absPartIdx, 0, childGeom.numPartitions);}} // end of loop over subPartIdx/*若之前发生了累计4个subCU的开销>bestMode的开销时,早退的情况,则跳过这里否则要进行SplitCheck,检查split是否比不split开销小  */if (!skipSplitCheck){//存储当前CU被split后的熵编码上下文nextContext->store(splitPred->contexts);//更新rdcostif (mightNotSplit)addSplitFlagCost(*splitPred, cuGeom.depth);elseupdateModeCost(*splitPred);checkDQPForSplitPred(*splitPred, cuGeom);//更新bestModecheckBestMode(*splitPred, depth);}} //end of if(mightSplit)//若允许RD优化且深度在最大DQP深度内,则缓存rdcostif (m_param->bEnableRdRefine && depth <= m_slice->m_pps->maxCuDQPDepth){int cuIdx = (cuGeom.childOffset - 1) / 3;cacheCost[cuIdx] = md.bestMode->rdCost;}//若CU大小在16x16及以上,且if ((m_limitTU & X265_TU_LIMIT_NEIGH) && cuGeom.log2CUSize >= 4){CUData* ctu = md.bestMode->cu.m_encData->getPicCTU(parentCTU.m_cuAddr);int8_t maxTUDepth = -1;for (uint32_t i = 0; i < cuGeom.numPartitions; i++)maxTUDepth = X265_MAX(maxTUDepth, md.bestMode->cu.m_tuDepth[i]);ctu->m_refTuDepth[cuGeom.geomRecurId] = maxTUDepth;}/* Copy best data to encData CTU and recon */md.bestMode->cu.copyToPic(depth);//若当前深度bestMode不是split,则if (md.bestMode != &md.pred[PRED_SPLIT])md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);//返回当前深度下最优mode的rdCostreturn md.bestMode->rdCost;
}

Analysis::compressIntraCU()相关推荐

  1. x265笔记_4_CompressCTU源码分析

    文章目录 Before `compressCTU` `compressCTU` 输入参数 处理流程 重要变量 `m_parame` `rd_level` `amp`和`rect` 重要函数 `comp ...

  2. Analysis::compressCTU()

    x265编码器在编码一帧时以行为单位进行WPP编码,一行一个线程,每个线程分别对自己的行中每个CTU进行compressCTU压缩分析 /*压缩分析CTU过程:1.为当前CTU加载QP/熵编码上下文2 ...

  3. TensorRT Analysis Report分析报告

    TensorRT Analysis Report 一.介绍 TensorRT是一个高性能的深度学习推理(Inference)优化器,可以为深度学习应用提供低延迟.高吞吐率的部署推理.TensorRT可 ...

  4. PCA(Principal Component Analysis)的原理、算法步骤和实现。

    PCA的原理介绍:  PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分 ...

  5. 机器学习与高维信息检索 - Note 7 - 核主成分分析(Kernel Principal Component Analysis,K-PCA)

    Note 7 - 核主成分分析(Kernel Principal Component Analysis) 核主成分分析 Note 7 - 核主成分分析(Kernel Principal Compone ...

  6. 机器学习与高维信息检索 - Note 4 - 主成分分析及其现代解释(Principal Component Analysis, PCA)及相关实例

    主成分分析及其现代解释 4. 主成分分析及其现代解释 Principal Component Analysis and Its Modern Interpretations 4.1 几何学解释 The ...

  7. 【免费软件测试视频-0013】——Loadrunner9.0 SLA Analysis

    LR9.0---SLA Analysis http://www.3atesting.com/mv/bencandy.php?fid=15&id=16 转载于:https://www.cnblo ...

  8. OpenCV3.3中主成分分析(Principal Components Analysis, PCA)接口简介及使用

    OpenCV3.3中给出了主成分分析(Principal Components Analysis, PCA)的实现,即cv::PCA类,类的声明在include/opencv2/core.hpp文件中 ...

  9. 笔试算法题(58):二分查找树性能分析(Binary Search Tree Performance Analysis)

    议题:二分查找树性能分析(Binary Search Tree Performance Analysis) 分析: 二叉搜索树(Binary Search Tree,BST)是一颗典型的二叉树,同时任 ...

最新文章

  1. 聊一聊ZooKeeper的顺序一致性
  2. 改进C#代码之24:通过定义并实现接口替代继承
  3. 借助C/C++进行Android开发:NDK的配置与使用
  4. 原作者出局,Faker.js已被社区控制
  5. 数据库原理与应用(SQL Server)笔记 第八章 用户自定义数据类型与变量
  6. mac safari无法连接服务器_宇航员乘坐SpaceX飞船返航中iPad上Safari出现“无法连接到网络”错误...
  7. yum仓库与pxe自动装机
  8. Spring Security(四) —— 核心过滤器源码分析
  9. 【华为云技术分享】唐老师带你秒懂大数据,以及Spark和Flink在干啥咧
  10. centos 切换用户_Centos7系统切换Python2到Python3.x
  11. python的三种数据类型列举_3.Python编程之数据类型
  12. 英伟达发布迁移学习工具包,现在可以申请早期试用
  13. 微信小程序API之getSystemInfo
  14. 想做好seo优化,关键词的选择可是重中之重!
  15. supervisor进程守护
  16. JDK API 1.6 中文版 及其简单使用
  17. 怎么申请https证书
  18. 粒径20nm的金纳米粒Nafion-GOx-AuNPs对十二烷醇/葡萄糖氧化酶的标记过程
  19. android原生app转成web,转战WebApp: 最适合Android开发者的WebApp框架
  20. Android之调节屏幕亮度

热门文章

  1. UML及其应用之通信图
  2. 交叉验证python代码_交叉验证以及python代码实现
  3. 深信服校招编程题-替换字符串里的字符
  4. 游侠安全网2011年网络与信息安全趋势10大预测
  5. JavaWeb之【转发与重定向】
  6. 2021-2027全球与中国年度健康访问(AWV)软件市场现状及未来发展趋势
  7. Simulink Test笔记(含一些小技巧)一
  8. LightGBM使用教程
  9. 程序设计【Week9】作业
  10. 手机自动化测试工具实现