x264库的编译可以见之前博客:http://blog.csdn.net/li_wen01/article/details/53571929
在PC上编译X264,可以直接执行下面三条命令:
./configure --enable-shared
make
make install
/*=============================================================================
# FileName: h264encoder.c
# Desc: this program aim to get image from USB camera,
# used the V4L2 interface.
# Author: licaibiao
# Version:
# LastChange: 2017-02-21
=============================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./include/h264encoder.h"
int WIDTH = 640;
int HEIGHT = 480;
void compress_begin(Encoder *en, int width, int height) {
en->param = (x264_param_t *) malloc(sizeof(x264_param_t));
en->picture = (x264_picture_t *) malloc(sizeof(x264_picture_t));
x264_param_default(en->param); //set default param
//en->param->rc.i_rc_method = X264_RC_CQP;
// en->param->i_log_level = X264_LOG_NONE;
en->param->i_threads = X264_SYNC_LOOKAHEAD_AUTO;
en->param->i_width = width; //set frame width
en->param->i_height = height; //set frame height
WIDTH = width;
HEIGHT = height;
//en->param->i_frame_total = 0;
//en->param->i_keyint_max = 10;
en->param->rc.i_lookahead = 0;
//en->param->i_bframe = 5;
//en->param->b_open_gop = 0;
//en->param->i_bframe_pyramid = 0;
//en->param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
//en->param->rc.i_bitrate = 1024 * 10;//rate 10 kbps
en->param->i_fps_num = 30;
en->param->i_fps_den = 1;
en->param->i_csp = X264_CSP_I422;
x264_param_apply_profile(en->param, x264_profile_names[4]);
if ((en->handle = x264_encoder_open(en->param)) == 0) {
return;
}
/* Create a new pic */
x264_picture_alloc(en->picture, X264_CSP_I422, en->param->i_width,
en->param->i_height);
}
int compress_frame(Encoder *en, int type, uint8_t *in, uint8_t *out) {
x264_picture_t pic_out;
int index_y, index_u, index_v;
int num;
int nNal = -1;
int result = 0;
int i = 0;
static long int pts = 0;
uint8_t *p_out = out;
char *y = en->picture->img.plane[0];
char *u = en->picture->img.plane[1];
char *v = en->picture->img.plane[2];
char * ptr;
index_y = 0;
index_u = 0;
index_v = 0;
num = WIDTH * HEIGHT * 2 - 4 ;
for(i=0; i<num; i=i+4)
{
*(y + (index_y++)) = *(in + i);
*(u + (index_u++)) = *(in + i + 1);
*(y + (index_y++)) = *(in + i + 2);
*(v + (index_v++)) = *(in + i + 3);
}
switch (type) {
case 0:
en->picture->i_type = X264_TYPE_P;
break;
case 1:
en->picture->i_type = X264_TYPE_IDR;
break;
case 2:
en->picture->i_type = X264_TYPE_I;
break;
default:
en->picture->i_type = X264_TYPE_AUTO;
break;
}
en->picture->i_pts = pts++;
if (x264_encoder_encode(en->handle, &(en->nal), &nNal, en->picture,
&pic_out) < 0) {
return -1;
}
for (i = 0; i < nNal; i++) {
memcpy(p_out, en->nal[i].p_payload, en->nal[i].i_payload);
p_out += en->nal[i].i_payload;
result += en->nal[i].i_payload;
}
return result;
}
void compress_end(Encoder *en) {
if (en->handle) {
x264_encoder_close(en->handle);
}
if (en->picture) {
x264_picture_clean(en->picture);
free(en->picture);
en->picture = 0;
}
if (en->param) {
free(en->param);
en->param = 0;
}
}
en->param->i_csp = X264_CSP_I422;
在X264中默认的i_csp值是3,也就是X264_CSP_NV12 的值,如果采用YUYV(422)输入格式,这个值一定需要重新设置,不然会出现错误提示:x264 [error]: Invalid input colorspace 。这是因为在x264内核中他会把输入格式装换为下面三种中的一种:X264_CSP_NV12,X264_CSP_NV16,X264_CSP_I444.转换如下:
static int x264_frame_internal_csp( int external_csp )
{
switch( external_csp & X264_CSP_MASK )
{
case X264_CSP_NV12:
case X264_CSP_NV21:
case X264_CSP_I420:
case X264_CSP_YV12:
return X264_CSP_NV12;
case X264_CSP_NV16:
case X264_CSP_I422:
case X264_CSP_YV16:
case X264_CSP_V210:
return X264_CSP_NV16;
case X264_CSP_I444:
case X264_CSP_YV24:
case X264_CSP_BGR:
case X264_CSP_BGRA:
case X264_CSP_RGB:
return X264_CSP_I444;
default:
return X264_CSP_NONE;
}
}
(2)profile类型设置
x264_param_apply_profile(en->param, x264_profile_names[4]);
在YUV422中,它不支持baseline,默认设置会提示:x264 [error]: baseline profile doesn't support 4:2:2 可以设置下面的其他参数:
x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 };
(3)图片内存分配
x264_picture_alloc(en->picture, X264_CSP_I422, en->param->i_width,
en->param->i_height);
这里的第二个参数一定要与你的输入格式先对应,不然的话会出现内存溢出的错误。因为默认的分配图片内存大小是YUV420的。以640*480 分辨率来举例,YUV420 分配一帧图像的内存是450K,而我们YUV422的数据量是600K。
(4)Y,U,V 数据需要分离
for(i=0; i<num; i=i+4)
{
*(y + (index_y++)) = *(in + i);
*(u + (index_u++)) = *(in + i + 1);
*(y + (index_y++)) = *(in + i + 2);
*(v + (index_v++)) = *(in + i + 3);
}
YUYV的数据是交错存储的,因此需要把他们分离出来单独存储,如果这里不做处理,图像就会出现异常。
(5)i_pts 参数需要递增
en->picture->i_pts = pts++;
i_pts = pts的参数是需要递增的,不让回出现警告:x264 [warning]: non-strictly-monotonic PTS