[asterisk-commits] jrose: branch jrose/bridge_projects r386562 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 25 14:32:12 CDT 2013


Author: jrose
Date: Thu Apr 25 14:32:08 2013
New Revision: 386562

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386562
Log:
merge and fix conflicts from automerge, still not turning automerge back on

Added:
    team/jrose/bridge_projects/channels/chan_gulp.c
      - copied unchanged from r386561, team/group/bridge_construction/channels/chan_gulp.c
    team/jrose/bridge_projects/configs/res_sip.conf.sample
      - copied unchanged from r386561, team/group/bridge_construction/configs/res_sip.conf.sample
    team/jrose/bridge_projects/include/asterisk/res_sip.h
      - copied unchanged from r386561, team/group/bridge_construction/include/asterisk/res_sip.h
    team/jrose/bridge_projects/include/asterisk/res_sip_pubsub.h
      - copied unchanged from r386561, team/group/bridge_construction/include/asterisk/res_sip_pubsub.h
    team/jrose/bridge_projects/include/asterisk/res_sip_session.h
      - copied unchanged from r386561, team/group/bridge_construction/include/asterisk/res_sip_session.h
    team/jrose/bridge_projects/res/res_sip/
      - copied from r386561, team/group/bridge_construction/res/res_sip/
    team/jrose/bridge_projects/res/res_sip.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip.c
    team/jrose/bridge_projects/res/res_sip.exports.in
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip.exports.in
    team/jrose/bridge_projects/res/res_sip/config_auth.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/config_auth.c
    team/jrose/bridge_projects/res/res_sip/config_domain_aliases.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/config_domain_aliases.c
    team/jrose/bridge_projects/res/res_sip/config_transport.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/config_transport.c
    team/jrose/bridge_projects/res/res_sip/include/
      - copied from r386561, team/group/bridge_construction/res/res_sip/include/
    team/jrose/bridge_projects/res/res_sip/include/res_sip_private.h
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/include/res_sip_private.h
    team/jrose/bridge_projects/res/res_sip/location.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/location.c
    team/jrose/bridge_projects/res/res_sip/sip_configuration.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/sip_configuration.c
    team/jrose/bridge_projects/res/res_sip/sip_distributor.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/sip_distributor.c
    team/jrose/bridge_projects/res/res_sip/sip_options.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/sip_options.c
    team/jrose/bridge_projects/res/res_sip/sip_outbound_auth.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip/sip_outbound_auth.c
    team/jrose/bridge_projects/res/res_sip_acl.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_acl.c
    team/jrose/bridge_projects/res/res_sip_authenticator_digest.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_authenticator_digest.c
    team/jrose/bridge_projects/res/res_sip_caller_id.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_caller_id.c
    team/jrose/bridge_projects/res/res_sip_dtmf_info.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_dtmf_info.c
    team/jrose/bridge_projects/res/res_sip_endpoint_identifier_constant.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_endpoint_identifier_constant.c
    team/jrose/bridge_projects/res/res_sip_endpoint_identifier_ip.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_endpoint_identifier_ip.c
    team/jrose/bridge_projects/res/res_sip_endpoint_identifier_user.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_endpoint_identifier_user.c
    team/jrose/bridge_projects/res/res_sip_logger.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_logger.c
    team/jrose/bridge_projects/res/res_sip_mwi.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_mwi.c
    team/jrose/bridge_projects/res/res_sip_nat.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_nat.c
    team/jrose/bridge_projects/res/res_sip_outbound_authenticator_digest.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_outbound_authenticator_digest.c
    team/jrose/bridge_projects/res/res_sip_outbound_registration.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_outbound_registration.c
    team/jrose/bridge_projects/res/res_sip_pubsub.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_pubsub.c
    team/jrose/bridge_projects/res/res_sip_pubsub.exports.in
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_pubsub.exports.in
    team/jrose/bridge_projects/res/res_sip_registrar.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_registrar.c
    team/jrose/bridge_projects/res/res_sip_rfc3326.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_rfc3326.c
    team/jrose/bridge_projects/res/res_sip_sdp_rtp.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_sdp_rtp.c
    team/jrose/bridge_projects/res/res_sip_session.c
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_session.c
    team/jrose/bridge_projects/res/res_sip_session.exports.in
      - copied unchanged from r386561, team/group/bridge_construction/res/res_sip_session.exports.in
