sdp: replace duplicated codes to call new base sdp apis
authorHyunjun Ko <zzoon.ko@samsung.com>
Wed, 7 Oct 2015 09:53:01 +0000 (18:53 +0900)
committerSebastian Dröge <sebastian@centricular.com>
Thu, 31 Dec 2015 15:13:39 +0000 (17:13 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=745880

gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-sdp.c

index ae590bb..4013813 100644 (file)
@@ -3206,490 +3206,6 @@ no_setup_sdp:
   }
 }
 
-static const gchar *
-rtsp_get_attribute_for_pt (const GstSDPMedia * media, const gchar * name,
-    gint pt)
-{
-  guint i;
-
-  for (i = 0;; i++) {
-    const gchar *attr;
-    gint val;
-
-    if ((attr = gst_sdp_media_get_attribute_val_n (media, name, i)) == NULL)
-      break;
-
-    if (sscanf (attr, "%d ", &val) != 1)
-      continue;
-
-    if (val == pt)
-      return attr;
-  }
-  return NULL;
-}
-
-#define PARSE_INT(p, del, res)          \
-G_STMT_START {                          \
-  gchar *t = p;                         \
-  p = strstr (p, del);                  \
-  if (p == NULL)                        \
-    res = -1;                           \
-  else {                                \
-    *p = '\0';                          \
-    p++;                                \
-    res = atoi (t);                     \
-  }                                     \
-} G_STMT_END
-
-#define PARSE_STRING(p, del, res)       \
-G_STMT_START {                          \
-  gchar *t = p;                         \
-  p = strstr (p, del);                  \
-  if (p == NULL) {                      \
-    res = NULL;                         \
-    p = t;                              \
-  }                                     \
-  else {                                \
-    *p = '\0';                          \
-    p++;                                \
-    res = t;                            \
-  }                                     \
-} G_STMT_END
-
-#define SKIP_SPACES(p)                  \
-  while (*p && g_ascii_isspace (*p))    \
-    p++;
-
-/* rtpmap contains:
- *
- *  <payload> <encoding_name>/<clock_rate>[/<encoding_params>]
- */
-static gboolean
-parse_rtpmap (const gchar * rtpmap, gint * payload, gchar ** name,
-    gint * rate, gchar ** params)
-{
-  gchar *p, *t;
-
-  p = (gchar *) rtpmap;
-
-  PARSE_INT (p, " ", *payload);
-  if (*payload == -1)
-    return FALSE;
-
-  SKIP_SPACES (p);
-  if (*p == '\0')
-    return FALSE;
-
-  PARSE_STRING (p, "/", *name);
-  if (*name == NULL) {
-    GST_DEBUG ("no rate, name %s", p);
-    /* no rate, assume -1 then, this is not supposed to happen but RealMedia
-     * streams seem to omit the rate. */
-    *name = p;
-    *rate = -1;
-    return TRUE;
-  }
-
-  t = p;
-  p = strstr (p, "/");
-  if (p == NULL) {
-    *rate = atoi (t);
-    return TRUE;
-  }
-  *p = '\0';
-  p++;
-  *rate = atoi (t);
-
-  t = p;
-  if (*p == '\0')
-    return TRUE;
-  *params = t;
-
-  return TRUE;
-}
-
-/*
- *  Mapping of caps to and from SDP fields:
- *
- *   a=rtpmap:<payload> <encoding_name>/<clock_rate>[/<encoding_params>]
- *   a=framesize:<payload> <width>-<height>
- *   a=fmtp:<payload> <param>[=<value>];...
- */
-static GstCaps *
-media_to_caps (gint pt, const GstSDPMedia * media)
-{
-  GstCaps *caps;
-  const gchar *rtpmap;
-  const gchar *fmtp;
-  const gchar *framesize;
-  gchar *name = NULL;
-  gint rate = -1;
-  gchar *params = NULL;
-  gchar *tmp;
-  GstStructure *s;
-  gint payload = 0;
-  gboolean ret;
-
-  /* get and parse rtpmap */
-  rtpmap = rtsp_get_attribute_for_pt (media, "rtpmap", pt);
-
-  if (rtpmap) {
-    ret = parse_rtpmap (rtpmap, &payload, &name, &rate, &params);
-    if (!ret) {
-      g_warning ("error parsing rtpmap, ignoring");
-      rtpmap = NULL;
-    }
-  }
-  /* dynamic payloads need rtpmap or we fail */
-  if (rtpmap == NULL && pt >= 96)
-    goto no_rtpmap;
-
-  /* check if we have a rate, if not, we need to look up the rate from the
-   * default rates based on the payload types. */
-  if (rate == -1) {
-    const GstRTPPayloadInfo *info;
-
-    if (GST_RTP_PAYLOAD_IS_DYNAMIC (pt)) {
-      /* dynamic types, use media and encoding_name */
-      tmp = g_ascii_strdown (media->media, -1);
-      info = gst_rtp_payload_info_for_name (tmp, name);
-      g_free (tmp);
-    } else {
-      /* static types, use payload type */
-      info = gst_rtp_payload_info_for_pt (pt);
-    }
-
-    if (info) {
-      if ((rate = info->clock_rate) == 0)
-        rate = -1;
-    }
-    /* we fail if we cannot find one */
-    if (rate == -1)
-      goto no_rate;
-  }
-
-  tmp = g_ascii_strdown (media->media, -1);
-  caps = gst_caps_new_simple ("application/x-unknown",
-      "media", G_TYPE_STRING, tmp, "payload", G_TYPE_INT, pt, NULL);
-  g_free (tmp);
-  s = gst_caps_get_structure (caps, 0);
-
-  gst_structure_set (s, "clock-rate", G_TYPE_INT, rate, NULL);
-
-  /* encoding name must be upper case */
-  if (name != NULL) {
-    tmp = g_ascii_strup (name, -1);
-    gst_structure_set (s, "encoding-name", G_TYPE_STRING, tmp, NULL);
-    g_free (tmp);
-  }
-
-  /* params must be lower case */
-  if (params != NULL) {
-    tmp = g_ascii_strdown (params, -1);
-    gst_structure_set (s, "encoding-params", G_TYPE_STRING, tmp, NULL);
-    g_free (tmp);
-  }
-
-  /* parse optional fmtp: field */
-  if ((fmtp = rtsp_get_attribute_for_pt (media, "fmtp", pt))) {
-    gchar *p;
-    gint payload = 0;
-
-    p = (gchar *) fmtp;
-
-    /* p is now of the format <payload> <param>[=<value>];... */
-    PARSE_INT (p, " ", payload);
-    if (payload != -1 && payload == pt) {
-      gchar **pairs;
-      gint i;
-
-      /* <param>[=<value>] are separated with ';' */
-      pairs = g_strsplit (p, ";", 0);
-      for (i = 0; pairs[i]; i++) {
-        gchar *valpos;
-        const gchar *val, *key;
-        gint j;
-        const gchar *reserved_keys[] =
-            { "media", "payload", "clock-rate", "encoding-name",
-          "encoding-params"
-        };
-
-        /* the key may not have a '=', the value can have other '='s */
-        valpos = strstr (pairs[i], "=");
-        if (valpos) {
-          /* we have a '=' and thus a value, remove the '=' with \0 */
-          *valpos = '\0';
-          /* value is everything between '=' and ';'. We split the pairs at ;
-           * boundaries so we can take the remainder of the value. Some servers
-           * put spaces around the value which we strip off here. Alternatively
-           * we could strip those spaces in the depayloaders should these spaces
-           * actually carry any meaning in the future. */
-          val = g_strstrip (valpos + 1);
-        } else {
-          /* simple <param>;.. is translated into <param>=1;... */
-          val = "1";
-        }
-        /* strip the key of spaces, convert key to lowercase but not the value. */
-        key = g_strstrip (pairs[i]);
-
-        /* skip keys from the fmtp, which we already use ourselves for the
-         * caps. Some software is adding random things like clock-rate into
-         * the fmtp, and we would otherwise here set a string-typed clock-rate
-         * in the caps... and thus fail to create valid RTP caps
-         */
-        for (j = 0; j < G_N_ELEMENTS (reserved_keys); j++) {
-          if (g_ascii_strcasecmp (reserved_keys[j], key) == 0) {
-            key = "";
-            break;
-          }
-        }
-
-        if (strlen (key) > 1) {
-          tmp = g_ascii_strdown (key, -1);
-          gst_structure_set (s, tmp, G_TYPE_STRING, val, NULL);
-          g_free (tmp);
-        }
-      }
-      g_strfreev (pairs);
-    }
-  }
-
-  /* parse framesize: field */
-  if ((framesize = gst_sdp_media_get_attribute_val (media, "framesize"))) {
-    gchar *p;
-
-    /* p is now of the format <payload> <width>-<height> */
-    p = (gchar *) framesize;
-
-    PARSE_INT (p, " ", payload);
-    if (payload != -1 && payload == pt) {
-      gst_structure_set (s, "a-framesize", G_TYPE_STRING, p, NULL);
-    }
-  }
-  return caps;
-
-  /* ERRORS */
-no_rtpmap:
-  {
-    g_warning ("rtpmap type not given for dynamic payload %d", pt);
-    return NULL;
-  }
-no_rate:
-  {
-    g_warning ("rate unknown for payload type %d", pt);
-    return NULL;
-  }
-}
-
-static gboolean
-parse_keymgmt (const gchar * keymgmt, GstCaps * caps)
-{
-  gboolean res = FALSE;
-  gsize size;
-  guchar *data;
-  GstMIKEYMessage *msg;
-  const GstMIKEYPayload *payload;
-  const gchar *srtp_cipher;
-  const gchar *srtp_auth;
-
-  {
-    gchar *orig_value;
-    gchar *p, *kmpid;
-
-    p = orig_value = g_strdup (keymgmt);
-
-    SKIP_SPACES (p);
-    if (*p == '\0') {
-      g_free (orig_value);
-      return FALSE;
-    }
-
-    PARSE_STRING (p, " ", kmpid);
-    if (kmpid == NULL || !g_str_equal (kmpid, "mikey")) {
-      g_free (orig_value);
-      return FALSE;
-    }
-    data = g_base64_decode (p, &size);
-
-    g_free (orig_value);        /* Don't need this any more */
-  }
-
-  if (data == NULL)
-    return FALSE;
-
-  msg = gst_mikey_message_new_from_data (data, size, NULL, NULL);
-  g_free (data);
-  if (msg == NULL)
-    return FALSE;
-
-  srtp_cipher = "aes-128-icm";
-  srtp_auth = "hmac-sha1-80";
-
-  /* check the Security policy if any */
-  if ((payload = gst_mikey_message_find_payload (msg, GST_MIKEY_PT_SP, 0))) {
-    GstMIKEYPayloadSP *p = (GstMIKEYPayloadSP *) payload;
-    guint len, i;
-
-    if (p->proto != GST_MIKEY_SEC_PROTO_SRTP)
-      goto done;
-
-    len = gst_mikey_payload_sp_get_n_params (payload);
-    for (i = 0; i < len; i++) {
-      const GstMIKEYPayloadSPParam *param =
-          gst_mikey_payload_sp_get_param (payload, i);
-
-      switch (param->type) {
-        case GST_MIKEY_SP_SRTP_ENC_ALG:
-          switch (param->val[0]) {
-            case 0:
-              srtp_cipher = "null";
-              break;
-            case 2:
-            case 1:
-              srtp_cipher = "aes-128-icm";
-              break;
-            default:
-              break;
-          }
-          break;
-        case GST_MIKEY_SP_SRTP_ENC_KEY_LEN:
-          switch (param->val[0]) {
-            case AES_128_KEY_LEN:
-              srtp_cipher = "aes-128-icm";
-              break;
-            case AES_256_KEY_LEN:
-              srtp_cipher = "aes-256-icm";
-              break;
-            default:
-              break;
-          }
-          break;
-        case GST_MIKEY_SP_SRTP_AUTH_ALG:
-          switch (param->val[0]) {
-            case 0:
-              srtp_auth = "null";
-              break;
-            case 2:
-            case 1:
-              srtp_auth = "hmac-sha1-80";
-              break;
-            default:
-              break;
-          }
-          break;
-        case GST_MIKEY_SP_SRTP_AUTH_KEY_LEN:
-          switch (param->val[0]) {
-            case HMAC_32_KEY_LEN:
-              srtp_auth = "hmac-sha1-32";
-              break;
-            case HMAC_80_KEY_LEN:
-              srtp_auth = "hmac-sha1-80";
-              break;
-            default:
-              break;
-          }
-          break;
-        case GST_MIKEY_SP_SRTP_SRTP_ENC:
-          break;
-        case GST_MIKEY_SP_SRTP_SRTCP_ENC:
-          break;
-        default:
-          break;
-      }
-    }
-  }
-
-  if (!(payload = gst_mikey_message_find_payload (msg, GST_MIKEY_PT_KEMAC, 0)))
-    goto done;
-  else {
-    GstMIKEYPayloadKEMAC *p = (GstMIKEYPayloadKEMAC *) payload;
-    const GstMIKEYPayload *sub;
-    GstMIKEYPayloadKeyData *pkd;
-    GstBuffer *buf;
-
-    if (p->enc_alg != GST_MIKEY_ENC_NULL || p->mac_alg != GST_MIKEY_MAC_NULL)
-      goto done;
-
-    if (!(sub = gst_mikey_payload_kemac_get_sub (payload, 0)))
-      goto done;
-
-    if (sub->type != GST_MIKEY_PT_KEY_DATA)
-      goto done;
-
-    pkd = (GstMIKEYPayloadKeyData *) sub;
-    buf =
-        gst_buffer_new_wrapped (g_memdup (pkd->key_data, pkd->key_len),
-        pkd->key_len);
-    gst_caps_set_simple (caps, "srtp-key", GST_TYPE_BUFFER, buf, NULL);
-  }
-
-  gst_caps_set_simple (caps,
-      "srtp-cipher", G_TYPE_STRING, srtp_cipher,
-      "srtp-auth", G_TYPE_STRING, srtp_auth,
-      "srtcp-cipher", G_TYPE_STRING, srtp_cipher,
-      "srtcp-auth", G_TYPE_STRING, srtp_auth, NULL);
-
-  res = TRUE;
-done:
-  gst_mikey_message_unref (msg);
-
-  return res;
-}
-
-/*
- * Mapping SDP attributes to caps
- *
- * prepend 'a-' to IANA registered sdp attributes names
- * (ie: not prefixed with 'x-') in order to avoid
- * collision with gstreamer standard caps properties names
- */
-static void
-sdp_attributes_to_caps (GArray * attributes, GstCaps * caps)
-{
-  if (attributes->len > 0) {
-    GstStructure *s;
-    guint i;
-
-    s = gst_caps_get_structure (caps, 0);
-
-    for (i = 0; i < attributes->len; i++) {
-      GstSDPAttribute *attr = &g_array_index (attributes, GstSDPAttribute, i);
-      gchar *tofree, *key;
-
-      key = attr->key;
-
-      /* skip some of the attribute we already handle */
-      if (!strcmp (key, "fmtp"))
-        continue;
-      if (!strcmp (key, "rtpmap"))
-        continue;
-      if (!strcmp (key, "control"))
-        continue;
-      if (!strcmp (key, "range"))
-        continue;
-      if (!strcmp (key, "framesize"))
-        continue;
-      if (g_str_equal (key, "key-mgmt")) {
-        parse_keymgmt (attr->value, caps);
-        continue;
-      }
-
-      /* string must be valid UTF8 */
-      if (!g_utf8_validate (attr->value, -1, NULL))
-        continue;
-
-      if (!g_str_has_prefix (key, "x-"))
-        tofree = key = g_strdup_printf ("a-%s", key);
-      else
-        tofree = NULL;
-
-      GST_DEBUG ("adding caps: %s=%s", key, attr->value);
-      gst_structure_set (s, key, G_TYPE_STRING, attr->value, NULL);
-      g_free (tofree);
-    }
-  }
-}
-
 static gboolean
 default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
 {
@@ -3756,7 +3272,7 @@ default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
       GST_DEBUG (" looking at %d pt: %d", j, pt);
 
       /* convert caps */
-      caps = media_to_caps (pt, sdp_media);
+      caps = gst_sdp_media_get_caps_from_media (sdp_media, pt);
       if (caps == NULL) {
         GST_WARNING (" skipping pt %d without caps", pt);
         continue;
@@ -3764,9 +3280,9 @@ default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp)
 
       /* do some tweaks */
       GST_DEBUG ("mapping sdp session level attributes to caps");
-      sdp_attributes_to_caps (sdp->attributes, caps);
+      gst_sdp_message_attributes_to_caps (sdp, caps);
       GST_DEBUG ("mapping sdp media level attributes to caps");
-      sdp_attributes_to_caps (sdp_media->attributes, caps);
+      gst_sdp_media_attributes_to_caps (sdp_media, caps);
 
       s = gst_caps_get_structure (caps, 0);
       gst_structure_set_name (s, media_type);
index 393b099..74ea340 100644 (file)
 
 #include "rtsp-sdp.h"
 
-#define AES_128_KEY_LEN 16
-#define AES_256_KEY_LEN 32
-
-#define HMAC_32_KEY_LEN 4
-#define HMAC_80_KEY_LEN 10
-
 static gboolean
 get_info_from_tags (GstPad * pad, GstEvent ** event, gpointer user_data)
 {
@@ -78,60 +72,27 @@ update_sdp_from_tags (GstRTSPStream * stream, GstSDPMedia * stream_media)
   gst_object_unref (src_pad);
 }
 
-static guint8
-enc_key_length_from_cipher_name (const gchar * cipher)
-{
-  if (g_strcmp0 (cipher, "aes-128-icm") == 0)
-    return AES_128_KEY_LEN;
-  else if (g_strcmp0 (cipher, "aes-256-icm") == 0)
-    return AES_256_KEY_LEN;
-  else {
-    GST_ERROR ("encryption algorithm '%s' not supported", cipher);
-    return 0;
-  }
-}
-
-static guint8
-auth_key_length_from_auth_name (const gchar * auth)
-{
-  if (g_strcmp0 (auth, "hmac-sha1-32") == 0)
-    return HMAC_32_KEY_LEN;
-  else if (g_strcmp0 (auth, "hmac-sha1-80") == 0)
-    return HMAC_80_KEY_LEN;
-  else {
-    GST_ERROR ("authentication algorithm '%s' not supported", auth);
-    return 0;
-  }
-}
-
 static void
 make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
-    GstRTSPStream * stream, GstStructure * s, GstRTSPProfile profile)
+    GstRTSPStream * stream, GstCaps * caps, GstRTSPProfile profile)
 {
   GstSDPMedia *smedia;
-  const gchar *caps_str, *caps_enc, *caps_params;
   gchar *tmp;
-  gint caps_pt, caps_rate;
-  guint n_fields, j;
-  gboolean first;
-  GString *fmtp;
   GstRTSPLowerTrans ltrans;
   GSocketFamily family;
   const gchar *addrtype, *proto;
   gchar *address;
   guint ttl;
   GstClockTime rtx_time;
+  gchar *base64;
+  guint32 ssrc;
+  GstMIKEYMessage *mikey_msg;
 
   gst_sdp_media_new (&smedia);
 
-  /* get media type and payload for the m= line */
-  caps_str = gst_structure_get_string (s, "media");
-  gst_sdp_media_set_media (smedia, caps_str);
-
-  gst_structure_get_int (s, "payload", &caps_pt);
-  tmp = g_strdup_printf ("%d", caps_pt);
-  gst_sdp_media_add_format (smedia, tmp);
-  g_free (tmp);
+  if (gst_sdp_media_set_media_from_caps (caps, smedia) != GST_SDP_OK) {
+    goto error;
+  }
 
   gst_sdp_media_set_port_info (smedia, 0, 1);
 
@@ -185,201 +146,27 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
   gst_sdp_media_add_connection (smedia, "IN", addrtype, address, ttl, 1);
   g_free (address);
 
-  /* get clock-rate, media type and params for the rtpmap attribute */
-  gst_structure_get_int (s, "clock-rate", &caps_rate);
-  caps_enc = gst_structure_get_string (s, "encoding-name");
-  caps_params = gst_structure_get_string (s, "encoding-params");
-
-  if (caps_enc) {
-    if (caps_params)
-      tmp = g_strdup_printf ("%d %s/%d/%s", caps_pt, caps_enc, caps_rate,
-          caps_params);
-    else
-      tmp = g_strdup_printf ("%d %s/%d", caps_pt, caps_enc, caps_rate);
-
-    gst_sdp_media_add_attribute (smedia, "rtpmap", tmp);
-    g_free (tmp);
-  }
-
   /* the config uri */
   tmp = gst_rtsp_stream_get_control (stream);
   gst_sdp_media_add_attribute (smedia, "control", tmp);
   g_free (tmp);
 
-
   /* check for srtp */
-  do {
-    GstBuffer *srtpkey;
-    const GValue *val;
-    const gchar *srtpcipher, *srtpauth, *srtcpcipher, *srtcpauth;
-    GstMIKEYMessage *msg;
-    GstMIKEYPayload *payload, *pkd;
-    GBytes *bytes;
-    GstMapInfo info;
-    const guint8 *data;
-    gsize size;
-    gchar *base64;
-    guint8 byte;
-    guint32 ssrc;
-
-    val = gst_structure_get_value (s, "srtp-key");
-    if (val == NULL)
-      break;
-
-    srtpkey = gst_value_get_buffer (val);
-    if (srtpkey == NULL)
-      break;
-
-    srtpcipher = gst_structure_get_string (s, "srtp-cipher");
-    srtpauth = gst_structure_get_string (s, "srtp-auth");
-    srtcpcipher = gst_structure_get_string (s, "srtcp-cipher");
-    srtcpauth = gst_structure_get_string (s, "srtcp-auth");
-
-    if (srtpcipher == NULL || srtpauth == NULL || srtcpcipher == NULL ||
-        srtcpauth == NULL)
-      break;
-
-    msg = gst_mikey_message_new ();
-    /* unencrypted MIKEY message, we send this over TLS so this is allowed */
-    gst_mikey_message_set_info (msg, GST_MIKEY_VERSION, GST_MIKEY_TYPE_PSK_INIT,
-        FALSE, GST_MIKEY_PRF_MIKEY_1, 0, GST_MIKEY_MAP_TYPE_SRTP);
-    /* add policy '0' for our SSRC */
+  mikey_msg = gst_mikey_message_new_from_caps (caps);
+  if (mikey_msg) {
     gst_rtsp_stream_get_ssrc (stream, &ssrc);
-    gst_mikey_message_add_cs_srtp (msg, 0, ssrc, 0);
-    /* timestamp is now */
-    gst_mikey_message_add_t_now_ntp_utc (msg);
-    /* add some random data */
-    gst_mikey_message_add_rand_len (msg, 16);
-
-    /* the policy '0' is SRTP with the above discovered algorithms */
-    payload = gst_mikey_payload_new (GST_MIKEY_PT_SP);
-    gst_mikey_payload_sp_set (payload, 0, GST_MIKEY_SEC_PROTO_SRTP);
-
-    /* only AES-CM is supported */
-    byte = 1;
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_ALG, 1,
-        &byte);
-    /* Encryption key length */
-    byte = enc_key_length_from_cipher_name (srtpcipher);
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_KEY_LEN, 1,
-        &byte);
-    /* only HMAC-SHA1 */
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_ALG, 1,
-        &byte);
-    /* Authentication key length */
-    byte = auth_key_length_from_auth_name (srtpauth);
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_KEY_LEN, 1,
-        &byte);
-    /* we enable encryption on RTP and RTCP */
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_ENC, 1,
-        &byte);
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTCP_ENC, 1,
-        &byte);
-    /* we enable authentication on RTP and RTCP */
-    gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_AUTH, 1,
-        &byte);
-    gst_mikey_message_add_payload (msg, payload);
-
-    /* make unencrypted KEMAC */
-    payload = gst_mikey_payload_new (GST_MIKEY_PT_KEMAC);
-    gst_mikey_payload_kemac_set (payload, GST_MIKEY_ENC_NULL,
-        GST_MIKEY_MAC_NULL);
-
-    /* add the key in key data */
-    pkd = gst_mikey_payload_new (GST_MIKEY_PT_KEY_DATA);
-    gst_buffer_map (srtpkey, &info, GST_MAP_READ);
-    gst_mikey_payload_key_data_set_key (pkd, GST_MIKEY_KD_TEK, info.size,
-        info.data);
-    gst_buffer_unmap (srtpkey, &info);
-    /* add key data to KEMAC */
-    gst_mikey_payload_kemac_add_sub (payload, pkd);
-    gst_mikey_message_add_payload (msg, payload);
-
-    /* now serialize this to bytes */
-    bytes = gst_mikey_message_to_bytes (msg, NULL, NULL);
-    gst_mikey_message_unref (msg);
-    /* and make it into base64 */
-    data = g_bytes_get_data (bytes, &size);
-    base64 = g_base64_encode (data, size);
-    g_bytes_unref (bytes);
-
-    tmp = g_strdup_printf ("mikey %s", base64);
-    g_free (base64);
-
-    gst_sdp_media_add_attribute (smedia, "key-mgmt", tmp);
-    g_free (tmp);
-  } while (FALSE);
-
-  /* collect all other properties and add them to fmtp or attributes */
-  fmtp = g_string_new ("");
-  g_string_append_printf (fmtp, "%d ", caps_pt);
-  first = TRUE;
-  n_fields = gst_structure_n_fields (s);
-  for (j = 0; j < n_fields; j++) {
-    const gchar *fname, *fval;
-
-    fname = gst_structure_nth_field_name (s, j);
-
-    /* filter out standard properties */
-    if (!strcmp (fname, "media"))
-      continue;
-    if (!strcmp (fname, "payload"))
-      continue;
-    if (!strcmp (fname, "clock-rate"))
-      continue;
-    if (!strcmp (fname, "encoding-name"))
-      continue;
-    if (!strcmp (fname, "encoding-params"))
-      continue;
-    if (!strcmp (fname, "ssrc"))
-      continue;
-    if (!strcmp (fname, "timestamp-offset"))
-      continue;
-    if (!strcmp (fname, "seqnum-offset"))
-      continue;
-    if (g_str_has_prefix (fname, "srtp-"))
-      continue;
-    if (g_str_has_prefix (fname, "srtcp-"))
-      continue;
-    /* handled later */
-    if (g_str_has_prefix (fname, "x-gst-rtsp-server-rtx-time"))
-      continue;
-
-    if (!strcmp (fname, "a-framesize")) {
-      /* a-framesize attribute */
-      if ((fval = gst_structure_get_string (s, fname))) {
-        tmp = g_strdup_printf ("%d %s", caps_pt, fval);
-        gst_sdp_media_add_attribute (smedia, fname + 2, tmp);
-        g_free (tmp);
-      }
-      continue;
-    }
-
-    if (g_str_has_prefix (fname, "a-")) {
-      /* attribute */
-      if ((fval = gst_structure_get_string (s, fname)))
-        gst_sdp_media_add_attribute (smedia, fname + 2, fval);
-      continue;
-    }
-    if (g_str_has_prefix (fname, "x-")) {
-      /* attribute */
-      if ((fval = gst_structure_get_string (s, fname)))
-        gst_sdp_media_add_attribute (smedia, fname, fval);
-      continue;
-    }
+    /* add policy '0' for our SSRC */
+    gst_mikey_message_add_cs_srtp (mikey_msg, 0, ssrc, 0);
 
-    if ((fval = gst_structure_get_string (s, fname))) {
-      g_string_append_printf (fmtp, "%s%s=%s", first ? "" : ";", fname, fval);
-      first = FALSE;
+    base64 = gst_mikey_message_base64_encode (mikey_msg);
+    if (base64) {
+      tmp = g_strdup_printf ("mikey %s", base64);
+      g_free (base64);
+      gst_sdp_media_add_attribute (smedia, "key-mgmt", tmp);
+      g_free (tmp);
     }
-  }
 
-  if (!first) {
-    tmp = g_string_free (fmtp, FALSE);
-    gst_sdp_media_add_attribute (smedia, "fmtp", tmp);
-    g_free (tmp);
-  } else {
-    g_string_free (fmtp, TRUE);
+    gst_mikey_message_unref (mikey_msg);
   }
 
   update_sdp_from_tags (stream, smedia);
@@ -394,6 +181,16 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
           "Not adding retransmission");
     } else {
       gchar *tmp;
+      GstStructure *s;
+      gint caps_pt, caps_rate;
+
+      s = gst_caps_get_structure (caps, 0);
+      if (s == NULL)
+        goto error;
+
+      /* get payload type and clock rate */
+      gst_structure_get_int (s, "payload", &caps_pt);
+      gst_structure_get_int (s, "clock-rate", &caps_rate);
 
       tmp = g_strdup_printf ("%d", rtx_pt);
       gst_sdp_media_add_format (smedia, tmp);
@@ -424,6 +221,12 @@ no_multicast:
         gst_rtsp_stream_get_index (stream));
     return;
   }
+error:
+  {
+    gst_sdp_media_free (smedia);
+    g_warning ("ignoring stream %d", gst_rtsp_stream_get_index (stream));
+    return;
+  }
 }
 
 /**
@@ -456,7 +259,6 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
   for (i = 0; i < n_streams; i++) {
     GstRTSPStream *stream;
     GstCaps *caps;
-    GstStructure *s;
     GstRTSPProfile profiles;
     guint mask;
 
@@ -468,13 +270,6 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
       continue;
     }
 
-    s = gst_caps_get_structure (caps, 0);
-    if (s == NULL) {
-      gst_caps_unref (caps);
-      g_warning ("ignoring stream %d without media type", i);
-      continue;
-    }
-
     /* make a new media for each profile */
     profiles = gst_rtsp_stream_get_profiles (stream);
     mask = 1;
@@ -482,7 +277,7 @@ gst_rtsp_sdp_from_media (GstSDPMessage * sdp, GstSDPInfo * info,
       GstRTSPProfile prof = profiles & mask;
 
       if (prof)
-        make_media (sdp, info, media, stream, s, prof);
+        make_media (sdp, info, media, stream, caps, prof);
 
       mask <<= 1;
     }