diff -u orig/chan_sip.c changed/chan_sip.c
--- orig/chan_sip.c	2006-07-13 20:44:23.000000000 +0400
+++ changed/chan_sip.c	2006-08-12 15:20:47.000000000 +0400
@@ -1878,6 +1878,9 @@
 		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));
 	}
+	if(r->rtp) {
+		ast_rtp_codec_setpref(r->rtp, &r->prefs);
+	}
 	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));
@@ -4351,19 +4354,33 @@
 			     int debug)
 {
 	int rtp_code;
+	struct ast_format_list fmt;
 
 	if (debug)
 		ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
 	if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1)
 		return;
 
+	if (p->rtp) {
+		struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
+		fmt = ast_codec_pref_getsize(pref, codec);
+	}
 	ast_build_string(m_buf, m_size, " %d", rtp_code);
 	ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
 			 ast_rtp_lookup_mime_subtype(1, codec),
 			 sample_rate);
-	if (codec == AST_FORMAT_G729A)
+	if (codec == AST_FORMAT_G729A) {
 		/* Indicate that we don't support VAD (G.729 annex B) */
 		ast_build_string(a_buf, a_size, "a=fmtp:%d annexb=no\r\n", rtp_code);
+	} else if (codec == AST_FORMAT_ILBC) {
+		/* Add information about us using only 20/30 ms packetization */
+		ast_build_string(a_buf, a_size, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms);
+	}
+
+	if (codec != AST_FORMAT_ILBC) {
+		ast_build_string(a_buf, a_size, "a=ptime:%d\r\n", fmt.cur_ms);
+	}
+
 }
 
 static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, int sample_rate,
@@ -6496,6 +6513,10 @@
 			ASTOBJ_UNREF(peer,sip_destroy_peer);
 	}
 	if (peer) {
+		/* Set Frame packetization */
+		if (p->rtp) {
+			ast_rtp_codec_setpref(p->rtp, &p->prefs);
+		}
 		if (!ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)) {
 			ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
 		} else {
@@ -7137,6 +7158,9 @@
 			}
 		}
 		p->prefs = user->prefs;
+		if (p->rtp) {
+			ast_rtp_codec_setpref(p->rtp, &p->prefs);
+		}
 		/* replace callerid if rpid found, and not restricted */
 		if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
 			if (*calleridname)
@@ -7216,6 +7240,9 @@
 			peer = find_peer(NULL, &p->recv, 1);
 
 		if (peer) {
+			if (p->rtp) {
+				ast_rtp_codec_setpref(p->rtp, &p->prefs);
+			}
 			if (debug)
 				ast_verbose("Found peer '%s'\n", peer->name);
 			/* Take the peer */
@@ -7910,6 +7937,7 @@
 		if (!codec)
 			break;
 		ast_cli(fd, "%s", ast_getformatname(codec));
+		ast_cli(fd, ":%d", pref->framing[x]);
 		if (x < 31 && ast_codec_pref_index(pref, x + 1))
 			ast_cli(fd, ",");
 	}
@@ -8142,15 +8170,9 @@
 		ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
 		ast_cli(fd, "%s\r\n", codec_buf);
 		ast_cli(fd, "CodecOrder: ");
-		pref = &peer->prefs;
-		for(x = 0; x < 32 ; x++) {
-			codec = ast_codec_pref_index(pref,x);
-			if (!codec)
-				break;
-			ast_cli(fd, "%s", ast_getformatname(codec));
-			if (x < 31 && ast_codec_pref_index(pref,x+1))
-				ast_cli(fd, ",");
-		}
+		print_codec_to_cli(fd, &peer->prefs);
+
+		ast_cli(fd, ")\n");
 
 		ast_cli(fd, "\r\n");
 		ast_cli(fd, "Status: ");
diff -u orig/frame.c changed/frame.c
--- orig/frame.c	2006-06-08 20:57:23.000000000 +0400
+++ changed/frame.c	2006-08-12 16:31:02.000000000 +0400
@@ -55,13 +55,6 @@
 #define TYPE_DONTSEND	 0x3
 #define TYPE_MASK	 0x3
 
