x264编码过程分析(二)核心函数x264_slice_write()

在这里插入图片描述

1)调用x264_nal_start()开始输出一个NALU。
//x264_macroblock_thread_init()设定了宏块编码数据指针p_fenc[0],p_fenc[1],p_fenc[2]在fenc_buf[]中的位置,
//以及宏块重建数据指针p_fdec[0],p_fdec[1],p_fdec[2] 在fdec_buf[]中的位置2x264_macroblock_thread_init():初始化宏块重建像素数据缓存fdec_buf[]和编码像素数据缓存fenc_buf[]。

(3)调用x264_slice_header_write()输出 Slice Header。

(4)进入一个循环,该循环每执行一遍编码一个宏块:
	a) 每处理一行宏块,调用一次x264_fdec_filter_row()执行滤波模块。
	//(1)环路滤波(去块效应滤波)。通过调用x264_frame_deblock_row()实现。
	//(2)半像素内插。通过调用x264_frame_filter()实现。
			//经过汇编半像素内插函数处理之后,得到的水平半像素内差点存储在x264_frame_t的filtered[][1]中,
			//垂直半像素内差点存储在x264_frame_t的filtered[][2]中,
			//对角线半像素内差点存储在x264_frame_t的filtered[][3]中
			//(整像素点存储在x264_frame_t的filtered[][0]中)。

	//(3)视频质量SSIM和PSNR计算。PSNR在这里只计算了SSD,通过调用x264_pixel_ssd_wxh()实现;SSIM的计算则是通过x264_pixel_ssim_wxh()实现。

	b) 调用x264_macroblock_cache_load()将要编码的宏块的周围的宏块的信息读进来。
	//(1)加载Intra4x4帧内预测模式intra4x4_pred_mode[]和DCT非零系数non_zero_count[]缓存Cache的宏块周边信息。加载顺序为:上->左->左上。
	//(2)加载宏块重建像素p_fdec[]的周边像素,以及宏块编码像素p_fenc[]。对于p_fdec[]来说,在本函数中直接加载当前宏块左边的像素;调用函数x264_macroblock_load_pic_pointers()加载当前宏块上面的像素。对于p_fenc[]来说,调用x264_macroblock_load_pic_pointers()从图像上拷贝数据。
					//x264_macroblock_load_pic_pointers()用于给宏块重建像素p_fdec[]和宏块编码像素p_fenc[]加载数据,并且加载图像的半像素数据。
					//(1)加载编码宏块mb.pic.p_fenc[]的像素数据,以及重建宏块mb.pic.p_fenc[]上边的像素数据。
					//(2)加载参考帧的半像素数据(除了整像素外,还包含了:H,V,C三组半像素数据点)。
	//(3)加载参考帧序号ref[]和运动矢量mv[]缓存Cache的宏块周边信息。加载顺序为:左上->上->左。
	//(4)加载其它信息。

	c) 调用x264_macroblock_analyse()用于分析宏块的编码模式。
		//对于帧内宏块来说,主要分析使用Intra16x16合适还是使用Intra4x4合适;
		//对于帧间宏块来说,主要分析它的划分模式,并且进行运动估计。


		//(1)如果I Slice,调用x264_mb_analyse_intra()帧内预测分析-从16x16的SAD(4种预测方向),4个8x8的SAD(方向同4x4 仅限high profile及更高profile)和,16个4x4SA(9种)中选出最优方式:宏块大小+预测模式
		//(2)如果当前是P Slice,则进行下面流程的分析:
			//1、调用x264_macroblock_probe_pskip()分析是否为Skip宏块,如果是的话则不再进行下面分析。
			//2、调用各种函数x264_mb_analyse_inter_?计算多种模式中哪一种代价最低(P16x16 P16x8 P8x16 P8x8 P4x8 P8x4 P4x4 Intra宏块)(P Slice中也允许有Intra宏块)。
		//(3)如果当前是B Slice,则进行和P Slice类似的处理。
//宏块的帧间预测方法:初始化 + x264_me_search_ref运动估计(先整像素 再亚像素精度) + 统计
			//X264中,半像素数据是在滤波(Filter)部分的x264_fdec_filter_row()中提前计算出来的,而1/4像素数据则是临时通过半像素数据线性内插得到的。
//运动搜索估计方式:1、快读搜索(菱形搜索算法(DIA) 六边形搜索算法(HEX)  非对称十字型多层次六边形格点搜索算法(UMH))
//2、全局搜索(太慢故极少使用)
//搜索的工作量越大。速度越慢 质量越高 (就是在找局部代价极小值点)

	d) 调用x264_macroblock_encode()执行宏块编码模块。
		//两个工作:编码(DCT变换和量化)和重建(DCT反变换和反量化)。
	e) 调用x264_macroblock_write_cabac()/x264_macroblock_write_cavlc()执行熵编码模块。
	//(1)根据Slice类型的不同,调用不同的函数输出宏块头(MB Header):对于P/B/I Slice,调用x264_cavlc_mb_header_p/b/i()
	//(2)调用x264_cavlc_qp_delta()输出宏块QP值
	//(3)调用x264_cavlc_block_residual()输出CAVLC编码的残差数据

	f) 调用x264_macroblock_cache_save()保存当前宏块的信息。以供后面宏块编码作为参考。
		//它的作用与x264_macroblock_cache_load()是相对应的。
	g) 调用x264_ratecontrol_mb()执行码率控制。
	h) 准备处理下一个宏块。

(5)调用x264_nal_end()结束输出一个NALU。
发布了81 篇原创文章 · 获赞 1 · 访问量 2882

猜你喜欢

转载自blog.csdn.net/qq_42024067/article/details/104561456