播放器重构中遇见的坑

播放器重构中遇见的坑

最近一直在重构公司项目的播放器项目, 这次重构是借鉴了Bilibili开源的ijkPlayer 代码的 写法, 一个VideoView 对应各种播放器内核.
(android mediaplayer, exoplayer, ijkplayer.)
rendenview 与 Mediaplayer 层面 隔离开.

在开发过程中遇见了几个小坑.

  • 播放器状态相关
    简单的来说, mediaplayer 和ijkplayer 在进入Preparing的状态中时, 是不会对视频本身进行缓冲的, 而仅仅是做了初始化播放器的工作, 也就是说在prepared完成之前, 是不会有buffer的生命周期回调的, 而是在prepared 之后, 才会开始进入buffering state. 但是exoplayer的理念和 这两者有一点小小的不同,
    exoplayer在 进入 preparing状态之后 初始化完成播放器以后,
    会对视频本身开始buffer, buffer到足够开始进行播放以后, 才会
    回掉 STATE_READY(Prepared)的状态.
    这会给上层做整套生命周期 造成一定的影响.

    如图:
    androidmediaplayer/ ijkplayer 的初始化生命周期
    IDLE –> Preparing –> Prepared –> buffering –> playing.
    exoplayer的 初始化生命周期
    IDLE –> preparing –> buffering –> prepared(ready)

  • onCompletion 相关
    这三个播放器都有onCompletion的回调,这个回调其实很好理解,就是播放完成的时候会回调该生命周期,
    但是ijkplayer回调的时机是有问题的, 它不仅仅在播放完成的时候会回调该方法,而且在出现错误的时候也会回调该方法。
    播放器产生错误 –> onError –> onCompletion.
    我也跟IJK的作者提了issue;
    作者也承认了这个错误, 但是 他说 这并不重要, not on plan.

  • SeekTo 相关
    android mediaplayer seekTo 到 mediaplayer.getDuration(); 也就是说 seek到最后 正常来说 是没有什么问题的.
    可以正常seek, 然后成功进入completed状态. 然后这个时候调用start. 也不会有什么问题 会进入Playing状态
    但是你如果再次seekTo mediaplayer.getDuration(); 再点播放 就会出问题了, Mediaplayer 内部状态已经混乱了.
    对于这件事 我不知道为什么网上搜不到很多相关的问题, 可能是我太无聊了或者我使用方法不恰当的问题把.
    总而言之最后我做了WorkAround.
    每次执行seekTo的时候 我都会判断1下 是不是seekTo到最后 如果是 我就seekTo到getDuration() - 2000;
    然后 问题解决了

不过还好 这些问题如果理解的好,可以在上层进行规避.把三套播放器的生命周期 可以整合一套的。

Share Comments