Index: pjproject/trunk/pjmedia/include/pjmedia/transport_ice.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/transport_ice.h	(revision 2275)
+++ pjproject/trunk/pjmedia/include/pjmedia/transport_ice.h	(revision 2276)
@@ -63,4 +63,21 @@
 
 /**
+ * Options that can be specified when creating ICE transport.
+ */
+enum pjmedia_transport_ice_options
+{
+    /**
+     * Normally when remote doesn't use ICE, the ICE transport will 
+     * continuously check the source address of incoming packets to see 
+     * if it is different than the configured remote address, and switch 
+     * the remote address to the source address of the packet if they 
+     * are different after several packets are received.
+     * Specifying this option will disable this feature.
+     */
+    PJMEDIA_ICE_NO_SRC_ADDR_CHECKING = 1
+};
+
+
+/**
  * Create the Interactive Connectivity Establishment (ICE) media transport
  * using the specified configuration. When STUN or TURN (or both) is used,
@@ -95,4 +112,27 @@
 					pjmedia_transport **p_tp);
 
+
+/**
+ * The same as @pjmedia_ice_create with additional \a options param.
+ *
+ * @param endpt		The media endpoint.
+ * @param name		Optional name to identify this ICE media transport
+ *			for logging purposes.
+ * @param comp_cnt	Number of components to be created.
+ * @param cfg		Pointer to configuration settings.
+ * @param cb		Optional structure containing ICE specific callbacks.
+ * @param options	Options, see #pjmedia_transport_ice_options.
+ * @param p_tp		Pointer to receive the media transport instance.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_ice_create2(pjmedia_endpt *endpt,
+					 const char *name,
+					 unsigned comp_cnt,
+					 const pj_ice_strans_cfg *cfg,
+					 const pjmedia_ice_cb *cb,
+					 unsigned options,
+					 pjmedia_transport **p_tp);
+
 PJ_END_DECL
 
Index: pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 2275)
+++ pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 2276)
@@ -50,4 +50,5 @@
     pj_pool_t		*pool;
     int			 af;
+    unsigned		 options;	/**< Transport options.		    */
 
     unsigned		 comp_cnt;
@@ -59,9 +60,15 @@
     pj_bool_t		 initial_sdp;
     enum oa_role	 oa_role;	/**< Last role in SDP offer/answer  */
-    struct sdp_state	 rem_offer_state;/**< Describes the remote offer	    */
+    struct sdp_state	 rem_offer_state;/**< Describes the remote offer    */
 
     void		*stream;
-    pj_sockaddr_in	 remote_rtp;
-    pj_sockaddr_in	 remote_rtcp;
+    pj_sockaddr		 remote_rtp;
+    pj_sockaddr		 remote_rtcp;
+    unsigned		 addr_len;	/**< Length of addresses.	    */
+
+    pj_bool_t		 use_ice;
+    pj_sockaddr		 rtp_src_addr;	/**< Actual source RTP address.	    */
+    pj_sockaddr		 rtcp_src_addr;	/**< Actual source RTCP address.    */
+    unsigned		 rtp_src_cnt;	/**< How many pkt from this addr.   */
 
     unsigned		 tx_drop_pct;	/**< Percent of tx pkts to drop.    */
@@ -182,4 +189,18 @@
 	    			       pjmedia_transport **p_tp)
 {
+    return pjmedia_ice_create2(endpt, name, comp_cnt, cfg, cb, 0, p_tp);
+}
+
+/*
+ * Create ICE media transport.
+ */
+PJ_DEF(pj_status_t) pjmedia_ice_create2(pjmedia_endpt *endpt,
+				        const char *name,
+				        unsigned comp_cnt,
+				        const pj_ice_strans_cfg *cfg,
+				        const pjmedia_ice_cb *cb,
+					unsigned options,
+	    			        pjmedia_transport **p_tp)
+{
     pj_pool_t *pool;
     pj_ice_strans_cb ice_st_cb;
@@ -194,4 +215,5 @@
     tp_ice->pool = pool;
     tp_ice->af = cfg->af;
+    tp_ice->options = options;
     tp_ice->comp_cnt = comp_cnt;
     pj_ansi_strcpy(tp_ice->base.name, pool->obj_name);
@@ -200,4 +222,5 @@
     tp_ice->initial_sdp = PJ_TRUE;
     tp_ice->oa_role = ROLE_NONE;
+    tp_ice->use_ice = PJ_FALSE;
 
     if (cb)
@@ -242,4 +265,6 @@
 
     pj_ice_strans_stop_ice(tp_ice->ice_st);
+
+    tp_ice->use_ice = PJ_FALSE;
 }
 
