ffmpeg源码简析(⼀)结构总览
未毕业通过校招进⼊了某做机的公司从事camera⽅⾯的⼯作。⽐较悲剧的是做了将近⼀年的Camera之后,正要研究Camera上下层打通任督⼆脉的时候,公司架构调整加上OS版本⼤变动,被调到了多媒体组(不过也好,我对编码解码这块也是向往已久)。以前⼤学的时候⽤vitamio写过⼀个播放器项⽬,后来ijkplayer 出来之后也实践过⼀两个⼩项⽬,它们都是基于ffmpeg的框架。
悬窗播放视频,让你聊天看视频两不误(上) :
悬窗播放视频,让你聊天看视频两不误(下) :
学习ffmpeg也有段时间了,ffmpeg这个框架实在是⼤,源码看着注释着忘着,很是凌乱。好记性不如烂笔头,古⼈诚不欺我啊。以后就整理下学习过的东西,分享出来,⽅便了⾃⼰也帮助了他⼈,真是快乐。
感谢雷神,中国⾳视频技术领域⽆私的拓荒者传承者,您的博⽂治学态度令我敬佩,⽂章使我受益良多
本系列前办部分应该是对雷神和其他资料的总结。
如果对ffmpeg不了解的客官进这⾥
ffmpeg必知道的知识点 :
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正在慢慢朝着“名称更加规范”的⽅向发展。
这⾥也更了⼀篇
⼤家务必对着新的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编码处理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()

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。