14. x264_macroblock_encode函数-1

这个函数主要根据已经选定的模式来对宏块残差进行编码。

)如果是P_SKIP模式,那么调用x264_macroblock_encode_pskip函数

),那么调用pixel_avg;否则,调用mc_copy。pixel_avg位于mc.c文件中,是1/4搜索时需要临时插值函数。 

dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;   //利用相邻半像素和两个像素取平均插值

mc_copy位于mc.c文件。

最后还要调用x264_macroblock_encode_skip函数,在这个函数中主要设置CBP值。

(2)如果是B_SKIP模式,先是调用x264_mb_mc函数完成运动补偿,然后调用x264_macroblock_encode_skip来进行CBP设置。

)接下来是帧内模式的编码,包括帧内I_16x16,帧内I_8x8和帧内I_4x4。在做每种模式的编码之前都要先计算预测帧。分别调用相应的预测函数 个块)和predict_4x4(16个块)。

A. 对于I_16x16,调用x264_mb_encode_i16x16进行编码,如果是无损编码h->mb.b_lossless被置上,则以4x4为单位,进行无损压缩的量化和扫描。若是有损压缩方式,先调用 h-> dctf. sub16x16_dct计算宏块残差(p_src-p_dst)并进行4x4大小的DCT变换。
仍然,h-> dctf. sub16x16_dct是一个函数指针,其最常设置的值是sub16x16_dct,位于dct.c文件中。

个8x8块进行调用分别调用sub8x8_dct来完成残差计算和DCT变换的。而sub8x8_dct则是调用4个sub4x4_dct分别对4个4x4块进行残差DCT变换计算的。具体到sub4x4_dct,是调用pixel_sub_wxh来计算得到残差,然后再进行DCT变换,采用264中经典的4x4DCT变换的算法。

个4x4块在for循环中进行处理:先拿出每个4x4块的DC系数(存放在一个数组dct4x4[0]中),然后对每个4x4块进行量化、扫描和反量化。分别由函数:x264_quant_4x4_trellis或quant_4x4、scan_zigzag_4x4和h->quantf.dequant_4x4完成。

接下来,对所有4x4块的在数组dct4x4 [0]中DCT系数进行:DCT变换、量化和扫描。分别由函数: h->dctf.dct4x4dc、quant_4x4_dc和scan_zigzag_4x4full完成。

然后,为了重建帧的需要,对DC系数进行反DCT变换、反量化(为什么不是先反量化后反变换,待解决)。分别由函数h->dctf.idct4x4dc和x264_mb_dequant_4x4_dc完成。对于直流系数,对每个4x4子块进行反DCT、反量化并加到预测宏块上得到重建的帧。由函数 h->dctf.add16x16_idct完成。

个8x8来分别进行。先调用predict_8x8函数来计算预测值,然后调用函数x264_mb_encode_i8x8进行编码。在该函数中,8x8DCT变换——h->dctf.sub8x8_dct8函数,量化—— x264_quant_8x8_trellis或quant_8x8函数、扫描——h->zigzagf.scan_8x8函数、反量化—— h->quantf.dequant_8x8函数和反DCT变换并加到预测宏块上——h->dctf.add8x8_idct8函数。

 

个4x4块分别进行。先h->predict_4x4[i_mode]进行帧内预测,得到预测帧。然后x264_mb_encode_i4x4编码。在x264_mb_encode_i4x4中,如果是无损压缩h->mb.b_lossless置位。调用sub_zigzag_4x4full计算残差,并扫描,返回。若是非无损编码,进行DCT、量化、Z字扫描、反量化、反IDCT并加到预测帧上。分别由函数:h->dctf.sub4x4_dct、 x264_quant_4x4_trellis或quant_4x4、scan_zigzag_4x4full、 h->quantf.dequant_4x4和h->dctf.add4x4_idct完成。

)如果是帧间模式编码,

