X264编码相关的总结
一、库的交叉编译
详情见交叉编译X264
注:
之前我用的arm9的板子,交叉编译x264库的时候出现问题,说是arm9的架构没办法编译
之后换成arm11的板子才成功的。
二、库的调用
typedef struct { //编码需要使用的对象 为Encoder结构的成员
x264_param_t *param; //参数设置
x264_t *handle;
x264_picture_t *picture;
x264_nal_t *nal;
} Encoder;
编码前的初始化函数,包括内存的分配,编码参数的初始化
//按照自己编码的需要,设定en->param里的值
void compress_begin(Encoder *en, int width, int height) { en->param = (x264_param_t *) malloc(sizeof(x264_param_t)); if(en->param==NULL) { printf("param=null "); exit(1); } en->picture = (x264_picture_t *) malloc(sizeof(x264_picture_t)); if(en->picture==NULL) { printf("pic=null "); exit(1); } 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 //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; en->param->i_fps_num = 5; en->param->i_fps_den = 1; x264_param_apply_profile(en->param, x264_profile_names[0]); if ((en->handle = x264_encoder_open(en->param)) == 0) { return; } /* Create a new pic */ x264_picture_alloc(en->picture, X264_CSP_I420, en->param->i_width, en->param->i_height); en->picture->img.i_csp = X264_CSP_I420; en->picture->img.i_plane = 3; }编码函数
//将yuv422的Y U V抽出,直接编码为264
int compress_frame(Encoder *en, int type, uint8_t *in, uint8_t *out) { x264_picture_t pic_out; int nNal = -1; int result = 0; int i = 0; uint8_t *p_out = out; uint8_t *y = en->picture->img.plane[0]; uint8_t *u = en->picture->img.plane[1]; uint8_t *v = en->picture->img.plane[2]; int is_y = 1, is_u = 1; int y_index = 0, u_index = 0, v_index = 0; int yuv422_length = 2 * en->param->i_width * en->param->i_height; for (i = 0; i < yuv422_length; ++i) { if (is_y) { *(y + y_index) = *(in + i); ++y_index; is_y = 0; } else { if (is_u) { *(u + u_index) = *(in + i); ++u_index; is_u = 0; } else { *(v + v_index) = *(in + i); ++v_index; is_u = 1; } is_y = 1; } } 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; } if (x264_encoder_encode(en->handle, &(en->nal), &nNal, en->picture, &pic_out) < 0) { return -1; } en->picture->i_pts++; 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; }
输出264内存的指针为out,长度为result,写入文件可能x264格式的文件,用VLC播放器可以打开。
编码结束的释放内存收尾函数
void compress_end(Encoder *en) { if (en->picture) { x264_picture_clean(en->picture); free(en->picture); en->picture = 0; } if (en->param) { free(en->param); en->param = 0; } if (en->handle) { x264_encoder_close(en->handle); } free(en); }
注:
摄像头的分辨率自己根据摄像头设置,否则可能出现segmentation fault.
高版本容易出现彩色空间无法编码的问题,也会出现segmentation fault,或者编码到264文件大小为0kb
建议用低版本的库进行编码。
如果你得到的数据和上面设置的X264_CSP_I420不匹配,每一帧会出现colorplace fault。