-struct ast_format_list {
-	int visible;	/*!< Can we see this entry */
-	int bits;	/*!< bitmask value */
-	char *name;	/*!< short name */
-	char *desc;	/*!< Description */
-};
-
 struct ast_smoother {
 	int size;
 	int format;
@@ -79,15 +72,15 @@
 
 /*! \brief Definition of supported media formats (codecs) */
 static struct ast_format_list AST_FORMAT_LIST[] = {
-	{ 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},	/*!< codec_g723_1.c */
-	{ 1, AST_FORMAT_GSM, "gsm" , "GSM"},		/*!< codec_gsm.c */
-	{ 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },	/*!< codec_ulaw.c */
-	{ 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },	/*!< codec_alaw.c */
-	{ 1, AST_FORMAT_G726, "g726", "G.726" },	/*!< codec_g726.c */
+	{ 1, AST_FORMAT_G723_1 , "g723" , "G.723.1", 24, 10, 660, 10, 30 },	/*!< codec_g723_1.c */
+	{ 1, AST_FORMAT_GSM, "gsm" , "GSM", 33, 10, 660, 20, 20},		/*!< codec_gsm.c */
+	{ 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law", 80, 10, 160, 10, 20 },	/*!< codec_ulaw.c */
+	{ 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law", 80, 10, 160, 10, 20 },	/*!< codec_alaw.c */
+	{ 1, AST_FORMAT_G726, "g726", "G.726", 40, 10, 320, 10, 20 },	/*!< codec_g726.c */
 	{ 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},	/*!< codec_adpcm.c */
-	{ 1, AST_FORMAT_SLINEAR, "slin",  "16 bit Signed Linear PCM"},	/*!<  */
+	{ 1, AST_FORMAT_SLINEAR, "slin",  "16 bit Signed Linear PCM", 160, 10, 80, 10, 20, AST_SMOOTHER_FLAG_BE},	/*!<  */
 	{ 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },	/*!< codec_lpc10.c */
-	{ 1, AST_FORMAT_G729A, "g729", "G.729A" },	/*!< Binary commercial distribution */
+	{ 1, AST_FORMAT_G729A, "g729", "G.729A", 10, 10, 1200, 10, 20, AST_SMOOTHER_FLAG_G729 },	/*!< Binary commercial distribution */
 	{ 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },	/*!< codec_speex.c */
 	{ 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},	/*!< codec_ilbc.c */
 	{ 0, 0, "nothing", "undefined" },
@@ -129,6 +122,11 @@
 	return s->flags;
 }
 
+int ast_smoother_test_flag(struct ast_smoother *s, int flag)
+{
+	return (s->flags & flag);
+}
+
 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
 {
 	s->flags = flags;
@@ -948,6 +946,7 @@
 	int x=0, y=0;
 	size_t size = 0;
 	int slot = 0;
+	int psize = 0;
 
 	if(!pref->order[0])
 		return;
@@ -959,10 +958,13 @@
 
 	for (x = 0; x < size; x++) {
 		slot = oldorder.order[x];
+		psize = oldorder.framing[x];
 		if(! slot)
 			break;
-		if(AST_FORMAT_LIST[slot-1].bits != format)
-			pref->order[y++] = slot;
+		if(AST_FORMAT_LIST[slot-1].bits != format) {
+			pref->order[y] = slot;
+			pref->framing[y++] = psize;
+		}
 	}
 	
 }
@@ -995,6 +997,100 @@
 	return x;
 }
 
+/*! \brief Set packet size for codec */
+int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
+{
+        int x, index = -2;
+
+        for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+                if(AST_FORMAT_LIST[x].bits == format) {
+                        index = x;
+                        break;
+                }
+        }
+
+        if(index < 0)
+                return -1;
+
+        /* size validation */
+        if(!framems) {
+                framems = AST_FORMAT_LIST[index].def_ms;
+		ast_log(LOG_WARNING, "Framing not set for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems % AST_FORMAT_LIST[index].inc_ms) {
+                framems -= framems % AST_FORMAT_LIST[index].inc_ms;
+		ast_log(LOG_WARNING, "Framing improper for codec %s, using closest match %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems < AST_FORMAT_LIST[index].min_ms) {
+                framems = AST_FORMAT_LIST[index].min_ms;
+		ast_log(LOG_WARNING, "Framing set too low for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems > AST_FORMAT_LIST[index].max_ms) {
+                framems = AST_FORMAT_LIST[index].max_ms;
+		ast_log(LOG_WARNING, "Framing set too high for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+
+        for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+                if(pref->order[x] == (index + 1)) {
+                        pref->framing[x] = framems;
+			ast_log(LOG_DEBUG, "Found codec in preferences, adding framing\n");
+                        break;
+                }
+        }
+
+        return x;
+}
+
+/*! \brief Get packet size for codec */
+struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
+{
+        int x, index = -2, framems = 0;
+        struct ast_format_list fmt;
+
+        for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+                if(AST_FORMAT_LIST[x].bits == format) {
+                        fmt = AST_FORMAT_LIST[x];
+                        index = x;
+                        break;
+                }
+        }
+
+        for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+                if(pref->order[x] == (index + 1)) {
+                        framems = pref->framing[x];
+                        break;
+                }
+        }
+
+        /* size validation */
+        if(!framems) {
+                framems = AST_FORMAT_LIST[index].def_ms;
+		ast_log(LOG_WARNING, "Framing not set for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems % AST_FORMAT_LIST[index].inc_ms) {
+                framems -= framems % AST_FORMAT_LIST[index].inc_ms;
+		ast_log(LOG_WARNING, "Framing improper for codec %s, using closest match %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems < AST_FORMAT_LIST[index].min_ms) {
+                framems = AST_FORMAT_LIST[index].min_ms;
+		ast_log(LOG_WARNING, "Framing set too low for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        if(framems > AST_FORMAT_LIST[index].max_ms) {
+                framems = AST_FORMAT_LIST[index].max_ms;
+		ast_log(LOG_WARNING, "Framing set too high for codec %s, using default %d\n", AST_FORMAT_LIST[index].name, framems);
+	}
+
+        fmt.cur_ms = framems;
+
+        return fmt;
+}
 
 /*! \brief ast_codec_choose: Pick a codec ---*/
 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
@@ -1024,9 +1120,22 @@
 	char *parse;
 	char *this;
 	int format;
+        char *psize;
+        int framems;
 
 	parse = ast_strdupa(list);
 	while ((this = strsep(&parse, ","))) {
+		framems = 0;
+                if ((psize = strrchr(this, ':'))) {
+                        *psize = '\0';
+                        psize++;
+                        if (option_debug)
+                                ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, 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;
@@ -1041,9 +1150,12 @@
 
 		if (pref) {
 			if (strcasecmp(this, "all")) {
-				if (allowing)
+				if (allowing) {
 					ast_codec_pref_append(pref, format);
-				else
+					ast_codec_pref_setsize(pref, format, framems);
+                    			if (option_debug)
+                            			ast_log(LOG_DEBUG,"parse: Packetization for codec: %s is %d\n", this, framems);
+				} else
 					ast_codec_pref_remove(pref, format);
 			} else if (!allowing) {
 				memset(pref, 0, sizeof(*pref));
diff -u orig/frame.h changed/frame.h
--- orig/frame.h	2005-11-29 21:24:39.000000000 +0300
+++ changed/frame.h	2006-08-12 14:19:28.000000000 +0400
@@ -35,6 +35,7 @@
 
 struct ast_codec_pref {
 	char order[32];
+	char framing[32];
 };
 
 /*! \page Def_Frame AST Multimedia and signalling frames
@@ -245,6 +246,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
@@ -299,6 +301,21 @@
 		u_int8_t data[0];
 };
 
+/*! \brief Definition of supported media formats (codecs) */
+struct ast_format_list {
+	int visible;    /*!< Can we see this entry */
+	int bits;       /*!< bitmask value */
+	char *name;     /*!< short name */
+	char *desc;     /*!< Description */
+	int fr_len;    /*!< Single frame length in bytes */
+	int min_ms;
+	int max_ms;    /*!< fixme: Calculated as RTP_MTU/(fr_len/inc_ms) ?? */
+	int inc_ms;
+	int def_ms;
+	unsigned int flags;
+	int cur_ms;     /*!< Current value */
+};
+
 /*! \brief  Requests a frame to be allocated 
  * 
  * \param source 
@@ -405,6 +422,7 @@
 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_get_flags(struct ast_smoother *smoother);
+extern int ast_smoother_test_flag(struct ast_smoother *s, int flag);
 extern void ast_smoother_free(struct ast_smoother *s);
 extern void ast_smoother_reset(struct ast_smoother *s, int bytes);
 extern int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
@@ -458,6 +476,15 @@
 	return (format == AST_FORMAT_ILBC) ? 30 : 20;
 }
 
+/*! \brief Set packet size for codec
+*/
+extern int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems);
+
+/*! \brief Get packet size for codec
+*/
+extern struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format);
+
+
 /*!
   \brief Adjusts the volume of the audio samples contained in a frame.
   \param f The frame containing the samples (must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR)
diff -u orig/rtp.c changed/rtp.c
--- orig/rtp.c	2006-07-13 22:44:17.000000000 +0400
+++ changed/rtp.c	2006-08-12 15:22:07.000000000 +0400
@@ -127,6 +127,7 @@
 	int rtp_lookup_code_cache_result;
 	int rtp_offered_from_local;
 	struct ast_rtcp *rtcp;
+	struct ast_codec_pref pref;
 };
 
 /*!
@@ -1315,6 +1316,24 @@
 	return 0;
 }
 
+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;
+	return 0;
+}
+
+struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp)
+{
+	return &rtp->pref;
+}
+
 int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
 {
 	struct ast_frame *f;
@@ -1358,96 +1377,29 @@
 	}
 
 
-	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");
+	if (!rtp->smoother) {
+		struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
+		if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
+			ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
 			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;
+		if (fmt.flags) {
+			ast_smoother_set_flags(rtp->smoother, fmt.flags);
 		}
-		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;
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+	}
+	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)))
 			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:
+	
+	} else {
 	        /* Don't buffer outgoing frames; send them one-per-packet: */
 		if (_f->offset < hdrlen) {
 			f = ast_frdup(_f);
diff -u orig/rtp.h changed/rtp.h
--- orig/rtp.h	2005-11-29 21:24:39.000000000 +0300
+++ changed/rtp.h	2006-08-12 14:20:20.000000000 +0400
@@ -160,6 +160,10 @@
 
 void ast_rtp_reload(void);
 
+int ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs);
+
+struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
