使用libx264将I420编码为H.264

标签: libx264 i420 编码 | 发表时间:2013-01-11 11:30 | 作者:杨粼波
出处:http://www.cppblog.com/tx7do/
转载自: http://www.cnblogs.com/fojian/archive/2012/09/01/2666627.html

libx264 

libx264是一个自由的H.264编码库,是 x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx264。

代码

要把一个 I420视频文件编码为H264格式。I420是YUV中planar格式的一种,一张I420图片中有三个plane,分别存放整张图片的Y、U、V分量;采样比例为4:2:0,12bpp,Y:U:V的分量长度是4:1:1。

头文件

1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <x264.h>

变量声明和参数

 1 int width = 480;
 2 int height = 360;
 3 int fps = 25;
 4 size_t yuv_size = width * height * 3 / 2;
 5 x264_t *encoder;
 6 x264_picture_t pic_in, pic_out;
 7 int inf, outf;
 8 uint8_t *yuv_buffer;
 9
10 if (argc != 3) {
11     printf("usage: %s input output\n", argv[0]);
12 }
  • 视频尺寸是480×360,YUV I420格式,每个像素1.5个字节,所以一张YUV图片大小是width * height * 1.5
  • encoder就是编码器,x264_t格式在x264.h文件中只有

          typedef struct x264_t x264_t
        

    编码器类型只需要也只能声明为x264_t的指针类型

  • 每次编码时,YUV图片的信息都保存在pic_in中
  • 输入输出的文件描述符
  • 从文件读入的YUV的缓冲区

初始化encoder

 1 x264_param_t param;
 2 x264_param_default_preset(&param, "veryfast", "zerolatency");
 3 param.i_threads = 1;
 4 param.i_width = width;
 5 param.i_height = height;
 6 param.i_fps_num = fps;
 7 param.i_fps_den = 1;
 8
 9 param.i_keyint_max = 25;
10 param.b_intra_refresh = 1;
11
12 param.b_annexb = 1;
13
14 x264_param_apply_profile(&param, "baseline");
15 encoder = x264_encoder_open(&param);

初始化pic_in

1 x264_picture_alloc(&pic_in, X264_CSP_I420, width, height);
2
3 yuv_buffer = malloc(yuv_size);
4
5 pic_in.img.plane[0] = yuv_buffer;
6 pic_in.img.plane[1] = pic_in.img.plane[0] + width * height;
7 pic_in.img.plane[2] = pic_in.img.plane[1] + width * height / 4;
  • pic_in.img中保存YUV图片各分量的信息

    typedef struct {
        int i_csp;
        int i_plane;
        int i_stride[4];
        uint8_t *plane[4];
        } x264_image_t;

    其中i csp, iplane, i stride的值在picin初始化的时候已经被赋值,代码中只需要将plane数组指向正确的位置

  • 程序中每一帧的图片都是读取到yuv_buffer中,所以在这里设置一次就行了

初始化文件描述符

1 inf = open(argv[1], O_RDONLY);
2 if (inf < 0) {
3     return -1;
4 }
5 outf = open(argv[2], O_CREAT | O_WRONLY, 444);
6 if (outf < 0) {
7     return -1;
8 }

编码

 1 int64_t i_pts = 0;
 2
 3 x264_nal_t *nals;
 4 int nnal;
 5 while (read(inf, yuv_buffer, yuv_size) > 0) {
 6     pic_in.i_pts = i_pts++;
 7     x264_encoder_encode(encoder, &nals, &nnal, &pic_in, &pic_out);
 8     x264_nal_t *nal;
 9     for (nal = nals; nal < nals + nnal; nal++) {
10         write(outf, nal->p_payload, nal->i_payload);
11     }
12 }
  • 关于ffmpeg的pts,网上有好多种公式,其实只要步长为1递增就行了
  • H.264的NAL层是为了适应网络传输的需要,将大的编码后的帧分成多个块
  • p_payload就是编码后的H.264的帧数据,写入输出文件

扫尾

1 x264_encoder_close(encoder);
2 close(inf);
3 close(outf);
4 free(yuv_buffer);
5 return 0;

编译

gcc sourcefile -lx264 -Wall -o execfile

 

