[asterisk-commits] dvossel: branch dvossel/shortbus r324845 - in /team/dvossel/shortbus: apps/ a...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jun 24 12:50:18 CDT 2011
Author: dvossel
Date: Fri Jun 24 12:50:14 2011
New Revision: 324845
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=324845
Log:
Confbridge video_mode options for distributing single src of video to all participants.
Modified:
team/dvossel/shortbus/apps/app_confbridge.c
team/dvossel/shortbus/apps/confbridge/conf_config_parser.c
team/dvossel/shortbus/apps/confbridge/include/confbridge.h
team/dvossel/shortbus/bridges/bridge_softmix.c
team/dvossel/shortbus/configs/confbridge.conf.sample
team/dvossel/shortbus/include/asterisk/bridging.h
team/dvossel/shortbus/main/bridging.c
Modified: team/dvossel/shortbus/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/apps/app_confbridge.c?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/apps/app_confbridge.c (original)
+++ team/dvossel/shortbus/apps/app_confbridge.c Fri Jun 24 12:50:14 2011
@@ -614,6 +614,72 @@
return res;
}
+static int conf_member_is_video_capable(struct conference_bridge_user *conference_bridge_user)
+{
+ if (!ast_format_cap_has_type(conference_bridge_user->chan->nativeformats, AST_FORMAT_TYPE_VIDEO)) {
+ return 0;
+ }
+ if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
+ return 0;
+ }
+ return 1;
+}
+
+static void handle_video_on_join(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+{
+ if (!conf_member_is_video_capable(conference_bridge_user)) {
+ return;
+ }
+
+ if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
+ int set = 1;
+ struct conference_bridge_user *tmp_user = NULL;
+ ao2_lock(conference_bridge);
+ /* see if anyone is already the video src */
+ AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) {
+ if (tmp_user == conference_bridge_user) {
+ continue;
+ }
+ if (conf_member_is_video_capable(tmp_user)) {
+ set = 0;
+ break;
+ }
+ }
+ ao2_unlock(conference_bridge);
+ if (set) {
+ ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan);
+ }
+ } else if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
+ /* we joined and are video capable, we override anyone else that may have already been the video feed */
+ ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan);
+ }
+}
+
+static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+{
+ struct conference_bridge_user *tmp_user = NULL;
+ if (!conf_member_is_video_capable(conference_bridge_user)) {
+ return;
+ }
+
+ /* if this isn't a video source, nothing to update */
+ if (!ast_bridge_is_video_src(conference_bridge->bridge, conference_bridge_user->chan)) {
+ return;
+ }
+
+ /* Make the next avaliable participant capable of video the src. */
+ ao2_lock(conference_bridge);
+ AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) {
+ if (tmp_user == conference_bridge_user) {
+ continue;
+ }
+ if (conf_member_is_video_capable(tmp_user)) {
+ ast_bridge_set_single_src_video_mode(conference_bridge->bridge, conference_bridge_user->chan);
+ }
+ }
+ ao2_unlock(conference_bridge);
+}
+
/*!
* \brief Perform post-joining marked specific actions
*
@@ -627,7 +693,8 @@
if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
struct conference_bridge_user *other_conference_bridge_user = NULL;
- /* If we are not the first marked user to join just bail out now */
+ /* If we are not the first user to join, then the users are already
+ * in the conference so we do not need to update them. */
if (conference_bridge->markedusers >= 2) {
return 0;
}
@@ -664,7 +731,6 @@
other_conference_bridge_user->features.mute = 0;
}
}
-
} else {
/* If a marked user already exists in the conference bridge we can just bail out now */
if (conference_bridge->markedusers) {
@@ -1370,6 +1436,8 @@
}
}
+ handle_video_on_join(conference_bridge, &conference_bridge_user);
+
/* Join our conference bridge for real */
send_join_event(conference_bridge_user.chan, conference_bridge->name);
ast_bridge_join(conference_bridge->bridge,
@@ -1378,6 +1446,9 @@
&conference_bridge_user.features,
&conference_bridge_user.tech_args);
send_leave_event(conference_bridge_user.chan, conference_bridge->name);
+
+
+ handle_video_on_exit(conference_bridge, &conference_bridge_user);
/* if this user has a intro, play it when leaving */
if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) {
Modified: team/dvossel/shortbus/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/apps/confbridge/conf_config_parser.c?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/apps/confbridge/conf_config_parser.c (original)
+++ team/dvossel/shortbus/apps/confbridge/conf_config_parser.c Fri Jun 24 12:50:14 2011
@@ -284,6 +284,12 @@
}
} else if (!strcasecmp(name, "record_conference")) {
ast_set2_flag(b_profile, ast_true(value), BRIDGE_OPT_RECORD_CONFERENCE);
+ } else if (!strcasecmp(name, "video_mode")) {
+ if (!strcasecmp(value, "first_marked")) {
+ ast_set_flag(b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED);
+ } else if (!strcasecmp(value, "last_marked")) {
+ ast_set_flag(b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED);
+ }
} else if (!strcasecmp(name, "max_members")) {
if (sscanf(value, "%30u", &b_profile->max_members) != 1) {
return -1;
@@ -983,6 +989,14 @@
ast_cli(a->fd,"Max Members: No Limit\n");
}
+ if (b_profile.flags & BRIDGE_OPT_VIDEO_SRC_LAST_MARKED) {
+ ast_cli(a->fd, "Video Mode: last_marked\n");
+ } else if (b_profile.flags & BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) {
+ ast_cli(a->fd, "Video Mode: first_marked\n");
+ } else {
+ ast_cli(a->fd, "Video Mode: no video\n");
+ }
+
ast_cli(a->fd,"sound_join: %s\n", conf_get_sound(CONF_SOUND_JOIN, b_profile.sounds));
ast_cli(a->fd,"sound_leave: %s\n", conf_get_sound(CONF_SOUND_LEAVE, b_profile.sounds));
ast_cli(a->fd,"sound_only_person: %s\n", conf_get_sound(CONF_SOUND_ONLY_PERSON, b_profile.sounds));
Modified: team/dvossel/shortbus/apps/confbridge/include/confbridge.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/apps/confbridge/include/confbridge.h?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/apps/confbridge/include/confbridge.h (original)
+++ team/dvossel/shortbus/apps/confbridge/include/confbridge.h Fri Jun 24 12:50:14 2011
@@ -61,6 +61,8 @@
enum bridge_profile_flags {
BRIDGE_OPT_RECORD_CONFERENCE = (1 << 0), /*!< Set if the conference should be recorded */
+ BRIDGE_OPT_VIDEO_SRC_LAST_MARKED = (1 << 1), /*!< Set if conference should feed video of last marked user to all participants. */
+ BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED = (1 << 2), /*!< Set if conference should feed video of first marked user to all participants. */
};
enum conf_menu_action_id {
Modified: team/dvossel/shortbus/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/bridges/bridge_softmix.c?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/bridges/bridge_softmix.c (original)
+++ team/dvossel/shortbus/bridges/bridge_softmix.c Fri Jun 24 12:50:14 2011
@@ -419,6 +419,17 @@
}
}
+static void softmix_pass_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+ struct ast_bridge_channel *tmp;
+ AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
+ if (tmp->suspended) {
+ continue;
+ }
+ ast_write(tmp->chan, frame);
+ }
+}
+
/*! \brief Function called when a channel writes a frame into the bridge */
static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
{
@@ -434,12 +445,26 @@
/* Only accept audio frames, all others are unsupported */
if (frame->frametype == AST_FRAME_DTMF_END || frame->frametype == AST_FRAME_DTMF_BEGIN) {
softmix_pass_dtmf(bridge, bridge_channel, frame);
- goto no_audio;
- } else if (frame->frametype != AST_FRAME_VOICE) {
+ goto bridge_write_cleanup;
+ } else if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO) {
res = AST_BRIDGE_WRITE_UNSUPPORTED;
- goto no_audio;
+ goto bridge_write_cleanup;
} else if (frame->datalen == 0) {
- goto no_audio;
+ goto bridge_write_cleanup;
+ }
+
+ /* Determine if this video frame should be distributed or not */
+ if (frame->frametype == AST_FRAME_VIDEO) {
+ 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);
+ }
+ break;
+ }
+ goto bridge_write_cleanup;
}
/* If we made it here, we are going to write the frame into the conference */
@@ -487,7 +512,7 @@
return res;
-no_audio:
+bridge_write_cleanup:
/* Even though the frame is not being written into the conference because it is not audio,
* we should use this opportunity to check to see if a frame is ready to be written out from
* the conference to the channel. */
@@ -817,7 +842,7 @@
static struct ast_bridge_technology softmix_bridge = {
.name = "softmix",
- .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED | AST_BRIDGE_CAPABILITY_OPTIMIZE,
+ .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED | AST_BRIDGE_CAPABILITY_OPTIMIZE | AST_BRIDGE_CAPABILITY_VIDEO,
.preference = AST_BRIDGE_PREFERENCE_LOW,
.create = softmix_bridge_create,
.destroy = softmix_bridge_destroy,
Modified: team/dvossel/shortbus/configs/confbridge.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/configs/confbridge.conf.sample?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/configs/confbridge.conf.sample (original)
+++ team/dvossel/shortbus/configs/confbridge.conf.sample Fri Jun 24 12:50:14 2011
@@ -167,6 +167,20 @@
; be chosen. Using a larger mixing interval comes at the cost of introducing
; larger amounts of delay into the bridge. Valid values here are 10, 20, 40,
; or 80. By default 20ms is used.
+
+;video_mode = first_marked ; Sets how confbridge handles video distribution to the conference participants.
+ ; --- MODES ---
+ ; none: No video is allowed into the conference. This is the default value.
+ ;
+ ; last_marked: The last marked user to join the conference with video capabilities
+ ; will be the single source of video distributed to all participants.
+ ; If multiple marked users are capable of video, the last one to join
+ ; is always the source, when that user leaves it goes to the one who
+ ; joined before them.
+ ;
+ ; first_marked: The first marked user to join the conference with video capabilities
+ ; is the single source of video distribution among all participants. If
+ ; that user leaves, the marked user to join after them becomes the source.
; All sounds in the conference are customizable using the bridge profile options below.
; Simply state the option followed by the filename or full path of the filename after
Modified: team/dvossel/shortbus/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/include/asterisk/bridging.h?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/include/asterisk/bridging.h (original)
+++ team/dvossel/shortbus/include/asterisk/bridging.h Fri Jun 24 12:50:14 2011
@@ -180,7 +180,7 @@
struct ast_bridge_video_single_src_data {
/*! Only accept video coming from this channel */
- struct ast_channel *src_chan;
+ struct ast_channel *chan_vsrc;
};
struct ast_bridge_video_mode {
@@ -501,6 +501,16 @@
*/
void ast_bridge_set_mixing_interval(struct ast_bridge *bridge, unsigned int mixing_interval);
+/*!
+ * \brief Set a bridge to feed a single video source to all participants.
+ */
+void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan);
+
+/*!
+ * \brief Determine if a channel is a video src for the bridge
+ */
+int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
Modified: team/dvossel/shortbus/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/shortbus/main/bridging.c?view=diff&rev=324845&r1=324844&r2=324845
==============================================================================
--- team/dvossel/shortbus/main/bridging.c (original)
+++ team/dvossel/shortbus/main/bridging.c Fri Jun 24 12:50:14 2011
@@ -50,6 +50,8 @@
/* Grow rate of bridge array of channels */
#define BRIDGE_ARRAY_GROW 32
+static void cleanup_video_mode(struct ast_bridge *bridge);
+
/*! Default DTMF keys for built in features */
static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING];
@@ -456,6 +458,8 @@
/* Drop the array of channels */
ast_free(bridge->array);
+
+ cleanup_video_mode(bridge);
return;
}
@@ -1470,3 +1474,44 @@
bridge->internal_sample_rate = sample_rate;
ao2_unlock(bridge);
}
+
+static void cleanup_video_mode(struct ast_bridge *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) {
+ ast_channel_unref(bridge->video_mode.mode_data.single_src_data.chan_vsrc);
+ }
+ break;
+ }
+ memset(&bridge->video_mode, 0, sizeof(bridge->video_mode));
+}
+
+void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
+{
+ ao2_lock(bridge);
+ cleanup_video_mode(bridge);
+ bridge->video_mode.mode = AST_BRIDGE_VIDEO_MODE_SINGLE_SRC;
+ bridge->video_mode.mode_data.single_src_data.chan_vsrc = ast_channel_ref(video_src_chan);
+ ao2_unlock(bridge);
+}
+
+int ast_bridge_is_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
+{
+ 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 == chan) {
+ res = 1;
+ }
+ break;
+ }
+ ao2_unlock(bridge);
+ return res;
+}
More information about the asterisk-commits
mailing list