Chromium源码--视频播放流程分析(WebMediaPlayerImpl解析)

转载请注明出处:http://www.cnblogs.com/fangkm/p/3797278.html

承接上一篇文章。媒体播放,需要指定一个源文件,html5用URL格式来指定视频源文件地址,可以是http链接,也可以使本地源文件(不能直接指定,需要借助blob二进制类型)。播放网络文件比播放本地文件多了个下载流程, 所以下面直接分析网络文件的播放流程,本地文件的播放流程也就清楚了。首先分析下网络视频资源的加载流程,相关结构图如下:

WebMediaPlayerImpl类有一成员BufferedDataSource来负责管理URL网络资源的加载逻辑。

BufferedDataSource资源加载逻辑主要由BufferedResourceLoader完成,

BufferedResourceLoader类维护一个WebURLLoader接口的派生类AssociatedURLLoader对象, AssociatedURLLoader类也并没有真正的和webkit_glue层的WebURLLoaderImpl一样实现WebURLLoader的接口,而是通过DocumentThreadableLoader类最终依赖WebURLLoaderImpl的实现给主进程发送URL请求WebURLLoaderImpl(WebURLLoaderImpl的流程请参见:http://www.cnblogs.com/fangkm/p/3784660.html)。

AssociatedURLLoader对象与frame对象关联,当调用WebFrame的stopLoading方法时,该请求也会取消。

BufferedResourceLoader内部维护一个可增长的内存缓冲区来保存请求到的视频数据。

分析到这里我始终没发现暂停缓冲机制,也没有找到缓冲到磁盘文件的地方,如果视频文件过大的话,全部积放在内存,资源消耗过大肯定造成极不好的程序体验。当然我这里的Chromium代码也有点老了,可能新版的已经改进了。

视频数据已经准备完毕,接下来的工作就是解析音视频数据了。在分析这部分之前首先简单普及下音视频的相关概念。一般的视频文件都有视频流和音频流两部分组成,不同的视频格式音视频的封装格式肯定不一样。将音频流和视频流合成文件的过程称为muxer,反之从媒体文件中分离音频流和视频流的过程称为demuxer. 播放视频文件就需要从文件流中分离出音频流和视频流,分别对其进行解码,解码后的视频帧可以直接渲染,音频帧可以送到音频输出设备的缓冲区进行播放,当然,视频渲染和音频播放的时间戳一定要控制同步。

WebMediaPlayerImpl中有关demuxer的逻辑结构如下:

WebMediaPlayerImpl根据资源的不同创建不同的demuxer对象。

如果视频源是通过JavaScript传送过来的二进制数据,则创建ChunkDemuxer对象来分离音频流和视频流;

如果视频源是通过URL指定的网络源,则创建FFmpegDemuxer对象,依赖BufferedDataSource对象来访问通过网络加载的媒体流数据。

ChunkDemuxer和FFmpegDemuxer的具体实现暂且不表,先只需要了解他们的作用是将媒体流分离出视频流和音频流。先分析整个播放流程。

WebMediaPlayerImpl类有一个Pipeline对象来负责视频的播放流程, Pipeline本身就是流水线的意思,正适合视频播放的一系列流程。Pipeline内部利用状态机维护播放中的各种阶段的逻辑。Pipeline调用AudioRendererImpl初始化时,会调用Demuxer的GetStream方法,指定获取音频流数据传入AudioRendererImpl对象;同理调用VideoRendererBase初始化时,会取到视频流数据来传入。音视频流的读取操作由DemuxerStream接口来抽象。

下面分析一下VideoRendererBase的流程, VideoRendererBase这名字起的有点奇怪,带个Render单词,确做的是视频流的解码逻辑,真正的绘制操作还是抛到WebMediaPlayerImpl类,具体请参见WebMediaPlayerImpl的paint方法。先看结构:

VideoRendererBase维护了一个VideoDecoder列表,内部主要逻辑都交给VideoFrameStream处理, VideoFrameStream的主要功能包括解码器的选取、从DemuxerStream读取视频流进行解码,解码后的结果为一视频帧结构VideoFrame,这个结构封装的是YUV数据,可以直接或转换成RGB进行渲染操作。

简单介绍下这里的视频解码器创建和选取逻辑:

在WebMediaPlayerImpl类中就已经创建好视频解码器列表,按顺序依次为:

1. 如果gpu支持视频解码,则创建GpuVideoDecoder对象

2. 创建VpxVideoDecoder对象

3. 创建FFmpegVideoDecoder对象

创建好解码器列表后传入VideoRendererBase对象,最终由VideoFrameStream来管理选取逻辑:

1. 如果视频配置信息里有加密选项,则创建DecryptingVideoDecoder做为解码器

2. 如果无加密选项,则从传入的解码器列表中选择第一个做为解码器。

3. 如果调用选择的解码器的Initialize无效(解码器不支持该格式的解码),则按顺序选择列表中的下一个解码器。

AudioRendererImpl的结构与VideoRendererBase类似,在音频渲染方面比视频渲染稍微复杂一点,需要将音频数据输出到声卡设备进行播放。相关结构图:

到此为止,网页播放器整个流程差不多已经清晰了,当然还有很多细节没扒,比如说Media Source流对应的分离器ChunkDemuxer的实现、FFmpegDemuxer内部怎么对ffmpeg的使用、各种解码器的实现等,没有开发经验,要研究透这些细节真的很耗时,有兴趣的童鞋可以自己研究。

Chromium源码--视频播放流程分析(WebMediaPlayerImpl解析)

时间: 2024-10-04 20:29:00

Chromium源码--视频播放流程分析(WebMediaPlayerImpl解析)的相关文章

Chromium源码--视频播放流程分析(拨开云雾)

转载请注明出处: http://www.cnblogs.com/fangkm/p/3791964.html 在PC浏览器中播放视频,大部分视频网站都是采用flash播放器,这多亏了Adobe Flash Player庞大的装机量.但Flash Player对于浏览器来说就是一个插件,插件内部下载flv流.解析flv视频格式.播放视频等流程与浏览器都没有太大关系.浏览器新标准HTML5中增加了视频支持,如:<video src="movie.ogg"> </video&

通过官方API结合源码,如何分析程序流程

通过官方API结合源码,如何分析程序流程通过官方API找到我们关注的API的某个方法,然后把整个流程执行起来,然后在idea中,把我们关注的方法打上断点,然后通过Step Out,从内向外一层一层分析调用链,然后找出我们要分析的流程的逆流程,然后再通过在每层上面打上断点,进而整理出代码的执行流程:其实,对于面向对象语言,由于有了多态特性,代码中有了很复杂的抽象结构,一个接口或者抽象类有很多的实现,有时通过代码可以看出来,有些不太好看,程序执行时到底调用了哪个实现类的方法,这就需要按照上面动态的方

从源码的角度分析ViewGruop的事件分发

从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子VewGroup,是Android中所有布局的父类或间接父类,像LinearLayout.RelativeLayout等都是继承自ViewGroup的.但ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能.ViewGroup继承结构示意图如

qt creator源码全方面分析(3-8)

目录 项目文件工作流程 多层目录模式 依赖解析模式 包含,链接和输出 包含 链接 输出 构建目录架构 项目文件工作流程 我们在前面已经讨论了所有的项目文件, qtcreator.pro qtcreator.pri qtcreatordata.pri qtcreatorlibrary.pri qtcreatorplugin.pri qtcreatortool.pri 下面我们再从头到尾来捋一遍. 多层目录模式 我们可以看到,所有的*.pro文件中,除了最底层的子项目.都采用TEMPLATE和SUB

[原创]chromium源码阅读-进程间通信IPC.消息的接收与应答

chromium源码阅读-进程间通信IPC.消息的接收与应答 chromium源码阅读-进程间通信IPC.消息的接收与应答 介绍 chromium进程间通信在win32下是通过命名管道的方式实现的,最后的数据都是以二进制流的方式进行传播,pickle类就是负责消息的封包与解包功能,它将各种数据已二进制的形式写到内存缓冲区中,在实际通信的时候通过与其他一些辅助类与模板函数来实现具体数据结构的写与读.本文主要介绍的是chromium在将消息发送与接收过程中,以及chromium如何通过各种消息宏与C

chromium浏览器开发系列第三篇:chromium源码目录结构

上两篇介绍了下载源码和编译源码,这次主要介绍chromium的源码目录结构,我也是通过源码和官网结合来跟大家说,如果有说的不准确的,欢迎交流. 另外,官网的不一定准确,他们其实也很懒,所以最主要还是靠自己.官网只能作为一个参考. Chromium结构相对两年前变化很大.目录结构依然很清晰,主要有三个部分(不包括其他的库):浏览器,渲染器,webkit.浏览器是主要的进程,代表所有的UI和I / O.渲染通常是每个tab页的子过程,是由浏览器驱动.Webkit做布局和渲染. 简单介绍解决方案文件:

从源码上,分析AsyncTask的实现

Android开发者们应该都知道AsyncTask这个类,它是系统提供的一个异步任务类,可以方便的让我们实现异步操作.在本篇文章中,我将带大家进入源码,简单分析一下AsyncTask的实现. 首先,贴上AsyncTask类的源码: package android.os; import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; impo

chromium浏览器开发系列第三篇:chromium源码目录说明

上两篇介绍了下载源码和编译源码,这次主要介绍chromium的源码目录结构,我也是通过源码和官网结合来跟大家说,如果有说的不准确的,欢迎交流. 另外,官网的不一定准确,他们其实也很懒,所以最主要还是靠自己.官网只能作为一个参考. Chromium结构相对两年前变化很大.目录结构依然很清晰,主要有三个部分(不包括其他的库):浏览器,渲染器,webkit.浏览器是主要的进程,代表所有的UI和I / O.渲染通常是每个tab页的子过程,是由浏览器驱动.Webkit做布局和渲染. 简单介绍解决方案文件:

qt creator源码全方面分析(3-6)

目录 qtcreatorplugin.pri 使用实例 上半部 下半部 结果 qtcreatorplugin.pri 上一节我们介绍了qtcreatorlibrary.pri,现在我们介绍qtcreatorplugin.pri,其实插件的本质也是动态库,所以qtcreatorplugin.pri实现的内容和功能与qtcreatorlibrary.pri差不多. 使用实例 和上一节一样,为了分析这个文件,我们也再找个使用该pri的例子,源目录\src\plugins\cppeditor\cpped