项目记录: Dynamic playlists with ExoPlayer

项目记录: Dynamic playlists with ExoPlayer

翻译一下 Dynamic playlists with ExoPlayer 2017.08.25

介绍

现在支持 Exoplayer media playlists . 使用者可以在播放器运行的过程中,任意添加和移除 playlist item .

从 Exoplayer 2.8.0 版本,通过更新 ConcatenatingMediaSourcedynamic playlist 的功能. 新的媒体资源可以通过以下简单和直接的接口:

  • addMediaSource(mediaSource) : 添加一个媒体资源到 playlist 的末尾;

  • addMediaSource(index,mediaSource) : 在 index 位置插入一个新的媒体资源;

  • addMediaSource(Collection<MediaSource>) : 添加一整个媒体资源到 playlist 的末尾;

  • addMediaSources(index, Collection<MediaSource>) : 在 index 位置插入一整个媒体资源;

  • removeMediaSource(index) : 溢出 index 位置的 媒体资源;

  • moveMediaSource(fromIndex, toIndex) : 将 fromindex位置的媒体资源移动至 toindex 位置处;

    可以不需要再创建新的 MediaSource . 而且可以不打乱播放,移动当前正在播放的 item ;

  • getMediaSource(index) : 获得index位置的媒体资源

  • getSize() : 返回当前 playlist 的长度

以上的方法,可以在播放器播放之前或者播放开始之后调用,而且无论哪个 item 正在播放.这些方法都是 thread-safe 线程安全的;

可以通过预先缓存下一个 playlist 的缓存来实现 gapless playback 无间隔播放.

而且, 在播放到一个新的元素,将会收到 eventListener.onPositionDiscontinuity 的通知.

如果你想要开始使用这个 playlist 的新功能,就去下载 新的 release 版本的ExoPlayer,开始码代码吧.

如果你对实现细节感兴趣,可以继续看下去.


实现细节

为了理解 支持 dynamiclly changing media source 其中涉及到的困难.

先一看 How ExoPlayer works with media sources internally ,Exoplayer和MediaSource在内部是如何一起工作的. 其中,涉及到5个类和5个线程:

  1. APP : 运行在 app thread . 这个线程调用了 如 prepare media source 的命令来调用 player
  2. Player : 创建一个实例,在 PlayBack thread 播放线程中.
  3. Media Source : 在 app thread 中创建,是接触到真正的媒体资源的. 在 loader threads 加载资源,而且与playback threadplayer 通信.
  4. timeline : timelines 是一成不变的? 可以在所有线程访问.
  5. media period : 负责 buffering (缓存数据)和 playback of the media data (播放媒体数据). 在 playback thread 中被media source 创建, 但是真正加载数据的呢:是在 loader thread ;

在这样的多线程环境下,一个很中药的问题是: 多个线程可能在时间上会出现 不同的 player state (播放器状态). 因此, 当一个命令在一个线程发布而在另一个线程处理,第二个线程必须必须处在和第一个线程发布命令的同一状态,二者要保持一致这是必须的.

当实现 dynamic playlist change into the process 会带来以下两个:

  1. 立即反应所有线程的状态变化 和 2) 等待一个异步的过程恰当地结束 是两个竞争的期望. 会造成以下三个难题:
  1. Lazily updating the master playlist on the playback thread while having a instantly updated playlist on the app thread

    app thread 更新了一个 playlist , playback thread 更新 playlist 延时了.(懒洋洋Lazily)

  2. Lazily waiting for new timeline information while keeping the timeline consistent with the playlist.

    缓慢地等待新的 timeline信息 当 和 playlist 保持一致

  3. Being able to create new periods based on the playlist while waiting for the lazy timeline information

    根据 playlist 创建新的 period 当等待 timeline缓慢更新

总的来说,解决方法是非常相似的: 我们使用 mocking instances of the objects we are waiting for (模拟的等待对象,相等于创建了临时的假的?)

这些 mocking instances 被立即创建,来尽可能地欺骗那些延迟操作. 因此呢. 整个系统的状态会得到迅速地更新,防止进入模糊不清的情况. 一旦真实的结果变得可用,这些 mocking instances 将会停止模拟,而是开始正式地调用真正的实例化对象.

Update the playlist

playback thread 线程的master playlist 作为我们想要实现所有操作的 playlist . 会有两个缺陷:

  1. 我们希望能够随时改变播放列表(即在 playback thread 这个线程起之前)
  2. 我们希望可视化这播放列表的信息来立即反应所有我们做的变化.

因此,我们将保持第二个(mocked) playlist (这个是在 app thread 线程上的),这个将会立即得到更新,而且它可以用来查询 playlist 的信息. 一旦 master playlist 是可用了,所有作应用在 这个 mocked playlist 的操作将会被使用在 playback thread 线程上的 playlist 来进行更新.

update playlist

keeping the timeline in syn with playlist

无论 playlist 何时变化,我们需要有一个新的 timeline 去反应新的 media structure . 有些时候,我们需要加载新添加的 media 的开始部分获取信息来更新 timeline. 但是呢,timeline立即反应所有 更新到playlist的所有变化是非常重要的.

  • 例如, 如果 app 添加了一个新的 source 在 index为 i 的位置, 立即 seek 到这个i位置,期望的结果是这个新的source将会被播放.如果player没有感知到这些变化的话(由于它还在就的时间信息上),那么它将 seek到 另一个 item 上,而非我们刚刚添加的. 这就是为什么立即更新 timeline是非常关键的.

为了解决这个问题, 当 master playlist变化时,我们立即触发 a timeline update , 用的是 a new mocked timeline element. 这个 mocked timeline element 是未知的时长, 它被标志位 dynamic 去告诉播放器,它应该期待发生在它属性上的变化. 尽管这个信息不是非常有帮助,但是,至少它保证了 timeline 和 playlist 保持一致. 当 playlist element 准备好了, 这个 mocked 的 timeline element 将会返回真实的媒体属性.

img

Creating periods while waiting for timeline updates

第三个问题是由于第二个问题的解决方案造成的.

想想一下我们立即想要播放这个新插入的 playlist item. 播放器会叫 media source创建一个新的 media period. 但是呢,meidia source 无法完成需求,仍然在等待一个真正的 media information

相同地,我们借用了一个 mocked media period 去为 mocked timeline 创建 一个 media period . 由于没有真实的 media, 这个 media period 将会用于保持在 缓冲模式,告诉播放器媒体还没有做不好播放.一旦呢,timeline获得更新真的media information ,这个 mocked media period 将创建真的media period, 推进调用那包装的实例.

img

总结:

  • 这个博客描述了 新的 ConcatenatingMediaSource 特性来添加和移除 播放器上的元素.

参考文献

Dynamic playlists with ExoPlayer

猜你喜欢

转载自blog.csdn.net/qjh5606/article/details/85009042
今日推荐