调用avcodec_open2返回-22(无效参数)的FFmpeg视频转换问题
排查FFmpeg avcodec_open2返回-22(无效参数)的问题
核心问题:编码器上下文缺少必要参数
avcodec_open2返回-22的本质是输出编码器上下文outputCodecContext的配置不符合编码器要求,以下是必须补充和修正的关键项:
1. 必须添加帧率(framerate)和GOP大小(gop_size)
绝大多数视频编码器需要明确的帧率和关键帧间隔,否则会判定参数无效:
// 从输入上下文推导帧率(或直接设置固定值如{30,1}表示30fps) outputCodecContext->framerate = av_inv_q(inputCodecContext->time_base); // 设置关键帧间隔,例如每10帧生成一个关键帧 outputCodecContext->gop_size = 10; // 可选:设置B帧数量,根据编码器支持情况调整 outputCodecContext->max_b_frames = 1;
2. 安全获取像素格式
直接取outputCodec->pix_fmts[0]可能拿到无效值(部分编码器的格式数组开头是AV_PIX_FMT_NONE),需要先验证:
if (outputCodec->pix_fmts && outputCodec->pix_fmts[0] != AV_PIX_FMT_NONE) { outputCodecContext->pix_fmt = outputCodec->pix_fmts[0]; } else { // fallback到通用兼容格式YUV420P outputCodecContext->pix_fmt = AV_PIX_FMT_YUV420P; }
3. 修正Time_base的设置逻辑
部分编码器要求time_base与帧率严格对应,建议通过输入流的实际帧率推导,而非直接复用输入的time_base:
// 获取输入流的实际帧率 AVRational input_frame_rate = av_guess_frame_rate(inputFormatContext, inputFormatContext->streams[videoStreamIndex], NULL); // 编码器的time_base通常设为帧率的倒数 outputCodecContext->time_base = av_inv_q(input_frame_rate);
修正后的编码器配置完整代码
const AVCodec* outputCodec = avcodec_find_encoder_by_name(codecName.c_str()); if (!outputCodec) { std::cout << "Zielformat-Codec nicht gefunden" << std::endl; return -1; } AVCodecContext* outputCodecContext = avcodec_alloc_context3(outputCodec); outputCodecContext->bit_rate = bitRate; outputCodecContext->width = inputCodecContext->width; outputCodecContext->height = inputCodecContext->height; // 安全设置像素格式 if (outputCodec->pix_fmts && outputCodec->pix_fmts[0] != AV_PIX_FMT_NONE) { outputCodecContext->pix_fmt = outputCodec->pix_fmts[0]; } else { outputCodecContext->pix_fmt = AV_PIX_FMT_YUV420P; } // 设置帧率和time_base AVRational input_frame_rate = av_guess_frame_rate(inputFormatContext, inputFormatContext->streams[videoStreamIndex], NULL); outputCodecContext->framerate = input_frame_rate; outputCodecContext->time_base = av_inv_q(input_frame_rate); // 添加关键帧间隔和B帧配置 outputCodecContext->gop_size = 10; outputCodecContext->max_b_frames = 1; int errorCode = avcodec_open2(outputCodecContext, outputCodec, NULL); if (errorCode != 0) { char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(errorCode, errbuf, AV_ERROR_MAX_STRING_SIZE); std::cout << "Fehler beim Öffnen des Zielformat-Codecs: " << errbuf << std::endl; return -1; }
额外优化:打印详细错误信息
添加av_strerror可以获取更具体的错误描述,帮助定位问题:
char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(errorCode, errbuf, AV_ERROR_MAX_STRING_SIZE); std::cout << "Fehler beim Öffnen des Zielformat-Codecs: " << errbuf << std::endl;
内容的提问来源于stack exchange,提问作者stupidbutseeking
相关产品推荐
相关产品推荐

