ffmpeg源码简析(一)结构总览

原创 2017年04月24日 14:24:00

未毕业通过校招进入了某做机的公司从事camera方面的工作。比较悲剧的是做了将近一年的Camera之后,正要研究Camera上下层打通任督二脉的时候,公司架构调整加上OS版本大变动,被调到了多媒体组(不过也好,我对编码解码这块也是向往已久)。以前大学的时候用vitamio写过一个播放器项目,后来ijkplayer 出来之后也实践过一两个小项目,它们都是基于ffmpeg的框架。
悬窗播放视频,让你聊天看视频两不误(上) :http://blog.csdn.net/king1425/article/details/59527229
悬窗播放视频,让你聊天看视频两不误(下) :http://blog.csdn.net/king1425/article/details/59538663

学习ffmpeg也有段时间了,ffmpeg这个框架实在是大,源码看着注释着忘着,很是凌乱。好记性不如烂笔头,古人诚不欺我啊。以后就整理下学习过的东西,分享出来,方便了自己也帮助了他人,真是快乐。
感谢雷神,中国音视频技术领域无私的拓荒者传承者,您的博文治学态度令我敬佩,文章使我受益良多
本系列前办部分应该是对雷神和其他资料的总结。
如果对ffmpeg不了解的客官进这里
ffmpeg必知道的知识点http://blog.csdn.net/king1425/article/details/70348374

ffmpeg API变更

雷神记录获取媒体信息使用的函数是av_find_stream_info()。但是较新的版本中,av_find_stream_info()函数已经无法使用了,取而代之的是avformat_find_stream_info()。再比如,早一些的程序中,打开解码器可以使用avcodec_open(),但是新版本的程序中必须使用avcodec_open2()。而早期版本的FFmpeg中打开媒体的函数av_open_input_file()也已经被avformat_open_input()所取代。可以看出一些与libavformat相关的av_***()都变更为了avformat_***(),这一趋势也说明FFmpeg的API正在慢慢朝着“名称更加规范”的方向发展。
这里也更了一篇 ffmpeg API变更 2009-03-01—— 2017-05-09变更
大家务必对着新的API学习

ffmpeg源码结构图

编码
引自雷神,图片较大建议保存为本地文件,然后再查看

函数背景色
函数在图中以方框的形式表现出来。不同的背景色标志了该函数不同的作用:

粉红色背景函数:FFmpeg的API函数。
白色背景的函数:FFmpeg的内部函数。
黄色背景的函数:URLProtocol结构体中的函数,包含了读写各种协议的功能。
绿色背景的函数:AVOutputFormat结构体中的函数,包含了读写各种封装格式的功能。
蓝色背景的函数:AVCodec结构体中的函数,包含了编解码的功能。

区域
整个关系图可以分为以下几个区域:

左边区域——架构函数区域:这些函数并不针对某一特定的视频格式。
右上方黄色区域——协议处理函数区域:不同的协议(RTP,RTMP,FILE)会调用不同的协议处理函数。
右边中间绿色区域——封装格式处理函数区域:不同的封装格式(MKV,FLV,MPEG2TS,AVI)会调用不同的封装格式处理函数。
右边下方蓝色区域——编解码函数区域:不同的编码标准(HEVC,H.264,MPEG2)会调用不同的编解码函数。

箭头线
为了把调用关系表示的更明显,图中的箭头线也使用了不同的颜色:

红色的箭头线:标志了编码的流程。
其他颜色的箭头线:标志了函数之间的调用关系。其中:

    调用URLProtocol结构体中的函数用黄色箭头线标识;

    调用AVOutputFormat结构体中的函数用绿色箭头线标识;

    调用AVCodec结构体中的函数用蓝色箭头线标识。

函数所在的文件
每个函数标识了它所在的文件路径。

左边区域(架构函数) 后续详细分析~~~

右上区域(URLProtocol协议处理函数)
URLProtocol结构体包含如下协议处理函数指针:

url_open():打开
url_read():读取
url_write():写入
url_seek():调整进度
url_close():关闭

【例子】不同的协议对应着上述接口有不同的实现函数,举几个例子:
File协议(即文件)对应的URLProtocol结构体ff_file_protocol:
url_open() -> file_open() -> open()
url_read() -> file_read() -> read()
url_write() -> file_write() -> write()
url_seek() -> file_seek() -> lseek()

url_close() -> file_close() -> close()

RTMP协议(libRTMP)对应的URLProtocol结构体ff_librtmp_protocol:
url_open() -> rtmp_open() -> RTMP_Init(), RTMP_SetupURL(), RTMP_Connect(), RTMP_ConnectStream()
url_read() -> rtmp_read() -> RTMP_Read()
url_write() -> rtmp_write() -> RTMP_Write()
url_seek() -> rtmp_read_seek() -> RTMP_SendSeek()

