ExoPlayer 开发指南

ExoPlayer 与 MediaPlayer

与Android内置的MediaPlayer相比,ExoPlayer具有许多优点:

1.支持通过HTTP(DASH)和SmoothStreaming进行动态自适应流,这两种都不受MediaPlayer的支持。还支持许多其他格式。同时它还支持HTTP直播(HLS),MP4,MP3,WebM,M4A,MPEG-TS 和 AAC的格式文件

2.能够自定义和扩展播放器,以适应各种不同需求。 ExoPlayer专门设计了这一点,大部分组件都可以自己替换
便于随着App的升级而升级。因为ExoPlayer是一个包含在你的应用中的库,对于你使用哪个版本有完全的控制权,并且你可以简单的跟随应用的升级而升级;

3.更少的适配性问题。

缺点:

ExoPlayer的音频和视频组件依赖Android的 MediaCodec接口,该接口发布于Android4.1(API 等级16)。因此它不能工作于之前的Android版本。

简述:
ExoPlayer库的核心是ExoPlayer接口,ExoPlayer公开了传统的高级媒体播放器功能,例如缓冲媒体,播放,暂停和seek等功能。在具体实现方面,该开源库对播放的媒体类型、存储方式、位置、渲染方式等进行了最少的实现,旨在让开发者自定义各种特性。ExoPlayer实现不是直接实现加载和呈现媒体,而是将这项工作委托给各种组件。 所有ExoPlayer共同的组件有:

  • MediaSource:定义多媒体数据源,这个类的功能就是从Uri中读取多媒体文件的二进制数据。 MediaSource在播放开始时通过ExoPlayer.prepare注入

  • TrackSelector:轨道提取器,从MediaSource中提取各个轨道的二进制数据,交给Renderer渲染。创建播放器时初注入

  • Renderer:对多媒体中的各个轨道(音轨、视频轨、字幕轨等)数据进行渲染,渲染就是“播放”,把二进制文件渲染成声音、画面。 创建播放器时注入

  • LoadControl:对MediaSource进行控制,比如什么时候开始缓冲、缓冲多少等等。创建播放器时注入

该库为提供了这些组件的默认实现,能够满足大部分需求,如果有特殊需求,可以通过自定义组件来实现。 比如,可以自定义LoadControl来更改播放器的缓冲策略,或自定义Renderer来渲染Android本身不支持的编解码器。

整个库中都存在注入组件的概念,许多子组件都能单独替换成自定义组件,而不会影响整个流程。 例如,默认的MediaSource实现需要通过其构造函数注入一个或多个DataSource工厂, 通过提供自定义Factory,可以从非标准源或不同的网络堆栈加载数据。

入门

实现一个最简单的播放器,需要如下流程:

  1. 添加ExoPlayer库作为依赖
  2. 创建一个SimpleExoPlayer实例
  3. 将播放器连接到UI,用于视频输出和用户输入(也就是放在某个Activity中)
  4. 准备播放器,传入MediaSource作为多媒体源
  5. 播放完成后释放

这些步骤在下面更详细地概述。完整的示例可以参考demo(github地址:https://github.com/google/ExoPlayer)中的PlayerActivity。

添加ExoPlayer作为依赖

第一步是确保项目根目录中的build.gradle文件中包含jcenter仓库:

repositories {
    jcenter()
}

然后在应用app模块的build.gradle文件中添加ExoPlayer库的依赖:

compile 'com.google.android.exoplayer:exoplayer:r2.X.X'

创建播放器

使用ExoPlayerFactory创建一个ExoPlayer实例, 该Factory提供了一系列方法来创建各种定制ExoPlayer实例。 大部分情况下,使用ExoPlayerFactory.newSimpleInstance方法之一即可, 这些方法返回SimpleExoPlayer,它实现了ExoPlayer以添加额外的高级别播放器功能。 下面是创建SimpleExoPlayer的示例:

// step1\. 创建一个默认的TrackSelector
Handler mainHandler = new Handler();

// 创建带宽
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

// 创建轨道选择工厂
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);

// 创建轨道选择器实例
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

//step2\. 创建播放器
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);

使用SimpleExoPlayer的setVideoSurfaceView、setVideoTextureView、setVideoSurfaceHolder和setVideoSurface方法设置播放器的目标SurfaceView、TextureView、SurfaceHolder或Surface。

准备播放器

在ExoPlayer中,每一个多媒体文件均由MediaSource表示,要播放一个多媒体,您必须先创建一个相应的MediaSource实例,然后将此实例传递给ExoPlayer.prepare。 ExoPlayer库为DASH(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供了默认MediaSource实现,这些实现将在本指南的后面更详细地描述。 下面的代码演示如何播放一个mp4文件:

// 测量播放带宽,如果不需要可以传null
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

// 创建加载数据的工厂
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
    Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);

// 创建解析数据的工厂
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

// 传入Uri、加载数据的工厂、解析数据的工厂,就能创建出MediaSource
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
    dataSourceFactory, extractorsFactory, null, null);

