gst/rtsp/URLS: Added some other URL.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 11 Oct 2006 16:21:53 +0000 (16:21 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 11 Oct 2006 16:21:53 +0000 (16:21 +0000)
Original commit message from CVS:
* gst/rtsp/URLS:
Added some other URL.
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_loop_udp),
(gst_rtspsrc_handle_request), (gst_rtspsrc_send),
(gst_rtspsrc_open), (gst_rtspsrc_play),
(gst_rtspsrc_handle_message), (gst_rtspsrc_change_state):
* gst/rtsp/gstrtspsrc.h:
Work on fallback to TCP connection when the UDP socket times out.
Handler server requests, just reply with OK for now.
* gst/rtsp/rtspdefs.c: (rtsp_strresult):
* gst/rtsp/rtspdefs.h:
Added some more Real extension headers.
* gst/rtsp/rtspurl.c: (rtsp_url_parse):
Fix parsing of urls with a ':' that is not part of the hostname:port
part of the url.

ChangeLog
gst/rtsp/URLS
gst/rtsp/gstrtspsrc.c
gst/rtsp/gstrtspsrc.h
gst/rtsp/rtspdefs.c
gst/rtsp/rtspdefs.h
gst/rtsp/rtspurl.c

index 1c6902c..95d2b2d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2006-10-11  Wim Taymans  <wim@fluendo.com>
+
+       * gst/rtsp/URLS:
+       Added some other URL.
+
+       * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_loop_udp),
+       (gst_rtspsrc_handle_request), (gst_rtspsrc_send),
+       (gst_rtspsrc_open), (gst_rtspsrc_play),
+       (gst_rtspsrc_handle_message), (gst_rtspsrc_change_state):
+       * gst/rtsp/gstrtspsrc.h:
+       Work on fallback to TCP connection when the UDP socket times out.
+       Handler server requests, just reply with OK for now.
+
+       * gst/rtsp/rtspdefs.c: (rtsp_strresult):
+       * gst/rtsp/rtspdefs.h:
+       Added some more Real extension headers.
+
+       * gst/rtsp/rtspurl.c: (rtsp_url_parse):
+       Fix parsing of urls with a ':' that is not part of the hostname:port
+       part of the url.
+
 2006-10-11  Tim-Philipp Müller  <tim at centricular dot net>
 
        * gst/apetag/gsttagdemux.c: (gst_tag_demux_add_srcpad):
index 16d5d5a..4c08f80 100644 (file)
@@ -16,3 +16,4 @@ MP4V-ES/mpeg4-generic(ACC):
 
 REAL:
   rtsp://213.254.239.61/farm/*/encoder/tagesschau/live1high.rm
+  rtsp://64.192.137.105:554/real.amazon-de.eu2/phononet/B/0/0/0/H/W/Y/4/K/S/01.01.rm?cloakport=80,554,7070
index f67ac46..4791753 100644 (file)
 #include "gstrtspsrc.h"
 #include "sdp.h"
 
+#if 0
+#define WITH_EXT_REAL
+#endif
+
 #include "rtspextwms.h"
 #ifdef WITH_EXT_REAL
 #include "rtspextreal.h"
@@ -173,6 +177,11 @@ static void gst_rtspsrc_set_property (GObject * object, guint prop_id,
 static void gst_rtspsrc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static gboolean gst_rtspsrc_open (GstRTSPSrc * src);
+static gboolean gst_rtspsrc_play (GstRTSPSrc * src);
+static gboolean gst_rtspsrc_pause (GstRTSPSrc * src);
+static gboolean gst_rtspsrc_close (GstRTSPSrc * src);
+
 static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler,
     const gchar * uri);
 
