CicadaPlayer实现多屏同步播放介绍

1. 多屏同步的使用场景

此功能来自于一个需求:在同一个屏幕上同步显示同一个内容的四个不同码率的画面,用来展示不同的分辨率和码率最终被播放出来的画质的差异。
抽象一下此需求的场景,其实就是要多个播放器之间进行同步的需求,这些播放器之间可以不一定是同一个app内,甚至可以是互联网上的任何两个播放器实例。

使用场景一

一个App中多个播放器间同步,如同最原始的需求。

使用场景二

一个博物馆要投射一个模拟清明上河图的场景再现视频,由于清明上河的宽度非常宽,如果用普通的方案去投射,那么视频将无法观看,博物馆采用的方案是使用多个投影仪排成一排,每个投影仪投射整个视频的一部分,多个投影仪同步播放,这样就可以更好的把清明上河图的场景再现视频更好的播放了。

此场景可以使用一台比较强大的主机,同时播放各个部分的画面,然后通过hdmi阵列输出,如果这样实现,则和场景一差不多,只是内容不是相同的而已。如果这么实现,那么对主机的要求就比较高了,需要一个强大的解码功能,和多hdmi输出的显卡,并需要考虑画面和hdmi的输出对应关系。

此场景也可以使用局域网来连接多个播放设备进行同步,这样的成本就会低很多,设备的摆放和线路的连接也要容易得多。

使用场景三

互联网上有个虚拟的房间,房间里面的人会观看同一个内容的视频,但是希望房间里面的所有观看者观看的视频的进度是一致的,这样可以更好的进行一些互动。如答题,猜球之类。

此场景需要互联网上的两个播放器进行同步。

2实现

从上面能想到的场景来看,只要播放器之间可以通过网络进行通信,上述的所有需求都可以满足,所以CicadaPlayer多屏同步采用的是tcp网络协议进行同步。

可以参考https://github.com/alibaba/CicadaPlayer/blob/develop/cmdline/example/syncPlayer.cpp
中的实现。

其中实现了一个用tcp client server的方式实现了一个master播放器和多个slave播放器之间进行同步的例子

static string serverIp = "tcp://localhost:8888";
server的地址,如果在同一台机器上跑,则host就是localhost或者127.0.0.1,如果跑在不同的机器上,请填入正确的ip地址。

此例子中同时实现了master和slave player,通过bMaster变量进行控制,
如果想启动server,则

./syncPlayer  file

如果想启动slave

./syncPlayer  file  1

由于播放的内容可能是网络内容,也有可能是直播,所以要想让两个视频能内容同步,则必须让两个播放器同时prepare,同时start才行,所以在syncPlayer中prepare是用户来控制的,并且不能autostart。

此示例是所有的slave只向master同步,未考虑双向通信,双向通信在后面如果有需求再去实现。

如果是master

创建一个messageServer并初始化,播放器的设置按照正常的逻辑走,在

syncPlayerEventListener::onPrePare中prepare自己,并同时向server中发送prepare消息,让所有的slave开始prepare。

onStatusChanged onLoadingStart onLoadingEnd中根据状态向server中发送start或者pause消息。

在一个循环中定时GetMasterClockPts获取当前播放器的clock发送给sever。

如果是slave

创建一个messageClient,并连接server,用来接收来自server的消息。

播放器设置成只播放视频(音视频都播放的case暂时还不支持),在一个循环中收到消息后进行处理,pause prepare start 暂不多说,slave中自己启动一个时钟来记录从server中发送过来的clock的值,由于server不可能特别频繁的发送clock值,所有slave中的clock本身就具有计时功能,在server的clock发送过来的时候只是进行校正而已。

slave播放器将自己的clock当成播放器的参考时钟,通过SetClockRefer api设置给播放器,这样slave播放器内部在播放视频的时候就会获取这个参考时钟,从而实现和master同步播放的功能。

未完成的工作

  1. 目前slave只支持纯视频播放,如果要音视频都要播放,要考虑slave播放过快或者过慢的时候要进行音频的等待或者丢帧(倍速也可以)。
  2. 目前只支持了单向通信,目前还不完善,只能比较好的实现通一个App内的同步,多进程间要考虑在每个slave都prepare完成后才能start。
  3. 目前无整体进度同步的逻辑,若在场景三种使用,则master应该不是一个实体播放器,应该是一个放到公网上的虚拟播放器,虚拟播放器通过所有的client端反馈上来的状态来决定什么时候要开始播放,怎么确定主时钟的值等,来让绝大部分播放器同步。
上一篇:南通移动:大数据在如东落地生花


下一篇:JQuery Tips(3)----关于$()包装集内元素的改变