FS-10121: [mod_conference] Add role-id and layout transitions to conference #resolve

This commit is contained in:
Anthony Minessale 2017-03-09 14:18:16 -06:00
parent c6ce9da470
commit a62f26803e
4 changed files with 124 additions and 6 deletions

View File

@ -103,6 +103,7 @@ api_command_t conference_api_sub_commands[] = {
{"vid-mute-img", (void_fn_t) & conference_api_sub_vid_mute_img, CONF_API_SUB_MEMBER_TARGET, "vid-mute-img", "<member_id|last> [<path>|clear]"},
{"vid-logo-img", (void_fn_t) & conference_api_sub_vid_logo_img, CONF_API_SUB_MEMBER_TARGET, "vid-logo-img", "<member_id|last> [<path>|clear]"},
{"vid-res-id", (void_fn_t) & conference_api_sub_vid_res_id, CONF_API_SUB_MEMBER_TARGET, "vid-res-id", "<member_id|last> <val>|clear"},
{"vid-role-id", (void_fn_t) & conference_api_sub_vid_role_id, CONF_API_SUB_MEMBER_TARGET, "vid-role-id", "<member_id|last> <val>|clear"},
{"get-uuid", (void_fn_t) & conference_api_sub_get_uuid, CONF_API_SUB_MEMBER_TARGET, "get-uuid", "<member_id|last>"},
{"clear-vid-floor", (void_fn_t) & conference_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
{"vid-layout", (void_fn_t) & conference_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>|group <group name> [<canvas id>]"},
@ -1875,6 +1876,24 @@ static void clear_res_id(conference_obj_t *conference, conference_member_t *memb
switch_mutex_unlock(conference->member_mutex);
}
static void clear_role_id(conference_obj_t *conference, conference_member_t *member, const char *id)
{
conference_member_t *imember;
switch_mutex_lock(conference->member_mutex);
for (imember = conference->members; imember; imember = imember->next) {
if (imember == member) {
continue;
}
if (imember->video_role_id && !strcasecmp(imember->video_role_id, id)) {
imember->video_role_id = NULL;
conference_video_detach_video_layer(imember);
}
}
switch_mutex_unlock(conference->member_mutex);
}
switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
char *text = (char *) data;
@ -1907,6 +1926,41 @@ switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switc
return SWITCH_STATUS_SUCCESS;
}
switch_status_t conference_api_sub_vid_role_id(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 (!member->conference->canvases[0]) {
stream->write_function(stream, "-ERR conference is not in mixing mode\n");
return SWITCH_STATUS_SUCCESS;
}
if (zstr(text) || !strcasecmp(text, "clear") || (member->video_role_id && !strcasecmp(text, member->video_role_id))) {
member->video_role_id = NULL;
stream->write_function(stream, "+OK role_id cleared\n");
} else {
clear_role_id(member->conference, member, text);
if (!member->video_role_id || strcmp(member->video_role_id, text)) {
member->video_role_id = switch_core_strdup(member->pool, text);
}
stream->write_function(stream, "+OK role_id %s\n", text);
conference_video_find_floor(member, SWITCH_FALSE);
}
return SWITCH_STATUS_SUCCESS;
}

View File

@ -197,6 +197,9 @@ void conference_member_update_status_field(conference_member_t *member)
cJSON_AddItemToObject(video, "reservationID", member->video_reservation_id ?
cJSON_CreateString(member->video_reservation_id) : cJSON_CreateNull());
cJSON_AddItemToObject(video, "roleID", member->video_role_id ?
cJSON_CreateString(member->video_role_id) : cJSON_CreateNull());
cJSON_AddItemToObject(video, "videoLayerID", cJSON_CreateNumber(member->video_layer_id));
cJSON_AddItemToObject(json, "video", video);
@ -759,6 +762,10 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
member->video_reservation_id = switch_core_strdup(member->pool, var);
}
if ((var = switch_channel_get_variable_dup(member->channel, "video_role_id", SWITCH_FALSE, -1))) {
member->video_role_id = switch_core_strdup(member->pool, var);
}
if ((var = switch_channel_get_variable(channel, "video_use_dedicated_encoder")) && switch_true(var)) {
conference_utils_member_set_flag_locked(member, MFLAG_NO_MINIMIZE_ENCODING);
}

View File

@ -110,7 +110,7 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
if ((x_layouts = switch_xml_child(x_layout_settings, "layouts"))) {
for (x_layout = switch_xml_child(x_layouts, "layout"); x_layout; x_layout = x_layout->next) {
video_layout_t *vlayout;
const char *val = NULL, *name = NULL, *bgimg = NULL, *fgimg = NULL;
const char *val = NULL, *name = NULL, *bgimg = NULL, *fgimg = NULL, *transition_in = NULL, *transition_out = NULL;
switch_bool_t auto_3d = SWITCH_FALSE;
int border = 0;
@ -128,6 +128,9 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
bgimg = switch_xml_attr(x_layout, "bgimg");
fgimg = switch_xml_attr(x_layout, "fgimg");
transition_in = switch_xml_attr(x_layout, "transition-in");
transition_out = switch_xml_attr(x_layout, "transition-out");
if ((val = switch_xml_attr(x_layout, "border"))) {
border = atoi(val);
if (border < 0) border = 0;
@ -145,8 +148,16 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
vlayout->fgimg = switch_core_strdup(conference->pool, fgimg);
}
if (transition_in) {
vlayout->transition_in = switch_core_sprintf(conference->pool, "{full-screen=true}%s", transition_in);
}
if (transition_out) {
vlayout->transition_out = switch_core_sprintf(conference->pool, "{full-screen=true}%s", transition_out);
}
for (x_image = switch_xml_child(x_layout, "image"); x_image; x_image = x_image->next) {
const char *res_id = NULL, *audio_position = NULL;
const char *res_id = NULL, *audio_position = NULL, *role_id = NULL;
int x = -1, y = -1, scale = -1, hscale = -1, floor = 0, flooronly = 0, fileonly = 0, overlap = 0, zoom = 0;
if ((val = switch_xml_attr(x_image, "x"))) {
@ -189,6 +200,14 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
res_id = val;
}
if ((val = switch_xml_attr(x_image, "reservation-id"))) {
res_id = val;
}
if ((val = switch_xml_attr(x_image, "role-id"))) {
role_id = val;
}
if ((val = switch_xml_attr(x_image, "audio-position"))) {
audio_position = val;
}
@ -231,6 +250,10 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
vlayout->images[vlayout->layers].res_id = switch_core_strdup(conference->pool, res_id);
}
if (role_id) {
vlayout->images[vlayout->layers].role_id = switch_core_strdup(conference->pool, role_id);
}
if (auto_3d || audio_position) {
if (auto_3d || !strcasecmp(audio_position, "auto")) {
int x_pos = (int)(WIDTH * x / VIDEO_LAYOUT_SCALE);
@ -1368,6 +1391,11 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
switch_mutex_lock(canvas->mutex);
canvas->layout_floor_id = -1;
if (canvas->vlayout && canvas->vlayout->transition_out) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play transition out [%s]\n", canvas->vlayout->transition_out);
conference_file_play(conference, canvas->vlayout->transition_out, 0, NULL, 0);
}
if (!vlayout) {
vlayout = canvas->new_vlayout;
canvas->new_vlayout = NULL;
@ -1417,10 +1445,11 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
if (layer->geometry.floor) {
canvas->layout_floor_id = i;
}
/* if we ever decided to reload layers config on demand the pointer assignment below will lead to segs but we
only load them once forever per conference so these pointers are valid for the life of the conference */
layer->geometry.res_id = vlayout->images[i].res_id;
layer->geometry.role_id = vlayout->images[i].role_id;
layer->geometry.audio_position = vlayout->images[i].audio_position;
}
@ -1469,6 +1498,10 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Canvas position %d applied layout %s\n", canvas->canvas_id + 1, vlayout->name);
if (vlayout->transition_in) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play transition in [%s]\n", vlayout->transition_in);
conference_file_play(conference, vlayout->transition_in, 0, NULL, 0);
}
}
switch_status_t conference_video_set_canvas_bgimg(mcu_canvas_t *canvas, const char *img_path)
@ -3014,7 +3047,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
layer = NULL;
switch_mutex_lock(canvas->mutex);
if (canvas->layout_floor_id > -1 && imember->id == conference->video_floor_holder &&
imember->video_layer_id != canvas->layout_floor_id) {
conference_video_attach_video_layer(imember, canvas, canvas->layout_floor_id);
@ -3023,8 +3056,27 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
//printf("MEMBER %d layer_id %d canvas: %d/%d\n", imember->id, imember->video_layer_id,
// canvas->layers_used, canvas->total_layers);
if (imember->video_layer_id > -1) {
if (imember->video_role_id) {
if (imember->video_layer_id > -1) {
layer = &canvas->layers[imember->video_layer_id];
}
if (!layer || (!layer->geometry.role_id || strcmp(layer->geometry.role_id, imember->video_role_id))) {
for (i = 0; i < canvas->total_layers; i++) {
mcu_layer_t *xlayer = &canvas->layers[i];
if (imember->video_role_id && xlayer->geometry.role_id && !strcmp(xlayer->geometry.role_id, imember->video_role_id)) {
conference_video_attach_video_layer(imember, canvas, i);
layer = xlayer;
}
}
}
}
if (!layer && imember->video_layer_id > -1) {
layer = &canvas->layers[imember->video_layer_id];
if (layer->member_id != (int)imember->id) {
imember->video_layer_id = -1;
layer = NULL;
@ -3530,7 +3582,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
canvas->send_keyframe = 1;
canvas->play_file = 0;
}
switch_img_free(&file_img);
file_img = write_img = write_frame.img;

View File

@ -422,6 +422,7 @@ typedef struct mcu_layer_geometry_s {
int zoom;
int border;
char *res_id;
char *role_id;
char *audio_position;
} mcu_layer_geometry_t;
@ -500,6 +501,8 @@ typedef struct video_layout_s {
char *audio_position;
char *bgimg;
char *fgimg;
char *transition_in;
char *transition_out;
mcu_layer_geometry_t images[MCU_MAX_LAYERS];
int layers;
} video_layout_t;
@ -834,6 +837,7 @@ struct conference_member {
switch_img_fit_t logo_fit;
char *video_mute_png;
char *video_reservation_id;
char *video_role_id;
switch_vid_params_t vid_params;
uint32_t auto_kps_debounce_ticks;
uint32_t layer_loops;
@ -1181,6 +1185,7 @@ switch_status_t conference_api_sub_vid_banner(conference_member_t *member, switc
switch_status_t conference_api_sub_enter_sound(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
switch_status_t conference_api_sub_set(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data);
switch_status_t conference_api_sub_vid_role_id(conference_member_t *member, switch_stream_handle_t *stream, void *data);
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);