ffmpeg解码器初始化必须调用avcodec_open2,仅avcodec_find_decoder无法完成资源分配;需先avcodec_parameters_to_context填充参数,再avcodec_open2初始化;解码帧为YUV格式,渲染前须用sws_scale转RGB;音视频同步需结合系统时钟动态校准,避免仅依赖PTS。
avcodec_open2,不能只靠 avcodec_find_decoder
很多人卡在“找不到解码器”或“avcodec_receive_frame 返回 AVERROR(EAGAIN)”,根本原因是只查了编码器但没真正打开它。查到 AVCodec 指针只是第一步,必须用 avcodec_open2 绑定上下文并完成内部初始化。
avcodec_find_decoder 只返回解码器描述,不分配资源avcodec_alloc_context3 创建空的 AVCodecContext,但字段全为 0 或 NULLavcodec_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,不要每帧重建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)或条件变量唤醒__STDC_CONSTANT_MACROS
在 MSVC 编译时,如果出现类似 undefined reference to 'ff_codec_bmp_tags' 或大量 AV_CODEC_ID_* 未定义,大概率是预处理器宏缺失。ffmpeg 头文件中部分常量依赖该宏展开。
libavcodec/avcodec.h 之前,必须定义:#define __STDC_CONSTANT_MACROS
:add_definitions(-D__STDC_CONSTANT_MACROS)
avutil、avcodec、avformat、swscale、swresample 全套,漏一个就会报奇怪的 undefined symboldumpbin /exports(MSVC)或 nm -D(MinGW)验证 DLL 是否导出了所需符号