Fix various typos and spelling errors.
[obnox/wireshark/wip.git] / epan / dissectors / packet-sdp.c
index 6b9b4c6cf71d6f88fd46c367114c9b682f3a292b..2199027780cecc46dcb6c7e7d9f4b2acde2164b3 100644 (file)
 
 #include "config.h"
 
+#include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #endif
 
 #ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>          /* needed to define AF_ values on Windows */
+#include <winsock2.h>           /* needed to define AF_ values on Windows */
 #endif
 
 #ifdef NEED_INET_V6DEFS_H
-# include "inet_v6defs.h"
+# include "wsutil/inet_v6defs.h"
 #endif
 
 #include <glib.h>
 #include <epan/packet.h>
-#include <epan/conversation.h>
 #include <epan/strutil.h>
 #include <epan/emem.h>
 #include <epan/base64.h>
 #include <epan/asn1.h>
 
-#include "tap.h"
+#include <epan/tap.h>
 #include "packet-sdp.h"
 
 #include "packet-rtp.h"
 #include "packet-msrp.h"
 #include "packet-per.h"
 #include "packet-h245.h"
+#include "packet-h264.h"
+#include "packet-mp4ves.h"
 
-static dissector_handle_t rtp_handle=NULL;
-static dissector_handle_t rtcp_handle=NULL;
-static dissector_handle_t t38_handle=NULL;
-static dissector_handle_t msrp_handle=NULL;
+static dissector_handle_t rtp_handle    = NULL;
+static dissector_handle_t rtcp_handle   = NULL;
+static dissector_handle_t t38_handle    = NULL;
+static dissector_handle_t msrp_handle   = NULL;
+static dissector_handle_t h264_handle   = NULL;
+static dissector_handle_t mp4ves_handle = NULL;
 
 static int sdp_tap = -1;
 
@@ -159,9 +165,13 @@ static int hf_media_format = -1;
 static int hf_media_attribute_field = -1;
 static int hf_media_attribute_value = -1;
 static int hf_media_encoding_name = -1;
+static int hf_media_sample_rate = -1;
 static int hf_media_format_specific_parameter = -1;
-static int hf_sdp_fmtp_profile_level_id = -1;
+static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
 static int hf_sdp_fmtp_h263_profile = -1;
+static int hf_sdp_fmtp_h263_level = -1;
+static int hf_sdp_h264_packetization_mode = -1;
+static int hf_sdp_h264_sprop_parameter_sets = -1;
 static int hf_SDPh223LogicalChannelParameters = -1;
 
 /* hf_session_attribute hf_media_attribute subfields */
@@ -187,7 +197,7 @@ static int ett_sdp_key_mgmt = -1;
 
 #define SDP_MAX_RTP_CHANNELS 4
 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
-
+#define SDP_NO_OF_PT 128
 typedef struct {
   gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
   gint8 pt_count;
@@ -197,7 +207,9 @@ typedef struct {
 typedef struct {
   char *connection_address;
   char *connection_type;
-  char *encoding_name;
+  char *media_type;
+  char *encoding_name[SDP_NO_OF_PT];
+  int   sample_rate[SDP_NO_OF_PT];
   char *media_port[SDP_MAX_RTP_CHANNELS];
   char *media_proto[SDP_MAX_RTP_CHANNELS];
   transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
@@ -224,7 +236,7 @@ void proto_reg_handoff_sdp(void);
 
 /* static functions */
 
-static void call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti,
+static void call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
                                   transport_info_t *transport_info);
 
 /* Subdissector functions */
@@ -239,7 +251,16 @@ static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti);
 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti);
 static void dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
                               transport_info_t *transport_info);
-static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti, transport_info_t *transport_info);
+static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti, int length,transport_info_t *transport_info);
+
+static void free_encoding_name_str (void *ptr)
+{
+  encoding_name_and_rate_t *encoding_name_and_rate = (encoding_name_and_rate_t *)ptr;
+
+  if (encoding_name_and_rate->encoding_name) {
+    g_free(encoding_name_and_rate->encoding_name);
+  }
+}
 
 static void
 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -269,9 +290,11 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   gboolean    set_rtp=FALSE;
   gboolean    is_ipv4_addr=FALSE;
   gboolean    is_ipv6_addr=FALSE;
+  gboolean    is_video=FALSE;
   guint32     ipaddr[4];
   gint        n,i;
   sdp_packet_info *sdp_pi;
+  gchar       *unknown_encoding = ep_strdup("Unknown");
 
   /* Initialise packet info for passing to tap */
   sdp_pi = ep_alloc(sizeof(sdp_packet_info));
@@ -280,19 +303,18 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   /* Initialise RTP channel info */
   transport_info.connection_address=NULL;
   transport_info.connection_type=NULL;
-  transport_info.encoding_name=NULL;
+  transport_info.media_type=NULL;
+  for (n=0; n < SDP_NO_OF_PT; n++){
+    transport_info.encoding_name[n]=unknown_encoding;
+    transport_info.sample_rate[n] = 0;
+  }
   for (n=0; n < SDP_MAX_RTP_CHANNELS; n++)
   {
     transport_info.media_port[n]=NULL;
     transport_info.media_proto[n]=NULL;
     transport_info.media[n].pt_count = 0;
-#if GLIB_MAJOR_VERSION < 2
-    transport_info.media[n].rtp_dyn_payload = g_hash_table_new( g_int_hash, 
-       g_int_equal);
-#else
-    transport_info.media[n].rtp_dyn_payload = g_hash_table_new_full( g_int_hash, 
-       g_int_equal, g_free, g_free);
-#endif
+    transport_info.media[n].rtp_dyn_payload =
+        g_hash_table_new_full( g_int_hash, g_int_equal, g_free, free_encoding_name_str);
   }
   transport_info.media_count = 0;
 
@@ -310,13 +332,10 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
    * what the protocol inside which the SDP stuff resides
    * put there.
    */
-  if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
+  col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
 
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    /* XXX: Needs description. */
-    col_append_str(pinfo->cinfo, COL_INFO, ", with session description");
-  }
+  /* XXX: Needs description. */
+  col_append_str(pinfo->cinfo, COL_INFO, ", with session description");
 
   ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, FALSE);
   sdp_tree = proto_item_add_subtree(ti, ett_sdp);
@@ -343,8 +362,8 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     type = tvb_get_guint8(tvb,offset);
     delim = tvb_get_guint8(tvb,offset + 1);
     if (delim != '=') {
-      proto_item *ti = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, FALSE);
-      expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_NOTE,
+      proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, FALSE);
+      expert_add_info_format(pinfo, ti2, PI_MALFORMED, PI_NOTE,
                              "Invalid SDP line (no '=' delimiter)");
       offset = next_offset;
       continue;
@@ -424,8 +443,8 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     call_sdp_subdissector(tvb_new_subset(tvb,offset+tokenoffset,
                                          linelen-tokenoffset,
                                          linelen-tokenoffset),
-                                                 pinfo,
-                          hf,sub_ti,&transport_info),
+                                         pinfo,
+                                         hf,sub_ti,linelen-tokenoffset,&transport_info),
     offset = next_offset;
   }
 
@@ -446,14 +465,15 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        * and stream decoding is enabled in preferences
        */
        if(global_sdp_establish_conversation){
-            /* Check if media protocol is RTP */
-            is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
-            /* Check if media protocol is SRTP */
-            is_srtp = (strcmp(transport_info.media_proto[n],"RTP/SAVP")==0);
-            /* Check if media protocol is T38 */
-            is_t38 = ( (strcmp(transport_info.media_proto[n],"UDPTL")==0) || (strcmp(transport_info.media_proto[n],"udptl")==0) );
-            /* Check if media protocol is MSRP/TCP */
-            is_msrp = (strcmp(transport_info.media_proto[n],"msrp/tcp")==0);
+         /* Check if media protocol is RTP */
+         is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
+         /* Check if media protocol is SRTP */
+         is_srtp = (strcmp(transport_info.media_proto[n],"RTP/SAVP")==0);
+         /* Check if media protocol is T38 */
+         is_t38 = ( (strcmp(transport_info.media_proto[n],"UDPTL")==0) ||
+                    (strcmp(transport_info.media_proto[n],"udptl")==0) );
+         /* Check if media protocol is MSRP/TCP */
+         is_msrp = (strcmp(transport_info.media_proto[n],"msrp/tcp")==0);
        }
     }
 
