目录(?)[+]

=====================================================

FFmpeg的库函数源代码分析文章列表:

【架构图】

FFmpeg源代码结构图 - 解码

FFmpeg源代码结构图 - 编码

【通用】

FFmpeg 源代码简单分析:av_register_all()

FFmpeg 源代码简单分析:avcodec_register_all()

FFmpeg 源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

FFmpeg 源代码简单分析:avio_open2()

FFmpeg 源代码简单分析:av_find_decoder()和av_find_encoder()

FFmpeg 源代码简单分析:avcodec_open2()

FFmpeg 源代码简单分析:avcodec_close()

【解码】

图解FFMPEG打开媒体的函数avformat_open_input

FFmpeg 源代码简单分析:avformat_open_input()

FFmpeg 源代码简单分析:avformat_find_stream_info()

FFmpeg 源代码简单分析:av_read_frame()

FFmpeg 源代码简单分析:avcodec_decode_video2()

FFmpeg 源代码简单分析:avformat_close_input()

【编码】

FFmpeg 源代码简单分析:avformat_alloc_output_context2()

FFmpeg 源代码简单分析:avformat_write_header()

FFmpeg 源代码简单分析:avcodec_encode_video()

FFmpeg 源代码简单分析:av_write_frame()

FFmpeg 源代码简单分析:av_write_trailer()

【其它】

FFmpeg源代码简单分析:日志输出系统(av_log()等)

FFmpeg源代码简单分析:结构体成员管理系统-AVClass

FFmpeg源代码简单分析:结构体成员管理系统-AVOption

FFmpeg源代码简单分析:libswscale的sws_getContext()

FFmpeg源代码简单分析:libswscale的sws_scale()

FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

FFmpeg源代码简单分析:libavdevice的gdigrab

【脚本】

FFmpeg源代码简单分析:makefile

FFmpeg源代码简单分析:configure

【H.264】

FFmpeg的H.264解码器源代码简单分析:概述

=====================================================

近期研究了一下FFmpeg的内部的源代码。之前对于FFmpeg的研究主要在它的应用层面上,因此制作的很多示例程序都是调用的FFmpeg的API。但是一直感觉这样对FFmpeg的理解还是比较浅,所以打算剖析一下它的源代码,理一下它内部结构的“脉络”。但是有一个很难办的问题:FFmpeg自带的三个工程:ffplay, ffmpeg, ffprobe的代码量非常的大,其中包含了成百上千的API;而这些API背后又包含了大量的FFmpeg内部函数。如此一来,几乎是不可能理清他们之间的关系的。经过一番思考之后,打算选择FFmpeg编码和解码过程中的最核心的API进行分析。在编码或者解码的过程中,核心的API数量不多,一共大约10个左右,这样一来就可以剖析其内部的源代码了。

  • FFmpeg解码过程核心的API可以参考:《最简单的基于FFmpeg+SDL的视频播放器》
  • 编码过程核心的API可以参考:《最简单的基于FFmpeg的视频编码器》

FFmpeg源代码结构图-解码

首先呈现分析出来的FFmpeg源代码结构图。这张图的尺寸非常的大,尺寸大约有4000x4000,有点像一张地图(因此最好选择“查看更清晰的图片”之后,右键保存图片到本机之后再查看)。它表明了FFmpeg在解码一个视频的时候的函数调用流程。为了保证结构清晰,其中仅列出了最关键的函数,剔除了其它不是特别重要的函数。

单击查看更清晰的图片

下面解释一下图中关键标记的含义。

函数背景色

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

  • 粉红色背景函数:FFmpeg的API函数。
  • 白色背景的函数:FFmpeg的内部函数。
  • 黄色背景的函数:URLProtocol结构体中的函数,包含处理协议(Protocol)的功能。
  • 绿色背景的函数:AVInputFormat结构体中的函数,包含处理封装格式(Format)的功能。
  • 蓝色背景的函数:AVCodec结构体中的函数,包含了编解码器(Codec)的功能。

