ANNOUNCEMENT: Live Wireshark University & Allegro Packets online APAC Wireshark Training Session
July 17th, 2024 | 10:00am-11:55am SGT (UTC+8) | Online

Ethereal-dev: [Ethereal-dev] RTP Dynamic Payload in SDP sessions

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
Date: Sat, 26 Mar 2005 16:42:03 -0700
Hi All,
   Find attached a patch for SDP sessions to:
- Dissect Dynamic payload types in RTP packets
- Add the dynamic payload type description in RTP packets
- Add RTP dynamic payload types description in the Voip Calls Graph, in the RTP and SDP.

Regards
Alejandro
Index: asn1/h245/h245.cnf
===================================================================
--- asn1/h245/h245.cnf	(revision 13743)
+++ asn1/h245/h245.cnf	(working copy)
@@ -375,7 +375,7 @@
 		src_addr.len=4;
 		src_addr.data=(char *)&ipv4_address;
 
-		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, 0);
+		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, NULL);
 	}
 	if((!pinfo->fd->flags.visited) && rtcp_ipv4_address!=0 && rtcp_ipv4_port!=0 && rtcp_handle){
 		address src_addr;
@@ -405,7 +405,7 @@
 		src_addr.len=4;
 		src_addr.data=(char *)&ipv4_address;
 
-		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, 0);
+		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, NULL);
 	}
 	if((!pinfo->fd->flags.visited) && rtcp_ipv4_address!=0 && rtcp_ipv4_port!=0 && rtcp_handle){
 		address src_addr;
Index: gtk/voip_calls.c
===================================================================
--- gtk/voip_calls.c	(revision 13743)
+++ gtk/voip_calls.c	(working copy)
@@ -56,6 +56,7 @@
 #include <plugins/mgcp/packet-mgcp.h>
 #include <epan/dissectors/packet-rtp.h>
 #include <epan/dissectors/packet-rtp-events.h>
+#include <epan/conversation.h>
 #include "rtp_pt.h"
 
 #include "alert_box.h"
@@ -376,6 +377,7 @@
 	voip_rtp_stream_info_t *tmp_listinfo;
 	voip_rtp_stream_info_t *strinfo = NULL;
 	GList* list;
+	struct _rtp_conversation_info *p_conv_data = NULL;
 
 	const struct _rtp_info *pi = RTPinfo;
 
@@ -413,6 +415,15 @@
 		strinfo->ssrc = pi->info_sync_src;
 		strinfo->end_stream = FALSE;
 		strinfo->pt = pi->info_payload_type;
+		strinfo->pt_str = NULL;
+		/* if it is dynamic payload, let use the conv data to see if it is defined */
+		if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
+			/* Use existing packet info if available */
+			p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
+			if (p_conv_data)
+				strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
+		}
+		if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
 		strinfo->npackets = 0;
 		strinfo->first_frame_num = pinfo->fd->num;
 		strinfo->start_rel_sec = pinfo->fd->rel_secs;
@@ -478,7 +489,8 @@
 						new_gai->port_src = rtp_listinfo->src_port;
 						new_gai->port_dst = rtp_listinfo->dest_port;
 						duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
