diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2006-09-29 11:09:40 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2006-09-29 11:09:40 +0000 |
commit | fcd901a5bf0edad1eb198758da293d0ec34269cf (patch) | |
tree | 814dbd8e3e28f748b491f914df22bcdc9093c085 /gst/udp | |
parent | e8c59d9da35e716049f89ce213f374556997e9df (diff) |
gst/udp/gstudpsrc.*: Added property to post a message on timeout.
Original commit message from CVS:
* gst/udp/gstudpsrc.c: (gst_udpsrc_class_init), (gst_udpsrc_init),
(gst_udpsrc_create), (gst_udpsrc_set_property),
(gst_udpsrc_get_property), (gst_udpsrc_unlock), (gst_udpsrc_stop):
* gst/udp/gstudpsrc.h:
Added property to post a message on timeout.
Updated docs.
When restarting the select, initialize the fdsets again.
Init control sockets so we don't accidentally close a random socket.
API: GstUDPSrc::timeout property
Diffstat (limited to 'gst/udp')
-rw-r--r-- | gst/udp/gstudpsrc.c | 100 | ||||
-rw-r--r-- | gst/udp/gstudpsrc.h | 23 |
2 files changed, 90 insertions, 33 deletions
diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index f7be0fd0..ba395e38 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -80,7 +80,25 @@ * URIs. * </para> * <para> - * Last reviewed on 2006-07-27 (0.10.4) + * If the <link linkend="GstUDPSrc--timeout">timeout property</link> is set to a + * value bigger than 0, udpsrc will generate an element message named + * <classname>"GstUDPSrcTimeout"</classname>: + * if no data was recieved in the given timeout. + * The message's structure contains one field: + * <itemizedlist> + * <listitem> + * <para> + * #guint64 + * <classname>"timeout"</classname>: the timeout that expired when + * waiting for data. + * </para> + * </listitem> + * </itemizedlist> + * The message is typically used to detect that no UDP arrives in the receiver + * because it is blocked by a firewall. + * </para> + * <para> + * Last reviewed on 2006-09-29 (0.10.5) * </para> * </refsect2> */ @@ -109,10 +127,10 @@ GST_DEBUG_CATEGORY_STATIC (udpsrc_debug); #define WRITE_SOCKET(src) src->control_sock[1] #define READ_SOCKET(src) src->control_sock[0] -#define SEND_COMMAND(src, command) \ -G_STMT_START { \ - unsigned char c; c = command; \ - write (WRITE_SOCKET(src), &c, 1); \ +#define SEND_COMMAND(src, command, res) \ +G_STMT_START { \ + unsigned char c; c = command; \ + res = write (WRITE_SOCKET(src), &c, 1); \ } G_STMT_END #define READ_COMMAND(src, command, res) \ @@ -134,10 +152,11 @@ GST_ELEMENT_DETAILS ("UDP packet receiver", #define UDP_DEFAULT_PORT 4951 #define UDP_DEFAULT_MULTICAST_GROUP "0.0.0.0" -#define UDP_DEFAULT_BUFFER_SIZE 0 #define UDP_DEFAULT_URI "udp://"UDP_DEFAULT_MULTICAST_GROUP":"G_STRINGIFY(UDP_DEFAULT_PORT) #define UDP_DEFAULT_CAPS NULL #define UDP_DEFAULT_SOCKFD -1 +#define UDP_DEFAULT_BUFFER_SIZE 0 +#define UDP_DEFAULT_TIMEOUT 0 enum { @@ -147,7 +166,8 @@ enum PROP_URI, PROP_CAPS, PROP_SOCKFD, - PROP_BUFFER_SIZE + PROP_BUFFER_SIZE, + PROP_TIMEOUT }; static void gst_udpsrc_uri_handler_init (gpointer g_iface, gpointer iface_data); @@ -228,6 +248,10 @@ gst_udpsrc_class_init (GstUDPSrcClass * klass) g_param_spec_int ("buffer-size", "Buffer Size", "Size of the kernel receive buffer in bytes, 0=default", 0, G_MAXINT, UDP_DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT, + g_param_spec_uint64 ("timeout", "Timeout", + "Post a message after this timeout (in microseconds) (0 = disabled)", + 0, G_MAXUINT64, UDP_DEFAULT_TIMEOUT, G_PARAM_READWRITE)); gstbasesrc_class->start = gst_udpsrc_start; gstbasesrc_class->stop = gst_udpsrc_stop; @@ -248,6 +272,10 @@ gst_udpsrc_init (GstUDPSrc * udpsrc, GstUDPSrcClass * g_class) udpsrc->multi_group = g_strdup (UDP_DEFAULT_MULTICAST_GROUP); udpsrc->uri = g_strdup (UDP_DEFAULT_URI); udpsrc->buffer_size = UDP_DEFAULT_BUFFER_SIZE; + udpsrc->timeout = UDP_DEFAULT_TIMEOUT; + + udpsrc->control_sock[0] = -1; + udpsrc->control_sock[1] = -1; } static GstCaps * @@ -277,8 +305,7 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) #ifdef G_OS_UNIX gint readsize; -#endif -#ifdef G_OS_WIN32 +#elif defined G_OS_WIN32 gulong readsize; #endif gint ret; @@ -286,32 +313,43 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) udpsrc = GST_UDPSRC (psrc); - FD_ZERO (&read_fds); - FD_SET (udpsrc->sock, &read_fds); -#ifdef G_OS_UNIX - FD_SET (READ_SOCKET (udpsrc), &read_fds); -#endif - max_sock = MAX (udpsrc->sock, READ_SOCKET (udpsrc)); - do { gboolean stop; + struct timeval timeval, *timeout; + + FD_ZERO (&read_fds); + FD_SET (udpsrc->sock, &read_fds); +#ifndef G_OS_WIN32 + FD_SET (READ_SOCKET (udpsrc), &read_fds); +#endif + max_sock = MAX (udpsrc->sock, READ_SOCKET (udpsrc)); try_again = FALSE; stop = FALSE; - GST_LOG_OBJECT (udpsrc, "doing select"); + GST_LOG_OBJECT (udpsrc, "doing select, timeout %" G_GUINT64_FORMAT, + udpsrc->timeout); + + if (udpsrc->timeout > 0) { + timeval.tv_sec = udpsrc->timeout / 1000; + timeval.tv_usec = (udpsrc->timeout % 1000) * 1000; + timeout = &timeval; + } else { + timeout = NULL; + } + #ifdef G_OS_WIN32 if (((max_sock + 1) != READ_SOCKET (udpsrc)) || ((max_sock + 1) != WRITE_SOCKET (udpsrc))) { - ret = select (max_sock + 1, &read_fds, NULL, NULL, NULL); + ret = select (max_sock + 1, &read_fds, NULL, NULL, timeout); } else { ret = 1; } #else - ret = select (max_sock + 1, &read_fds, NULL, NULL, NULL); + ret = select (max_sock + 1, &read_fds, NULL, NULL, timeout); #endif GST_LOG_OBJECT (udpsrc, "select returned %d", ret); - if (ret <= 0) { + if (ret < 0) { #ifdef G_OS_WIN32 if (WSAGetLastError () != WSAEINTR) goto select_error; @@ -320,6 +358,13 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) goto select_error; #endif try_again = TRUE; + } else if (ret == 0) { + /* timeout, post element message */ + gst_element_post_message (GST_ELEMENT_CAST (udpsrc), + gst_message_new_element (GST_OBJECT_CAST (udpsrc), + gst_structure_new ("GstUDPSrcTimeout", + "timeout", G_TYPE_UINT64, udpsrc->timeout, NULL))); + try_again = TRUE; } else { if (FD_ISSET (READ_SOCKET (udpsrc), &read_fds)) { /* got control message */ @@ -353,7 +398,8 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) goto stopped; } while (try_again); - /* ask how much is available for reading on the socket */ + /* ask how much is available for reading on the socket, this is exactly one + * UDP packet. */ if ((ret = IOCTL_SOCKET (udpsrc->sock, FIONREAD, &readsize)) < 0) goto ioctl_failed; @@ -515,6 +561,9 @@ gst_udpsrc_set_property (GObject * object, guint prop_id, const GValue * value, udpsrc->sock = g_value_get_int (value); GST_DEBUG ("setting SOCKFD to %d", udpsrc->sock); break; + case PROP_TIMEOUT: + udpsrc->timeout = g_value_get_uint64 (value); + break; default: break; } @@ -545,6 +594,9 @@ gst_udpsrc_get_property (GObject * object, guint prop_id, GValue * value, case PROP_SOCKFD: g_value_set_int (value, udpsrc->sock); break; + case PROP_TIMEOUT: + g_value_set_uint64 (value, udpsrc->timeout); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -729,11 +781,13 @@ static gboolean gst_udpsrc_unlock (GstBaseSrc * bsrc) { GstUDPSrc *src; + gint res; src = GST_UDPSRC (bsrc); GST_DEBUG ("sending stop command"); - SEND_COMMAND (src, CONTROL_STOP); + SEND_COMMAND (src, CONTROL_STOP, res); + GST_DEBUG ("sent stop command %d", res); return TRUE; } @@ -745,6 +799,8 @@ gst_udpsrc_stop (GstBaseSrc * bsrc) src = GST_UDPSRC (bsrc); + GST_DEBUG ("stopping, closing sockets"); + if (src->sock != -1) { CLOSE_SOCKET (src->sock); src->sock = -1; diff --git a/gst/udp/gstudpsrc.h b/gst/udp/gstudpsrc.h index 4b0b152b..0730cadf 100644 --- a/gst/udp/gstudpsrc.h +++ b/gst/udp/gstudpsrc.h @@ -52,19 +52,20 @@ struct _GstUDPSrc { GstPushSrc parent; /* properties */ - gchar *uri; - int port; - gchar *multi_group; - gint ttl; - gint buffer_size; - - int sock; - int control_sock[2]; + gchar *uri; + int port; + gchar *multi_group; + gint ttl; + GstCaps *caps; + gint buffer_size; + guint64 timeout; - struct sockaddr_in myaddr; - struct ip_mreq multi_addr; + /* our sockets */ + int sock; + int control_sock[2]; - GstCaps *caps; + struct sockaddr_in myaddr; + struct ip_mreq multi_addr; }; struct _GstUDPSrcClass { |