转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/54693696

在Android设备上播放音频和视频已经很流行了,Android框架提供了用于播放媒体用最少的代码的快速解决方案MediaPlayer。也提供了low-level 的 api 用于构建定制媒体播放器的解决方案,例如MediaCodec, AudioTrack和MediaDrm。

ExoPlayer是建立在 Android low-level api之上的 app级开源播放器。开源项目包含 ExoPlayer库和demo。

  • ExoPlayer库 - 类库源代码

  • Demo - 演示类库的使用

本文介绍了 ExoPlayer 库及其用途,使用 ExoPlayer 的利弊 ,具体的代码示例演示了如何使用,展示了如何使用ExoPlayer 播放 DASH,SmoothStreaming 和 HLS 自适应流,如 MP4,M4A,FMP4,支持 WebM,MKV,MP3,OGG,WAV,MPEG-TS,MPEG-PS,FLV 和 ADTS( AAC)。还讨论 ExoPlayer 的事件、消息、定制和 对 DRM 的支持。

1
优点和缺点

相比 Android 内置的 MediaPlayer,ExoPlayer 具有许多优于优势:

  • 支持 Dynamic Adaptive Streaming over HTTP (DASH) 和SmoothStreaming,更多支持请参阅支持的格式)详细信息页面。

  • 支持高级 HLS (HTTP Live Streaming)功能,如正确处理 #EXT-X-DISCONTINUITY的标签。

  • 能够无缝融合,串联和循环媒体资源。

  • 支持定制和扩展,ExoPlayer是考虑到这一点而设计的,并允许许多部件与定制实现替换。

  • 更新起来更方便

  • 设备通用性更强

  • 支持在Android 4.3(API级别18)和更高的Widevine通用加密。

需要注意的是,也有一些缺点,这一点很重要:

  • ExoPlayer的标准音频和视频部件依赖于Android的 MediaCodecAPI,MediaCodecAPI 在搭载Android 4.1(API级别16)发布。因此,他们不会在较早版本的 Android 的工作。Widevine 的通用加密可以在 Android 4.3(API级别18)和更高。

2
Library overview

ExoPlayer库的核心是ExoPlayer接口。ExoPlayer 接口暴露了传统的 high-level 播放器中的功能,如资源缓冲,播放,暂停和拖拽等。接口的实现类对媒体的播放类型、存储位置和渲染方式做出假设,而不是笼统的加载和渲染。Exoplayer 把播放类型、存储位置和渲染方式等任务委派给不同的部件,然后在创建播放器或后台播放的时候把这些部件注入。这些部件包括:

  • MediaSource - 负责装载 media,装载到MediaSource 的 media 可以被读取,MediaSource 在调用 ExoPlayer.prepare 方法时被注入。

  • Render S - 用于渲染 media 的部件,在创建播放器时被注入

  • TrackSelector - 从MediaSource 中选出 media 提供给可用的 Render S 来渲染,在创建播放器时被注入。

  • LoadControl - 控制 MediaSource 缓存更多的 media,有多少 media 被缓冲。在创建播放器时被注入。

类库提供这些部件在通常情况下的默认实现,下面有详细描述。一个 ExoPlayer 可以利用这些部件。如果标准实现不能满足需求,也可以使用自定义实现。例如,自定义LoadControl 可以改变播放器的缓冲策略,或自定义Renderer 可实现 Android 本身不支持的视频编解码器。

ExoPlayer提供默认的音频和视频渲染器,利用了Android框架中的MediaCodec和AudioTrack类。这两个都需要一个SampleSource对象中注入,用来实现媒体示例的播放。

组件的注入在当前ExoPlayer库中是普遍存在的。下图展示了使用一个ExoPlayer来配置和播放MP4媒体流的高级对象模型。默认的音频和视频渲染器已经被注解到ExoPlayer中。一个叫ExtractorSampleSource类的实现被注解到渲染器中用于提供简单的媒体播放功能。DataSource和Extractor示例被注解到ExtractorSampleSource来支持加载媒体流和在被加载的数据中提取样板。在这个示例中DefaultUriDataSource和Mp4Extractor被用于播放从URIs中导入的MP4流。

注入的概念贯穿整个类库的实现,默认的部件实现类何以被进一步的委托注入,这让许多子部件被单独更换成自定义实现。比如,通过提供一个定制的工厂有可能从一个非标准的源或通过不同的网络协议栈加载数据。而默认的MediaSource 实现需要一个或多个 DataSource 工厂的构造函数被注入。