-						new_gai->frame_label = g_strdup_printf("RTP (%s) %s", val_to_str(rtp_listinfo->pt, rtp_payload_type_short_vals, "%u"), (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Uknown RTP Event"));
+						new_gai->frame_label = g_strdup_printf("RTP (%s) %s", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Uknown RTP Event")); 
+						g_free(rtp_listinfo->pt_str);
 						new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
 						new_gai->conv_num = conv_num;
 						new_gai->display=FALSE;
Index: gtk/voip_calls.h
===================================================================
--- gtk/voip_calls.h	(revision 13743)
+++ gtk/voip_calls.h	(working copy)
@@ -169,7 +169,8 @@
 	address dest_addr;
 	guint16 dest_port;
 	guint32 ssrc;
-	guint8  pt;
+	guint32  pt;
+	gchar *pt_str;
 	guint32 npackets;
 	gboolean end_stream;
 
@@ -211,7 +212,6 @@
 void sdp_calls_init_tap(void);
 void rtp_init_tap(void);
 void rtp_event_init_tap(void);
-void rtp_init_tap_event(void);
 void mgcp_calls_init_tap(void);
 
 
Index: plugins/plugin_api_list.c
===================================================================
--- plugins/plugin_api_list.c	(revision 13743)
+++ plugins/plugin_api_list.c	(working copy)
@@ -498,7 +498,7 @@
 
 proto_item *proto_tree_add_debug_text(proto_tree *tree, const char *format, ...);
 
-void rtp_add_address(packet_info *pinfo, address *addr, int port, int other_port, gchar *setup_method, guint32 setup_frame_number, int rtp_event_pt);
+void rtp_add_address(packet_info *pinfo, address *addr, int port, int other_port, gchar *setup_method, guint32 setup_frame_number, GHashTable *rtp_dyn_payload);
 void rtcp_add_address(packet_info *pinfo, address *addr, int port, int other_port, gchar *setup_method, guint32 setup_frame_number);
 
 GString *register_tap_listener(char *, void *, char *, tap_reset_cb, tap_packet_cb, tap_draw_cb);
Index: plugins/Xplugin_table.h
===================================================================
--- plugins/Xplugin_table.h	(revision 13743)
+++ plugins/Xplugin_table.h	(working copy)
@@ -302,7 +302,7 @@
 typedef gfloat (*addr_tvb_get_letohieee_float) (tvbuff_t *, gint);
 typedef gdouble (*addr_tvb_get_letohieee_double) (tvbuff_t *, gint);
 typedef proto_item *(*addr_proto_tree_add_debug_text) (proto_tree *, const char *, ...);
-typedef void (*addr_rtp_add_address) (packet_info *, address *, int, int, gchar *, guint32);
+typedef void (*addr_rtp_add_address) (packet_info *, address *, int, int, gchar *, guint32, GHashTable *);
 typedef void (*addr_rtcp_add_address) (packet_info *, address *, int, int, gchar *, guint32);
 typedef GString *(*addr_register_tap_listener) (char *, void *, char *, tap_reset_cb, tap_packet_cb, tap_draw_cb);
 typedef const char *(*addr_get_datafile_dir) (void);
Index: epan/libethereal.def
===================================================================
--- epan/libethereal.def	(revision 13743)
+++ epan/libethereal.def	(working copy)
@@ -490,6 +490,7 @@
 rpc_roundup
 rtcp_add_address
 rtp_add_address
+rtp_free_hash_dyn_payload
 rtp_payload_type_vals           DATA
 rtp_payload_type_short_vals    DATA
 set_actual_length
Index: epan/dissectors/packet-rtsp.c
===================================================================
--- epan/dissectors/packet-rtsp.c	(revision 13743)
+++ epan/dissectors/packet-rtsp.c	(working copy)
@@ -462,7 +462,7 @@
 	if (rtp_transport)
 	{
 		rtp_add_address(pinfo, &pinfo->dst, c_data_port, s_data_port,
-						"RTSP", pinfo->fd->num, 0);
+						"RTSP", pinfo->fd->num, NULL);
 	
 		if (!c_mon_port)
 			return;
Index: epan/dissectors/packet-sdp.c
===================================================================
--- epan/dissectors/packet-sdp.c	(revision 13743)
+++ epan/dissectors/packet-sdp.c	(working copy)
@@ -163,14 +163,17 @@
 
 
 #define SDP_MAX_RTP_CHANNELS 4
+#define SDP_MAX_RTP_PAYLOAD_TYPES 10
 
 typedef struct {
 	char *connection_address;
 	char *connection_type;
 	char *media_port[SDP_MAX_RTP_CHANNELS];
 	char *media_proto[SDP_MAX_RTP_CHANNELS];
+	gint32 media_pt[SDP_MAX_RTP_PAYLOAD_TYPES];
 	gint8 media_count;
-	guint32 rtp_event_pt;
+	gint8 media_pt_count;
+	GHashTable *rtp_dyn_payload;
 } transport_info_t;
 
 /* static functions */
@@ -228,14 +231,19 @@
 	/* Initialise RTP channel info */
 	transport_info.connection_address=NULL;
 	transport_info.connection_type=NULL;
-	transport_info.rtp_event_pt=0;
 	for (n=0; n < SDP_MAX_RTP_CHANNELS; n++)
 	{
 	    transport_info.media_port[n]=NULL;
 	    transport_info.media_proto[n]=NULL;
 	}
+	for (n=0; n < SDP_MAX_RTP_PAYLOAD_TYPES; n++)
+	{
+	    transport_info.media_pt[n]=-1;
+	}
 	transport_info.media_count = 0;
+	transport_info.media_pt_count = 0;
 
+	transport_info.rtp_dyn_payload = g_hash_table_new( g_int_hash, g_int_equal);
 
 	/*
 	 * As RFC 2327 says, "SDP is purely a format for session
@@ -417,7 +425,7 @@
 		    src_addr.data=(char *)&ipaddr;
 		    if(rtp_handle){
 				rtp_add_address(pinfo, &src_addr, port, 0,
-	                "SDP", pinfo->fd->num, transport_info.rtp_event_pt);
+	                "SDP", pinfo->fd->num, transport_info.rtp_dyn_payload);
 				set_rtp = TRUE;
 		    }
 		    if(rtcp_handle){
@@ -425,7 +433,7 @@
 				rtcp_add_address(pinfo, &src_addr, port, 0,
 	                 "SDP", pinfo->fd->num);
 		    }
-	    }
+		} 
 			
 	    /* Add t38 conversation, if available and only if no rtp */
 	    if((!pinfo->fd->flags.visited) && port!=0 && !set_rtp && is_t38 && is_ipv4_addr){
@@ -450,6 +458,25 @@
 		proto_tree_add_text(sdp_tree, tvb, offset, datalen,
 		    "Data (%d bytes)", datalen);
 	}
+
+	/* Create the summary str for the Voip Call analysis */
+	for (n = 0; n < transport_info.media_pt_count; n++)
+	{
+		/* if the payload type is dynamic (96 to 127), check the hash table */
+		if ( (transport_info.media_pt[n] >=96) && (transport_info.media_pt[n] <=127) ) {
+			gchar *str_dyn_pt = g_hash_table_lookup(transport_info.rtp_dyn_payload, &transport_info.media_pt[n]);
+			if (str_dyn_pt)
+				g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, str_dyn_pt);
+			else
+				g_snprintf(sdp_pi->summary_str, 50, "%s %d", sdp_pi->summary_str, transport_info.media_pt[n]);
+		} else 
+			g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, val_to_str(transport_info.media_pt[n], rtp_payload_type_short_vals, "%u"));
+	}
+
+	/* Free the hash table if we don't use it */
+    if (set_rtp == FALSE) 
+		rtp_free_hash_dyn_payload(transport_info.rtp_dyn_payload);
+
     /* Report this packet to the tap */
     tap_queue_packet(sdp_tap, pinfo, sdp_pi);
 }
@@ -900,7 +927,9 @@
       media_format = tvb_get_string(tvb, offset, tokenlen);
       proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
                              tokenlen, val_to_str(atol(media_format), rtp_payload_type_vals, "%u"));
-      g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, val_to_str(atol(media_format), rtp_payload_type_short_vals, "%u"));
+	  transport_info->media_pt[transport_info->media_pt_count] = atol(media_format);
+	  if (transport_info->media_pt_count < SDP_MAX_RTP_PAYLOAD_TYPES)
+		  transport_info->media_pt_count++;
       g_free(media_format);
     } else {
       proto_tree_add_item(sdp_media_tree, hf_media_format, tvb,
@@ -955,8 +984,10 @@
 		      hf_media_attribute_value,
 		      tvb, offset, -1, FALSE);
 
-  /* decode the rtpmap to see if it is DynamicPayload for RTP-Events RFC2833 to dissect them automatic */
+  /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
   if (strcmp(field_name, "rtpmap") == 0) {
+	gint *key;
+
 	next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 	g_free(field_name);
 
@@ -980,11 +1011,11 @@
 
     encoding_name = tvb_get_string(tvb, offset, tokenlen);
 
-    if (strcmp(encoding_name, "telephone-event") == 0)
-		transport_info->rtp_event_pt = atol(payload_type);
+	key=g_malloc( sizeof(gint) );
+	*key=atol(payload_type);
+	g_hash_table_insert(transport_info->rtp_dyn_payload, key, encoding_name);
 
     g_free(payload_type);
-    g_free(encoding_name);
   } else g_free(field_name);
 }
 
