x265编码器在编码一帧时以行为单位进行WPP编码,一行一个线程,每个线程分别对自己的行中每个CTU进行compressCTU压缩分析

/*压缩分析CTU过程:1.为当前CTU加载QP/熵编码上下文2.是否有编码信息输入来方便快速最优模式分析·bCTUInfo,加载depth/content/prevCtuInfoChange·analysisMultiPassRefine,加载之前pass计算分析得到的mv/mvpIdx/ref/modes/depth·analysisLoad && 非Islice,加载load数据中的Ref/Depth/Modes/PartSize/MergeFlag3.对CTU压缩编码·Islice1.若analysisLoad,则加载cuDepth/partSize/lumaIntraDir/chromaIntraDir2.compressIntraCU·P/Bslice1.判断是否有可用的编码分析数据2.若有可用编码分析数据则拷贝这些可用数据:cuDepth/predMode/partSize/skipFlag/lumaIntraDir/chromaIntraDir3.进行实际的P/Bslice编码·若开启bIntraRefresh,且CTU处于Pir范围内,则对CTU进行compressIntraCU编码·若rdlevel = 01.将原始YUV数据拷贝到recon图像中2.进行compressInterCU_rd0_4压缩编码3.进行encodeResidue编码残差·若analysisLoad1.拷贝cuDepth/predMode/partSize/lumaIntraDir/chromaIntraDir2.进行qprdRefine优化rd qp3.返回CTU的bestMode·若开启bDistributeModeAnalysis,且rdlevel>=2,则进行compressInterCU_dist分布式压缩编码·若rdlevel 0~4,则进行compressInterCU_rd0_4压缩编码·若rdlevel 5~6,则进行compressInterCU_rd5_6压缩编码4.若使用 rd优化 或 CU级qp优化,则进行qprdRefine优化5.若csvlog等级>=2,则collectPUStatistics进行PU信息统计6.返回CTU的bestMode
*/
Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, const Entropy& initialContext)
{//取CTU所在slicem_slice = ctu.m_slice;//取CTU所在framem_frame = &frame;//取paramm_param = m_frame->m_param;//若rdlevel>=3则要计算chroma的sa8dm_bChromaSa8d = m_param->rdLevel >= 3;#if _DEBUG || CHECKED_BUILDinvalidateContexts(0);
#endifint qp = setLambdaFromQP(ctu, m_slice->m_pps->bUseDQP ? calculateQpforCuSize(ctu, cuGeom) : m_slice->m_sliceQp);ctu.setQPSubParts((int8_t)qp, 0, 0);//0深度四叉树加载contextm_rqt[0].cur.load(initialContext);//得到CTU的mean qpctu.m_meanQP = initialContext.m_meanQP;//复制YUV数据到0深度的modeDepth中m_modeDepth[0].fencYuv.copyFromPicYuv(*m_frame->m_fencPic, ctu.m_cuAddr, 0);if (m_param->bSsimRd)   //若使用ssim rdocalculateNormFactor(ctu, qp);//取CTU的4x4块个数uint32_t numPartition = ctu.m_numPartitions;//bCTUInfoif (m_param->bCTUInfo && (*m_frame->m_ctuInfo + ctu.m_cuAddr)){//取CTU的infox265_ctu_info_t* ctuTemp = *m_frame->m_ctuInfo + ctu.m_cuAddr;//深度0int32_t depthIdx = 0;//最大64个8x8块uint32_t maxNum8x8Partitions = 64;//取目标数据存储 depthInfoPtr/contentInfoPtr/prevCtuInfoChangePtruint8_t* depthInfoPtr = m_frame->m_addOnDepth[ctu.m_cuAddr];uint8_t* contentInfoPtr = m_frame->m_addOnCtuInfo[ctu.m_cuAddr];int* prevCtuInfoChangePtr = m_frame->m_addOnPrevChange[ctu.m_cuAddr];//遍历所有的partition,拷贝API外的编码分析数据到目标depthInfoPtr/contentInfoPtr/prevCtuInfoChangePtr中do{//取出API外的编码分析数据depth/content/prevCtuInfoChangeuint8_t depth = (uint8_t)ctuTemp->ctuPartitions[depthIdx];uint8_t content = (uint8_t)(*((int32_t *)ctuTemp->ctuInfo + depthIdx));int prevCtuInfoChange = m_frame->m_prevCtuInfoChange[ctu.m_cuAddr * maxNum8x8Partitions + depthIdx];//将depth/content/prevCtuInfoChange拷贝给addOnDepth/addOnCtuInfo/addOnPrevChangememset(depthInfoPtr, depth, sizeof(uint8_t) * numPartition >> 2 * depth);memset(contentInfoPtr, content, sizeof(uint8_t) * numPartition >> 2 * depth);memset(prevCtuInfoChangePtr, 0, sizeof(int) * numPartition >> 2 * depth);for (uint32_t l = 0; l < numPartition >> 2 * depth; l++)prevCtuInfoChangePtr[l] = prevCtuInfoChange;//更新depthInfoPtr/contentInfoPtr/prevCtuInfoChangePtr数据指针depthInfoPtr += ctu.m_numPartitions >> 2 * depth;contentInfoPtr += ctu.m_numPartitions >> 2 * depth;prevCtuInfoChangePtr += ctu.m_numPartitions >> 2 * depth;depthIdx++;} while (ctuTemp->ctuPartitions[depthIdx] != 0);m_additionalCtuInfo = m_frame->m_addOnCtuInfo[ctu.m_cuAddr];m_prevCtuInfoChange = m_frame->m_addOnPrevChange[ctu.m_cuAddr];memcpy(ctu.m_cuDepth, m_frame->m_addOnDepth[ctu.m_cuAddr], sizeof(uint8_t) * numPartition);//Calculate log2CUSize from depthfor (uint32_t i = 0; i < cuGeom.numPartitions; i++)ctu.m_log2CUSize[i] = (uint8_t)m_param->maxLog2CUSize - ctu.m_cuDepth[i];}//若开启analysisMultiPassRefine && bStatRead && 非Isliceif (m_param->analysisMultiPassRefine && m_param->rc.bStatRead && (m_slice->m_sliceType != I_SLICE)){int numPredDir = m_slice->isInterP() ? 1 : 2;//取之前pass计算分析得到interDatam_reuseInterDataCTU = m_frame->m_analysisData.interData;//加载之前pass计算分析得到的mv/mvpIdx/ref/modes/depthfor (int dir = 0; dir < numPredDir; dir++){m_reuseMv[dir] = &m_reuseInterDataCTU->mv[dir][ctu.m_cuAddr * ctu.m_numPartitions];m_reuseMvpIdx[dir] = &m_reuseInterDataCTU->mvpIdx[dir][ctu.m_cuAddr * ctu.m_numPartitions];}m_reuseRef = &m_reuseInterDataCTU->ref[ctu.m_cuAddr * ctu.m_numPartitions];m_reuseModes = &m_reuseInterDataCTU->modes[ctu.m_cuAddr * ctu.m_numPartitions];m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions];}/*若开启了编码器外第三方编码信息读取,则将读取的信息载入,用于后续编码*///若(开启analysisSave || 开启analysisLoad) && 非Islice && analysisReuseLevel等级在[2,9]if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel < 10){//得到预测方向int numPredDir = m_slice->isInterP() ? 1 : 2;//取interData/ref/depth/mode数据m_reuseInterDataCTU = m_frame->m_analysisData.interData;m_reuseRef = &m_reuseInterDataCTU->ref [ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir];m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions];m_reuseModes = &m_reuseInterDataCTU->modes[ctu.m_cuAddr * ctu.m_numPartitions];//若analysisReuseLevel > 4,则再取PartSize/MergeFlag数据if (m_param->analysisReuseLevel > 4){m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions];m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions];}//若analysisSave而不analysisLoad,则置所有Ref为-1if (m_param->analysisSave && !m_param->analysisLoad)for (int i = 0; i < X265_MAX_PRED_MODE_PER_CTU * numPredDir; i++)m_reuseRef[i] = -1;}ProfileCUScope(ctu, totalCTUTime, totalCTUs);/*进行压缩*/if (m_slice->m_sliceType == I_SLICE)   //Islice{//取分析的intraDatax265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData;//若analysisLoad && analysisReuseLevel > 1if (m_param->analysisLoad && m_param->analysisReuseLevel > 1){//复制analysisData中的cuDepth/lumaIntraDir/partSize/chromaIntraDir到CTU信息中,用于编码memcpy(ctu.m_cuDepth, &intraDataCTU->depth[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);memcpy(ctu.m_partSize, &intraDataCTU->partSizes[ctu.m_cuAddr * numPartition], sizeof(char) * numPartition);memcpy(ctu.m_chromaIntraDir, &intraDataCTU->chromaModes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);}//进行帧内压缩compressIntraCU(ctu, cuGeom, qp);} //end of I sliceelse //P、Bslice{/*判断是否bCopyAnalysis*/bool bCopyAnalysis = ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16));//bAnalysisType = AVC_INFO && analysisReuseLevel >= 7 && rdlevel 0~4bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel <= 4);//bAnalysisType = AVC_INFO && analysisReuseLevel >= 7 && rdlevel 5~6bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6);bCopyAnalysis = bCopyAnalysis || BCompressInterCUrd0_4 || BCompressInterCUrd5_6;//若bCopyAnalysis,则拷贝编码分析数据if (bCopyAnalysis){//取分析的intraDatax265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData;//得到CTU的位置,单位4x4blockint posCTU = ctu.m_cuAddr * numPartition;//复制analysisData中的cuDepth/predMode/partSize/skipFlag到CTU信息中,用于编码memcpy(ctu.m_cuDepth, &interDataCTU->depth[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_predMode, &interDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_partSize, &interDataCTU->partSize[posCTU], sizeof(uint8_t) * numPartition);for (int list = 0; list < m_slice->isInterB() + 1; list++)memcpy(ctu.m_skipFlag[list], &m_frame->m_analysisData.modeFlag[list][posCTU], sizeof(uint8_t) * numPartition);//若(是Pslice || 允许Bslice中intra) && bAnalysisType != AVC_INFO,则还要读取intra信息if ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !(m_param->bAnalysisType == AVC_INFO)){//取分析的intraDatax265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData;//复制analysisData中的lumaIntraDir/chromaIntraDir到CTU信息中,用于编码memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_chromaIntraDir, &intraDataCTU->chromaModes[posCTU], sizeof(uint8_t) * numPartition);}//Calculate log2CUSize from depthfor (uint32_t i = 0; i < cuGeom.numPartitions; i++)ctu.m_log2CUSize[i] = (uint8_t)m_param->maxLog2CUSize - ctu.m_cuDepth[i];}//若开启了bIntraRefresh && Pslice && CTU处于pirStartCol和pirEndCol之间,则进行intra编码if (m_param->bIntraRefresh && m_slice->m_sliceType == P_SLICE &&ctu.m_cuPelX / m_param->maxCUSize >= frame.m_encData->m_pir.pirStartCol&& ctu.m_cuPelX / m_param->maxCUSize < frame.m_encData->m_pir.pirEndCol)compressIntraCU(ctu, cuGeom, qp);//rd level = 0else if (!m_param->rdLevel){/* In RD Level 0/1, copy source pixels into the reconstructed block so* they are available for intra predictions *///将原始YUV数据拷贝到recon中m_modeDepth[0].fencYuv.copyToPicYuv(*m_frame->m_reconPic, ctu.m_cuAddr, 0);//进行inter压缩compressInterCU_rd0_4(ctu, cuGeom, qp);/* generate residual for entire CTU at once and copy to reconPic 编码残差值 */encodeResidue(ctu, cuGeom);}/*开启analysisLoad && analysisReuseLevel=10 && (bAnalysisType!=HEVC || 非Pslice)或bAnalysisType = AVC_INFO && analysisReuseLevel >= 7 && 4x4block个数<=16*/else if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) ||((m_param->bAnalysisType == AVC_INFO) && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)){//取分析的interDatax265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData;//得到CTU以4x4block为单位的positionint posCTU = ctu.m_cuAddr * numPartition;//将载入的interData中的cuDepth/predMode/partSize拷贝到CTU信息中,用于后续编码memcpy(ctu.m_cuDepth, &interDataCTU->depth[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_predMode, &interDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_partSize, &interDataCTU->partSize[posCTU], sizeof(uint8_t) * numPartition);//若(是Pslice || 允许Bslice使用intra) && bAnalysisType!=AVC_INFOif ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !(m_param->bAnalysisType == AVC_INFO)){//将载入的interData中的lumaIntraDir/chromaIntraDir拷贝到CTU信息中,用于后续编码x265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData;memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition);memcpy(ctu.m_chromaIntraDir, &intraDataCTU->chromaModes[posCTU], sizeof(uint8_t) * numPartition);}//Calculate log2CUSize from depth 计算CTU每个4x4block的sizefor (uint32_t i = 0; i < cuGeom.numPartitions; i++)ctu.m_log2CUSize[i] = (uint8_t)m_param->maxLog2CUSize - ctu.m_cuDepth[i];//qp rd 优化qprdRefine (ctu, cuGeom, qp, qp);//返回CTU的bestModereturn *m_modeDepth[0].bestMode;}//分布式多线程mode分析 && rdlevel>=2。当rdlevel<2时分布式收益不大,rdlevel越高收益越大else if (m_param->bDistributeModeAnalysis && m_param->rdLevel >= 2)compressInterCU_dist(ctu, cuGeom, qp);else if (m_param->rdLevel <= 4) //rdlevel 0~4 inter compresscompressInterCU_rd0_4(ctu, cuGeom, qp);else //rdlevel 5~6 inter compresscompressInterCU_rd5_6(ctu, cuGeom, qp);}    //end of p/b slice//若bEnableRdRefine || bOptCUDeltaQP,则进行qp rd优化if (m_param->bEnableRdRefine || m_param->bOptCUDeltaQP)qprdRefine(ctu, cuGeom, qp, qp);//若csvLogLevel >= 2,则统计PU信息if (m_param->csvLogLevel >= 2)collectPUStatistics(ctu, cuGeom);//返回当前深度的bestModereturn *m_modeDepth[0].bestMode;
}