@@ -478,6 +498,9 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         }
       }
     }
+    if (strcmp(transport_info.media_type,"video")==0){
+      is_video = TRUE;
+    }
     set_rtp = FALSE;
     /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
     if((!pinfo->fd->flags.visited) && port!=0 && (is_rtp||is_srtp) && (is_ipv4_addr || is_ipv6_addr)){
@@ -485,10 +508,10 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
       if(rtp_handle){
         if (is_srtp) {
           struct srtp_info *dummy_srtp_info = se_alloc0(sizeof(struct srtp_info));
-          srtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num,
+          srtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num, is_video,
                            transport_info.media[n].rtp_dyn_payload, dummy_srtp_info);
         } else {
-          rtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num,
+          rtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num, is_video,
                           transport_info.media[n].rtp_dyn_payload);
         }
         set_rtp = TRUE;
@@ -510,28 +533,36 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     /* Add MSRP conversation.  Uses addresses discovered in attribute
        rather than connection information of media session line */
     if (is_msrp ){
-        if ((!pinfo->fd->flags.visited) && msrp_transport_address_set){
-            if(msrp_handle){
-                src_addr.type=AT_IPv4;
-                src_addr.len=4;
-                src_addr.data=(guint8*)&msrp_ipaddr;
-                msrp_add_address(pinfo, &src_addr, msrp_port_number, "SDP", pinfo->fd->num);
-            }
+      if ((!pinfo->fd->flags.visited) && msrp_transport_address_set){
+        if(msrp_handle){
+          src_addr.type=AT_IPv4;
+          src_addr.len=4;
+          src_addr.data=(guint8*)&msrp_ipaddr;
+          msrp_add_address(pinfo, &src_addr, msrp_port_number, "SDP", pinfo->fd->num);
         }
+      }
     }
 
-    /* Create the RTP summary str for the Voip Call analysis */
-    for (i = 0; i < transport_info.media[n].pt_count; i++)
-    {
-      /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
-      if ( (transport_info.media[n].pt[i] >=96) && (transport_info.media[n].pt[i] <=127) ) {
-        gchar *str_dyn_pt = g_hash_table_lookup(transport_info.media[n].rtp_dyn_payload, &transport_info.media[n].pt[i]);
-        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[n].pt[i]);
-      } else
-        g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, val_to_str(transport_info.media[n].pt[i], rtp_payload_type_short_vals, "%u"));
+    if (port!=0) {
+      /* Create the RTP summary str for the Voip Call analysis */
+      for (i = 0; i < transport_info.media[n].pt_count; i++)
+      {
+        /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
+        if ( (transport_info.media[n].pt[i] >=96) && (transport_info.media[n].pt[i] <=127) ) {
+          encoding_name_and_rate_t *encoding_name_and_rate_pt = g_hash_table_lookup(transport_info.media[n].rtp_dyn_payload, &transport_info.media[n].pt[i]);
+          if (encoding_name_and_rate_pt) {
+            if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
+            g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
+          } else {
+            char num_pt[10];
+            g_snprintf(num_pt, 10, "%u", transport_info.media[n].pt[i]);
+            if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
+            g_strlcat(sdp_pi->summary_str, num_pt, 50);
+          }
+        } else
+          if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
+          g_strlcat(sdp_pi->summary_str, val_to_str_ext(transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"), 50);
+      }
     }
 
     /* Free the hash table if we did't assigned it to a conv use it */
@@ -539,7 +570,10 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
       rtp_free_hash_dyn_payload(transport_info.media[n].rtp_dyn_payload);
 
     /* Create the T38 summary str for the Voip Call analysis */
-    if (is_t38) g_snprintf(sdp_pi->summary_str, 50, "%s t38", sdp_pi->summary_str);
+    if (port!=0 && is_t38) {
+      if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
+      g_strlcat(sdp_pi->summary_str, "t38", 50);
+    }
   }
 
   /* Free the remainded hash tables not used */
@@ -560,7 +594,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 }
 
 static void
-call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, transport_info_t *transport_info){
+call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,transport_info_t *transport_info){
   if(hf == hf_owner){
     dissect_sdp_owner(tvb,ti);
   } else if ( hf == hf_connection_info) {
@@ -580,7 +614,7 @@ call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti,
   } else if ( hf == hf_media ) {
     dissect_sdp_media(tvb,ti,transport_info);
   } else if ( hf == hf_media_attribute ){
-    dissect_sdp_media_attribute(tvb,pinfo,ti,transport_info);
+    dissect_sdp_media_attribute(tvb,pinfo,ti, length, transport_info);
   }
 }
 
@@ -751,14 +785,14 @@ dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti){
   item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
                       tokenlen, FALSE);
   if (tvb_strneql(tvb, offset, "CT", 2) == 0){
-         proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
-         unit_is_kbs = TRUE;
+    proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
+    unit_is_kbs = TRUE;
   }else if (tvb_strneql(tvb, offset, "AS", 2) == 0){
-         proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
-         unit_is_kbs = TRUE;
+    proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
+    unit_is_kbs = TRUE;
   }else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0){
-         proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
-         unit_is_bps = TRUE;
+    proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
+    unit_is_bps = TRUE;
   }
 
 
@@ -767,9 +801,9 @@ dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti){
   item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
                       FALSE);
   if (unit_is_kbs == TRUE)
-          proto_item_append_text(item, " kb/s");
+    proto_item_append_text(item, " kb/s");
   if (unit_is_bps == TRUE)
-          proto_item_append_text(item, " b/s");
+    proto_item_append_text(item, " b/s");
 }
 
 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti){
@@ -897,27 +931,8 @@ static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti){
                       tvb, offset, -1, FALSE);
 }
 
-/* Return a tvb that contains the binary representation of a base64
-   string */
-
-static tvbuff_t *
-base64_to_tvb(const char *base64)
-{
-  tvbuff_t *tvb;
-  char *data = g_strdup(base64);
-  size_t len;
-
-  len = epan_base64_decode(data);
-  tvb = tvb_new_real_data((const guint8 *)data, len, len);
-
-  tvb_set_free_cb(tvb, g_free);
-
-  return tvb;
-}
-
-
 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti){
-  gchar *data = NULL;
+  gchar *data_p = NULL;
   gchar *prtcl_id = NULL;
   gint len;
   tvbuff_t *keymgmt_tvb;
@@ -945,25 +960,27 @@ static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti
   if (len < 0)
     return;
 
-  data = tvb_get_ephemeral_string(tvb, offset, len);
-  keymgmt_tvb = base64_to_tvb(data);
-  tvb_set_child_real_data_tvbuff(tvb, keymgmt_tvb);
+  data_p = tvb_get_ephemeral_string(tvb, offset, len);
+  keymgmt_tvb = base64_to_tvb(tvb, data_p);
   add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
 
   if ( prtcl_id != NULL && key_mgmt_dissector_table != NULL ) {
     found_match = dissector_try_string(key_mgmt_dissector_table,
-                                      prtcl_id,
-                                      keymgmt_tvb, pinfo,
-                                      key_tree);
+                                       prtcl_id,
+                                       keymgmt_tvb, pinfo,
+                                       key_tree);
   }
 
-  if (found_match)
-    proto_tree_add_item_hidden(key_tree, hf_key_mgmt_data,
-                              keymgmt_tvb, 0, -1, FALSE);
-  else
+  if (found_match) {
+    proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
+                                         keymgmt_tvb, 0, -1, FALSE);
+    PROTO_ITEM_SET_HIDDEN(ti2);
+  }
+  else {
     proto_tree_add_item(key_tree, hf_key_mgmt_data,
-                       keymgmt_tvb, 0, -1, FALSE);
-  return;
+                        keymgmt_tvb, 0, -1, FALSE);
+  }
+
 }
 
 
@@ -994,7 +1011,7 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr
   offset = next_offset + 1;
 
   if (strcmp((char*)field_name, "ipbcp") == 0) {
-    offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"0123456789");
+    offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"0123456789", NULL);
 
     if (offset == -1)
       return;
@@ -1008,7 +1025,7 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr
 
     proto_tree_add_item(sdp_session_attribute_tree,hf_ipbcp_version,tvb,offset,tokenlen,FALSE);
 
-    offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+    offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
 
     if (offset == -1)
       return;
@@ -1023,7 +1040,7 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr
     tvbuff_t *key_tvb;
     proto_item *key_ti;
 
-    key_tvb = tvb_new_subset(tvb, offset, -1, -1);
+    key_tvb = tvb_new_subset_remaining(tvb, offset);
     key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, FALSE);
 
     dissect_key_mgmt(key_tvb, pinfo, key_ti);
@@ -1033,11 +1050,13 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr
   }
 }
 
+
+/* Dissect media description */
 static void
 dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
                   transport_info_t *transport_info){
   proto_tree *sdp_media_tree;
-  gint offset, next_offset, tokenlen, index;
+  gint offset, next_offset, tokenlen, idx;
   guint8 *media_format;
 
   offset = 0;
@@ -1047,6 +1066,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
   /* Re-initialise for a new media description */
   msrp_transport_address_set = FALSE;
 
+  /* Create tree for media session */
   sdp_media_tree = proto_item_add_subtree(ti,ett_sdp_media);
 
   next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
@@ -1056,9 +1076,12 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
 
   tokenlen = next_offset - offset;
 
+  /* Type of media session */
   proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
                       FALSE);
 
+  transport_info->media_type = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
+
   offset = next_offset + 1;
 
   next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
@@ -1110,7 +1133,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
   proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
                       FALSE);
 
-  do{
+  do {
     offset = next_offset + 1;
     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 
@@ -1126,10 +1149,10 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
                "RTP/AVP") == 0) {
       media_format = tvb_get_ephemeral_string(tvb, offset, tokenlen);
       proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
-                            tokenlen, val_to_str(atol((char*)media_format), rtp_payload_type_vals, "%u"));
-      index = transport_info->media[transport_info->media_count].pt_count;
-      transport_info->media[transport_info->media_count].pt[index] = atol((char*)media_format);
-      if (index < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
+                            tokenlen, val_to_str_ext(atol((char*)media_format), &rtp_payload_type_vals_ext, "%u"));
+      idx = transport_info->media[transport_info->media_count].pt_count;
+      transport_info->media[transport_info->media_count].pt[idx] = atol((char*)media_format);
+      if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
         transport_info->media[transport_info->media_count].pt_count++;
     } else {
       proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
@@ -1152,95 +1175,81 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
 
 }
 
-/*
-14496-2, Annex G, Table G-1.
-Table G-1 FLC table for profile_and_level_indication Profile/Level Code
-*/
-static const value_string mpeg4es_level_indication_vals[] =
+static tvbuff_t *
+ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
 {
-  { 0,    "Reserved" },
-  { 1,    "Simple Profile/Level 1" },
-  { 2,    "Simple Profile/Level 2" },
-  { 3,    "Reserved" },
-  { 4,    "Reserved" },
-  { 5,    "Reserved" },
-  { 6,    "Reserved" },
-  { 7,    "Reserved" },
-  { 8,    "Simple Profile/Level 0" },
-  { 9,    "Simple Profile/Level 0b" },
-  /* Reserved 00001001 - 00010000 */
-  { 0x11, "Simple Scalable Profile/Level 1" },
-  { 0x12, "Simple Scalable Profile/Level 2" },
-  /* Reserved 00010011 - 00100000 */
-  { 0x21, "Core Profile/Level 1" },
-  { 0x22, "Core Profile/Level 2" },
-  /* Reserved 00100011 - 00110001 */
-  { 0x32, "Main Profile/Level 2" },
-  { 0x33, "Main Profile/Level 3" },
-  { 0x34, "Main Profile/Level 4" },
-  /* Reserved 00110101 - 01000001  */
-  { 0x42, "N-bit Profile/Level 2" },
-  /* Reserved 01000011 - 01010000  */
-  { 0x51, "Scalable Texture Profile/Level 1" },
-  /* Reserved 01010010 - 01100000 */
-  { 0x61, "Simple Face Animation Profile/Level 1" },
-  { 0x62, "Simple Face Animation Profile/Level 2" },
-  { 0x63, "Simple FBA Profile/Level 1" },
-  { 0x64, "Simple FBA Profile/Level 2" },
-  /* Reserved 01100101 - 01110000 */
-  { 0x71, "Basic Animated Texture Profile/Level 1" },
-  { 0x72, "Basic Animated Texture Profile/Level 2" },
-  /* Reserved 01110011 - 10000000 */
-  { 0x81, "Hybrid Profile/Level 1" },
-  { 0x82, "Hybrid Profile/Level 2" },
-  /* Reserved 10000011 - 10010000 */
-  { 0x91, "Advanced Real Time Simple Profile/Level 1" },
-  { 0x92, "Advanced Real Time Simple Profile/Level 2" },
-  { 0x93, "Advanced Real Time Simple Profile/Level 3" },
-  { 0x94, "Advanced Real Time Simple Profile/Level 4" },
-  /* Reserved 10010101 - 10100000 */
-  { 0xa1, "Core Scalable Profile/Level 1" },
-  { 0xa2, "Core Scalable Profile/Level 2" },
-  { 0xa3, "Core Scalable Profile/Level 3" },
-  /* Reserved 10100100 - 10110000  */
-  { 0xb1, "Advanced Coding Efficiency Profile/Level 1" },
-  { 0xb2, "Advanced Coding Efficiency Profile/Level 2" },
-  { 0xb3, "Advanced Coding Efficiency Profile/Level 3" },
-  { 0xb4, "Advanced Coding Efficiency Profile/Level 4" },
-  /* Reserved 10110101 - 11000000 */
-  { 0xc1, "Advanced Core Profile/Level 1" },
-  { 0xc2, "Advanced Core Profile/Level 2" },
-  /* Reserved 11000011 - 11010000 */
-  { 0xd1, "Advanced Scalable Texture/Level 1" },
-  { 0xd2, "Advanced Scalable Texture/Level 2" },
-  { 0xd3, "Advanced Scalable Texture/Level 3" },
-  /* Reserved 11010100 - 11100000 */
-  { 0xe1, "Simple Studio Profile/Level 1" },
-  { 0xe2, "Simple Studio Profile/Level 2" },
-  { 0xe3, "Simple Studio Profile/Level 3" },
-  { 0xe4, "Simple Studio Profile/Level 4" },
-  { 0xe5, "Core Studio Profile/Level 1" },
-  { 0xe6, "Core Studio Profile/Level 2" },
-  { 0xe7, "Core Studio Profile/Level 3" },
-  { 0xe8, "Core Studio Profile/Level 4" },
-  /* Reserved 11101001 - 11101111 */
-  { 0xf0, "Advanced Simple Profile/Level 0" },
-  { 0xf1, "Advanced Simple Profile/Level 1" },
-  { 0xf2, "Advanced Simple Profile/Level 2" },
-  { 0xf3, "Advanced Simple Profile/Level 3" },
-  { 0xf4, "Advanced Simple Profile/Level 4" },
-  { 0xf5, "Advanced Simple Profile/Level 5" },
-  /* Reserved 11110110 - 11110111 */
-  { 0xf8, "Fine Granularity Scalable Profile/Level 0" },
-  { 0xf9, "Fine Granularity Scalable Profile/Level 1" },
-  { 0xfa, "Fine Granularity Scalable Profile/Level 2" },
-  { 0xfb, "Fine Granularity Scalable Profile/Level 3" },
-  { 0xfc, "Fine Granularity Scalable Profile/Level 4" },
-  { 0xfd, "Fine Granularity Scalable Profile/Level 5" },
-  { 0xfe, "Reserved" },
-  { 0xff, "Reserved for Escape" },
-  { 0, NULL },
-};
+  guint8 *buf = g_malloc(10240);
+
+  /* arbitrary maximum length */
+  if(len<20480){
+    int i;
+    tvbuff_t *bytes_tvb;
+
+    /* first, skip to where the encoded pdu starts, this is
+       the first hex digit after the '=' char.
+    */
+    while(1){
+      if((*msg==0)||(*msg=='\n')){
+        return NULL;
+      }
+      if(*msg=='='){
+        msg++;
+        break;
+      }
+      msg++;
+    }
+    while(1){
+      if((*msg==0)||(*msg=='\n')){
+        return NULL;
+      }
+      if( ((*msg>='0')&&(*msg<='9'))
+          ||  ((*msg>='a')&&(*msg<='f'))
+          ||  ((*msg>='A')&&(*msg<='F'))){
+        break;
+      }
+      msg++;
+    }
+    i=0;
+    while( ((*msg>='0')&&(*msg<='9'))
+           ||((*msg>='a')&&(*msg<='f'))
+           ||((*msg>='A')&&(*msg<='F'))  ){
+      int val;
+      if((*msg>='0')&&(*msg<='9')){
+        val=(*msg)-'0';
+      } else if((*msg>='a')&&(*msg<='f')){
+        val=(*msg)-'a'+10;
+      } else if((*msg>='A')&&(*msg<='F')){
+        val=(*msg)-'A'+10;
+      } else {
+        return NULL;
+      }
+      val<<=4;
+      msg++;
+      if((*msg>='0')&&(*msg<='9')){
+        val|=(*msg)-'0';
+      } else if((*msg>='a')&&(*msg<='f')){
+        val|=(*msg)-'a'+10;
+      } else if((*msg>='A')&&(*msg<='F')){
+        val|=(*msg)-'A'+10;
+      } else {
+        return NULL;
+      }
+      msg++;
+
+      buf[i]=(guint8)val;
+      i++;
+    }
+    if(i==0){
+      return NULL;
+    }
+    bytes_tvb = tvb_new_child_real_data(tvb, buf,i,i);
+    tvb_set_free_cb(bytes_tvb, g_free);
+    add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
+    return bytes_tvb;
+  }
+  return NULL;
+}
+
 /* Annex X Profiles and levels definition */
 static const value_string h263_profile_vals[] =
 {
@@ -1256,19 +1265,49 @@ static const value_string h263_profile_vals[] =
   { 0, NULL },
 };
 
