You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:14:52