Index: /pjproject/trunk/pjmedia/include/pjmedia/transport.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/transport.h	(revision 1762)
+++ /pjproject/trunk/pjmedia/include/pjmedia/transport.h	(revision 1763)
@@ -242,8 +242,8 @@
 			  unsigned addr_len,
 			  void (*rtp_cb)(void *user_data,
-					 const void *pkt,
+					 void *pkt,
 					 pj_ssize_t size),
 			  void (*rtcp_cb)(void *user_data,
-					  const void *pkt,
+					  void *pkt,
 					  pj_ssize_t size));
 
@@ -424,8 +424,8 @@
 					        unsigned addr_len,
 					        void (*rtp_cb)(void *user_data,
-							       const void *pkt,
+							       void *pkt,
 							       pj_ssize_t),
 					        void (*rtcp_cb)(void *usr_data,
-							        const void*pkt,
+							        void*pkt,
 							        pj_ssize_t))
 {
Index: /pjproject/trunk/pjmedia/include/pjmedia/transport_srtp.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/transport_srtp.h	(revision 1762)
+++ /pjproject/trunk/pjmedia/include/pjmedia/transport_srtp.h	(revision 1763)
@@ -226,4 +226,28 @@
 
 /**
+ * This is a utility function to decrypt SRTP packet using SRTP transport.
+ * This function is not part of SRTP transport's API, but it can be used
+ * to decrypt SRTP packets from non-network (for example, from a saved file)
+ * without having to use the transport framework. See pcaputil.c in the
+ * samples collection on how to use this function.
+ *
+ * @param tp		The SRTP transport.
+ * @param is_rtp	Set to non-zero if the packet is SRTP, otherwise set
+ *			to zero if the packet is SRTCP.
+ * @param pkt		On input, it contains SRTP or SRTCP packet. On
+ *			output, it contains the decrypted RTP/RTCP packet.
+ * @param pkt_len	On input, specify the length of the buffer. On
+ *			output, it will be filled with the actual length
+ *			of decrypted packet.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
+							pj_bool_t is_rtp,
+							void *pkt,
+							int *pkt_len);
+
+
+/**
  * Query member transport of SRTP.
  *
Index: /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 1762)
+++ /pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c	(revision 1763)
@@ -41,8 +41,8 @@
 
     void	       (*rtp_cb)(void*,
-			         const void*,
+			         void*,
 				 pj_ssize_t);
     void	       (*rtcp_cb)(void*,
-				  const void*,
+				  void*,
 				  pj_ssize_t);
 };
@@ -60,8 +60,8 @@
 				       unsigned addr_len,
 				       void (*rtp_cb)(void*,
-						      const void*,
+						      void*,
 						      pj_ssize_t),
 				       void (*rtcp_cb)(void*,
-						       const void*,
+						       void*,
 						       pj_ssize_t));
 static void	   transport_detach   (pjmedia_transport *tp,
@@ -675,8 +675,8 @@
 				      unsigned addr_len,
 				      void (*rtp_cb)(void*,
-						     const void*,
+						     void*,
 						     pj_ssize_t),
 				      void (*rtcp_cb)(void*,
-						      const void*,
+						      void*,
 						      pj_ssize_t))
 {
Index: /pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c	(revision 1762)
+++ /pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c	(revision 1763)
@@ -84,5 +84,4 @@
     pj_lock_t		*mutex;
     char		 tx_buffer[MAX_BUFFER_LEN];
-    char		 rx_buffer[MAX_BUFFER_LEN];
 
     pjmedia_srtp_setting setting;
@@ -103,8 +102,8 @@
     void		*user_data;
     void		(*rtp_cb)( void *user_data,
-				   const void *pkt,
+				   void *pkt,
 				   pj_ssize_t size);
     void		(*rtcp_cb)(void *user_data,
-				   const void *pkt,
+				   void *pkt,
 				   pj_ssize_t size);
         
@@ -118,10 +117,10 @@
  * This callback is called by transport when incoming rtp is received
  */
-static void srtp_rtp_cb( void *user_data, const void *pkt, pj_ssize_t size);
+static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size);
 
 /*
  * This callback is called by transport when incoming rtcp is received
  */