Modified:
    team/jrose/bridge_projects/   (props changed)
    team/jrose/bridge_projects/CHANGES
    team/jrose/bridge_projects/channels/Makefile
    team/jrose/bridge_projects/configure
    team/jrose/bridge_projects/funcs/func_jitterbuffer.c
    team/jrose/bridge_projects/include/asterisk/abstract_jb.h
    team/jrose/bridge_projects/include/asterisk/autoconfig.h.in
    team/jrose/bridge_projects/include/asterisk/sorcery.h
    team/jrose/bridge_projects/include/asterisk/threadpool.h
    team/jrose/bridge_projects/main/abstract_jb.c
    team/jrose/bridge_projects/main/astobj2.c
    team/jrose/bridge_projects/main/bridging.c
    team/jrose/bridge_projects/main/loader.c
    team/jrose/bridge_projects/main/sorcery.c
    team/jrose/bridge_projects/main/taskprocessor.c
    team/jrose/bridge_projects/main/threadpool.c
    team/jrose/bridge_projects/res/Makefile
    team/jrose/bridge_projects/res/res_sorcery_config.c
    team/jrose/bridge_projects/tests/test_sorcery.c

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Thu Apr 25 14:32:08 2013
@@ -1,1 +1,1 @@
-/trunk:1-386488
+/trunk:1-386543

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_projects-integrated (original)
+++ bridge_projects-integrated Thu Apr 25 14:32:08 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-386542
+/team/group/bridge_construction:1-386561

Modified: team/jrose/bridge_projects/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/CHANGES?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/CHANGES (original)
+++ team/jrose/bridge_projects/CHANGES Thu Apr 25 14:32:08 2013
@@ -74,6 +74,11 @@
 
 Channel Drivers
 ------------------
+ * When a channel driver is configured to enable jiterbuffers, they are now
+   applied unconditionally when a channel joins a bridge. If a jitterbuffer
+   is already set for that channel when it enters, such as by the JITTERBUFFER
+   function, then the existing jitterbuffer will be used and the one set by
+   the channel driver will not be applied.
 
 chan_local
 ------------------
@@ -109,6 +114,12 @@
  * You can now have the settings for a channel updated using the FEATURE()
    and FEATUREMAP() functions inherited to child channels by setting
    FEATURE(inherit)=yes.
+
+Functions
+------------------
+ * JITTERBUFFER now accepts an argument of 'disabled' which can be used
+   to remove jitterbuffers previously set on a channel with JITTERBUFFER.
+   The value of this setting is ignored when disabled is used for the argument.
 
 Logging
 -------------------

Modified: team/jrose/bridge_projects/channels/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/channels/Makefile?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/channels/Makefile (original)
+++ team/jrose/bridge_projects/channels/Makefile Thu Apr 25 14:32:08 2013
@@ -113,3 +113,4 @@
 
 h323/libchanh323.a: h323/Makefile.ast
 	$(CMD_PREFIX) $(MAKE) -C h323 libchanh323.a
+

Modified: team/jrose/bridge_projects/funcs/func_jitterbuffer.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/funcs/func_jitterbuffer.c?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/funcs/func_jitterbuffer.c (original)
+++ team/jrose/bridge_projects/funcs/func_jitterbuffer.c Thu Apr 25 14:32:08 2013
@@ -36,6 +36,7 @@
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
 #include "asterisk/framehook.h"
+#include "asterisk/frame.h"
 #include "asterisk/pbx.h"
 #include "asterisk/abstract_jb.h"
 #include "asterisk/timing.h"
@@ -48,7 +49,8 @@
 		</synopsis>
 		<syntax>
 			<parameter name="jitterbuffer type" required="true">
-				<para>Jitterbuffer type can be either <literal>fixed</literal> or <literal>adaptive</literal>.</para>
+				<para>Jitterbuffer type can be <literal>fixed</literal>, <literal>adaptive</literal>, or
+					<literal>disabled</literal>.</para>
 				<para>Used as follows. </para>
 				<para>Set(JITTERBUFFER(type)=max_size[,resync_threshold[,target_extra]])</para>
 				<para>Set(JITTERBUFFER(type)=default) </para>
@@ -70,85 +72,31 @@
 			<para>exten => 1,1,Set(JITTERBUFFER(fixed)=200,1500);Fixed with max size 200ms resync threshold 1500. </para>
 			<para>exten => 1,1,Set(JITTERBUFFER(adaptive)=default);Adaptive with defaults. </para>
 			<para>exten => 1,1,Set(JITTERBUFFER(adaptive)=200,,60);Adaptive with max size 200ms, default resync threshold and 40ms target extra. </para>
+			<para>exten => 1,n,Set(JITTERBUFFER(disabled)=);Remove previously applied jitterbuffer </para>
+			<note><para>If a channel specifies a jitterbuffer due to channel driver configuration and
+			the JITTERBUFFER function has set a jitterbuffer for that channel, the jitterbuffer set by
+			the JITTERBUFFER function will take priority and the jitterbuffer set by the channel
+			configuration will not be applied.</para></note>
 		</description>
 	</function>
  ***/
 
