ffmpeg 各库的介绍、解码流程、常用结构体

世界杯开幕式视频

6.1 AVFormatContext

解封装上下文,是存储音视频封装格式中包含信息的结构体。

char filename[1024] // 保存打开的文件名,一般用在 rtsp、rtmp 断开重连

unsigned int nb_streams // 音视频流的个数

AVStream **streams // 存储视频流、音频流、字幕流信息

int64_t duration // 媒体文件的总时长,单位是把 1 秒切成 AV_TIME_BASE(1000000)份,即单位。为 us,注意不一定每个视频都能获取到 duration

int64_t bit_rate // 比特率(单位bps,转换为kbps需要除以1000)

6.2 AVStream

AVStream 是存储每一个音频/视频流信息的结构体。其重要的变量如下所示:

int index // 标识该视频/音频流

AVCodecContext *codec // 解码器,4.0 版本后已弃用

AVRational time_base // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)

int64_t duration // 该视频/音频流时长,单位为 ms

AVRational avg_frame_rate // 帧率(注:对视频来说,这个挺重要的)

AVPacket attached_pic // 附带的图片。比如说一些 MP3,AAC 音频文件附带的专辑封面

AVCodecParameters *codecpar // 音视频参数,新增用来替换AVCodecContext *codec

6.3 AVCodecContext

AVCodecContext 是一个描述编解码器上下文的结构体,包含了众多编解码器需要的参数信息。下面挑一些关键的变量来看看(这里只考虑解码)。

enum AVMediaType codec_type // 编解码器的类型(视频,音频...)

struct AVCodec *codec // 采用的解码器AVCodec(H.264,MPEG2...)

enum AVCodecID codec_id // 标示特定的编解码器(H.264,MPEG2...)

int format // 视频像素格式/音频采样数据格式

int width, height // 表示视频的宽和高

int bit_rate // 平均比特率

int channels // 声道数(音频)

uint64_t channel_layout // 声道格式

int sample_rate // 采样率(音频)

AVRational time_base; // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)

uint8_t *extradata; int extradata_size; // 针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

6.4 AVCodec

AVCodec 是存储编码器信息的结构体。其重要的变量如下所示:

const char *name; // 编解码器的名字的简称

const char *long_name; // 编解码器名字的全称

enum AVMediaType type; // 指明了类型,是视频,音频,还是字幕

enum AVCodecID id; // ID,不重复

const AVRational *supported_framerates; // 支持的帧率(仅视频)

const enum AVPixelFormat *pix_fmts; // 支持的像素格式(仅视频),如RGB24、YUV420P等。

const int *supported_samplerates; // 支持的采样率(仅音频)

const enum AVSampleFormat *sample_fmts; // 支持的采样格式(仅音频)

const uint64_t *channel_layouts; // 支持的声道数(仅音频)

int priv_data_size; // 私有数据的大小

6.5 AVCodecParameters

新增用来替换AVCodecContext *codec。因为 AVCodecContext 结构体包含的参数太多,AVCodecParameters 将编码器的参数从 AVCodecContext 分离出来,AVCodecParameters 结构体中部分重要的参数如下:

enum AVMediaType codec_type // 编解码器的类型(视频,音频...)

enum AVCodecID codec_id // 标示特定的编解码器(H.264,MPEG2...)

int format // 视频像素格式/音频采样数据格式

int width, height // 表示视频的宽和高

int bit_rate // 平均比特率

int channels // 声道数(音频)

uint64_t channel_layout // 声道格式

int sample_rate // 采样率(音频)

AVRational time_base; // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)

uint8_t *extradata; int extradata_size; // 针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

可以看到两者的成员基本一致。

avcodec_decode_video2():解码一帧视频数据

sws_scale():转换视频数据格式

av_frame_free():释放xx上下文申请的内存

avcodec_close():关闭解码器

6.6 AVPacket

AVPacket 是存储压缩编码数据相关信息的结构体。其重要的变量如下所示:

uint8_t *data; // 压缩编码的数据。

/* 例如对于H.264来说。1个AVPacket的data通常对应一个NAL。

注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流。因此在使用FFMPEG进行音视频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到音视频的码流文件。*/

int size; // data的大小

int64_t pts; // 显示时间戳

int64_t dts; // 解码时间戳

int stream_index; // 标识该AVPacket所属的视频/音频流。

6.7 AVFrame

AVFrame 结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是 YUV,RGB,对音频来说是 PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP 表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用 FFmpeg 进行码流分析的时候,AVFrame 是一个很重要的结构体。

下面看几个主要变量的作用(在这里考虑解码的情况):

uint8_t *data[AV_NUM_DATA_POINTERS]; // 解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)

int linesize[AV_NUM_DATA_POINTERS]; // data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

int width, height; // 视频帧宽和高(1920x1080,1280x720...)

int nb_samples; // 音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个

int format; // 解码后原始数据类型(YUV420,YUV422,RGB24...)

int key_frame; // 是否是关键帧

enum AVPictureType pict_type; // 帧类型(I,B,P...)

AVRational sample_aspect_ratio; // 宽高比(16:9,4:3...)

int64_t pts; // 显示时间戳

int coded_picture_number; // 编码帧序号

int display_picture_number; // 显示帧序