Adaptive media playbacks


ExoPlayer 支持自适应流,即在播放的时候,根据网络状况自动调节视频质量。DASH,SmoothStreaming和HLS展示了自适应流技术。以上三种,媒体都是通过小块的方式加载(通常2到10秒的长度)。每当一块媒体被请求,客户端将会选择一种可能的规格。例如:如果网络情况比较好,客户端将选择高质量的规格,如果网络比较差则会低质量的。在两种技术中,视频和音频都需要被分割。

DASH android SmoothStreaming


ExoPlayer库通过ChunkSampleSource支持DASH和SmoothStreaming动态播放,即通过读取独立的媒体块。每个ChunkSampleSOurce需要一个ChunkSource通过构造方法注入进来。ChunkSource主要负责加载和读取样本来提供媒体块。DashChunkSource类使用FMP4和WebM容器格式来提供DASH播放。SmoothStreamingChunkSource类使用FMP4容器格式。

两种类型的ChunkSource实例需要一个解析器FormatEvaluator和一个数据源DataSource通过构造的方式注入。FormatEvaluator在每个块被加载之前选择一种可用的格式,DataSource提供数据源。最终,ChunkSampleSource需要一个LoadControl对象去控制缓冲块。
下图演示了DASH动态播放通常的配置。通过FormatEvaluator实现视频质量的动态变化,但是音频的质量是固定的。

3
Getting started

开始使用 ExoPlayer 需要执行以下步骤:

  1. 添加依赖

  2. 创建一个 SimpleExoPlayer 实例

  3. 将 player 和 view (用于视频输出和用户输入)关联

  4. 调用 prepare 方法,注入MediaSource,准备播放

  5. 播放结束释放 player

这些步骤在下面更详细地所述。对于一个完整的示例,请参阅 PlayerActivity在ExoPlayer演示程序。

Add ExoPlayer as a dependency

确保支持 Jcenter 仓库

  1. repositories {

  2.   jcenter()

  3. }

添加依赖 - 版本

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

4
Creating the player

您可以通过 ExoPlayerFactory 工厂方法创建一个 ExoPlayer 实例。 工厂提供了一系列的方法创建不同程度定制的 ExoPlayer 实例。对于绝大多数使用情况下,默认 Renderer 库提供的实现足够用。这时应该使用 ExoPlayerFactory.newSimpleInstance 方法。方法返回 SimpleExoPlayer,SimpleExoPlayer 扩展了 ExoPlayer 并添加额外的 high-level 播放功能。下面演示了如何创建一个 SimpleExoPlayer。

  1. // 1. Create a default TrackSelector

  2. Handler mainHandler = new Handler();

  3. BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

  4. TrackSelection.Factory videoTrackSelectionFactory =

  5.    new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);

  6. TrackSelector trackSelector =

  7.    new DefaultTrackSelector(mainHandler,

  8.                             videoTrackSelectionFactory);

  9. // 2. Create a default LoadControl

  10. LoadControl loadControl = new DefaultLoadControl();

  11. // 3. Create the player

  12. SimpleExoPlayer player =

  13.    ExoPlayerFactory.newSimpleInstance(context,

  14.                                 trackSelector, loadControl);

5
Attaching the player to a view

ExoPlayer 库提供了 SimpleExoPlayerView ,它封装了一个 PlaybackControlView 和 Surface 用来渲染视频。一个 SimpleExoPlayerView 可以包含在布局 XML 文件中。下面演示了如何绑定 player

  1. simpleExoPlayerView.setPlayer(player);

如果您需要比播放器控制和渲染视频的 Surface 上更细粒度的控制,可以给播放器设置目标 SurfaceView, TextureView,SurfaceHolder 或 Surface 直接分别使用 SimpleExoPlayer 的 setVideoSurfaceView,setVideoTextureView,setVideoSurfaceHolder 和 setVideoSurface 方法。您可以使用PlaybackControlView 作为一个独立的部件,或实现自己的 playback 直接与 player 进行交互。setTextOutput 和setId3Output可用于 playback 时接收字幕和 ID3 元数据输出。本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/54693696

6
Preparing the player

