diff -ur /usr/src/asterisk/channels/chan_sip.c asterisk/channels/chan_sip.c
--- /usr/src/asterisk/channels/chan_sip.c	2005-12-29 10:25:25.000000000 -0800
+++ /usr/src/asterisk/channels/chan_sip.c	2005-12-29 11:09:11.000000000 -0800
@@ -347,6 +347,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 */
@@ -692,6 +694,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)
@@ -739,6 +742,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 registered  or fixed IP address (host) */
@@ -795,6 +799,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);
@@ -1861,6 +1866,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));
@@ -2002,7 +2015,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);
@@ -2782,6 +2794,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));
@@ -3057,6 +3070,7 @@
 			free(p);
 			return NULL;
 		}
+
 		ast_rtp_settos(p->rtp, tos);
 		if (p->vrtp)
 			ast_rtp_settos(p->vrtp, tos);
@@ -6371,6 +6385,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 {
@@ -6988,6 +7008,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)
@@ -7066,6 +7092,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 */
@@ -7938,6 +7970,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)
@@ -11842,6 +11875,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));
@@ -11906,6 +11940,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)
@@ -11927,6 +11963,7 @@
 		return NULL;
 
 	memset(peer, 0, sizeof(*peer));
+	peer->framems = global_framems;
 	apeerobjs++;
 	ASTOBJ_INIT(peer);
 
@@ -11982,6 +12019,7 @@
 		peer = malloc(sizeof(*peer));
 		if (peer) {
 			memset(peer, 0, sizeof(*peer));
+			peer->framems = global_framems;
 			if (realtime)
 				rpeerobjs++;
 			else
@@ -12070,6 +12108,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) {
@@ -12313,6 +12353,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")) {
diff -ur /usr/src/asterisk/configs/sip.conf.sample asterisk/configs/sip.conf.sample
--- /usr/src/asterisk/configs/sip.conf.sample	2005-12-29 10:25:41.000000000 -0800
+++ /usr/src/asterisk/configs/sip.conf.sample	2005-12-29 11:10:09.000000000 -0800
@@ -102,6 +102,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
 ;subscribecontext = default	; Set a specific context for SUBSCRIBE requests
 				; Useful to limit subscriptions to local extensions
 				; Settable per peer/user also
@@ -405,7 +406,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
diff -ur /usr/src/asterisk/frame.c asterisk/frame.c
--- /usr/src/asterisk/frame.c	2005-12-29 10:25:42.000000000 -0800
+++ /usr/src/asterisk/frame.c	2005-12-29 11:05:05.000000000 -0800
@@ -134,6 +134,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) {
diff -ur /usr/src/asterisk/include/asterisk/frame.h asterisk/include/asterisk/frame.h
--- /usr/src/asterisk/include/asterisk/frame.h	2005-12-29 10:25:26.000000000 -0800
+++ /usr/src/asterisk/include/asterisk/frame.h	2005-12-29 11:05:05.000000000 -0800
@@ -245,6 +245,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
@@ -404,6 +405,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);
diff -ur /usr/src/asterisk/include/asterisk/rtp.h asterisk/include/asterisk/rtp.h
--- /usr/src/asterisk/include/asterisk/rtp.h	2005-12-29 10:25:26.000000000 -0800
+++ /usr/src/asterisk/include/asterisk/rtp.h	2005-12-29 11:05:05.000000000 -0800
@@ -161,6 +161,8 @@
 
 void ast_rtp_reload(void);
 
+int ast_rtp_set_framems(struct ast_rtp *rtp, int ms);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff -ur /usr/src/asterisk/rtp.c asterisk/rtp.c
--- /usr/src/asterisk/rtp.c	2005-12-29 10:25:42.000000000 -0800
+++ /usr/src/asterisk/rtp.c	2005-12-29 11:06:26.000000000 -0800
@@ -103,6 +103,8 @@
 	unsigned int dtmfduration;
 	int nat;
 	unsigned int flags;
+	int framems;
+	int rtplen;
 	/*! Socket representation of the local endpoint. */
 	struct sockaddr_in us;
 	/*! Socket representation of the remote endpoint. */
@@ -148,6 +150,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;
@@ -175,6 +221,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, };
@@ -1427,98 +1487,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;
-		}
-		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_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);
 		}
-		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 {
@@ -1526,7 +1531,7 @@
 		}
 		ast_rtp_raw_write(rtp, f, codec);
 	}
-		
+
 	return 0;
 }
 
