相关概念

avatar: 针对没有摄像头的用户,使用一个默认头像作为视频来显示,显示给其他人看。

conference flags

video-muxing-personal-canvas:只能看到自己视频(看到自己的canvas),看不到彼此。
video-bridge-first-two:适用于mux模式,如果会议室中只有2个人了,他们只能互相看到对方(应该是全屏都是对方的脸)
video-mute-exit-canvas:视频被mute的用户,就没必要显示在画布上了。
video-required-for-canvas:只显示真实的视频,不显示avatar(无摄像头用户,连个头像都不能显示,阔怜!)
minimize-video-encoding:每个通道的编码输出,都使用独立的视频编码器

avatar:相关属性变量

conference profile parameters: 针对某个会议室的无视频用户
video-no-video-avatar: Path to PNG file for member without video to display.

channel variable: 针对从某个拨号方案入会的无视频用户
video_avatar_png:Path to PNG file to use when an avatar image is needed.

基本的数据结构

会议:conference_obj(核心对象)

下面是将conference里面一些基础的属性去掉,剩下的重要对象。

  1. typedef struct conference_obj {
  2. char *name;
  3. ...
  4. switch_event_t *variables;
  5. conference_video_mode_t conference_video_mode;
  6. ...
  7. switch_codec_settings_t video_codec_settings;
  8. ...
  9. uint32_t announce_count;
  10. ...
  11. conference_flag_t flags[CFLAG_MAX];
  12. member_flag_t mflags[MFLAG_MAX];
  13. ...
  14. conference_member_t *members;
  15. ...
  16. conference_file_node_t *fnode;
  17. conference_file_node_t *async_fnode;
  18. ...
  19. switch_call_cause_t cancel_cause;
  20. conference_cdr_node_t *cdr_nodes;
  21. conference_cdr_reject_t *cdr_rejected;
  22. ...
  23. struct vid_helper vh[2];
  24. struct vid_helper mh;
  25. conference_record_t *rec_node_head;
  26. ...
  27. mcu_canvas_t *canvases[MAX_CANVASES+1];
  28. ...
  29. switch_fps_t video_fps;
  30. ...
  31. video_layout_t *new_personal_vlayout;
  32. ...
  33. } conference_obj_t;

画布:mcu_canvas_t

  1. typedef struct mcu_canvas_s {
  2. int width;
  3. int height;
  4. switch_image_t *img;
  5. mcu_layer_t layers[MCU_MAX_LAYERS];
  6. int res_count;
  7. int role_count;
  8. int total_layers;
  9. int layers_used;
  10. int layout_floor_id;
  11. int refresh;
  12. int send_keyframe;
  13. int play_file;
  14. int video_count;
  15. char *video_layout_group;
  16. switch_rgb_color_t bgcolor;
  17. switch_rgb_color_t border_color;
  18. switch_rgb_color_t letterbox_bgcolor;
  19. switch_mutex_t *mutex;
  20. switch_mutex_t *write_mutex;
  21. switch_timer_t timer;
  22. switch_memory_pool_t *pool;
  23. video_layout_t *vlayout;
  24. video_layout_t *new_vlayout;
  25. int canvas_id;
  26. struct conference_obj *conference;
  27. switch_thread_t *video_muxing_thread;
  28. int video_timer_reset;
  29. switch_queue_t *video_queue;
  30. int recording;
  31. switch_image_t *bgimg;
  32. switch_image_t *fgimg;
  33. int playing_video_file;
  34. int overlay_video_file;
  35. codec_set_t *write_codecs[MAX_MUX_CODECS];
  36. int write_codecs_count;
  37. switch_bool_t disable_auto_clear;
  38. } mcu_canvas_t;

图层:mcu_layer_t

  1. typedef struct mcu_layer_s {
  2. mcu_layer_geometry_t geometry;
  3. int member_id;
  4. int idx;
  5. int tagged;
  6. int bugged;
  7. uint32_t screen_w;
  8. uint32_t screen_h;
  9. int x_pos;
  10. int y_pos;
  11. int banner_patched;
  12. int mute_patched;
  13. int avatar_patched;
  14. int refresh;
  15. int clear;
  16. int is_avatar;
  17. int crop_x;
  18. int crop_y;
  19. int crop_w;
  20. int crop_h;
  21. int last_w;
  22. int last_h;
  23. uint32_t img_count;
  24. switch_image_t *img;
  25. switch_image_t *cur_img;
  26. switch_image_t *overlay_img;
  27. switch_image_t *banner_img;
  28. switch_image_t *logo_img;
  29. switch_image_t *mute_img;
  30. switch_img_txt_handle_t *txthandle;
  31. conference_file_node_t *fnode;
  32. switch_img_position_t logo_pos;
  33. switch_img_fit_t logo_fit;
  34. struct mcu_canvas_s *canvas;
  35. int need_patch;
  36. conference_member_t *member;
  37. switch_frame_t bug_frame;
  38. switch_frame_geometry_t last_geometry;
  39. switch_frame_geometry_t auto_geometry;
  40. switch_frame_geometry_t zoom_geometry;
  41. switch_frame_geometry_t pan_geometry;
  42. switch_frame_geometry_t manual_geometry;
  43. mcu_layer_cam_opts_t cam_opts;
  44. switch_mutex_t *overlay_mutex;
  45. switch_core_video_filter_t overlay_filters;
  46. int manual_border;
  47. } mcu_layer_t;

会议、画布、图层关系

  1. 一个会议室,包含多个画布,最多为MAX_CANVASES+1 = 21
  2. 一个画布,包含多个图层,最多为MCU_MAX_LAYERS = 64

简陋的时序图

放音方法调用时序

Conference主要数据结构 - 图1

conference_video_muxing_thread_run代码主要流程

  1. 首先来一个死循环
    1. while (conference_globals.running && !conference_utils_test_flag(conference, CFLAG_DESTRUCT) && conference_utils_test_flag(conference, CFLAG_VIDEO_MUXING)) {
    2. ...
    3. }
    只要conference模块还在跑,刚申请的会议室还么释放,会议室还是mux模式,就循环到地老天荒。

conference_function:
2456行调用conference_video_launch_muxing_write_thread

conference_video_muxing_write_thread_run:
用于启动视频帧发送线程,不断的从pop视频帧,然后发送:
pop_status = switch_frame_buffer_pop(member->fb, &pop);