+
+/* RFC 4629 The level are described in table X.2 of H.263 annex X */
+static const value_string h263_level_vals[] =
+{
+  { 10,    "QCIF (176 x 144), 1 x 64Kb/s" },
+  { 20,    "CIF (352 x 288), 2 x 64Kb/s" },
+  { 30,    "CIF (352 x 288), 6 x 64Kb/s" },
+  { 40,    "CIF (352 x 288), 32 x 64Kb/s" },
+  { 45,    "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
+  { 50,    "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
+  { 60,    "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
+  { 70,    "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
+  { 0, NULL },
+};
+
+
+static const value_string h264_packetization_mode_vals[] =
+{
+  { 0,    "Single NAL mode" },
+  { 1,    "Non-interleaved mode" },
+  { 2,    "Interleaved mode" },
+  { 0, NULL },
+};
+
 /*
  * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
  */
 static void
-decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, gint offset, gint tokenlen, guint8 *mime_type){
+decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type){
   gint next_offset;
   gint end_offset;
   guint8 *field_name;
-  guint8 *format_specific_parameter;
+  gchar *format_specific_parameter;
   proto_item *item;
+  tvbuff_t *data_tvb;
 
   end_offset = offset + tokenlen;
 
+  /*
+  proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
+  tvb_get_ephemeral_string(tvb, offset, tokenlen));
+  */
+
   /* Look for an '=' within this value - this may indicate that there is a
      profile-level-id parameter to find if the MPEG4 media type is in use */
   next_offset = tvb_find_guint8(tvb,offset,-1,'=');
@@ -1281,23 +1320,33 @@ decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, gint offset, gint tokenlen, gui
   /* Find the name of the parameter */
   tokenlen = next_offset - offset;
   field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+  /*proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
 
   offset = next_offset;
 
   /* Dissect the MPEG4 profile-level-id parameter if present */
-  if (mime_type != NULL && strcmp((char*)mime_type, "MP4V-ES") == 0) {
+  if (mime_type != NULL && g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0) {
     if (strcmp((char*)field_name, "profile-level-id") == 0) {
       offset++;
       tokenlen = end_offset - offset;
       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
-      item = proto_tree_add_uint(tree, hf_sdp_fmtp_profile_level_id, tvb, offset, tokenlen,
+      item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
                                  atol((char*)format_specific_parameter));
       PROTO_ITEM_SET_GENERATED(item);
+    } else if (strcmp((char*)field_name, "config") == 0) {
+      /* String including "=" */
+      tokenlen = end_offset - offset;
+      format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+      /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
+      data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
+      if(mp4ves_handle && data_tvb){
+        dissect_mp4ves_config(data_tvb, pinfo, tree);
+      }
     }
   }
 
   /* Dissect the H263-2000 profile parameter if present */
-  if (mime_type != NULL && strcmp((char*)mime_type, "H263-2000") == 0) {
+  if ((mime_type != NULL && g_ascii_strcasecmp(mime_type, "H263-2000") == 0)||(mime_type != NULL && g_ascii_strcasecmp(mime_type, "H263-1998") == 0)) {
     if (strcmp((char*)field_name, "profile") == 0) {
       offset++;
       tokenlen = end_offset - offset;
@@ -1305,67 +1354,153 @@ decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, gint offset, gint tokenlen, gui
       item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
                                  atol((char*)format_specific_parameter));
       PROTO_ITEM_SET_GENERATED(item);
+    } else if(strcmp((char*)field_name, "level") == 0) {
+      offset++;
+      tokenlen = end_offset - offset;
+      format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+      item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
+                                 atol((char*)format_specific_parameter));
+      PROTO_ITEM_SET_GENERATED(item);
     }
   }
 
-#if 0
-  /* TODO: Add code to dissect H264 fmtp parameters wehen an example can be found */
-  if (mime_type != NULL && strcmp(mime_type, "H264") == 0) {
+
+  /* Dissect the H264 profile-level-id parameter
+   * RFC 3984:
+   * A base16 [6] (hexadecimal) representation of
+   * the following three bytes in the sequence
+   * parameter set NAL unit specified in [1]: 1)
+   * profile_idc, 2) a byte herein referred to as
+   * profile-iop, composed of the values of
+   * constraint_set0_flag, constraint_set1_flag,
+   * constraint_set2_flag, and reserved_zero_5bits
+   * in bit-significance order, starting from the
+   * most significant bit, and 3) level_idc.
+   */
+  if (mime_type != NULL && g_ascii_strcasecmp(mime_type, "H264") == 0) {
     if (strcmp(field_name, "profile-level-id") == 0) {
-      char **endptr;
+      int length = 0;
 
+      /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
+      tokenlen = end_offset - offset;
+      format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+      data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
+         if(!data_tvb){
+                 item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes",format_specific_parameter);
+                 return;
+         }
+         length = tvb_length(data_tvb);
+      if (length == 3){
+        if(h264_handle && data_tvb){
+          dissect_h264_profile(data_tvb, pinfo, tree);
+        }
+      }else{
+        item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
+        PROTO_ITEM_SET_GENERATED(item);
+      }
+    }else if (strcmp(field_name, "packetization-mode") == 0) {
       offset++;
       tokenlen = end_offset - offset;
       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
-      proto_tree_add_text(tree, tvb, offset, tokenlen,
-                                   "Test %u", strtoul(format_specific_parameter, endptr, 16));
-       }
+      item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
+                                 atol((char*)format_specific_parameter));
+      PROTO_ITEM_SET_GENERATED(item);
+
+    }else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
+      /* The value of the parameter is the
+         base64 [6] representation of the initial
+         parameter set NAL units as specified in
+         sections 7.3.2.1 and 7.3.2.2 of [1].  The
+         parameter sets are conveyed in decoding order,
+         and no framing of the parameter set NAL units
+         takes place.  A comma is used to separate any
+         pair of parameter sets in the list.
+      */
+      gchar *data_p = NULL;
+      gint comma_offset;
+
+
+      /* Move past '=' */
+      offset++;
+      comma_offset = tvb_find_guint8(tvb,offset,-1,',');
+      if (comma_offset != -1){
+        tokenlen = comma_offset - offset;
+      }else{
+        tokenlen = end_offset - offset;
+      }
+
+      data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+      proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 1 string: %s", data_p);
+
+      /* proto_tree_add_text(tree, tvb, offset, tokenlen, "String %s",data_p); */
+      data_tvb = base64_to_tvb(tvb, data_p);
+      add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
+
+      if(h264_handle && data_tvb){
+        dissect_h264_nal_unit(data_tvb, pinfo, tree);
+        if (comma_offset != -1){
+          /* Second NAL unit */
+          offset = comma_offset +1;
+          tokenlen = end_offset - offset;
+          data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+          proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 2 string: %s", data_p);
+          data_tvb = base64_to_tvb(tvb, data_p);
+          add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
+          dissect_h264_nal_unit(data_tvb, pinfo, tree);
+        }
+      }
+    }
   }
-#endif
+
 }
 
 typedef struct {
         const char *name;
 } sdp_names_t;
 
-#define SDP_RTPMAP             1
-#define SDP_FMTP               2
-#define SDP_PATH               3
-#define SDP_H248_ITEM  4
+#define SDP_RTPMAP              1
+#define SDP_FMTP                2
+#define SDP_PATH                3
+#define SDP_H248_ITEM   4
 
 static const sdp_names_t sdp_media_attribute_names[] = {
-               { "Unknown-name"},      /* 0 Pad so that the real headers start at index 1 */
-               { "rtpmap"},            /* 1 */
-               { "fmtp"},                      /* 2 */
-               { "path"},                      /* 3 */
-               { "h248item"},          /* 4 */
+  { "Unknown-name"},    /* 0 Pad so that the real headers start at index 1 */
+  { "rtpmap"},          /* 1 */
+  { "fmtp"},            /* 2 */
+  { "path"},            /* 3 */
+  { "h248item"},        /* 4 */
 };
 
 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
 {
-        guint i;
+  guint i;
 
-        for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
-                if (len == strlen(sdp_media_attribute_names[i].name) &&
-                    tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0)
-                        return i;
-        }
+  for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
+    if (len == strlen(sdp_media_attribute_names[i].name) &&
+        tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0)
+      return i;
+  }
 
