视频会议订阅:
- 在每一个会议member的结构体中增加一个
conference_member_t *target_video_member;
变量,代表该成员想订阅的目标成员。 - 如果该目标成员指针为NULL,说明没有想要特殊订阅的,那就按照正常逻辑去获取video_floor_holder成员的视频数据。如果有想订阅的目标成员,那就去获取这个目标成员的当前一帧视频数据。
- 代码修改主要在
conference_video_thread_run
函数中,使用条件编译将原来的视频会议逻辑保留。 - 首先用一个for循环遍历读取每个会议成员的一帧视频数据,然后保存到该member的结构体对象中的
switch_frame_t video_frame;
变量中,具体的视频数据保存到char video_frame_packet[65535];
变量中。 - 再用一个for循环遍历各个成员,根据订阅的目标成员去读取对应的视频数据。
API设计:
-
conference 会议室 subscribe <member_id|user_id> <target member_id|user_id>
如conference 7000 subscribe 1003 1006
表示用户1003要订阅用户1006的视频
如conference 7000 subscribe 2 3
表示会议成员2要订阅成员3的视频 - 以上区分是用户号码还是成员号,是用的999作为分界数字,低于999的认为是member_id,高于999的认为是user_id。然后分别根据这两个id去获取对应的member对象,然后去修改第一个member对象的内容,将第二个member对象作为它的target_video_member。
- 首先要在
conf_api_sub_commands[]
这个数组中增加一个新的api_command_t结构体数据
{ "subscribe", (void_fn_t)& conf_api_sub_subscribe, CONF_API_SUB_MEMBER_TARGET, "subscribe", "<member_id1|user_id1> <member_id2|user_id2>"}
- 然后执行一个conference API时会由
conf_api_main
函数转到conf_api_dispatch
函数,在这里要增加上面所说的根据第一个member_id或user_id获取第一个member对象的逻辑。 - 接着就转到API结构体数据中,绑定的回调函数
conf_api_sub_subscribe(conference_member_t *member, switch_stream_handle_t *stream, void *data)
。传入的member参数就是第一个member对象,传入的data是第二个member_id或user_id。然后根据data参数去获取对应的member对象作为第一个member对象的target_video_member,即member->target_video_member = target_video_member;
。 - 其中为了方便,新增加了根据用户号码user_id获取到member对象的函数
conference_member_get_by_user_id
。
测试结果
- 各种途径的API调用都能够成功修改member对象的订阅目标,并打印一些通知信息。
- 在视频数据接收和转发的过程中,member对象中的订阅目标也会随着API的调用立即改变。
- 但是,视频转发只在video_floor_holder那边稳定;单独订阅的目标的视频不稳定,只能偶尔看到视频数据。可见视频数据接收和转发逻辑内部还是有问题。