[svn-commits] file: branch file/bridge_unreal r410301 - in /team/file/bridge_unreal: bridge...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Mar 8 12:40:45 CST 2014


Author: file
Date: Sat Mar  8 12:40:41 2014
New Revision: 410301

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410301
Log:
Add the bridge_unreal module itself with minor core_unreal mods.

The bridge_unreal module takes a different approach to optimizing channels.
Instead of attempting to collapse a chain of channels down it takes the
approach of an eventual optimization of the frame path itself. This is much
less intrusive and complicated with similar end result.

Added:
    team/file/bridge_unreal/bridges/bridge_unreal.c   (with props)
Modified:
    team/file/bridge_unreal/include/asterisk/core_unreal.h
    team/file/bridge_unreal/main/core_unreal.c

Added: team/file/bridge_unreal/bridges/bridge_unreal.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal/bridges/bridge_unreal.c?view=auto&rev=410301
==============================================================================
--- team/file/bridge_unreal/bridges/bridge_unreal.c (added)
+++ team/file/bridge_unreal/bridges/bridge_unreal.c Sat Mar  8 12:40:41 2014
@@ -1,0 +1,251 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Unreal channel bridging optimization module
+ *
+ * \author Joshua Colp <jcolp at digium.com>
+ *
+ * \ingroup bridges
+ */
+
+/*** MODULEINFO
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "asterisk/module.h"
+#include "asterisk/channel.h"
+#include "asterisk/bridge.h"
+#include "asterisk/bridge_technology.h"
+#include "asterisk/frame.h"
+#include "asterisk/core_unreal.h"
+
+/*!
+ * \internal
+ * \brief Check if channel is compatible.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Is this channel compatible.
+ *
+ * \retval TRUE if channel is compatible with native DAHDI bridge.
+ */
+static int native_bridge_is_capable(struct ast_bridge_channel *bridge_channel)
+{
+	struct ast_channel *chan = bridge_channel->chan;
+
+	ast_channel_lock(chan);
+
+	if (ast_channel_tech(chan)->write != ast_unreal_write) {
+		ast_debug(2, "Channel '%s' is not unreal.\n", ast_channel_name(chan));
+		ast_channel_unlock(chan);
+		return 0;
+	}
+
+	if (ast_channel_has_audio_frame_or_monitor(chan)) {
+		ast_debug(2, "Channel '%s' has an active monitor, audiohook, or framehook.\n",
+			ast_channel_name(chan));
+		ast_channel_unlock(chan);
+		return 0;
+	}
+
+	ast_channel_unlock(chan);
+
+	return 1;
+}
+
+static int unreal_bridge_compatible(struct ast_bridge *bridge)
+{
+	struct ast_bridge_channel *cur;
+
+	/* We require two channels before even considering native bridging. */
+	if (bridge->num_channels != 2) {
+		ast_debug(1, "Bridge %s: Cannot use native unreal.  Must have two channels.\n",
+			bridge->uniqueid);
+		return 0;
+	}
+
+	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
+		if (!native_bridge_is_capable(cur)) {
+			ast_debug(1, "Bridge %s: Cannot use native unreal.  Channel '%s' not compatible.\n",
+				bridge->uniqueid, ast_channel_name(cur->chan));
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*! \brief Helper function which notifies that a source update has occurred */
+static void unreal_bridge_notify_source_update(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+	static struct ast_frame f = {
+		.frametype = AST_FRAME_CONTROL,
+		.subclass.integer = AST_CONTROL_SRCUPDATE,
+	};
+
+	ast_bridge_queue_everyone_else(bridge, bridge_channel, &f);
+}
+
+/*! \brief Helper function which retrieves the channel that should be connected to */
+static struct ast_channel *unreal_get_channel_to_connect_to(struct ast_bridge_channel *bridge_channel)
+{
+	struct ast_unreal_pvt *pvt = ast_channel_tech_pvt(bridge_channel->chan);
+	struct ast_channel *chan;
+
+	ao2_lock(pvt);
+	if (AST_UNREAL_IS_OUTBOUND(bridge_channel->chan, pvt)) {
+		chan = ast_channel_ref(pvt->bridged_owner ? pvt->bridged_owner : pvt->owner);
+	} else {
+		chan = ast_channel_ref(pvt->bridged_chan ? pvt->bridged_chan : pvt->chan);
+	}
+	ao2_unlock(pvt);
+
+	return chan;
+}
+
+/*! \brief Helper function which changes what channel we are connected to */
+static int unreal_apply_channel_connection(struct ast_bridge_channel *bridge_channel, struct ast_channel *chan)
+{
+	struct ast_unreal_pvt *pvt = ast_channel_tech_pvt(bridge_channel->chan);
+	int changed = 0;
+
+	ao2_lock(pvt);
+	if (AST_UNREAL_IS_OUTBOUND(bridge_channel->chan, pvt)) {
+		if (pvt->bridged_chan != chan) {
+			changed = 1;
+		}
+		if (pvt->bridged_chan) {
+			ast_channel_unref(pvt->bridged_chan);
+		}
+		pvt->bridged_chan = chan;
+	} else {
+		if (pvt->bridged_owner != chan) {
+			changed = 1;
+		}
+		if (pvt->bridged_owner) {
+			ast_channel_unref(pvt->bridged_owner);
+		}
+		pvt->bridged_owner = chan;
+	}
+	ao2_unlock(pvt);
+
+	return changed;
+}
+
+static void unreal_bridge_update_connections(struct ast_bridge *bridge)
+{
+	struct ast_bridge_channel *c0 = AST_LIST_FIRST(&bridge->channels);
+	struct ast_bridge_channel *c1 = AST_LIST_LAST(&bridge->channels);
+	struct ast_channel *c0_chan, *c1_chan;
+	int changed = 0;
+
+	if (c0 == c1) {
+		return;
+	}
+
+	/* Acquire the channels that we can short circuit to */
+	c0_chan = unreal_get_channel_to_connect_to(c0);
+	c1_chan = unreal_get_channel_to_connect_to(c1);
+
+	/* Apply the connections to the unreal channels, notifying upstream if the connection has changed */
+	changed = unreal_apply_channel_connection(c0, c1_chan);
+	changed |= unreal_apply_channel_connection(c1, c0_chan);
+
+	if (changed) {
+		unreal_bridge_notify_source_update(bridge, c0);
+		unreal_bridge_notify_source_update(bridge, c1);
+	}
+}
+
+static void unreal_bridge_terminate_connections(struct ast_bridge *bridge)
+{
+	struct ast_bridge_channel *c0 = AST_LIST_FIRST(&bridge->channels);
+	struct ast_bridge_channel *c1 = AST_LIST_LAST(&bridge->channels);
+	int changed = 0;
+
+	changed = unreal_apply_channel_connection(c0, NULL);
+	changed |= unreal_apply_channel_connection(c1, NULL);
+
+	if (changed) {
+		unreal_bridge_notify_source_update(bridge, c0);
+		unreal_bridge_notify_source_update(bridge, c1);
+	}
+}
+
+static int unreal_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+	unreal_bridge_update_connections(bridge);
+	return 0;
+}
+
+static void unreal_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+	unreal_bridge_terminate_connections(bridge);
+}
+
+static int unreal_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+	/* If a source update has occurred update connections in case they have changed */
+	if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_SRCUPDATE) {
+		unreal_bridge_update_connections(bridge);
+		return 0;
+	}
+
+	return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
+}
+
+static struct ast_bridge_technology unreal_bridge = {
+	.name = "unreal_bridge",
+	.capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
+	.preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
+	.compatible = unreal_bridge_compatible,
+	.join = unreal_bridge_join,
+	.leave = unreal_bridge_leave,
+	.write = unreal_bridge_write,
+};
+
+static int unload_module(void)
+{
+	ast_format_cap_destroy(unreal_bridge.format_capabilities);
+	return ast_bridge_technology_unregister(&unreal_bridge);
+}
+
+static int load_module(void)
+{
+	if (!(unreal_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	ast_format_cap_add_all_by_type(unreal_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
+	ast_format_cap_add_all_by_type(unreal_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
+	ast_format_cap_add_all_by_type(unreal_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+
+	return ast_bridge_technology_register(&unreal_bridge);
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Unreal channel bridging module");

Propchange: team/file/bridge_unreal/bridges/bridge_unreal.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/file/bridge_unreal/bridges/bridge_unreal.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/file/bridge_unreal/bridges/bridge_unreal.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/file/bridge_unreal/include/asterisk/core_unreal.h
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal/include/asterisk/core_unreal.h?view=diff&rev=410301&r1=410300&r2=410301
==============================================================================
--- team/file/bridge_unreal/include/asterisk/core_unreal.h (original)
+++ team/file/bridge_unreal/include/asterisk/core_unreal.h Sat Mar  8 12:40:41 2014
@@ -92,6 +92,8 @@
 	struct ast_unreal_pvt_callbacks *callbacks; /*!< Event callbacks */
 	struct ast_channel *owner;                  /*!< Master Channel - ;1 side */
 	struct ast_channel *chan;                   /*!< Outbound channel - ;2 side */
+	struct ast_channel *bridged_owner;			/*!< Master Channel - Bridged */
+	struct ast_channel *bridged_chan;			/*!< Outbound channel - Bridged */
 	struct ast_format_cap *reqcap;              /*!< Requested format capabilities */
 	struct ast_jb_conf jb_conf;                 /*!< jitterbuffer configuration */
 	unsigned int flags;                         /*!< Private option flags */

Modified: team/file/bridge_unreal/main/core_unreal.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal/main/core_unreal.c?view=diff&rev=410301&r1=410300&r2=410301
==============================================================================
--- team/file/bridge_unreal/main/core_unreal.c (original)
+++ team/file/bridge_unreal/main/core_unreal.c Sat Mar  8 12:40:41 2014
@@ -203,10 +203,24 @@
 static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f,
 	struct ast_channel *us, int us_locked)
 {
-	struct ast_channel *other;
+	struct ast_channel *other = NULL;
 
 	/* Recalculate outbound channel */
-	other = isoutbound ? p->owner : p->chan;
+	if (isoutbound) {
+		if (f->frametype != AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_SRCUPDATE) {
+			other = p->bridged_owner;
+		}
+		if (!other) {
+			other = p->owner;
+		}
+	} else {
+		if (f->frametype != AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_SRCUPDATE) {
+			other = p->bridged_chan;
+		}
+		if (!other) {
+			other = p->chan;
+		}
+	}
 	if (!other) {
 		return 0;
 	}




More information about the svn-commits mailing list