-        return -1;
+  return -1;
 }
 
-static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, transport_info_t *transport_info){
+static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length, transport_info_t *transport_info){
   proto_tree *sdp_media_attribute_tree;
   proto_item *fmtp_item, *media_format_item;
   proto_tree *fmtp_tree;
-  gint offset, next_offset, tokenlen, n;
+  gint offset, next_offset, tokenlen, n, colon_offset;
+  gint start_offset;
   guint8 *field_name;
   guint8 *payload_type;
   guint8 *attribute_value;
   gint   *key;
-  gint sdp_media_attrbute_code;
+  guint8 pt;
+  gint  sdp_media_attrbute_code;
   const char *msrp_res = "msrp://";
   const char *h324ext_h223lcparm = "h324ext/h223lcparm";
+  gboolean has_more_pars = TRUE;
+  tvbuff_t *h245_tvb;
+  encoding_name_and_rate_t *encoding_name_and_rate;
 
   offset = 0;
   next_offset = 0;
@@ -1375,13 +1510,13 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
   sdp_media_attribute_tree = proto_item_add_subtree(ti,
                                                     ett_sdp_media_attribute);
   /* Find end of field */
-  next_offset = tvb_find_guint8(tvb,offset,-1,':');
+  colon_offset = tvb_find_guint8(tvb,offset,-1,':');
 
-  if(next_offset == -1)
+  if(colon_offset == -1)
     return;
 
   /* Attribute field name is token before ':' */
-  tokenlen = next_offset - offset;
+  tokenlen = colon_offset - offset;
   proto_tree_add_item(sdp_media_attribute_tree,
                       hf_media_attribute_field,
                       tvb, offset, tokenlen, FALSE);
@@ -1389,7 +1524,9 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
   sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
 
   /* Skip colon */
-  offset = next_offset + 1;
+  offset = colon_offset + 1;
+  /* skip leading wsp */
+  offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
 
   /* Value is the remainder of the line */
   attribute_value = tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
@@ -1401,250 +1538,229 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
 
   switch (sdp_media_attrbute_code){
   case SDP_RTPMAP:
-        /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
-         next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+    /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
+    next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 
-         if(next_offset == -1)
-                 return;
+    if(next_offset == -1)
+      return;
 
-         tokenlen = next_offset - offset;
+    tokenlen = next_offset - offset;
 
-         proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
+    proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
                         offset, tokenlen, FALSE);
 
-         payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+    payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
 
-         offset = next_offset + 1;
+    offset = next_offset + 1;
 
-         next_offset = tvb_find_guint8(tvb,offset,-1,'/');
+    next_offset = tvb_find_guint8(tvb,offset,-1,'/');
 
-         if(next_offset == -1){
-                 return;
-         }
+    if(next_offset == -1){
+      return;
+    }
 
-         tokenlen = next_offset - offset;
+    tokenlen = next_offset - offset;
 
-         proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
+    start_offset = offset;
+    proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
                         offset, tokenlen, FALSE);
-         /* get_string is needed here as the string is "saved" in a hashtable */
-         transport_info->encoding_name = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
-
-         key=g_malloc( sizeof(gint) );
-         *key=atol((char*)payload_type);
-
-         /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
-            For example:
-
-            a=rtpmap:101 G726-32/8000
-            m=audio 49170 RTP/AVP 0 97
-            a=rtpmap:97 telephone-event/8000
-            m=audio 49172 RTP/AVP 97 101
-            a=rtpmap:97 G726-24/8000
-
-               The Media attributes ("a="s) after the "m=" only apply for that "m=".
-               If there is an "a=" before the first "m=", that attribute applies for
-               all the session (all the "m="s).
-         */
-
-         /* so, if this "a=" appear before any "m=", we add it to all the dynamic
-          * hash tables
-          */
-         if (transport_info->media_count == 0) {
-                 for (n=0; n < SDP_MAX_RTP_CHANNELS; n++) {
-                         if (n==0)
-                                 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
-                                    key, g_strdup(transport_info->encoding_name));
-                         else {    /* we create a new key and encoding_name to assign to the other hash tables */
-                                 gint *key2;
-                                 key2=g_malloc( sizeof(gint) );
-                                 *key2=atol((char*)payload_type);
-                                 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
-                                         key2, g_strdup(transport_info->encoding_name));
-                         }
-                 }
-                 return;
-                 /* if the "a=" is after an "m=", only apply to this "m=" */
-         }else
-                 /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
-                 if (transport_info->media_count == SDP_MAX_RTP_CHANNELS-1)
-                         g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
-                                       key, g_strdup(transport_info->encoding_name));
-                 else
-                         g_hash_table_insert(transport_info->media[ transport_info->media_count-1 ].rtp_dyn_payload,
-                                       key, g_strdup(transport_info->encoding_name));
-         return;
-         break;
-  case SDP_FMTP:
-         /* Reading the Format parameter(fmtp) */
-         next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 
-         if(next_offset == -1)
-                 return;
-
-         tokenlen = next_offset - offset;
-
-         /* Media format extends to the next space */
-         media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
-                                            hf_media_format, tvb, offset,
-                                            tokenlen, FALSE);
-         /* Append encoding name to format if known */
-         if (transport_info->encoding_name)
-                 proto_item_append_text(media_format_item, " [%s]",
-                             transport_info->encoding_name);
+    key=g_malloc( sizeof(gint) );
+    *key=atol((char*)payload_type);
+    pt = atoi((char*)payload_type);
+    if (pt >= SDP_NO_OF_PT) {
+      return;   /* Invalid */
+    }
+    transport_info->encoding_name[pt] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
 