@@ -1207,9 +1216,12 @@ need_pause:
 static void
 gst_rtspsrc_loop_udp (GstRTSPSrc * src)
 {
+  gboolean restart = FALSE;
+
   GST_OBJECT_LOCK (src);
   if (src->loop_cmd == CMD_STOP)
     goto stopping;
+
   while (src->loop_cmd == CMD_WAIT) {
     GST_DEBUG_OBJECT (src, "waiting");
     GST_RTSP_LOOP_WAIT (src);
@@ -1220,9 +1232,42 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
   if (src->loop_cmd == CMD_RECONNECT) {
     /* FIXME, when we get here we have to reconnect using tcp */
     src->loop_cmd = CMD_WAIT;
+    restart = TRUE;
   }
   GST_OBJECT_UNLOCK (src);
 
+  if (restart) {
+    gst_rtspsrc_pause (src);
+
+    if (src->task) {
+      /* stop task, we cannot join as this would deadlock */
+      gst_task_stop (src->task);
+      /* and free the task so that _close will not stop/join it again. */
+      gst_object_unref (GST_OBJECT (src->task));
+      src->task = NULL;
+    }
+    gst_rtspsrc_close (src);
+
+    /* see if we have TCP left to try */
+    if (src->cur_protocols & RTSP_LOWER_TRANS_TCP) {
+      /* We post a warning message now to inform the user
+       * that nothing happened. It's most likely a firewall thing. */
+      GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
+          ("Could not receive any UDP packets for %.4f seconds, maybe your "
+              "firewall is blocking it. Retrying using a TCP connection.",
+              (gdouble) src->timeout / 1000000));
+      /* we can try only TCP now */
+      src->cur_protocols = RTSP_LOWER_TRANS_TCP;
+      gst_rtspsrc_open (src);
+      gst_rtspsrc_play (src);
+    } else {
+      src->cur_protocols = 0;
+      /* no transport possible, post an error */
+      GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
+          ("Could not receive any UDP packets for %.4f seconds, maybe your "
+              "firewall is blocking it.", (gdouble) src->timeout / 1000000));
+    }
+  }
   return;
 
   /* ERRORS */
@@ -1253,6 +1298,36 @@ gst_rtspsrc_loop (GstRTSPSrc * src)
     gst_rtspsrc_loop_udp (src);
 }
 
+static RTSPResult
+gst_rtspsrc_handle_request (GstRTSPSrc * src, RTSPMessage * request)
+{
+  RTSPMessage response = { 0 };
+  RTSPResult res;
+
+  res = rtsp_message_init_response (&response, RTSP_STS_OK, "OK", request);
+  if (res < 0)
+    goto send_error;
+
+  if (src->debug)
+    rtsp_message_dump (&response);
+
+  if ((res = rtsp_connection_send (src->connection, &response)) < 0)
+    goto send_error;
+
+  return RTSP_OK;
+
+  /* ERRORS */
+send_error:
+  {
+    gchar *str = rtsp_strresult (res);
+
+    GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
+        ("Could not send message. (%s)", str));
+    g_free (str);
+    return res;
+  }
+}
+
 /**
  * gst_rtspsrc_send:
  * @src: the rtsp source
@@ -1287,12 +1362,28 @@ gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request,
   if ((res = rtsp_connection_send (src->connection, request)) < 0)
     goto send_error;
 
+next:
   if ((res = rtsp_connection_receive (src->connection, response)) < 0)
     goto receive_error;
 
   if (src->debug)
     rtsp_message_dump (response);
 
+  switch (response->type) {
+    case RTSP_MESSAGE_REQUEST:
+      /* FIXME, handle server request, reply with OK, for now */
+      if ((res = gst_rtspsrc_handle_request (src, response)) < 0)
+        goto handle_request_failed;
+      goto next;
+    case RTSP_MESSAGE_RESPONSE:
+      /* ok, a response is good */
+      break;
+    default:
+    case RTSP_MESSAGE_DATA:
+      /* get next response */
+      goto next;
+  }
+
   thecode = response->type_data.response.code;
   /* if the caller wanted the result code, we store it. Else we check if it's
    * OK. */
@@ -1332,6 +1423,11 @@ receive_error:
     g_free (str);
     return FALSE;
   }
+handle_request_failed:
+  {
+    /* ERROR was posted */
+    return FALSE;
+  }
 error_response:
   {
     switch (response->type_data.response.code) {
@@ -1566,6 +1662,11 @@ gst_rtspsrc_open (GstRTSPSrc * src)
   GstRTSPStream *stream = NULL;
   gchar *respcont = NULL;
 
+  /* reset our state */
+  src->free_channel = 0;
+  src->interleaved = FALSE;
+  gst_segment_init (&src->segment, GST_FORMAT_TIME);
+
   /* can't continue without a valid url */
   if (G_UNLIKELY (src->url == NULL))
     goto no_url;
@@ -1639,7 +1740,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
 
   /* we initially allow all configured lower transports. based on the
    * replies from the server we narrow them down. */
-  protocols = src->protocols;
+  protocols = src->cur_protocols;
 
   /* setup streams */
   n_streams = sdp_message_medias_len (&sdp);
@@ -1952,7 +2053,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
   if (res < 0)
     goto create_request_failed;
 
-  rtsp_message_add_header (&request, RTSP_HDR_RANGE, "npt=0.000-");
+  rtsp_message_add_header (&request, RTSP_HDR_RANGE, "npt=0-");
 
   if (!gst_rtspsrc_send (src, &request, &response, NULL))
     goto send_error;
@@ -2051,13 +2152,6 @@ gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message)
       if (gst_structure_has_name (s, "GstUDPSrcTimeout")) {
         GST_DEBUG_OBJECT (bin, "timeout on UDP port");
         gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_RECONNECT);
-        /* FIXME, we post an error message now to inform the user
-         * that nothing happened. It's most likely a firewall thing. Ideally we
-         * notify the thread and redo the setup with only TCP. */
-        GST_ELEMENT_ERROR (rtspsrc, RESOURCE, READ, (NULL),
-            ("Could not receive any UDP packets for %.4f seconds, maybe your "
-                "firewall is blocking it.",
-                (gdouble) rtspsrc->timeout / 1000000));
         return;
       }
     }
