1. 理解avcodec_send_frame()与-22错误当你用FFmpeg处理视频编码时avcodec_send_frame()是个关键函数。它负责把准备好的视频帧AVFrame喂给编码器。但很多开发者都遇到过它突然返回-22的情况这时候控制台可能会打印出AVERROR(EINVAL)的错误提示。这个错误代码的字面意思是无效参数但实际上它更像编码器在说我现在没法工作我第一次遇到这个问题时也很懵——明明参数都检查过了为什么还说无效后来发现这个错误码其实是个万能筐可能隐藏着多种底层问题。就像你按下电灯开关灯不亮可能是灯泡坏了、没通电或者开关本身故障。我们需要用排除法来定位真实原因。2. 编码器未初始化的排查与修复2.1 检查编码器打开状态最常见的原因就像你忘记打开水龙头却纳闷为什么没水——编码器根本没启动。在FFmpeg中avcodec_open2()就是那个开关。我见过不少案例都是开发者调用了avcodec_alloc_context3()创建上下文后直接跳过了打开步骤。验证方法很简单在调用avcodec_send_frame()前加个检查if (!avctx-codec || !avcodec_is_open(avctx)) { fprintf(stderr, 编码器未初始化请检查avcodec_open2调用\n); return; }2.2 编码器参数配置要点即使调用了avcodec_open2()参数配置不当也会导致初始化失败。去年我帮一个团队调试时发现他们设置了AV_CODEC_FLAG_GLOBAL_HEADER却忘记配置extradata导致编码器半瘫痪状态。建议检查分辨率是否超出编码器限制比如某些硬件编码器要求16对齐像素格式是否被支持用avcodec_get_supported_framerate()验证比特率/帧率设置是否合理3. 编码器类型错误的典型场景3.1 编码器与解码器混淆新手最容易踩的坑就是把avcodec_find_encoder()错写成avcodec_find_decoder()。这种错误在音频处理时特别隐蔽——因为有些编解码器同时支持双向操作但视频编码器通常区分严格。建议在代码里显式验证if (!av_codec_is_encoder(codec)) { fprintf(stderr, 错误%s不是编码器\n, codec-name); return AVERROR(EINVAL); }3.2 硬件编码器的特殊要求如果你在使用VAAPI、NVENC等硬件编码器还需要注意设备初始化是否成功检查hw_device_ctx像素格式是否匹配比如NVENC通常要求NV12是否有足够的显存有个真实案例某直播应用在Windows平台正常但在Linux上报-22错误最后发现是缺少libva驱动。这种跨平台问题建议用av_hwdevice_iterate_types()枚举支持的设备类型。4. 帧数据与编码状态检查4.1 帧参数匹配性验证即使编码器正常帧数据不匹配也会触发EINVAL。我曾遇到一个4:2:2格式的帧试图喂给只支持4:2:0的编码器的情况。关键检查点if (frame-format ! avctx-pix_fmt) { fprintf(stderr, 像素格式不匹配帧%d编码器%d\n, frame-format, avctx-pix_fmt); } if (frame-width ! avctx-width || frame-height ! avctx-height) { fprintf(stderr, 分辨率不匹配帧%dx%d编码器%dx%d\n, frame-width, frame-height, avctx-width, avctx-height); }4.2 编码器内部状态机FFmpeg编码器内部有复杂的状态管理。当出现EAGAIN错误后立即重试可能触发EINVAL。建议的处理流程收到EAGAIN时调用avcodec_receive_packet()清空缓冲区检查avci-draining状态对于视频编码确保PTS是严格递增的5. 高级调试技巧与工具5.1 启用FFmpeg调试日志在调用avcodec_open2()前设置avctx-debug FF_DEBUG_PICT_INFO | FF_DEBUG_RC; av_log_set_level(AV_LOG_DEBUG);这样可以看到编码器初始化的详细过程有时能发现配置参数被自动修改的情况。5.2 使用GDB/LLDB断点调试对于偶发问题可以在avcodec_send_frame()内部设断点。重点关注av_codec_is_encoder()的返回值avcodec_is_open()的判定路径encode_send_frame_internal()的预处理逻辑6. 跨版本兼容性处理FFmpeg不同版本的行为可能有差异。比如在4.3版本中某些编码器对NULL帧的处理更严格。建议用avcodec_version()检查运行时版本对于关键应用固定链接特定版本的库注意AVCodecContext结构体字段的变化最近就遇到一个案例某项目升级FFmpeg后出现-22错误原来是thread_count默认值从0变成了auto导致某些编码器异常。7. 实战问题排查流程图遇到-22错误时可以按以下步骤排查[编码器类型] 确认使用的是编码器而非解码器[初始化] 检查avcodec_open2()是否成功调用[参数匹配] 验证帧参数与编码器设置一致[硬件支持] 如果是硬件编码检查设备初始化[状态机] 确认没有处在draining或异常状态[版本检查] 对比FFmpeg版本差异把这个流程图打印贴在工位上能节省大量调试时间——这是我从三个通宵的调试经历中得出的经验。