-static void srtp_rtcp_cb( void *user_data, const void *pkt, pj_ssize_t size);
+static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size);
 
 
@@ -137,8 +136,8 @@
 				       unsigned addr_len,
 				       void (*rtp_cb)(void*,
-						      const void*,
+						      void*,
 						      pj_ssize_t),
 				       void (*rtcp_cb)(void*,
-						       const void*,
+						       void*,
 						       pj_ssize_t));
 static void	   transport_detach   (pjmedia_transport *tp,
@@ -358,5 +357,8 @@
     /* Initialize base pjmedia_transport */
     pj_memcpy(srtp->base.name, pool->obj_name, PJ_MAX_OBJ_NAME);
-    srtp->base.type = tp->type;
+    if (tp)
+	srtp->base.type = tp->type;
+    else
+	srtp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
     srtp->base.op = &transport_srtp_op;
 
@@ -565,7 +567,7 @@
 				    const pj_sockaddr_t *rem_rtcp,
 				    unsigned addr_len,
-				    void (*rtp_cb) (void*, const void*,
+				    void (*rtp_cb) (void*, void*,
 						    pj_ssize_t),
-				    void (*rtcp_cb)(void*, const void*,
+				    void (*rtcp_cb)(void*, void*,
 						    pj_ssize_t))
 {
@@ -591,8 +593,10 @@
     transport_srtp *srtp = (transport_srtp*) tp;
 
-    PJ_ASSERT_ON_FAIL(tp && srtp->real_tp, return);
-
     PJ_UNUSED_ARG(strm);
-    pjmedia_transport_detach(srtp->real_tp, srtp);
+    PJ_ASSERT_ON_FAIL(tp, return);
+
+    if (srtp->real_tp) {
+	pjmedia_transport_detach(srtp->real_tp, srtp);
+    }
 
     /* Clear up application infos from transport */
@@ -688,5 +692,5 @@
     pjmedia_transport_detach(tp, NULL);
     
-    if (srtp->setting.close_member_tp) {
+    if (srtp->setting.close_member_tp && srtp->real_tp) {
 	pjmedia_transport_close(srtp->real_tp);
     }
@@ -705,5 +709,5 @@
  * This callback is called by transport when incoming rtp is received
  */
-static void srtp_rtp_cb( void *user_data, const void *pkt, pj_ssize_t size)
+static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
 {
     transport_srtp *srtp = (transport_srtp *) user_data;
@@ -716,15 +720,17 @@
     }
 
-    if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) {
+    if (size < 0 || !srtp->session_inited) {
 	return;
     }
 
+    /* Make sure buffer is 32bit aligned */
+    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return );
+
     pj_lock_acquire(srtp->mutex);
-    pj_memcpy(srtp->rx_buffer, pkt, size);
-
-    err = srtp_unprotect(srtp->srtp_rx_ctx, srtp->rx_buffer, &len);
+
+    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
     
     if (err == err_status_ok) {
-	srtp->rtp_cb(srtp->user_data, srtp->rx_buffer, len);
+	srtp->rtp_cb(srtp->user_data, pkt, len);
     } else {
 	PJ_LOG(5,(srtp->pool->obj_name, 
@@ -739,5 +745,5 @@
  * This callback is called by transport when incoming rtcp is received
  */
-static void srtp_rtcp_cb( void *user_data, const void *pkt, pj_ssize_t size)
+static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size)
 {
     transport_srtp *srtp = (transport_srtp *) user_data;
@@ -750,15 +756,17 @@
     }
 
-    if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) {
+    if (size < 0 || !srtp->session_inited) {
 	return;
     }
 
+    /* Make sure buffer is 32bit aligned */
+    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return );
+
     pj_lock_acquire(srtp->mutex);
-    pj_memcpy(srtp->rx_buffer, pkt, size);
-
-    err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, srtp->rx_buffer, &len);
+
+    err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
 
     if (err == err_status_ok) {
-	srtp->rtcp_cb(srtp->user_data, srtp->rx_buffer, len);
+	srtp->rtcp_cb(srtp->user_data, pkt, len);
     } else {
 	PJ_LOG(5,(srtp->pool->obj_name, 
@@ -1265,4 +1273,40 @@
 }
 
+/* Utility */
+PJ_DEF(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
+						       pj_bool_t is_rtp,
+						       void *pkt,
+						       int *pkt_len)
+{
+    transport_srtp *srtp = (transport_srtp *)tp;
+    err_status_t err;
+
+    if (srtp->bypass_srtp)
+	return PJ_SUCCESS;
+
+    PJ_ASSERT_RETURN(*pkt_len>0, PJ_EINVAL);
+    PJ_ASSERT_RETURN(srtp->session_inited, PJ_EINVALIDOP);
+
+    /* Make sure buffer is 32bit aligned */
+    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return PJ_EINVAL);
+
+    pj_lock_acquire(srtp->mutex);
+
+    if (is_rtp)
+	err = srtp_unprotect(srtp->srtp_rx_ctx, pkt, pkt_len);
+    else
+	err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len);
+    
+    if (err != err_status_ok) {
+	PJ_LOG(5,(srtp->pool->obj_name, 
+		  "Failed to unprotect SRTP, pkt size=%d, err=%s", 
+		  *pkt_len, get_libsrtp_errstr(err)));
+    }
+
+    pj_lock_release(srtp->mutex);
+
+    return (err==err_status_ok) ? PJ_SUCCESS : PJMEDIA_ERRNO_FROM_LIBSRTP(err);
+}
+
 #endif
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 1762)
+++ /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 1763)
@@ -56,8 +56,8 @@
     int			addr_len;	/**< Length of addresses.	    */
     void  (*rtp_cb)(	void*,		/**< To report incoming RTP.	    */
-			const void*,
+			void*,
 			pj_ssize_t);
     void  (*rtcp_cb)(	void*,		/**< To report incoming RTCP.	    */
-			const void*,
+			void*,
 			pj_ssize_t);
 
@@ -106,8 +106,8 @@
 				       unsigned addr_len,
 				       void (*rtp_cb)(void*,
-						      const void*,
+						      void*,
 						      pj_ssize_t),
 				       void (*rtcp_cb)(void*,
-						       const void*,
+						       void*,
 						       pj_ssize_t));
 static void	   transport_detach   (pjmedia_transport *tp,
@@ -420,5 +420,5 @@
 
     do {
-	void (*cb)(void*,const void*,pj_ssize_t);
+	void (*cb)(void*,void*,pj_ssize_t);
 	void *user_data;
 
@@ -524,5 +524,5 @@
 
     do {
-	void (*cb)(void*,const void*,pj_ssize_t);
+	void (*cb)(void*,void*,pj_ssize_t);
 	void *user_data;
 
@@ -588,8 +588,8 @@
 				       unsigned addr_len,
 				       void (*rtp_cb)(void*,
-						      const void*,
+						      void*,
 						      pj_ssize_t),
 				       void (*rtcp_cb)(void*,
-						       const void*,
+						       void*,
 						       pj_ssize_t))
 {
