Index: frame.c
===================================================================
RCS file: /usr/cvsroot/asterisk/frame.c,v
retrieving revision 1.62
diff -u -r1.62 frame.c
--- frame.c	22 Aug 2005 19:29:29 -0000	1.62
+++ frame.c	9 Sep 2005 14:43:13 -0000
@@ -93,6 +93,11 @@
 	s->flags = flags;
 }
 
+int ast_smoother_test_flag(struct ast_smoother *s, int flag)
+{
+	return (s->flags & flag);
+}
+
 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
 {
 	if (f->frametype != AST_FRAME_VOICE) {
Index: rtp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/rtp.c,v
retrieving revision 1.144
diff -u -r1.144 rtp.c
--- rtp.c	7 Sep 2005 20:33:30 -0000	1.144
+++ rtp.c	9 Sep 2005 14:43:13 -0000
@@ -49,7 +49,6 @@
 #define RTP_MTU		1200
 
 static int dtmftimeout = 3000;	/* 3000 samples */
-
 static int rtpstart = 0;
 static int rtpend = 0;
 static int rtpdebug = 0;		/* Are we debugging? */
@@ -90,6 +89,8 @@
 	unsigned int dtmfduration;
 	int nat;
 	unsigned int flags;
+	int framems;
+	int rtplen;
 	struct sockaddr_in us;
 	struct sockaddr_in them;
 	struct timeval rxcore;
@@ -119,6 +120,50 @@
 
 static struct ast_rtp_protocol *protos = NULL;
 
+struct rtp_codec_table {
+	int format;
+	int len;
+	int defaultms;
+	int increment;
+	unsigned int flags;
+};
+
+struct rtp_codec_table RTP_CODEC_TABLE[] = {
+	{AST_FORMAT_SLINEAR, 160, 20, 10, AST_SMOOTHER_FLAG_BE},
+	{AST_FORMAT_ULAW, 80, 20, 10},
+	{AST_FORMAT_G726, 40, 20, 10},
+	{AST_FORMAT_ILBC, 50, 30, 30},
+	{AST_FORMAT_G729A, 10, 20, 10, AST_SMOOTHER_FLAG_G729},
+	{AST_FORMAT_GSM, 33, 20, 20},
+	{0,0,0,0,0}
+};
+
+static struct rtp_codec_table *lookup_rtp_smoother_codec(int format, int *ms, int *len)
+{
+	int x;
+	int res;
+	struct rtp_codec_table *ent = NULL;
+
+	*len = 0;
+	for(x = 0 ; RTP_CODEC_TABLE[x].format ; x++) {
+		if (RTP_CODEC_TABLE[x].format == format) {
+			ent = &RTP_CODEC_TABLE[x];
+			if (! *ms) {
+				*ms = ent->defaultms;
+			}
+			while((res = (*ms % ent->increment))) {
+				(*ms)++;
+			}
+			while((*len = (*ms / ent->increment) * ent->len) > RTP_MTU) {
+				*ms -= ent->increment;
+			}
+			break;
+		}
+	}
+
+	return ent;
+}
+
 int ast_rtp_fd(struct ast_rtp *rtp)
 {
 	return rtp->s;
@@ -146,6 +191,20 @@
 	rtp->nat = nat;
 }
 
+int ast_rtp_set_framems(struct ast_rtp *rtp, int ms) 
+{
+	if (ms) {
+		if (rtp->smoother) {
+            ast_smoother_free(rtp->smoother);
+			rtp->smoother = NULL;
+		}
+
+		rtp->framems = ms;
+	}
+
+	return rtp->framems;
+}
+
 static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
 {
 	static struct ast_frame null_frame = { AST_FRAME_NULL, };
@@ -1286,98 +1345,43 @@
 		rtp->smoother = NULL;
 	}
 
+	
+	if (!rtp->smoother) {
+		struct rtp_codec_table *ent;
+		int ms = rtp->framems;
+		int len;
+
+		if ((ent = lookup_rtp_smoother_codec(subclass, &rtp->framems, &len))) {
+			
+			if (rtp->framems != ms) {
+				ast_log(LOG_DEBUG, "Had to change frame MS from %d to %d\n", ms, rtp->framems);
+			}
 
-	switch(subclass) {
-	case AST_FORMAT_SLINEAR:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(320);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create smoother :(\n");
-			return -1;
-		}
-		ast_smoother_feed_be(rtp->smoother, _f);
-		
-		while((f = ast_smoother_read(rtp->smoother)))
-			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	case AST_FORMAT_ULAW:
-	case AST_FORMAT_ALAW:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(160);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create smoother :(\n");
-			return -1;
-		}
-		ast_smoother_feed(rtp->smoother, _f);
-		
-		while((f = ast_smoother_read(rtp->smoother)))
-			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	case AST_FORMAT_ADPCM:
-	case AST_FORMAT_G726:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(80);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create smoother :(\n");
-			return -1;
-		}
-		ast_smoother_feed(rtp->smoother, _f);
-		
-		while((f = ast_smoother_read(rtp->smoother)))
-			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	case AST_FORMAT_G729A:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(20);
-			if (rtp->smoother)
-				ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
-			return -1;
-		}
-		ast_smoother_feed(rtp->smoother, _f);
-		
-		while((f = ast_smoother_read(rtp->smoother)))
-			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	case AST_FORMAT_GSM:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(33);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
-			return -1;
+			if (!(rtp->smoother = ast_smoother_new(len))) {
+				ast_log(LOG_WARNING, "Unable to create smoother ms: %d len: %d:(\n", rtp->framems, len);
+				return -1;
+			}
+
+			if (ent->flags) {
+				ast_smoother_set_flags(rtp->smoother, ent->flags);			
+			}
+
+			ast_log(LOG_DEBUG, "Able to create smoother :) ms: %d len %d\n", rtp->framems, len);
 		}
-		ast_smoother_feed(rtp->smoother, _f);
-		while((f = ast_smoother_read(rtp->smoother)))
-			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	case AST_FORMAT_ILBC:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(50);
-		}
-		if (!rtp->smoother) {
-			ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
-			return -1;
+	}
+
+	if (rtp->smoother) {
+		if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
+			ast_smoother_feed_be(rtp->smoother, _f);
+		} else {
+			ast_smoother_feed(rtp->smoother, _f);
 		}
-		ast_smoother_feed(rtp->smoother, _f);
-		while((f = ast_smoother_read(rtp->smoother)))
+
+		while((f = ast_smoother_read(rtp->smoother))) {
 			ast_rtp_raw_write(rtp, f, codec);
-		break;
-	default:	
-		ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
-		/* fall through to... */
-	case AST_FORMAT_H261:
-	case AST_FORMAT_H263:
-	case AST_FORMAT_H263_PLUS:
-	case AST_FORMAT_G723_1:
-	case AST_FORMAT_LPC10:
-	case AST_FORMAT_SPEEX:
-	        /* Don't buffer outgoing frames; send them one-per-packet: */
+		} 
+	} else {
+		/* Don't buffer outgoing frames; send them one-per-packet: */
 		if (_f->offset < hdrlen) {
 			f = ast_frdup(_f);
 		} else {
@@ -1385,7 +1389,7 @@
 		}
 		ast_rtp_raw_write(rtp, f, codec);
 	}
-		
+
 	return 0;
 }
 
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.845
diff -u -r1.845 chan_sip.c
--- channels/chan_sip.c	8 Sep 2005 15:34:38 -0000	1.845
+++ channels/chan_sip.c	9 Sep 2005 14:43:13 -0000
@@ -322,6 +322,8 @@
 
 static int global_notifyringing = 1;	/* Send notifications on ringing */
 
