前言
在学习FFmpeg的时候很有幸读到了雷霄骅博士的博客,非常感谢他留下的宝贵财富,知识是不朽的。
1 FFmpeg库简介
2 总体流程图如下
以上的所有函数都比较重要,需要记住。另外由于FFmpeg版本的改变,其中的不少函数也进行了修改。修改的地方大家可以查看ffmpeg-3.4.1\doc\APIchanges
文件,里面有不同版本函数更改的说明。
2.1 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() 关闭输入视频文件
2.2 FFmpeg解码的数据结构
有的视频含有字幕,还会有AVStrean[3]
读取例如MP4格式的数据,就会得到stream数组,含有音视频和字幕那么数组的长度就是3,这里不确定哪个是音视频,这里就需要
遍历数组判断。
//视频解码,需要找到视频对应的AVStream所在format_ctx->streams的索引位置
//获取音频和视频流的索引位置
int i;
for(i = 0; i < format_ctx->nb_streams;i++){
if(format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
player->video_stream_index = i;
}
else if(format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){
player->audio_stream_index = i;
}
}
然后根据索引的位置获取相应的解码器
得到解码器上下文
AVFormatContext *format_ctx = player->input_format_ctx;
//获取解码器
AVCodecContext *codec_ctx = format_ctx->streams[stream_idx]->codec;
2.3 FFmpeg数据结构简介
- AVFormatContext
封装格式上下文结构体,也是统领全局的结构体,保存了视频文件的封装格式相关信息
初始化AVFormatContext *pFormatCtx = avformat_alloc_context();
- AVInputFormat
每种封装格式(例如FLV,MKV,MP4,AVI)对应一个该结构体
初始化AVInputFormat *av_input_format = pFormatCtx->iformat;
- AVStream
视频文件中每个视频(音频)流对应的一个该结构体pFormatCtx->streams[i]
- AVCodecContext
编码器上下文结构体,保存了视频(音频)编解码相关信息AVCodecContext *pCodecCtx = pFormatCtx->streams[v_stream_idx]->codec;
- AVCodec
每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id)
- AVPacket
AVPacket用于存储一帧一帧的压缩数据(H264)
缓冲区,开辟空间AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));
- AVFrame
存储一帧解码后像素(采样)数据AVFrame *pFrame = av_frame_alloc();
3 总结
基础很重要,前期由于纠结一些细节导致学习效率很低,经过这一段时间的学习、总结发现还是要将基础打牢才能事半功倍。