前一篇笔记空下了貌似非常重要的FFplay的数据结构,不得不说FFplay的数据结构的实现确实可圈可点,作者也用了很长一段篇幅对它进行了介绍。但笔者认为,结构终归只是结构,无论是动态静态排他还是包含,只有结合了应用才能真正体会原作者的用意,所以没敢班门弄斧。这篇笔记主要是为了总结记录原书后续的函数部分。
Ps:原书中主要是大量的代码注释(所有代码都贴上了),介绍比较详细,但篇幅太长。本篇总结主要是摘取原属文字部分内容,并将注释稍作总结,可作索引看待。
3 libavutil
common.h
ffplay 使用的工具类数据类型定义,宏定义和两个简单的内联函数
1)定义一些全局变量
2)定义大小写敏感的字符串比较函数
3)定义限幅函数
定义和内联过程对系统编译器存在区分,所以还需要在宏定义处给出系统的区分。bswap.h
进行大小端转换。
大端模式:数据的高字节保存在内存的低地址中,低字节保存在内存的高地址中。
小端模式:数据的高字节保存在内存的高地址中,低字节保存在内存的低地址中。
常见的 CPU 中,Intel X86 序列及其兼容序列只能是小端,Motorola 68 序列只能是大端,ARM 大端小端都 支持,但默认小端。rational.h
用两整数精确表示分数。常规的可以用一个 float 或 double 型数来表示分数,但不是精确表示,在需要相 对比较精确计算的时候,为避免非精确表示带来的计算误差,采用两整数来精确表示。
实现时用原始的分子和分母的组合来表示分数,用 float或double 表示分数值。mathematics.h
这里暂时只需要一个缩放函数:a*b/cavutil.h
FFplay 基础工具库使用的一些常数和宏的定义。
4 libavformat
avformat.h
定义识别文件格式和媒体类型库使用的宏、数据结构和函数,通常这些宏、数据结构和函数在此模块内相对全局有效。
1)定义必要的宏变量
2)定义音频数据包,每一个包是一个完整的帧
3)定义链表格式,存储数据包(帧)
4)定义媒体流
5)定义文件特征结构及容器匹配实例(只保留了avi)
6)变量的初始化和善后处理的实现allformat.h
简单的注册/初始化函数,把相应的协议,文件格式,解码器等用相应的链表串起来便于查找。
1)ffplay 把CPU 当做一个广义的 DSP。有些计算可以用 CPU 自带的加速指令来优化,ffplay 把这类函数独立出来放到 dsputil.h 和dsputil.c 文件中,用函数指针的方法映射到各个 CPU 具体的加速优化实现函数,在这个文件中首先初始化了这些函数指针
2)把所有的解码器用链表的方式都串连起来,链表头指针是 first_avcodec
3)把所有的输入文件格式用链表的方式都串连起来,链表头指针是 first_iformat
4)把所有的输入协议用链表的方式都串连起来,比如 tcp/udp/file 等,链表头指针是 first_protocolcutils.c
ffplay 文件格式分析模块使用的两个工具类函数,都是对字符串的操作。
1)字符串搜索,在字符串中搜索给定字符串指示的头,去掉头后用指针返回
2)字符串拷贝file.c
ffplay 把 file 当做类似于 rtsp,rtp,tcp 等协议的一种协议,用 file:前缀标示 file 协议。 URLContext 结构抽象统一表示这些广义上的协议,对外提供统一的抽象接口。 各具体的广义协议实现文件实现 URLContext 接口。此文件实现了 file 广义协议的 URLContext 接口。avio
文件读写模块定义的数据结构和函数。
1)函数必要的宏定义(.h)
2)广义的文件协议
3)加入缓存,改善广义输入文件的IO性能
4)协调抽象file,pipe为URLProtocol(.c)aviobuf.c
有缓存的广义文件 ByteIOContext 相关的文件操作utils_format.c
识别文件格式和媒体格式部分使用的一些工具类函数。
1)文件容器格式识别
2)索引建立及使用
3)时钟avicodec.c
AVI 文件解析的相关函数。
1)格式参数
2)标签匹配
3)文件校验
4)AVI索引表建立及加载
5)音视频数据区分
6)交织存放媒体流判断
7)AVI文件打开关闭初始化注册...
5 libavcodec
avcodec.h
定义编解码器库使用的宏、数据结构和函数,通常这些宏、数据结构和函数在此模块内相对全局有效。
1)版本信息
2)Code ID
3)Codec 类型
4)解码过程的缓存格式(YUV/RGB)
5)其他的结构、接口
6)编解码库使用的函数声明allcodec.c
简单的注册/初始化函数,把编解码器用相应的链表串起来便于查找识别。dsputil
dsp 优化限幅运算,查找表及其初始化。utils_codec.c
编解码库使用的帮助和工具函数。
1)内存动态分配、重分配、释放
2)视频图像长宽效验
3)上下文处理(参数初始化、内存分配)
4)向音视频解码跳转imgconvert
定义并实现图像颜色空间转换,定义、分析、转换、拷贝...msrle.c
实现微软行程长度压缩算法解码器。turespeech
实现truespeed 音频解码器。
封装格式avi、视频编码压缩算法msrle、音频格式压缩算法turespeech仅是原作者为实现功能挑选的较为简单普遍的算法,可以通过其他资料详细了解,但本质上与FFplay实现不是绝对关系。
6 FFplay余下部分
berrno.h
错误码定义,用于描述错误类型。来源于 \VC98\Include\ERRNO.H,做了删减。ffplay.c
主控文件,初始化运行环境,把各个数据结构和功能函数有机组织起来,协调数据流和功能函数,响应用户 操作,启动并控制程序运行。
1)屏蔽SDL中的main
2)导入SDL库
3)必要数据结构定义
4)获取时间(当前, 1/1000000 秒为单位)
5)多线程执行及阻塞控制
6)搭建SDL的运行环境(配置各项参数)
7)读取数据包链表,打开编解码器
8)调用之前各个文件的各个函数完成音视频的同步播放*External Dependcies
SDL的各项依赖文件(不属于FFplay)
整本书到此为止就已经结束,即使总结后也颇像一本指导性或者概念性的普及。没有一行行细看具体实现的代码,因为阅读后感觉这本书提供的主要是一种整体观感。大致知道了如果面对一个完整的FFplay播放器如果需要按自己的需求进行更改应该寻找哪些部件。接下来的计划就是从这本书出发,尝试修改出一个我们自己的FFplay吧。