+static int global_framems = 0;
+
 static int default_qualify = 0;		/* Default Qualify= setting */
 
 static struct ast_flags global_flags = {0};		/* global SIP_ flags */
@@ -605,7 +607,7 @@
 	time_t ospstart;			/* OSP Start time */
 #endif
 	struct sip_request initreq;		/* Initial request */
-	
+
 	int maxtime;				/* Max time for first response */
 	int maxforwards;			/* keep the max-forwards info */
 	int initid;				/* Auto-congest ID if appropriate */
@@ -631,6 +633,7 @@
 	struct ast_variable *chanvars;		/* Channel variables to set for call */
 	struct sip_pvt *next;			/* Next call in chain */
 	struct sip_invite_param *options;	/* Options for INVITE */
+	int framems;                /* Packetization */
 } *iflist = NULL;
 
 #define FLAG_RESPONSE (1 << 0)
@@ -678,6 +681,7 @@
 	int call_limit;			/* Limit of concurrent calls */
 	struct ast_ha *ha;		/* ACL setting */
 	struct ast_variable *chanvars;	/* Variables to set for channel created by user */
+	int framems;                /* Packetization */
 };
 
 /* Structure for SIP peer data, we place calls to peers if registred  or fixed IP address (host) */
@@ -736,6 +740,7 @@
 	struct ast_ha *ha;		/* Access control list */
 	struct ast_variable *chanvars;	/* Variables to set for channel created by user */
 	int lastmsg;
