gst/rtsp/gstrtspsrc.c: Refactor timeout handling.
authorWim Taymans <wim.taymans@gmail.com>
Fri, 18 May 2007 10:36:12 +0000 (10:36 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 18 May 2007 10:36:12 +0000 (10:36 +0000)
Original commit message from CVS:
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send_keep_alive),
(gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp),
(gst_rtspsrc_try_send), (gst_rtspsrc_send),
(gst_rtspsrc_setup_streams):
Refactor timeout handling.
Also send keep-alive when dealing with TCP transport.
* gst/rtsp/rtspconnection.c: (rtsp_connection_create),
(rtsp_connection_free), (rtsp_connection_next_timeout),
(rtsp_connection_reset_timeout):
* gst/rtsp/rtspconnection.h:
Use a timer to handle the session timeouts, add some methods to deal
with timeouts.

ChangeLog
gst/rtsp/gstrtspsrc.c
gst/rtsp/rtspconnection.c
gst/rtsp/rtspconnection.h

index 251ebc1..09924a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-05-18  Wim Taymans  <wim@fluendo.com>
+
+       * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send_keep_alive),
+       (gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp),
+       (gst_rtspsrc_try_send), (gst_rtspsrc_send),
+       (gst_rtspsrc_setup_streams):
+       Refactor timeout handling.
+       Also send keep-alive when dealing with TCP transport.
+
+       * gst/rtsp/rtspconnection.c: (rtsp_connection_create),
+       (rtsp_connection_free), (rtsp_connection_next_timeout),
+       (rtsp_connection_reset_timeout):
+       * gst/rtsp/rtspconnection.h:
+       Use a timer to handle the session timeouts, add some methods to deal
+       with timeouts.
+
 2007-05-17  Wim Taymans  <wim@fluendo.com>
 
        * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send),
index 1586171..d7743a9 100644 (file)
@@ -2079,6 +2079,47 @@ send_error:
   }
 }
 
