FS-10121: [mod_conference] Add role-id and layout transitions to conference #resolve
This commit is contained in:
parent
c6ce9da470
commit
a62f26803e
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue