Index: pjproject/trunk/pjmedia/include/pjmedia/transport.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/transport.h	(revision 5477)
+++ pjproject/trunk/pjmedia/include/pjmedia/transport.h	(revision 5478)
@@ -242,4 +242,9 @@
 
 /**
+ * Forward declaration for media transport attach param.
+ */
+typedef struct pjmedia_transport_attach_param pjmedia_transport_attach_param;
+
+/**
  * This enumeration specifies the general behaviour of media processing
  */
@@ -304,5 +309,6 @@
      * to be used by the stream for the first time, and it tells the transport
      * about remote RTP address to send the packet and some callbacks to be 
-     * called for incoming packets.
+     * called for incoming packets. This function exists for backwards
+     * compatibility. Transports should implement attach2 instead.
      *
      * Application should call #pjmedia_transport_attach() instead of 
@@ -434,4 +440,16 @@
      */
     pj_status_t (*destroy)(pjmedia_transport *tp);
+
+    /**
+     * This function is called by the stream when the transport is about
+     * to be used by the stream for the first time, and it tells the transport
+     * about remote RTP address to send the packet and some callbacks to be
+     * called for incoming packets.
+     *
+     * Application should call #pjmedia_transport_attach2() instead of
+     * calling this function directly.
+     */
+    pj_status_t (*attach2)(pjmedia_transport *tp,
+			   pjmedia_transport_attach_param *att_param);
 };
 
@@ -546,4 +564,54 @@
 };
 
+
+/**
+ * This structure describes the data passed when calling
+ * #pjmedia_transport_attach2().
+ */
+struct pjmedia_transport_attach_param
+{
+    /**
+     * The media stream.
+     */
+    void *stream;
+
+    /**
+     * Indicate the stream type, either it's audio (PJMEDIA_TYPE_AUDIO) 
+     * or video (PJMEDIA_TYPE_VIDEO).
+     */
+    pjmedia_type media_type;
+
+    /**
+     * Remote RTP address to send RTP packet to.
+     */
+    pj_sockaddr rem_addr;
+
+    /**
+     * Optional remote RTCP address. If the argument is NULL
+     * or if the address is zero, the RTCP address will be
+     * calculated from the RTP address (which is RTP port plus one).
+     */
+    pj_sockaddr rem_rtcp;
+
+    /**
+     * Length of the remote address.
+     */
+    unsigned addr_len;
+
+    /**
+     * Arbitrary user data to be set when the callbacks are called.
+     */
+    void *user_data;
+
+    /**
+     * Callback to be called when RTP packet is received on the transport.
+     */
+    void (*rtp_cb)(void *user_data, void *pkt, pj_ssize_t);
+
+    /**
+     * Callback to be called when RTCP packet is received on the transport.
+     */
+    void (*rtcp_cb)(void *user_data, void *pkt, pj_ssize_t);
+};
 
 /**
@@ -600,4 +668,30 @@
     }
     return NULL;
+}
+
+
+/**
+ * Attach callbacks to be called on receipt of incoming RTP/RTCP packets.
+ * This is just a simple wrapper which calls <tt>attach2()</tt> member of
+ * the transport if it is implemented, otherwise it calls <tt>attach()</tt>
+ * member of the transport.
+ *
+ * @param tp	    The media transport.
+ * @param att_param The transport attach param.
+ *
+ * @return	    PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_attach2(pjmedia_transport *tp,
+                                      pjmedia_transport_attach_param *att_param)
+{
+    if (tp->op->attach2) {
+	return tp->op->attach2(tp, att_param);
+    } else {
+	return tp->op->attach(tp, att_param->user_data, 
+			      (pj_sockaddr_t*)&att_param->rem_addr, 
+			      (pj_sockaddr_t*)&att_param->rem_rtcp, 
+			      att_param->addr_len, att_param->rtp_cb, 
+			      att_param->rtcp_cb);
+    }
 }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 5477)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 5478)
@@ -2006,4 +2006,5 @@
     char *p;
     pj_status_t status;
+    pjmedia_transport_attach_param att_param;
 
     PJ_ASSERT_RETURN(endpt && info && p_stream, PJ_EINVAL);
@@ -2347,10 +2348,15 @@
 
     stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
+    att_param.stream = stream;
+    att_param.media_type = PJMEDIA_TYPE_AUDIO;
+    att_param.user_data = stream;
+    pj_sockaddr_cp(&att_param.rem_addr, &info->rem_addr);
+    pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp);
+    att_param.addr_len = pj_sockaddr_get_len(&info->rem_addr);
+    att_param.rtp_cb = &on_rx_rtp;
+    att_param.rtcp_cb = &on_rx_rtcp;
 
     /* Only attach transport when stream is ready. */
-    status = pjmedia_transport_attach(tp, stream, &info->rem_addr,
-				      &info->rem_rtcp,
-				      pj_sockaddr_get_len(&info->rem_addr),
-                                      &on_rx_rtp, &on_rx_rtcp);
+    status = pjmedia_transport_attach2(tp, &att_param);
     if (status != PJ_SUCCESS)
 	goto err_cleanup;
