diff --git a/conf/vanilla/autoload_configs/conference.conf.xml b/conf/vanilla/autoload_configs/conference.conf.xml
index a51d568337..30664e286f 100644
--- a/conf/vanilla/autoload_configs/conference.conf.xml
+++ b/conf/vanilla/autoload_configs/conference.conf.xml
@@ -175,9 +175,12 @@
+
+
+
diff --git a/conf/vanilla/autoload_configs/conference_layouts.conf.xml b/conf/vanilla/autoload_configs/conference_layouts.conf.xml
index 0c97ac1e01..26f149deb2 100644
--- a/conf/vanilla/autoload_configs/conference_layouts.conf.xml
+++ b/conf/vanilla/autoload_configs/conference_layouts.conf.xml
@@ -105,7 +105,7 @@
-
+
@@ -113,7 +113,7 @@
-
+
@@ -123,7 +123,7 @@
-
+
@@ -135,7 +135,7 @@
-
+
@@ -147,7 +147,7 @@
-
+
@@ -159,7 +159,7 @@
-
+
@@ -171,7 +171,7 @@
-
+
@@ -180,7 +180,7 @@
-
+
diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h
index e922ff262a..4604e620b8 100644
--- a/src/include/switch_utils.h
+++ b/src/include/switch_utils.h
@@ -976,6 +976,27 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, swit
#define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)
+static inline uint32_t switch_parse_bandwidth_string(const char *bwv)
+{
+ uint32_t bw = 0;
+
+ if (!bwv) return 0;
+
+ if (bwv && (bw = (uint32_t) atol(bwv))) {
+ if (bw < 0) return 0;
+
+ if (switch_stristr("KB", bwv)) {
+ bw *= 8;
+ } else if (switch_stristr("mb", bwv)) {
+ bw *= 1024;
+ } else if (switch_stristr("MB", bwv)) {
+ bw *= 8192;
+ }
+ }
+
+ return bw;
+}
+
static inline int switch_needs_url_encode(const char *s)
{
const char hex[] = "0123456789ABCDEF";
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 80ddd0886c..42e9a446a6 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -231,8 +231,9 @@ typedef enum {
CFLAG_LIVEARRAY_SYNC = (1 << 21),
CFLAG_CONF_RESTART_AUTO_RECORD = (1 << 22),
CFLAG_POSITIONAL = (1 << 23),
- CFLAG_DECODE_VIDEO = (1 << 24),
- CFLAG_VIDEO_MUXING = (1 << 25)
+ CFLAG_TRANSCODE_VIDEO = (1 << 24),
+ CFLAG_VIDEO_MUXING = (1 << 25),
+ CFLAG_MINIMIZE_VIDEO_ENCODING = (1 << 26)
} conf_flag_t;
typedef enum {
@@ -342,6 +343,7 @@ typedef struct mcu_layer_geometry_s {
int scale;
int floor;
char *res_id;
+ char *audio_position;
} mcu_layer_geometry_t;
typedef struct mcu_layer_def_s {
@@ -352,6 +354,7 @@ typedef struct mcu_layer_def_s {
typedef struct mcu_layer_s {
mcu_layer_geometry_t geometry;
int member_id;
+ int idx;
switch_image_t *img;
switch_image_t *cur_img;
} mcu_layer_t;
@@ -370,6 +373,7 @@ typedef struct mcu_canvas_s {
mcu_layer_t layers[MCU_MAX_LAYERS];
int total_layers;
int layers_used;
+ int layout_floor_id;
bgcolor_yuv_t bgcolor;
switch_mutex_t *mutex;
switch_mutex_t *cond_mutex;
@@ -423,6 +427,7 @@ typedef struct conference_obj {
char *outcall_templ;
char *video_layout_name;
char *video_canvas_bgcolor;
+ uint32_t video_codec_bandwidth;
uint32_t canvas_width;
uint32_t canvas_height;
uint32_t terminate_on_silence;
@@ -674,7 +679,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data);
static switch_status_t conf_api_sub_vid_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data);
static switch_status_t conf_api_sub_clear_vid_floor(conference_obj_t *conference, switch_stream_handle_t *stream, void *data);
-
+static switch_status_t conf_api_sub_position(conference_member_t *member, switch_stream_handle_t *stream, void *data);
#define lock_member(_member) switch_mutex_lock(_member->write_mutex); switch_mutex_lock(_member->read_mutex)
#define unlock_member(_member) switch_mutex_unlock(_member->read_mutex); switch_mutex_unlock(_member->write_mutex)
@@ -684,6 +689,7 @@ static switch_status_t conf_api_sub_clear_vid_floor(conference_obj_t *conference
typedef struct layout_node_s {
char *name;
+ char *audio_position;
mcu_layer_geometry_t images[MCU_MAX_LAYERS];
struct layout_node_s *next;
int layers;
@@ -718,14 +724,13 @@ static void conference_parse_layouts(conference_obj_t *conference)
if ((x_layout_settings = switch_xml_child(cfg, "layout-settings"))) {
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) {
- layout_node_t *lnode;
- int x = -1, y = -1, scale = -1, floor = 0;
- const char *val, *res_id = NULL, *name = NULL;
+ layout_node_t *lnode;
+ const char *val = NULL, *name = NULL;
if ((val = switch_xml_attr(x_layout, "name"))) {
name = val;
}
-
+
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid layout\n");
continue;
@@ -735,7 +740,9 @@ static void conference_parse_layouts(conference_obj_t *conference)
lnode->name = switch_core_strdup(conference->pool, name);
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;
+
if ((val = switch_xml_attr(x_image, "x"))) {
x = atoi(val);
}
@@ -755,7 +762,13 @@ static void conference_parse_layouts(conference_obj_t *conference)
if ((val = switch_xml_attr(x_image, "reservation_id"))) {
res_id = val;
}
-
+
+ if ((val = switch_xml_attr(x_image, "audio-position"))) {
+ audio_position = val;
+ }
+
+
+
if (x < 0 || y < 0 || scale < 0 || !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid image\n");
continue;
@@ -770,7 +783,11 @@ static void conference_parse_layouts(conference_obj_t *conference)
if (res_id) {
lnode->images[lnode->layers].res_id = switch_core_strdup(conference->pool, res_id);
}
-
+
+ if (audio_position) {
+ lnode->images[lnode->layers].audio_position = switch_core_strdup(conference->pool, audio_position);
+ }
+
lnode->layers++;
}
@@ -1005,15 +1022,99 @@ static void set_canvas_bgcolor(mcu_canvas_t *canvas, char *color)
reset_image(canvas->img, &canvas->bgcolor);
}
+static void detach_video_layer(conference_member_t *member)
+{
+ mcu_layer_t *layer = NULL;
+
+ if (!member->conference->canvas || member->video_layer_id < 0) {
+ return;
+ }
+
+ layer = &member->conference->canvas->layers[member->video_layer_id];
+
+ if (layer->geometry.audio_position) {
+ conf_api_sub_position(member, NULL, "0:0:0");
+ }
+
+ switch_mutex_lock(member->conference->canvas->mutex);
+ reset_layer(member->conference->canvas, layer);
+ member->conference->canvas->layers_used--;
+ layer->member_id = 0;
+ member->video_layer_id = -1;
+ switch_mutex_unlock(member->conference->canvas->mutex);
+}
+
+static switch_status_t attach_video_layer(conference_member_t *member, int idx)
+{
+ mcu_layer_t *layer = NULL;
+ conference_member_t *imember = NULL;
+ switch_channel_t *channel = NULL;
+ const char *res_id = NULL;
+ if (!member->session) abort();
+
+ channel = switch_core_session_get_channel(member->session);
+ res_id = switch_channel_get_variable(channel, "video_reservation_id");
+
+
+ layer = &member->conference->canvas->layers[idx];
+
+ if (layer->member_id && layer->member_id == member->id) return SWITCH_STATUS_BREAK; /* no op */
+
+ if (layer->geometry.res_id || res_id) {
+ if (!layer->geometry.res_id || !res_id || strcmp(layer->geometry.res_id, res_id)) {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ switch_mutex_lock(member->conference->canvas->mutex);
+
+ if (layer->member_id && (imember = conference_member_get(member->conference, layer->member_id))) {
+ detach_video_layer(imember);
+ switch_thread_rwlock_unlock(imember->rwlock);
+ }
+
+ layer->member_id = member->id;
+ member->conference->canvas->layers_used++;
+ member->video_layer_id = idx;
+ switch_mutex_unlock(member->conference->canvas->mutex);
+
+ if (layer->geometry.audio_position) {
+ conf_api_sub_position(member, NULL, layer->geometry.audio_position);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
static void init_canvas_layers(conference_obj_t *conference, layout_node_t *lnode)
{
int i = 0;
+ conference_member_t *member = NULL;
+ conference->canvas->layout_floor_id = -1;
+
for (i = 0; i < lnode->layers; i++) {
- conference->canvas->layers[i].geometry.x = lnode->images[i].x;
- conference->canvas->layers[i].geometry.y = lnode->images[i].y;
- conference->canvas->layers[i].geometry.scale = lnode->images[i].scale;
+ mcu_layer_t *layer = &conference->canvas->layers[i];
+
+ layer->geometry.x = lnode->images[i].x;
+ layer->geometry.y = lnode->images[i].y;
+ layer->geometry.scale = lnode->images[i].scale;
+ layer->geometry.floor = lnode->images[i].floor;
+ layer->idx = i;
+
+ if (layer->geometry.floor) {
+ conference->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 = lnode->images[i].res_id;
+ layer->geometry.audio_position = lnode->images[i].audio_position;
+ }
+
+ if (conference->canvas->layout_floor_id > -1 &&
+ conference->video_floor_holder && (member = conference_member_get(conference, conference->video_floor_holder))) {
+ attach_video_layer(member, conference->canvas->layout_floor_id);
+ switch_thread_rwlock_unlock(member->rwlock);
}
conference->canvas->total_layers = lnode->layers;
@@ -1028,6 +1129,7 @@ static void init_canvas(conference_obj_t *conference, layout_node_t *lnode)
switch_mutex_init(&conference->canvas->mutex, SWITCH_MUTEX_NESTED, conference->pool);
switch_mutex_init(&conference->canvas->cond_mutex, SWITCH_MUTEX_NESTED, conference->pool);
switch_mutex_init(&conference->canvas->cond2_mutex, SWITCH_MUTEX_NESTED, conference->pool);
+ conference->canvas->layout_floor_id = -1;
}
switch_img_free(&conference->canvas->img);
@@ -1036,9 +1138,10 @@ static void init_canvas(conference_obj_t *conference, layout_node_t *lnode)
switch_assert(conference->canvas->img);
+ switch_mutex_lock(conference->canvas->mutex);
set_canvas_bgcolor(conference->canvas, conference->video_canvas_bgcolor);
-
init_canvas_layers(conference, lnode);
+ switch_mutex_unlock(conference->canvas->mutex);
}
static void destroy_canvas(mcu_canvas_t **canvasP) {
@@ -1136,9 +1239,11 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
switch_timer_t timer = { 0 };
int i = 0;
int used = 0, remaining = 0;
- uint32_t video_key_freq = 10000000;
+ uint32_t video_key_freq = 30000000;
switch_time_t last_key_time = 0;
mcu_layer_t *layer = NULL;
+ switch_frame_t write_frame = { 0 };
+ uint8_t *packet = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
#ifdef TRACK_FPS
uint64_t frames = 0;
switch_time_t started = switch_micro_time_now();
@@ -1172,46 +1277,48 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
continue;
}
+ if (switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
- if (switch_channel_test_flag(ichannel, CF_VIDEO_REFRESH_REQ)) {
- switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
- need_refresh = SWITCH_TRUE;
- }
+ if (switch_channel_test_flag(ichannel, CF_VIDEO_REFRESH_REQ)) {
+ switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
+ need_refresh = SWITCH_TRUE;
+ }
- 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;
- break;
+ 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;
+ 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, 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);
+
+ imember->video_codec_index = i;
+ imember->video_codec_id = check_codec->implementation->codec_id;
+
+ 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 = 0;
+ write_codecs[i]->frame.buflen = buflen - 12;
+ switch_set_flag((&write_codecs[i]->frame), SFF_RAW_RTP);
+
+ }
}
}
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, 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);
-
- imember->video_codec_index = i;
- imember->video_codec_id = check_codec->implementation->codec_id;
-
- 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 = 0;
- write_codecs[i]->frame.buflen = buflen - 12;
- switch_set_flag((&write_codecs[i]->frame), SFF_RAW_RTP);
-
- }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Codec Error\n");
+ continue;
}
}
- if (imember->video_codec_index < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Codec Error\n");
- continue;
- }
-
img = NULL;
size = 0;
@@ -1234,13 +1341,9 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
used++;
switch_mutex_lock(conference->canvas->mutex);
-
if (imember->video_layer_id > -1) {
if (imember->video_layer_id >= conference->canvas->total_layers) {
- conference->canvas->layers[imember->video_layer_id].member_id = 0;
- reset_layer(conference->canvas, &conference->canvas->layers[imember->video_layer_id]);
- imember->video_layer_id = -1;
- conference->canvas->layers_used--;
+ detach_video_layer(imember);
} else {
layer = &conference->canvas->layers[imember->video_layer_id];
}
@@ -1251,10 +1354,10 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
for (i = 0; i < conference->canvas->total_layers; i++) {
layer = &conference->canvas->layers[i];
if (!layer->member_id) {
- conference->canvas->layers[i].member_id = imember->id;
- conference->canvas->layers_used++;
- imember->video_layer_id = i;
- break;
+ switch_status_t lstatus = attach_video_layer(imember, i);
+ if (lstatus == SWITCH_STATUS_SUCCESS || lstatus == SWITCH_STATUS_BREAK) {
+ break;
+ }
}
}
}
@@ -1266,8 +1369,6 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
layer->cur_img = img;
scale_and_patch(conference, layer);
}
-
-
}
if (imember->session) {
@@ -1298,9 +1399,36 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
switch_core_timer_sync(&timer);
- for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) {
- write_codecs[i]->frame.img = conference->canvas->img;
- write_canvas_image_to_codec_group(conference, write_codecs[i], i, timer.samplecount, need_refresh, need_keyframe);
+ if (switch_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 = conference->canvas->img;
+ write_canvas_image_to_codec_group(conference, write_codecs[i], i, timer.samplecount, need_refresh, need_keyframe);
+ }
+ } else {
+ switch_mutex_lock(conference->member_mutex);
+ for (imember = conference->members; imember; imember = imember->next) {
+ switch_channel_t *ichannel = switch_core_session_get_channel(imember->session);
+
+ if (!imember->session || !switch_channel_test_flag(ichannel, CF_VIDEO) ||
+ switch_core_session_read_lock(imember->session) != SWITCH_STATUS_SUCCESS) {
+ continue;
+ }
+
+ switch_set_flag(&write_frame, SFF_RAW_RTP);
+ write_frame.img = conference->canvas->img;
+ write_frame.packet = packet;
+ write_frame.data = packet + 12;
+ write_frame.datalen = SWITCH_RECOMMENDED_BUFFER_SIZE - 12;
+ write_frame.buflen = write_frame.datalen;
+ write_frame.packetlen = SWITCH_RECOMMENDED_BUFFER_SIZE;
+
+ switch_core_session_write_video_frame(imember->session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
+
+ if (imember->session) {
+ switch_core_session_rwunlock(imember->session);
+ }
+ }
+ switch_mutex_unlock(conference->member_mutex);
}
}
@@ -3023,7 +3151,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
}
- if (switch_test_flag(conference, CFLAG_DECODE_VIDEO)) {
+ if (switch_test_flag(conference, CFLAG_TRANSCODE_VIDEO)) {
switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
}
@@ -3240,6 +3368,15 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
conference->last_video_floor_holder = conference->video_floor_holder;
if (conference->last_video_floor_holder && (imember = conference_member_get(conference, conference->last_video_floor_holder))) {
+
+ if (member->conference->canvas) {
+ switch_mutex_lock(member->conference->canvas->mutex);
+ detach_video_layer(member);
+ detach_video_layer(imember);
+ attach_video_layer(member, conference->canvas->layout_floor_id);
+ switch_mutex_unlock(member->conference->canvas->mutex);
+ }
+
switch_core_session_request_video_refresh(imember->session);
if (switch_test_flag(imember, MFLAG_VIDEO_BRIDGE)) {
@@ -3247,7 +3384,7 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
}
switch_thread_rwlock_unlock(imember->rwlock);
imember = NULL;
- }
+ }
old_member = conference->video_floor_holder;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Dropping video floor %d\n", old_member);
@@ -3265,6 +3402,10 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
}
}
+ if (member && conference->canvas && conference->canvas->layout_floor_id > -1) {
+ attach_video_layer(member, conference->canvas->layout_floor_id);
+ }
+
if (member) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Adding video floor %s\n",
switch_channel_get_name(member->channel));
@@ -3485,13 +3626,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
lock_member(member);
- if (member->video_layer_id > -1 && member->conference->canvas) {
- reset_layer(conference->canvas, &conference->canvas->layers[member->video_layer_id]);
- switch_mutex_lock(conference->canvas->mutex);
- conference->canvas->layers_used--;
- conference->canvas->layers[member->video_layer_id].member_id = 0;
- switch_mutex_unlock(conference->canvas->mutex);
- }
+ detach_video_layer(member);
member_del_relationship(member, 0);
@@ -7278,7 +7413,7 @@ static switch_status_t conf_api_sub_auto_position(conference_obj_t *conference,
static switch_status_t conf_api_sub_position(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
#ifndef OPENAL_POSITIONING
- stream->write_function(stream, "-ERR not supported\n");
+ if (stream) stream->write_function(stream, "-ERR not supported\n");
#else
switch_event_t *event;
@@ -9685,8 +9820,12 @@ static void set_cflags(const char *flags, uint32_t *f)
*f |= CFLAG_RFC4579;
} else if (!strcasecmp(argv[i], "auto-3d-position")) {
*f |= CFLAG_POSITIONAL;
- } else if (!strcasecmp(argv[i], "decode-video")) {
- *f |= CFLAG_DECODE_VIDEO;
+ } else if (!strcasecmp(argv[i], "decode-video") || !strcasecmp(argv[i], "transcode-video")) {
+ *f |= CFLAG_TRANSCODE_VIDEO;
+ } else if (!strcasecmp(argv[i], "minimize-video-encoding")) {
+ *f |= CFLAG_MINIMIZE_VIDEO_ENCODING;
+ } else if (!strcasecmp(argv[i], "mix-video")) {
+ *f |= CFLAG_VIDEO_MUXING;
}
@@ -10780,6 +10919,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
char *video_layout_name = NULL;
char *video_canvas_size = NULL;
char *video_canvas_bgcolor = NULL;
+ char *video_codec_bandwidth = NULL;
uint32_t max_members = 0;
uint32_t announce_count = 0;
char *maxmember_sound = NULL;
@@ -10933,6 +11073,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
video_canvas_bgcolor= val;
} else if (!strcasecmp(var, "video-canvas-size") && !zstr(val)) {
video_canvas_size = val;
+ } else if (!strcasecmp(var, "video-codec-bandwidth") && !zstr(val)) {
+ video_codec_bandwidth = val;
} else if (!strcasecmp(var, "exit-sound") && !zstr(val)) {
exit_sound = val;
} else if (!strcasecmp(var, "alone-sound") && !zstr(val)) {
@@ -11116,6 +11258,10 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
conference->broadcast_chat_messages = broadcast_chat_messages;
conference_parse_layouts(conference);
+ if (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)) {
video_layout_name = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid conference layout settings\n");
diff --git a/src/switch_core_media.c b/src/switch_core_media.c
index a807c4c777..ce10085cf4 100644
--- a/src/switch_core_media.c
+++ b/src/switch_core_media.c
@@ -2367,23 +2367,12 @@ static void switch_core_session_parse_codec_settings(switch_core_session_t *sess
case SWITCH_MEDIA_TYPE_VIDEO:
{
const char *bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth");
- uint32_t bw = 0;
-
+
if (!bwv) {
bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth_out");
}
-
-
- if (bwv && (bw = (uint32_t) atol(bwv))) {
- if (switch_stristr("KB", bwv)) {
- bw *= 8;
- } else if (switch_stristr("mb", bwv)) {
- bw *= 1024;
- } else if (switch_stristr("MB", bwv)) {
- bw *= 8192;
- }
- engine->codec_settings.video.bandwidth = bw;
- }
+
+ engine->codec_settings.video.bandwidth = switch_parse_bandwidth_string(bwv);
}
break;
default:
@@ -7291,26 +7280,12 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
}
-
- if (vbw) {
- int v = atoi(vbw);
- bw = v;
-
- if (switch_stristr("KB", vbw)) {
- bw *= 8;
- } else if (switch_stristr("mb", vbw)) {
- bw *= 1024;
- } else if (switch_stristr("MB", vbw)) {
- bw *= 8192;
- }
-
- }
+ bw = switch_parse_bandwidth_string(vbw);
if (bw > 0) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\n", bw);
//switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\n", bw);
}
-
if (sdp_type == SDP_TYPE_REQUEST) {
fir++;
diff --git a/src/switch_vidderbuffer.c b/src/switch_vidderbuffer.c
index 9553ded9ab..07c83d1933 100644
--- a/src/switch_vidderbuffer.c
+++ b/src/switch_vidderbuffer.c
@@ -191,8 +191,8 @@ static inline void add_node(switch_vb_t *vb, switch_rtp_packet_t *packet, switch
- if (vb->write_init && ((abs(htons(packet->header.seq) - htons(vb->highest_wrote_seq)) > 10) ||
- (abs(ntohl(node->packet.header.ts) - ntohl(vb->highest_wrote_ts)) > 270000))) {
+ if (vb->write_init && ((abs(htons(packet->header.seq) - htons(vb->highest_wrote_seq)) > 16) ||
+ (abs(ntohl(node->packet.header.ts) - ntohl(vb->highest_wrote_ts)) > 900000))) {
vb_debug(vb, 2, "%s", "CHANGE DETECTED, PUNT\n");
switch_vb_reset(vb);
}
@@ -408,11 +408,9 @@ SWITCH_DECLARE(uint32_t) switch_vb_pop_nack(switch_vb_t *vb)
nack = (uint32_t) htons(least);
for(i = 0; i < 16; i++) {
- if (switch_core_inthash_delete(vb->missing_seq_hash, (uint32_t)htons(least + i))) {
+ if (switch_core_inthash_delete(vb->missing_seq_hash, (uint32_t)htons(least + i + 1))) {
vb_debug(vb, 3, "Found addtl NACKABLE seq %u\n", least + i + 1);
blp |= (1 << i);
- } else {
- break;
}
}
@@ -443,18 +441,17 @@ SWITCH_DECLARE(switch_status_t) switch_vb_put_packet(switch_vb_t *vb, switch_rtp
if (!want) want = got;
if (got > want) {
+ vb_debug(vb, 2, "GOT %u WANTED %u; MARK SEQS MISSING %u - %u\n", got, want, want, got - 1);
+
for (i = want; i < got; i++) {
- vb_debug(vb, 2, "MARK SEQ MISSING %u\n", i);
switch_core_inthash_insert(vb->missing_seq_hash, (uint32_t)htons(i), (void *)SWITCH_TRUE);
}
} else {
- if (switch_core_inthash_delete(vb->missing_seq_hash, (uint32_t)htons(got))) {
- vb_debug(vb, 2, "MARK SEQ FOUND %u\n", got);
- }
+ switch_core_inthash_delete(vb->missing_seq_hash, (uint32_t)htons(got));
}
if (got >= want) {
- vb->next_seq = htons(ntohs(packet->header.seq) + 1);
+ vb->next_seq = htons(got + 1);
}
add_node(vb, packet, len);