+	int framems;                /* Packetization */
 };
 
 AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
@@ -1785,6 +1790,14 @@
 		ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
 		ast_rtp_setnat(r->vrtp, (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
 	}
+
+
+	r->framems = peer->framems;
+	/* Set Frame packetization, use default if it doesn't exist. */
+	if (r->rtp && r->framems) {
+		ast_rtp_set_framems(r->rtp, r->framems);
+	}
+
 	ast_copy_string(r->peername, peer->username, sizeof(r->peername));
 	ast_copy_string(r->authname, peer->username, sizeof(r->authname));
 	ast_copy_string(r->username, peer->username, sizeof(r->username));
@@ -1926,7 +1939,6 @@
 	struct ast_var_t *current;
 	
 
-	
 	p = ast->tech_pvt;
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name);
@@ -2689,6 +2701,7 @@
 	i->owner = tmp;
 	ast_mutex_lock(&usecnt_lock);
 	usecnt++;
+
 	ast_mutex_unlock(&usecnt_lock);
 	ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
 	ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
@@ -2950,6 +2963,7 @@
 			free(p);
 			return NULL;
 		}
+
 		ast_rtp_settos(p->rtp, tos);
 		if (p->vrtp)
 			ast_rtp_settos(p->vrtp, tos);
@@ -5983,6 +5997,12 @@
 			ASTOBJ_UNREF(peer,sip_destroy_peer);
 	}
 	if (peer) {
+		p->framems = peer->framems;
+		/* Set Frame packetization, use default if it doesn't exist. */
+		if (p->rtp && p->framems) {
+			ast_rtp_set_framems(p->rtp, p->framems);
+		}
+
 		if (!ast_test_flag(peer, SIP_DYNAMIC)) {
 			ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
 		} else {
@@ -6552,6 +6572,12 @@
 			}
 		}
 		p->prefs = user->prefs;
+		p->framems = user->framems;
+		/* Set Frame packetization, use default if it doesn't exist. */
+		if (p->rtp && p->framems) {
+			ast_rtp_set_framems(p->rtp, p->framems);
+		}
+
 		/* replace callerid if rpid found, and not restricted */
 		if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
 			if (*calleridname)
@@ -6625,6 +6651,12 @@
  		*/
 		peer = find_peer(NULL, &p->recv, 1);
 		if (peer) {
+			p->framems = peer->framems;
+			/* Set Frame packetization, use default if it doesn't exist. */
+			if (p->rtp && p->framems) {
+				ast_rtp_set_framems(p->rtp, p->framems);
+			}
+
 			if (debug)
 				ast_verbose("Found peer '%s'\n", peer->name);
 			/* Take the peer */
@@ -7471,6 +7503,7 @@
 		ast_cli(fd, "%s\n",status);
  		ast_cli(fd, "  Useragent    : %s\n", peer->useragent);
  		ast_cli(fd, "  Reg. Contact : %s\n", peer->fullcontact);
+ 		ast_cli(fd, "  Packetization: %d\n", peer->framems);
 		if (peer->chanvars) {
  			ast_cli(fd, "  Variables    :\n");
 			for (v = peer->chanvars ; v ; v = v->next)
@@ -11155,6 +11188,7 @@
 		return NULL;
 	}
 	memset(user, 0, sizeof(struct sip_user));
+	user->framems = global_framems;
 	suserobjs++;
 	ASTOBJ_INIT(user);
 	ast_copy_string(user->name, name, sizeof(user->name));
@@ -11223,6 +11257,8 @@
 			ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
 		} else if (!strcasecmp(v->name, "disallow")) {
 			ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 0);
