Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 37292)
+++ channels/chan_sip.c	(working copy)
@@ -493,6 +493,7 @@
 /* Global settings only apply to the channel */
 static int global_rtautoclear;
 static int global_notifyringing;	/*!< Send notifications on ringing */
+static int global_framems = 0;		/*!< Default audio payload in ms */
 static int global_alwaysauthreject;	/*!< Send 401 Unauthorized for all failing requests */
 static int srvlookup;			/*!< SRV Lookup on or off. Default is off, RFC behavior is on */
 static int pedanticsipchecking;		/*!< Extra checking ?  Default off */
@@ -953,6 +954,7 @@
 	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
 	struct sip_pvt *next;			/*!< Next dialog in chain */
 	struct sip_invite_param *options;	/*!< Options for INVITE */
+	int framems;				/*!< Packetization */
 } *iflist = NULL;
 
 #define FLAG_RESPONSE (1 << 0)
@@ -1000,6 +1002,7 @@
 	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	struct ast_ha *ha;		/*!< ACL setting */
 	struct ast_variable *chanvars;	/*!< Variables to set for channel created by user */
+	int framems;                    /*!< Audio payload Packetization */
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
 };
 
@@ -1061,6 +1064,7 @@
 	struct ast_variable *chanvars;	/*!<  Variables to set for channel created by user */
 	struct sip_pvt *mwipvt;		/*!<  Subscription for MWI */
 	int lastmsg;
+	int framems;                /* Packetization */
 };
 
 
@@ -2524,6 +2528,11 @@
 			ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", natflags ? "On" : "Off");
 		ast_udptl_setnat(r->udptl, natflags);
 	}
+	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_string_field_set(r, peername, peer->username);
 	ast_string_field_set(r, authname, peer->username);
 	ast_string_field_set(r, username, peer->username);
@@ -3684,6 +3693,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));
@@ -7892,6 +7902,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->flags[1], SIP_PAGE2_DYNAMIC)) {
 			ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
 		} else {
@@ -8622,6 +8638,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->flags[0], SIP_TRUSTRPID)) {
 			char *tmp;
@@ -8729,6 +8751,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);
 
@@ -9683,6 +9711,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)
@@ -14997,6 +15026,7 @@
 	if (!(user = ast_calloc(1, sizeof(*user))))
 		return NULL;
 		
+	user->framems = global_framems;
 	suserobjs++;
 	ASTOBJ_INIT(user);
 	ast_copy_string(user->name, name, sizeof(user->name));
@@ -15065,6 +15095,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)
@@ -15122,6 +15154,7 @@
 	peer->rtptimeout = global_rtptimeout;
 	peer->rtpholdtimeout = global_rtpholdtimeout;
 	peer->rtpkeepalive = global_rtpkeepalive;
+	peer->framems = global_framems;
 	peer->allowtransfer = global_allowtransfer;
 	strcpy(peer->vmexten, default_vmexten);
 	peer->secret[0] = '\0';
@@ -15146,6 +15179,7 @@
 	if (!(peer = ast_calloc(1, sizeof(*peer))))
 		return NULL;
 
+	peer->framems = global_framems;
 	apeerobjs++;
 	ASTOBJ_INIT(peer);
 	set_peer_defaults(peer);
@@ -15241,6 +15275,8 @@
 			ast_set2_flag(&peer->flags[0], 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) {
@@ -15544,6 +15580,8 @@
 			ast_copy_string(global_useragent, v->value, sizeof(global_useragent));
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Setting SIP channel User-Agent Name to %s\n", global_useragent);
+		} else if (!strcasecmp(v->name, "packetization")) {
+			global_framems = atoi(v->value);
 		} else if (!strcasecmp(v->name, "allowtransfer")) {
 			global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
 		} else if (!strcasecmp(v->name, "rtcachefriends")) {
Index: include/asterisk/rtp.h
===================================================================
--- include/asterisk/rtp.h	(revision 37292)
+++ include/asterisk/rtp.h	(working copy)
@@ -185,6 +185,8 @@
 
 int ast_rtp_reload(void);
 
+int ast_rtp_set_framems(struct ast_rtp *rtp, int ms);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
Index: include/asterisk/frame.h
===================================================================
--- include/asterisk/frame.h	(revision 37292)
+++ include/asterisk/frame.h	(working copy)
@@ -270,6 +270,7 @@
 };
 
 #define AST_SMOOTHER_FLAG_G729		(1 << 0)
+#define AST_SMOOTHER_FLAG_BE		(1 << 1)
 
 /* Option identifiers and flags */
 #define AST_OPTION_FLAG_REQUEST		0
@@ -440,6 +441,7 @@
 struct ast_format_list *ast_get_format_list(size_t *size);
 struct ast_smoother *ast_smoother_new(int bytes);
 void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
+int ast_smoother_test_flag(struct ast_smoother *s, int flag);
 int ast_smoother_get_flags(struct ast_smoother *smoother);
 void ast_smoother_free(struct ast_smoother *s);
 void ast_smoother_reset(struct ast_smoother *s, int bytes);
Index: rtp.c
===================================================================
--- rtp.c	(revision 37292)
+++ rtp.c	(working copy)
@@ -135,6 +135,8 @@
 	unsigned int dtmfduration;
 	int nat;
 	unsigned int flags;
+	unsigned int framems;           /*!< Codec packetization */
+	unsigned int rtplen;
 	struct sockaddr_in us;		/*!< Socket representation of the local endpoint. */
 	struct sockaddr_in them;	/*!< Socket representation of the remote endpoint. */
 	struct timeval rxcore;
@@ -485,6 +487,51 @@
 	*lsw = frac;
 }
 
+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_ALAW, 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;
@@ -526,6 +573,20 @@
 	ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
 }
 
+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)
 {
 	char iabuf[INET_ADDRSTRLEN];
@@ -2346,98 +2407,43 @@
 	}
 
 
-	switch(subclass) {
-	case AST_FORMAT_SLINEAR:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(320);
+	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);
+			}
+
+			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 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_be(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;
-	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_log(LOG_WARNING, "Unable to create ILBC 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;
-	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_H264:
-	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 {
@@ -2445,7 +2451,7 @@
 		}
 		ast_rtp_raw_write(rtp, f, codec);
 	}
-		
+
 	return 0;
 }
 
Index: frame.c
===================================================================
--- frame.c	(revision 37292)
+++ frame.c	(working copy)
@@ -137,6 +137,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: configs/sip.conf.sample
===================================================================
--- configs/sip.conf.sample	(revision 37292)
+++ configs/sip.conf.sample	(working copy)
@@ -101,6 +101,7 @@
 
 ;compactheaders = yes		; send compact sip headers.
 ;
+;packetization = 20		; The global size in ms of the rtp packets
 ;videosupport=yes		; Turn on support for SIP video
 ;maxcallbitrate=384		; Maximum bitrate for video calls (default 384 kb/s)
 				; Videosupport and maxcallbitrate is settable
@@ -528,8 +529,8 @@
 ;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
 ;secret=blah
