YUYV資料—X264編碼H264視訊例項
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