-         payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+    next_offset =  next_offset + 1;
+    offset = next_offset;
+    while (length-1 >= next_offset){
+      if(!isdigit(tvb_get_guint8(tvb, next_offset)))
+        break;
+      next_offset++;
+    }
+    tokenlen = next_offset - offset;
+    proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
+                        offset, tokenlen, FALSE);
+    transport_info->sample_rate[pt] = atoi(tvb_get_ephemeral_string(tvb, offset, tokenlen));
+    /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
+       For example:
+
+       a=rtpmap:101 G726-32/8000
+       m=audio 49170 RTP/AVP 0 97
+       a=rtpmap:97 telephone-event/8000
+       m=audio 49172 RTP/AVP 97 101
+       a=rtpmap:97 G726-24/8000
+
+       The Media attributes ("a="s) after the "m=" only apply for that "m=".
+       If there is an "a=" before the first "m=", that attribute applies for
+       all the session (all the "m="s).
+    */
+
+    /* so, if this "a=" appear before any "m=", we add it to all the dynamic
+     * hash tables
+     */
+    if (transport_info->media_count == 0) {
+      for (n=0; n < SDP_MAX_RTP_CHANNELS; n++) {
+        encoding_name_and_rate = g_malloc( sizeof(encoding_name_and_rate_t));
+        encoding_name_and_rate->encoding_name = g_strdup(transport_info->encoding_name[pt]);
+        encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
+        if (n==0){
+          g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
+                              key, encoding_name_and_rate);
+        }
+        else {    /* we create a new key and encoding_name to assign to the other hash tables */
+          gint *key2;
+          key2=g_malloc( sizeof(gint) );
+          *key2=atol((char*)payload_type);
+          g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
+                              key2, encoding_name_and_rate);
+        }
+      }
+      return;
+      /* if the "a=" is after an "m=", only apply to this "m=" */
+    }else
+      /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
+      encoding_name_and_rate = g_malloc( sizeof(encoding_name_and_rate_t));
+
+    encoding_name_and_rate->encoding_name = g_strdup(transport_info->encoding_name[pt]);
+    encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
+    if (transport_info->media_count == SDP_MAX_RTP_CHANNELS-1)
+      g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
+                          key, encoding_name_and_rate);
+    else
+      g_hash_table_insert(transport_info->media[ transport_info->media_count-1 ].rtp_dyn_payload,
+                            key, encoding_name_and_rate);
+    break;
+  case SDP_FMTP:
+    if(sdp_media_attribute_tree){
+      guint8 media_format;
+      /* Reading the Format parameter(fmtp) */
+      /* Skip leading space, if any */
+      offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
+      /* Media format extends to the next space */
+      next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 
-         offset = next_offset + 1;
+      if(next_offset == -1)
+        return;
 
-         /* There may be 2 parameters given
-          * TODO: Handle arbitary number of parameters.
-          */
-         next_offset = tvb_find_guint8(tvb,offset,-1,';');
+      tokenlen = next_offset - offset;
 
-         if(next_offset != -1){
-                 /* There are 2 - add the first parameter */
-                 tokenlen = next_offset - offset;
-                 fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
-                                      hf_media_format_specific_parameter, tvb,
-                                      offset, tokenlen, FALSE);
 
-                 fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
+      media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
+                                              hf_media_format, tvb, offset,
+                                              tokenlen, FALSE);
+      media_format = atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen));
+      if (media_format >= SDP_NO_OF_PT) {
+        return;   /* Invalid */
+      }
 
-                 decode_sdp_fmtp(fmtp_tree, tvb, offset, tokenlen,
-                      (guint8 *)transport_info->encoding_name);
+      /* Append encoding name to format if known */
+      proto_item_append_text(media_format_item, " [%s]",
+                             transport_info->encoding_name[media_format]);
 
-                 offset = next_offset + 1;
-         }
+      payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
+      /* Move offset past the payload type */
+      offset = next_offset + 1;
 
-         /* Now add remaining (or only) parameter */
-         tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+      while(has_more_pars==TRUE){
+        next_offset = tvb_find_guint8(tvb,offset,-1,';');
+        offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
 
-         fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
-                                    hf_media_format_specific_parameter, tvb,
-                                    offset, tokenlen, FALSE);
+        if(next_offset == -1){
+          has_more_pars = FALSE;
+          next_offset= tvb_length(tvb);
+        }else{
 
-         fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
+        }
 
-         decode_sdp_fmtp(fmtp_tree, tvb, offset, tokenlen,
-                    (guint8 *)transport_info->encoding_name);
-         return;
-         break;
-  case SDP_PATH:
-         /* msrp attributes that contain address needed for conversation */
-         if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0){
-                 int address_offset, port_offset, port_end_offset;
+        /* There are at least 2 - add the first parameter */
+        tokenlen = next_offset - offset;
+        fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
+                                        hf_media_format_specific_parameter, tvb,
+                                        offset, tokenlen, FALSE);
 
-                 /* Address starts here */
-                 address_offset = offset + strlen(msrp_res);
+        fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
 
-                 /* Port is after next ':' */
-                 port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
+        decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
+                        transport_info->encoding_name[media_format]);
 
+        /* Move offset past "; " and onto firts char */
+        offset = next_offset + 1;
+      }
+    }
+    break;
+  case SDP_PATH:
+    /* msrp attributes that contain address needed for conversation */
+    /*    RFC 4975
+     *    path = path-label ":" path-list
+     *    path-label = "path"
+     *    path-list= MSRP-URI *(SP MSRP-URI)
+     *    MSRP-URI = msrp-scheme "://" authority
+     *       ["/" session-id] ";" transport *( ";" URI-parameter)
+     *                        ; authority as defined in RFC3986
+        *
+        *    msrp-scheme = "msrp" / "msrps"
+        * RFC 3986
+        * The authority component is preceded by a double slash ("//") and is terminated by 
+        * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by 
+        * the end of the URI. 
+        */
+
+    /* Check for "msrp://" */
+    if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0){
+      int address_offset, port_offset, port_end_offset;
+
+      /* Address starts here */
+      address_offset = offset + (int)strlen(msrp_res);
+
+      /* Port is after next ':' */
+      port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
+         /* Check if port is present if not skipp */
+         if(port_offset!= -1){
                  /* Port ends with '/' */
                  port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
 
                  /* Attempt to convert address */
                  if (inet_pton(AF_INET, (char*)tvb_get_ephemeral_string(tvb, address_offset, port_offset-address_offset), &msrp_ipaddr) > 0) {
-                         /* Get port number */
-                         msrp_port_number = atoi((char*)tvb_get_ephemeral_string(tvb, port_offset+1, port_end_offset-port_offset-1));
-                         /* Set flag so this info can be used */
-                         msrp_transport_address_set = TRUE;
+                       /* Get port number */
+                       msrp_port_number = atoi((char*)tvb_get_ephemeral_string(tvb, port_offset+1, port_end_offset-port_offset-1));
+                       /* Set flag so this info can be used */
+                       msrp_transport_address_set = TRUE;
                  }
          }
-         break;
+    }
+    break;
   case SDP_H248_ITEM:
-         /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
-         if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0){
-                 /* A.5.1.3 H.223 Logical channel parameters
-                  * This property indicates the H.245
-                  * H223LogicalChannelsParameters structure encoded by applying the PER specified in
-                  * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
-                  * in ITU-T Rec. H.248.15 is used.
-                  */
-                 guint8 *buf = ep_alloc(256);
-                 gint len;
-                 asn1_ctx_t actx;
-
-                 len = strlen(attribute_value);
-                 /* arbitrary maximum length */
-                 if(len<20480){
-                         int i;
-                         tvbuff_t *h245_tvb;
-
-                         /* first, skip to where the encoded pdu starts, this is
-                        the first hex digit after the '=' char.
-                         */
-                         while(1){
-                                 if((*attribute_value==0)||(*attribute_value=='\n')){
-                                         return;
-                                 }
-                                 if(*attribute_value=='='){
-                                         attribute_value++;
-                                         break;
-                                 }
-                                 attribute_value++;
-                         }
-                         while(1){
-                                 if((*attribute_value==0)||(*attribute_value=='\n')){
-                                         return;
-                                 }
-                                 if( ((*attribute_value>='0')&&(*attribute_value<='9'))
-                                 ||  ((*attribute_value>='a')&&(*attribute_value<='f'))
-                                 ||  ((*attribute_value>='A')&&(*attribute_value<='F'))){
-                                         break;
-                                 }
-                                 attribute_value++;
-                         }
-                         i=0;
-                         while( ((*attribute_value>='0')&&(*attribute_value<='9'))
-                         ||((*attribute_value>='a')&&(*attribute_value<='f'))
-                         ||((*attribute_value>='A')&&(*attribute_value<='F'))  ){
-                                 int val;
-                                 if((*attribute_value>='0')&&(*attribute_value<='9')){
-                                         val=(*attribute_value)-'0';
-                                 } else if((*attribute_value>='a')&&(*attribute_value<='f')){
-                                         val=(*attribute_value)-'a'+10;
-                                 } else if((*attribute_value>='A')&&(*attribute_value<='F')){
-                                         val=(*attribute_value)-'A'+10;
-                                 } else {
-                                         return;
-                                 }
-                                 val<<=4;
-                                 attribute_value++;
-                                 if((*attribute_value>='0')&&(*attribute_value<='9')){
-                                         val|=(*attribute_value)-'0';
-                                 } else if((*attribute_value>='a')&&(*attribute_value<='f')){
-                                         val|=(*attribute_value)-'a'+10;
-                                 } else if((*attribute_value>='A')&&(*attribute_value<='F')){
-                                         val|=(*attribute_value)-'A'+10;
-                                 } else {
-                                         return;
-                                 }
-                                 attribute_value++;
-
-                                 buf[i]=(guint8)val;
-                                 i++;
-                         }
-                         if(i==0){
-                                 return;
-                         }
-                         h245_tvb = tvb_new_real_data(buf,i,i);
-                         tvb_set_child_real_data_tvbuff(tvb,h245_tvb);
-                         add_new_data_source(pinfo, h245_tvb, "H.245 in SDP");
-                         /* should go through a handle, however,  the two h245 entry
-                         points are different, one is over tpkt and the other is raw
-                         */
-                         asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
-                         dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, sdp_media_attribute_tree, hf_SDPh223LogicalChannelParameters);
-                 }
-
-               }
-         break;
+    /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
+    if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0){
+      /* A.5.1.3 H.223 Logical channel parameters
+       * This property indicates the H.245
+       * H223LogicalChannelsParameters structure encoded by applying the PER specified in
+       * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
+       * in ITU-T Rec. H.248.15 is used.
+       */
+      gint len;
+      asn1_ctx_t actx;
+
+      len = (gint)strlen(attribute_value);
+      h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
+      /* arbitrary maximum length */
+      /* should go through a handle, however,  the two h245 entry
+         points are different, one is over tpkt and the other is raw
+      */
+      if (h245_tvb){
+        asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
+        dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, sdp_media_attribute_tree, hf_SDPh223LogicalChannelParameters);
+      }
+    }
+    break;
   default:
-         /* No special treatment for values of this attribute type, just add as one item. */
-         proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
-                      tvb, offset, -1, FALSE);
-         break;
+    /* No special treatment for values of this attribute type, just add as one item. */
+    proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
+                        tvb, offset, -1, FALSE);
+    break;
   }
 }
 
