summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bridges/bridge_softmix.c33
-rw-r--r--include/asterisk/bridging.h13
-rw-r--r--main/bridging.c48
3 files changed, 87 insertions, 7 deletions
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 8828d640a..00b0556d0 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -435,13 +435,30 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann
}
}
-static void softmix_pass_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
{
struct ast_bridge_channel *tmp;
AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
if (tmp->suspended) {
continue;
}
+ if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) {
+ ast_write(tmp->chan, frame);
+ break;
+ }
+ }
+}
+
+static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame, int echo)
+{
+ struct ast_bridge_channel *tmp;
+ AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
+ if (tmp->suspended) {
+ continue;
+ }
+ if ((tmp->chan == bridge_channel->chan) && !echo) {
+ continue;
+ }
ast_write(tmp->chan, frame);
}
}
@@ -472,20 +489,26 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
/* Determine if this video frame should be distributed or not */
if (frame->frametype == AST_FRAME_VIDEO) {
+ int num_src = ast_bridge_number_video_src(bridge);
+ int video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
+
switch (bridge->video_mode.mode) {
case AST_BRIDGE_VIDEO_MODE_NONE:
break;
case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
- if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) {
- softmix_pass_video(bridge, bridge_channel, frame);
+ if (video_src_priority == 1) {
+ softmix_pass_video_all(bridge, bridge_channel, frame, 1);
}
break;
case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
ast_mutex_lock(&sc->lock);
ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan, sc->video_talker.energy_average, ast_format_get_video_mark(&frame->subclass.format));
ast_mutex_unlock(&sc->lock);
- if (ast_bridge_is_video_src(bridge, bridge_channel->chan)) {
- softmix_pass_video(bridge, bridge_channel, frame);
+ if (video_src_priority == 1) {
+ int echo = num_src > 1 ? 0 : 1;
+ softmix_pass_video_all(bridge, bridge_channel, frame, echo);
+ } else if (video_src_priority == 2) {
+ softmix_pass_video_top_priority(bridge, frame);
}
break;
}
diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h
index 849f88741..54137b028 100644
--- a/include/asterisk/bridging.h
+++ b/include/asterisk/bridging.h
@@ -190,6 +190,9 @@ struct ast_bridge_video_talker_src_data {
/*! Only accept video coming from this channel */
struct ast_channel *chan_vsrc;
int average_talking_energy;
+
+ /*! Current talker see's this person */
+ struct ast_channel *chan_old_vsrc;
};
struct ast_bridge_video_mode {
@@ -528,7 +531,17 @@ void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge);
void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyfame);
/*!
+ * \brief Returns the number of video sources currently active in the bridge
+ */
+int ast_bridge_number_video_src(struct ast_bridge *bridge);
+
+/*!
* \brief Determine if a channel is a video src for the bridge
+ *
+ * \retval 0 Not a current video source of the bridge.
+ * \retval None 0, is a video source of the bridge, The number
+ * returned represents the priority this video stream has
+ * on the bridge where 1 is the highest priority.
*/
int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan);
diff --git a/main/bridging.c b/main/bridging.c
index 1563e4789..835a849fb 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -1489,6 +1489,9 @@ static void cleanup_video_mode(struct ast_bridge *bridge)
if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc);
}
+ if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+ ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc);
+ }
}
memset(&bridge->video_mode, 0, sizeof(bridge->video_mode));
}
@@ -1525,20 +1528,51 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a
if (data->chan_vsrc == chan) {
data->average_talking_energy = talker_energy;
} else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
+ if (data->chan_old_vsrc) {
+ ast_channel_unref(data->chan_old_vsrc);
+ }
if (data->chan_vsrc) {
- ast_channel_unref(data->chan_vsrc);
+ data->chan_old_vsrc = data->chan_vsrc;
+ ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE);
}
data->chan_vsrc = ast_channel_ref(chan);
data->average_talking_energy = talker_energy;
- ast_indicate(chan, AST_CONTROL_VIDUPDATE);
} else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
ast_indicate(chan, AST_CONTROL_VIDUPDATE);
} else if (!data->chan_vsrc && is_keyframe) {
data->chan_vsrc = ast_channel_ref(chan);
data->average_talking_energy = talker_energy;
ast_indicate(chan, AST_CONTROL_VIDUPDATE);
+ } else if (!data->chan_old_vsrc && is_keyframe) {
+ data->chan_old_vsrc = ast_channel_ref(chan);
+ ast_indicate(chan, AST_CONTROL_VIDUPDATE);
+ }
+ ao2_unlock(bridge);
+}
+
+int ast_bridge_number_video_src(struct ast_bridge *bridge)
+{
+ int res = 0;
+
+ ao2_lock(bridge);
+ switch (bridge->video_mode.mode) {
+ case AST_BRIDGE_VIDEO_MODE_NONE:
+ break;
+ case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
+ if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) {
+ res = 1;
+ }
+ break;
+ case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
+ if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
+ res++;
+ }
+ if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+ res++;
+ }
}
ao2_unlock(bridge);
+ return res;
}
int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
@@ -1557,7 +1591,10 @@ int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) {
res = 1;
+ } else if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
+ res = 2;
}
+
}
ao2_unlock(bridge);
return res;
@@ -1583,6 +1620,13 @@ void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *
ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc);
}
bridge->video_mode.mode_data.talker_src_data.chan_vsrc = NULL;
+ bridge->video_mode.mode_data.talker_src_data.average_talking_energy = 0;
+ }
+ if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
+ if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
+ ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc);
+ }
+ bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc = NULL;
}
}
ao2_unlock(bridge);