-#define DEFAULT_TIMER_INTERVAL 20
-#define DEFAULT_SIZE  200
-#define DEFAULT_TARGET_EXTRA  40
-#define DEFAULT_RESYNC  1000
-#define DEFAULT_TYPE AST_JB_FIXED
+static int jb_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+	struct ast_jb_conf jb_conf;
 
-struct jb_framedata {
-	const struct ast_jb_impl *jb_impl;
-	struct ast_jb_conf jb_conf;
-	struct timeval start_tv;
-	struct ast_format last_format;
-	struct ast_timer *timer;
-	int timer_interval; /* ms between deliveries */
-	int timer_fd;
-	int first;
-	void *jb_obj;
-};
-
-static void jb_framedata_destroy(struct jb_framedata *framedata)
-{
-	if (framedata->timer) {
-		ast_timer_close(framedata->timer);
-		framedata->timer = NULL;
-	}
-	if (framedata->jb_impl && framedata->jb_obj) {
-		struct ast_frame *f;
-		while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
-			ast_frfree(f);
-		}
-		framedata->jb_impl->destroy(framedata->jb_obj);
-		framedata->jb_obj = NULL;
-	}
-	ast_free(framedata);
-}
-
-static void jb_conf_default(struct ast_jb_conf *conf)
-{
-	conf->max_size = DEFAULT_SIZE;
-	conf->resync_threshold = DEFAULT_RESYNC;
-	ast_copy_string(conf->impl, "fixed", sizeof(conf->impl));
-	conf->target_extra = DEFAULT_TARGET_EXTRA;
-}
-
-/* set defaults */
-static int jb_framedata_init(struct jb_framedata *framedata, const char *data, const char *value)
-{
-	int jb_impl_type = DEFAULT_TYPE;
-
-	/* Initialize defaults */
-	framedata->timer_fd = -1;
-	jb_conf_default(&framedata->jb_conf);
-	if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
-		return -1;
-	}
-	if (!(framedata->timer = ast_timer_open())) {
-		return -1;
-	}
-	framedata->timer_fd = ast_timer_fd(framedata->timer);
-	framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
-	ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
-	framedata->start_tv = ast_tvnow();
-
-
+	/* Initialize and set jb_conf */
+	ast_jb_conf_default(&jb_conf);
 
 	/* Now check user options to see if any of the defaults need to change. */
 	if (!ast_strlen_zero(data)) {
-		if (!strcasecmp(data, "fixed")) {
-			jb_impl_type = AST_JB_FIXED;
-		} else if (!strcasecmp(data, "adaptive")) {
-			jb_impl_type = AST_JB_ADAPTIVE;
-		} else {
+		if (strcasecmp(data, "fixed") &&
+				strcasecmp(data, "adaptive") &&
+				strcasecmp(data, "disabled")) {
 			ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", data);
 			return -1;
 		}
-		ast_copy_string(framedata->jb_conf.impl, data, sizeof(framedata->jb_conf.impl));
+		ast_copy_string(jb_conf.impl, data, sizeof(jb_conf.impl));
 	}
 
 	if (!ast_strlen_zero(value) && strcasecmp(value, "default")) {
@@ -162,17 +110,17 @@
 
 		AST_STANDARD_APP_ARGS(args, parse);
 		if (!ast_strlen_zero(args.max_size)) {
-			res |= ast_jb_read_conf(&framedata->jb_conf,
+			res |= ast_jb_read_conf(&jb_conf,
 				"jbmaxsize",
 				args.max_size);
 		}
 		if (!ast_strlen_zero(args.resync_threshold)) {
-			res |= ast_jb_read_conf(&framedata->jb_conf,
+			res |= ast_jb_read_conf(&jb_conf,
 				"jbresyncthreshold",
 				args.resync_threshold);
 		}
 		if (!ast_strlen_zero(args.target_extra)) {
-			res |= ast_jb_read_conf(&framedata->jb_conf,
+			res |= ast_jb_read_conf(&jb_conf,
 				"jbtargetextra",
 				args.target_extra);
 		}
@@ -181,197 +129,11 @@
 		}
 	}
 
-	/* now that all the user parsing is done and nothing will change, create the jb obj */
-	framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
+	ast_jb_create_framehook(chan, &jb_conf, 0);
+
 	return 0;
 }
 
-static void datastore_destroy_cb(void *data) {
-	ast_free(data);
-	ast_debug(1, "JITTERBUFFER datastore destroyed\n");
-}
-
-static const struct ast_datastore_info jb_datastore = {
-	.type = "jitterbuffer",
-	.destroy = datastore_destroy_cb
-};
-
-static void hook_destroy_cb(void *framedata)
-{
-	ast_debug(1, "JITTERBUFFER hook destroyed\n");
-	jb_framedata_destroy((struct jb_framedata *) framedata);
-}
-
-static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
-{
-	struct jb_framedata *framedata = data;
-	struct timeval now_tv;
-	unsigned long now;
-	int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
-
-	switch (event) {
-	case AST_FRAMEHOOK_EVENT_READ:
-		break;
-	case AST_FRAMEHOOK_EVENT_ATTACHED:
-	case AST_FRAMEHOOK_EVENT_DETACHED:
-	case AST_FRAMEHOOK_EVENT_WRITE:
-		return frame;
-	}
-
-	if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
-		if (ast_timer_ack(framedata->timer, 1) < 0) {
-			ast_log(LOG_ERROR, "Failed to acknowledge timer in jitter buffer\n");
-			return frame;
-		}
-	}
-
-	if (!frame) {
-		return frame;
-	}
-
-	now_tv = ast_tvnow();
-	now = ast_tvdiff_ms(now_tv, framedata->start_tv);
-
-	if (frame->frametype == AST_FRAME_VOICE) {
-		int res;
-		struct ast_frame *jbframe;
-
-		if (!ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO) || frame->len < 2 || frame->ts < 0) {
-			/* only frames with timing info can enter the jitterbuffer */
-			return frame;
-		}
-
-		jbframe = ast_frisolate(frame);
-		ast_format_copy(&framedata->last_format, &frame->subclass.format);
-
-		if (frame->len && (frame->len != framedata->timer_interval)) {
-			framedata->timer_interval = frame->len;
-			ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
-		}
-		if (!framedata->first) {
-			framedata->first = 1;
-			res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, now);
-		} else {
-			res = framedata->jb_impl->put(framedata->jb_obj, jbframe, now);
-		}
-		if (res == AST_JB_IMPL_OK) {
-			frame = &ast_null_frame;
-		}
-		putframe = 1;
-	}
-
-	if (frame->frametype == AST_FRAME_NULL) {
-		int res;
-		long next = framedata->jb_impl->next(framedata->jb_obj);
-
-		/* If now is earlier than the next expected output frame
-		 * from the jitterbuffer we may choose to pass on retrieving
-		 * a frame during this read iteration.  The only exception
-		 * to this rule is when an audio frame is placed into the buffer
-		 * and the time for the next frame to come out of the buffer is
-		 * at least within the timer_interval of the next output frame. By
-		 * doing this we are able to feed off the timing of the input frames
-		 * and only rely on our jitterbuffer timer when frames are dropped.
-		 * During testing, this hybrid form of timing gave more reliable results. */
-		if (now < next) {
-			long int diff = next - now;
-			if (!putframe) {
-				return frame;
-			} else if (diff >= framedata->timer_interval) {
-				return frame;
-			}
-		}
-
-		res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
-		switch (res) {
-		case AST_JB_IMPL_OK:
-			/* got it, and pass it through */
-			break;
-		case AST_JB_IMPL_DROP:
-			ast_frfree(frame);
-			frame = &ast_null_frame;
-			break;
-		case AST_JB_IMPL_INTERP:
-			if (framedata->last_format.id) {
-				struct ast_frame tmp = { 0, };
-				tmp.frametype = AST_FRAME_VOICE;
-				ast_format_copy(&tmp.subclass.format, &framedata->last_format);
-				/* example: 8000hz / (1000 / 20ms) = 160 samples */
-				tmp.samples = ast_format_rate(&framedata->last_format) / (1000 / framedata->timer_interval);
-				tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
-				tmp.offset = AST_FRIENDLY_OFFSET;
-				tmp.src  = "func_jitterbuffer interpolation";
-				frame = ast_frdup(&tmp);
-				break;
-			}
-			/* else fall through */
-		case AST_JB_IMPL_NOFRAME:
-			frame = &ast_null_frame;
-			break;
-		}
-	}
-
-	return frame;
-}
-
-static int jb_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
-{
-	struct jb_framedata *framedata;
-	struct ast_datastore *datastore = NULL;
-	struct ast_framehook_interface interface = {
-		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
-		.event_cb = hook_event_cb,
-		.destroy_cb = hook_destroy_cb,
-	};
-	int i = 0;
-
-	if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
-		return 0;
-	}
-
-	if (jb_framedata_init(framedata, data, value)) {
-		jb_framedata_destroy(framedata);
-		return 0;
-	}
-
-	interface.data = framedata;
-
-	ast_channel_lock(chan);
-	i = ast_framehook_attach(chan, &interface);
-	if (i >= 0) {
-		int *id;
-		if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
-			id = datastore->data;
-			ast_framehook_detach(chan, *id);
-			ast_channel_datastore_remove(chan, datastore);
-		}
-
-		if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
-			ast_framehook_detach(chan, i);
-			ast_channel_unlock(chan);
-			return 0;
-		}
-
-		if (!(id = ast_calloc(1, sizeof(int)))) {
-			ast_datastore_free(datastore);
-			ast_framehook_detach(chan, i);
-			ast_channel_unlock(chan);
-			return 0;
-		}
-
-		*id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
-		datastore->data = id;
-		ast_channel_datastore_add(chan, datastore);
-
-		ast_channel_set_fd(chan, AST_JITTERBUFFER_FD, framedata->timer_fd);
-	} else {
-		jb_framedata_destroy(framedata);
-		framedata = NULL;
-	}
-	ast_channel_unlock(chan);
-
-	return 0;
-}
 
 static struct ast_custom_function jb_function = {
 	.name = "JITTERBUFFER",

Modified: team/jrose/bridge_projects/include/asterisk/abstract_jb.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/abstract_jb.h?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/abstract_jb.h (original)
+++ team/jrose/bridge_projects/include/asterisk/abstract_jb.h Thu Apr 25 14:32:08 2013
@@ -246,6 +246,14 @@
  */
 int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value);
 