@@ -1655,23 +1771,23 @@ proto_register_sdp(void)
     { &hf_protocol_version,
       { "Session Description Protocol Version (v)",
         "sdp.version", FT_STRING, BASE_NONE,NULL,0x0,
-        "Session Description Protocol Version", HFILL }},
+        NULL, HFILL }},
     { &hf_owner,
       { "Owner/Creator, Session Id (o)",
         "sdp.owner", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Owner/Creator, Session Id", HFILL}},
+        NULL, HFILL}},
     { &hf_session_name,
       { "Session Name (s)",
         "sdp.session_name", FT_STRING, BASE_NONE,NULL, 0x0,
-        "Session Name", HFILL }},
+        NULL, HFILL }},
     { &hf_session_info,
       { "Session Information (i)",
         "sdp.session_info", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Information", HFILL }},
+        NULL, HFILL }},
     { &hf_uri,
       { "URI of Description (u)",
         "sdp.uri", FT_STRING, BASE_NONE,NULL, 0x0,
-        "URI of Description", HFILL }},
+        NULL, HFILL }},
     { &hf_email,
       { "E-mail Address (e)",
         "sdp.email", FT_STRING, BASE_NONE, NULL, 0x0,
@@ -1679,43 +1795,43 @@ proto_register_sdp(void)
     { &hf_phone,
       { "Phone Number (p)",
         "sdp.phone", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Phone Number", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info,
       { "Connection Information (c)",
         "sdp.connection_info", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection Information", HFILL }},
+        NULL, HFILL }},
     { &hf_bandwidth,
       { "Bandwidth Information (b)",
         "sdp.bandwidth", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Bandwidth Information", HFILL }},
+        NULL, HFILL }},
     { &hf_timezone,
       { "Time Zone Adjustments (z)",
         "sdp.timezone", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Time Zone Adjustments", HFILL }},
+        NULL, HFILL }},
     { &hf_encryption_key,
       { "Encryption Key (k)",
         "sdp.encryption_key", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Encryption Key", HFILL }},
+        NULL, HFILL }},
     { &hf_session_attribute,
       { "Session Attribute (a)",
         "sdp.session_attr", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Attribute", HFILL }},
+        NULL, HFILL }},
     { &hf_media_attribute,
       { "Media Attribute (a)",
         "sdp.media_attr", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Attribute", HFILL }},
+        NULL, HFILL }},
     { &hf_time,
       { "Time Description, active time (t)",
         "sdp.time", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Time Description, active time", HFILL }},
+        NULL, HFILL }},
     { &hf_repeat_time,
       { "Repeat Time (r)",
         "sdp.repeat_time", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Repeat Time", HFILL }},
+        NULL, HFILL }},
     { &hf_media,
       { "Media Description, name and address (m)",
         "sdp.media", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Description, name and address", HFILL }},
+        NULL, HFILL }},
     { &hf_media_title,
       { "Media Title (i)",
         "sdp.media_title",FT_STRING, BASE_NONE, NULL, 0x0,
@@ -1723,59 +1839,59 @@ proto_register_sdp(void)
     { &hf_unknown,
       { "Unknown",
         "sdp.unknown",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Unknown", HFILL }},
+        NULL, HFILL }},
     { &hf_invalid,
       { "Invalid line",
         "sdp.invalid",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Invalid line", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_username,
       { "Owner Username",
         "sdp.owner.username",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Owner Username", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_sessionid,
       { "Session ID",
         "sdp.owner.sessionid",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session ID", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_version,
       { "Session Version",
         "sdp.owner.version",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Version", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_network_type,
       { "Owner Network Type",
         "sdp.owner.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Owner Network Type", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_address_type,
       { "Owner Address Type",
         "sdp.owner.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Owner Address Type", HFILL }},
+        NULL, HFILL }},
     { &hf_owner_address,
       { "Owner Address",
         "sdp.owner.address",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Owner Address", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info_network_type,
       { "Connection Network Type",
         "sdp.connection_info.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection Network Type", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info_address_type,
       { "Connection Address Type",
         "sdp.connection_info.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection Address Type", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info_connection_address,
       { "Connection Address",
         "sdp.connection_info.address",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection Address", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info_ttl,
       { "Connection TTL",
         "sdp.connection_info.ttl",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection TTL", HFILL }},
+        NULL, HFILL }},
     { &hf_connection_info_num_addr,
       { "Connection Number of Addresses",
         "sdp.connection_info.num_addr",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Connection Number of Addresses", HFILL }},
+        NULL, HFILL }},
     { &hf_bandwidth_modifier,
       { "Bandwidth Modifier",
         "sdp.bandwidth.modifier",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Bandwidth Modifier", HFILL }},
+        NULL, HFILL }},
     { &hf_bandwidth_value,
       { "Bandwidth Value",
         "sdp.bandwidth.value",FT_STRING, BASE_NONE, NULL, 0x0,
@@ -1783,115 +1899,131 @@ proto_register_sdp(void)
     { &hf_time_start,
       { "Session Start Time",
         "sdp.time.start",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Start Time", HFILL }},
+        NULL, HFILL }},
     { &hf_time_stop,
       { "Session Stop Time",
         "sdp.time.stop",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Stop Time", HFILL }},
+        NULL, HFILL }},
     { &hf_repeat_time_interval,
       { "Repeat Interval",
         "sdp.repeat_time.interval",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Repeat Interval", HFILL }},
+        NULL, HFILL }},
     { &hf_repeat_time_duration,
       { "Repeat Duration",
         "sdp.repeat_time.duration",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Repeat Duration", HFILL }},
+        NULL, HFILL }},
     { &hf_repeat_time_offset,
       { "Repeat Offset",
         "sdp.repeat_time.offset",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Repeat Offset", HFILL }},
+        NULL, HFILL }},
     { &hf_timezone_time,
       { "Timezone Time",
         "sdp.timezone.time",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Timezone Time", HFILL }},
+        NULL, HFILL }},
     { &hf_timezone_offset,
       { "Timezone Offset",
         "sdp.timezone.offset",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Timezone Offset", HFILL }},
+        NULL, HFILL }},
     { &hf_encryption_key_type,
       { "Key Type",
         "sdp.encryption_key.type",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Type", HFILL }},
+        NULL, HFILL }},
     { &hf_encryption_key_data,
       { "Key Data",
         "sdp.encryption_key.data",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Data", HFILL }},
+        NULL, HFILL }},
     { &hf_session_attribute_field,
       { "Session Attribute Fieldname",
         "sdp.session_attr.field",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Attribute Fieldname", HFILL }},
+        NULL, HFILL }},
     { &hf_session_attribute_value,
       { "Session Attribute Value",
         "sdp.session_attr.value",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Session Attribute Value", HFILL }},
+        NULL, HFILL }},
     { &hf_media_media,
       { "Media Type",
         "sdp.media.media",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Type", HFILL }},
+        NULL, HFILL }},
     { &hf_media_port,
       { "Media Port",
         "sdp.media.port",FT_UINT16, BASE_DEC, NULL, 0x0,
-        "Media Port", HFILL }},
+        NULL, HFILL }},
     { &hf_media_portcount,
       { "Media Port Count",
         "sdp.media.portcount",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Port Count", HFILL }},
+        NULL, HFILL }},
     { &hf_media_proto,
-      { "Media Proto",
+      { "Media Protocol",
         "sdp.media.proto",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Protocol", HFILL }},
+        NULL, HFILL }},
     { &hf_media_format,
       { "Media Format",
         "sdp.media.format",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Format", HFILL }},
+        NULL, HFILL }},
     { &hf_media_attribute_field,
       { "Media Attribute Fieldname",
         "sdp.media_attribute.field",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Attribute Fieldname", HFILL }},
+        NULL, HFILL }},
     { &hf_media_attribute_value,
       { "Media Attribute Value",
         "sdp.media_attribute.value",FT_STRING, BASE_NONE, NULL, 0x0,
-        "Media Attribute Value", HFILL }},
-        { &hf_media_encoding_name,
+        NULL, HFILL }},
+    { &hf_media_encoding_name,
       { "MIME Type",
         "sdp.mime.type",FT_STRING, BASE_NONE, NULL, 0x0,
         "SDP MIME Type", HFILL }},
-        { &hf_media_format_specific_parameter,
+    { &hf_media_sample_rate,
+      { "Sample Rate",
+        "sdp.sample_rate",FT_STRING, BASE_NONE, NULL, 0x0,
+        NULL, HFILL }},
+    { &hf_media_format_specific_parameter,
       { "Media format specific parameters",
         "sdp.fmtp.parameter",FT_STRING, BASE_NONE, NULL, 0x0,
         "Format specific parameter(fmtp)", HFILL }},
     { &hf_ipbcp_version,
       { "IPBCP Protocol Version",
         "ipbcp.version",FT_STRING, BASE_NONE, NULL, 0x0,
-        "IPBCP Protocol Version", HFILL }},
+        NULL, HFILL }},
     { &hf_ipbcp_type,
       { "IPBCP Command Type",
         "ipbcp.command",FT_STRING, BASE_NONE, NULL, 0x0,
-        "IPBCP Command Type", HFILL }},
-       {&hf_sdp_fmtp_profile_level_id,
+        NULL, HFILL }},
+    {&hf_sdp_fmtp_mpeg4_profile_level_id,
       { "Level Code",
-        "sdp.fmtp.profile_level_id",FT_UINT32, BASE_DEC,VALS(mpeg4es_level_indication_vals), 0x0,
-        "Level Code", HFILL }},
-       { &hf_sdp_fmtp_h263_profile,
+        "sdp.fmtp.profile_level_id",FT_UINT32, BASE_DEC,VALS(mp4ves_level_indication_vals), 0x0,
+        NULL, HFILL }},
+    { &hf_sdp_fmtp_h263_profile,
       { "Profile",
         "sdp.fmtp.h263profile",FT_UINT32, BASE_DEC,VALS(h263_profile_vals), 0x0,
-        "Profile", HFILL }},
+        NULL, HFILL }},
+    { &hf_sdp_fmtp_h263_level,
+      { "Level",
+        "sdp.fmtp.h263level",FT_UINT32, BASE_DEC,VALS(h263_level_vals), 0x0,
+        NULL, HFILL }},
+    { &hf_sdp_h264_packetization_mode,
+      { "Packetization mode",
+        "sdp.fmtp.h264_packetization_mode",FT_UINT32, BASE_DEC,VALS(h264_packetization_mode_vals), 0x0,
+        NULL, HFILL }},
+    { &hf_sdp_h264_sprop_parameter_sets,
+      { "Sprop_parameter_sets",
+        "sdp.h264.sprop_parameter_sets", FT_BYTES, BASE_NONE, NULL, 0x0,
+        NULL, HFILL }},
     { &hf_SDPh223LogicalChannelParameters,
       { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
         FT_NONE, BASE_NONE, NULL, 0,
-        "sdp.h223LogicalChannelParameters", HFILL }},
+        NULL, HFILL }},
     { &hf_key_mgmt_att_value,
       { "Key Management",
         "sdp.key_mgmt", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Key Management", HFILL }},
+        NULL, HFILL }},
     { &hf_key_mgmt_prtcl_id,
       { "Key Management Protocol (kmpid)",
         "sdp.key_mgmt.kmpid", FT_STRING, BASE_NONE, NULL, 0x0,
-        "Key Management Protocol", HFILL }},
+        NULL, HFILL }},
     { &hf_key_mgmt_data,
       { "Key Management Data",
         "sdp.key_mgmt.data", FT_BYTES, BASE_NONE, NULL, 0x0,
-        "Key Management Data", HFILL }},
+        NULL, HFILL }},
   };
   static gint *ett[] = {
     &ett_sdp,
@@ -1917,7 +2049,7 @@ proto_register_sdp(void)
   proto_register_subtree_array(ett, array_length(ett));
 
   key_mgmt_dissector_table = register_dissector_table("key_mgmt",
-           "Key Management", FT_STRING, BASE_NONE);
+                                                      "Key Management", FT_STRING, BASE_NONE);
 
   /*
    * Preferences registration
@@ -1926,7 +2058,7 @@ proto_register_sdp(void)
    prefs_register_bool_preference(sdp_module, "establish_conversation",
        "Establish Media Conversation",
        "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
-       "upon port numbers found in SIP/SDP payload",
+       "upon port numbers found in SDP payload",
        &global_sdp_establish_conversation);
 
   /*
@@ -1948,6 +2080,8 @@ proto_reg_handoff_sdp(void)
   rtcp_handle = find_dissector("rtcp");
   msrp_handle = find_dissector("msrp");
   t38_handle = find_dissector("t38");
+  h264_handle = find_dissector("h264");
+  mp4ves_handle = find_dissector("mp4ves");
 
   sdp_handle = find_dissector("sdp");
   dissector_add_string("media_type", "application/sdp", sdp_handle);