// Prepare
player.prepare(videoSource);

播放器准备好后,可以通过各种方法来控制播放。 例如,setPlayWhenReady启动和暂停播放,seekTo方法控制进度。

退出时通过ExoPlayer.release释放播放器,释放硬件资源。

MediaSource

在ExoPlayer中,每个多媒体均由MediaSource表示, ExoPlayer库为DASH(DashMediaSource)、SmoothStreaming(SsMediaSource)、HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供了默认实现。 github上的demo中,可以在PlayerActivity中找到实例化所有四个示例。

除了上述的MediaSource之外,ExoPlayer库还提供了MergingMediaSource、LoopingMediaSource和ConcatenatingMediaSource。 这些MediaSource通过组合实现更复杂的播放功能。 一些常见的用例如下所述。 注意,示例描述的是视频播放,但它们同样适用于仅音频播放,实际上也适用于任何支持的媒体类型的播放。

事件监听

播放期间,可以监听由ExoPlayer生成的事件,指示播放器的整体状态。 这些事件可用作更新用户界面(如播放控件)的触发器。 许多ExoPlayer组件还报告自己的组件特定的底层事件,可以用来监听性能。

上层事件

ExoPlayer通过addListener/removeListener方法添加/删除ExoPlayer.EventListener的实例, 监听者能够监听到播放状态的变化,以及播放失败的事件。

使用SimpleExoPlayer时,可以在播放器上设置其他侦听器。 比如,setVideoListener允许应用程序接收与视频渲染有关的事件,这些事件可能对于调整UI(例如,一个特定宽高比的视频被渲染到surface上了)有用。 可以在SimpleExoPlayer上设置其他侦听器来接收调试信息,例如调用setVideoDebugListener和setAudioDebugListener。

底层事件

除了上层监听外,ExoPlayer库提供的许多单独的组件允许自己的事件监听器。 通常需要将Handler对象传递给这些组件,这些Handler决定侦听器方法将在哪个线程调用,所以在大多数情况下,应该使用主线程的Handler。

向组件发送消息

一些组件允许在播放过程中更改配置。 一般来说,可以通过sendMessages或blockingSendMessages方法将消息通过ExoPlayer传递到组件来进行更改。 这种方法确保了线程安全,更改配置的操作与ExoPlayer上的其它事件一样,需要按顺序执行。

自定义

ExoPlayer与MediaPlayer的主要优点之一是可以自定义和扩展播放器,以更好地适应开发人员使用。 ExoPlayer库专门设计了这一点,定义了一些接口和抽象基类,使应用程序开发人员可以轻松地替换库提供的默认实现。 以下是构建自定义组件的一些case:

  • Renderer:可以自定义Renderer来处理默认实现不支持的多媒体格式

  • TrackSelector:自定义TrackSelector可以更改从MediaSource中提取轨道的方式

  • LoadControl:自定义LoadControl可以更改播放器的缓冲策略

  • Extractor:如果需要支持默认库不支持的容器格式,可以自定义Extractor类,然后可以将其与ExtractorMediaSource一起使用,以播放容器格式的多媒体

  • MediaSource:如果希望获取媒体样本以自定义方式提供给渲染器,或者希望实现自定义MediaSource合成行为,则实现自定义MediaSource类可能是适当的

  • DataSource:ExoPlayer库已经包含了许多不同情况的DataSource实现。您可能希望实现自己的DataSource类,以其他方式加载数据,比如通过自定义协议,使用自定义HTTP堆栈或从自定义持久缓存加载数据。

自定义指南

如果自定义组件需要将事件报告回应用程序,我们建议您使用与现有ExoPlayer组件相同的模型,其中将事件侦听器与Handler一起传递到组件的构造函数。

我们建议自定义组件使用与现有ExoPlayer组件相同的模型,以便在播放过程中可以方便地重新配置,请参考上面“向组件发送消息”章节。 为此,您应该实现一个ExoPlayerComponent并在其handleMessage方法中接收配置更改消息。 您的应用程序应通过调用ExoPlayer的sendMessages和blockingSendMessages方法来传递配置更改。

参考:http://blog.csdn.net/u014606081/article/details/76181049

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,566评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,612评论 4 59
  • 最近被《我的前半生》刷屏。刚开始想去看完全是无意中看预告剧情简介,有马伊琍这几个实力派演员主演,再也行是年龄的倾缘...
    暖晴汝阅读 121评论 0 0
  • 第三十二章 北山密谋 领导班子会议结束后,卜贤玉没有走,一个人在办公室呆坐。此刻,他心乱如麻,乱得像塞了一脑袋稻...
    雨燕江南阅读 341评论 1 8
  • 今天九点以后真是晴空万里,阳光普照。难得好天起!就给女儿说:“快点把练习题做完,我带你们去公园” 孩子听后都很开心...
    粽子妈妈爱星星阅读 975评论 0 0