ExoPlayer结构分析

来源:互联网 发布:多媒体网络中控系统 编辑:程序博客网 时间:2024/06/03 20:35

最近要做音乐播放器,经过一周的调研,最终决定使用google的ExoPlayer,对ExoPlayer的架构、流程做个分析,梳理一下调用逻辑。

先做个笔记,等项目做完了写一个多媒体播放的大型攻略。

媒体资源的获取

MediaSource类代表媒体资源,new出这个类的实例需要uri,DataSourceFactory和ExtractorsFactory。

uri是资源的路径;

DataSourceFactory的作用是创建对应的DataSource实例,从uri资源中读取文件流;

ExtractorsFactory的作用是创建Extractors实例,Extractor翻译过来就是“抽出器”,在这里就是把媒体文件从二进制的媒体流中抽出来。这个开源项目已经实现了mp3/mp4/flv等常见格式的抽出器,如果需要解析不支持的格式,还可以自己实现,或使用ffmpeg扩展。

MediaSource是一个接口,也没声明几个方法,其中最主要的一个就是createPeriod()方法,用来创建一个MediaPeriod对象,这个对象就是真正做资源处理的。

对媒体资源的使用

ExoPlayer类代表这“播放器”的概念,就是接收媒体资源,把媒体资源解析成声音和画面呈现出来。ExoPlayer是一个接口,它有很多实现,我们以SimpleExoPlayer为例子。new出一个SimpleExoPlayer实例需要RenderersFactory、TrackSelector和LoadControl三个参数。

RenderersFactory是用来生产Renderer数组的。Renderer翻译过来就是渲染器的意思,就是把音频、视频、文字源显示在画面上或输出成声音。音视频文件的录制都是二进制的,只是时间间隔非常短,所以输出时让人感觉是连续的,而Renderer的工作就是“快速、连续地输出这些文件”。为什么是数组呢,因为一个媒体文件可能有音频、视频等多个轨道,一个Render对应一个轨道;

TrackSelector翻译过来就是轨道选择器的意思,它在这里的作用就是轨道选择,它有个方法selectTracks(),返回TrackSelection数组,TrackSelection就是对轨道进行解析的。一个媒体文件会包含多个轨道,音轨、视频轨、文字轨等,所以需要多个TrackSelection;

LoadControl主要是解析的一些进度控制、参数控制等,主要是记录一些position;

整个播放逻辑流程

上面分析了资源的获取和资源的使用,现在就分析下ExoPlayer是如何启动整个流程、控制整个流程的。

ExoPlayer通过prepare(MediaSource m,xxx,xxx)方法启动,方法里面调用ExoPlayerImpl的prepare方法,里面又调用ExoPlayerImplInternal的prepare方法,这个类就是真正的逻辑实现。

ExoPlayerImplInternal里面会通过Handler发送MSG_PREPARE消息,然后最终会调用prepareInternal方法。这个方法里面进行一些初始化操作后,就会发送MSG_DO_SOME_WORK消息,最终调用doSomeWork方法。

doSomeWork方法里首先会调用updatePeriods方法更新Period。播放由三个MediaPeriodHolder实例控制,MediaPeriodHolder是什么呢?它持有MediaPeriod、MediaSource、Render等所有实例,这里面就是真正完成所有逻辑的。这三个实例分别是loadingPeriodHolder、readingPeriodHolder和playingPeriodHolder。

updatePeriods方法会调用setPlayingPeriodHolder方法,设置将要播放的MediaPeriod。setPlayingPeriodHolder方法最后会调用enableRenderers方法,该方法会遍历render数组(创建ExoPlayer实例时传入的参数),调用render的start方法,这里面会执行一些状态的重置、通知。

然后再回到doSomeWork方法,接着往下走,会调用render的render方法,这个方法就是真正的解析、渲染了。