使用ffvhuff编码写入AVI时FFmpeg像素格式异常问题
问题原因与修复方案
核心原因
- AVI容器格式限制:旧版AVI规范对YUV格式原生支持有限,FFmpeg的AVI muxer会默认将YUV像素格式映射为BGR系列写入文件头,导致ffprobe解析时误判格式,实际编码数据仍是YUV422P,进而播放乱码。
- 参数同步错误:手动设置
stream->codecpar后,未将编码器上下文参数同步到流的codecpar中,导致流参数与实际编码参数不一致。 - 时间戳处理不当:手动覆盖packet的pts/dts会破坏编码器生成的正确时间戳,可能引发播放时序或格式解析错误。
修复步骤
1. 修正参数同步逻辑
删除所有手动设置m_stream->codecpar的代码,在打开编码器后调用avcodec_parameters_from_context同步参数:
// 打开编码器后添加以下代码 ret = avcodec_parameters_from_context(m_stream->codecpar, m_codec_context); if (ret < 0) { throw std::runtime_error("failed to copy codec parameters to stream"); }
2. 强制AVI muxer使用YUV422P格式
在调用avformat_write_header前,添加格式参数指定像素格式:
AVDictionary* format_options = nullptr; av_dict_set(&format_options, "pix_fmt", "yuv422p", 0); ret = avformat_write_header(m_format_context, &format_options); if (ret < 0) { throw std::runtime_error("header writing error"); } av_dict_free(&format_options);
3. 修正时间戳处理
移除手动设置packet->pts和packet->dts的代码,仅保留时间戳转换:
// 删除以下两行 // m_packet->pts = m_frameNumber; // m_packet->dts = m_frameNumber; av_packet_rescale_ts(m_packet, m_codec_context->time_base, m_stream->time_base);
4. 统一尺寸变量
确保帧的width和height与编码器设置的变量一致,避免尺寸不匹配。
验证修复
修复后重新生成文件,ffprobe检测应显示正确的像素格式:
ffprobe ./test0.avi # 预期输出: # Stream #0:0: Video: ffvhuff (FFVH / 0x48564646), yuv422p, 1280x720, ...
内容的提问来源于stack exchange,提问作者folibis
相关产品推荐
相关产品推荐

