我試圖使用Mac OS X 10.9.5上的libx264實時將來自MacBook Pro內置FaceTime高清攝像頭的輸入圖像實時編碼爲H.264視頻流。如何將來自攝像機的輸入圖像編碼爲H.264流?
下面是我所採取的步驟:在15fps的使用AVFoundation API(AVCaptureDevice類等)
- 獲取1280×720從相機32BGRA圖像。
- 使用libx264將圖像編碼爲H.264視頻流(基線配置文件)。
我每次從相機獲取圖像時都會應用上述步驟,相信編碼器會跟蹤編碼狀態並在可用時生成NAL單元。因爲我希望在向編碼器提供輸入圖像的同時獲得編碼幀,所以我決定每隔30幀(2秒)刷新一次編碼器(調用x264_encoder_delayed_frames())以調用x264_encoder_delayed_frames()。但是,當我重新啓動編碼時,編碼器會在一段時間後停止(x264_encoder_encode()永不返回)。我嘗試在刷新之前更改幀數,但情況沒有改變。
下面是相關的代碼(我省略了圖像捕捉代碼,因爲它看起來沒有問題。)
你能指出什麼我可能是做錯了?
x264_t *encoder;
x264_param_t param;
// Will be called only first time.
int initEncoder() {
int ret;
if ((ret = x264_param_default_preset(¶m, "medium", NULL)) < 0) {
return ret;
}
param.i_csp = X264_CSP_I420;
param.i_width = 320;
param.i_height = 180;
param.b_vfr_input = 0;
param.b_repeat_headers = 1;
param.b_annexb = 1;
if ((ret = x264_param_apply_profile(¶m, "baseline")) < 0) {
return ret;
}
encoder = x264_encoder_open(¶m);
if (!encoder) {
return AVERROR_UNKNOWN;
}
return 0;
}
// Will be called from encodeFrame() defined below.
int convertImage(const enum AVPixelFormat srcFmt, const int srcW, const int srcH, const uint8_t *srcData, const enum AVPixelFormat dstFmt, const int dstW, const int dstH, x264_image_t *dstData) {
struct SwsContext *sws_ctx;
int ret;
int src_linesize[4];
uint8_t *src_data[4];
sws_ctx = sws_getContext(srcW, srcH, srcFmt,
dstW, dstH, dstFmt,
SWS_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
return AVERROR_UNKNOWN;
}
if ((ret = av_image_fill_linesizes(src_linesize, srcFmt, srcW)) < 0) {
sws_freeContext(sws_ctx);
return ret;
}
if ((ret = av_image_fill_pointers(src_data, srcFmt, srcH, (uint8_t *) srcData, src_linesize)) < 0) {
sws_freeContext(sws_ctx);
return ret;
}
sws_scale(sws_ctx, (const uint8_t * const*)src_data, src_linesize, 0, srcH, dstData->plane, dstData->i_stride);
sws_freeContext(sws_ctx);
return 0;
}
// Will be called for each frame.
int encodeFrame(const uint8_t *data, const int width, const int height) {
int ret;
x264_picture_t pic;
x264_picture_t pic_out;
x264_nal_t *nal;
int i_nal;
if ((ret = x264_picture_alloc(&pic, param.i_csp, param.i_width, param.i_height)) < 0) {
return ret;
}
if ((ret = convertImage(AV_PIX_FMT_RGB32, width, height, data, AV_PIX_FMT_YUV420P, 320, 180, &pic.img)) < 0) {
x264_picture_clean(&pic);
return ret;
}
if ((ret = x264_encoder_encode(encoder, &nal, &i_nal, &pic, &pic_out)) < 0) {
x264_picture_clean(&pic);
return ret;
}
if(ret) {
for (int i = 0; i < i_nal; i++) {
printNAL(nal + i);
}
}
x264_picture_clean(&pic);
return 0;
}
// Will be called every 30 frames.
int flushEncoder() {
int ret;
x264_nal_t *nal;
int i_nal;
x264_picture_t pic_out;
/* Flush delayed frames */
while (x264_encoder_delayed_frames(encoder)) {
if ((ret = x264_encoder_encode(encoder, &nal, &i_nal, NULL, &pic_out)) < 0) {
return ret;
}
if (ret) {
for (int j = 0; j < i_nal; j++) {
printNAL(nal + j);
}
}
}
}
在flushEncoder()的末尾插入兩行後,上面的代碼就開始工作了。我添加了x264_encoder_close(編碼器);和initEncoder(); – kuu