+/* send server keep-alive */
+static RTSPResult
+gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
+{
+  RTSPMessage request = { 0 };
+  RTSPResult res;
+  RTSPMethod method;
+
+  GST_DEBUG_OBJECT (src, "creating server keep-alive");
+
+  /* find a method to use for keep-alive */
+  if (src->methods & RTSP_GET_PARAMETER)
+    method = RTSP_GET_PARAMETER;
+  else
+    method = RTSP_OPTIONS;
+
+  res = rtsp_message_init_request (&request, method, src->req_location);
+  if (res < 0)
+    goto send_error;
+
+  if ((res = rtsp_connection_send (src->connection, &request, NULL)) < 0)
+    goto send_error;
+
+  rtsp_connection_reset_timeout (src->connection);
+  rtsp_message_unset (&request);
+
+  return RTSP_OK;
+
+  /* ERRORS */
+send_error:
+  {
+    gchar *str = rtsp_strresult (res);
+
+    rtsp_message_unset (&request);
+    GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
+        ("Could not send keep-alive. (%s)", str));
+    g_free (str);
+    return res;
+  }
+}
+
 static void
 gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
 {
@@ -2096,10 +2137,35 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
 
   have_data = FALSE;
   do {
+    GTimeVal tv_timeout;
+
+    /* get the next timeout interval */
+    rtsp_connection_next_timeout (src->connection, &tv_timeout);
+
+    /* see if the timeout period expired */
+    if ((tv_timeout.tv_usec | tv_timeout.tv_usec) == 0) {
+      GST_DEBUG_OBJECT (src, "timout, sending keep-alive");
+      /* send keep-alive, ignore the result, a warning will be posted. */
+      res = gst_rtspsrc_send_keep_alive (src);
+    }
+
     GST_DEBUG_OBJECT (src, "doing receive");
 
-    if ((res = rtsp_connection_receive (src->connection, &message, NULL)) < 0)
-      goto receive_error;
+    res = rtsp_connection_receive (src->connection, &message, NULL);
+
+    switch (res) {
+      case RTSP_OK:
+        GST_DEBUG_OBJECT (src, "we received a server message");
+        break;
+      case RTSP_EINTR:
+        /* we got interrupted, see what we have to do */
+        GST_DEBUG_OBJECT (src, "we got interrupted, unset flushing");
+        /* unset flushing so we can do something else */
+        rtsp_connection_flush (src->connection, FALSE);
+        goto interrupt;
+      default:
+        goto receive_error;
+    }
 
     switch (message.type) {
       case RTSP_MESSAGE_REQUEST:
@@ -2200,6 +2266,13 @@ unknown_stream:
     rtsp_message_unset (&message);
     return;
   }
+interrupt:
+  {
+    GST_DEBUG_OBJECT (src, "we got interrupted");
+    rtsp_message_unset (&message);
+    ret = GST_FLOW_WRONG_STATE;
+    goto need_pause;
+  }
 receive_error:
   {
     gchar *str = rtsp_strresult (res);
@@ -2260,49 +2333,6 @@ need_pause:
   }
 }
 
-/* send server keep-alive */
-static RTSPResult
-gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
-{
-  RTSPMessage request = { 0 };
-  RTSPMessage response = { 0 };
-  RTSPResult res;
-  RTSPStatusCode code;
-  RTSPMethod method;
-
-  GST_DEBUG_OBJECT (src, "creating server keep-alive");
-
-  /* find a method to use for keep-alive */
-  if (src->methods & RTSP_GET_PARAMETER)
-    method = RTSP_GET_PARAMETER;
-  else
-    method = RTSP_OPTIONS;
-
-  res = rtsp_message_init_request (&request, method, src->req_location);
-  if (res < 0)
-    goto send_error;
-
-  /* let us handle the error code because we don't care */
-  if ((res = gst_rtspsrc_send (src, &request, &response, &code)) < 0)
-    goto send_error;
-
-  rtsp_message_unset (&request);
-
-  return RTSP_OK;
-
-  /* ERRORS */
-send_error:
-  {
-    gchar *str = rtsp_strresult (res);
-
-    rtsp_message_unset (&request);
-    GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
-        ("Could not send keep-alive. (%s)", str));
-    g_free (str);
-    return res;
-  }
-}
-
 static void
 gst_rtspsrc_loop_udp (GstRTSPSrc * src)
 {
@@ -2314,26 +2344,17 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
     goto stopping;
 
   while (src->loop_cmd == CMD_WAIT) {
-    GTimeVal tv_timeout;
-    gint timeout;
-
     GST_OBJECT_UNLOCK (src);
 
     while (TRUE) {
       RTSPMessage message = { 0 };
+      GTimeVal tv_timeout;
 
-      /* calculate the session timeout. We should send the keep-alive request a
-       * little earlier to compensate for the round trip time to the server. We
-       * subtract 1 second here. */
-      timeout = src->connection->timeout;
-      if (timeout > 1)
-        timeout -= 1;
-
-      /* use the session timeout for receiving data */
-      tv_timeout.tv_sec = timeout;
-      tv_timeout.tv_usec = 0;
+      /* get the next timeout interval */
+      rtsp_connection_next_timeout (src->connection, &tv_timeout);
 
-      GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds", timeout);
+      GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
+          tv_timeout.tv_sec);
 
       /* we should continue reading the TCP socket because the server might
        * send us requests. When the session timeout expires, we need to send a
@@ -2366,9 +2387,12 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
             goto handle_request_failed;
           break;
         case RTSP_MESSAGE_RESPONSE:
+          /* we ignore response and data messages */
+          GST_DEBUG_OBJECT (src, "ignoring response message");
+          break;
         case RTSP_MESSAGE_DATA:
           /* we ignore response and data messages */
-          GST_DEBUG_OBJECT (src, "ignoring message");
+          GST_DEBUG_OBJECT (src, "ignoring data message");
           break;
         default:
           GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
@@ -2673,6 +2697,8 @@ gst_rtspsrc_try_send (GstRTSPSrc * src, RTSPMessage * request,
   if ((res = rtsp_connection_send (src->connection, request, NULL)) < 0)
     goto send_error;
 
+  rtsp_connection_reset_timeout (src->connection);
+
 next:
   if ((res = rtsp_connection_receive (src->connection, response, NULL)) < 0)
     goto receive_error;
index d806b50..cb81c72 100644 (file)
@@ -142,6 +142,7 @@ rtsp_connection_create (RTSPUrl * url, RTSPConnection ** conn)
   newconn->fd = -1;
   newconn->cseq = 0;
   newconn->session_id[0] = 0;
+  newconn->timer = g_timer_new ();
 
   newconn->auth_method = RTSP_AUTH_NONE;
   newconn->username = NULL;
@@ -900,6 +901,7 @@ rtsp_connection_free (RTSPConnection * conn)
   WSACleanup ();
 #endif
 
+  g_timer_destroy (conn->timer);
   g_free (conn->username);
   g_free (conn->passwd);
 
@@ -909,6 +911,40 @@ rtsp_connection_free (RTSPConnection * conn)
 }
 
 RTSPResult
+rtsp_connection_next_timeout (RTSPConnection * conn, GTimeVal * timeout)
+{
+  gdouble elapsed;
+  glong sec;
+  gulong usec;
+
+  g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
+  g_return_val_if_fail (timeout != NULL, RTSP_EINVAL);
+
+  elapsed = g_timer_elapsed (conn->timer, &usec);
+  if (elapsed >= conn->timeout) {
+    sec = 0;
+    usec = 0;
+  } else {
+    sec = conn->timeout - elapsed;
+  }
+
+  timeout->tv_sec = sec;
+  timeout->tv_usec = usec;
+
+  return RTSP_OK;
+}
+
+RTSPResult
+rtsp_connection_reset_timeout (RTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
+
+  g_timer_start (conn->timer);
+
+  return RTSP_OK;
+}
+
+RTSPResult
 rtsp_connection_flush (RTSPConnection * conn, gboolean flush)
 {
   g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
index b2fcd07..2827258 100644 (file)
@@ -65,11 +65,12 @@ typedef struct _RTSPConnection
   gint          cseq;                   /* sequence number */
   gchar         session_id[512];        /* session id */
   gint          timeout;                /* session timeout in seconds */
+  GTimer       *timer;                  /* timeout timer */
 
   /* Authentication */
-  RTSPAuthMethod auth_method;
-  gchar *username;
-  gchar *passwd;
+  RTSPAuthMethod  auth_method;
+  gchar          *username;
+  gchar          *passwd;
 } RTSPConnection;
 
 /* opening/closing a connection */
@@ -88,6 +89,10 @@ RTSPResult      rtsp_connection_write    (RTSPConnection * conn, const guint8 *
 RTSPResult      rtsp_connection_send     (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
 RTSPResult      rtsp_connection_receive  (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
 
+/* reset the timeout */
+RTSPResult      rtsp_connection_next_timeout   (RTSPConnection *conn, GTimeVal *timeout);
+RTSPResult      rtsp_connection_reset_timeout  (RTSPConnection *conn);
+
 /* flushing state */
 RTSPResult      rtsp_connection_flush    (RTSPConnection *conn, gboolean flush);