在 ExoPlayer 每一个 media 都由 MediaSource 代表。要播放 media 必须先创建一个相应的 MediaSource,然后把这个对象传递给 ExoPlayer.prepare。ExoPlayer 库提供 MediaSource 的DASH实现(实DashMediaSource),SmoothStreaming 实现( SsMediaSource),HLS 实现(HlsMediaSource)和常规 media files 实现(ExtractorMediaSource)。这些实现在后面详细介绍。下面的代码演示如何使用 MediaSource prapare 一个适合播放 MP4 文件的 player。

  1. // Measures bandwidth during playback. Can be null if not required.

  2. DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

  3. // Produces DataSource instances through which media data is loaded.

  4. DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(

  5. this,Util.getUserAgent(this, "yourApplicationName"), bandwidthMeter);

  6. // Produces Extractor instances for parsing the media data.

  7. ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

  8. // This is the MediaSource representing the media to be played.

  9. MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,

  10.    dataSourceFactory, extractorsFactory, null, null);

  11. // Prepare the player with the source.

  12. player.prepare(videoSource);

一旦 player 已经被 prepared,playback 可以通过调用播放器上的方法进行控制。例如 setPlayWhenReady 可用于启动和暂停播放,和各种 seekTo 方法可以用于改变进度。如果 player 被绑定到 SimpleExoPlayerView 或 PlaybackControlView ,那么用户与这些部件的交互将会导致 player 相应的方法被调用。本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/54693696

7
Releasing the player

不再使用的时候将 player 释放掉是非常重要的,以便腾出有限的资源,如为其他应用程序使用视频解码器。这可以通过调用 ExoPlayer.release 来完成。

MediaSource

在 ExoPlayer 每一个 media 都由 MediaSource 代表。要播放 media 必须先创建一个相应的 MediaSource,然后把这个对象传递给 ExoPlayer.prepare。ExoPlayer 库提供 MediaSource 的DASH实现(实DashMediaSource),SmoothStreaming 实现( SsMediaSource),HLS 实现(HlsMediaSource)和常规 media files 实现(ExtractorMediaSource)。Demo app de PlayerActivity,分别演示了如何实例化以上四种 MediaSource。

除了上述的 MediaSource 的实现方式,ExoPlayer 库还提供MergingMediaSource,LoopingMediaSource 和 ConcatenatingMediaSource。这些 MediaSource 实现能够通过组合能够支持更复杂的 playback 功能。下面对一些常见的用例进行说明。注意,尽管下面的实例使用的视频 playback,它们同样适用于仅有音频 playback,事实上适用于所有支持的 media types 的 playback。

8

8
Side-loading a subtitle file

给定的视频文件和一个单独的字幕文件,MergingMediaSource 可以将它们合并到用于 playback 的单一来源。

  1. MediaSource videoSource = new ExtractorMediaSource(videoUri, ...);

  2. MediaSource subtitleSource =

  3.   new SingleSampleMediaSource(subtitleUri, ...);

  4. // Plays the video with the sideloaded subtitle.

  5. MergingMediaSource mergedSource =

  6.    new MergingMediaSource(videoSource, subtitleSource);

Seamlessly looping a video

LoopingMediaSource 可以实现视频的无缝循环。下面演示了如何实现无缝循环。也可以创建一个指定循环计数的 LoopingMediaSource。

  1. MediaSource source = new ExtractorMediaSource(videoUri, ...);

  2. // Loops the video indefinitely.

  3. LoopingMediaSource loopingSource = new LoopingMediaSource(source);

Seamlessly playing a sequence of videos

ConcatenatingMediaSource 使得 playback 支持顺序播放两个或多个单独的 MediaSource S,下面的示例顺序播放两段视频。无缝切换资源,并且对被串联资源的格式是否相同没有要求。

  1. MediaSource firstSource =

  2.    new ExtractorMediaSource(firstVideoUri, ...);

  3. MediaSource secondSource =

  4.    new ExtractorMediaSource(secondVideoUri, ...);

  5. // Plays the first video, then the second video.

  6. ConcatenatingMediaSource concatenatedSource =

  7.    new ConcatenatingMediaSource(firstSource, secondSource);

Advanced composition

可以为了更不寻常的用例进一步结合复合 MediaSourceS。给定两个视频 A 和 B,下面的例子演示了如何使用 LoopingMediaSource 和ConcatenatingMediaSource 按照( A,A,B)的序列进行无线循环。

  1. MediaSource firstSource =

  2.   new ExtractorMediaSource(firstVideoUri, ...);

  3. MediaSource secondSource =

  4.   new ExtractorMediaSource(secondVideoUri, ...);

  5. // Plays the first video twice.

  6. LoopingMediaSource firstSourceTwice =

  7.   new LoopingMediaSource(firstSource, 2);

  8. // Plays the first video twice, then the second video.

  9. ConcatenatingMediaSource concatenatedSource =

  10.   new ConcatenatingMediaSource(firstSourceTwice, secondSource);

  11. // Loops the sequence indefinitely.

  12. LoopingMediaSource compositeSource =

  13.   new LoopingMediaSource(concatenatedSource);

