(转)x264 编码流程

时间:2021-07-22 11:46:44

转自:http://alphamailpost.blog.163.com/blog/static/20111808120128111160728/

http://www.usr.cc/thread-52674-1-1.html

Main函数中包含三个函数:Init,Encode,Fini,分别用来初始化,编码和编码后内存处理。

Init:

I(1)X264_param_default: 参数初始化,包括:CPU,视频参数,编码参数,码率控制参数,日志,分析参数和量化参数等。需要注意的是:

    param->rc.i_qp_constant = 26;  //量化步长;
    param->b_cabac=0;//   关闭CABAC编码;
    param->analyse.i_me_method = X264_ME_DIA; // 菱形搜索
(2)x264_encode_open: 对不正确的参数进行修改,并对各结构体的参数和预测等需要的参数进行初始化。
        x264_validate_parameters参数有效性检验
         1. x264_cpu_num_processors:根据不同的系统确定使用的CPU个数
         2. x264_clip3:取三者之间的最大值

Fini:

x264_picture_clean:释放一副图像所占内存

x264_encoder_close:计算每个宏块的数量和其对应的PSNR值,删除一些关键数据(包括帧的有关信息,量化矩阵和码率控制信息)
/*率失真理论:对有损压缩编码下的失真和编码性能之间的关系
码率控制方法:利用半精度的SATD(sum of absolute transformed differrence)作为模式选择的依据。SATD是将残差经哈达曼变换4*4块的预测残差绝对值总和*/

Encode:

Efseek:重定位文件流上的内部位置指针

  fread:从文件流中读数据

x264_encoder_encode:

编码时,维持着三个队列:frame_next队列(临时缓存,帧类型没确定,待编码的帧队列),frame_current队列(按编码顺序排放,已经确定了帧的类型,正在编码的帧队列)和frame_unused队列(空白队列,将要编码的帧放入该队列)。

1.x264_reference_update:(更新参考帧队列,若为B帧则不更新)将上一个参考帧放入参考帧队列,并从空闲队列中取出一帧作为当前参考工作帧;

2.x264_frame_pop_unused:(获取一帧的空间fenc,用来存放待编码的帧)若unused队列不为空,则将取出的帧放入unused队列(x264_frame_pop),否则,分配一帧空间(x264_frame_new);
   3. x264_frame_copy_picture:将该帧图像拷贝到fenc中
   4.判断是否需要进行边界扩展(x264_frame_expand_border_mod16),不能被16整除的都需要进行扩展。
   5.将fenc放入frame_next中(x264_frame_push)
  6.如果用到半精度亮度块,需要进行1/2像素扩展(x264_frame_init_lowres)
   7.若frame.current[0]==NULL(当前队列中没有帧需要编码)
       I.若frame.next[0]==NULL,结束编码(x264_encoder_frame_end)
       II. 判断帧类型(x264_slicetype_decide)
       III.将帧类型确定的帧重新排列存放在frame.current队列中
   8. 调整当前队列中帧的顺序,开始编码
  9.对编码之后的nal封装成NAL单元(x264_nal_encode);
   10.将NALU单元写入输出文件(p_write_nalu)

do_encode:

(1).        根据帧类型设置NAL的类型和优先级,若是IDR帧,则清空所有参考帧(x264_reference_reset)。
(2).        初始化参考队列(x264_reference_build_list),list0 前向参考队列,P帧参考;list1,后向参考队列(B帧参考list0和list1)
(3).        码率控制初始化(x264_ratecontrol_start),得到该帧所使用的量化步长QP(x264_ratecontrol_qp)
(4).        创建片头数据(x264_slice_init)
(5).        初始化比特流(bs_init)
(6).        当前帧为IDR帧时,NAL单元更新SPS(x264_sps_write)和PPS(x264_pps_write)
(7).        写片操作,返回编完一帧之后的比特流(x264_slices_write)
(8).        恢复CPU状态(x264_cpu_restore)
(9).        若帧类型是P帧,分别计算帧内编码开销和帧间编码开销,若帧间>帧内,则将P帧重新按I帧进行编码(若图片组的大小>=最小关键帧的个数,则按IDR帧编码)。
(10).        编码结束(x264_encoder_frame_end)

x264_slices_write:

1. 帧内帧间编码(x264_slice_write)
   2. 去块滤波(x264_fdec_filter_row)

x264_slice_write:

1.        初始化当前帧的状态
2.        当前进行的是帧编码,因此NAL单元携带的是一个编码片,一个NAL单元应由一组对应于视频编码的头信息和一个压缩编码后的视频数据序列。 写当前NAL单元的头信息(x264_nal_start)
3.        写片头信息(x264_slice_header_write),包括:片中第一宏块的地址,片的类型,参考帧索引及一些帧编码模式的选择
4.        循环对每个宏块进行编码:
         I.        先获得宏块的位置坐标(i_mb_x,i_mb_y),若i_mb_x为0,则进行去块滤波;
         II.        将当前宏块的上和左边的宏块加载进来存入数组(x264_macroblock_cache_load)。
         III.        对宏块进行分析(x264_macroblock_analyse),通过计算SAD值,决定宏块预测类型
                  A.        I帧:只使用帧内预测,分别计算亮度16x16(4种)和4x4(9种)色度8x8(3种)所有模式的代价值,选                              出SAT值最小的模式
                  B.        P帧:计算帧内模式(同A)和帧间模式。帧间预测:对P帧的每一种分割进行帧间预测,得到最佳的运动矢量及最佳匹配块。过程:寻找当前块的后续矢量—— >选出最佳矢量——>找到最佳的整像素点——>找到最佳的二分之一像素点——>找到最佳的1/4像素点,取代码最小的为最佳MV 和分割方式。最后从帧内模式和帧间模式中选择小者。
          IV.        对宏块进行编码
                  A、        帧内预测模式时,用所选的预测模式对宏块中的像素值进行预测,若当前块是第一块,则预测值为128
                  B、        帧间预测模式,用所选的运动矢量进行运动补偿得到宏块的预测值。对残差矩阵进行变换量化,扫描和CAVLC熵编码。
           V. 将CAVLC编码结果写入h->out.bs(x264_macroblock_write_cavlc);保存宏块信息 (x264_macroblock_cache_save);通过调整QP进行码率控制;RBSP比特填充(bs_rbsp_trailing),一次 nal编码结束,指向下一个nal(x264_nal_end);