Analysis::compressCTU()相关推荐

  1. x265笔记_4_CompressCTU源码分析

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

  2. x265-1.8版本-encoder/frameencoder.cpp注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

  3. x265-1.7版本-encoder/frameencoder.cpp注释

    注:问号以及未注释部分 会在x265-1.8版本内更新 /*********************************************************************** ...

  4. TensorRT Analysis Report分析报告

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. c语言存储多个数据,C语言中如何求数组真实存有数据的元素个数
  2. 查询SDE数据库,GSON报错:declares mutiple JSON fields named data
  3. HCNA(012-211) 试题解析
  4. strongswan技术
  5. C# 正则表达式(备忘录)
  6. 单机负载告警,数据库与应用分离
  7. unity ppr_智能自动PPR更改事件策略
  8. 数据分析和大数据哪个更吃香_处理数据,大数据甚至更大数据的17种策略
  9. 【CF#931.B】World Cup (思维,模拟)
  10. 域添加另一台机器_巨杉Tech | SequoiaDB数据域概念解读与实践
  11. 【 Educational Codeforces Round 71 (Rated for Div. 2) F】Remainder Problem【分块】
  12. android手机模拟鼠标控制pc,利用Android手机仿真PC鼠标的设计与实现
  13. cocos2d-x 移动MM平台SDK接入
  14. 火车头免登录php代码,福利|火车采集器免登陆发布接口集合
  15. Angular学习笔记之慕课大漠穷秋塞主讲
  16. NOIP2017提高组模拟赛4 (总结)
  17. astar插件下载 就行_PS模拟下雨插件下载 一键为照片添加下雨效果 小伙伴们收货啦...
  18. win10用html文件做壁纸,利用win10自带工具制作动态壁纸的简单方法
  19. vue3 +Element-puls ,table 中使用$refs修改scrollTop 到顶部
  20. 开利宣布收购空调企业广东积微集团,包括志高暖通等多家子公司

热门文章

  1. day70-大数据之Hadoop部署1(单机部署与伪分布式部署)
  2. 3蛋白wb_IHC、ELISA和WB区别
  3. Quartz 的使用
  4. root-me:network(一)
  5. innovus:earlyGlobalRoute与trial route
  6. 2021年4月30日 星期五 阴
  7. ubi以及ubifs
  8. offsetParent is not set报错
  9. 【阅读笔记】Partner-Assisted Learning for Few-Shot Image Classification
  10. 黑马程序员JAVA基础-多线程