Index: pjproject/trunk/pjmedia/include/pjmedia/sdp.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/sdp.h	(revision 3546)
+++ pjproject/trunk/pjmedia/include/pjmedia/sdp.h	(revision 3547)
@@ -48,4 +48,12 @@
 #ifndef PJMEDIA_MAX_SDP_FMT
 #   define PJMEDIA_MAX_SDP_FMT		32
+#endif
+
+/**
+ * The PJMEDIA_MAX_SDP_BANDW macro defines maximum bandwidth information
+ * lines in a media line.
+ */
+#ifndef PJMEDIA_MAX_SDP_BANDW
+#   define PJMEDIA_MAX_SDP_BANDW	4
 #endif
 
@@ -365,4 +373,32 @@
 PJ_DECL(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone(pj_pool_t *pool, 
 						  const pjmedia_sdp_conn *rhs);
+
+
+
+/* **************************************************************************
+ * SDP BANDWIDTH INFO
+ ****************************************************************************
+ */
+
+/**
+ * This structure describes SDP bandwidth info ("b=" line). 
+ */
+typedef struct pjmedia_sdp_bandw
+{
+    pj_str_t	modifier;	/**< Bandwidth modifier.		*/
+    pj_uint32_t	value;	        /**< Bandwidth value.	                */
+} pjmedia_sdp_bandw;
+
+
+/** 
+ * Clone bandwidth info. 
+ * 
+ * @param pool	    Pool to allocate memory for the new bandwidth info.
+ * @param rhs	    The bandwidth into to clone.
+ *
+ * @return	    The new bandwidth info.
+ */
+PJ_DECL(pjmedia_sdp_bandw*)
+pjmedia_sdp_bandw_clone(pj_pool_t *pool, const pjmedia_sdp_bandw *rhs);
 
 
@@ -388,10 +424,12 @@
 	pj_str_t    transport;		/**< Transport ("RTP/AVP")	    */
 	unsigned    fmt_count;		/**< Number of formats.		    */
-	pj_str_t    fmt[PJMEDIA_MAX_SDP_FMT];	/**< Media formats.	    */
+	pj_str_t    fmt[PJMEDIA_MAX_SDP_FMT];       /**< Media formats.	    */
     } desc;
 
-    pjmedia_sdp_conn *conn;		/**< Optional connection info.	    */
-    unsigned	     attr_count;	/**< Number of attributes.	    */
-    pjmedia_sdp_attr*attr[PJMEDIA_MAX_SDP_ATTR];  /**< Attributes.	    */
+    pjmedia_sdp_conn   *conn;		/**< Optional connection info.	    */
+    unsigned	        bandw_count;	/**< Number of bandwidth info.	    */
+    pjmedia_sdp_bandw  *bandw[PJMEDIA_MAX_SDP_BANDW]; /**< Bandwidth info.  */
+    unsigned	        attr_count;	/**< Number of attributes.	    */
+    pjmedia_sdp_attr   *attr[PJMEDIA_MAX_SDP_ATTR];   /**< Attributes.	    */
 
 };
Index: pjproject/trunk/pjmedia/src/pjmedia/sdp.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/sdp.c	(revision 3546)
+++ pjproject/trunk/pjmedia/src/pjmedia/sdp.c	(revision 3547)
@@ -545,4 +545,37 @@
 }
 
+PJ_DEF(pjmedia_sdp_bandw*)
+pjmedia_sdp_bandw_clone (pj_pool_t *pool, 
+			 const pjmedia_sdp_bandw *rhs)
+{
+    pjmedia_sdp_bandw *b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw);
+    if (!b) return NULL;
+
+    if (!pj_strdup (pool, &b->modifier, &rhs->modifier)) return NULL;
+    b->value = rhs->value;
+
+    return b;
+}
+
+static pj_ssize_t print_bandw(const pjmedia_sdp_bandw *bandw,
+			      char *buf, pj_size_t len)
+{
+    char *p = buf;
+
+    if ((int)len < bandw->modifier.slen + 10 + 5)
+	return -1;
+
+    *p++ = 'b';
+    *p++ = '=';
+    pj_memcpy(p, bandw->modifier.ptr, bandw->modifier.slen);
+    p += bandw->modifier.slen;
+    *p++ = ':';
+    p += pj_utoa(bandw->value, p);
+
+    *p++ = '\r';
+    *p++ = '\n';
+    return p-buf;
+}
+
 static pj_ssize_t print_attr(const pjmedia_sdp_attr *attr, 
 			     char *buf, pj_size_t len)
@@ -612,4 +645,13 @@
 	p += printed;
     }
+    
+    /* print optional bandwidth info. */
+    for (i=0; i<m->bandw_count; ++i) {
+	printed = print_bandw(m->bandw[i], p, end-p);
+	if (printed < 0) {
+	    return -1;
+	}
+	p += printed;
+    }
 
     /* print attributes. */
@@ -646,4 +688,10 @@
     } else {
 	m->conn = NULL;
+    }
+
+    m->bandw_count = rhs->bandw_count;
+    for (i=0; i < rhs->bandw_count; ++i) {
+	m->bandw[i] = pjmedia_sdp_bandw_clone (pool, rhs->bandw[i]);
+	PJ_ASSERT_RETURN(m->bandw[i] != NULL, NULL);
     }
 
@@ -1468,4 +1516,10 @@
     }
 
+    m->bandw_count = rhs->bandw_count;
+    for (i=0; i < rhs->bandw_count; ++i) {
+	m->bandw[i] = pjmedia_sdp_bandw_clone (pool, rhs->bandw[i]);
+	PJ_ASSERT_RETURN(m->bandw[i] != NULL, NULL);
+    }
+
     /* And deactivate it */
     pjmedia_sdp_media_deactivate(pool, m);
Index: pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 3546)
+++ pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 3547)
@@ -175,4 +175,6 @@
 static const pj_str_t STR_IP6		= { "IP6", 3 };
 static const pj_str_t STR_RTCP		= { "rtcp", 4 };
+static const pj_str_t STR_BANDW_RR	= { "RR", 2 };
+static const pj_str_t STR_BANDW_RS	= { "RS", 2 };
 
 enum {
@@ -602,4 +604,18 @@
 	if (attr)
 	    pjmedia_sdp_attr_remove(&m->attr_count, m->attr, attr);
+        /* If RTCP is not in use, we MUST send b=RS:0 and b=RR:0. */
+        pj_assert(m->bandw_count + 2 <= PJ_ARRAY_SIZE(m->bandw));
+        if (m->bandw_count + 2 <= PJ_ARRAY_SIZE(m->bandw)) {
+            m->bandw[m->bandw_count] = PJ_POOL_ZALLOC_T(sdp_pool,
+                                                        pjmedia_sdp_bandw);
+            pj_memcpy(&m->bandw[m->bandw_count]->modifier, &STR_BANDW_RS,
+                      sizeof(pj_str_t));
+            m->bandw_count++;
+            m->bandw[m->bandw_count] = PJ_POOL_ZALLOC_T(sdp_pool,
+                                                        pjmedia_sdp_bandw);
+            pj_memcpy(&m->bandw[m->bandw_count]->modifier, &STR_BANDW_RR,
+                      sizeof(pj_str_t));
+            m->bandw_count++;
+        }
     }
     