url_close() -> rtmp_close() -> RTMP_Close()
UDP协议对应的URLProtocol结构体ff_udp_protocol:
url_open() -> udp_open()
url_read() -> udp_read()
url_write() -> udp_write()
url_seek() -> udp_close()
url_close() -> udp_close()

右中区域(AVOutputFormat封装格式处理函数)
AVOutputFormat包含如下封装格式处理函数指针:

write_header():写文件头
write_packet():写一帧数据
write_trailer():写文件尾

【例子】不同的封装格式对应着上述接口有不同的实现函数,举几个例子:
FLV封装格式对应的AVOutputFormat结构体ff_flv_muxer:
write_header() -> flv_write_header()
write_packet() –> flv_write_packet()

write_trailer() -> flv_write_trailer()
MKV封装格式对应的AVOutputFormat结构体ff_matroska_muxer:
write_header() -> mkv_write_header()
write_packet() –> mkv_write_flush_packet()

write_trailer() -> mkv_write_trailer()
MPEG2TS封装格式对应的AVOutputFormat结构体ff_mpegts_muxer:
write_header() -> mpegts_write_header()
write_packet() –> mpegts_write_packet()

write_trailer() -> mpegts_write_end()
AVI封装格式对应的AVOutputFormat结构体ff_avi_muxer:
write_header() -> avi_write_header()
write_packet() –> avi_write_packet()
write_trailer() -> avi_write_trailer()

右下区域(AVCodec编解码函数)
AVCodec包含如下编解码函数指针:

init():初始化
encode2():编码一帧数据
close():关闭

【例子】不同的编解码器对应着上述接口有不同的实现函数,举几个例子:
HEVC编码器对应的AVCodec结构体ff_libx265_encoder:
init() -> libx265_encode_init() -> x265_param_alloc(), x265_param_default_preset(), x265_encoder_open()
encode2() -> libx265_encode_frame() -> x265_encoder_encode()

close() -> libx265_encode_close() -> x265_param_free(), x265_encoder_close()
H.264编码器对应的AVCodec结构体ff_libx264_encoder:
init() -> X264_init() -> x264_param_default(), x264_encoder_open(), x264_encoder_headers()
encode2() -> X264_frame() -> x264_encoder_encode()

close() -> X264_close() -> x264_encoder_close()
VP8编码器(libVPX)对应的AVCodec结构体ff_libvpx_vp8_encoder:
init() -> vpx_init() -> vpx_codec_enc_config_default()
encode2() -> vp8_encode() -> vpx_codec_enc_init(), vpx_codec_encode()

close() -> vp8_free() -> vpx_codec_destroy()
MPEG2编码器对应的AVCodec结构体ff_mpeg2video_encoder:
init() -> encode_init()
encode2() -> ff_mpv_encode_picture()
close() -> ff_mpv_encode_end()

解码

右上区域(URLProtocol协议处理函数)
URLProtocol结构体包含如下协议处理函数指针:

url_open():打开
url_read():读取
url_write():写入
url_seek():调整进度
url_close():关闭

【例子】不同的协议对应着上述接口有不同的实现函数,举几个例子:
File协议(即文件)对应的URLProtocol结构体ff_file_protocol:

url_open() -> file_open() -> open()
url_read() -> file_read() -> read()
url_write() -> file_write() -> write()
url_seek() -> file_seek() -> lseek()
url_close() -> file_close() -> close()

RTMP协议(libRTMP)对应的URLProtocol结构体ff_librtmp_protocol:

url_open() -> rtmp_open() -> RTMP_Init(), RTMP_SetupURL(), RTMP_Connect(), RTMP_ConnectStream()
url_read() -> rtmp_read() -> RTMP_Read()
url_write() -> rtmp_write() -> RTMP_Write()
url_seek() -> rtmp_read_seek() -> RTMP_SendSeek()
url_close() -> rtmp_close() -> RTMP_Close()

UDP协议对应的URLProtocol结构体ff_udp_protocol:

url_open() -> udp_open()
url_read() -> udp_read()
url_write() -> udp_write()
url_seek() -> udp_close()

url_close() -> udp_close()

右中区域(AVInputFormat封装格式处理函数)
AVInputFormat包含如下封装格式处理函数指针:

read_probe():检查格式
read_header():读取文件头
read_packet():读取一帧数据
read_seek():调整进度
read_close():关闭

【例子】不同的封装格式对应着上述接口有不同的实现函数,举几个例子:
FLV封装格式对应的AVInputFormat结构体ff_flv_demuxer:

read_probe() -> flv_probe() –> probe()
read_header() -> flv_read_header() -> create_stream() -> avformat_new_stream()
read_packet() -> flv_read_packet()
read_seek() -> flv_read_seek()
read_close() -> flv_read_close()

MKV封装格式对应的AVInputFormat结构体ff_matroska_demuxer:

read_probe() -> matroska_probe()
read_header() -> matroska_read_header()
read_packet() -> matroska_read_packet()
read_seek() -> matroska_read_seek()
read_close() -> matroska_read_close()

