[asterisk-commits] dvossel: branch dvossel/jb_ftw r311924 - in /team/dvossel/jb_ftw: funcs/ incl...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 30 16:51:46 CDT 2011


Author: dvossel
Date: Wed Mar 30 16:51:40 2011
New Revision: 311924

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311924
Log:
Prototype code creates a jitterbuffer on the read side of a channel using framehooks (awesomehooks)

This looks like it actually will work. Channels using a jitterbuffer will get read
called twice as often as those without, but it will just generate a NULL frame until
a real frame is time to be sent. In theory, this shouldn't be much more expensive
since NULL frames are just ignored.

Modified:
    team/dvossel/jb_ftw/funcs/func_jitterbuffer.c
    team/dvossel/jb_ftw/include/asterisk/abstract_jb.h
    team/dvossel/jb_ftw/include/asterisk/channel.h
    team/dvossel/jb_ftw/main/abstract_jb.c
    team/dvossel/jb_ftw/main/channel.c

Modified: team/dvossel/jb_ftw/funcs/func_jitterbuffer.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/jb_ftw/funcs/func_jitterbuffer.c?view=diff&rev=311924&r1=311923&r2=311924
==============================================================================
--- team/dvossel/jb_ftw/funcs/func_jitterbuffer.c (original)
+++ team/dvossel/jb_ftw/funcs/func_jitterbuffer.c Wed Mar 30 16:51:40 2011
@@ -33,15 +33,65 @@
 #include "asterisk/channel.h"
 #include "asterisk/framehook.h"
 #include "asterisk/pbx.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/timing.h"
 
 struct jb_framedata {
-	/*jb stuff todohere, don't know what this is yet */
-	struct ast_jb_impl *jb_impl;
-	void *data;
+	const struct ast_jb_impl *jb_impl;
+	struct ast_jb_conf jb_conf;
+	void *jb_obj;
+	struct ast_timer *timer;
+	int timer_rate;
+	int timer_fd;
+
+	struct timeval start_tv;
+	/* used for debug */
+	struct timeval last_tv;
 };
+
+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) {
+		framedata->jb_impl->destroy(framedata->jb_obj);
+		framedata->jb_obj = NULL;
+	}
+	ast_free(framedata);
+}
+static int jb_framedata_init(struct jb_framedata *framedata)
+{
+//todohere eventually this should take a custom jb config, for testing this is all hardcoded at the moment.
+	framedata->timer_fd = -1;
+	if (!(framedata->jb_impl = ast_jb_get_impl(AST_JB_ADAPTIVE))) {
+		return -1;
+	}
+
+	if (!(framedata->timer = ast_timer_open())) {
+		return -1;
+	}
+	framedata->timer_fd = ast_timer_fd(framedata->timer);
+	ast_timer_set_rate(framedata->timer, 1000 / 20); //todohere move this to cb and check based on frame samples 
+
+	framedata->start_tv = ast_tvnow();
+	framedata->last_tv = framedata->start_tv;
+
+//todohere setup fake conf
+	framedata->jb_conf.max_size = 200;
+	framedata->jb_conf.resync_threshold = 1000;
+	ast_copy_string(framedata->jb_conf.impl, "adaptive", sizeof(framedata->jb_conf.impl));
+	framedata->jb_conf.target_extra = 40;
+
+	framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf, 1000);
+
+	return 0;
+}
 
 static void datastore_destroy_cb(void *data) {
 	ast_free(data);
+	ast_verb(1, "JITTERBUFFER datastore destroyed\n"); //todohere change to debug
 }
 
 static const struct ast_datastore_info jb_datastore = {
@@ -51,13 +101,74 @@
 
 static void hook_destroy_cb(void *framedata)
 {
-	ast_free(framedata);
+	ast_verb(1, "JITTERBUFFER hook destroyed\n"); //todohere change to debug
+	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 jb_framedata *framedata = data;
+	struct timeval now_tv;
+	unsigned long now;
+
+	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;
+	}
+
+	now_tv = ast_tvnow();
+	now = ast_tvdiff_ms(now_tv, framedata->start_tv);
+
+	if (chan->fdno == AST_JITTERBUFFER_FD && framedata->timer) {
+		ast_timer_ack(framedata->timer, 1);
+	}
+
+	if (!frame) {
+		return frame;
+	}
+
 	/* todohere add jb logic, just passing frame through right now. */
+	if (frame->frametype == AST_FRAME_VOICE) {
+
+		// ---todohere DEBUG 
+		framedata->jb_impl->put(framedata->jb_obj, frame, now);
+
+		frame = &ast_null_frame;
+	}
+
+	if (frame->frametype == AST_FRAME_NULL) {
+		int res;
+		long next = framedata->jb_impl->next(framedata->jb_obj);
+
+		if (now < next) {
+			return frame;
+		}
+		/* todohere may have to return multiple frames */
+
+		res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, 20);
+		switch (res) {
+		case AST_JB_IMPL_OK:
+//			printf("----- diff: %lu now: %lu next: %lu\n", ast_tvdiff_ms(now_tv, framedata->last_tv), now, next);
+//			framedata->last_tv = now_tv;
+			break;
+		case AST_JB_IMPL_DROP:
+			ast_frfree(frame);
+			frame = &ast_null_frame;
+			break;
+		case AST_JB_IMPL_INTERP:
+			/* todohere */
+			ast_log(LOG_NOTICE, "got interp frame err\n");
+			/* fall through */
+		case AST_JB_IMPL_NOFRAME:
+			frame = &ast_null_frame;
+			break;
+		}
+	}
+
 	return frame;
 }
 
