ffmpeg解码器初始化必须调用avcodec_open2,仅avcodec_find_decoder无法完成资源分配;需先avcodec_parameters_to_context填充参数,再avcodec_open2初始化;解码帧为YUV格式,渲染前须用sws_scale转RGB;音视频同步需结合系统时钟动态校准,避免仅依赖PTS。

ffmpeg 解码器初始化必须调用 avcodec_open2,不能只靠 avcodec_find_decoder
很多人卡在“找不到解码器”或“avcodec_receive_frame 返回 AVERROR(EAGAIN)”,根本原因是只查了编码器但没真正打开它。查到 AVCodec 指针只是第一步,必须用 avcodec_open2 绑定上下文并完成内部初始化。
-
avcodec_find_decoder只返回解码器描述,不分配资源 -
avcodec_alloc_context3创建空的AVCodecContext,但字段全为 0 或 NULL - 必须用
avcodec_parameters_to_context把流参数(如宽高、codec_id)复制进去,再调avcodec_open2 - 若返回负值,用
av_strerror打印具体错误,常见是Invalid argument(参数未填全)或Unknown error(缺少硬件加速支持)
渲染前要手动做色彩空间转换:sws_getContext + sws_scale
ffmpeg 解码出的帧(AVFrame)默认是 AV_PIX_FMT_YUV420P 等 YUV 格式,而 OpenGL / SDL2 / Direct3D 基本只接受 RGB。跳过转换直接送显,画面会全绿、偏色或崩溃。
- 不要硬编码目标格式,用
SDL_PIXELFORMAT_RGB24或AV_PIX_FMT_RGB24都行,但需与渲染后端对齐 -
sws_getContext要传入源/目标宽高——注意:不是原始视频分辨率,而是解码帧的width/height(可能被 codec 对齐为 16 的倍数) - 转换后记得用
av_frame_alloc+av_frame_get_buffer为 RGB 帧分配内存,否则sws_scale写入会越界 - 转换是性能热点,应复用
SwsContext,不要每帧重建
音视频同步不能只依赖 PTS,得用 av_gettime_relative 做时钟校准
单纯按解码帧的 pts 值 sleep 渲染,会导致音画不同步、卡顿或加速播放。PTS 是容器时间戳,受封装误差、B帧顺序、DTS/PTS 不一致影响,必须结合系统时钟动态调整。
- 维护一个主时钟(通常以音频时钟为基准),用
av_gettime_relative()获取毫秒级单调递增时间 - 视频线程计算当前帧应显示的时间点:
video_clock + frame_delay,再与主时钟比对,决定 sleep、丢帧或加速 - 丢帧逻辑必须在
avcodec_receive_frame后立即判断,不能等渲染完再丢——否则已解码未渲染帧积压,延迟飙升 - 避免用
std::this_thread::sleep_for精确等待,优先用事件循环(如 SDL_Delay)或条件变量唤醒
Windows 下链接 ffmpeg 库容易缺符号:确认是否启用了 __STDC_CONSTANT_MACROS
在 MSVC 编译时,如果出现类似 undefined reference to 'ff_codec_bmp_tags' 或大量 AV_CODEC_ID_* 未定义,大概率是预处理器宏缺失。ffmpeg 头文件中部分常量依赖该宏展开。
立即学习“C++免费学习笔记(深入)”;
- 在所有包含
libavcodec/avcodec.h之前,必须定义:#define __STDC_CONSTANT_MACROS
- CMake 中添加:
add_definitions(-D__STDC_CONSTANT_MACROS)
- MinGW 用户还需检查是否链接了
avutil、avcodec、avformat、swscale、swresample全套,漏一个就会报奇怪的 undefined symbol - 调试时用
dumpbin /exports(MSVC)或nm -D(MinGW)验证 DLL 是否导出了所需符号











