[asterisk-commits] kpfleming: branch 1.4 r180372 - in /branches/1.4: include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Mar 5 12:22:31 CST 2009


Author: kpfleming
Date: Thu Mar  5 12:22:16 2009
New Revision: 180372

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=180372
Log:
Fix problems when RTP packet frame size is changed

During some code analysis, I found that calling ast_rtp_codec_setpref() on an ast_rtp session does not work as expected; it does not adjust the smoother that may on the RTP session, in fact it summarily drops it, even if it has data in it, even if the current format's framing size has not changed. This is not good.

This patch changes this behavior, so that if the packetization size for the current format changes, any existing smoother is safely updated to use the new size, and if no smoother was present, one is created. A new API call for smoothers, ast_smoother_reconfigure(), was required to implement these changes.

Review: http://reviewboard.digium.com/r/184/


Modified:
    branches/1.4/include/asterisk/frame.h
    branches/1.4/main/frame.c
    branches/1.4/main/rtp.c

Modified: branches/1.4/include/asterisk/frame.h
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/include/asterisk/frame.h?view=diff&rev=180372&r1=180371&r2=180372
==============================================================================
--- branches/1.4/include/asterisk/frame.h (original)
+++ branches/1.4/include/asterisk/frame.h Thu Mar  5 12:22:16 2009
@@ -478,6 +478,16 @@
 int ast_smoother_test_flag(struct ast_smoother *s, int flag);
 void ast_smoother_free(struct ast_smoother *s);
 void ast_smoother_reset(struct ast_smoother *s, int bytes);
+
+/*!
+ * \brief Reconfigure an existing smoother to output a different number of bytes per frame
+ * \param s the smoother to reconfigure
+ * \param bytes the desired number of bytes per output frame
+ * \return nothing
+ *
+ */
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
+
 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
 struct ast_frame *ast_smoother_read(struct ast_smoother *s);
 #define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)

Modified: branches/1.4/main/frame.c
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/main/frame.c?view=diff&rev=180372&r1=180371&r2=180372
==============================================================================
--- branches/1.4/main/frame.c (original)
+++ branches/1.4/main/frame.c Thu Mar  5 12:22:16 2009
@@ -93,10 +93,9 @@
 struct ast_smoother {
 	int size;
 	int format;
-	int readdata;
-	int optimizablestream;
 	int flags;
 	float samplesperbyte;
+	unsigned int opt_needs_swap:1;
 	struct ast_frame f;
 	struct timeval delivery;
 	char data[SMOOTHER_SIZE];
@@ -139,10 +138,54 @@
 
 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
 
-void ast_smoother_reset(struct ast_smoother *s, int size)
+static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+	if (s->flags & AST_SMOOTHER_FLAG_G729) {
+		if (s->len % 10) {
+			ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
+			return 0;
+		}
+	}
+	if (swap) {
+		ast_swapcopy_samples(s->data + s->len, f->data, f->samples);
+	} else {
+		memcpy(s->data + s->len, f->data, f->datalen);
+	}
+	/* If either side is empty, reset the delivery time */
+	if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) {	/* XXX really ? */
+		s->delivery = f->delivery;
+	}
+	s->len += f->datalen;
+
+	return 0;
+}
+
+void ast_smoother_reset(struct ast_smoother *s, int bytes)
 {
 	memset(s, 0, sizeof(*s));
-	s->size = size;
+	s->size = bytes;
+}
+
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
+{
+	/* if there is no change, then nothing to do */
+	if (s->size == bytes) {
+		return;
+	}
+	/* set the new desired output size */
+	s->size = bytes;
+	/* if there is no 'optimized' frame in the smoother,
+	 *   then there is nothing left to do
+	 */
+	if (!s->opt) {
+		return;
+	}
+	/* there is an 'optimized' frame here at the old size,
+	 * but it must now be put into the buffer so the data
+	 * can be extracted at the new size
+	 */
+	smoother_frame_feed(s, s->opt, s->opt_needs_swap);
+	s->opt = NULL;
 }
 
 struct ast_smoother *ast_smoother_new(int size)
@@ -187,33 +230,22 @@
 		ast_log(LOG_WARNING, "Out of smoother space\n");
 		return -1;
 	}
-	if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
-				 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
-		if (!s->len) {
-			/* Optimize by sending the frame we just got
-			   on the next read, thus eliminating the douple
-			   copy */
-			if (swap)
-				ast_swapcopy_samples(f->data, f->data, f->samples);
-			s->opt = f;
-			return 0;
-		}
-	}
-	if (s->flags & AST_SMOOTHER_FLAG_G729) {
-		if (s->len % 10) {
-			ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
-			return 0;
-		}
-	}
-	if (swap)
-		ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
-	else
-		memcpy(s->data + s->len, f->data, f->datalen);
-	/* If either side is empty, reset the delivery time */
-	if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))	/* XXX really ? */
-		s->delivery = f->delivery;
-	s->len += f->datalen;
-	return 0;
+	if (((f->datalen == s->size) ||
+	     ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
+	    !s->opt &&
+	    !s->len &&
+	    (f->offset >= AST_MIN_OFFSET)) {
+		/* Optimize by sending the frame we just got
+		   on the next read, thus eliminating the douple
+		   copy */
+		if (swap)
+			ast_swapcopy_samples(f->data, f->data, f->samples);
+		s->opt = f;
+		s->opt_needs_swap = swap ? 1 : 0;
+		return 0;
+	}
+
+	return smoother_frame_feed(s, f, swap);
 }
 
 struct ast_frame *ast_smoother_read(struct ast_smoother *s)

Modified: branches/1.4/main/rtp.c
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/main/rtp.c?view=diff&rev=180372&r1=180371&r2=180372
==============================================================================
--- branches/1.4/main/rtp.c (original)
+++ branches/1.4/main/rtp.c Thu Mar  5 12:22:16 2009
@@ -2723,14 +2723,48 @@
 
 int ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs)
 {
-	int x;
-	for (x = 0; x < 32; x++) {  /* Ugly way */
-		rtp->pref.order[x] = prefs->order[x];
-		rtp->pref.framing[x] = prefs->framing[x];
-	}
-	if (rtp->smoother)
-		ast_smoother_free(rtp->smoother);
-	rtp->smoother = NULL;
+	struct ast_format_list current_format_old, current_format_new;
+
+	/* if no packets have been sent through this session yet, then
+	 *  changing preferences does not require any extra work
+	 */
+	if (rtp->lasttxformat == 0) {
+		rtp->pref = *prefs;
+		return 0;
+	}
+
+	current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
+
+	rtp->pref = *prefs;
+
+	current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
+
+	/* if the framing desired for the current format has changed, we may have to create
+	 * or adjust the smoother for this session
+	 */
+	if ((current_format_new.inc_ms != 0) &&
+	    (current_format_new.cur_ms != current_format_old.cur_ms)) {
+		int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
+
+		if (rtp->smoother) {
+			ast_smoother_reconfigure(rtp->smoother, new_size);
+			if (option_debug) {
+				ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
+			}
+		} else {
+			if (!(rtp->smoother = ast_smoother_new(new_size))) {
+				ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
+				return -1;
+			}
+			if (current_format_new.flags) {
+				ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
+			}
+			if (option_debug) {
+				ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
+			}
+		}
+	}
+
 	return 0;
 }
 




More information about the asterisk-commits mailing list