这里有一段I420视频可供测试。

参考

  1. How does one encode a series of images into H264 using the x264 C API? - Stack Overflow
  2. YUV RGB 常见视频格式解析 - 一指流砂 - 博客园


本文链接

相关 [libx264 i420 编码] 推荐:

使用libx264将I420编码为H.264

- - C++博客_杨粼波
libx264是一个自由的H.264编码库,是. x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx264. I420视频文件编码为H264格式. I420是YUV中planar格式的一种,一张I420图片中有三个plane,分别存放整张图片的Y、U、V分量;采样比例为4:2:0,12bpp,Y:U:V的分量长度是4:1:1.

编码

- - 人月神话的BLOG
前面谈需求,架构和设计都比较多,今天谈一下编码方面的内容,做一个好的程序员不容易,很多时候不是体现在需求和架构能力的缺少上面,更多的是体现在最基础的编码和实现能力的不足上面. 编码是一个技术活,需要大量的脑力活动,但是很多人确可以把编码做为一个体力活,我在这里想继续强调的是如果编码是一个完全的重复体力劳动的话,那么所有工作就一定是可以自动化掉的,在这个时候你原来所有的工作没有任何的价值体现而被完全替代.

字符编码

- - 博客 - 伯乐在线
伯乐在线注:本文来自文章作者 @acmerfight 的投稿( 原文链接). 如果其他朋友也想投稿,请发邮件至 [email protected],或直接给 @伯乐在线官方微博 私信投递. 你是否认为“ASCII码 = 一个字符就是8比特”. 你是否认为一个字节就是一个字符,一个字符就是8比特.

将URL编码?

- - JavaScript - Web前端 - ITeye博客
    URL一般只能由字母、数字、$ - _. * ' ( ) 等一些字符构成. 那么当URL中需要用到汉字时怎么办,譬如有这样的URL: "www.test.com/search?name=张三",此时,只有通过将URL进行编码的方式进行传递了.     Javascript编/解码方法:.     如果对上面的URL(www.test.com/search?name=张三)进行编码的话.

编码风格不是编码规范

- - 外刊IT评论
我并不认为程序员是一个情绪特别丰富的群体. 但有一些事情却能很容易刺激程序员的神经,那就是代码格式和布局. 如果看到一个函数的括弧在同一行上没有闭合,我的眼睛会喷血. 如果看到有人没有 恰好的在两个函数间留一空行,我的小腿会抽筋. 但重点在这里——除非是在家里开发自己的业余爱好软件,我的这些个人喜好其实是无关紧要的.

理清URL编码

- winners - Thinking for Fun
关于URL编码,RFC1738做了如下的规定:. “Only alphanumerics [0-9a-zA-Z], the special characters “$-_.+!*’(),” [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL.”.

编码那些事

- winners - UEDMAGAZINE
前端开发中编码的问题一向是让人头疼的,尤其是在以gbk为基础页面编码的淘宝,情况更加复杂,除了常见的页面文件的编码之外,对不同编码js/css文件的引用、meta的charset设置、表单提交的URL编码等问题的处理稍微粗心就会出问题,特别是ajax中的编码转换,始终缺乏统一方便的解决方案,今天我们就分享两个js转码的常见案例的解决.

java编码规范

- - ITeye博客
   总结前期做的几个项目,个人认为代码的规范对团队的协作有着密切的关系. 现将一些常用的约束总结如下,以便今后参阅:. 1、所有的类、属性、方法都遵守以字母和数字为主,尽量不要参与特殊符号如下划线. 其次,除类名开头字母大写外,其他名字都要小写,然后第二个后的单词首字母大写,长度在30个字符以内.

oracle 编码规范

- - 操作系统 - ITeye博客
军规一:【恰当控制事务大小,commit不要过于频繁. 】 军规二:【在OLTP系统中一定要注意使用绑定变量. 】 军规三:【在OLTP系统中一定要注意复杂的多表关联不宜超过4个,关联十分复杂时,需要拆分成多个步骤,防止执行计划不正确. 】 军规四:【合理收集统计信息,固定住SQL的执行计划. 】 军规五:【尽量避免使用XA事务,在RAC环境中要避免XA事务跨节点操作.