freeswitch会议floor获取方式分析

1、设置conference->video_floor_holder成员的函数

  • conference_set_video_floor_holder(conference_obj_t *conference, conference_member_t *member, switch_bool_t force)
  • 前提是检查到该member有video视频功能。
  • 关键是函数内设置conference对象的成员这一句:conference->video_floor_holder = member;
  • 若传入的member参数为NULL,则会遍历会议中成员链表将第一个(链表是头插法故链表第一个往往是最后一个进入会议中的成员)非原video_floor_holder的成员设为新的video_floor_holder。
  • 若传入的第三参数force为true,则会设置floor锁定标志switch_set_flag(conference, CFLAG_VID_FLOOR_LOCK),若是其他地方要更改video_floor_holder则必须是在检查非锁定状态下才可以更改。
  • 函数中默认会打印DEBUG1类型的日志通知旧的和新的video_floor_holder更新。可换成INFO或者NOTIFY类型日志,更容易看到。
  • 函数末尾还会生成用户自定义事件CUSTOM::conference::maintenance下发新旧video_floor_holder更新的通知,可用事件订阅的方式获取。

2、设置conference->floor_holder成员的函数

  • conference_set_floor_holder(conference_obj_t *conference, conference_member_t *member)
  • 适用于任何有无视频功能的member。
  • 首先会检查该member是否支持video视频,若是,则也会调用conference_set_video_floor_holder函数去设置video_floor_holder。
  • 若传入的member参数为NULL,则将floor_holder也设为NULL。
  • 其他打印日志和下发事件通知功能同上。

3、通过api去修改floor拥有者

  • 控制台api命令:
    conference 3000 floor member-id
    conference 3000 vid-floor member-id [force]若是加了force则锁定该video_floor
    conference 3000 clear-vid-floor
  • 模块内函数调用逻辑:
    conf_api_sub_floor =》conference_set_floor_holder
    conf_api_sub_vid_floor =》conference_set_video_floor_holder
    conf_api_sub_clear_vid_floor =》switch_clear_flag(conference, CFLAG_VID_FLOOR_LOCK),即解除video_floor锁定

4、通过dtmf键控去修改floor拥有者

  • 可在配置文件conference.conf.xml中设置某个按键对应vid-floor-force,然后再模块源码中有一个映射表,将vid-floor-force动作对应到一个函数conference_loop_fn_vid_floor_force,该函数内部实际调用上面的conf_api_sub_vid_floor函数。

5、根据声音能量member->score_iir切换floor_holder

  • score_iir在代码开头使用宏定义设置SCORE_IIR_SPEAKING_MAX 300SCORE_IIR_SPEAKING_MIN 100,意思是一个已经获取floor的用户只有在score_iir值小于100时才会失去floor控制权,否则会先保持而不是说有其他member的值比它的大就切换。而其他用户想要获取floor,则至少要自身score_iir值大于300。这两个条件同时满足才会因为声音能量去切换floor_holder。
  • 证明,在conference_thread_run函数中对每一个收到的语音包检查(imember->score_iir > SCORE_IIR_SPEAKING_MAX && (floor_holder->score_iir < SCORE_IIR_SPEAKING_MIN)若满足条件,则会切换floor_holder。当然,若是没有旧的floor_hoder则第一个检查的member就是。
  • 关于score_iir声音能量值的修改是在函数conference_loop_input中会对每个接收的语音数据包进行分析,然后统计出声音能量值,再更新这一个member对应的score_iir成员值
    member->score_iir = (int) (((1.0 - SCORE_DECAY) * (float) member->score) + (SCORE_DECAY * (float) member->score_iir));。其中的member->score = energy / samples;而energy是对接收到的语音数据包的data的每个short两字节数据取绝对值然后统计求和,而samples是一个对应于这条channel的采样值。
  • 具体切换,也是调用conference_set_floor_holder函数。

针对项目问题解决方案:

  • 已在conference_set_video_floor_holder函数中旧的和新的video_floor_holder更新时打印INFO类型日志。可看到切换时打印的用户账号名(%s)和用户声音能量值(%d)。代码在2555行左右:
    丢弃旧的"===================================Dropping video floor %s, score_iir=%d\n"
    增加新的"===================================Adding video floor %s, score_iir=%d\n"
  • 若是video_floor_holder一直不切换,也就是视频会议一直只显示一个人的视频,那就让其他用户使用按键’#’去强制获取video_floor_holder,然后就会触发调用上面这个函数打印出以上日志。然后就可以看到一直占据video_floor_holder的用户是谁,以及他的声音能量score_iir是多少,若是该能量值一直是高于100的,那么就符合逻辑,因为只有在该能量值低于100并且同时其他会议成员的能量值高于300时才会引发切换。
  • 方案一:若是因为score_iir值一直高于100,那就只能想办法从客户端那边将话机不讲话时的score_iir控制在100以下。
  • 方案二:或者也可以通过观察打印出的日志,看看话机不讲话时score_iir的值在什么水平范围,假设一直在150左右不高于160,那么也可以在服务器的会议模块代码mod_conference.c中设置将该能量低阈值从100设置为160。具体设置很简单,只需要将代码第91行的宏定义修改为:
    #define SCORE_IIR_SPEAKING_MIN 160
    然后在mod_conference.c所在文件目录位置,执行make install 命令,重新编译安装mod_conference.c文件,并在服务器中重新加载会议模块或者重启服务器。

你可能感兴趣的:(freeswitch会议floor获取方式分析)