+/*!
+ * \since 12.0
+ * \brief Sets a jitterbuffer frame hook on the channel based on the channel's stored
+ *        jitterbuffer configuration
+ *
+ * \param chan Which channel is being set up
+ */
+void ast_jb_enable_for_channel(struct ast_channel *chan);
 
 /*!
  * \brief Configures a jitterbuffer on a channel.
@@ -257,7 +265,6 @@
  */
 void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf);
 
-
 /*!
  * \brief Copies a channel's jitterbuffer configuration.
  * \param chan channel.
@@ -274,6 +281,25 @@
 
 const struct ast_jb_impl *ast_jb_get_impl(enum ast_jb_type type);
 
+/*!
+ * \since 12
+ * \brief Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings
+ *
+ * \param conf Which jitterbuffer is being set
+ */
+void ast_jb_conf_default(struct ast_jb_conf *conf);
+
+/*!
+ * \since 12
+ * \brief Applies a jitterbuffer framehook to a channel based on a provided jitterbuffer config
+ *
+ * \param chan Which channel the jitterbuffer is being set on
+ * \param jb_conf Configuration to use for the jitterbuffer
+ * \param prefer_existing If this is true and a jitterbuffer already exists for the channel,
+ *        use the existing jitterbuffer
+ */
+void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/jrose/bridge_projects/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/autoconfig.h.in?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/autoconfig.h.in (original)
+++ team/jrose/bridge_projects/include/asterisk/autoconfig.h.in Thu Apr 25 14:32:08 2013
@@ -294,7 +294,7 @@
 /* Define if your system has the GLOB_NOMAGIC headers. */
 #undef HAVE_GLOB_NOMAGIC
 