@@ -1358,4 +1383,5 @@
 
     /* Done */
+    tp_ice->use_ice = PJ_TRUE;
 
     return PJ_SUCCESS;
@@ -1423,4 +1449,5 @@
     pj_memcpy(&tp_ice->remote_rtp, rem_addr, addr_len);
     pj_memcpy(&tp_ice->remote_rtcp, rem_rtcp, addr_len);
+    tp_ice->addr_len = addr_len;
 
     return PJ_SUCCESS;
@@ -1461,5 +1488,5 @@
     return pj_ice_strans_sendto(tp_ice->ice_st, 1, 
 			        pkt, size, &tp_ice->remote_rtp,
-				sizeof(pj_sockaddr_in));
+				tp_ice->addr_len);
 }
 
@@ -1515,8 +1542,85 @@
 	(*tp_ice->rtp_cb)(tp_ice->stream, pkt, size);
 
-    } else if (comp_id==2 && tp_ice->rtcp_cb)
+	/* See if source address of RTP packet is different than the 
+	 * configured address, and switch RTP remote address to 
+	 * source packet address after several consecutive packets
+	 * have been received.
+	 */
+	if (!tp_ice->use_ice &&
+	    (tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING) == 0 &&
+	    pj_sockaddr_cmp(&tp_ice->remote_rtp, src_addr) != 0 )
+	{
+	    /* Check if the source address is recognized. */
+	    if (pj_sockaddr_cmp(src_addr, &tp_ice->rtp_src_addr) != 0) {
+		/* Remember the new source address. */
+		pj_sockaddr_cp(&tp_ice->rtp_src_addr, src_addr);
+
+		/* Reset counter */
+		tp_ice->rtp_src_cnt = 0;
+	    }
+
+	    tp_ice->rtp_src_cnt++;
+
+	    if (tp_ice->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) {
+    	
+		char addr_text[80];
+
+		/* Set remote RTP address to source address */
+		pj_sockaddr_cp(&tp_ice->remote_rtp, &tp_ice->rtp_src_addr);
+		tp_ice->addr_len = pj_sockaddr_get_len(&tp_ice->remote_rtp);
+
+		/* Reset counter */
+		tp_ice->rtp_src_cnt = 0;
+
+		PJ_LOG(4,(tp_ice->base.name,
+			  "Remote RTP address switched to %s",
+			  pj_sockaddr_print(&tp_ice->remote_rtp, addr_text,
+					    sizeof(addr_text), 3)));
+
+		/* Also update remote RTCP address if actual RTCP source
+		 * address is not heard yet.
+		 */
+		if (!pj_sockaddr_has_addr(&tp_ice->rtcp_src_addr)) {
+		    pj_uint16_t port;
+
+		    pj_sockaddr_cp(&tp_ice->remote_rtcp, &tp_ice->remote_rtp);
+
+		    port = (pj_uint16_t)
+			   (pj_sockaddr_get_port(&tp_ice->remote_rtp)+1);
+		    pj_sockaddr_set_port(&tp_ice->remote_rtcp, port);
+
+		    PJ_LOG(4,(tp_ice->base.name,
+			      "Remote RTCP address switched to %s",
+			      pj_sockaddr_print(&tp_ice->remote_rtcp, addr_text,
+						sizeof(addr_text), 3)));
+
+		}
+	    }
+	}
+    } else if (comp_id==2 && tp_ice->rtcp_cb) {
 	(*tp_ice->rtcp_cb)(tp_ice->stream, pkt, size);
 
-    PJ_UNUSED_ARG(src_addr);
+	/* Check if RTCP source address is the same as the configured
+	 * remote address, and switch the address when they are
+	 * different.
+	 */
+	if (!tp_ice->use_ice &&
+	    (tp_ice->options & PJMEDIA_ICE_NO_SRC_ADDR_CHECKING)==0 &&
+	    pj_sockaddr_cmp(&tp_ice->remote_rtcp, src_addr) != 0)
+	{
+	    char addr_text[80];
+
+	    pj_sockaddr_cp(&tp_ice->remote_rtcp, src_addr);
+	    pj_sockaddr_cp(&tp_ice->rtcp_src_addr, src_addr);
+
+	    pj_assert(tp_ice->addr_len == pj_sockaddr_get_len(src_addr));
+
+	    PJ_LOG(4,(tp_ice->base.name,
+		      "Remote RTCP address switched to %s",
+		      pj_sockaddr_print(&tp_ice->remote_rtcp, addr_text,
+					sizeof(addr_text), 3)));
+	}
+    }
+
     PJ_UNUSED_ARG(src_addr_len);
 }