+		} else if (!strcasecmp(v->name, "packetization")) {
+			user->framems = atoi(v->value);
 		} else if (!strcasecmp(v->name, "callingpres")) {
 			user->callingpres = ast_parse_caller_presentation(v->value);
 			if (user->callingpres == -1)
@@ -11248,6 +11284,7 @@
 		return NULL;
 
 	memset(peer, 0, sizeof(*peer));
+	peer->framems = global_framems;
 	apeerobjs++;
 	ASTOBJ_INIT(peer);
 
@@ -11304,6 +11341,7 @@
 		peer = malloc(sizeof(*peer));
 		if (peer) {
 			memset(peer, 0, sizeof(*peer));
+			peer->framems = global_framems;
 			if (realtime)
 				rpeerobjs++;
 			else
@@ -11393,6 +11431,8 @@
 			ast_set2_flag(peer, ast_true(v->value), SIP_USEREQPHONE);
 		else if (!strcasecmp(v->name, "fromuser"))
 			ast_copy_string(peer->fromuser, v->value, sizeof(peer->fromuser));
+		else if (!strcasecmp(v->name, "packetization"))
+			peer->framems = atoi(v->value);
 		else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "outboundproxy")) {
 			if (!strcasecmp(v->value, "dynamic")) {
 				if (!strcasecmp(v->name, "outboundproxy") || obproxyfound) {
@@ -11639,6 +11679,8 @@
 			ast_copy_string(default_useragent, v->value, sizeof(default_useragent));
 			ast_log(LOG_DEBUG, "Setting User Agent Name to %s\n",
 				default_useragent);
+		} else if (!strcasecmp(v->name, "packetization")) {
+			global_framems = atoi(v->value);
 		} else if (!strcasecmp(v->name, "rtcachefriends")) {
 			ast_set2_flag((&global_flags_page2), ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);	
 		} else if (!strcasecmp(v->name, "rtupdate")) {
Index: include/asterisk/frame.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/frame.h,v
retrieving revision 1.57
diff -u -r1.57 frame.h
--- include/asterisk/frame.h	8 Sep 2005 03:23:38 -0000	1.57
+++ include/asterisk/frame.h	9 Sep 2005 14:43:13 -0000
@@ -197,6 +197,7 @@
 #define AST_CONTROL_VIDUPDATE		18
 
 #define AST_SMOOTHER_FLAG_G729		(1 << 0)
+#define AST_SMOOTHER_FLAG_BE		(1 << 1)
 
 /* Option identifiers and flags */
 #define AST_OPTION_FLAG_REQUEST		0
@@ -365,6 +366,7 @@
 extern struct ast_format_list *ast_get_format_list(size_t *size);
 extern struct ast_smoother *ast_smoother_new(int bytes);
 extern void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
+extern int ast_smoother_test_flag(struct ast_smoother *s, int flag);
 extern int ast_smoother_get_flags(struct ast_smoother *smoother);
 extern void ast_smoother_free(struct ast_smoother *s);
 extern void ast_smoother_reset(struct ast_smoother *s, int bytes);
Index: include/asterisk/rtp.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/rtp.h,v
retrieving revision 1.23
diff -u -r1.23 rtp.h
--- include/asterisk/rtp.h	30 Aug 2005 18:32:10 -0000	1.23
+++ include/asterisk/rtp.h	9 Sep 2005 14:43:13 -0000
@@ -130,6 +130,8 @@
 
 void ast_rtp_reload(void);
 
+int ast_rtp_set_framems(struct ast_rtp *rtp, int ms);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
Index: configs/sip.conf.sample
===================================================================
RCS file: /usr/cvsroot/asterisk/configs/sip.conf.sample,v
retrieving revision 1.68
diff -u -r1.68 sip.conf.sample
--- configs/sip.conf.sample	6 Sep 2005 21:04:40 -0000	1.68
+++ configs/sip.conf.sample	9 Sep 2005 14:43:13 -0000
@@ -88,6 +88,7 @@
 ;compactheaders = yes		; send compact sip headers.
 ;sipdebug = yes			; Turn on SIP debugging by default, from
 				; the moment the channel loads this configuration
+;packetization = 20		; The global size in ms of the rtp packets
 
 ;
 ; If regcontext is specified, Asterisk will dynamically 
@@ -349,7 +350,7 @@
 ;disallow=all
 ;allow=ulaw                     ; dtmfmode=inband only works with ulaw or alaw!
 ;progressinband=no		; Polycom phones don't work properly with "never"
-
+;packetization = 20		; the size in ms of the rtp packets
 
 ;[pingtel]
 ;type=friend