Index: epan/dissectors/packet-h245.c
===================================================================
--- epan/dissectors/packet-h245.c	(revision 13743)
+++ epan/dissectors/packet-h245.c	(working copy)
@@ -9866,7 +9866,7 @@
 		src_addr.len=4;
 		src_addr.data=(char *)&ipv4_address;
 
-		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, 0);
+		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, NULL);
 	}
 	if((!pinfo->fd->flags.visited) && rtcp_ipv4_address!=0 && rtcp_ipv4_port!=0 && rtcp_handle){
 		address src_addr;
@@ -12539,7 +12539,7 @@
 		src_addr.len=4;
 		src_addr.data=(char *)&ipv4_address;
 
-		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, 0);
+		rtp_add_address(pinfo, &src_addr, ipv4_port, 0, "H245", pinfo->fd->num, NULL);
 	}
 	if((!pinfo->fd->flags.visited) && rtcp_ipv4_address!=0 && rtcp_ipv4_port!=0 && rtcp_handle){
 		address src_addr;
Index: epan/dissectors/packet-rtp-events.c
===================================================================
--- epan/dissectors/packet-rtp-events.c	(revision 13743)
+++ epan/dissectors/packet-rtp-events.c	(working copy)
@@ -253,6 +253,6 @@
 	saved_payload_type_value = rtp_event_payload_type_value;
 	/* rtp_event_payload_type_value is set from preferences */
 
-    	dissector_add("rtp.pt", saved_payload_type_value, rtp_events_handle);
-
+    dissector_add("rtp.pt", saved_payload_type_value, rtp_events_handle);
+	dissector_add_string("rtp_dyn_payload_type", "telephone-event", rtp_events_handle);
 }
Index: epan/dissectors/packet-skinny.c
===================================================================
--- epan/dissectors/packet-skinny.c	(revision 13743)
+++ epan/dissectors/packet-skinny.c	(working copy)
@@ -1396,7 +1396,7 @@
 	    src_addr.len=4;
 	    src_addr.data=(char *)&ipv4_address;
 	    tvb_memcpy(tvb, (char *)&ipv4_address, offset+16, 4);
-	    rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset+20), 0, "Skinny", pinfo->fd->num, 0);
+	    rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset+20), 0, "Skinny", pinfo->fd->num, NULL);
       }
       break;
 
@@ -1777,7 +1777,7 @@
 	    src_addr.len=4;
 	    src_addr.data=(char *)&ipv4_address;
 	    tvb_memcpy(tvb, (char *)&ipv4_address, offset+20, 4);
-	    rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset+24), 0, "Skinny", pinfo->fd->num, 0);
+	    rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset+24), 0, "Skinny", pinfo->fd->num, 0, NULL);
       }
       break;
 
Index: epan/dissectors/packet-rtp.c
===================================================================
--- epan/dissectors/packet-rtp.c	(revision 13743)
+++ epan/dissectors/packet-rtp.c	(working copy)
@@ -70,11 +70,11 @@
 
 static dissector_handle_t rtp_handle;
 static dissector_handle_t stun_handle;
-static dissector_handle_t rtpevent_handle=NULL;
 
 static int rtp_tap = -1;
 
 static dissector_table_t rtp_pt_dissector_table;
+static dissector_table_t rtp_dyn_pt_dissector_table;
 
 /* RTP header fields             */
 static int proto_rtp           = -1;
@@ -126,6 +126,7 @@
 static void dissect_rtp( tvbuff_t *tvb, packet_info *pinfo,
     proto_tree *tree );
 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void get_conv_info(tvbuff_t *tvb, packet_info *pinfo);
 
 /* Preferences bool to control whether or not setup info should be shown */
 static gboolean global_rtp_show_setup_info = TRUE;
@@ -235,11 +236,27 @@
        { 0,            NULL },
 };
 
