使用avcodec_alloc_context(NULL)初始化libx264rgb编码器失败求助
问题描述
我希望使用FFmpeg编码库结合libx264rgb编码器实现音视频复用。当调用avcodec_alloc_context3时指定该编码器可正常打开,但传入NULL分配上下文则失败——我认为需用NULL来同时处理音频编码器。
示例中第一种指定编码器的初始化方式可行,第二种失败。代码如下:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <libavcodec/avcodec.h> #include <libavutil/opt.h> #define WIDTH 400 #define HEIGHT 300 const AVCodec *videocodec; bool init_video_encoder(AVCodecContext *c, int width, int height) { int ret; const AVRational tb_rat = {1, 30}; const AVRational fr_rat = {30, 1}; fprintf(stderr, "init video encoder\n"); // video //fprintf(stderr, "speed= %d \n", videocodec->speed); c->bit_rate = 400000; c->width = width; c->height = height; c->time_base = tb_rat; c->framerate = fr_rat; c->gop_size = 10; c->max_b_frames = 1; c->pix_fmt = AV_PIX_FMT_RGB24; if( videocodec->id == AV_CODEC_ID_H264 ) av_opt_set(c->priv_data, "preset", "slow", 0); ret = avcodec_open2(c, videocodec, NULL); if( ret < 0 ) { fprintf(stderr, "failure to open codec: %s\n", av_err2str(ret)); return false; } //avcodec_free_context(&c); return true; } int main(int argc, char **argv) { AVCodecContext *context = NULL; videocodec = avcodec_find_encoder_by_name("libx264rgb"); if( videocodec == NULL ) { fprintf(stderr, "video encoder 'libx264rgb' not found"); exit; } context = avcodec_alloc_context3(videocodec); if( context == NULL ) { fprintf(stderr, "could not allocate context with codec"); return false; } if( init_video_encoder( context, WIDTH, HEIGHT ) ) fprintf(stderr, " success initializing video encoder case one\n"); else fprintf(stderr, " failure to initialize video encoder case one\n"); avcodec_close( context ); context = avcodec_alloc_context3(NULL); if( context == NULL ) { fprintf(stderr, "could not allocate context without codec"); return false; } if( init_video_encoder( context, WIDTH, HEIGHT ) ) fprintf(stderr, " success initializing video encoder case two\n"); else fprintf(stderr, " failure to initialize video encoder case two\n"); avcodec_close( context ); }
错误信息如下:
broken ffmpeg default settings detected use an encoding preset (e.g. -vpre medium) preset usage: -vpre <speed> -vpre <profile> speed presets are listed in x264 --help profile is optional; x264 defaults to high failure to open codec: Generic error in an external library failure to initialize video encoder case two
请问该方法是否正确?如何设置编码预设?代码中似乎已完成相关设置。
解决方案
方法可行性说明
用avcodec_alloc_context3(NULL)兼容音视频编码器的思路是可行的,但当前代码的实现存在逻辑问题,导致编码预设设置失效,进而引发编码器打开失败。
问题根源分析
- 调用
avcodec_alloc_context3(videocodec)时,FFmpeg会自动基于指定编码器初始化上下文,包括分配并初始化编码器的私有数据(c->priv_data),此时调用av_opt_set设置预设是有效的。 - 用
avcodec_alloc_context3(NULL)创建的上下文是空白状态,c->priv_data此时为NULL,在avcodec_open2之前调用av_opt_set(c->priv_data, ...)相当于对空指针操作,预设根本没有设置成功,因此x264编码器检测不到预设配置,抛出错误。
修复后的代码
调整init_video_encoder函数,在设置参数前先基于目标编码器初始化上下文默认参数,确保c->priv_data被正确分配:
bool init_video_encoder(AVCodecContext *c, int width, int height) { int ret; const AVRational tb_rat = {1, 30}; const AVRational fr_rat = {30, 1}; fprintf(stderr, "init video encoder\n"); // 关键步骤:基于目标编码器初始化上下文默认参数,包括分配priv_data avcodec_get_context_defaults3(c, videocodec); // 设置视频参数 c->bit_rate = 400000; c->width = width; c->height = height; c->time_base = tb_rat; c->framerate = fr_rat; c->gop_size = 10; c->max_b_frames = 1; c->pix_fmt = AV_PIX_FMT_RGB24; // 此时priv_data已分配,可以正常设置编码预设 if( videocodec->id == AV_CODEC_ID_H264 ) av_opt_set(c->priv_data, "preset", "slow", 0); ret = avcodec_open2(c, videocodec, NULL); if( ret < 0 ) { fprintf(stderr, "failure to open codec: %s\n", av_err2str(ret)); return false; } return true; }
补充说明
- 编码预设的设置逻辑本身是正确的,但必须确保在
c->priv_data已分配的前提下调用av_opt_set,否则设置不会生效。 - 使用
avcodec_alloc_context3(NULL)可以灵活切换音视频编码器,只需针对不同编码器编写对应的参数初始化逻辑即可。
内容的提问来源于stack exchange,提问作者user3763774
相关产品推荐
相关产品推荐

