-
Notifications
You must be signed in to change notification settings - Fork 163
播放消息机制
播放器在播放过程,需要将播放进度、播放完成,等等消息通知给用户。常见的消息有:
- 播放进度
- 播放完成
对于网络流媒体视频的播放,还会用到的消息有:
- 播放器初始化完成
- 播放器初始化失败
- 播放缓冲中 ...
本地文件的播放,我们一般只需要知道播放进度和播放是否完成。对于网络流媒体,会存在网络质量导致的播放缓冲,这时画面停止同时需要显示缓冲进度条进行提示。另外网络流媒体的播放,在播放器初始化的时候,打开一个 URL 可能会长时间阻塞(可长达数十秒),这样我们就需要用异步的方式去打开 URL,并监听播放器初始化成功或失败的消息,然后在 UI 上显示给用户。
windows 平台上,我们可以很好的利用窗口消息的机制,来发送播放器消息。android 平台上,可以利用 java + jni 实现 callback 方法。最简单的消息处理方式,就是 callback 函数,在 fanplayer 的 windows 和 android 版本的实现上都已经支持了这种机制。但是在 callback 方法中,我们并不建议直接执行消息处理的代码,而是通过在 callback 中发送消息给 UI 的主线程来进行消息处理。windows 上用的是 PostMessage API,android 上用到的是 Handler 的 sendMessage 方法。
为什么不建议直接在 callback 方法中直接执行消息处理的代码?fanplayer 的 callback 的回调,会在 vdev 的视频渲染线程中执行到。如果在 callback 中执行了大量的、耗时的、UI 操作的代码,可能会导致视频显示异常、程序崩溃等问题。在 android 平台上,更是建议把所有 UI 操作都放在 activity 的主线程中去执行,否则是会导致程序崩溃的。所以在 callback 中采用发送消息的方法,由 UI 主线程来处理消息,这样的方式是最可靠的播放器消息的处理方式。
另外一个更加稳定可靠的方式,就是查询方式来处理播放器消息。播放器消息对实时性的要求通常情况都是不高的,因此几乎所有的消息,都可以使用查询的方式来处理。而播放器要显示播放进度,本身也是要不停的去查询。查询播放进度的 API 返回的是 ms 为单位的时间进度,而播放完成、播放缓冲、播放器初始化成功或失败,我们可以定义特殊值来表示(比如 -1、-2、-3),这样我们就只需要用同一个进度查询的 API 就能处理完全部的播放器消息。
我个人更加倾向于使用查询机制来处理播放器消息,这种方法简单、有效、可控、稳定。简单有效稳定就不说了,“可控”体现查询的频率是可控了,说白了就是查询定时器的周期的设定。如果采用 callback 或消息机制上报播放器进度,播放器内部会频繁的触发 callback 函数或者执行发送消息的 API。比如 vdev 的渲染线程中,每一帧就执行一次 callback 函数?这样的频繁执行,带来的是性能和稳定性的下降。
总结来说,播放器的消息并不多,进度、完成、初始化、缓冲...,而且对实时性要求并不高,使用窗口消息(windows)和 Handler 消息(android)机制,可以很好的处理,使用查询方式也可以简单有效的解决问题。
fanplayer wiki