(h->mb.i_type == P_L0)的16x16预测模式,根据h->mb.i_partition的类型(D_16x16、D_16x8、D_8x16),分别调用 x264_mb_mc_0xywh函数进行前向宏块运动补偿。x264_mb_mc_0xywh分别对亮度和色度进行运动补偿: h->mc.mc_luma和h->mc.mc_chroma函数。如果宏块类型(h->mb.i_type)为P_8x8或B_8x8。对4个8x8块,分别调用x264_mb_mc_8x8进行运动补偿。
其根据字块类型(h->mb.i_sub_partition[i8])分别进行运动补偿。D_L0_8x8、D_L0_8x4、D_L0_4x8 和D_L0_4x4类型,调用x264_mb_mc_0xywh进行前向宏块运动补偿。D_L1_8x8、D_L1_8x4、D_L1_4x8和 D_L1_4x4类型,调用x264_mb_mc_1xywh进行后向宏块运动补偿。D_BI_8x8、D_BI_8x4、D_BI_4x8和 D_BI_4x4类型,分别调用x264_mb_mc_01xywh进行宏块双向运动补偿。D_DIRECT_8x8类型,调用x264_mb_mc_direct8x8 进行直接模式8*8块运动补偿。x264_mb_mc_direct8x8函数根据不同的条件调用x264_mb_mc_0xywh、x264_mb_mc_1xywh和x264_mb_mc_01xywh函数。如果宏块类型(h->mb.i_type)为B_SKIP或B_DIRECT。调用直接模式8*8块运动补偿函数x264_mb_mc_direct8x8。如果宏块类型(h->mb.i_type)为其它B帧模式。先初始化参考列表。根据子块类型(h->mb.i_partition)
为,D_16x16、D_16x8、D_8x16和前向、后项、双向参考类型,分别调用x264_mb_mc_0xywh、 x264_mb_mc_1xywh和x264_mb_mc_01xywh函数。

个4x4块,分别进行残差计算和z字扫描,由函数个8x8块,分别调用x264_denoise_dct去噪、x264_quant_8x8_trellis或quant_8x8量化、字扫描。然后是反量化、将残差加到参考宏块上。由h->quantf.dequant_8x8和h->dctf.add8x8_idct8完成。然后对4个8x8块,分别调用x264_denoise_dct去噪、x264_quant_8x8_trellis或quant_8x8量化、scan_zigzag_8x8full Z字扫描。然后是反量化、将残差加到参考宏块上。由h->quantf.dequant_8x8和h->dctf.add8x8_idct8完成。

个4x4块进行去噪——x264_denoise_dct、量化x264_quant_4x4_trellis或 quant_4x4、Z字扫描——scan_zigzag_4x4full。然后是反量化——h->quantf.dequant_4x4和
反DCT并加到参考帧上——h->dctf.add8x8_idct。

D. 亮度编码完成后,进行色度编码。x264_mb_encode_8x8_chroma函数。对Cb和Cr分量分别进行。

个4x4块进行残差计算、Z字扫描和DC系数计算。

非无损编码,用h->dctf.sub8x8_dct对每个4x4块进行残差计算和DCT转换。之后对每个4x4块,先取2x2DC系数,量
化——quant_4x4_chroma、Z字扫描——h->zigzagf.scan_4x4ac。对2x2DC系数进行DCT变换、量化和Z字
扫描,分别由函数h->dctf.dct2x2dc、quant_2x2_dc和scan_zigzag_2x2_dc。接着是反DCT变换和反量
化,h->dctf.idct2x2dc与x264_mb_dequant_2x2_dc函数。h->quantf.dequant_4x4 对4x4块反量化,h->dctf.add8x8_idct对每个4x4块反DCT变换并且加到色度预测帧上。

E. 亮度和色度编码完成后。计算亮度和色度模式和非零的个数,确定h->mb.i_cbp_chroma和h->mb.cbp的值。

 

 

15. x264_macroblock_encode函数-2

下面是该函数的调用情况,在上面对这个函数的分析中,已经对其中的大部分的函数都有了一个相对比较详细的介绍,

 

16. x264_macroblock_write_cabac函数

在宏块编码结束后,就要将编码生成的内容写到码流中。如果支持CABAC编码,就调用x264_macroblock_write_cabac。如果是CAVLC编码,就调用x264_macroblock_write_cavlc。

先调用函数x264_cabac_mb_type来将宏块类型写入码流,然后根据宏块的类型进行码流的写入操作:

A. 如果是I_PCM类型,那么直接对亮度和色度调用函数bs_write来将数据写入码流,然后返回。

B. 如果是帧内类型,如果采用了8x8DCT变换并且不是I_16x16,那么就调用x264_cabac_mb_transform_size来将变换的尺寸写入码流,如果是I_8x8或I_4x4,需要将预测模式写入码流,然后是将色度预测模式写入码流。

C. 如果是帧间16x16, 16x8 和 8x16 ,则根据相应的类型,调用x264_cabac_mb_ref将参考帧写入码流,调用x264_cabac_mb_mvd将运动矢量差写入码流

D. 如果是帧间P_8x8模式,首先将每一个子块的模式写入码流x264_cabac_mb_sub_p_partition,然后将每一个块用到的参考帧写入码流x264_cabac_mb_ref,最后在函数x264_cabac_mb8x8_mvd中将每一个8x8块的mvd写入码流。

E. 如果是B_8x8模式,同样写入子块模式x264_cabac_mb_sub_b_partition,然后前后参考帧写入码流x264_cabac_mb_ref,最后调用x264_cabac_mb8x8_mvd将L0和L1上的参考帧写入码流。

F. 如果是除B_DIRECT之外所有其他模式,将参考帧和mvd写入码流。

 

接下来将亮度和色度CBP写入码流:x264_cabac_mb_cbp_luma和x264_cabac_mb_cbp_chroma。

然后将qp_delta写入码流x264_cabac_mb_qp_delta,
同时根据宏块类型将残差系数写入码流block_residual_write_cabac。

 

 

17.x264_macroblock_write_cavlc函数

首先,根据帧类型计算i_mb_i_offset的值。依据宏块类型(i_mb_type)写相应的数据到流中:

A. 如果宏块类型是I_PCM,就把16x16个亮度值、2x8x8个色度值直接写到码流中。

个4x4块和4个8x8块,先调用 x264_mb_predict_intra4x4_mode获取最可能的预测模式,然后比较当前的预测模式和最可能的预测模式,将判断结果写入码流中,
最后写入当前的预测模式值。

C. 如果宏块类型是I_16x16,将当前的预测模式写入码流。

D. 如果宏块类型是P_L0, 宏块子分区分别为D_16x16、D_16x8和D_8x16时,处理步骤相似,先将分区类型写入码流,然后预测运动向量(x264_mb_predict_mv)得到mvp,最后写入当前运动向量与mvp的差值(MVD)。

个子宏块类型,参考帧信息,调用cavlc_mb8x8_mvd计算 mvd。cavlc_mb8x8_mvd函数中根据不同的子分区类型(D_L0_8x8/D_L1_8x8/D_BI_8x8...)调用 cavlc_mb_mvd函数计算MVD并写入码流。cavlc_mb_mvd函数中也是计算mvp(x264_mb_predict_mv),算mvd 并写入码流中。

F. 如果宏块类型是非B_DIRECT——B帧的非直接模式,可能会双向参考。之后根据两个参考帧列表结合子分区类型(D_16x16、D_16x8、D_8x16),写入参考帧信息,计算mvp(x264_mb_predict_mv),计算mvd并写入码流中。

G. 如果宏块类型是B_DIRECT,就写个类型。

 

这样,在运动向量差写入完成后。写编码的块模式。写残差数据,分亮度残差数据和色度残差数据。

A. 如果类型是I_16x16,先计算qp-delta并写入码流,写亮度DC和AC系数(block_residual_write_cavlc)。

B. 如果不是I_16x16,且亮度和色度有一个不是零(h->mb.i_cbp_luma != 0 || h->mb.i_cbp_chroma != 0)。先计算qp-delta并写入码流,然后调用x264_macroblock_luma_write_cavlc进行亮度宏块编码。

 

对于色度残差数据的cavlc编码,先写入Cb,Cr的DC系数(block_residual_write_cavlc),后写入AC系数(block_residual_write_cavlc)。

这样就完成了熵编码。

 

 

 

 

 