+static void
+free_hash_item( gpointer key _U_ , gpointer value, gpointer user_data _U_ )
+{
+        g_free(value);
+		g_free(key);
+}
+
+void
+rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload)
+{
+	if (rtp_dyn_payload == NULL) return;
+	g_hash_table_foreach(rtp_dyn_payload, (GHFunc)free_hash_item, NULL);
+	g_hash_table_destroy(rtp_dyn_payload);
+	rtp_dyn_payload = NULL;
+}
+
 /* Set up an RTP conversation */
 void rtp_add_address(packet_info *pinfo,
                      address *addr, int port,
                      int other_port,
-                     gchar *setup_method, guint32 setup_frame_number, int rtp_event_pt)
+                     gchar *setup_method, guint32 setup_frame_number, GHashTable *rtp_dyn_payload)
 {
 	address null_addr;
 	conversation_t* p_conv;
@@ -287,6 +304,7 @@
 	if ( ! p_conv_data ) {
 		/* Create conversation data */
 		p_conv_data = g_mem_chunk_alloc(rtp_conversations);
+		p_conv_data->rtp_dyn_payload = NULL;
 
 		conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
 	}
@@ -294,10 +312,13 @@
 	/*
 	 * Update the conversation data.
 	 */
+	/* Free the hash if already exists */
+	rtp_free_hash_dyn_payload(p_conv_data->rtp_dyn_payload);
+
 	strncpy(p_conv_data->method, setup_method, MAX_RTP_SETUP_METHOD_SIZE);
 	p_conv_data->method[MAX_RTP_SETUP_METHOD_SIZE] = '\0';
 	p_conv_data->frame_number = setup_frame_number;
-	p_conv_data->rtp_event_pt = rtp_event_pt;
+	p_conv_data->rtp_dyn_payload = rtp_dyn_payload;
 }
 
 static void rtp_init( void )
@@ -370,25 +391,26 @@
     unsigned int data_reported_len, unsigned int payload_type )
 {
 	tvbuff_t *newtvb;
+	gboolean found_match = FALSE;
 	struct _rtp_conversation_info *p_conv_data = NULL;
 
 	newtvb = tvb_new_subset( tvb, offset, data_len, data_reported_len );
 
-	/* if this is part of a conv set by a SDP, we know the payload type for dynamic payloads */
-	p_conv_data = p_get_proto_data(pinfo->fd, proto_rtp);
-	if (p_conv_data && (strcmp(p_conv_data->method, "SDP") == 0) ) {
-		if ( (p_conv_data->rtp_event_pt != 0) && (p_conv_data->rtp_event_pt == (guint32)payload_type) )
-		{
-			call_dissector(rtpevent_handle, newtvb, pinfo, tree);
-		} else 
-		{
-			proto_tree_add_item( rtp_tree, hf_rtp_data, newtvb, 0, -1, FALSE );
+	/* if the payload type is dynamic (96 to 127), we check if the conv is set and we look for the pt definition */
+	if ( (payload_type >=96) && (payload_type <=127) ) {
+		p_conv_data = p_get_proto_data(pinfo->fd, proto_rtp);
+		if (p_conv_data && p_conv_data->rtp_dyn_payload) {
+			gchar *payload_type_str = NULL;
+			payload_type_str = g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &payload_type);
+			if (payload_type_str)
+				found_match = dissector_try_string(rtp_dyn_pt_dissector_table,
+													payload_type_str, newtvb, pinfo, tree);
 		}
-	} else {
-    /* is not part of a conv, use the preference saved value do decode the payload type */
+	}
+	/* if we don't found, it is static OR could be set static from the preferences */
+	if (found_match == FALSE) 
 		if (!dissector_try_port(rtp_pt_dissector_table, payload_type, newtvb, pinfo, tree))
 				proto_tree_add_item( rtp_tree, hf_rtp_data, newtvb, 0, -1, FALSE );
-	}
 }
 
 static struct _rtp_info rtp_info;
@@ -406,6 +428,7 @@
 	unsigned int csrc_count;
 	gboolean    marker_set;
 	unsigned int payload_type;
+	gchar *payload_type_str = NULL;
 	unsigned int i            = 0;
 	unsigned int hdr_extension= 0;
 	unsigned int padding_count;
@@ -416,7 +439,9 @@
 	guint32     timestamp;
 	guint32     sync_src;
 	guint32     csrc_item;
