之前讨论的思路:
- 让每一个会议成员的结构体conference_member_t对象中增加一个链表,保存多个要订阅这个成员视频数据的其他成员对象的指针。
- 但是这样做有一个问题,显然某成员只能订阅另外一个成员的视频而不能同时订阅多个,因此上面这种订阅记录方式有可能导致订阅多个,额外增加判断方式也麻烦。
- 另一个麻烦在于使用键控时是操作的当前这个用户线程,而若是要成功实现订阅却要在当前用户线程修改其他用户的数据,会增加锁的使用和复杂度。
- 方便之处在于遍历读取视频数据到该成员时,能够很方便的将该视频数据转发给订阅了的其他成员。
换一种思路:
- 在每一个会议member的结构体中增加一个
conference_member_t *target_video_member;
变量,代表该成员想订阅的目标成员。
- 如果该目标成员指针为NULL,说明没有想要特殊订阅的,那就按照正常逻辑去获取video_floor_holder成员的视频数据。
- 如果有想订阅的目标成员,那就去获取这个目标成员的当前一帧视频数据。
- 首先用一个for循环遍历读取每个会议成员的一帧视频数据,然后保存到该member的结构体对象中。
- 再用一个for循环遍历各个成员,根据订阅的目标成员去读取对应的视频数据。
- 以上代码修改主要在
conference_video_thread_run
函数中。
如何绑定按键订阅指定用户的问题?
- 在
conference_loop_input
函数中,会对应每个member开启的一个线程,去循环接收按键控制信息。比如在客户端按键'0',则在该函数中会接收到dtmf字符'0',然后转到调用switch_ivr_dmachine_feed
函数将字符传到switch_ivr_dmachine_ping
函数去检查该字符是否有匹配的执行动作函数调用,若是找到了那就执行该动作函数。
- 键控字符和执行动作有一个对应的结构体映射表:
static struct _mapping control_mappings[] = {
{"mute", conference_loop_fn_mute_toggle},
...
{"vid-floor-force", conference_loop_fn_vid_floor_force}
};
- 然后在
member_bind_controls
函数中,会读取conference.conf.xml配置文件中指定的按键字符和对应的动作配置,然后绑定上面的回调函数。
<caller-controls>
<group name="default">
<control action="mute" digits="0"/>
...
<control action="vid-floor-force" digits="#"/>
</group>
</caller-controls>
- 因此,若要新增订阅指定会议成员的视频键控功能,需要在以上几个地方进行修改,新增一个执行键控动作的回调函数。