@@ -2080,15 +2174,13 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      /* the first free channel for interleaved mode */
-      rtspsrc->free_channel = 0;
-      rtspsrc->interleaved = FALSE;
-      gst_segment_init (&rtspsrc->segment, GST_FORMAT_TIME);
+      rtspsrc->cur_protocols = rtspsrc->protocols;
       if (!gst_rtspsrc_open (rtspsrc))
         goto open_failed;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       rtsp_connection_flush (rtspsrc->connection, FALSE);
+      /* copy configuerd protocols */
       gst_rtspsrc_play (rtspsrc);
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
index 94b9ed3..d7ea7e5 100644 (file)
@@ -124,14 +124,18 @@ struct _GstRTSPSrc {
   GList           *streams;
   GstStructure    *props;
 
+  /* properties */
   gchar           *location;
   RTSPUrl         *url;
-  gchar           *content_base;
   RTSPLowerTrans   protocols;
   gboolean         debug;
   guint           retry;
   guint64          timeout;
 
+  /* state */
+  gchar           *content_base;
+  RTSPLowerTrans   cur_protocols;
+
   /* supported methods */
   gint             methods;
 
index 0138d79..63b68a3 100644 (file)
@@ -128,7 +128,16 @@ static const gchar *rtsp_headers[] = {
   "ClientChallenge",            /* ClientChallenge */
   "RealChallenge1",             /* RealChallenge1 */
   "RealChallenge2",             /* RealChallenge2 */
+  "RealChallenge3",             /* RealChallenge3 */
   "Subscribe",                  /* Subscribe */
+  "Alert",                      /* Alert */
+  "ClientID",                   /* ClientID */
+  "CompanyID",                  /* CompanyID */
+  "GUID",                       /* GUID */
+  "RegionData",                 /* RegionData */
+  "SupportsMaximumASMBandwidth",        /* SupportsMaximumASMBandwidth */
+  "Language",                   /* Language */
+  "PlayerStarttime",            /* PlayerStarttime */
 
   NULL
 };
index 229fc42..7afece9 100644 (file)
@@ -155,7 +155,17 @@ typedef enum {
   RTSP_HDR_CLIENT_CHALLENGE,    /* ClientChallenge */
   RTSP_HDR_REAL_CHALLENGE1,     /* RealChallenge1 */
   RTSP_HDR_REAL_CHALLENGE2,     /* RealChallenge2 */
+  RTSP_HDR_REAL_CHALLENGE3,     /* RealChallenge3 */
   RTSP_HDR_SUBSCRIBE,           /* Subscribe */
+  RTSP_HDR_ALERT,               /* Alert */
+  RTSP_HDR_CLIENT_ID,           /* ClientID */
+  RTSP_HDR_COMPANY_ID,          /* CompanyID */
+  RTSP_HDR_GUID,                /* GUID */
+  RTSP_HDR_REGION_DATA,         /* RegionData */
+  RTSP_HDR_MAX_ASM_WIDTH,       /* SupportsMaximumASMBandwidth */
+  RTSP_HDR_LANGUAGE,            /* Language */
+  RTSP_HDR_PLAYER_START_TIME,   /* PlayerStarttime */
+
 
 } RTSPHeaderField;
 
index 04b455a..cc11e91 100644 (file)
@@ -95,6 +95,11 @@ rtsp_url_parse (const gchar * urlstr, RTSPUrl ** url)
   }
 
   col = strstr (p, ":");
+  /* we have a ':' and a slash but the ':' is after the slash, it's not really
+   * part of the hostname */
+  if (col && slash && col >= slash)
+    col = NULL;
+
   if (col) {
     res->host = g_strndup (p, col - p);
     p = col + 1;