(转)x264 编码流程的更多相关文章

  1. X264编码流程详解(转)

    http://blog.csdn.net/xingyu19871124/article/details/7671634 对H.264编码标准一直停留在理解原理的基础上,对于一个实际投入使用的编码器是如 ...

  2. WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码

    转自:http://blog.csdn.net/nonmarking/article/details/47958395 本系列目前共三篇文章,后续还会更新 WebRTC VideoEngine超详细教 ...

  3. Android camera采集视频 X264编码

    参考 http://blog.csdn.net/zblue78/article/details/6058147 感谢 ExperiencesOfCode 硬件平台:CPU Intel G630 @2. ...

  4. x264编码的图像出现乱码的问题

    将YUV进行x264编码的时候,建议将 i_threads 参数设置成 X264_SYNC_LOOKAHEAD_AUTO//* 取空缓冲区继续使用不死锁的保证. 否则有可能编码出来的数据会出现IDR_ ...

  5. 视频x264编码浅析

    声明 x264_param_t 结构体变量: x264_param_t params; x264_param_default_preset(&params, "ultrafast&q ...

  6. 使用良好的自定义X264编码,取得极佳质量!《转》

    原帖地址:http://www.xspliter.com/forum.php?mod=viewthread&tid=447 一般直播时使用A设定即可.你尝试设置并找出你最满意的设定 A为最需最 ...

  7. ffmpeg,X264编码结果I帧QP比P帧还大

    enc_ctx->profile =FF_PROFILE_H264_MAIN ; enc_ctx->time_base.den = 24; enc_ctx->time_base.nu ...

  8. 使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧

    前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境.以下就来问个样例: 1.利用x264库将YUV格式视频文件编码为h264格式视频文件 2.利用ffmpeh库将h264格 ...

  9. 用X264编码以后的H264数据

    输入的数据准备好了,编码后的数据都在x264_nal_t的数组.我这里设置的参数是Baseline Profile,所以编码后没有B帧,将编码后的数据保存分析后发现,第一次编码的时候会有4个NAl,分 ...

随机推荐

  1. C++与C# UDP通信实例(同一台PC)

    对于同一个PC机而言,服务器端和客户端在一个PC机上面,端口必须要不一样,不然会冲突. 你总不能自己又当爹又当妈吧. 所以在进行程序设计的时候,需要考虑这一点: 在此接口设计中,C++当作UDP的服务 ...

  2. 【整理】认识MSG结构体

    在Windows程序中,消息是由MSG结构体来表示的.MSG结构体的定义如下(参见MSDN): typedef struct tagMSG { HWND hwnd; UINT message; WPA ...

  3. discuz论坛移植修改数据库配置

    从其他地方拷贝的discuz源码,可能需要修改数据库配置 分别打开discuz目录下面以下三个文件 discuzRoot/uc_server/data/config.inc.phpdiscuzRoot ...

  4. POJ 2513 Colored Sticks 解题报告

    第一次接触欧拉回路.虽然在离散数学里学过,敲代码还是第一次. 本题是说端点颜色相同的两根木棒可连接,能否将所有的木棒连成一条直线. 将颜色视为节点v,将木棒视为边e,构成图G.如果能找到一条一笔画的路 ...

  5. 《大道至简》第一章读后感Java伪代码

    在<大道至简>第一章中,周爱民先生引用一则<愚公移山>的寓言,引出了编程的根本:顺序.选择.循环.“愚公移山”的工程虽然庞大,但是可以通过极其简单的变成来完成.我身边的有一些人 ...

  6. Autofs

    1. Introduction autofs is a program for automatically mounting directories on an as-needed basis. Au ...

  7. 《Android源代码设计模式解析与实战》读书笔记(十七)

    第十七章.中介者模式 中介者模式也称为调解者模式或调停者模式,是一种行为型模式. 1.定义 中介者模式包装了一系列对象相互作用的方式.使得这些对象不必相互明显作用.从而使它们能够松散耦合.当某些对象之 ...

  8. c&num;将十进制转64进制

    //由于用于文件命名,所以将64位中的+转换为=,/转换为_     static char[] digits = {          '0' , '1' , '2' , '3' , '4' , ' ...

  9. 「小程序JAVA实战」小程序首页视频(49)

    转自:https://idig8.com/2018/09/21/xiaochengxujavashizhanxiaochengxushouyeshipin48/ 视频显示的内容是视频的截图,用户的头像 ...

  10. 初识WCF2

    参照: http://blog.csdn.net/songyefei/article/details/7371571 在上一篇中,我们在一个控制台应用程序中编写了一个简单的WCF服务并承载了它.先回顾 ...