FFmpeg写入输出文件

本文介绍如何使用 FFmpeg 的 API 函数 avio_open2 打开一个输出文件,然后用 av_interleaved_write_frame 来把编码器输出的 AVPacket 保存进去文件。 本文的代码下载地址:百度网盘,提取码:hpdo

与 输出 相关的 API 函数如下: 1,avformat_alloc_output_context2,申请一个输出文件上下文,这个函数会生成 AVFormatContext 2,avformat_new_stream,往容器增加一个输出流,可以是音频流,或者视频流,或者一些其他的数据流。 3,avcodec_parameters_from_context,把 AVCodecContext 里面的 编解码参数 复制到输出流的 AVCodecParameters 。 4,avio_open2,正式打开输出文件。 5,avformat_write_header,往输出文件写入头信息。 6,av_interleaved_write_frame,把 AVPacket 写入输出文件。


要特别注意 avformat_write_header 这个函数,必须是容器里面的所有流都初始化完成了,才能调 avformat_write_header。 本文的代码只有一个视频流,所以比较简单,但是如果同时有音频流跟视频流,那就必须等音频也解码出 AVFrame,音频流初始化完成才能 执行 avformat_write_header。 输出流的初始化主要通过两个函数完成,avformat_new_stream 跟 avcodec_parameters_from_context。 avformat_new_stream 函数是创建一个输出流,而 avcodec_parameters_from_context 是把编码器参数复制到流里面,因为容器里面也需要保存一下编码器的参数跟信息。 我经常会把 容器,输出文件上下文 混着来说,其实是一个意思,MP4 是一个 容器,可以容纳音频流视频流。

​上面的代码,是申请一个输出文件的上下文,然后添加了一个流,这里还没确定这个流是音频流还是视频流,是通过后面的 avcodec_parameters_from_context 来确定的,会设置 codec_type 。 还需要特别注意这行代码,: st->time_base = fmt_ctx->streams[0]->time_base; 我把输入流的时间基 复制 给了输出流。

继续看代码,如下:

​上面代码的调用流程如下:

avcodec_parameters_from_context ➔ avio_open2 ➔ avformat_write_header

【CSDN后台扣1,免费分享】资料包括《Andoird音视频开发必备手册+音视频学习视频+学习文档资料包+大厂面试真题+2022最新学习路线图》等

继续看代码,如下:

​编码器输出 AVPakcet 之后,在写入文件之前,还需要做2个操作。 1,设置 AVPakcet 的 stream_index,因为编码器输出的 AVPakcet 还没有跟输出流绑定,容器里面可以有多个流,所以写入的时候需要根据 stream_index 来确认这个包应该写进去哪个流里面。 2,转换 AVPakcet 的 PTS ,DTS,duration 的时间基,因为本文输入流跟输出流的时间基一样,所以不转换也可以。 但是如果输入流的时间基跟输出流的时间基不一样就需要转换,因为当时设置编码器的时间基是以输入流为准的,所以编码器输出的 AVPacket 的时间基也是输入流的时间基。所以需要把 AVPacket 的时间基转成 输出流的时间基。

最后调 av_interleaved_write_frame 写入文件即可。

猜你喜欢

转载自blog.csdn.net/yinshipin007/article/details/125791772