diff --git a/src/mod/applications/mod_conference/conference_api.c b/src/mod/applications/mod_conference/conference_api.c index 99d6d98101..c399e18365 100644 --- a/src/mod/applications/mod_conference/conference_api.c +++ b/src/mod/applications/mod_conference/conference_api.c @@ -103,6 +103,7 @@ api_command_t conference_api_sub_commands[] = { {"vid-banner", (void_fn_t) & conference_api_sub_vid_banner, CONF_API_SUB_MEMBER_TARGET, "vid-banner", " "}, {"vid-mute-img", (void_fn_t) & conference_api_sub_vid_mute_img, CONF_API_SUB_MEMBER_TARGET, "vid-mute-img", " [|clear]"}, {"vid-logo-img", (void_fn_t) & conference_api_sub_vid_logo_img, CONF_API_SUB_MEMBER_TARGET, "vid-logo-img", " [|clear]"}, + {"vid-codec-group", (void_fn_t) & conference_api_sub_vid_codec_group, CONF_API_SUB_MEMBER_TARGET, "vid-codec-group", " [|clear]"}, {"vid-res-id", (void_fn_t) & conference_api_sub_vid_res_id, CONF_API_SUB_MEMBER_TARGET, "vid-res-id", " |clear"}, {"vid-role-id", (void_fn_t) & conference_api_sub_vid_role_id, CONF_API_SUB_MEMBER_TARGET, "vid-role-id", " |clear"}, {"get-uuid", (void_fn_t) & conference_api_sub_get_uuid, CONF_API_SUB_MEMBER_TARGET, "get-uuid", ""}, @@ -1314,8 +1315,11 @@ switch_status_t conference_api_sub_vid_bandwidth(conference_obj_t *conference, s { uint32_t i; int32_t video_write_bandwidth; - int x = 0; - + int x = 0, id = -1; + char *group = NULL; + char *array[4] = {0}; + int sdiv = 0, fdiv = 0; + if (!conference_utils_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) { stream->write_function(stream, "Bandwidth control not available.\n"); return SWITCH_STATUS_SUCCESS; @@ -1325,15 +1329,87 @@ switch_status_t conference_api_sub_vid_bandwidth(conference_obj_t *conference, s stream->write_function(stream, "Invalid input\n"); return SWITCH_STATUS_SUCCESS; } + + switch_split(argv[2], ':', array); - video_write_bandwidth = switch_parse_bandwidth_string(argv[2]); - for (i = 0; i <= conference->canvas_count; i++) { - if (conference->canvases[i]) { - stream->write_function(stream, "Set Bandwidth for canvas %d to %d\n", i + 1, video_write_bandwidth); - x++; - conference->canvases[i]->video_write_bandwidth = video_write_bandwidth; + if (array[1]) { + sdiv = atoi(array[2]); + if (sdiv < 2 || sdiv > 8) { + sdiv = 0; } } + + if (array[2]) { + fdiv = atoi(array[2]); + if (fdiv < 2 || fdiv > 8) { + fdiv = 0; + } + } + + video_write_bandwidth = switch_parse_bandwidth_string(array[0]); + + if (argv[3]) { + group = argv[3]; + } + + if (argv[4]) { + + if (argv[4]) { + id = atoi(argv[4]); + } + + if (id < 1 || id > MAX_CANVASES+1) { + id = -1; + } + + if (id < 1 || id > conference->canvas_count) { + stream->write_function(stream, "-ERR Invalid canvas\n"); + goto end; + } + } + + switch_mutex_lock(conference->member_mutex); + for (i = 0; i <= conference->canvas_count; i++) { + if (i > -1 && i != id - 1) { + continue; + } + + if (conference->canvases[i]) { + mcu_canvas_t *canvas = conference->canvases[i]; + int j; + + for (j = 0; j < canvas->write_codecs_count; j++) { + if ((zstr(group) || !strcmp(group, switch_str_nil(canvas->write_codecs[j]->video_codec_group)))) { + switch_core_codec_control(&canvas->write_codecs[j]->codec, SCC_VIDEO_BANDWIDTH, + SCCT_INT, &video_write_bandwidth, SCCT_NONE, NULL, NULL, NULL); + stream->write_function(stream, "Set Bandwidth for canvas %d index %d group[%s] to %d\n", i + 1, j, + switch_str_nil(canvas->write_codecs[j]->video_codec_group), video_write_bandwidth); + + if (fdiv) { + canvas->write_codecs[j]->fps_divisor = fdiv; + } + + if (sdiv) { + int w = 0, h = 0; + + w = canvas->width; + h = canvas->width; + + w /= sdiv; + h /= sdiv; + + switch_img_free(&canvas->write_codecs[j]->scaled_img); + canvas->write_codecs[j]->scaled_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, w, h, 16); + } + + x++; + } + } + } + } + switch_mutex_unlock(conference->member_mutex); + + end: if (!x) { stream->write_function(stream, "Bandwidth not set\n"); @@ -1903,6 +1979,39 @@ switch_status_t conference_api_sub_vid_logo_img(conference_member_t *member, swi } + +switch_status_t conference_api_sub_vid_codec_group(conference_member_t *member, switch_stream_handle_t *stream, void *data) +{ + char *text = (char *) data; + + if (member == NULL) + return SWITCH_STATUS_GENERR; + + if (!switch_channel_test_flag(member->channel, CF_VIDEO)) { + return SWITCH_STATUS_FALSE; + } + + if (text) { + + if (!strcmp(text, "clear")) { + member->video_codec_group = NULL; + } else { + member->video_codec_group = switch_core_strdup(member->pool, text); + } + + switch_mutex_lock(member->conference->member_mutex); + member->video_codec_index = -1; + switch_mutex_unlock(member->conference->member_mutex); + stream->write_function(stream, "Video codec group %s %s\n", member->video_codec_group ? "set" : "cleared", switch_str_nil(member->video_codec_group)); + } else { + stream->write_function(stream, "Video codec group is %s\n", member->video_codec_group); + } + + + return SWITCH_STATUS_SUCCESS; + +} + switch_status_t conference_api_sub_get_uuid(conference_member_t *member, switch_stream_handle_t *stream, void *data) { if (member->session) { diff --git a/src/mod/applications/mod_conference/conference_member.c b/src/mod/applications/mod_conference/conference_member.c index b197a891ec..cfbc4c30d8 100644 --- a/src/mod/applications/mod_conference/conference_member.c +++ b/src/mod/applications/mod_conference/conference_member.c @@ -745,6 +745,10 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m conference_member_set_logo(member, var); } + if ((var = switch_channel_get_variable_dup(member->channel, "video_codec_group", SWITCH_FALSE, -1))) { + member->video_codec_group = switch_core_strdup(member->pool, var); + } + if ((var = switch_channel_get_variable_dup(member->channel, "conference_join_volume_in", SWITCH_FALSE, -1))) { uint32_t id = atoi(var); diff --git a/src/mod/applications/mod_conference/conference_video.c b/src/mod/applications/mod_conference/conference_video.c index ff63f750f2..6dee4c851d 100644 --- a/src/mod/applications/mod_conference/conference_video.c +++ b/src/mod/applications/mod_conference/conference_video.c @@ -1755,11 +1755,15 @@ void conference_video_write_canvas_image_to_codec_group(conference_obj_t *confer if (imember->watching_canvas_id != canvas->canvas_id) { continue; } - + if (conference_utils_member_test_flag(imember, MFLAG_NO_MINIMIZE_ENCODING)) { continue; } + if (codec_set->video_codec_group && (!imember->video_codec_group || strcmp(codec_set->video_codec_group, imember->video_codec_group))) { + continue; + } + if (imember->video_codec_index != codec_index) { continue; } @@ -2854,7 +2858,6 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr conference_obj_t *conference = canvas->conference; conference_member_t *imember; switch_codec_t *check_codec = NULL; - codec_set_t *write_codecs[MAX_MUX_CODECS] = { 0 }; int buflen = SWITCH_RTP_MAX_BUF_LEN; int i = 0; uint32_t video_key_freq = 10000000; @@ -3056,35 +3059,66 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr if (switch_channel_test_flag(imember->channel, CF_VIDEO_READY)) { if (imember->video_codec_index < 0 && (check_codec = switch_core_session_get_video_write_codec(imember->session))) { - for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { - if (check_codec->implementation->codec_id == write_codecs[i]->codec.implementation->codec_id) { - imember->video_codec_index = i; - imember->video_codec_id = check_codec->implementation->codec_id; - need_refresh = SWITCH_TRUE; - break; + for (i = 0; canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { + if (check_codec->implementation->codec_id == canvas->write_codecs[i]->codec.implementation->codec_id) { + if ((zstr(imember->video_codec_group) && zstr(canvas->write_codecs[i]->video_codec_group)) || + (!strcmp(switch_str_nil(imember->video_codec_group), switch_str_nil(canvas->write_codecs[i]->video_codec_group)))) { + + imember->video_codec_index = i; + imember->video_codec_id = check_codec->implementation->codec_id; + need_refresh = SWITCH_TRUE; + break; + } } } - + if (imember->video_codec_index < 0) { - write_codecs[i] = switch_core_alloc(conference->pool, sizeof(codec_set_t)); + canvas->write_codecs[i] = switch_core_alloc(conference->pool, sizeof(codec_set_t)); + canvas->write_codecs_count = i+1; - if (switch_core_codec_copy(check_codec, &write_codecs[i]->codec, + if (switch_core_codec_copy(check_codec, &canvas->write_codecs[i]->codec, &conference->video_codec_settings, conference->pool) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Setting up video write codec %s at slot %d\n", write_codecs[i]->codec.implementation->iananame, i); - + "Setting up video write codec %s at slot %d group %s\n", + canvas->write_codecs[i]->codec.implementation->iananame, i, + imember->video_codec_group ? imember->video_codec_group : "_none_"); + imember->video_codec_index = i; imember->video_codec_id = check_codec->implementation->codec_id; need_refresh = SWITCH_TRUE; - write_codecs[i]->frame.packet = switch_core_alloc(conference->pool, buflen); - write_codecs[i]->frame.data = ((uint8_t *)write_codecs[i]->frame.packet) + 12; - write_codecs[i]->frame.packetlen = buflen; - write_codecs[i]->frame.buflen = buflen - 12; + if (imember->video_codec_group) { + const char *gname = switch_core_sprintf(conference->pool, "group-%s", imember->video_codec_group); + const char *val = NULL; + + canvas->write_codecs[i]->video_codec_group = switch_core_strdup(conference->pool, imember->video_codec_group); + + if ((val = conference_get_variable(conference, gname))) { + switch_stream_handle_t stream = { 0 }; + char *argv[5] = {0}; + char cid[32] = ""; + + SWITCH_STANDARD_STREAM(stream); + switch_snprintf(cid, sizeof(cid), "%d", canvas->canvas_id + 1); + + argv[2] = (char *)val; + argv[3] = imember->video_codec_group; + argv[4] = cid; + conference_api_sub_vid_bandwidth(conference, &stream, 5, argv); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "codec group init [%s]\n", (char *)stream.data); + free(stream.data); + } + + } + canvas->write_codecs[i]->frame.packet = switch_core_alloc(conference->pool, buflen); + canvas->write_codecs[i]->frame.data = ((uint8_t *)canvas->write_codecs[i]->frame.packet) + 12; + canvas->write_codecs[i]->frame.packetlen = buflen; + canvas->write_codecs[i]->frame.buflen = buflen - 12; if (conference->scale_h264_canvas_width > 0 && conference->scale_h264_canvas_height > 0 && !strcmp(check_codec->implementation->iananame, "H264")) { int32_t bw = -1; - write_codecs[i]->fps_divisor = conference->scale_h264_canvas_fps_divisor; - write_codecs[i]->scaled_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, conference->scale_h264_canvas_width, conference->scale_h264_canvas_height, 16); + canvas->write_codecs[i]->fps_divisor = conference->scale_h264_canvas_fps_divisor; + canvas->write_codecs[i]->scaled_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, conference->scale_h264_canvas_width, conference->scale_h264_canvas_height, 16); if (conference->scale_h264_canvas_bandwidth) { if (strcasecmp(conference->scale_h264_canvas_bandwidth, "auto")) { @@ -3095,14 +3129,14 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr if (bw == -1) { float fps = conference->video_fps.fps; - if (write_codecs[i]->fps_divisor) fps /= write_codecs[i]->fps_divisor; + if (canvas->write_codecs[i]->fps_divisor) fps /= canvas->write_codecs[i]->fps_divisor; bw = switch_calc_bitrate(conference->scale_h264_canvas_width, conference->scale_h264_canvas_height, conference->video_quality, fps); } - switch_core_codec_control(&write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, &bw, SCCT_NONE, NULL, NULL, NULL); + switch_core_codec_control(&canvas->write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, &bw, SCCT_NONE, NULL, NULL, NULL); } - switch_set_flag((&write_codecs[i]->frame), SFF_RAW_RTP); + switch_set_flag((&canvas->write_codecs[i]->frame), SFF_RAW_RTP); } } @@ -3796,17 +3830,10 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr } if (min_members && conference_utils_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) { - for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { - write_codecs[i]->frame.img = write_img; - conference_video_write_canvas_image_to_codec_group(conference, canvas, write_codecs[i], i, + for (i = 0; canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { + canvas->write_codecs[i]->frame.img = write_img; + conference_video_write_canvas_image_to_codec_group(conference, canvas, canvas->write_codecs[i], i, timestamp, need_refresh, send_keyframe, need_reset); - - if (canvas->video_write_bandwidth) { - switch_core_codec_control(&write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, - SCCT_INT, &canvas->video_write_bandwidth, SCCT_NONE, NULL, NULL, NULL); - canvas->video_write_bandwidth = 0; - } - } } @@ -3894,9 +3921,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr } for (i = 0; i < MAX_MUX_CODECS; i++) { - if (write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec)) { - switch_core_codec_destroy(&write_codecs[i]->codec); - switch_img_free(&(write_codecs[i]->scaled_img)); + if (canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec)) { + switch_core_codec_destroy(&canvas->write_codecs[i]->codec); + switch_img_free(&(canvas->write_codecs[i]->scaled_img)); } } @@ -3935,7 +3962,6 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_ conference_obj_t *conference = canvas->conference; conference_member_t *imember; switch_codec_t *check_codec = NULL; - codec_set_t *write_codecs[MAX_MUX_CODECS] = { 0 }; int buflen = SWITCH_RTP_MAX_BUF_LEN; int i = 0; switch_time_t last_key_time = 0; @@ -4046,31 +4072,63 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_ if (switch_channel_test_flag(imember->channel, CF_VIDEO_READY)) { if (imember->video_codec_index < 0 && (check_codec = switch_core_session_get_video_write_codec(imember->session))) { - for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { - if (check_codec->implementation->codec_id == write_codecs[i]->codec.implementation->codec_id) { - imember->video_codec_index = i; - imember->video_codec_id = check_codec->implementation->codec_id; - need_refresh = SWITCH_TRUE; - break; + for (i = 0; canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { + if (check_codec->implementation->codec_id == canvas->write_codecs[i]->codec.implementation->codec_id) { + if ((zstr(imember->video_codec_group) && zstr(canvas->write_codecs[i]->video_codec_group)) || + (!strcmp(switch_str_nil(imember->video_codec_group), switch_str_nil(canvas->write_codecs[i]->video_codec_group)))) { + + imember->video_codec_index = i; + imember->video_codec_id = check_codec->implementation->codec_id; + need_refresh = SWITCH_TRUE; + break; + } } } - + if (imember->video_codec_index < 0) { - write_codecs[i] = switch_core_alloc(conference->pool, sizeof(codec_set_t)); - - if (switch_core_codec_copy(check_codec, &write_codecs[i]->codec, + canvas->write_codecs[i] = switch_core_alloc(conference->pool, sizeof(codec_set_t)); + canvas->write_codecs_count = i+1; + + if (switch_core_codec_copy(check_codec, &canvas->write_codecs[i]->codec, &conference->video_codec_settings, conference->pool) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Setting up video write codec %s at slot %d\n", write_codecs[i]->codec.implementation->iananame, i); - + "Setting up video write codec %s at slot %d group %s\n", + canvas->write_codecs[i]->codec.implementation->iananame, i, + imember->video_codec_group ? imember->video_codec_group : "_none_"); + imember->video_codec_index = i; imember->video_codec_id = check_codec->implementation->codec_id; need_refresh = SWITCH_TRUE; - write_codecs[i]->frame.packet = switch_core_alloc(conference->pool, buflen); - write_codecs[i]->frame.data = ((uint8_t *)write_codecs[i]->frame.packet) + 12; - write_codecs[i]->frame.packetlen = buflen; - write_codecs[i]->frame.buflen = buflen - 12; - switch_set_flag((&write_codecs[i]->frame), SFF_RAW_RTP); + if (imember->video_codec_group) { + canvas->write_codecs[i]->video_codec_group = switch_core_strdup(conference->pool, imember->video_codec_group); + } + canvas->write_codecs[i]->frame.packet = switch_core_alloc(conference->pool, buflen); + canvas->write_codecs[i]->frame.data = ((uint8_t *)canvas->write_codecs[i]->frame.packet) + 12; + canvas->write_codecs[i]->frame.packetlen = buflen; + canvas->write_codecs[i]->frame.buflen = buflen - 12; + if (conference->scale_h264_canvas_width > 0 && conference->scale_h264_canvas_height > 0 && !strcmp(check_codec->implementation->iananame, "H264")) { + int32_t bw = -1; + + canvas->write_codecs[i]->fps_divisor = conference->scale_h264_canvas_fps_divisor; + canvas->write_codecs[i]->scaled_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, conference->scale_h264_canvas_width, conference->scale_h264_canvas_height, 16); + + if (conference->scale_h264_canvas_bandwidth) { + if (strcasecmp(conference->scale_h264_canvas_bandwidth, "auto")) { + bw = switch_parse_bandwidth_string(conference->scale_h264_canvas_bandwidth); + } + } + + if (bw == -1) { + float fps = conference->video_fps.fps; + + if (canvas->write_codecs[i]->fps_divisor) fps /= canvas->write_codecs[i]->fps_divisor; + + bw = switch_calc_bitrate(conference->scale_h264_canvas_width, conference->scale_h264_canvas_height, conference->video_quality, fps); + } + + switch_core_codec_control(&canvas->write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, &bw, SCCT_NONE, NULL, NULL, NULL); + } + switch_set_flag((&canvas->write_codecs[i]->frame), SFF_RAW_RTP); } } @@ -4154,15 +4212,9 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_ } if (min_members && conference_utils_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) { - for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { - write_codecs[i]->frame.img = write_img; - conference_video_write_canvas_image_to_codec_group(conference, canvas, write_codecs[i], i, timestamp, need_refresh, send_keyframe, need_reset); - - if (canvas->video_write_bandwidth) { - switch_core_codec_control(&write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, - SCCT_INT, &canvas->video_write_bandwidth, SCCT_NONE, NULL, NULL, NULL); - canvas->video_write_bandwidth = 0; - } + for (i = 0; canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) { + canvas->write_codecs[i]->frame.img = write_img; + conference_video_write_canvas_image_to_codec_group(conference, canvas, canvas->write_codecs[i], i, timestamp, need_refresh, send_keyframe, need_reset); } } @@ -4241,8 +4293,8 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_ } for (i = 0; i < MAX_MUX_CODECS; i++) { - if (write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec)) { - switch_core_codec_destroy(&write_codecs[i]->codec); + if (canvas->write_codecs[i] && switch_core_codec_ready(&canvas->write_codecs[i]->codec)) { + switch_core_codec_destroy(&canvas->write_codecs[i]->codec); } } diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 55e517ffd3..a15a5fc34d 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -843,6 +843,9 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob switch_core_hash_destroy(&conference->layout_group_hash); } + switch_mutex_lock(conference->flag_mutex); + switch_event_destroy(&conference->variables); + switch_mutex_unlock(conference->flag_mutex); if (conference->pool) { switch_memory_pool_t *pool = conference->pool; @@ -2550,6 +2553,28 @@ conference_obj_t *conference_find(char *name, char *domain) return conference; } +void conference_set_variable(conference_obj_t *conference, const char *var, const char *val) +{ + switch_mutex_lock(conference->flag_mutex); + switch_event_add_header_string(conference->variables, SWITCH_STACK_BOTTOM, var, val); + switch_mutex_unlock(conference->flag_mutex); +} + +const char *conference_get_variable(conference_obj_t *conference, const char *var) +{ + const char *val; + + switch_mutex_lock(conference->flag_mutex); + val = switch_event_get_header(conference->variables, var); + switch_mutex_unlock(conference->flag_mutex); + + if (val) { + return switch_core_strdup(conference->pool, val); + } + + return NULL; +} + /* create a new conferene with a specific profile */ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_core_session_t *session, switch_memory_pool_t *pool) { @@ -3070,7 +3095,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co conference->broadcast_chat_messages = broadcast_chat_messages; conference->video_quality = conference_video_quality; conference->auto_kps_debounce = auto_kps_debounce; - + switch_event_create_plain(&conference->variables, SWITCH_EVENT_CHANNEL_DATA); conference->conference_video_mode = conference_video_mode; conference->scale_h264_canvas_width = scale_h264_canvas_width; @@ -3567,7 +3592,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co if (conference->conference_video_mode == CONF_VIDEO_MODE_MUX) { video_layout_t *vlayout = conference_video_get_layout(conference, conference->video_layout_name, conference->video_layout_group); - + if (!vlayout) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot find layout\n"); conference->video_layout_name = conference->video_layout_group = NULL; @@ -3598,6 +3623,28 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co switch_mutex_unlock(conference->canvas_mutex); } } + + if (cfg.profile) { + for (xml_kvp = switch_xml_child(cfg.profile, "video-codec-group"); xml_kvp; xml_kvp = xml_kvp->next) { + char *name = (char *) switch_xml_attr_soft(xml_kvp, "name"); + char *bw = (char *) switch_xml_attr_soft(xml_kvp, "bandwidth"); + char *fps = (char *) switch_xml_attr_soft(xml_kvp, "fps-divisor"); + char *res = (char *) switch_xml_attr_soft(xml_kvp, "res-divisor"); + + if (name && bw) { + const char *str = switch_core_sprintf(conference->pool, "%s%s%s%s%s", bw, + !zstr(res) ? ":" : "", res, !zstr(fps) ? ":" : "", fps); + + const char *gname = switch_core_sprintf(conference->pool, "group-%s", name); + + conference_set_variable(conference, gname, str); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video codec group preset %s set to [%s]\n", gname, str); + } + + } + + } + } } diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h index 668b95cf6a..8fc46bb40e 100644 --- a/src/mod/applications/mod_conference/mod_conference.h +++ b/src/mod/applications/mod_conference/mod_conference.h @@ -105,7 +105,7 @@ #define CONFFUNCAPISIZE (sizeof(conference_api_sub_commands)/sizeof(conference_api_sub_commands[0])) -#define MAX_MUX_CODECS 10 +#define MAX_MUX_CODECS 50 #define ALC_HRTF_SOFT 0x1992 @@ -521,6 +521,17 @@ typedef struct layout_group_s { video_layout_node_t *layouts; } layout_group_t; +typedef struct codec_set_s { + switch_codec_t codec; + switch_frame_t frame; + uint8_t *packet; + switch_image_t *scaled_img; + uint8_t fps_divisor; + uint32_t frame_count; + char *video_codec_group; +} codec_set_t; + + typedef struct mcu_canvas_s { int width; int height; @@ -549,13 +560,14 @@ typedef struct mcu_canvas_s { switch_thread_t *video_muxing_thread; int video_timer_reset; switch_queue_t *video_queue; - int32_t video_write_bandwidth; int recording; switch_image_t *bgimg; switch_image_t *fgimg; switch_thread_rwlock_t *video_rwlock; int playing_video_file; int overlay_video_file; + codec_set_t *write_codecs[MAX_MUX_CODECS]; + int write_codecs_count; } mcu_canvas_t; /* Record Node */ @@ -620,6 +632,7 @@ typedef struct conference_obj { char *video_letterbox_bgcolor; char *video_mute_banner; char *no_video_avatar; + switch_event_t *variables; conference_video_mode_t conference_video_mode; int video_quality; int members_with_video; @@ -847,6 +860,7 @@ struct conference_member { char *video_mute_png; char *video_reservation_id; char *video_role_id; + char *video_codec_group; switch_vid_params_t vid_params; uint32_t auto_kps_debounce_ticks; uint32_t layer_loops; @@ -897,15 +911,6 @@ typedef struct api_command { char *psyntax; } api_command_t; -typedef struct codec_set_s { - switch_codec_t codec; - switch_frame_t frame; - uint8_t *packet; - switch_image_t *scaled_img; - uint8_t fps_divisor; - uint32_t frame_count; -} codec_set_t; - typedef void (*conference_key_callback_t) (conference_member_t *, struct caller_control_actions *); typedef struct { @@ -1200,6 +1205,7 @@ switch_status_t conference_api_sub_vid_role_id(conference_member_t *member, swit switch_status_t conference_api_sub_get_uuid(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_get(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_vid_mute_img(conference_member_t *member, switch_stream_handle_t *stream, void *data); +switch_status_t conference_api_sub_vid_codec_group(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_vid_logo_img(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_vid_fps(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_canvas_fgimg(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); @@ -1262,7 +1268,8 @@ void conference_loop_exec_app(conference_member_t *member, caller_control_action void conference_loop_deaf_toggle(conference_member_t *member, caller_control_action_t *action); void conference_loop_deaf_on(conference_member_t *member, caller_control_action_t *action); void conference_loop_deaf_off(conference_member_t *member, caller_control_action_t *action); - +void conference_set_variable(conference_obj_t *conference, const char *var, const char *val); +const char *conference_get_variable(conference_obj_t *conference, const char *var); /* Global Structs */ diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 3f0cf8b61a..2b1181d638 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -41,7 +41,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_verto_runtime); SWITCH_MODULE_DEFINITION(mod_verto, mod_verto_load, mod_verto_shutdown, mod_verto_runtime); #define EP_NAME "verto.rtc" -#define WSS_STANDALONE 1 +//#define WSS_STANDALONE 1 #include "ws.h" //////////////////////////