mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-05 04:19:46 +00:00
FS-7513: add auto layout advance based on group
This commit is contained in:
parent
a56e65bace
commit
3e323e3b09
@ -178,10 +178,12 @@
|
|||||||
<!--<param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|auto-3d-position|transcode-video|minimize-video-encoding"/> -->
|
<!--<param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|auto-3d-position|transcode-video|minimize-video-encoding"/> -->
|
||||||
|
|
||||||
<!-- <param name="video-layout-name" value="3x3"/> -->
|
<!-- <param name="video-layout-name" value="3x3"/> -->
|
||||||
|
<!-- <param name="video-layout-name" value="group:grid"/> -->
|
||||||
<!-- <param name="video-canvas-size" value="1280x720"/> -->
|
<!-- <param name="video-canvas-size" value="1280x720"/> -->
|
||||||
<!-- <param name="video-canvas-bgcolor" value="#0000FF"/> -->
|
<!-- <param name="video-canvas-bgcolor" value="#0000FF"/> -->
|
||||||
<!-- <param name="video-codec-bandwidth" value="2mb"/> -->
|
<!-- <param name="video-codec-bandwidth" value="2mb"/> -->
|
||||||
|
|
||||||
|
|
||||||
<!--<param name="tts-engine" value="flite"/>-->
|
<!--<param name="tts-engine" value="flite"/>-->
|
||||||
<!--<param name="tts-voice" value="kal16"/>-->
|
<!--<param name="tts-voice" value="kal16"/>-->
|
||||||
</profile>
|
</profile>
|
||||||
|
@ -105,7 +105,7 @@
|
|||||||
<image x="300" y="300" scale="60"/>
|
<image x="300" y="300" scale="60"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="1up_top_left+5">
|
<layout name="1up_top_left+5">
|
||||||
<image x="0" y="0" scale="240" floor="true"/>
|
<image x="0" y="0" scale="240" floor="true" reservation_id="primary"/>
|
||||||
<image x="240" y="0" scale="120"/>
|
<image x="240" y="0" scale="120"/>
|
||||||
<image x="240" y="120" scale="120"/>
|
<image x="240" y="120" scale="120"/>
|
||||||
<image x="0" y="240" scale="120"/>
|
<image x="0" y="240" scale="120"/>
|
||||||
@ -113,7 +113,7 @@
|
|||||||
<image x="240" y="240" scale="120"/>
|
<image x="240" y="240" scale="120"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="1up_top_left+7">
|
<layout name="1up_top_left+7">
|
||||||
<image x="0" y="0" scale="270" floor="true"/>
|
<image x="0" y="0" scale="270" floor="true" reservation_id="primary"/>
|
||||||
<image x="270" y="0" scale="90"/>
|
<image x="270" y="0" scale="90"/>
|
||||||
<image x="270" y="90" scale="90"/>
|
<image x="270" y="90" scale="90"/>
|
||||||
<image x="270" y="180" scale="90"/>
|
<image x="270" y="180" scale="90"/>
|
||||||
@ -123,7 +123,7 @@
|
|||||||
<image x="270" y="270" scale="90"/>
|
<image x="270" y="270" scale="90"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="1up_top_left+9">
|
<layout name="1up_top_left+9">
|
||||||
<image x="0" y="0" scale="288" floor="true"/>
|
<image x="0" y="0" scale="288" floor="true" reservation_id="primary"/>
|
||||||
<image x="288" y="0" scale="72"/>
|
<image x="288" y="0" scale="72"/>
|
||||||
<image x="288" y="72" scale="72"/>
|
<image x="288" y="72" scale="72"/>
|
||||||
<image x="288" y="144" scale="72"/>
|
<image x="288" y="144" scale="72"/>
|
||||||
@ -135,7 +135,7 @@
|
|||||||
<image x="288" y="288" scale="72"/>
|
<image x="288" y="288" scale="72"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="2up_top+8">
|
<layout name="2up_top+8">
|
||||||
<image x="0" y="0" scale="180" floor="true"/>
|
<image x="0" y="0" scale="180" floor="true" reservation_id="primary"/>
|
||||||
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
||||||
<image x="0" y="180" scale="90"/>
|
<image x="0" y="180" scale="90"/>
|
||||||
<image x="90" y="180" scale="90"/>
|
<image x="90" y="180" scale="90"/>
|
||||||
@ -147,7 +147,7 @@
|
|||||||
<image x="270" y="270" scale="90"/>
|
<image x="270" y="270" scale="90"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="2up_middle+8">
|
<layout name="2up_middle+8">
|
||||||
<image x="0" y="90" scale="180" floor="true"/>
|
<image x="0" y="90" scale="180" floor="true" reservation_id="primary"/>
|
||||||
<image x="180" y="90" scale="180" reservation_id="secondary"/>
|
<image x="180" y="90" scale="180" reservation_id="secondary"/>
|
||||||
<image x="0" y="0" scale="90"/>
|
<image x="0" y="0" scale="90"/>
|
||||||
<image x="90" y="0" scale="90"/>
|
<image x="90" y="0" scale="90"/>
|
||||||
@ -159,7 +159,7 @@
|
|||||||
<image x="270" y="270" scale="90"/>
|
<image x="270" y="270" scale="90"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="2up_bottom+8">
|
<layout name="2up_bottom+8">
|
||||||
<image x="0" y="180" scale="180" floor="true"/>
|
<image x="0" y="180" scale="180" floor="true" reservation_id="primary"/>
|
||||||
<image x="180" y="180" scale="180" reservation_id="secondary"/>
|
<image x="180" y="180" scale="180" reservation_id="secondary"/>
|
||||||
<image x="0" y="0" scale="90"/>
|
<image x="0" y="0" scale="90"/>
|
||||||
<image x="90" y="0" scale="90"/>
|
<image x="90" y="0" scale="90"/>
|
||||||
@ -171,7 +171,7 @@
|
|||||||
<image x="270" y="90" scale="90"/>
|
<image x="270" y="90" scale="90"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="3up+4">
|
<layout name="3up+4">
|
||||||
<image x="0" y="0" scale="180" floor="true"/>
|
<image x="0" y="0" scale="180" floor="true" reservation_id="primary"/>
|
||||||
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
||||||
<image x="0" y="180" scale="180" reservation_id="third"/>
|
<image x="0" y="180" scale="180" reservation_id="third"/>
|
||||||
<image x="180" y="180" scale="90"/>
|
<image x="180" y="180" scale="90"/>
|
||||||
@ -180,7 +180,7 @@
|
|||||||
<image x="270" y="270" scale="90"/>
|
<image x="270" y="270" scale="90"/>
|
||||||
</layout>
|
</layout>
|
||||||
<layout name="3up+9">
|
<layout name="3up+9">
|
||||||
<image x="0" y="0" scale="180" floor="true"/>
|
<image x="0" y="0" scale="180" floor="true" reservation_id="primary"/>
|
||||||
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
<image x="180" y="0" scale="180" reservation_id="secondary"/>
|
||||||
<image x="0" y="180" scale="180" reservation_id="third"/>
|
<image x="0" y="180" scale="180" reservation_id="third"/>
|
||||||
<image x="180" y="180" scale="60"/>
|
<image x="180" y="180" scale="60"/>
|
||||||
|
@ -426,6 +426,7 @@ typedef struct conference_obj {
|
|||||||
char *record_filename;
|
char *record_filename;
|
||||||
char *outcall_templ;
|
char *outcall_templ;
|
||||||
char *video_layout_name;
|
char *video_layout_name;
|
||||||
|
char *video_layout_group;
|
||||||
char *video_canvas_bgcolor;
|
char *video_canvas_bgcolor;
|
||||||
uint32_t video_codec_bandwidth;
|
uint32_t video_codec_bandwidth;
|
||||||
uint32_t canvas_width;
|
uint32_t canvas_width;
|
||||||
@ -687,16 +688,20 @@ static switch_status_t conf_api_sub_position(conference_member_t *member, switch
|
|||||||
//#define lock_member(_member) switch_mutex_lock(_member->write_mutex)
|
//#define lock_member(_member) switch_mutex_lock(_member->write_mutex)
|
||||||
//#define unlock_member(_member) switch_mutex_unlock(_member->write_mutex)
|
//#define unlock_member(_member) switch_mutex_unlock(_member->write_mutex)
|
||||||
|
|
||||||
typedef struct layout_node_s {
|
typedef struct video_layout_s {
|
||||||
char *name;
|
char *name;
|
||||||
char *audio_position;
|
char *audio_position;
|
||||||
mcu_layer_geometry_t images[MCU_MAX_LAYERS];
|
mcu_layer_geometry_t images[MCU_MAX_LAYERS];
|
||||||
struct layout_node_s *next;
|
|
||||||
int layers;
|
int layers;
|
||||||
} layout_node_t;
|
} video_layout_t;
|
||||||
|
|
||||||
|
typedef struct video_layout_node_s {
|
||||||
|
video_layout_t *vlayout;
|
||||||
|
struct video_layout_node_s *next;
|
||||||
|
} video_layout_node_t;
|
||||||
|
|
||||||
typedef struct layout_group_s {
|
typedef struct layout_group_s {
|
||||||
layout_node_t *layouts;
|
video_layout_node_t *layouts;
|
||||||
} layout_group_t;
|
} layout_group_t;
|
||||||
|
|
||||||
static void conference_parse_layouts(conference_obj_t *conference)
|
static void conference_parse_layouts(conference_obj_t *conference)
|
||||||
@ -724,7 +729,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
|
|||||||
if ((x_layout_settings = switch_xml_child(cfg, "layout-settings"))) {
|
if ((x_layout_settings = switch_xml_child(cfg, "layout-settings"))) {
|
||||||
if ((x_layouts = switch_xml_child(x_layout_settings, "layouts"))) {
|
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) {
|
for (x_layout = switch_xml_child(x_layouts, "layout"); x_layout; x_layout = x_layout->next) {
|
||||||
layout_node_t *lnode;
|
video_layout_t *vlayout;
|
||||||
const char *val = NULL, *name = NULL;
|
const char *val = NULL, *name = NULL;
|
||||||
|
|
||||||
if ((val = switch_xml_attr(x_layout, "name"))) {
|
if ((val = switch_xml_attr(x_layout, "name"))) {
|
||||||
@ -736,8 +741,8 @@ static void conference_parse_layouts(conference_obj_t *conference)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lnode = switch_core_alloc(conference->pool, sizeof(*lnode));
|
vlayout = switch_core_alloc(conference->pool, sizeof(*vlayout));
|
||||||
lnode->name = switch_core_strdup(conference->pool, name);
|
vlayout->name = switch_core_strdup(conference->pool, name);
|
||||||
|
|
||||||
for (x_image = switch_xml_child(x_layout, "image"); x_image; x_image = x_image->next) {
|
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;
|
||||||
@ -775,33 +780,34 @@ static void conference_parse_layouts(conference_obj_t *conference)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lnode->images[lnode->layers].x = x;
|
vlayout->images[vlayout->layers].x = x;
|
||||||
lnode->images[lnode->layers].y = y;
|
vlayout->images[vlayout->layers].y = y;
|
||||||
lnode->images[lnode->layers].scale = scale;
|
vlayout->images[vlayout->layers].scale = scale;
|
||||||
lnode->images[lnode->layers].floor = floor;
|
vlayout->images[vlayout->layers].floor = floor;
|
||||||
|
|
||||||
if (res_id) {
|
if (res_id) {
|
||||||
lnode->images[lnode->layers].res_id = switch_core_strdup(conference->pool, res_id);
|
vlayout->images[vlayout->layers].res_id = switch_core_strdup(conference->pool, res_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audio_position) {
|
if (audio_position) {
|
||||||
lnode->images[lnode->layers].audio_position = switch_core_strdup(conference->pool, audio_position);
|
vlayout->images[vlayout->layers].audio_position = switch_core_strdup(conference->pool, audio_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
lnode->layers++;
|
vlayout->layers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_core_hash_insert(conference->layout_hash, name, lnode);
|
switch_core_hash_insert(conference->layout_hash, name, vlayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x_groups = switch_xml_child(cfg, "groups"))) {
|
if ((x_groups = switch_xml_child(x_layout_settings, "groups"))) {
|
||||||
for (x_group = switch_xml_child(x_groups, "group"); x_group; x_group = x_group->next) {
|
for (x_group = switch_xml_child(x_groups, "group"); x_group; x_group = x_group->next) {
|
||||||
const char *name = switch_xml_attr(x_group, "name");
|
const char *name = switch_xml_attr(x_group, "name");
|
||||||
layout_group_t *lg;
|
layout_group_t *lg;
|
||||||
|
video_layout_node_t *last_vlnode = NULL;
|
||||||
|
|
||||||
x_layout = switch_xml_child(cfg, "layout");
|
x_layout = switch_xml_child(x_group, "layout");
|
||||||
|
|
||||||
if (!name || !x_group || !x_layout) {
|
if (!name || !x_group || !x_layout) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid group\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid group\n");
|
||||||
@ -809,22 +815,30 @@ static void conference_parse_layouts(conference_obj_t *conference)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lg = switch_core_alloc(conference->pool, sizeof(*lg));
|
lg = switch_core_alloc(conference->pool, sizeof(*lg));
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding layout group %s\n", name);
|
||||||
|
switch_core_hash_insert(conference->layout_group_hash, name, lg);
|
||||||
|
|
||||||
while(x_layout) {
|
while(x_layout) {
|
||||||
const char *name = x_layout->txt;
|
const char *nname = x_layout->txt;
|
||||||
layout_node_t *lnode, *last_lnode = NULL;
|
video_layout_t *vlayout;
|
||||||
|
video_layout_node_t *vlnode;
|
||||||
|
|
||||||
if ((lnode = switch_core_hash_find(conference->layout_hash, name))) {
|
if ((vlayout = switch_core_hash_find(conference->layout_hash, nname))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding node %s to layout group %s\n", nname, name);
|
||||||
|
|
||||||
if (!lg->layouts) {
|
vlnode = switch_core_alloc(conference->pool, sizeof(*vlnode));
|
||||||
lnode = lg->layouts;
|
vlnode->vlayout = vlayout;
|
||||||
|
|
||||||
|
if (last_vlnode) {
|
||||||
|
last_vlnode->next = vlnode;
|
||||||
|
last_vlnode = last_vlnode->next;
|
||||||
} else {
|
} else {
|
||||||
lnode = last_lnode->next;
|
lg->layouts = last_vlnode = vlnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_lnode = lnode;
|
|
||||||
} else {
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid group member\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid group member %s\n", nname);
|
||||||
}
|
}
|
||||||
|
|
||||||
x_layout = x_layout->next;
|
x_layout = x_layout->next;
|
||||||
@ -1050,8 +1064,11 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
|
|||||||
conference_member_t *imember = NULL;
|
conference_member_t *imember = NULL;
|
||||||
switch_channel_t *channel = NULL;
|
switch_channel_t *channel = NULL;
|
||||||
const char *res_id = NULL;
|
const char *res_id = NULL;
|
||||||
|
|
||||||
if (!member->session) abort();
|
if (!member->session) abort();
|
||||||
|
|
||||||
|
switch_mutex_lock(member->conference->canvas->mutex);
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(member->session);
|
channel = switch_core_session_get_channel(member->session);
|
||||||
res_id = switch_channel_get_variable(channel, "video_reservation_id");
|
res_id = switch_channel_get_variable(channel, "video_reservation_id");
|
||||||
|
|
||||||
@ -1062,12 +1079,11 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
|
|||||||
|
|
||||||
if (layer->geometry.res_id || res_id) {
|
if (layer->geometry.res_id || res_id) {
|
||||||
if (!layer->geometry.res_id || !res_id || strcmp(layer->geometry.res_id, res_id)) {
|
if (!layer->geometry.res_id || !res_id || strcmp(layer->geometry.res_id, res_id)) {
|
||||||
|
switch_mutex_unlock(member->conference->canvas->mutex);
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_mutex_lock(member->conference->canvas->mutex);
|
|
||||||
|
|
||||||
if (layer->member_id && (imember = conference_member_get(member->conference, layer->member_id))) {
|
if (layer->member_id && (imember = conference_member_get(member->conference, layer->member_id))) {
|
||||||
detach_video_layer(imember);
|
detach_video_layer(imember);
|
||||||
switch_thread_rwlock_unlock(imember->rwlock);
|
switch_thread_rwlock_unlock(imember->rwlock);
|
||||||
@ -1085,20 +1101,22 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_canvas_layers(conference_obj_t *conference, layout_node_t *lnode)
|
static void init_canvas_layers(conference_obj_t *conference, video_layout_t *vlayout)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
conference_member_t *member = NULL;
|
conference_member_t *member = NULL;
|
||||||
|
|
||||||
|
if (!conference->canvas) return;
|
||||||
|
|
||||||
conference->canvas->layout_floor_id = -1;
|
conference->canvas->layout_floor_id = -1;
|
||||||
|
|
||||||
for (i = 0; i < lnode->layers; i++) {
|
for (i = 0; i < vlayout->layers; i++) {
|
||||||
mcu_layer_t *layer = &conference->canvas->layers[i];
|
mcu_layer_t *layer = &conference->canvas->layers[i];
|
||||||
|
|
||||||
layer->geometry.x = lnode->images[i].x;
|
layer->geometry.x = vlayout->images[i].x;
|
||||||
layer->geometry.y = lnode->images[i].y;
|
layer->geometry.y = vlayout->images[i].y;
|
||||||
layer->geometry.scale = lnode->images[i].scale;
|
layer->geometry.scale = vlayout->images[i].scale;
|
||||||
layer->geometry.floor = lnode->images[i].floor;
|
layer->geometry.floor = vlayout->images[i].floor;
|
||||||
layer->idx = i;
|
layer->idx = i;
|
||||||
|
|
||||||
if (layer->geometry.floor) {
|
if (layer->geometry.floor) {
|
||||||
@ -1107,8 +1125,8 @@ static void init_canvas_layers(conference_obj_t *conference, layout_node_t *lnod
|
|||||||
|
|
||||||
/* if we ever decided to reload layers config on demand the pointer assignment below will lead to segs but we
|
/* 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 */
|
only load them once forever per conference so these pointers are valid for the life of the conference */
|
||||||
layer->geometry.res_id = lnode->images[i].res_id;
|
layer->geometry.res_id = vlayout->images[i].res_id;
|
||||||
layer->geometry.audio_position = lnode->images[i].audio_position;
|
layer->geometry.audio_position = vlayout->images[i].audio_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conference->canvas->layout_floor_id > -1 &&
|
if (conference->canvas->layout_floor_id > -1 &&
|
||||||
@ -1117,10 +1135,10 @@ static void init_canvas_layers(conference_obj_t *conference, layout_node_t *lnod
|
|||||||
switch_thread_rwlock_unlock(member->rwlock);
|
switch_thread_rwlock_unlock(member->rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
conference->canvas->total_layers = lnode->layers;
|
conference->canvas->total_layers = vlayout->layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_canvas(conference_obj_t *conference, layout_node_t *lnode)
|
static void init_canvas(conference_obj_t *conference, video_layout_t *vlayout)
|
||||||
{
|
{
|
||||||
if (!conference->canvas) {
|
if (!conference->canvas) {
|
||||||
conference->canvas = switch_core_alloc(conference->pool, sizeof(*conference->canvas));
|
conference->canvas = switch_core_alloc(conference->pool, sizeof(*conference->canvas));
|
||||||
@ -1140,7 +1158,7 @@ static void init_canvas(conference_obj_t *conference, layout_node_t *lnode)
|
|||||||
|
|
||||||
switch_mutex_lock(conference->canvas->mutex);
|
switch_mutex_lock(conference->canvas->mutex);
|
||||||
set_canvas_bgcolor(conference->canvas, conference->video_canvas_bgcolor);
|
set_canvas_bgcolor(conference->canvas, conference->video_canvas_bgcolor);
|
||||||
init_canvas_layers(conference, lnode);
|
init_canvas_layers(conference, vlayout);
|
||||||
switch_mutex_unlock(conference->canvas->mutex);
|
switch_mutex_unlock(conference->canvas->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,11 +1246,26 @@ static void write_canvas_image_to_codec_group(conference_obj_t *conference, code
|
|||||||
#define MAX_MUX_CODECS 10
|
#define MAX_MUX_CODECS 10
|
||||||
//#define TRACK_FPS
|
//#define TRACK_FPS
|
||||||
|
|
||||||
|
static video_layout_t *find_best_layout(conference_obj_t *conference, layout_group_t *lg)
|
||||||
|
{
|
||||||
|
video_layout_node_t *vlnode = NULL, *last = NULL;
|
||||||
|
|
||||||
|
for (vlnode = lg->layouts; vlnode; vlnode = vlnode->next) {
|
||||||
|
if (vlnode->vlayout->layers >= conference->count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = vlnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vlnode? vlnode->vlayout : last ? last->vlayout : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thread, void *obj)
|
static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thread, void *obj)
|
||||||
{
|
{
|
||||||
conference_obj_t *conference = (conference_obj_t *) obj;
|
conference_obj_t *conference = (conference_obj_t *) obj;
|
||||||
conference_member_t *imember;
|
conference_member_t *imember;
|
||||||
layout_node_t *lnode = switch_core_hash_find(conference->layout_hash, conference->video_layout_name);
|
video_layout_t *vlayout = NULL;
|
||||||
switch_codec_t *check_codec = NULL;
|
switch_codec_t *check_codec = NULL;
|
||||||
codec_set_t *write_codecs[MAX_MUX_CODECS] = { 0 };
|
codec_set_t *write_codecs[MAX_MUX_CODECS] = { 0 };
|
||||||
int buflen = SWITCH_RECOMMENDED_BUFFER_SIZE * 2;
|
int buflen = SWITCH_RECOMMENDED_BUFFER_SIZE * 2;
|
||||||
@ -1243,15 +1276,29 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
|
|||||||
switch_time_t last_key_time = 0;
|
switch_time_t last_key_time = 0;
|
||||||
mcu_layer_t *layer = NULL;
|
mcu_layer_t *layer = NULL;
|
||||||
switch_frame_t write_frame = { 0 };
|
switch_frame_t write_frame = { 0 };
|
||||||
uint8_t *packet = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
|
uint8_t *packet = NULL;
|
||||||
|
layout_group_t *lg = NULL;
|
||||||
|
|
||||||
#ifdef TRACK_FPS
|
#ifdef TRACK_FPS
|
||||||
uint64_t frames = 0;
|
uint64_t frames = 0;
|
||||||
switch_time_t started = switch_micro_time_now();
|
switch_time_t started = switch_micro_time_now();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch_assert(lnode);
|
if (conference->video_layout_group) {
|
||||||
|
lg = switch_core_hash_find(conference->layout_group_hash, conference->video_layout_group);
|
||||||
|
vlayout = find_best_layout(conference, lg);
|
||||||
|
} else {
|
||||||
|
vlayout = switch_core_hash_find(conference->layout_hash, conference->video_layout_name);
|
||||||
|
}
|
||||||
|
|
||||||
init_canvas(conference, lnode);
|
if (!vlayout) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot find layout\n");
|
||||||
|
conference->video_layout_name = conference->video_layout_group = NULL;
|
||||||
|
switch_clear_flag(conference, CFLAG_VIDEO_MUXING);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_canvas(conference, vlayout);
|
||||||
|
|
||||||
switch_core_timer_init(&timer, "soft", 1, 90, conference->pool);
|
switch_core_timer_init(&timer, "soft", 1, 90, conference->pool);
|
||||||
|
|
||||||
@ -1277,8 +1324,9 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
|
if (!switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
|
||||||
|
packet = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
|
||||||
|
} else {
|
||||||
if (switch_channel_test_flag(ichannel, CF_VIDEO_REFRESH_REQ)) {
|
if (switch_channel_test_flag(ichannel, CF_VIDEO_REFRESH_REQ)) {
|
||||||
switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
|
switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
|
||||||
need_refresh = SWITCH_TRUE;
|
need_refresh = SWITCH_TRUE;
|
||||||
@ -1341,6 +1389,9 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
|
|||||||
used++;
|
used++;
|
||||||
|
|
||||||
switch_mutex_lock(conference->canvas->mutex);
|
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) {
|
if (imember->video_layer_id > -1) {
|
||||||
if (imember->video_layer_id >= conference->canvas->total_layers) {
|
if (imember->video_layer_id >= conference->canvas->total_layers) {
|
||||||
detach_video_layer(imember);
|
detach_video_layer(imember);
|
||||||
@ -3043,7 +3094,8 @@ static void find_video_floor(conference_member_t *member, switch_bool_t entering
|
|||||||
{
|
{
|
||||||
conference_member_t *imember;
|
conference_member_t *imember;
|
||||||
conference_obj_t *conference = member->conference;
|
conference_obj_t *conference = member->conference;
|
||||||
|
layout_group_t *lg = NULL;
|
||||||
|
video_layout_t *vlayout = NULL;
|
||||||
|
|
||||||
if (!entering) {
|
if (!entering) {
|
||||||
if (member->id == conference->video_floor_holder) {
|
if (member->id == conference->video_floor_holder) {
|
||||||
@ -3088,6 +3140,19 @@ static void find_video_floor(conference_member_t *member, switch_bool_t entering
|
|||||||
if (conference->last_video_floor_holder == conference->video_floor_holder) {
|
if (conference->last_video_floor_holder == conference->video_floor_holder) {
|
||||||
conference->last_video_floor_holder = 0;
|
conference->last_video_floor_holder = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conference->canvas && conference->video_layout_group && (lg = switch_core_hash_find(conference->layout_group_hash, conference->video_layout_group))) {
|
||||||
|
if ((vlayout = find_best_layout(conference, lg))) {
|
||||||
|
switch_mutex_lock(conference->member_mutex);
|
||||||
|
init_canvas_layers(conference, vlayout);
|
||||||
|
reset_image(conference->canvas->img, &conference->canvas->bgcolor);
|
||||||
|
switch_mutex_unlock(conference->member_mutex);
|
||||||
|
}
|
||||||
|
if (conference->canvas->layout_floor_id > -1) {
|
||||||
|
attach_video_layer(member, conference->canvas->layout_floor_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3371,9 +3436,9 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
|
|||||||
|
|
||||||
if (member->conference->canvas) {
|
if (member->conference->canvas) {
|
||||||
switch_mutex_lock(member->conference->canvas->mutex);
|
switch_mutex_lock(member->conference->canvas->mutex);
|
||||||
detach_video_layer(member);
|
if (conference->canvas->layout_floor_id > -1) {
|
||||||
detach_video_layer(imember);
|
|
||||||
attach_video_layer(member, conference->canvas->layout_floor_id);
|
attach_video_layer(member, conference->canvas->layout_floor_id);
|
||||||
|
}
|
||||||
switch_mutex_unlock(member->conference->canvas->mutex);
|
switch_mutex_unlock(member->conference->canvas->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3626,8 +3691,6 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
|||||||
|
|
||||||
lock_member(member);
|
lock_member(member);
|
||||||
|
|
||||||
detach_video_layer(member);
|
|
||||||
|
|
||||||
member_del_relationship(member, 0);
|
member_del_relationship(member, 0);
|
||||||
|
|
||||||
conference_cdr_del(member);
|
conference_cdr_del(member);
|
||||||
@ -3705,10 +3768,6 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
|||||||
member->conference->video_floor_holder = 0;
|
member->conference->video_floor_holder = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
find_video_floor(member, SWITCH_FALSE);
|
|
||||||
|
|
||||||
member->conference = NULL;
|
|
||||||
|
|
||||||
if (!switch_test_flag(member, MFLAG_NOCHANNEL)) {
|
if (!switch_test_flag(member, MFLAG_NOCHANNEL)) {
|
||||||
switch_channel_t *channel = switch_core_session_get_channel(member->session);
|
switch_channel_t *channel = switch_core_session_get_channel(member->session);
|
||||||
if (switch_test_flag(member, MFLAG_GHOST)) {
|
if (switch_test_flag(member, MFLAG_GHOST)) {
|
||||||
@ -3752,6 +3811,12 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
|||||||
switch_event_fire(&event);
|
switch_event_fire(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find_video_floor(member, SWITCH_FALSE);
|
||||||
|
detach_video_layer(member);
|
||||||
|
|
||||||
|
member->conference = NULL;
|
||||||
|
|
||||||
switch_mutex_unlock(conference->member_mutex);
|
switch_mutex_unlock(conference->member_mutex);
|
||||||
unlock_member(member);
|
unlock_member(member);
|
||||||
switch_mutex_unlock(member->audio_out_mutex);
|
switch_mutex_unlock(member->audio_out_mutex);
|
||||||
@ -7541,20 +7606,40 @@ static switch_status_t conf_api_sub_volume_out(conference_member_t *member, swit
|
|||||||
|
|
||||||
static switch_status_t conf_api_sub_vid_layout(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
|
static switch_status_t conf_api_sub_vid_layout(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
|
||||||
{
|
{
|
||||||
layout_node_t *lnode;
|
video_layout_t *vlayout = NULL;
|
||||||
|
|
||||||
if (!argv[2]) {
|
if (!argv[2]) {
|
||||||
stream->write_function(stream, "Invalid input\n");
|
stream->write_function(stream, "Invalid input\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(lnode = switch_core_hash_find(conference->layout_hash, argv[2]))) {
|
if (!strcasecmp(argv[2], "group")) {
|
||||||
|
layout_group_t *lg = NULL;
|
||||||
|
|
||||||
|
if (!argv[3]) {
|
||||||
|
stream->write_function(stream, "Group name not specified.\n");
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
if (((lg = switch_core_hash_find(conference->layout_group_hash, argv[3])))) {
|
||||||
|
vlayout = find_best_layout(conference, lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vlayout) {
|
||||||
|
stream->write_function(stream, "Invalid group layout [%s]\n", argv[3]);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vlayout && !(vlayout = switch_core_hash_find(conference->layout_hash, argv[2]))) {
|
||||||
stream->write_function(stream, "Invalid layout [%s]\n", argv[2]);
|
stream->write_function(stream, "Invalid layout [%s]\n", argv[2]);
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->write_function(stream, "Change to layout [%s]\n", vlayout->name);
|
||||||
|
|
||||||
switch_mutex_lock(conference->member_mutex);
|
switch_mutex_lock(conference->member_mutex);
|
||||||
init_canvas_layers(conference, lnode);
|
init_canvas_layers(conference, vlayout);
|
||||||
reset_image(conference->canvas->img, &conference->canvas->bgcolor);
|
reset_image(conference->canvas->img, &conference->canvas->bgcolor);
|
||||||
switch_mutex_unlock(conference->member_mutex);
|
switch_mutex_unlock(conference->member_mutex);
|
||||||
|
|
||||||
@ -10917,6 +11002,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
|||||||
char *moh_sound = NULL;
|
char *moh_sound = NULL;
|
||||||
char *outcall_templ = NULL;
|
char *outcall_templ = NULL;
|
||||||
char *video_layout_name = NULL;
|
char *video_layout_name = NULL;
|
||||||
|
char *video_layout_group = NULL;
|
||||||
char *video_canvas_size = NULL;
|
char *video_canvas_size = NULL;
|
||||||
char *video_canvas_bgcolor = NULL;
|
char *video_canvas_bgcolor = NULL;
|
||||||
char *video_codec_bandwidth = NULL;
|
char *video_codec_bandwidth = NULL;
|
||||||
@ -11262,10 +11348,20 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
|||||||
conference->video_codec_bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
|
conference->video_codec_bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_layout_name && !switch_core_hash_find(conference->layout_hash, video_layout_name)) {
|
if (video_layout_name) {
|
||||||
|
|
||||||
|
if (!strncasecmp(video_layout_name, "group:", 6)) {
|
||||||
|
if (!switch_core_hash_find(conference->layout_group_hash, video_layout_name + 6)) {
|
||||||
|
video_layout_name = NULL;
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout group settings\n");
|
||||||
|
} else {
|
||||||
|
video_layout_group = video_layout_name + 6;
|
||||||
|
}
|
||||||
|
} else if (!switch_core_hash_find(conference->layout_hash, video_layout_name)) {
|
||||||
video_layout_name = NULL;
|
video_layout_name = NULL;
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout settings\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout settings\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!video_canvas_bgcolor) {
|
if (!video_canvas_bgcolor) {
|
||||||
video_canvas_bgcolor = "#000000";
|
video_canvas_bgcolor = "#000000";
|
||||||
@ -11292,11 +11388,14 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
|||||||
if (video_layout_name) {
|
if (video_layout_name) {
|
||||||
conference->video_layout_name = switch_core_strdup(conference->pool, video_layout_name);
|
conference->video_layout_name = switch_core_strdup(conference->pool, video_layout_name);
|
||||||
}
|
}
|
||||||
|
if (video_layout_group) {
|
||||||
|
conference->video_layout_group = switch_core_strdup(conference->pool, video_layout_group);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference dimensions\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference dimensions\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (video_canvas_size || video_layout_name) {
|
} else if (video_canvas_size || video_layout_name || video_layout_group) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout settings\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout settings\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user