下面的例子是等价的,这表明实现相同的结果方式不止一个。

  1. MediaSource firstSource =

  2.    new ExtractorMediaSource(firstVideoUri, ...);

  3. MediaSource secondSource =

  4.    new ExtractorMediaSource(secondVideoUri, ...);

  5. // Plays the first video twice, then the second video.

  6. ConcatenatingMediaSource concatenatedSource =

  7.    new ConcatenatingMediaSource(

  8.      firstSource, firstSource, secondSource);

  9. // Loops the sequence indefinitely.

  10. LoopingMediaSource compositeSource =

  11.    new LoopingMediaSource(concatenatedSource);

避免在一次 composition 中用同一个 MediaSource 实例多次,除非文档中明确允许。在上面的例子中两次使用 firstSource 的就是这样的情况,由于对 Javadoc 中 ConcatenatingMediaSource 明确规定,重复项是允许的。在一般情况下,由组合物形成的对象的曲线应该是一个树。在 composition 中使用多个等同于 MediaSource 的实例是允许的。

Player events

playback 过程中,应用程序可以监听由 ExoPlayer 生成的指示 player 全部状态的事件。可以根据这些事件来更新用户界面。许多 ExoPlayer 组件还报告它们自己特定的 low-level 的事件,可以用于性能监控。

High level events

ExoPlayer 使用 addListener 和 removeListener 添加和移除 ExoPlayer.EventListener 实例。被注册的侦听器可以发布 playback 的状态变化,以及出错时发布错误产生的原因。

开发者自定义 playback 应该注册一个监听器,并根据 player 的状态变化来更新控件。如果播放失败,应用程序还应该向用户显示相应的错误。

使用 SimpleExoPlayer 时,可以在 player 上设置额外的监听器。特别是 setVideoListener 允许应用程序接收与视频渲染有关的事件,该事件可以是用于调整用户界面。setVideoDebugListener 和setAudioDebugListener 可以接收调试信息。

Low level events

除了 high-level 监听器,许多由 ExoPlayer 库提供的组件,允许拥有自己的事件侦听器。通常需要传递一个 Handler 给部件,用来确定监听器方法被调用线程。在大多数情况下,Handler应与应用程序的主线程关联。

Sending messages to components

有些 ExoPlayer 组件允许在播放过程中更改配置。按照惯例,您通过使用 sendMessages 或 blockingSendMessages 方法传递变化消息给ExoPlayer 组件。这种方式可以确保两个线程安全并且使得配置更改和在 player 上的他操作执行有序。

Customization

相比 Android 内置的 MediaPlayer,ExoPlayer 的主要好处是支持定制和扩展的 player 以更好地满足开发者的实际用例。在考虑到这一点而设计ExoPlayer 库时,定义了大量接口和抽象基类帮助开发者轻松的替换类库提供的默认实现,下面展示了一些用于构建自定义组件的用例:

  • Render - 实现自定义Renderer处理不是由库提供的默认实现所支持的媒体类型。

  • 如果自定义组件需要向应用程序发布事件,我们建议您一定要使用现有的 ExoPlayer 组件模型,在构造组件的时候同时传递监听器和 Handler

  • 我们建议的自定义组件使用现有 ExoPlayer 组件相同的模型,允许在playback 的过程中重新配置。要做到这一点,就需要实现ExoPlayerComponent 接口,并在 handleMessage 方法中处理接收到的配置改变信息。您的应用程序应该调用 ExoPlayer 的 sendMessages和blockingSendMessages 方法来传递改变的配置信息。

ExoPlayer Demo 中 PlayerActivity 演示了 DrmSessionManager 如何在初始化 player 的时候被创建和注入

本文翻译自:https://google.github.io/ExoPlayer/guide.html

翻译者:SavySoda、逆流的鱼yuiop

第一时间获得博客更新提醒,以及更多android、小程序干货,源码分析,最新开源项目推荐,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

Google Exoplayer之全面认识相关推荐

  1. Android视频播放器Google Exoplayer

    最近开发的项目涉及音频.视频播放,搜索了解到ExoPlayer2.x可以很好的满足需求,现在跟大家分享一下. ExoPlayer库的核心是ExoPlayer接口.ExoPlayer 接口暴露了传统的 ...

  2. Google Exoplayer 之全面认识

    转自:https://juejin.im/entry/5884061f128fe1006c34ea43 在Android设备上播放音频和视频已经很流行了,Android框架提供了用于播放媒体用最少的代 ...

  3. 使用google开源框架Exoplayer开发自定义播放器

    http://ju.outofmemory.cn/entry/143633 背景: 移动端播放视频的需求如日中天, 最近特此使用google的开源框架Exoplayer来开发Android端的视频播放 ...

  4. ExoPlayer简单使用

    2019独角兽企业重金招聘Python工程师标准>>> 一.介绍 ExoPlayer是google开源的应用级媒体播放器项目,该开源项目包含ExoPlayer库和演示demo,git ...

  5. [转]Google的60款开源项目

    1.机器学习系统 TensorFlow 详情:https://github.com/tensorflow/tensorflow 2.material-design-icons 详情:http://go ...

  6. ExoPlayer播放器 开发者指南(官方权威指南译文)

    前言   因为公司项目原因,目前开始研究ExoPlayer的原理及实现.其中对DRM更是有所涉及,因此自己也好借此机会扩展自己的音视频知识,同时写出一些自己的技术总结与分享,希望对其他学习此播放器的朋 ...

  7. ExoPlayer+Shaka-packager播放自制DRM视频

    1. 工具说明 1.1 ExoPlayer ExoPlayer是google开源的应用级媒体播放器项目,构建在Android的底层多媒体API之上.该开源项目包含ExoPlayer库和演示demo. ...

  8. Google最热门60款开源项目

    0.机器学习系统 TensorFlow  ★Star 62533 TensorFlow 是谷歌的第二代机器学习系统,按照谷歌所说,在某些基准测试中,TensorFlow的表现比第一代的DistBeli ...

  9. Google的60款开源项目

    1.机器学习系统 TensorFlow 详情:https://github.com/tensorflow/tensorflow 2.material-design-icons 详情:http://go ...

  10. 开源巨献:Google最热门60款开源项目(转)

    https://www.cnblogs.com/svili/p/7889436.html 0.机器学习系统 TensorFlow  ★Star 62533 TensorFlow 是谷歌的第二代机器学习 ...

最新文章

  1. Atitit 为什么网络会有延时 电路交换与分组交换的区别
  2. 5月,我面试了60多号人,写了些总结
  3. php网页添加图片的代码,天天查询-PHP版的kindeditor编辑器加图片上传水印功能
  4. c++ 利用内存映射读取大文件
  5. PX4的workqueue
  6. 8.对Hello World程序的深入
  7. 神经进化学的简介和一个简单的CPPN(Compositional Pattern Producing Networks)DEMO
  8. 关于redis的pipline和lua脚本
  9. 关于jquery你不得不知的小知识
  10. asc怎么用 linux zip_linux的asc文件怎么打开
  11. License Server Version 11.9 Installation on Windows Server 2003 Hangs
  12. switch里面变量吗c语言,讨教一下关于switch语句中变量定义的相关问题
  13. vue v-if未生效问题
  14. 自定义列表数据自动循环向下滚动view(类似于通知通报消息)
  15. 线程的stop方法和interrupt方法
  16. Datawhale- DS- Jun - 第一章:第一节数据载入及初步观察-课程
  17. html 文字段后间距怎么设置,p字间距 html段落内文字设置字间距间隔
  18. 关于高通平台下camera一些参数的设置
  19. 计算机名打印机无法共享,打印机共享不了怎么回事 打印机共享不了原因和解决办法【详解】...
  20. HTML5期末大作业:轮滑运动体育类人物介绍主题网站设计(12页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计

热门文章

  1. 设计模式(14)——原型模式(Prototype)
  2. 反射相关知识及jOOR反射库介绍
  3. 多视几何_计算一副图像上的点在另一福图像上的对应点
  4. ML/DL-复习笔记【四】- DeepLab系列模型总结
  5. Java:对于Borderlayout布局管理的理解
  6. ICCV2021|性能优于何恺明团队MoCo v2,DetCo:为目标检测定制任务的对比学习
  7. 如何查询Oracle性能监控
  8. java多线程编程(一基础概念)
  9. 学习使用TestNG中的注解(2)——@Factory的使用
  10. Apache整合Tomcat(转)