如何使用FFmpeg的libAV库将H264编码数据封装到.mp4容器
基于libAV实现H.264码流封装MP4的实现步骤
你已经完成H.264编码的前提下,只需要额外补充复用器相关逻辑即可输出标准MP4文件,具体实现步骤如下:
1. 初始化复用器上下文
提前注册容器相关组件,创建指定MP4格式的输出上下文:
// 前置组件注册,全局仅需调用一次 av_register_all(); avformat_network_init(); AVFormatContext *fmt_ctx = NULL; // 第四个参数传入你的输出文件路径 int ret = avformat_alloc_output_context2(&fmt_ctx, NULL, "mp4", "output_test.mp4"); if (ret < 0 || !fmt_ctx) { // 自定义错误处理逻辑 }
2. 关联视频流参数
创建输出视频流,参数和你正在用的H.264编码器上下文完全对齐:
AVStream *out_stream = avformat_new_stream(fmt_ctx, NULL); if (!out_stream) { // 自定义错误处理逻辑 } // 直接拷贝编码器的参数到输出流,避免手动配置出错 ret = avcodec_parameters_from_context(out_stream->codecpar, your_h264_encoder_ctx); if (ret < 0) { // 自定义错误处理逻辑 } // 时间基和编码器保持一致,避免后续时间戳换算错误 out_stream->time_base = your_h264_encoder_ctx->time_base;
特别注意:必须给H.264编码器开启全局头参数,否则MP4容器会缺少SPS/PPS信息,播放器无法识别:
your_h264_encoder_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;该参数要在打开编码器之前设置才生效。
3. 打开输出文件写入容器头
// 打开IO句柄 if (!(fmt_ctx->oformat->flags & AVFMT_NOFILE)) { ret = avio_open(&fmt_ctx->pb, "output_test.mp4", AVIO_FLAG_WRITE); if (ret < 0) { // 自定义错误处理逻辑 } } // 写入MP4文件头 ret = avformat_write_header(fmt_ctx, NULL); if (ret < 0) { // 自定义错误处理逻辑 }
4. 循环写入编码后的数据包
每次拿到编码输出的AVPacket后,先做时间基转换再写入容器:
// pkt是你编码得到的H.264数据包 av_packet_rescale_ts(pkt, your_h264_encoder_ctx->time_base, out_stream->time_base); pkt->stream_index = out_stream->index; // 写入容器,libAV会自动处理帧顺序、MP4 box组装 ret = av_interleaved_write_frame(fmt_ctx, pkt); if (ret < 0) { // 自定义错误处理逻辑 } // 用完记得释放packet av_packet_unref(pkt);
5. 收尾释放资源
所有帧写入完成后执行:
// 写入MP4文件尾,补全所有容器元信息 av_write_trailer(fmt_ctx); // 释放IO和上下文资源 if (!(fmt_ctx->oformat->flags & AVFMT_NOFILE)) { avio_close(fmt_ctx->pb); } avformat_free_context(fmt_ctx);
内容的提问来源于stack exchange,提问作者Aravind A
相关产品推荐
相关产品推荐

