FFMPEG音视频解码
1.播放多媒体文件步骤
通常情况下,我们下载的视频文件如MP4,MKV、FLV等都属于封装格式,就是把音视频数据按照相应的规范,打包成一个文本文件。我们可以使用MediaInfo这个工具查看媒体文件的相关信息。
所以当我们播放一个媒体文件时,通常需要经过以下几个步骤
①解封装(Demuxing):就是将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV格式的数据,经过解封装操作后,输出H.264编码的视频码流和AAC编码的音频码流。
②解码(Decode):就是将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含AAC,MP3等,视频的压缩编码标准则包含H.264,MPEG2等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如YUV、RGB等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如PCM数据。
③音视频同步:就是根据解封装模块处理过程中获取到的参数信息,同步解码出来的音频和视频数据,并将音视频频数据送至系统的显卡和声卡播放出来(Render)。
2.FFMPEG音视频解码
通过上面对媒体文件播放步骤的了解,我们在解码多媒体文件的时候需要经过两个步骤,即解封装(Demuxing)和解码(Decode)。下面就来看一下FFMPEG解码媒体文件的时候是怎样做这两个步骤的。
FFmpeg解码函数简介:
▫ av_register_all():注册所有组件。
▫ avformat_open_input():打开输入视频文件。
▫ avformat_find_stream_info():获取视频文件信息。
▫ avcodec_find_decoder():查找解码器。
▫ avcodec_open2():打开解码器。
▫ av_read_frame():从输入文件读取一帧压缩数据。
▫ avcodec_decode_video2():解码一帧压缩数据。
▫ avcodec_close():关闭解码器。
▫ avformat_close_input():关闭输入视频文件。
注:AVStream[0]一般为视频流,AVStream[0]一般为音频流
3.FFmpeg中的数据结构
-
AVFormatContext 封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装 格式相关信息。
- iformat:输入视频的AVInputFormat
- nb_streams :输入视频的AVStream 个数
- streams :输入视频的AVStream []数组
- duration :输入视频的时长(以微秒为单位)
- bit_rate :输入视频的码率
-
AVInputFormat 每种封装格式(例如FLV, MKV, MP4, AVI)对应一个该结构体。
- name:封装格式名称
- long_name:封装格式的长名称
- extensions:封装格式的扩展名
- id:封装格式ID
- 一些封装格式处理的接口函数
- FFmpeg数据结构分析
-
AVStream 视频文件中每个视频(音频)流对应一个该结构体。
- id:序号
- codec:该流对应的AVCodecContext
- time_base:该流的时基
- r_frame_rate:该流的帧率
-
AVCodecContext编码器上下文结构体,保存了视频(音频)编解码相关信息。
- codec:编解码器的AVCodec
- width, height:图像的宽高(只针对视频)
- pix_fmt:像素格式(只针对视频)
- sample_rate:采样率(只针对音频)
- channels:声道数(只针对音频)
- sample_fmt:采样格式(只针对音频)
-
AVCodec 每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体。
- name:编解码器名称
- long_name:编解码器长名称
- type:编解码器类型
- id:编解码器ID
- 一些编解码的接口函数
-
AVPacket 存储一帧压缩编码数据。
- pts:显示时间戳
- dts :解码时间戳
- data :压缩编码数据
- size :压缩编码数据大小
- stream_index :所属的AVStream
-
AVFrame存储一帧解码后像素(采样)数据。
- data:解码后的图像像素数据(音频采样数据)。
- linesize:对视频来说是图像中一行像素的大小;对音频来说是音频帧的大小。
- width, height:图像的宽高(只针对视频)。
- key_frame:是否为关键帧(只针对视频) 。
- pict_type:帧类型(只针对视频) 。例如I,P,B。