1 播放器技术分享:架构设计

搞音视频开发好些年,分享过许多博客文章,比如:前几年发布的《 Tips》系列,《 音频开发》系列,《直播疑难杂症排查》系列等等 。最近想把多年来开发和优化播放器的经验也分享出来,同时也考虑把自己业余时间开发的基于的播放器内核开源出来,希望能帮助到音视频领域的初学者 。第一期文章要推出的内容主要涉及到播放器比较核心的几个技术点,大概的目录如下:
1. 播放器技术分享(1): 架构设计2. 播放器技术分享(2):缓冲区管理3. 播放器技术分享(3):音画同步4. 播放器技术分享(4):首开时间5. 播放器技术分享(5):延时优化
本篇是系列文章的第一篇,主要聊一聊播放器的架构设计 。
1 概述
首先,我们了解一下播放器的定义是什么 ?
“播放器,是指能播放以数字信号形式存储的视频或音频文件的软件,也指具有播放视频或音频文件功能的电子器件产品 。”—— 《百度百科》
我的解读如下:“播放器,是指能读取、解析、渲染存储在本地或者服务器上的音视频文件的软件,或者电子产品 。”
归纳起来,它主要有如下 3 个方面的功能特性:
读取(IO):“获取” 内容 -> 从 “本地” or “服务器” 上获取解析():“理解” 内容 -> 参考 “格式&协议” 来 “理解” 内容渲染():“展示” 内容 -> 通过扬声器/屏幕来 “展示” 内容
把这 3 个方面的功能串起来,就构成了整个播放器的数据流,如图所示:
IO:负责数据的读取 。从数据源读取数据有多种标准协议,比如常见的有:File,HTTP(s),RTMP,RTSP 等
& :负责数据的解析 。音视频数据的封装格式,都有着各种业界标准,只需要参考这些行业标准文档,即可解析各种封装格式,比如常见的格式:mp4,flv,m3u8,avi 等
:其实也属于数据解析的一种,只不过更多的是负责对压缩的音视频数据进行解码,拿到原始的 YUV 和 PCM 数据,常见的视频压缩格式如:H.264、MPEG4、VP8/VP9,音频压缩格式如 G.711、AAC、Speex 等
:负责视频数据的绘制和渲染,是一个平台相关的特性,不同的平台有不同的渲染 API 和方法,比如: 的 DDraw/,的 /,跨平台的如: 和 ALSA 等
下面我们逐一剖析一下播放器整个数据流的每一个模块的输入和输出,并一起设计一下每一个模块的接口 API 。
2 模块设计
2.1 IO 模块
IO 模块的输入:数据源的地址(URL),这个 URL 可以是一个本地的文件路径,也可以是一个网络的流地址 。
IO 模块的输出:二进制的数据,即通过 IO 协议读取的音视频二进制数据 。
视频数据源的 URL 示例如下:
file:///c:/WINDOWS/clock.avirtmp://live.hkstv.hk.lxdns.com/live/hkshttp://www.w3school.com.cn/i/movie.mp4http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8
综上,播放器 IO 模块的接口设计如下所示:

1  播放器技术分享:架构设计

文章插图
Open/Close 方法主要是用于打开/关闭视频流,播放器内核可以通过 URL 的头()知道需要采用哪一种 IO 协议来拉流(如:FILE/RTMP/HTTP),然后通过继承本接口的子类去完成实际的协议解析和数据读取 。
IO 模块读取数据,则定义了 2 个方法,Read 方法用于顺序读取数据,用于从指定的偏移的位置读取数据,后者主要用于文件或者视频点播,为播放器提供 Seek 能力 。
对于网络流,可能出现断线的情况,因此独立出一个接口,用于提供重连的能力 。
2.2 解析模块
从 IO 模块读到的音视频二进制数据,其实都是用如 mp4、flv、avi 等格式封装起来的,如果想分离出音频包和视频包,则需要通过一个&模块进行解析 。