-/* Define if your system has the GMIME libraries. */
+/* Define to 1 if you have the GMime library. */
 #undef HAVE_GMIME
 
 /* Define to indicate the GSM library */
@@ -306,7 +306,7 @@
 /* Define to indicate that gsm.h has no prefix for its location */
 #undef HAVE_GSM_HEADER
 
-/* Define if your system has the GTK2 libraries. */
+/* Define to 1 if you have the gtk2 library. */
 #undef HAVE_GTK2
 
 /* Define to 1 if you have the Hoard Memory Allocator library. */
@@ -324,7 +324,7 @@
 /* Define to 1 if you have the Iksemel Jabber library. */
 #undef HAVE_IKSEMEL
 
-/* Define if your system has the ILBC libraries. */
+/* Define to 1 if you have the System iLBC library. */
 #undef HAVE_ILBC
 
 /* Define if your system has the UW IMAP Toolkit c-client library. */
@@ -376,7 +376,7 @@
 /* Define to 1 if you have the OpenLDAP library. */
 #undef HAVE_LDAP
 
-/* Define if your system has the LIBEDIT libraries. */
+/* Define to 1 if you have the NetBSD Editline library library. */
 #undef HAVE_LIBEDIT
 
 /* Define to 1 if you have the <libintl.h> header file. */
@@ -551,7 +551,7 @@
 /* Define to indicate presence of the pg_encoding_to_char API. */
 #undef HAVE_PGSQL_pg_encoding_to_char
 
-/* Define if your system has the PJPROJECT libraries. */
+/* Define to 1 if you have the PJPROJECT library. */
 #undef HAVE_PJPROJECT
 
 /* Define to 1 if your system defines IP_PKTINFO. */
@@ -854,19 +854,19 @@
 /* Define to 1 if you have the `strtoq' function. */
 #undef HAVE_STRTOQ
 
-/* Define to 1 if `ifr_ifru.ifru_hwaddr' is a member of `struct ifreq'. */
+/* Define to 1 if `ifr_ifru.ifru_hwaddr' is member of `struct ifreq'. */
 #undef HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR
 
