一、引言
我台之前采购过一台Atem系列的4K切换台,尺寸为标准1U宽度,视频信号8进2出,音频模拟信号2进2出,带多画面输出,属于比较入门级别的切换台。由于采购的时候没有采购对应BMD切换台面板,应此使用该BMD Atem切换台必须外接电脑,通过它的对应软件切换,这跟我们传统的实体按键方式的切换相比还是有点不适应。
正好我们台仓库里有一批标清时代过渡过来的切换台面板和主机,型号是ROSS的Synergy100面板和Synergy1主机,标清16进15出,以前老台新闻演播室内备用的台子,所有功能完好,配件和说明书都在,放着也是吃灰,那就拿出来改造下,重新发光发彩。
二、BMD切换台API分析及工作流程
2.1、BMD切换台介绍
BMD系列的产品以其功能强大,性价比高,已于扩展开发的优点,得到了很多广电和业内同行的肯定,我在之前有篇关于BMD多画面的开发上也做过介绍通过TallyMan实现BMD多画面内动态源名及Tally显示,在此篇我们重点讲讲它的切换台和它开放给用户的SDK,切换台主机的前后面板如图所示。切换台前面板实体按键代表的是AUX1的输出监看,可直接切AUX1母线的信号源;切换台后面板带4路HMDI输入和4路HDSDI输入,同时Program输出2路,AUX输出1路,多画面输出2路,音频2入2出,切换台主机的Program输出控制采用网口,需配套它对应的切换台面板或切换台软件。
2.2、BMD SDK开发包
在BMD官网通过开发者选项,可以下载到Atem系列切换台对应的SDK,同时BMD还有内部开发者论坛,在定向开发上有问题,都可以在开发者论坛找到对应的答案。BMD SDK针对MAC和Windows平台有不同的API文件和案例,此次我开发采用的是Windows平台C#的方式,在做开发之前先得了解它的API及工作方式。
BMD介绍API的手册600多页,秘密麻麻全是接口和数据类型,对于我这种刚接触API开发的小白来说,看懂确实花了不少时间,我对BMD底层的内容以及COM组件这类也知之甚少,这块留到以后的开发中继续学习,话不多啰嗦,我把我梳理的对BMD API的介绍做简单总结如下:
a.IUnknow基类接口
IUnknow接口是一个基类接口,所有的API接口都是继承自IUnknow接口,并且所有接口在注册时都含有一个独有的GUID,同时IUnknow接口下提供了3个方法QueryInterface、AddRef、Release.QueryInterface提供获取子类接口的方法,AddRef增加接口计数,Release减少接口计数,具体原理说明网上有很多,在此不做过多解释,BMD的接口直接继承此类,然后对方法进行封装,写入COM组件,同时再提供BMD自己API接口文件,让开发者直接调用。
b.EventType事件枚举
切换台的每个操作,如切换信号源、更改多画面输出、选择视频格式、连接、断开等,都可以当作一个事件,BMD对这些事件进行了分类,每一类事件中可以枚举出具体的事件接口,通过接口获取事件对象,在通过事件对象操作事件方法,比如说更新按钮状态、更新Tally指示灯等。
1.BMDSwitcherMixEffectBlockEventType,MixEffectBlock可以当作切换台的ME母线处理模块,根据切换台ME级的数量有MixEffectBlock1到MixEffectBlock4递增,ME母线上的处理事件包含了我们切换台平时的主要操作,如“bmdSwitcherMixEffectBlockEventTypeProgramInputChanged”事件表示PGM输入信号变换;“bmdSwitcherMixEffectBlockEventTypePreviewInputChanged”事件表示PST输入信号变换;“bmdSwitcherMixEffectBlockEventTypeTransitionPositionChanged”事件表示推杆位置的变换;在此我们只要记住这些事件的作用(从字面意思去理解),然后去覆写它的方法,就能实现对该事件的操作。
2.BMDSwitcherEventType,这里面枚举了切换台配置变换后的事件,如切换台连接断开事件bmdSwitcherEventTypeDisconnected,多画面变化事件bmdSwitcherEventTypeMultiViewVideoModeChanged,视频格式变化事件bmdSwitcherEventTypeVideoModeChanged等等,我们可以利用这些事件对切换台的工作状态进行监测,以及时做出应对。
3.BMDSwitcherInputEventType,这里枚举了对切换台输入信号源的变化所采取的对应事件,如输入源名变更事件bmdSwitcherInputEventTypeShortNameChanged,Program Tally是否改变的事件bmdSwitcherInputEventTypeIsProgramTalliedChanged,我们可以利用这些事件对输入源名的变化做出实时更新。
4.BMDSwitcherInputAuxEventType,这里枚举了切换台AUX母线输入源的事件,主要包含对AUX母线上输入源信号变化的处理事件bmdSwitcherInputAuxEventTypeInputSourceChanged。
c.BMD主要API接口分析
1.IBMDSwitcherDiscovery,该接口内提供了连接切换台主机的方法“ConnectTo”,在使用该接口时,IBMDSwitcherDiscovery提供了一个子类CBMDSwitcherDiscovery,用作该接口的入口(COM出于安全性考虑),CBMDSwitcherDiscovery类中隐藏了CoCreateInstance方法,该方法用于发现IBMDSwitcherDiscovery接口并实例化,因此我们在使用该接口的时候应做如下操作。
2.IBMDSwitcher,该接口与IBMDSwitcherDiscovery一起使用,通过IBMDSwitcherDiscovery实例化并获取的m_switcher对象就是IBMDSwitcher接口的实例化,同时该接口中还提供了很多对切换台的操作方法,如获取切换台名字GetProductName,设定视频模式SetVideoMode,获取电源状态指示GetPowerStatus,添加/删除回调Add/RemoveCallback,创建迭代器CreateIterator,其中比较重要的是回调和迭代器的两种方法。
Callback回调相当于一个中断处理函数,当符合条件时,会自动调用中断里面的函数,我们在IBMDSwitcher的对象中添加回调,主要是为了添加对切换台事件的自动处理BMDSwitcherEventType,例如对切换台断开连接后的自动处理bmdSwitcherEventTypeDisconnected。
CreateIterator迭代器,可以通过接口的GUID,获取获取对应接口迭代器的指针,进而通过指针获取迭代器的对象,迭代器简单点说就是一个FIFO的队列,例如IBMDSwitcher中的CreateIterator方法,可以获取IBMDSwitcherInputIterator和IBMDSwitcherMixEffectBlockIterator两个对象,前者包含输入源的对象,如CAM1,CAM2,AUX,ColorBars的对象,通过Next方法,可以将这些对象一一放出;后者包含MixEffectBlock对象,即处理ME母线的对象,默认MixEffectBlock1开始,根据ME级母线数量增加。
3.IBMDSwitcherMixEffectBlock,该接口主要实现了对ME级母线的一系列操作,该接口的对象可以通过之前介绍的CreateIterator获取,本次使用的切换台只有1级ME,所有只需要从迭代器中取出MixEffectBlock1即可。该接口同样提供了很多操作方法,如设定PGM的输入SetProgramInput,设定PST的输入SetPreviewInput,使用AutoTrans功能PerformAutoTransition,使用Cut功能PerformCut等等,基本ME级母线需要用到的操作都在此处。
与此同时,IBMDSwitcherMixEffectBlock也提供了Add/RemoveCallback回调方法的操作,原理同之前介绍的IBMDSwitcher回调一样,此处IBMDSwitcherMixEffectBlock用到回调的作用,是为了监测PGM和PST母线上输入源的变化,同时更具变化更新切换台面板按钮灯的状态。
4.IBMDSwitcherInputAux,该接口提供了对Aux母线的操作方法,IBMDSwitcherInputAux是IBMDSwitcherInput的子接口,之前通过IBMDSwitcher中CreateIterator方法获取输入的迭代器inputIterator,该迭代器内包含各种输入信号源,同时也包含对Aux母线的操作对象,为了拿到这个Aux母线的操作对象,我们需要从迭代器中遍历查找,具体方法如下,当迭代器中的输入源类型为_BMDSwitcherPortType.bmdSwitcherPortTypeAuxOutput时,说明此输入源是Aux。
有了IBMDSwitcherInputAux对象以后,就可以通过端口对象里的方法,实现对Aux母线的操作,如设定Aux输入源SetInputSource,Add/RemoveCallback回调方法操作等,跟之前的IBMDSwitcherMixEffectBlock接口对象操作类似,在此不做复述。
2.3、BMD切换台连接简单流程的实现
BMD切换台的接口简图如图所示,主要用到的接口对象IBMDSwitcherDiscovery,IBMDSwitcherInput,IBMDSwitcherMixEffectBlock之前都有介绍,通过这些接口以及这些接口下面的子接口和方法,我们就能简单实现对BMD切换台的操作,具体软件设计流程如下:
1.使用IBMDSwitcherDiscovery::ConnectTo连接切换台设备,并获得IBMDSwitcher接口对象,同时为切换台注册监听事件IBMDSwitcherCallback,当切换台连接发生断开时,重置全部资源。
2.通过IBMDSwitcher::CreateIterator,获取IBMDSwitcherInputIterator的迭代器对象,对于每个IBMDSwitcherInput输入对象,可以通过IBMDSwitcherInputIterator::Next方法实现,获取输入对象以后,通过IBMDSwitcherInput::GetInputId获取输入对象的ID,IBMDSwitcherInput::GetShortName获取输入对象的名字,同时为每个输入对象注册监控事件IBMDSwitcherInputCallback,监测属于源名是否发生变化。
3.通过IBMDSwitcher::CreateIterator,获取IBMDSwitcherMixEffectBlockIterator的迭代器对象,通过IBMDSwitcherMixEffectBlockIterator::Next方法,获取第一级ME的接口对象,可以对该接口对象进行各类操作,如IBMDSwitcherMixEffectBlock::SetProgramInput设置PGM输入源,IBMDSwitcherMixEffectBlock::SetPreviewInput设置PST输入源,IBMDSwitcherMixEffectBlock::PerformAutoTransition使用AutoTrans功能等,同时为rMixEffectBlock1注册监控事件IBMDSwitcherMixEffectBlockCallback,当PGM和PST发生变化时,更新切换台面板上按钮状态。
4.添加外围输入事件触发,如Synergy100切换面板,通过RS422串口收发信号,当切换台收到切换面板发送过来的串口信号时,自动转换成切换台内部信号触发方式。
5.添加外围输出事件触发,BMD切换台主机需要给外部摄像机单元提供Tally GPIO信号,我们可以通过网口转GPIO的方式,将BMD切换台内数字Tally信号转换成模拟Tally信号,发送给摄像机CCU单元。
软件界面设计如下图,PGM,PST,AUX母线上的信号源选中状态,分别以不同的颜色显示。
软件设计流程框图如下图所示
三、Synergy100面板探索及按键定义
Ross Synergy100从使用至今,十几年风风雨雨,依旧坚挺,在工业设计上,运行稳定性上,不得不佩服老外。切换台采用的切换协议是GVG 100,该切换台协议至今仍在很多切换台上使用,BMD Atem其他系列的切换台主机,4ME及以上的,带COM口的,都支持GVG 100,松下的AV-HS410,AV-HS450系列也同样支持GVG 100协议,不过经过这么多年的发展,该协议的原版,或者说Synergy 100上对应的协议,早已经无处可找,从切他品牌的切换台上拿到的GVG 100协议,也是经过改良,加入过新的字段的。找不到协议说明,就不能和Synergy 100切换台握手,因此我只能从有限的信息中去获取相关操作,尝试打通它对BMD切换台的操作。
3.1、Synergy100切换台面板的连接
从切换台面板后视图可见,其提供有三种连接方式,分别是Analog模拟连接,100/10 GVG100协议连接和Synergy连接,模拟连接采用并口方式,就是简单的短路和开路信号源,此处不做深入研究;100/10接口走的是GVG100协议,为DB15的母头,RS422接口协议;Synergy接口经过测定,走的也是GVG100协议,此接口并非按照RJ45接口定义,而是RS422接口协议,不能用网线代替。
100/10接口和Synergy接口的定义分别如下图,在连接上,只需要TX+,TX-,RX+,RX-四针引出来就行。
Synergy控制面板的后端还有两个Tally并口输出,经过测试发现,只有在GVG100协议打通的时候并口Tally才能使用,因此本次项目中暂时不能用到,如需要Tally信号,需要从BMD主机中读取,将串行Tally信号转换为并行Tally信号。
3.2、Synergy切换台面板按键测试
3.2.1、面板失联状态按键输出
切换台面板上电以后,如果没有接入切换台主机,则面板上显示Lost状态,但是如果按下面板上按键,100/10接口和Synergy接口仍旧有信号输出,通过在将输出信号接入电脑,串口波特率115200,停止位1位,校验位没有,并用“串口精灵”测试,得到的按键码如下:
1.PGM按键,面板上从左往右数共有9个,按下按键并松开,对应面板的输出信号是F0 02 FB/FA 20~28 XX XX,数据显示以16进制显示,FB表示按下,FA表示松开,20表示PGM母线第一个按键,以此类推,XX XX表示两个校验位。
2.PST按键,面板上从左往右数共9个,和PGM按键类似,对应输出信号是F0 02 FB/FA 00~08 XX XX。
3.AUX按键,面板上从左往右数共9个,和PGM按键类似,对应输出信号是F0 02 FB/FA 40~48 XX XX。
4.Cut按键,对应输出信号F0 02 FB/FA 6D XX XX
5.AutoTrans按键,对应输出信号F0 02 FB/FA 6C XX XX
6.滑杆,对应输出信号F0 04 C5 00 00 00 XX XX~F0 04 C5 00 0F FF XX XX,滑杆在最下方时中间数据位是00 00 00,滑杆在最上方时,中间数据位是00 0F FF,经过测定,随着滑杆由下往上推动,数据呈现一个线性递增的状态,类似于滑动变阻器。
有了如上测定的按键信号,就算Synergy100面板处于Lost状态,仍旧能够通过相应的编程,实现对BMD切换台的控制。
3.2.2、面板锁定状态按键输出
为了要一探究竟,笔者尝试读取了Synergy100面板和Synergy1主机连接状态下,信号的输入输出状态,看看原生状态下,主机和面板通过GVG100的协议是怎么工作的。
主机和面板在发送命令的格式上相同,都是每隔15ms发送,数据格式是F0 03 C8 00 00 XX XX到F0 03 C8 FF 00 XX XX,其中00~FF是呈递增状态,XX是两个校验位;同时每隔500ms,会发发送一串以F0 01 00 D0 63为首尾的数据;主机和面板发送数据一样,可以认为主机是命令发起方,面板在接收到命令以后,返回给同样的命令。
上述发送的数据可以理解为按键的扫描周期,然后每隔500ms会发送F0 01 00 D0 63作为同步锁定,此时面板显示连接状态,同时能够记住面板上的每一个按键状态;继续测试发现,F0 03 C8 XX XX XX XX数据的第5位为00和01两个状态,其中01表示按下按键,00表示没按下按键,例如F0 03 C8 21 01 0E 2A这行数据,表示0x21号按钮已经被按下,它的状态被记住在Synergy1主机中,下次开机重启仍旧是这个状态,0x21由上述按键码描述可知,就是PGM母线上的第1个按钮;也就是说当在Synergy100面板上按下按键时,面板先会发送类似F0 02 FB/FA 20~28 XX XX字样的数据给切换台主机,主机记住了按钮状态和编号,并在按键周期内不断反馈给切换台面板。
最后,主机和面板通信的数据分析,主要集中在最后两个校验位的计算上,笔者暂时还没找到规律,这待以后的开发中还需解决,目前GVG100在Synergy系列切换台上的通信暂时研究到此。
四、总结
此次开发难度,主要还是在设备资料的接收上,BMD公司提供的API确实能满足广大开发者的二次开发,如果要弄清楚它每个API的作用和用法,估计要花上不少时间,但我们项目从实际应用出发的话,本文分析的几个API已经能够很好的解决问题了。
同时,使用BMD公司提供的API必须安装它的切换台软件系统,在安装过程中,它会自动将它的COM组件注册到Windows系统,然后通过它提供给我们的idl文件进行调用接口,对于idl怎么编写,COM怎么注册,其原理这块我也是看的云里雾里,微软的东西真的是博大精深哈。