@@ -76,6 +187,11 @@
 		return 0;
 	}
 
+	if (jb_framedata_init(framedata)) {
+		jb_framedata_destroy(framedata);
+		return 0;
+	}
+
 	interface.data = framedata;
 
 	ast_channel_lock(chan);
@@ -104,6 +220,11 @@
 		*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);
 

Modified: team/dvossel/jb_ftw/include/asterisk/abstract_jb.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/jb_ftw/include/asterisk/abstract_jb.h?view=diff&rev=311924&r1=311923&r2=311924
==============================================================================
--- team/dvossel/jb_ftw/include/asterisk/abstract_jb.h (original)
+++ team/dvossel/jb_ftw/include/asterisk/abstract_jb.h Wed Mar 30 16:51:40 2011
@@ -50,6 +50,14 @@
 enum ast_jb_type {
 	AST_JB_FIXED,
 	AST_JB_ADAPTIVE,
+};
+
+/*! Abstract return codes */
+enum {
+	AST_JB_IMPL_OK,
+	AST_JB_IMPL_DROP,
+	AST_JB_IMPL_INTERP,
+	AST_JB_IMPL_NOFRAME
 };
 
 #define AST_JB_IMPL_NAME_SIZE 12

Modified: team/dvossel/jb_ftw/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/jb_ftw/include/asterisk/channel.h?view=diff&rev=311924&r1=311923&r2=311924
==============================================================================
--- team/dvossel/jb_ftw/include/asterisk/channel.h (original)
+++ team/dvossel/jb_ftw/include/asterisk/channel.h Wed Mar 30 16:51:40 2011
@@ -154,7 +154,7 @@
 
 #define DATASTORE_INHERIT_FOREVER	INT_MAX
 
-#define AST_MAX_FDS		10
+#define AST_MAX_FDS		11
 /*
  * We have AST_MAX_FDS file descriptors in a channel.
  * Some of them have a fixed use:
@@ -163,6 +163,7 @@
 #define AST_TIMING_FD	(AST_MAX_FDS-2)		/*!< used for timingfd */
 #define AST_AGENT_FD	(AST_MAX_FDS-3)		/*!< used by agents for pass through */
 #define AST_GENERATOR_FD	(AST_MAX_FDS-4)	/*!< used by generator */