Index: pjproject/trunk/pjmedia/src/pjmedia/transport_adapter_sample.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/transport_adapter_sample.c	(revision 5477)
+++ pjproject/trunk/pjmedia/src/pjmedia/transport_adapter_sample.c	(revision 5478)
@@ -27,15 +27,6 @@
 static pj_status_t transport_get_info (pjmedia_transport *tp,
 				       pjmedia_transport_info *info);
-static pj_status_t transport_attach   (pjmedia_transport *tp,
-				       void *user_data,
-				       const pj_sockaddr_t *rem_addr,
-				       const pj_sockaddr_t *rem_rtcp,
-				       unsigned addr_len,
-				       void (*rtp_cb)(void*,
-						      void*,
-						      pj_ssize_t),
-				       void (*rtcp_cb)(void*,
-						       void*,
-						       pj_ssize_t));
+static pj_status_t transport_attach2  (pjmedia_transport *tp,
+                                       pjmedia_transport_attach_param *att_prm);
 static void	   transport_detach   (pjmedia_transport *tp,
 				       void *strm);
@@ -77,5 +68,5 @@
 {
     &transport_get_info,
-    &transport_attach,
+    NULL,
     &transport_detach,
     &transport_send_rtp,
@@ -87,5 +78,6 @@
     &transport_media_stop,
     &transport_simulate_lost,
-    &transport_destroy
+    &transport_destroy,
+    &transport_attach2,
 };
 
@@ -101,4 +93,5 @@
     /* Stream information. */
     void		*stream_user_data;
+    void                *stream_ref;
     void	       (*stream_rtp_cb)(void *user_data,
 					void *pkt,
@@ -191,20 +184,10 @@
 }
 
-
-/*
- * attach() is called by stream to register callbacks that we should
+/*
+ * attach2() is called by stream to register callbacks that we should
  * call on receipt of RTP and RTCP packets.
  */
-static pj_status_t transport_attach(pjmedia_transport *tp,
-				    void *user_data,
-				    const pj_sockaddr_t *rem_addr,
-				    const pj_sockaddr_t *rem_rtcp,
-				    unsigned addr_len,
-				    void (*rtp_cb)(void*,
-						   void*,
-						   pj_ssize_t),
-				    void (*rtcp_cb)(void*,
-						    void*,
-						    pj_ssize_t))
+static pj_status_t transport_attach2(pjmedia_transport *tp,
+                                     pjmedia_transport_attach_param *att_param)
 {
     struct tp_adapter *adapter = (struct tp_adapter*)tp;
@@ -216,15 +199,19 @@
      */
     pj_assert(adapter->stream_user_data == NULL);
-    adapter->stream_user_data = user_data;
-    adapter->stream_rtp_cb = rtp_cb;
-    adapter->stream_rtcp_cb = rtcp_cb;
-
-    status = pjmedia_transport_attach(adapter->slave_tp, adapter, rem_addr,
-				      rem_rtcp, addr_len, &transport_rtp_cb,
-				      &transport_rtcp_cb);
+    adapter->stream_user_data = att_param->user_data;
+    adapter->stream_rtp_cb = att_param->rtp_cb;
+    adapter->stream_rtcp_cb = att_param->rtcp_cb;
+    adapter->stream_ref = att_param->stream;
+
+    att_param->rtp_cb = &transport_rtp_cb;
+    att_param->rtcp_cb = &transport_rtcp_cb;
+    att_param->user_data = adapter;
+        
+    status = pjmedia_transport_attach2(adapter->slave_tp, att_param);
     if (status != PJ_SUCCESS) {
 	adapter->stream_user_data = NULL;
 	adapter->stream_rtp_cb = NULL;
 	adapter->stream_rtcp_cb = NULL;
+        adapter->stream_ref = NULL;
 	return status;
     }
@@ -248,4 +235,5 @@
 	adapter->stream_rtp_cb = NULL;
 	adapter->stream_rtcp_cb = NULL;
+        adapter->stream_ref = NULL;
     }
 }
Index: pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c	(revision 5477)
+++ pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c	(revision 5478)
@@ -1425,4 +1425,5 @@
     char *p;
     pj_status_t status;
+    pjmedia_transport_attach_param att_param;
 
     if (!pool) {
@@ -1666,10 +1667,15 @@
 
     stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
+    att_param.stream = stream;
+    att_param.media_type = PJMEDIA_TYPE_VIDEO;
+    att_param.user_data = stream;
+    pj_sockaddr_cp(&att_param.rem_addr, &info->rem_addr);
+    pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp);
+    att_param.addr_len = pj_sockaddr_get_len(&info->rem_addr);
+    att_param.rtp_cb = &on_rx_rtp;
+    att_param.rtcp_cb = &on_rx_rtcp;
 
     /* Only attach transport when stream is ready. */
-    status = pjmedia_transport_attach(tp, stream, &info->rem_addr, 
-				      &info->rem_rtcp, 
-				      pj_sockaddr_get_len(&info->rem_addr), 
-                                      &on_rx_rtp, &on_rx_rtcp);
+    status = pjmedia_transport_attach2(tp, &att_param);
     if (status != PJ_SUCCESS)
 	return status;
