- * @address: (allow-none): an address or %NULL
- * @port: a port or 0
- *
- * Get the #GstNetTimeProvider for the clock used by @media. The time provider
- * will listen on @address and @port for client time requests.
- *
- * Returns: (transfer full): the #GstNetTimeProvider of @media.
- */
-GstNetTimeProvider *
-gst_rtsp_media_get_time_provider (GstRTSPMedia * media, const gchar * address,
- guint16 port)
-{
- GstRTSPMediaPrivate *priv;
- GstNetTimeProvider *provider = NULL;
-
- g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
-
- priv = media->priv;
-
- g_rec_mutex_lock (&priv->state_lock);
- if (priv->time_provider) {
- if ((provider = priv->nettime) == NULL) {
- GstClock *clock;
-
- if (priv->time_provider && (clock = get_clock_unlocked (media))) {
- provider = gst_net_time_provider_new (clock, address, port);
- gst_object_unref (clock);
-
- priv->nettime = provider;
- }
- }
- }
- g_rec_mutex_unlock (&priv->state_lock);
-
- if (provider)
- gst_object_ref (provider);
-
- return provider;
-}
-
-static gboolean
-default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info)
-{
- return gst_rtsp_sdp_from_media (sdp, info, media);
-}
-
-/**
- * gst_rtsp_media_setup_sdp:
- * @media: a #GstRTSPMedia
- * @sdp: (transfer none): a #GstSDPMessage
- * @info: (transfer none): a #GstSDPInfo
- *
- * Add @media specific info to @sdp. @info is used to configure the connection
- * information in the SDP.
- *
- * Returns: TRUE on success.
- */
-gboolean
-gst_rtsp_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
- GstSDPInfo * info)
-{
- GstRTSPMediaPrivate *priv;
- GstRTSPMediaClass *klass;
- gboolean res;
-
- g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
- g_return_val_if_fail (sdp != NULL, FALSE);
- g_return_val_if_fail (info != NULL, FALSE);
-
- priv = media->priv;
-
- g_rec_mutex_lock (&priv->state_lock);
-
- klass = GST_RTSP_MEDIA_GET_CLASS (media);
-
- if (!klass->setup_sdp)
- goto no_setup_sdp;
-
- res = klass->setup_sdp (media, sdp, info);
-
- g_rec_mutex_unlock (&priv->state_lock);
-
- return res;
-
- /* ERRORS */
-no_setup_sdp:
- {
- g_rec_mutex_unlock (&priv->state_lock);
- GST_ERROR ("no setup_sdp function");
- g_critical ("no setup_sdp vmethod function set");
- return FALSE;
- }
-}
-
-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, ¶ms);
- 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;
-
- /* 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]);
- 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)