Index: trunk/include/asterisk/rtp.h
===================================================================
--- trunk/include/asterisk/rtp.h	(revision 33812)
+++ trunk/include/asterisk/rtp.h	(working copy)
@@ -62,7 +62,6 @@
 	AST_LIST_ENTRY(ast_rtp_protocol) list;
 };
 
-
 #define FLAG_3389_WARNING		(1 << 0)
 
 typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
@@ -185,6 +184,14 @@
 
 int ast_rtp_reload(void);
 
+int ast_rtp_set_framems(struct ast_rtp *rtp, int ms);
+
+void ast_rtp_set_codec_info(struct ast_rtp *rtp, struct ast_codec_pref *pref);
+
+void ast_rtp_set_codec_size(struct ast_rtp *rtp, int format, int ms);
+
+int ast_rtp_get_codec_size(struct ast_rtp *rtp, int format);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
Index: trunk/include/asterisk/frame.h
===================================================================
--- trunk/include/asterisk/frame.h	(revision 33812)
+++ trunk/include/asterisk/frame.h	(working copy)
@@ -35,6 +35,7 @@
 
 struct ast_codec_pref {
 	char order[32];
+	char psize[32];
 };
 
 /*! \page Def_Frame AST Multimedia and signalling frames
@@ -270,6 +271,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
@@ -445,6 +447,7 @@
 void ast_smoother_reset(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);
+extern int ast_smoother_test_flag(struct ast_smoother *s, int flag);
 #define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
@@ -482,6 +485,10 @@
 */
 int ast_codec_pref_append(struct ast_codec_pref *pref, int format);
 
+/*! \brief Set packet size for codec
+*/
+int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems);
+
 /*! \brief Select the best audio format according to preference list from supplied options. 
    If "find_best" is non-zero then if nothing is found, the "Best" format of 
    the format list is selected, otherwise 0 is returned. */
Index: trunk/rtp.c
===================================================================
--- trunk/rtp.c	(revision 33812)
+++ trunk/rtp.c	(working copy)
@@ -103,6 +103,11 @@
 };
 
 
+struct ast_rtp_codec {
+	int format;
+	int size;
+};
+
 /*! \brief RTP session description */
 struct ast_rtp {
 	int s;
@@ -134,6 +139,8 @@
 	int dtmfcount;
 	unsigned int dtmfduration;
 	int nat;
+	int framems;
+	int rtplen;
 	unsigned int flags;
 	struct sockaddr_in us;		/*!< Socket representation of the local endpoint. */
 	struct sockaddr_in them;	/*!< Socket representation of the remote endpoint. */
@@ -155,6 +162,7 @@
 	int rtp_lookup_code_cache_code;
 	int rtp_lookup_code_cache_result;
 	struct ast_rtcp *rtcp;
+	struct ast_rtp_codec codecs[32];
 };
 
 /* Forward declarations */
@@ -475,6 +483,90 @@
 /*! \brief List of current sessions */
 static AST_LIST_HEAD_STATIC(protos, ast_rtp_protocol);
 
+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;
+}
+
+void ast_rtp_set_codec_info(struct ast_rtp *rtp, struct ast_codec_pref *pref)
+{
+	int x;
+	for (x = 0; x < 32; x++) {
+		rtp->codecs[x].format = pref->order[x];
+		rtp->codecs[x].size = pref->psize[x];
+	}
+	if (rtp->smoother) {
+		ast_smoother_free(rtp->smoother);
+		rtp->smoother = NULL;
+	}
+}
+
+void ast_rtp_set_codec_size(struct ast_rtp *rtp, int format, int ms)
+{
+	int x;
+	for(x = 0 ; x < 32 ; x++) {
+        	if (rtp->codecs[x].format == format) {
+                	rtp->codecs[x].size = ms;
+        	}
+	}
+	if (rtp->smoother) {
+		ast_smoother_free(rtp->smoother);
+		rtp->smoother = NULL;
+	}
+
+}
+
+int ast_rtp_get_codec_size(struct ast_rtp *rtp, int format)
+{
+	int x;
+	for(x = 0 ; x < 32 ; x++) {
+		if (rtp->codecs[x].format == format) {
+			return rtp->codecs[x].size;
+		}
+	}
+	return 0;
+}
+
 static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
 {
 	unsigned int sec, usec, frac;
@@ -521,6 +613,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;
+}
+
 void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
 {
 	ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
@@ -2341,99 +2447,44 @@
 		rtp->smoother = NULL;
 	}
 
+	
+	if (!rtp->smoother) {
+		struct rtp_codec_table *ent;
+		rtp->framems = ast_rtp_get_codec_size(rtp, subclass);
+		int ms = rtp->framems;
+		int len;
 
-	switch(subclass) {
-	case AST_FORMAT_SLINEAR:
-		if (!rtp->smoother) {
-			rtp->smoother = ast_smoother_new(320);
+		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 {
Index: trunk/frame.c
===================================================================
--- trunk/frame.c	(revision 33812)
+++ trunk/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) {
@@ -1000,7 +1005,22 @@
 	return x;
 }
 
+/*! \brief Set packet size for codec */
+int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
+{
+	int x;
 
+	for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+		if(pref->order[x] == format) {
+			pref->psize[x] = framems;
+			break;
+		}
+	}
+
+	return x;
+}
+
+
 /*! \brief Pick a codec */
 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
 {
@@ -1029,10 +1049,20 @@
 {
 	char *parse;
 	char *this;
+	char *psize;
+	int framems;
 	int format;
 
 	parse = ast_strdupa(list);
 	while ((this = strsep(&parse, ","))) {
+		if ((psize=strrchr(this,':'))) {
+			psize='\0';
+			psize++;
+			framems=strtol(psize,NULL,10);
+			if (framems==LONG_MIN || framems==LONG_MAX) {
+				framems=0;
+			}
+		}
 		if (!(format = ast_getformatbyname(this))) {
 			ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
 			continue;
@@ -1050,9 +1080,10 @@
 		 */
 		if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
 			if (strcasecmp(this, "all")) {
-				if (allowing)
+				if (allowing) {
 					ast_codec_pref_append(pref, format);
-				else
+					ast_codec_pref_setsize(pref, format, framems);
+				} else
 					ast_codec_pref_remove(pref, format);
 			} else if (!allowing) {
 				memset(pref, 0, sizeof(*pref));
