这是典型的库版本不匹配或链接顺序错误;需用pkg-config获取完整链接参数,并严格按依赖顺序链接libavcodec、libavformat、libavutil等库。

ffmpeg C++ 编译链接时找不到 avcodec_open2 或 avformat_network_init
这是典型的库版本不匹配或链接顺序错误。FFmpeg 从 4.0 开始把功能拆到 libavcodec、libavformat、libavutil 等独立库,C++ 项目里只链接 -lavcodec 不够,漏掉依赖项就会报“undefined reference”。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
pkg-config --libs libavcodec libavformat libavutil libswscale libswresample拿完整链接参数,别手写 - 链接顺序必须是:你的目标文件 →
-lavcodec→-lavformat→-lavutil→-lswscale→-lswresample(顺序反了会失败) - 如果用 CMake,别只写
target_link_libraries(myapp avcodec),得补全全部且按依赖顺序列出来 - Windows 下用 MinGW 链接 .dll.a 时,确保头文件和库文件来自同一套编译产物(比如都用 ffmpeg-6.1-full_build,别混用 Zeranoe 和官方 build)
用 AVFrame 解码视频帧后,data[0] 是空的或图像错乱
常见于没正确分配输出缓冲区,或忽略像素格式转换。FFmpeg 解码出来的 AVFrame 数据布局(如 planar YUV)和你要显示/处理的格式(如 RGB24)不一致,直接读 data[0] 就是错的。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 解码后先检查
frame->format和frame->width/frame->height是否有效,不是所有帧都成功解码 - 要用
sws_getContext+sws_scale做格式/尺寸转换,不能假设解码输出就是你要的 layout -
AVFrame的内存由av_frame_alloc()分配,但数据缓冲区需用av_frame_get_buffer()显式申请(尤其硬解码场景下,有些 decoder 会复用内部 buffer) - 别在循环里反复
av_frame_free()+av_frame_alloc(),复用一个AVFrame*更安全
调用 avcodec_send_packet 返回 AVERROR(EAGAIN) 或卡住
这不是错误,是 FFmpeg 的流控信号:编码器/解码器内部缓冲区满了,需要先调 avcodec_receive_frame(解码)或 avcodec_receive_packet(编码)把积压数据取走,才能继续送新数据。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须用 do-while 循环处理
avcodec_receive_frame,直到它返回AVERROR(EAGAIN)或AVERROR_EOF,否则会漏帧 - 发送 packet 前确认
pkt->size > 0,空 packet(size == 0)可能触发 flush 行为,但不是所有 codec 都支持 - H.264/H.265 流里带 B 帧时,
avcodec_receive_frame可能比avcodec_send_packet慢一拍,时间戳对不上是正常的,别靠 packet 时间戳直接当 frame 时间戳用 - 多线程调用时,
AVCodecContext*不是线程安全的,要么加锁,要么每个线程独占一个 context
C++ RAII 封装 AVFormatContext 容易 double-free
FFmpeg 的资源释放函数(如 avformat_close_input)会把指针置为 nullptr,但 C++ 析构函数里再调一次就崩了。更隐蔽的是,avformat_open_input 失败时,传入的 AVFormatContext** 可能部分初始化,直接析构会访问野指针。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 构造时把
AVFormatContext*初始化为nullptr,析构前只在非空时调avformat_close_input - 不要在 RAII 对象里存裸指针,改用
std::unique_ptr<AVFormatContext, void(*)(AVFormatContext*)>,自定义 deleter 里判断是否为空 -
avio_open打开的 IO 上下文要单独管理,它不随avformat_close_input自动释放 - 用
avformat_find_stream_info前,确保ic->streams已分配,否则某些低版本 FFmpeg 会 crash
avcodec_send_packet 和 avcodec_receive_frame 返回负值时,多数人直接忽略,结果后面操作全在无效数据上跑。