-/* Define to 1 if `uid' is a member of `struct sockpeercred'. */
+/* Define to 1 if `uid' is member of `struct sockpeercred'. */
 #undef HAVE_STRUCT_SOCKPEERCRED_UID
 
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_BLKSIZE
 
-/* Define to 1 if `cr_uid' is a member of `struct ucred'. */
+/* Define to 1 if `cr_uid' is member of `struct ucred'. */
 #undef HAVE_STRUCT_UCRED_CR_UID
 
-/* Define to 1 if `uid' is a member of `struct ucred'. */
+/* Define to 1 if `uid' is member of `struct ucred'. */
 #undef HAVE_STRUCT_UCRED_UID
 
 /* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -1144,11 +1144,11 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#undef PROTOTYPES
 
 /* Define to necessary symbol if this constant uses a non-standard name on
    your system. */
@@ -1168,6 +1168,11 @@
 
 /* Define to the type of arg 5 for `select'. */
 #undef SELECT_TYPE_ARG5
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+#undef SETVBUF_REVERSED
 
 /* The size of `char *', as computed by sizeof. */
 #undef SIZEOF_CHAR_P
@@ -1204,54 +1209,53 @@
 /* Define to a type of the same size as fd_set.fds_bits[[0]] */
 #undef TYPEOF_FD_SET_FDS_BITS
 
-/* Enable extensions on AIX 3, Interix.  */
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
 #ifndef _ALL_SOURCE
 # undef _ALL_SOURCE
 #endif
+
+/* Define to 1 if running on Darwin. */
+#undef _DARWIN_UNLIMITED_SELECT
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
 /* Enable GNU extensions on systems that have them.  */
 #ifndef _GNU_SOURCE
 # undef _GNU_SOURCE
 #endif
-/* Enable threading extensions on Solaris.  */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Enable extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
 #ifndef _POSIX_PTHREAD_SEMANTICS
 # undef _POSIX_PTHREAD_SEMANTICS
 #endif
-/* Enable extensions on HP NonStop.  */
 #ifndef _TANDEM_SOURCE
 # undef _TANDEM_SOURCE
 #endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
-/* Define to 1 if running on Darwin. */
-#undef _DARWIN_UNLIMITED_SELECT
-
-/* Enable large inode numbers on Mac OS X 10.5.  */
-#ifndef _DARWIN_USE_64_BIT_INODE
-# define _DARWIN_USE_64_BIT_INODE 1
-#endif
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-#undef _LARGEFILE_SOURCE
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
-   this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#undef __PROTOTYPES
 
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const

Modified: team/jrose/bridge_projects/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/sorcery.h?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/sorcery.h (original)
+++ team/jrose/bridge_projects/include/asterisk/sorcery.h Thu Apr 25 14:32:08 2013
@@ -157,10 +157,15 @@
 /*!
  * \brief A callback function for when an object set is successfully applied to an object
  *
+ * \note On a failure return, the state of the object is left undefined. It is a bad
+ * idea to try to use this object.
+ *
  * \param sorcery Sorcery structure in use
  * \param obj The object itself
- */
-typedef void (*sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj);
+ * \retval 0 Success
+ * \retval non-zero Failure
+ */
+typedef int (*sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj);
 
 /*!
  * \brief A callback function for copying the contents of one object to another

Modified: team/jrose/bridge_projects/include/asterisk/threadpool.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/threadpool.h?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/threadpool.h (original)
+++ team/jrose/bridge_projects/include/asterisk/threadpool.h Thu Apr 25 14:32:08 2013
@@ -108,6 +108,20 @@
 	 * maximum size.
 	 */
 	int max_size;
+	/*!
+	 * \brief Function to call when a thread starts
+	 *
+	 * This is useful if there is something common that all threads
+	 * in a threadpool need to do when they start.
+	 */
+	void (*thread_start)(void);
+	/*!
+	 * \brief Function to call when a thread ends
+	 *
+	 * This is useful if there is common cleanup to execute when
+	 * a thread completes
+	 */
+	void (*thread_end)(void);
 };
 
 /*!

Modified: team/jrose/bridge_projects/main/abstract_jb.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/abstract_jb.c?view=diff&rev=386562&r1=386561&r2=386562
==============================================================================
--- team/jrose/bridge_projects/main/abstract_jb.c (original)
+++ team/jrose/bridge_projects/main/abstract_jb.c Thu Apr 25 14:32:08 2013
@@ -41,6 +41,8 @@
 #include "asterisk/channel.h"
 #include "asterisk/term.h"
 #include "asterisk/utils.h"
+#include "asterisk/pbx.h"
+#include "asterisk/timing.h"
 
 #include "asterisk/abstract_jb.h"
 #include "fixedjitterbuf.h"
@@ -567,10 +569,16 @@
 	return 0;
 }
 
+void ast_jb_enable_for_channel(struct ast_channel *chan)
+{
+	struct ast_jb_conf conf = ast_channel_jb(chan)->conf;
+	if (ast_test_flag(&conf, AST_JB_ENABLED)) {
+		ast_jb_create_framehook(chan, &conf, 1);
+	}
+}
 
 void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
 {
-/* BUGBUG convert this to use func_jitterbuffer then the channel jitterbuffer may be able to go away. */
 	memcpy(&ast_channel_jb(chan)->conf, conf, sizeof(*conf));
 }
 
