Chromium 视频架构设计文档介绍
如果你一直在进行浏览器的音视频开发,一定要去阅读官方的设计文档。
Chrome 在支持 HTML5 的 <video>
标签与 <img>
标签(仅要求浏览器知道如何解码少数几种图像格式)不同,<video>
标签要求浏览器知道如何:
- 通过网络获取视频数据
- 解复用(demux)容器格式以找到音频和视频轨道
- 解码各种各样的音频和视频编解码器 (codec)。
此外,时间同步对于播放至关重要:音频和视频必须根据容器格式和用户代理控件(播放、暂停、跳转/快进)指定的时间点相互同步地呈现出来。
Chromium 的媒体播放实现有几个部分
- Pipeline:Chromium 的媒体播放引擎实现,处理音频/视频同步和资源获取
- FFmpeg{解复用器, 音频解码器, 视频解码器}:用于容器解析和软件音视频解码的开源库。
- Blink 的 HTMLMediaElement: 按照 WHATWG 的规定实现 HTML 和 Javascript 绑定;处理渲染用户代理控件
Pipeline
其中 pipeline 则是最为关键的一环,因为 Blink 大家都比较熟悉,FFmpeg 相对而言非常底层,你完全动不了。因此理解 pipeline 的设计,非常重要。
Pipeline 是媒体处理的控制器,它将从一个 URL 播放媒体所需的所有对象连接(或捆绑)在一起。该流水线大致上是模仿 GStreamer 的流水线进行建模的,并遵循一种使用异步调用的“拉取式”(pull-based)模型。该流水线由以下对象组成:
- DataSource(数据源): 从网络或本地存储拉取数据。
- Demuxer(解复用器): 从数据源中提取音频/视频流。
- Audio/Video Decoders(音频/视频解码器): 将压缩的音频/视频流解码成原始采样(raw samples)。
- Audio/Video Renderers(音频/视频渲染器): 将原始的音频/视频采样呈现给用户。
如图所述,该管道完全基于拉取,并依靠声卡来驱动播放。当声卡请求其他数据时, 音频渲染器 会从音频解码器请求解码后的音频数据,音频解码器从解复用器请求编码缓冲区 ,解复用器从数据源读取数据,依此类推。当解码后的音频数据输入声卡时,管道的全局时钟会更新。
视频渲染器 在每个垂直同步时轮询全局时钟,以确定何时从视频解码器请求解码后的帧以及何时将新帧渲染到视频显示器。在没有声卡或音轨的情况下,系统时钟用于驱动视频解码和渲染。
管线使用状态机来处理播放以及诸如暂停、定位和停止等事件。状态转换通常包括通知所有过滤器该事件,并等待完成回调,然后完成转换(图来自 pipeline_impl.h):
// [ *Created ] [ 任何状态 ] // | Start() | Stop() // VV // [ 开始 ] [ 停止 ] // | | // VV // [ 播放 ] <---------. [ 停止 ] // | | Seek() | // | V | // | [ 寻找 ] ----' // | ^ // | Suspend() | // V | // [ 暂停 ] | // | | // V | // [ 暂停 ] | // | Resume() | // V | // [ 恢复 ] ---------'
基于拉取的设计允许通过将播放速率设置为零来实现暂停,从而使音频和视频渲染器停止向上游过滤器请求数据。如果没有任何待处理的请求,整个管道将进入隐式暂停状态。
更为细节的交如图
- WebKit 请求创建一个媒体播放器,在 Chromium 的例子中,它会创建 WebMediaPlayerImpl 和 Pipeline。
- BufferedDataSource通过ResourceLoader请求获取当前视频URL。+ ResourceDispatcher将请求转发给浏览器进程。
- 为该请求创建一个 URLRequest,该 URLRequest 可能已经缓存了 HttpCache 中的数据。当数据可用时,会将其返回给 BufferedDataSource。
- FFmpeg 对音频/视频数据进行解复用和解码。
- 由于沙盒的原因,AudioRendererImpl 无法直接打开音频设备,而是请求浏览器代为打开。
- 浏览器打开新的音频设备,并将音频回调转发给相应的渲染进程。
- 当有新的框架可用时,将无效信息发送到 WebKit。
扩展阅读
- https://html.spec.whatwg.org/#htmlaudioelement
- https://html.spec.whatwg.org/#htmlvideoelement
- https://html.spec.whatwg.org/#htmlmediaelement
- https://www.chromium.org/developers/design-documents/video/#:~:text=user agent controls-,Pipeline,Supports arbitrary audio/video codecs
- https://developer.chrome.com/docs/chromium/videong