FS-7513: improve reservation id and layout switching with overlap

This commit is contained in:
Anthony Minessale 2015-02-18 20:27:08 -06:00 committed by Michael Jerris
parent 93b3a946ec
commit 270aba6849
1 changed files with 97 additions and 18 deletions

View File

@ -366,6 +366,7 @@ typedef struct mcu_layer_geometry_s {
int y;
int scale;
int floor;
int overlap;
char *res_id;
char *audio_position;
} mcu_layer_geometry_t;
@ -627,6 +628,7 @@ struct conference_member {
char *video_banner_text;
char *video_logo;
char *video_mute_png;
char *video_reservation_id;
};
typedef enum {
@ -763,6 +765,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
{
switch_event_t *params;
switch_xml_t cxml = NULL, cfg = NULL, x_layouts, x_layout, x_layout_settings, x_group, x_groups, x_image;
char cmd_str[256] = "";
if (!conference->layout_hash) {
switch_core_hash_init(&conference->layout_hash);
@ -801,7 +804,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
for (x_image = switch_xml_child(x_layout, "image"); x_image; x_image = x_image->next) {
const char *res_id = NULL, *audio_position = NULL;
int x = -1, y = -1, scale = -1, floor = 0;
int x = -1, y = -1, scale = -1, floor = 0, overlap = 0;
if ((val = switch_xml_attr(x_image, "x"))) {
x = atoi(val);
@ -818,6 +821,10 @@ static void conference_parse_layouts(conference_obj_t *conference)
if ((val = switch_xml_attr(x_image, "floor"))) {
floor = switch_true(val);
}
if ((val = switch_xml_attr(x_image, "overlap"))) {
overlap = switch_true(val);
}
if ((val = switch_xml_attr(x_image, "reservation_id"))) {
res_id = val;
@ -838,6 +845,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
vlayout->images[vlayout->layers].y = y;
vlayout->images[vlayout->layers].scale = scale;
vlayout->images[vlayout->layers].floor = floor;
vlayout->images[vlayout->layers].overlap = overlap;
if (res_id) {
vlayout->images[vlayout->layers].res_id = switch_core_strdup(conference->pool, res_id);
@ -851,6 +859,8 @@ static void conference_parse_layouts(conference_obj_t *conference)
}
switch_core_hash_insert(conference->layout_hash, name, vlayout);
switch_snprintf(cmd_str, sizeof(cmd_str), "add conference ::conference::list_conferences vid-layout %s", name);
switch_console_set_complete(cmd_str);
}
}
@ -1248,7 +1258,6 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
{
mcu_layer_t *layer = NULL;
switch_channel_t *channel = NULL;
const char *res_id = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *var = NULL;
switch_rgb_color_t color;
@ -1257,6 +1266,7 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
channel = switch_core_session_get_channel(member->session);
if (!switch_channel_test_flag(channel, CF_VIDEO)) {
return SWITCH_STATUS_FALSE;
}
@ -1264,12 +1274,24 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
switch_mutex_lock(member->conference->canvas->mutex);
layer = &member->conference->canvas->layers[idx];
layer->tagged = 0;
if (layer->geometry.res_id) {
if (!member->video_reservation_id || strcmp(layer->geometry.res_id, member->video_reservation_id)) {
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
if (layer->member_id && layer->member_id == member->id) {
member->video_layer_id = idx;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
if (layer->geometry.res_id || member->video_reservation_id) {
if (!layer->geometry.res_id || !member->video_reservation_id || strcmp(layer->geometry.res_id, member->video_reservation_id)) {
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
if (member->video_layer_id > -1) {
detach_video_layer(member);
@ -1277,14 +1299,6 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
reset_layer(member->conference->canvas, layer);
switch_img_free(&layer->mute_img);
res_id = switch_channel_get_variable_dup(channel, "video_reservation_id", SWITCH_FALSE, -1);
if (layer->geometry.res_id || res_id) {
if (!layer->geometry.res_id || !res_id || strcmp(layer->geometry.res_id, res_id)) {
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
var = NULL;
if (member->video_banner_text || (var = switch_channel_get_variable_dup(channel, "video_banner_text", SWITCH_FALSE, -1))) {
@ -1331,6 +1345,7 @@ static void init_canvas_layers(conference_obj_t *conference, video_layout_t *vla
layer->geometry.y = vlayout->images[i].y;
layer->geometry.scale = vlayout->images[i].scale;
layer->geometry.floor = vlayout->images[i].floor;
layer->geometry.overlap = vlayout->images[i].overlap;
layer->idx = i;
@ -1651,7 +1666,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
switch_mutex_lock(conference->canvas->mutex);
//printf("MEMBER %d layer_id %d canvas: %d/%d\n", imember->id, imember->video_layer_id,
// conference->canvas->layers_used, conference->canvas->total_layers);
if (imember->video_layer_id > -1) {
layer = &conference->canvas->layers[imember->video_layer_id];
if (layer->member_id != imember->id) {
@ -1663,10 +1678,21 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
if (!layer && conference->canvas->layers_used < conference->canvas->total_layers) {
/* find an empty layer */
for (i = 0; i < conference->canvas->total_layers; i++) {
layer = &conference->canvas->layers[i];
if (!layer->member_id) {
switch_status_t lstatus = attach_video_layer(imember, i);
mcu_layer_t *xlayer = &conference->canvas->layers[i];
if (xlayer->geometry.res_id) {
if (imember->video_reservation_id && !strcmp(xlayer->geometry.res_id, imember->video_reservation_id)) {
layer = xlayer;
attach_video_layer(imember, i);
break;
}
} else if (!xlayer->member_id) {
switch_status_t lstatus;
lstatus = attach_video_layer(imember, i);
if (lstatus == SWITCH_STATUS_SUCCESS || lstatus == SWITCH_STATUS_BREAK) {
layer = xlayer;
break;
}
}
@ -1716,7 +1742,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
for (i = 0; i < conference->canvas->total_layers; i++) {
mcu_layer_t *layer = &conference->canvas->layers[i];
if (layer->member_id > -1 && layer->cur_img && layer->tagged) {
if (layer->member_id > -1 && layer->cur_img && (layer->tagged || layer->geometry.overlap)) {
scale_and_patch(conference, layer, NULL);
layer->tagged = 0;
}
@ -3547,6 +3573,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
member->video_mute_png = switch_core_strdup(member->pool, var);
}
if ((var = switch_channel_get_variable_dup(member->channel, "video_reservation_id", SWITCH_FALSE, -1))) {
member->video_reservation_id = switch_core_strdup(member->pool, var);
}
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
switch_channel_set_variable_printf(channel, "conference_ghost", "%s", switch_test_flag(member, MFLAG_GHOST) ? "true" : "false");
@ -8140,6 +8170,17 @@ static switch_status_t conf_api_sub_vid_layout(conference_obj_t *conference, swi
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[2], "list")) {
switch_hash_index_t *hi;
void *val;
const void *vvar;
for (hi = switch_core_hash_first(conference->layout_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
stream->write_function(stream, "%s\n", (char *)vvar);
}
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[2], "group")) {
layout_group_t *lg = NULL;
@ -8425,15 +8466,15 @@ static switch_status_t conf_api_sub_vid_logo_img(conference_member_t *member, sw
return SWITCH_STATUS_FALSE;
}
switch_mutex_lock(member->conference->canvas->mutex);
if (member->video_layer_id == -1 || !member->conference->canvas) {
goto end;
}
switch_mutex_lock(member->conference->canvas->mutex);
layer = &member->conference->canvas->layers[member->video_layer_id];
if (!strcasecmp(text, "clear")) {
if (strcasecmp(text, "clear")) {
member->video_logo = switch_core_strdup(member->pool, text);
}
@ -8449,6 +8490,43 @@ static switch_status_t conf_api_sub_vid_logo_img(conference_member_t *member, sw
}
static switch_status_t conf_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
char *text = (char *) data;
//mcu_layer_t *layer = NULL;
if (member == NULL)
return SWITCH_STATUS_GENERR;
if (!switch_channel_test_flag(member->channel, CF_VIDEO)) {
return SWITCH_STATUS_FALSE;
}
if (!member->conference->canvas) {
stream->write_function(stream, "-ERR conference is not in mixing mode\n");
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(member->conference->canvas->mutex);
//layer = &member->conference->canvas->layers[member->video_layer_id];
if (!strcasecmp(text, "clear")) {
member->video_reservation_id = NULL;
stream->write_function(stream, "+OK reservation_id cleared\n");
} else {
member->video_reservation_id = switch_core_strdup(member->pool, text);
stream->write_function(stream, "+OK reservation_id %s\n", text);
}
detach_video_layer(member);
switch_mutex_unlock(member->conference->canvas->mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t conf_api_sub_vid_banner(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
mcu_layer_t *layer = NULL;
@ -9919,6 +9997,7 @@ static api_command_t conf_api_sub_commands[] = {
{"vid-banner", (void_fn_t) & conf_api_sub_vid_banner, CONF_API_SUB_MEMBER_TARGET, "vid-banner", "<member_id|last> <text>"},
{"vid-mute-img", (void_fn_t) & conf_api_sub_vid_mute_img, CONF_API_SUB_MEMBER_TARGET, "vid-mute-img", "<member_id|last> [<path>|clear]"},
{"vid-logo-img", (void_fn_t) & conf_api_sub_vid_logo_img, CONF_API_SUB_MEMBER_TARGET, "vid-logo-img", "<member_id|last> [<path>|clear]"},
{"vid-res-id", (void_fn_t) & conf_api_sub_vid_res_id, CONF_API_SUB_MEMBER_TARGET, "vid-res-id", "<member_id|last> <val>|clear"},
{"clear-vid-floor", (void_fn_t) & conf_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
{"vid-layout", (void_fn_t) & conf_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>"},
{"vid-write-png", (void_fn_t) & conf_api_sub_write_png, CONF_API_SUB_ARGS_SPLIT, "vid-write-png", "<path>"},