PS:URLProtocol,AVInputFormat,AVCodec在FFmpeg开始运行并且注册完组件之后,都会分别被连接成一个个的链表。因此实际上是有很多的URLProtocol,AVInputFormat,AVCodec的。图中画出了解码一个输入协议是“文件”(其实就是打开一个文件。“文件”也被当做是一种广义的协议),封装格式为FLV,视频编码格式是H.264的数据的函数调用关系。

区域

整个架构图可以分为以下几个区域:

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

箭头线

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

黑色箭头线:标志了函数之间的调用关系。

红色的箭头线:标志了解码的流程。

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

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

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

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

函数所在的文件

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

此外,还有一点需要注意的是,一些API函数内部也调用了另一些API函数。也就是说,API函数并不一定全部都调用FFmpeg的内部函数,他也有可能调用其他的API函数。例如从图中可以看出来,avformat_close_input()调用了avformat_free_context()和avio_close()。这些在内部代码中被调用的API函数也标记为粉红色。

函数调用关系

下面简单列出几个区域中函数之间的调用关系(函数之间的调用关系使用缩进的方式表现出来)。详细的函数分析可以参考相关的《FFmpeg源代码分析》系列文章。

左边区域(FFmpeg架构函数)

1.  av_register_all()【函数简单分析】

1)  avcodec_register_all()

(a) REGISTER_HWACCEL()

(b) REGISTER_ENCODER()

(c) REGISTER_DECODER()

(d) REGISTER_PARSER()

(e) REGISTER_BSF()

2)  REGISTER_MUXER()

3)  REGISTER_DEMUXER()

4)  REGISTER_PROTOCOL()

2.  avformat_alloc_context()【函数简单分析】

1) av_malloc(sizeof(AVFormatContext))

2) avformat_get_context_defaults()

(a) av_opt_set_defaults()

3.  avformat_open_input()【函数简单分析】

1) init_input()

(a) avio_open2()【函数简单分析】

a) ffurl_open()

i. ffurl_alloc()

url_find_protocol()

url_alloc_for_protocol()

ii. ffurl_connect()

URLProtocol->url_open()

b) ffio_fdopen()

i. av_malloc(buffer_size)

ii. avio_alloc_context()

av_mallocz(sizeof(AVIOContext))

ffio_init_context()

(b) av_probe_input_buffer2()

a) avio_read()

i.  AVInputFormat->read_packet()

b) av_probe_input_format2()

c) av_probe_input_format3()

i. av_iformat_next()

ii. av_match_name()

iii. av_match_ext()

iv. AVInputFormat->read_probe()

2) AVInputFormat->read_header()

4. avformat_find_stream_info()【函数简单分析】

1) find_decoder()

(a) avcodec_find_decoder()

2) avcodec_open2()

3) read_frame_internal()

4) try_decode_frame()

(a) avcodec_decode_video2()

5) avcodec_close()

6) estimate_timings()

(a)  estimate_timings_from_pts()

(b)  estimate_timings_from_bit_rate()

(c)  update_stream_timings()

5. avcodec_find_decoder()【函数简单分析】

1) find_encdec()

6. avcodec_open2()【函数简单分析】

1) AVCodec->init()

7. av_read_frame()【函数简单分析】

1) read_from_packet_buffer()

2) read_frame_internal()

(a) ff_read_packet()

a) AVInputFormat->read_packet()

(b) parse_packet()

a) av_parser_parse2()

8. avcodec_decode_video2()【函数简单分析】

1) av_packet_split_side_data()

2) AVCodec-> decode()

3) av_frame_set_pkt_pos()

4) av_frame_set_best_effort_timestamp()

9. avcodec_close()【函数简单分析】

1) AVCodec->close()

10. avformat_close_input()【函数简单分析】

1) AVInputFormat->read_close()

2) avformat_free_context()

(a) ff_free_stream()

3) avio_close()

(a) avio_flush()

a) flush_buffer()

(b) ffurl_close()

a) ffurl_closep()

URLProtocol->url_close()

右上区域(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()

雷霄骅 (Lei Xiaohua)
leixiaohua1020@126.com
http://blog.csdn.net/leixiaohua1020

ffmpeg framework相关推荐

  1. FFmpeg简介及在vc2010下编译步骤

    FFmpeg是一个开源的多媒体库,最新版本是2.4.3,它的License是LGPL或GPL.FFmpeg可以用来记录.转换数字音频.视频,并能将其转换为流的开源计算机程序.它包括了音/视频编码库li ...

  2. iOS 开发音视频流[1]---FFmpeg

    原文地址: http://www.jianshu.com/p/4811f11aed27 本文是自己实际开发过程中遇到的问题. 1.准备 1.1.Xcode `XCode`提供了Mac平台开发环境必须的 ...

  3. VideoTool之FFmpeg:FFmpeg的简介、安装、使用方法之详细攻略

    VideoTool之FFmpeg:FFmpeg的简介.安装.使用方法之详细攻略 目录 FFmpeg的简介 FFmpeg的安装 1.Windows下安装 第一步,下载软件 第二步,解压文件 第三步,将文 ...

  4. ubuntu 交叉编译 armv7_32 ffmpeg x264(已完成)

    文章目录 1.交叉编译x264(x264要先编译,因为到时编译ffmpeg时要用到x264的头文件和库) 2.接着我们编译ffmpeg FFmpeg和X264的交叉编译环境 arm linux交叉编译 ...

  5. Linux-安装FFmpeg

    FFmpeg官网:http://www.ffmpeg.org 官网介绍 FFmpeg is the leading multimedia framework, able to decode, enco ...

  6. 最简单的基于FFmpeg的AVDevice例子(屏幕录制)

    ===================================================== 最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDe ...

  7. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

    ===================================================== 最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDe ...

  8. FFmpeg 硬件加速方案概览 (下)

    被称为"多媒体技术领域的瑞士军刀",FFmpeg拥有广泛的应用基础.不过,当(实时)处理海量视频时,需要借助各种方法提升效率.比如,短视频平台Revvel将视频转码服务迁移到AWS ...

  9. FFmpeg 硬件加速方案概览 (上)

    被称为"多媒体技术领域的瑞士军刀",FFmpeg拥有广泛的应用基础.不过,当(实时)处理海量视频时,需要借助各种方法提升效率.比如,短视频平台Revvel将视频转码服务迁移到AWS ...

最新文章

  1. awk 和sed的用法介绍
  2. java2期末考试试题及答案_《JAVA语言程序设计》期末考试试题及答案(2)
  3. px4原生源码学习二--实时操作系统篇
  4. php如何反向排列数组,php中的sort()如何排列目录结构数组?
  5. struct device结构体(2.6.23)
  6. 关于TTThumbsViewController加载更多
  7. 如何查看有没有django及版本
  8. memento模式_Java中的Memento设计模式
  9. 智慧城市的宠儿 大数据为城市建设添彩
  10. H5页面和微信小程序的优劣对比
  11. 生物医学信号处理之数字信号处理基础
  12. flex java blazeds_Flex BlazeDS Java 使用
  13. Spring5全面详解
  14. 【练习】新浪邮箱注册测试用例
  15. 面试:你印象最深的BUG,举个例子
  16. 6月13日云栖精选夜读:数梦工场完成A轮7.5亿融资 三个维度构建“新型互联网”
  17. wlop2020全奖励包_真的要来?网友发现新更新包拥有“夜魇暗潮2020”信息
  18. 四川大学计算机学院硕士毕业要求,四川大学计算机学院(软件学院)2020年非全日制硕士研究生接受调剂生的通知...
  19. 交通预见未来(1):循环神经网络之LSTM,不只有七秒钟的记忆
  20. 非齐次Poisson过程的期望与方差

热门文章

  1. Oracle创建和查询索引
  2. 跨境运营培训做亚马逊广告要注意什么
  3. 动态IP与静态IP的区别
  4. 无人机深度学习虚拟现实平台构建
  5. Kali linux安装步骤,史上最详细的步骤,傻瓜式教学
  6. 本科毕业、硕士毕业和博士毕业PPT制作和预答辩、答辩注意事项
  7. [PATCH] ARM: add dtbImage.dt and dtbuImage.dt rules
  8. 干货 | 这些年,我用的绘图工具大合集
  9. 其次线性方程组,行列式为0,一定有非0解.
  10. 运维 —— 1521端口不通