av_write_header()调用失败,报Invalid data found错误(错误码-1094995529)
问题描述
编写了一段基础代码尝试将样本帧编码到文件,但还未进入编码步骤就无法写入文件头;若忽略该错误或跳过写头操作,av_write_frame()会触发段错误,推测这两个问题均与I/O相关。
原代码
#include <stdlib.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <stdio.h> int main() { AVFormatContext* formatContext = NULL; avformat_alloc_output_context2(&formatContext, NULL, NULL, "output.mkv"); if (!formatContext) { return 1; } const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!codec) { return 1; } AVStream* stream = avformat_new_stream(formatContext, codec); if (!stream) { return 1; } AVCodecContext* codecContext = avcodec_alloc_context3(codec); if (!codecContext) { return 1; } codecContext->codec_id = AV_CODEC_ID_H264; codecContext->codec_type = AVMEDIA_TYPE_VIDEO; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; codecContext->width = 640; codecContext->height = 480; codecContext->time_base.den = 30; codecContext->time_base.num = 1; codecContext->gop_size = 30; if (avcodec_open2(codecContext, codec, NULL) < 0) { return 1; } avcodec_parameters_from_context(stream->codecpar, codecContext); if (avio_open(&formatContext->pb, "output.mkv", AVIO_FLAG_WRITE) < 0) { return 1; } int h = avformat_write_header(formatContext, NULL); if (h < 0) { printf("failed to write header: %s (%d)\n",av_err2str(h),h); return 1; } avformat_free_context(formatContext); avcodec_free_context(&codecContext); }
程序输出
$ ./a.out [libx264 @ 0x6468176c52c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0x6468176c52c0] profile High, level 3.0, 4:2:0, 8-bit failed to write header: Invalid data found when processing input (-1094995529)
问题分析与修正
核心问题
手动调用avio_open重复初始化了formatContext->pb,而avformat_alloc_output_context2已经根据指定的输出文件名自动创建并初始化了IO上下文,重复打开会导致资源冲突,引发写头失败。
修正步骤
- 移除手动
avio_open调用:删除重复打开文件的代码块,依赖avformat_alloc_output_context2自动创建的IO上下文即可 - 修正
avformat_new_stream参数:新版本FFmpeg中该函数的codec参数已废弃,传入NULL即可 - 同步流的时间基:添加
stream->time_base = codecContext->time_base;,确保流参数与编码上下文一致 - 补全收尾操作:写完头后调用
av_write_trailer完成文件写入,避免文件损坏 - 完善错误打印:添加更清晰的错误信息输出,方便调试
修正后的代码
#include <stdlib.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <stdio.h> int main() { AVFormatContext* formatContext = NULL; int ret = avformat_alloc_output_context2(&formatContext, NULL, NULL, "output.mkv"); if (ret < 0 || !formatContext) { fprintf(stderr, "Failed to allocate output context: %s\n", av_err2str(ret)); return 1; } const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!codec) { fprintf(stderr, "H264 encoder not found\n"); return 1; } AVStream* stream = avformat_new_stream(formatContext, NULL); if (!stream) { fprintf(stderr, "Failed to create new stream\n"); return 1; } AVCodecContext* codecContext = avcodec_alloc_context3(codec); if (!codecContext) { fprintf(stderr, "Failed to allocate codec context\n"); return 1; } codecContext->codec_id = AV_CODEC_ID_H264; codecContext->codec_type = AVMEDIA_TYPE_VIDEO; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; codecContext->width = 640; codecContext->height = 480; codecContext->time_base.den = 30; codecContext->time_base.num = 1; codecContext->gop_size = 30; codecContext->bit_rate = 500000; // 显式设置码率,避免编码器自动计算异常 ret = avcodec_open2(codecContext, codec, NULL); if (ret < 0) { fprintf(stderr, "Failed to open codec: %s\n", av_err2str(ret)); return 1; } ret = avcodec_parameters_from_context(stream->codecpar, codecContext); if (ret < 0) { fprintf(stderr, "Failed to copy codec parameters: %s\n", av_err2str(ret)); return 1; } stream->time_base = codecContext->time_base; ret = avformat_write_header(formatContext, NULL); if (ret < 0) { fprintf(stderr, "Failed to write header: %s (%d)\n", av_err2str(ret), ret); return 1; } // 此处可添加帧编码与写入逻辑 av_write_trailer(formatContext); avformat_free_context(formatContext); avcodec_free_context(&codecContext); return 0; }
说明
修正后的代码解决了IO上下文冲突问题,同时完善了错误处理和资源管理逻辑,能够正常写入文件头。后续只需添加帧编码和写入的逻辑即可完成完整的视频编码流程。
内容的提问来源于stack exchange,提问作者Dan Rafone
相关产品推荐
相关产品推荐

