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

avcodec_open2返回Invalid Argument(-22):H264编码AVFrames到MP4遇错求助

排查avcodec_open2返回Invalid Argument(-22)的原因及解决方案

核心问题分析

avcodec_open2返回错误码-22(无效参数),通常是因为编码器上下文缺少关键配置、参数不符合编码器要求,或是编码器实例获取错误导致的。结合你的代码,以下是针对性的排查和修复方案:


具体修复步骤

1. 确认编码器实例获取正确

必须确保你是通过编码器查找函数获取H264编码器,而非解码器或空指针:

const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
    std::cout << "H264编码器未找到" << std::endl;
    return;
}

如果误用avcodec_find_decoder获取解码器,调用avcodec_open2会直接返回参数错误。

2. 修正视频分辨率的对齐要求

H264编码器对分辨率有宏块对齐要求(通常为16的倍数),你的宽度270不是16的倍数(16×17=272),这会触发编码器参数校验失败。调整分辨率为16的倍数:

stream->codecpar->width = 272; // 替换原270
stream->codecpar->height = 480; // 480是16的倍数,无需修改

3. 补充编码器上下文的关键参数

从codecpar拷贝参数到codec_ctx后,部分H264编码器需要额外配置核心参数,否则会拒绝启动。在avcodec_parameters_to_context之后添加:

// 配置帧率、GOP、时间基等核心参数
codec_ctx->framerate = (AVRational){1, 30};
codec_ctx->gop_size = 60; // 每60帧生成一个关键帧,可按需调整
codec_ctx->max_b_frames = 0; // 先禁用B帧,避免编码器不兼容
codec_ctx->time_base = stream->time_base;
codec_ctx->profile = AV_PROFILE_H264_BASELINE; // 指定H264基线 profile

4. 开启全局头参数(适配MP4封装)

MP4封装要求编码器生成全局头信息,这也是部分编码器启动的必要条件,在avcodec_open2之前添加:

codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

开启后需要将上下文参数回写到流的codecpar:

ret = avcodec_parameters_from_context(stream->codecpar, codec_ctx);
if (ret < 0) {
    std::cout << "更新流编码参数失败: " << av_err2str(ret) << std::endl;
    // 错误处理逻辑
}

完整修复后的代码片段

// 1. 正确获取H264编码器
const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
    std::cout << "H264编码器未找到" << std::endl;
    avformat_free_context(format_ctx);
    return;
}

// 2. 设置流参数(修正分辨率)
stream->codecpar->codec_id = AV_CODEC_ID_H264;
stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
stream->codecpar->width = 272; // 调整为16的倍数
stream->codecpar->height = 480;
stream->codecpar->format = AV_PIX_FMT_YUV420P;
stream->codecpar->bit_rate = 500000; // 适度提高码率,避免过低触发校验
AVRational framerate = {1, 30};
stream->time_base = av_inv_q(framerate);

// 3. 初始化编码器上下文
AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
    std::cout << "分配编码器上下文失败" << std::endl;
    avformat_free_context(format_ctx);
    return;
}

ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
if (ret < 0) {
    std::cout << "设置编码器上下文参数失败: " << av_err2str(ret) << std::endl;
    avcodec_free_context(&codec_ctx);
    avformat_free_context(format_ctx);
    return;
}

// 4. 补充编码器关键配置
codec_ctx->framerate = framerate;
codec_ctx->gop_size = 60;
codec_ctx->max_b_frames = 0;
codec_ctx->time_base = stream->time_base;
codec_ctx->profile = AV_PROFILE_H264_BASELINE;
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

// 5. 打开编码器
ret = avcodec_open2(codec_ctx, codec, nullptr);
if (ret < 0) {
    wxMessageBox("打开编码器错误: ");
    wxMessageBox(av_err2str(ret));
    avcodec_free_context(&codec_ctx);
    avformat_free_context(format_ctx);
    return;
}

// 6. 将上下文参数回写到流
ret = avcodec_parameters_from_context(stream->codecpar, codec_ctx);
if (ret < 0) {
    std::cout << "更新流编码参数失败: " << av_err2str(ret) << std::endl;
    avcodec_free_context(&codec_ctx);
    avformat_free_context(format_ctx);
    return;
}

内容的提问来源于stack exchange,提问作者nokla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:37:21