FFmpeg API(下)
接着上一篇《FFmpeg API(上)》中的示例代码,其中代码很多方法调用并没有详细注释,现在特意注释一下,顺便对着这张图熟悉熟悉FFmpeg处理音视频的基本流程。需要理解的几个重要的结构体 AVFormatContext 、AVCodecContext 、AVPacket 与 AVFrame,这同样也是上篇文章中的示例程序里用的特别多的几个结构体。

FFmpeg主要模块
上面的示例程序基本上演示了 FFmpeg 的一些常用 API,现在就对这些函数进行一个大致解读。
libavformat模块

AVFormatContext 是API层直接接触到的结构体,它会进行格式的封装与解封装,它的数据部分由底层提供,底层使用了 AVIOContext,这个 AVIOContext 实际上就是为普通的I/O增加了一层Buffer缓冲区,再往底层就是URLContext,也就是到达了协议层,协议层的具体实现有很多,包括rtmp、http、hls、file等,这就是libavformat的内部封装了。
libavcodec模块

对于开发者来说,这一层我们能接触到的最顶层的结构体就是 AVCodecContext,该结构体包含的就是与实际的编解码有关的部分。首先,AVCodecContext 是包含在一个 AVStream里面的,即描述了这路流的编码格式是什么,其中存放了具体的编码格式信息,根据Codec的信息可以打开编码器或者解码器,然后利用该编码器或者解码器进行 AVPacket 与 AVFrame 之间的转换(实际上就是解码或者编码的过程),这是 FFmpeg 中最重要的一部分。
函数功能
主要是介绍从文件/文件夹操作之后的一些函数。
av_register_all
在编译FFmpeg的时候,其中开启或者关闭了很多选项,生成 config.mk 与 config.h。config.mk实际上就是makefile文件需要包含进去的子模块,从而编译出正确的库;而config.h是作用在运行阶段,这一阶段将确定需要注册哪些容器以及编解码格式到FFmpeg框架中。所以该函数的内部实现会先调用 avcodec_register_all 来注册所有config.h 里面开放的编解码器,然后会注册所有的Muxer和Demuxer(也就是封装格式),最后注册所有的Protocol(即协议层的东西)。
avformat_open_input
函数 avformat_open_input 会根据所提供的文件路径判断文件的格式,其实就是通过这一步来决定使用的到底是哪一个 Demuxer。举例来说,如果是 flv,那么 Demuxer 就会使用对应的 ff_flv_demuxer,所以对应的关键生命周期的方法 read_header、read_packet、read_seek、read_close 都会使用该 flv的 Demuxer 中函数指针指定的函数。read_header 函数会将 AVStream 结构体构造好,以便后续的步骤继续使用 AVStream 作为输入参数。
