[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