x265,帧内预测代码分析

  1 void Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, uint32_t& zOrder)
  2 {
  3     uint32_t depth = cuGeom.depth;//geometric  CU几何结构
  4     ModeDepth& md = m_modeDepth[depth];
  5     md.bestMode = NULL;
  6
  7     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);//为ture非叶子节点,还需继续分裂
  8     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);//
  9
 10     if (m_param->analysisMode == X265_ANALYSIS_LOAD)
 11     {
 12         uint8_t* reuseDepth  = &m_reuseIntraDataCTU->depth[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
 13         uint8_t* reuseModes  = &m_reuseIntraDataCTU->modes[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
 14         char* reusePartSizes = &m_reuseIntraDataCTU->partSizes[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
 15
 16         if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder == cuGeom.encodeIdx)
 17         {
 18             m_quant.setQPforQuant(parentCTU);
 19
 20             PartSize size = (PartSize)reusePartSizes[zOrder];
 21             Mode& mode = size == SIZE_2Nx2N ? md.pred[PRED_INTRA] : md.pred[PRED_INTRA_NxN];
 22             mode.cu.initSubCU(parentCTU, cuGeom);
 23             checkIntra(mode, cuGeom, size, &reuseModes[zOrder]);
 24             checkBestMode(mode, depth);
 25
 26             if (m_bTryLossless)
 27                 tryLossless(cuGeom);
 28
 29             if (mightSplit)
 30                 addSplitFlagCost(*md.bestMode, cuGeom.depth);
 31
 32             // increment zOrder offset to point to next best depth in sharedDepth buffer
 33             zOrder += g_depthInc[g_maxCUDepth - 1][reuseDepth[zOrder]];
 34             mightSplit = false;
 35         }
 36     }
 37     else if (mightNotSplit)
 38     {
 39         m_quant.setQPforQuant(parentCTU);
 40
 41         md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
 42         checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N, NULL);//intra2Nx2N  模式
 43         checkBestMode(md.pred[PRED_INTRA], depth);
 44
 45         if (depth == g_maxCUDepth)
 46         {
 47             md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);
 48             checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN, NULL);//INTRA_NxN  模式
 49             checkBestMode(md.pred[PRED_INTRA_NxN], depth);
 50         }
 51
 52         if (m_bTryLossless)
 53             tryLossless(cuGeom);
 54
 55         if (mightSplit)
 56             addSplitFlagCost(*md.bestMode, cuGeom.depth);
 57     }
 58
 59     if (mightSplit)
 60     {
 61         Mode* splitPred = &md.pred[PRED_SPLIT];
 62         splitPred->initCosts();
 63         CUData* splitCU = &splitPred->cu;
 64         splitCU->initSubCU(parentCTU, cuGeom);//分裂成4四subCU
 65
 66         uint32_t nextDepth = depth + 1;
 67         ModeDepth& nd = m_modeDepth[nextDepth];
 68         invalidateContexts(nextDepth);
 69         Entropy* nextContext = &m_rqt[depth].cur;
 70
 71         for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)
 72         {
 73             const CUGeom& childGeom = *(&cuGeom + cuGeom.childOffset + subPartIdx);
 74             if (childGeom.flags & CUGeom::PRESENT)
 75             {
 76                 m_modeDepth[0].fencYuv.copyPartToYuv(nd.fencYuv, childGeom.encodeIdx);
 77                 m_rqt[nextDepth].cur.load(*nextContext);
 78                 compressIntraCU(parentCTU, childGeom, zOrder);//递归
 79
 80                 // Save best CU and pred data for this sub CU
 81                 splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);
 82                 splitPred->addSubCosts(*nd.bestMode);
 83                 nd.bestMode->reconYuv.copyToPartYuv(splitPred->reconYuv, childGeom.numPartitions * subPartIdx);
 84                 nextContext = &nd.bestMode->contexts;
 85             }
 86             else
 87             {
 88                 /* record the depth of this non-present sub-CU */
 89                 splitCU->setEmptyPart(childGeom, subPartIdx);
 90                 zOrder += g_depthInc[g_maxCUDepth - 1][nextDepth];
 91             }
 92         }
 93         nextContext->store(splitPred->contexts);
 94         if (mightNotSplit)
 95             addSplitFlagCost(*splitPred, cuGeom.depth);
 96         else
 97             updateModeCost(*splitPred);
 98         checkBestMode(*splitPred, depth);
 99     }
100
101     checkDQP(md.bestMode->cu, cuGeom);
102
103     /* Copy best data to encData CTU and recon */
104     md.bestMode->cu.copyToPic(depth);
105     if (md.bestMode != &md.pred[PRED_SPLIT])
106         md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.encodeIdx);
107 }
时间: 2024-08-07 19:57:48

x265,帧内预测代码分析的相关文章

x264 亮度信号8x8帧内预测模式

1 该模式的8个预测方向与4x4帧内预测模式一样. 2 该模式只有High profile及更高的Profile的才有可能使用,Baseline.Main Profile.Preset为ultrafast时不支持,命令行参数为--8x8dct与--no-8x8dct控制是否使用,x264内部参数结构x264_param_t的成员b_transform_8x8的值控制是否使用. 1 x264_param_default函数中将b_transform_8x8设为1,即默认为使用亮度信号8x8帧内预测

