V4L2视频采集与H264编码4—X264编码H264视频
? ? 在我們的視頻采集傳輸設(shè)備中,先是通過攝像頭采集顏色數(shù)據(jù)組成一張畫面,也就是我們常說的一幀。數(shù)據(jù)格式可以是YUV數(shù)據(jù)也可以是RGB數(shù)據(jù),他們之間可以通過計算轉(zhuǎn)換。我們看到的視頻其實就是由一幀一幀的畫面組成,其速度一般是25幀/秒,電影《比利林恩的中場戰(zhàn)事》采用的120幀/秒的技術(shù)。如果直接將攝像頭采集到的顏色編碼成視頻,那么視頻要求的帶寬是非常非常高的。以30萬像素攝像頭YUV420格式來計算一幀數(shù)據(jù)大小 = 長 * 寬 * 1.5 = 640 * 480 * 1.5 ?/ 1024 ?= 450 K,視頻的碼流將會是 450 K * 25 ?/ 1024 = 9.88M/s。為了使視頻傳輸更加的流暢,現(xiàn)在的視頻都采用的壓縮編碼。這里我們將介紹使用X264編碼器將YUV420 數(shù)據(jù)編碼成H264格式視頻。YUV數(shù)據(jù)采集在前面已經(jīng)介紹:
V4L2視頻采集與H264編碼1—V4L2采集JPEG數(shù)據(jù)
V4L2視頻采集與H264編碼2—v4l2采集YUV數(shù)據(jù)?
V4L2視頻采集與H264編碼3—X264移植
現(xiàn)在直接上本章的代碼,也就是編碼部分的代碼:
/*============================================================================= # FileName: h264encoder.c # Desc: this program aim to get image from USB camera, # used the V4L2 interface. # Author: Licaibiao # Version: # LastChange: 2016-12-11 # History:=============================================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "./include/h264encoder.h"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 widthen->param->i_height = height; //set frame heighten->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 kbpsen->param->i_fps_num = 25; 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; }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;char *y = en->picture->img.plane[0]; char *u = en->picture->img.plane[1]; char *v = en->picture->img.plane[2]; //yuv420_length = 1.5 * en->param->i_width * en->param->i_height//int length = en->param->i_width * en->param->i_height;//y = 640*480 ; U = 640*480*0.25, V = 640*480*0.25; memcpy(y,in,307200);memcpy(u,in+307200,76800);memcpy(v,in+384000,76800);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;}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->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); } ? ? 函數(shù)compress_begin 初始化的各參數(shù)的意思,可以參考x264重要結(jié)構(gòu)體詳細說明?上面的參數(shù)我是隨意配置的。compress_frame 里面的
? ? memcpy(y,in,307200);
? ? memcpy(u,in+307200,76800);
? ? memcpy(v,in+384000,76800);
? ? 這數(shù)值是根據(jù)我之前v4l2輸出格式計算的,我設(shè)置的是YUV420 輸出格式,其每個像素是每4個Y分量公用一個UV分量,所以Y = 4/4*width*hight;U = 1/4 *width*hight; V =?1/4 *width*hight。具體的可以參考:圖文詳解YUV420數(shù)據(jù)格式
? ? 編譯方到開發(fā)板的執(zhí)行結(jié)果如下:
/tmp # /tmp # ls hostapd lib messages utmp x264_test /tmp # ls lib libx264.so.148 /tmp # export LD_LIBRARY_PATH=/tmp/lib:$LD_LIBRARY_PATH /tmp # ./x264_test camera driver name is : sunxi-vfe camera device name is : sunxi-vfe camera bus information: sunxi_vfe vfe.2 n_buffer = 3 x264 [warning]: lookaheadless mb-tree requires intra refresh or infinite keyint x264 [info]: using cpu capabilities: none! x264 [info]: profile Constrained Baseline, level 3.0 x264 [warning]: non-strictly-monotonic PTS encode_frame num = 0 x264 [warning]: non-strictly-monotonic PTS encode_frame num = 1........ x264 [warning]: non-strictly-monotonic PTS encode_frame num = 98 x264 [info]: frame I:10 Avg QP:23.29 size: 15057 x264 [info]: frame P:89 Avg QP:26.69 size: 2080 x264 [info]: mb I I16..4: 63.6% 0.0% 36.4% x264 [info]: mb P I16..4: 10.6% 0.0% 0.2% P16..4: 39.0% 3.5% 1.8% 0.0% 0.0% skip:44.8% x264 [info]: coded y,uvDC,uvAC intra: 17.2% 83.3% 39.6% inter: 4.0% 30.0% 0.1% x264 [info]: i16 v,h,dc,p: 49% 24% 13% 14% x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 13% 39% 23% 5% 4% 2% 8% 2% 4% x264 [info]: i8c dc,h,v,p: 63% 18% 16% 3% x264 [info]: ref P L0: 62.1% 21.6% 16.2% x264 [info]: kb/s:inf /tmp # /tmp # ls -l total 588 drwxr-x--- 2 root root 60 Jan 1 00:00 hostapd drwxr-xr-x 2 root root 60 Jan 1 00:00 lib -rw-r--r-- 1 root root 28372 Jan 1 00:37 messages -rw-r--r-- 1 root root 335669 Jan 1 00:37 test.h264 -rw-r--r-- 1 root root 1152 Jan 1 00:00 utmp -rwxrwxrwx 1 root root 20674 Dec 11 2016 x264_test /tmp #? ? 生成了我們所需要的H264格式視頻文件test.h264,使用VLC media player 播放器可以直接播放。本來想做成實時視頻流,無奈我開發(fā)板太low,編寫一幀數(shù)據(jù)就需要接近兩秒的時間,實在是受不了。
下面是使用播放器播放錄制的視頻截圖
? ? 這個工程的全部代碼和X264編譯生成的庫文件可以到這里下載?X264編碼H264工程
? ? 最簡單的視頻編碼到這里告一段落。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2016.12.11
總結(jié)
以上是生活随笔為你收集整理的V4L2视频采集与H264编码4—X264编码H264视频的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《图书管理系统》—需求分析报告
- 下一篇: [css] 不用换行的标签,怎么伪元素