+#define AST_JITTERBUFFER_FD	(AST_MAX_FDS-5)	/*!< used by generator */
 
 enum ast_bridge_result {
 	AST_BRIDGE_COMPLETE = 0,

Modified: team/dvossel/jb_ftw/main/abstract_jb.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/jb_ftw/main/abstract_jb.c?view=diff&rev=311924&r1=311923&r2=311924
==============================================================================
--- team/dvossel/jb_ftw/main/abstract_jb.c (original)
+++ team/dvossel/jb_ftw/main/abstract_jb.c Wed Mar 30 16:51:40 2011
@@ -104,20 +104,11 @@
 
 static int default_impl = 0;
 
-
-/*! Abstract return codes */
-enum {
-	JB_IMPL_OK,
-	JB_IMPL_DROP,
-	JB_IMPL_INTERP,
-	JB_IMPL_NOFRAME
-};
-
 /* Translations between impl and abstract return codes */
 static const int fixed_to_abstract_code[] =
-	{JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
+	{AST_JB_IMPL_OK, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME};
 static const int adaptive_to_abstract_code[] =
-	{JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
+	{AST_JB_IMPL_OK, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_INTERP, AST_JB_IMPL_DROP, AST_JB_IMPL_OK};
 
 /* JB_GET actions (used only for the frames log) */
 static const char * const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
@@ -311,7 +302,7 @@
 		return 0;
 	} else {
 		now = get_now(jb, NULL);
-		if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
+		if (jbimpl->put(jbobj, frr, now) != AST_JB_IMPL_OK) {
 			jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
 			ast_frfree(frr);
 			/*return -1;*/
@@ -368,16 +359,16 @@
 		res = jbimpl->get(jbobj, &f, now, interpolation_len);
 
 		switch (res) {
-		case JB_IMPL_OK:
+		case AST_JB_IMPL_OK:
 			/* deliver the frame */
 			ast_write(chan, f);
-		case JB_IMPL_DROP:
+		case AST_JB_IMPL_DROP:
 			jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
 				now, jb_get_actions[res], f->ts, f->len);
 			ast_format_copy(&jb->last_format, &f->subclass.format);
 			ast_frfree(f);
 			break;
-		case JB_IMPL_INTERP:
+		case AST_JB_IMPL_INTERP:
 			/* interpolate a frame */
 			f = &finterp;
 			ast_format_copy(&f->subclass.format, &jb->last_format);
@@ -389,9 +380,9 @@
 			ast_write(chan, f);
 			jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
 			break;
-		case JB_IMPL_NOFRAME:
+		case AST_JB_IMPL_NOFRAME:
 			ast_log(LOG_WARNING,
-				"JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
+				"AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
 				jbimpl->name, now, jb->next, jbimpl->next(jbobj));
 			jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
 			return;
@@ -429,7 +420,7 @@
 
 	/* The result of putting the first frame should not differ from OK. However, its possible
 	   some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
-	if (res != JB_IMPL_OK) {
+	if (res != AST_JB_IMPL_OK) {
 		ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
 		/*
 		jbimpl->destroy(jbobj);
@@ -473,7 +464,7 @@
 			}
 		}
 
-		if (res == JB_IMPL_OK) {
+		if (res == AST_JB_IMPL_OK) {
 			jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
 				now, frr->ts, frr->len);
 		} else {
@@ -485,7 +476,7 @@
 	ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
 
 	/* Free the frame if it has not been queued in the jb */
-	if (res != JB_IMPL_OK) {
+	if (res != AST_JB_IMPL_OK) {
 		ast_frfree(frr);
 	}
 
@@ -507,7 +498,7 @@
 
 	if (ast_test_flag(jb, JB_CREATED)) {
 		/* Remove and free all frames still queued in jb */
-		while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
+		while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
 			ast_frfree(f);
 		}
 

Modified: team/dvossel/jb_ftw/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/jb_ftw/main/channel.c?view=diff&rev=311924&r1=311923&r2=311924
==============================================================================
--- team/dvossel/jb_ftw/main/channel.c (original)
+++ team/dvossel/jb_ftw/main/channel.c Wed Mar 30 16:51:40 2011
@@ -3874,15 +3874,15 @@
 			ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
 	}
 
+	/* Perform the framehook read event here. After the frame enters the framehook list
+	 * there is no telling what will happen, <insert mad scientist laugh here>!!! */
+	f = ast_framehook_list_read_event(chan->framehooks, f);
+
 	/*
 	 * Reset the recorded file descriptor that triggered this read so that we can
 	 * easily detect when ast_read() is called without properly using ast_waitfor().
 	 */
 	chan->fdno = -1;
-
-	/* Perform the framehook read event here. After the frame enters the framehook list
-	 * there is no telling what will happen, <insert mad scientist laugh here>!!! */
-	f = ast_framehook_list_read_event(chan->framehooks, f);
 
 	if (f) {
 		struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq);




More information about the asterisk-commits mailing list