HEVC算法和体系结构:预测编码之帧内预测

预测编码之帧内预测(Intra-Picture Prediction) 预测编码(Prediction Coding)是视频编码的核心技术之一,指利用已编码的一个或几个样本值,根据某种模型或方法,对当前的样本值进行预测,并对样本真实值和预测值之间的差值进行编码.视频编码器对预测后的残差而不是原始像素值进行变换.量化.熵编码,由此大幅度提高编码效率. 对于视频信号来说,一帧图像内临近像素之间有着较强的空间相关性,即空域冗余:相邻图像之间也有很强的相关性,即时域冗余.去除空域冗余和时域冗余的技术分别

【HEVC】2、HM-16.7编码一个CU(帧内部分) 2.帧内预测各种模式实现

HEVC中一共定义了35中帧内编码预测模式,编号分别以0-34定义.其中模式0定义为平面模式(INTRA_PLANAR),模式1定义为均值模式(INTRA_DC),模式2~34定义为角度预测模式(INTRA_ANGULAR2~INTRA_ANGULAR34),分别代表了不同的角度. 最简单的Intra_DC模式,DC模式适用于大面积平摊区域,当前预测值可由其左侧和上方(不包含左上角,左下方和右上方)参考像素的平均值得到.该模式同角度预测模式实现在同一个函数Void TComPrediction:

H.264学习笔记2——帧内预测

帧内预测:根据经过反量化和反变换(没有进行去块效应)之后的同一条带内的块进行预测. A.4x4亮度块预测: 用到的像素和预测方向如图: a~f是4x4块中要预测的像素值,A~Q是临块中解码后的参考值.0~8是4x4的亮度块的9个预测方向(模式).当E~H不可得时,用D代替. A~Q在下面情况下不可用: >不在当前图像或条带:在该4x4块之前还没有被编码:位于帧间编码宏块,且constrained_intra_pred为1: 对于9个预测模式,简述如下: >模式0:垂直模式,条件:A~D可用.

H264帧内预测模式编号的编码过程

1 本文词汇约定 宏块:H264编码基本单元,16x16像素(或采样)构成 块:   由8x8像素(或采样)构成的单位 子块:   由4x4像素(或采样)构成的单位 2 帧内亮度预测模式 H264规范中,宏块有4种帧内亮度预测模式,模式编号为0,1,2,3;块与子块分别有9种帧内亮度预测模式,模式编号从0至9,即0,1,2,.......,8.具体不细说了,可查H264标准.下文以子块为例说明其亮度预测模式如何编码进码流中的. 3 子块亮度预测模式编码的句法元素 prev_intra4x4_pr

FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧内宏块(Intra)

本文分析FFmpeg的H.264解码器的宏块解码(Decode)部分的源代码.FFmpeg的H.264解码器调用decode_slice()函数完成了解码工作.这些解码工作可以大体上分为3个步骤:熵解码,宏块解码以及环路滤波.本文分析这3个步骤中的第2个步骤.由于宏块解码部分的内容比较多,因此将本部分内容拆分成两篇文章:一篇文章记录帧内预测宏块(Intra)的宏块解码,另一篇文章记录帧间预测宏块(Inter)的宏块解码. 函数调用关系图 宏块解码(Decode)部分的源代码在整个H.264解码器

x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)

本文记录x264的 x264_slice_write()函数中调用的x264_macroblock_analyse()的源代码.x264_macroblock_analyse()对应着x264中的分析模块.分析模块主要完成了下面2个方面的功能: (1)对于帧内宏块,分析帧内预测模式(2)对于帧间宏块,进行运动估计,分析帧间预测模式 由于分析模块比较复杂,因此分成两篇文章记录其中的源代码:本文记录帧内宏块预测模式的分析,下一篇文章记录帧间宏块预测模式的分析. 函数调用关系图 宏块分析(Analys

HEVC算法和体系结构:预测编码之帧间预测

预测编码之帧间预测(Inter-Picture Prediction) 帧间预测是指利用视频时间域相关性,使用临近已编码图像像素预测当前图像的像素,以达到有效去除视频时域冗余的目的.由于视频序列通常包括较强的时域相关性,因此预测残差值接近于0,将残差信号作为后续模块的输入进行变换.量化.扫描及熵编码,可实现对视频信号的高效压缩. 一.帧间预测编码原理 目前主要的视频编码标准帧间预测部分都采用了基于块的运动补偿技术,如下图所示,其基本原理为:当前图像的每个像素块在之前已编码图像中寻找一个最佳匹配块

(转)x264源码分析(1):main、parse、encode、x264_encoder_open函数代码分析

转自:http://nkwavelet.blog.163.com/blog/static/2277560382013103010312144/ x264版本:   x264-snapshot-20140226-2245  1.     首先对主函数进行分析,main函数很简洁,主要有三个步骤,见下图: 2.   接下来分析一下Parse函数中的主要过程: static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t