x264阅读记录-3的更多相关文章

  1. x264阅读记录-2

    x264阅读记录-2 7. x264_encoder_encode函数-1 查看该函数代码(Encoder.c文件)可以发现,该函数中注释很详细,对编码的整个步骤展示的也相对比较清晰. 在查看具体的代 ...

  2. x264阅读记录-1

    x264阅读记录-1 采用x264版本是x264-snapshot-20060316-2245. 1. main函数 x264的main函数位于x264.c中,下面是main函数调用情况: (1)_s ...

  3. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  4. Elasticsearch6.3.2启动过程源码阅读记录

    Elasticsearch6.3.2启动过程源码阅读记录 网上有很多关于es的源码分析,觉得自己技术深度还不够,所以这些文章只是看源码过程中的一个笔记,谈不上分析. 整个启动过程以类名.方法名,按顺序 ...

  5. 《Javascript高级程序设计》阅读记录(七):第七章

    <Javascript高级程序设计>中,2-7章中已经涵盖了大部分精华内容,所以摘录到博客中,方便随时回忆.本系列基本完成,之后的章节,可能看情况进行摘录. 这个系列以往文字地址: < ...

  6. 《Javascript高级程序设计》阅读记录(六):第六章 下

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...

  7. 《Javascript高级程序设计》阅读记录(五):第六章 上

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 <Javascript ...

  8. 《Javascript高级程序设计》阅读记录(三):第五章 上

    这个系列以往文字地址: <Javascript高级程序设计>阅读记录(一):第二.三章 <Javascript高级程序设计>阅读记录(二):第四章 这个系列,我会把阅读< ...

  9. 《Javascript高级程序设计》阅读记录(一):第二、三章

    <Javascript高级程序设计>阅读记录(一) 这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较深入,而且实际使用价值较大的内容记录下来,并且注释 ...

随机推荐

  1. python全栈开发day99-DRF序列化组件

    1.解释器组件源码分析 https://www.processon.com/view/link/5ba0a8e7e4b0534c9be0c968 2.基于CBV的接口设计 1).django循环que ...

  2. python全栈开发day54-mysql库操作、表操作、数据类型、完整性约束

    一.昨日内容回顾 1.mysql的安装 1).解压文件 添加环境变量bin 2).初始化mysql生成数据data文件夹: mysqld --initialize-insecure 3).mysqld ...

  3. (三)apache的安装与配置

    一.安装: 推荐使用cygwin自带的Setup.exe.带来的好处不言而喻,所有安装的程序都是经过测试的,这样确保你不会把宝贵的时间浪费来毫无意义的劳动上. 在安装程序中选择两个包就行了(分别是ap ...

  4. 【转】通过 INotifyPropertyChanged 实现观察者模式

    通过 INotifyPropertyChanged 实现观察者模式 原博客地址 http://frankdzu.blog.sohu.com/117654536.html 普通观察者模式存在的问题 我们 ...

  5. Python执行ImportError:No module named MySQLdb异常

  6. Zabbix监控Nginx性能状态

    Nginx在生产环境中的应用越来越广泛,所以需要对nginx的性能状态做一些监控,从而发现故障隐患,Ngnx的监控指标可分为:基本活动指标,错误指标,性能指标 监控Nginx思路: 1)首先,要想监控 ...

  7. BZOJ3437 小P的牧场 动态规划 斜率优化

    原文链接http://www.cnblogs.com/zhouzhendong/p/8696321.html 题目传送门 - BZOJ3437 题意 给定两个序列$a,b$,现在划分$a$序列. 被划 ...

  8. 02. Pandas 1|数据结构Series、Dataframe

    1."一维数组"Series Pandas数据结构Series:基本概念及创建 s.index  . s.values # Series 数据结构 # Series 是带有标签的一 ...

  9. 009 pandas的Series

    一:创建 1.通过Numpy数组创建 2.属性查看 3.一维数组创建(与numpy的创建一样) 4.通过字典创建 二:应用Numpy数组运算 1.获取值 numpy的数组运算,在Series中都被保留 ...

  10. Python 豆瓣mv爬取

    爬取网址:https://www.dbmeinv.com/       豆瓣mv(现已更名) 注:自制力不好的同学,先去准备营养快线! import requests from bs4 import ...