+	struct _rtp_conversation_info *p_conv_data = NULL;
 
+
 	/* Get the fields in the first octet */
 	octet1 = tvb_get_guint8( tvb, offset );
 	version = RTP_VERSION( octet1 );
@@ -515,21 +540,34 @@
 		rtp_info.info_data = NULL;
 	}
 
+	/* Look for conv and add to the frame if found */
+	get_conv_info(tvb, pinfo);
+
 	if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )   {
 		col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP" );
 	}
 
+	/* if it is dynamic payload, let use the conv data to see if it is defined */
+	if ( (payload_type>95) && (payload_type<128) ) {
+		/* Use existing packet info if available */
+		p_conv_data = p_get_proto_data(pinfo->fd, proto_rtp);
+		if (p_conv_data)
+			payload_type_str = g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &payload_type);
+	}
+
 	if ( check_col( pinfo->cinfo, COL_INFO) ) {
 		col_add_fstr( pinfo->cinfo, COL_INFO,
 		    "Payload type=%s, SSRC=%u, Seq=%u, Time=%u%s",
-		    val_to_str( payload_type, rtp_payload_type_vals,
-		        "Unknown (%u)" ),
+			payload_type_str ? payload_type_str : val_to_str( payload_type, rtp_payload_type_vals,"Unknown (%u)" ),
 		    sync_src,
 		    seq_num,
 		    timestamp,
 		    marker_set ? ", Mark" : "");
 	}
+
+
 	if ( tree ) {
+		proto_tree *item;
 		/* Create RTP protocol tree */
 		ti = proto_tree_add_item(tree, proto_rtp, tvb, offset, -1, FALSE );
 		rtp_tree = proto_item_add_subtree(ti, ett_rtp );
@@ -552,8 +590,12 @@
 
 		proto_tree_add_boolean( rtp_tree, hf_rtp_marker, tvb, offset,
 		    1, octet2 );
-		proto_tree_add_uint( rtp_tree, hf_rtp_payload_type, tvb,
-		    offset, 1, octet2 );
+
+		item = proto_tree_add_uint_format( rtp_tree, hf_rtp_payload_type, tvb,
+		    offset, 1, octet2, "Payload type: %s (%u)", 
+			payload_type_str ? payload_type_str : val_to_str( payload_type, rtp_payload_type_vals,"Unknown"),
+			payload_type);
+
 		offset++;
 
 		/* Sequence number 16 bits (2 octets) */
@@ -568,7 +610,6 @@
 		proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src );
 		offset += 4;
 	} else {
-		show_setup_info(tvb, pinfo, NULL);
 		offset += 12;
 	}
 	/* CSRC list*/
@@ -703,9 +744,8 @@
 		tap_queue_packet(rtp_tap, pinfo, &rtp_info);
 }
 
-
-/* Look for conversation info and display any setup info found */
-static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+/* Look for conversation info */
+static void get_conv_info(tvbuff_t *tvb, packet_info *pinfo)
 {
 	/* Conversation and current data */
 	conversation_t *p_conv = NULL;
@@ -731,34 +771,45 @@
 				p_conv_packet_data = g_mem_chunk_alloc(rtp_conversations);
 				strcpy(p_conv_packet_data->method, p_conv_data->method);
 				p_conv_packet_data->frame_number = p_conv_data->frame_number;
-				p_conv_packet_data->rtp_event_pt = p_conv_data->rtp_event_pt;
+				p_conv_packet_data->rtp_dyn_payload = p_conv_data->rtp_dyn_payload;
 				p_add_proto_data(pinfo->fd, proto_rtp, p_conv_packet_data);
 			}
 		}
 	}
+	if (p_conv_data) rtp_info.info_setup_frame_num = p_conv_data->frame_number;
+}
 
+
+/* Display setup info */
+static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	/* Conversation and current data */
+	struct _rtp_conversation_info *p_conv_data = NULL;
+	proto_tree *rtp_setup_tree;
+	proto_item *ti;
+
+	/* Use existing packet info if available */
+	p_conv_data = p_get_proto_data(pinfo->fd, proto_rtp);
+
+	if (!p_conv_data) return;
+
 	/* Create setup info subtree with summary info. */