MPEG2TS封装格式对应的AVInputFormat结构体ff_mpegts_demuxer:

read_probe() -> mpegts_probe()
read_header() -> mpegts_read_header()
read_packet() -> mpegts_read_packet() 
read_close() -> mpegts_read_close()

AVI封装格式对应的AVInputFormat结构体ff_avi_demuxer:

read_probe() -> avi_probe()
read_header() -> avi_read_header()
read_packet() -> avi_read_packet()
read_seek() -> avi_read_seek()
read_close() -> avi_read_close()

右下区域(AVCodec编解码函数)
AVCodec包含如下编解码函数指针:

init():初始化
decode():解码一帧数据
close():关闭

【例子】不同的编解码器对应着上述接口有不同的实现函数,举几个例子:
HEVC解码对应的AVCodec结构体ff_hevc_decoder:

init() -> hevc_decode_init()
decode() -> hevc_decode_frame() -> decode_nal_units()
close() -> hevc_decode_free()

H.264解码对应的AVCodec结构体ff_h264_decoder:

init() -> ff_h264_decode_init()
decode() -> h264_decode_frame() -> decode_nal_units()
close() -> h264_decode_end()

VP8解码(libVPX)对应的AVCodec结构体ff_libvpx_vp8_decoder:

init() -> vpx_init() -> vpx_codec_dec_init()
decode() -> vp8_decode() -> vpx_codec_decode(), vpx_codec_get_frame()
close() -> vp8_free() -> vpx_codec_destroy()

MPEG2解码对应的AVCodec结构体ff_mpeg2video_decoder:

init() -> mpeg_decode_init()
decode() -> mpeg_decode_frame()

close() -> mpeg_decode_end()
版权声明:本文为博主原创文章,未经博主允许不得转载。

[总结]FFMPEG视音频编解码零基础学习方法

在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者。在和大家探讨的过程中,我忽然发现了一个问题:在“...
  • leixiaohua1020
  • leixiaohua1020
  • 2013年11月16日 00:04
  • 464933

Windows下FFmpeg快速入门

本系列文章导航Windows下FFmpeg快速入门ffmpeg参数解释mencoder和ffmpeg参数详解(Java处理视频)Java 生成视频缩略图(ffmpeg)使用ffmpeg进行视频文件转换...
  • hemingwang0902
  • hemingwang0902
  • 2009年07月26日 22:43
  • 110506

FFmpeg发送流媒体的命令(UDP,RTP,RTMP)

这两天研究了FFmpeg发送流媒体的命令,在此简单记录一下以作备忘。1.      UDP1.1. 发送H.264裸流至组播地址(注:组播地址指的范围是224.0.0.0—239.255.255.25...
  • leixiaohua1020
  • leixiaohua1020
  • 2014年08月01日 00:10
  • 115442

FFmpeg 基本用法

FFmpeg FFmpeg 基本用法 本课要解决的问题 1.FFmpeg的转码流程是什么? 2.常见的视频格式包含哪些内容吗? 3.如何把这些内容从视频文件中抽取出来? ...
  • doublefi123
  • doublefi123
  • 2014年04月22日 19:51
  • 66447

ffmpeg 各个版本下载地址

下载地址:http://ffmpeg.org/releases/ 下载   wget http://ffmpeg.org/releases/ffmpeg-3.3.tar.gz 解压 tar -x...
  • lcalqf
  • lcalqf
  • 2017年04月28日 14:47
  • 5338

FFmpeg总结(十二)用ffmpeg与nginx实现直播多路流并发播放

下载 nginx 和 nginx-rtmp源码: http://nginx.org/download/nginx-1.5.10.tar.gz https://github.com/arut/ngi...
  • hejjunlin
  • hejjunlin
  • 2017年05月07日 16:21
  • 5684

在Windows上安装FFmpeg程序

原文地址:http://helloway.blog.51cto.com/7666282/1642247 FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它提...
  • yy3097
  • yy3097
  • 2016年04月05日 13:13
  • 25303

【整理】Libav、FFmpeg、mplayer、VLC开源项目、FFDshow

ffmpeg    FFmpeg(现改名为Libav) FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流...
  • conowen
  • conowen
  • 2012年02月13日 18:28
  • 40687

java封装FFmpeg命令,支持原生ffmpeg全部命令,实现FFmpeg多进程处理与多线程输出控制(开启、关闭、查询),rtsp/rtmp推流、拉流

前言: 之前已经对FFmpeg命令进行了封装http://blog.csdn.net/eguid_1/article/details/51787646,但是当时没有考虑到扩展性,所以总体设计不是太好,...
  • eguid_1
  • eguid_1
  • 2016年10月30日 00:01
  • 6287
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ffmpeg源码简析(一)结构总览
举报原因:
原因补充:

(最多只允许输入30个字)