3.2 FFmpeg文件结构
Ffmpeg从文件构成上来说主要分为以下5个部分,分别是ffmpeg、libavformat、libavcodec、ffserver、ffplay。ffmpeg被称之为多媒体文件转换工具,在进行交叉编译的时候其中的一些编译选项也是由这个模块来进行控制的。Libavformat包含了所有ffmpeg所支持的音视频编解码器中解析器。Libavcodec包含了相应的一些音视频编解码算法。ffserver支持http、rtsp等多媒体实时广播。ffplay提供了一个基于SDL的简单音视频播放器。至于在linux环境下具体的交叉编译选项,会在“基于ffmpeg制作简单播放器”这一章节详细介绍。
在ffmpeg的libavcodec编解码库中提供了多达2、3百种音频编解码算法,几乎可以包含日常所用的所有音视频格式。如音频mp3提供了各种采样速率以及各种传输速率下的编解码算法。
对于视频格式来说支持:rmvb、mkv、avi、mp4等等各种视频格式。对于图像来说,支持png、jpg、jpeg、bmp、gif。
在前面的分析我们知道,ffmpeg除了支持本地音视频文件解码之外,还可以播放网络流媒体关拨,具体实现过程如图1所示。基本过程可以总结如下:
(1)输入网络流媒体协议
(2)读取所播放多媒体的文件格式
(3)经过转码输出相应文件格式
(4)输出转码之后的网络协议
3.3 FFmpeg数据类型
首先先来认识一下FFmpeg在音频解码中需要使用的数据类型。
AVCodecContext这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息,如下列出了部分比较重要的参数:
AVCodecContext位于avcodec.h文件中。AVCodecContext数据类型非常复杂,打开文件可以看到:
typedef struct AVCodecContext {
constAVClass *av_class;
int log_level_offset;
enum AVMediaType codec_type;
const struct AVCodec *codec;
char codec_name[32];
enum AVCodecID codec_id;
unsigned int codec_tag;
…….
} AVCodecContext;
整个AVCodecContext的内容从1141行一直延伸到2865行。详细描述了包括音频、视频解码器在内的众多参数。因为这一个数据类型就已经相当复杂,因此要想在这一个章节中对FFmpeg中的每种数据结构都介绍清楚几乎是不可能的。因此在本章节中主要对一些重要的音视频编解码文件中使用的参数进行详细介绍。
在AVCodecContext中包含了AVCodec指针以及与编解码相关的一些参数。如其中定义了视频文件的宽、高信息。音频文件的采样频率以及信道数等,同时还包含编解码器的一些相关参数,其中最为重要的要数codec_name、codec_type、codec_id。其中codec_name保存了解码器的名称,codec_type保存了需要进行解码的音视频文件的类型,codec_id保存了需要调用相应解码器的id号。
为了便于大家理解,这里列举一个wav音频文件解码的例子。首先通过open类函数打开wav音频格式,然后读取一系列的文件参数信息。通过wav头文件信息匹配可以找到相应的音视频文件类型codec_type,然后根据相应的解码上下文环境可以获得音视频解码器的id号,利用这些解码的id号就可以实现相应的音视频编解码。
AVStream 结构包含了与数据流相关的一些解码信息。
typedef struct AVStream {
int index;
int id;
AVCodecContext *codec;
AVRational r_frame_rate;
……
int64_t start_time;
} AVStream;
其中较为重要的参数有codec指针,记录了编解码的数据结构信息。time_base数据类型为实数。是数据流的时间基准。 通常,使用av_rescale/av_rescale_q可以实现不同时间基准的转换。在流数据的处理中,流数据周期:duration,流数据基准单位need_parsing等这些参数都是非常重要的。
typedef struct AVPacket {
AVBufferRef*buf;
int64_tpts;
int64_tdts;
uint8_t*data;
int size;
int stream_index;
……
} AVPacket;
当读取到音频文件之后,会将一帧的数据保存在帧结构上下文的AVPackage包中。其中经常使用的参数有:在实现音频与视频同步的同时,会经常使用到pts和dts这两个参数 。利用stream_index可以指示出流媒体的索引,当然还有其它的一些参数,这里就不一一列举。
typedef struct AVFormatContext {
const AVClass *av_class;
struct AVInputFormat *iformat;
structAVOutputFormat *oformat;
void *priv_data;