@@ -801,3 +809,303 @@
 	}
 	return NULL;
 }
+
+#define DEFAULT_TIMER_INTERVAL 20
+#define DEFAULT_SIZE  200
+#define DEFAULT_TARGET_EXTRA  40
+#define DEFAULT_RESYNC  1000
+#define DEFAULT_TYPE AST_JB_FIXED
+
+struct jb_framedata {
+	const struct ast_jb_impl *jb_impl;
+	struct ast_jb_conf jb_conf;
+	struct timeval start_tv;
+	struct ast_format last_format;
+	struct ast_timer *timer;
+	int timer_interval; /* ms between deliveries */
+	int timer_fd;
+	int first;
+	void *jb_obj;
+};
+
+static void jb_framedata_destroy(struct jb_framedata *framedata)
+{
+	if (framedata->timer) {
+		ast_timer_close(framedata->timer);
+		framedata->timer = NULL;
+	}
+	if (framedata->jb_impl && framedata->jb_obj) {
+		struct ast_frame *f;
+		while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
+			ast_frfree(f);
+		}
+		framedata->jb_impl->destroy(framedata->jb_obj);
+		framedata->jb_obj = NULL;
+	}
+	ast_free(framedata);
+}
+
+void ast_jb_conf_default(struct ast_jb_conf *conf)
+{
+	conf->max_size = DEFAULT_SIZE;
+	conf->resync_threshold = DEFAULT_RESYNC;
+	ast_copy_string(conf->impl, "fixed", sizeof(conf->impl));
+	conf->target_extra = DEFAULT_TARGET_EXTRA;
+}
+
+static void datastore_destroy_cb(void *data) {
+	ast_free(data);
+	ast_debug(1, "JITTERBUFFER datastore destroyed\n");
+}
+
+static const struct ast_datastore_info jb_datastore = {
+	.type = "jitterbuffer",
+	.destroy = datastore_destroy_cb
+};
+
+static void hook_destroy_cb(void *framedata)
+{
+	ast_debug(1, "JITTERBUFFER hook destroyed\n");
+	jb_framedata_destroy((struct jb_framedata *) framedata);
+}
+
+static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
+{
+	struct jb_framedata *framedata = data;
+	struct timeval now_tv;
+	unsigned long now;
+	int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
+
+	switch (event) {
+	case AST_FRAMEHOOK_EVENT_READ:
+		break;
+	case AST_FRAMEHOOK_EVENT_ATTACHED:
+	case AST_FRAMEHOOK_EVENT_DETACHED:
+	case AST_FRAMEHOOK_EVENT_WRITE:
+		return frame;
+	}
+
+	if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
+		if (ast_timer_ack(framedata->timer, 1) < 0) {
+			ast_log(LOG_ERROR, "Failed to acknowledge timer in jitter buffer\n");
+			return frame;
+		}
+	}
+
+	if (!frame) {
+		return frame;
+	}
+
+	now_tv = ast_tvnow();
+	now = ast_tvdiff_ms(now_tv, framedata->start_tv);
+
+	if (frame->frametype == AST_FRAME_VOICE) {
+		int res;
+		struct ast_frame *jbframe;
+
+		if (!ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO) || frame->len < 2 || frame->ts < 0) {
+			/* only frames with timing info can enter the jitterbuffer */
+			return frame;
+		}
+
+		jbframe = ast_frisolate(frame);
+		ast_format_copy(&framedata->last_format, &frame->subclass.format);
+
+		if (frame->len && (frame->len != framedata->timer_interval)) {
+			framedata->timer_interval = frame->len;
+			ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
+		}
+		if (!framedata->first) {
+			framedata->first = 1;
+			res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, now);
+		} else {
+			res = framedata->jb_impl->put(framedata->jb_obj, jbframe, now);
+		}
+		if (res == AST_JB_IMPL_OK) {
+			frame = &ast_null_frame;
+		}
+		putframe = 1;
+	}
+
+	if (frame->frametype == AST_FRAME_NULL) {
+		int res;
+		long next = framedata->jb_impl->next(framedata->jb_obj);
+
+		/* If now is earlier than the next expected output frame
+		 * from the jitterbuffer we may choose to pass on retrieving
+		 * a frame during this read iteration.  The only exception
+		 * to this rule is when an audio frame is placed into the buffer
+		 * and the time for the next frame to come out of the buffer is
+		 * at least within the timer_interval of the next output frame. By
+		 * doing this we are able to feed off the timing of the input frames
+		 * and only rely on our jitterbuffer timer when frames are dropped.
+		 * During testing, this hybrid form of timing gave more reliable results. */
+		if (now < next) {
+			long int diff = next - now;
+			if (!putframe) {
+				return frame;
+			} else if (diff >= framedata->timer_interval) {
+				return frame;
+			}
+		}
+
+		res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
+		switch (res) {
+		case AST_JB_IMPL_OK:
+			/* got it, and pass it through */
+			break;
+		case AST_JB_IMPL_DROP:
+			ast_frfree(frame);
+			frame = &ast_null_frame;
+			break;
+		case AST_JB_IMPL_INTERP:
+			if (framedata->last_format.id) {
+				struct ast_frame tmp = { 0, };
+				tmp.frametype = AST_FRAME_VOICE;
+				ast_format_copy(&tmp.subclass.format, &framedata->last_format);
+				/* example: 8000hz / (1000 / 20ms) = 160 samples */
+				tmp.samples = ast_format_rate(&framedata->last_format) / (1000 / framedata->timer_interval);
+				tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
+				tmp.offset = AST_FRIENDLY_OFFSET;
+				tmp.src  = "func_jitterbuffer interpolation";
+				frame = ast_frdup(&tmp);
+				break;
+			}
+			/* else fall through */
+		case AST_JB_IMPL_NOFRAME:
+			frame = &ast_null_frame;
+			break;
+		}
+	}
+
+	if (frame->frametype == AST_FRAME_CONTROL) {
+		switch(frame->subclass.integer) {
+		case AST_CONTROL_SRCUPDATE:
+		case AST_CONTROL_SRCCHANGE:
+			framedata->jb_impl->force_resync(framedata->jb_obj);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return frame;
+}
+
+/* set defaults */
+static int jb_framedata_init(struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
+{
+	int jb_impl_type = DEFAULT_TYPE;
+	/* Initialize defaults */
+	framedata->timer_fd = -1;
+	memcpy(&framedata->jb_conf, jb_conf, sizeof(*jb_conf));
+
+	/* Figure out implementation type from the configuration implementation string */
+	if (!ast_strlen_zero(jb_conf->impl)) {
+		if (!strcasecmp(jb_conf->impl, "fixed")) {
+			jb_impl_type = AST_JB_FIXED;
+		} else if (!strcasecmp(jb_conf->impl, "adaptive")) {
+			jb_impl_type = AST_JB_ADAPTIVE;
+		} else {
+			ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", jb_conf->impl);
+			return -1;
+		}
+	}
+
+	if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
+		return -1;
+	}
+
+	if (!(framedata->timer = ast_timer_open())) {
+		return -1;
+	}
+
+	framedata->timer_fd = ast_timer_fd(framedata->timer);
+	framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
+	ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
+	framedata->start_tv = ast_tvnow();
+
+	framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
+	return 0;
+}
+
+
+void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing)
+{
+	struct jb_framedata *framedata;
+	struct ast_datastore *datastore = NULL;
+	struct ast_framehook_interface interface = {
+		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
+		.event_cb = hook_event_cb,
+		.destroy_cb = hook_destroy_cb,
+	};
+	int i = 0;
+
+	/* If disabled, strip any existing jitterbuffer and don't replace it. */
+	if (!strcasecmp(jb_conf->impl, "disabled")) {
+		int *id;
+		ast_channel_lock(chan);
+		if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
+			id = datastore->data;
+			ast_framehook_detach(chan, *id);
+			ast_channel_datastore_remove(chan, datastore);
+		}
+		ast_channel_unlock(chan);
+		return;
+	}
+
+	if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
+		return;
+	}
+
+	if (jb_framedata_init(framedata, jb_conf)) {
+		jb_framedata_destroy(framedata);
+		return;
+	}
+
+	interface.data = framedata;
+
+	ast_channel_lock(chan);
+	i = ast_framehook_attach(chan, &interface);
+	if (i >= 0) {
+		int *id;
+		if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
+			/* There is already a jitterbuffer on the channel. */
+			if (prefer_existing) {
+				/* We prefer the existing jitterbuffer, so remove the new one and keep the old one. */
+				ast_framehook_detach(chan, i);
+				ast_channel_unlock(chan);
+				return;
+			}
+			/* We prefer the new jitterbuffer, so strip the old one. */

[... 190 lines stripped ...]



More information about the asterisk-commits mailing list