-	if (p_conv_data)
-	{
-		proto_tree *rtp_setup_tree;
-		proto_item *ti =  proto_tree_add_string_format(tree, hf_rtp_setup, tvb, 0, 0,
+	ti =  proto_tree_add_string_format(tree, hf_rtp_setup, tvb, 0, 0,
 		                                               "",
 		                                               "Stream setup by %s (frame %d)",
 		                                               p_conv_data->method,
 		                                               p_conv_data->frame_number);
-		PROTO_ITEM_SET_GENERATED(ti);
-		rtp_setup_tree = proto_item_add_subtree(ti, ett_rtp_setup);
-		if (rtp_setup_tree)
-		{
-			/* Add details into subtree */
-			proto_item* item = proto_tree_add_uint(rtp_setup_tree, hf_rtp_setup_frame,
-			                                       tvb, 0, 0, p_conv_data->frame_number);
-			PROTO_ITEM_SET_GENERATED(item);
-			item = proto_tree_add_string(rtp_setup_tree, hf_rtp_setup_method,
-			                             tvb, 0, 0, p_conv_data->method);
-			PROTO_ITEM_SET_GENERATED(item);
-		}
-		rtp_info.info_setup_frame_num = p_conv_data->frame_number;
+	PROTO_ITEM_SET_GENERATED(ti);
+	rtp_setup_tree = proto_item_add_subtree(ti, ett_rtp_setup);
+	if (rtp_setup_tree)
+	{
+		/* Add details into subtree */
+		proto_item* item = proto_tree_add_uint(rtp_setup_tree, hf_rtp_setup_frame,
+		                                       tvb, 0, 0, p_conv_data->frame_number);
+		PROTO_ITEM_SET_GENERATED(item);
+		item = proto_tree_add_string(rtp_setup_tree, hf_rtp_setup_method,
+		                             tvb, 0, 0, p_conv_data->method);
+		PROTO_ITEM_SET_GENERATED(item);
 	}
 }
 
@@ -835,7 +886,7 @@
 				"rtp.p_type",
 				FT_UINT8,
 				BASE_DEC,
-				VALS(rtp_payload_type_vals),
+				"",
 				0x7F,
 				"", HFILL
 			}
@@ -1016,11 +1067,15 @@
 	proto_register_subtree_array(ett, array_length(ett));
 
 	register_dissector("rtp", dissect_rtp, proto_rtp);
+
 	rtp_tap = register_tap("rtp");
 
 	rtp_pt_dissector_table = register_dissector_table("rtp.pt",
 	                                                  "RTP payload type", FT_UINT8, BASE_DEC);
+	rtp_dyn_pt_dissector_table = register_dissector_table("rtp_dyn_payload_type",
+												    "Dynamic RTP payload type", FT_STRING, BASE_NONE);
 
+
 	rtp_module = prefs_register_protocol(proto_rtp, NULL);
 
 	prefs_register_bool_preference(rtp_module, "show_setup_info",
@@ -1048,7 +1103,6 @@
 {
 	data_handle = find_dissector("data");
 	stun_handle = find_dissector("stun");
-	rtpevent_handle = find_dissector("rtpevent");
 
 	/*
 	 * Register this dissector as one that can be selected by a
Index: epan/dissectors/packet-rtp.h
===================================================================
--- epan/dissectors/packet-rtp.h	(revision 13743)
+++ epan/dissectors/packet-rtp.h	(working copy)
@@ -58,7 +58,7 @@
 {
 	gchar   method[MAX_RTP_SETUP_METHOD_SIZE + 1];
 	guint32 frame_number;
-	guint32 rtp_event_pt;	/* this is payload type for dynamic RTP events (RFC2833) */
+	GHashTable *rtp_dyn_payload;   /* a hash table with the dynamic RTP payload */
 };
 
 /* Add an RTP conversation with the given details */
@@ -67,4 +67,8 @@
                      int other_port,
                      gchar *setup_method, 
 					 guint32 setup_frame_number,
-					 int rtp_event_pt);
+					 GHashTable *rtp_dyn_payload);
+
+/* Free and destroy the dyn_payload hash table */
+void rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload);
+