20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
21 * Boston, MA 02111-1307, USA. |
21 * Boston, MA 02111-1307, USA. |
22 */ |
22 */ |
23 /** |
23 /** |
24 * SECTION:element-fdsrc |
24 * SECTION:element-fdsrc |
25 * @short_description: read from a unix file descriptor |
|
26 * @see_also: #GstFdSink |
25 * @see_also: #GstFdSink |
27 * |
26 * |
28 * Read data from a unix file descriptor. |
27 * Read data from a unix file descriptor. |
|
28 * |
|
29 * To generate data, enter some data on the console folowed by enter. |
|
30 * The above mentioned pipeline should dump data packets to the console. |
|
31 * |
|
32 * If the #GstFdSrc:timeout property is set to a value bigger than 0, fdsrc will |
|
33 * generate an element message named |
|
34 * <classname>"GstFdSrcTimeout"</classname> |
|
35 * if no data was recieved in the given timeout. |
|
36 * The message's structure contains one field: |
|
37 * <itemizedlist> |
|
38 * <listitem> |
|
39 * <para> |
|
40 * #guint64 |
|
41 * <classname>"timeout"</classname>: the timeout in microseconds that |
|
42 * expired when waiting for data. |
|
43 * </para> |
|
44 * </listitem> |
|
45 * </itemizedlist> |
|
46 * |
|
47 * <refsect2> |
|
48 * <title>Example launch line</title> |
|
49 * |[ |
|
50 * echo "Hello GStreamer" | gst-launch -v fdsrc ! fakesink dump=true |
|
51 * ]| A simple pipeline to read from the standard input and dump the data |
|
52 * with a fakesink as hex ascii block. |
|
53 * </refsect2> |
|
54 * |
|
55 * Last reviewed on 2008-06-20 (0.10.21) |
29 */ |
56 */ |
30 |
|
31 |
57 |
32 #ifdef HAVE_CONFIG_H |
58 #ifdef HAVE_CONFIG_H |
33 # include "config.h" |
59 # include "config.h" |
34 #endif |
60 #endif |
35 #ifdef __SYMBIAN32__ |
61 #include "gst/gst_private.h" |
36 #include <gst_global.h> |
62 |
|
63 #include <sys/types.h> |
|
64 |
|
65 #ifdef G_OS_WIN32 |
|
66 #include <io.h> /* lseek, open, close, read */ |
|
67 #undef lseek |
|
68 #define lseek _lseeki64 |
|
69 #undef off_t |
|
70 #define off_t guint64 |
37 #endif |
71 #endif |
38 #include "gst/gst_private.h" |
72 |
39 |
|
40 #include <sys/types.h> |
|
41 #include <sys/stat.h> |
73 #include <sys/stat.h> |
42 #include <sys/socket.h> |
74 #include <sys/socket.h> |
43 #include <fcntl.h> |
75 #include <fcntl.h> |
44 #include <stdio.h> |
76 #include <stdio.h> |
45 #ifdef HAVE_UNISTD_H |
77 #ifdef HAVE_UNISTD_H |
50 #endif |
82 #endif |
51 #include <stdlib.h> |
83 #include <stdlib.h> |
52 #include <errno.h> |
84 #include <errno.h> |
53 |
85 |
54 #include "gstfdsrc.h" |
86 #include "gstfdsrc.h" |
55 #ifdef __SYMBIAN32__ |
|
56 #include <glib_global.h> |
|
57 #include <gobject_global.h> |
|
58 #include <gstpoll.h> |
|
59 #include <gstelement.h> |
|
60 #endif |
|
61 |
|
62 #define DEFAULT_BLOCKSIZE 4096 |
|
63 |
87 |
64 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", |
88 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", |
65 GST_PAD_SRC, |
89 GST_PAD_SRC, |
66 GST_PAD_ALWAYS, |
90 GST_PAD_ALWAYS, |
67 GST_STATIC_CAPS_ANY); |
91 GST_STATIC_CAPS_ANY); |
68 |
92 |
69 GST_DEBUG_CATEGORY_STATIC (gst_fd_src_debug); |
93 GST_DEBUG_CATEGORY_STATIC (gst_fd_src_debug); |
70 #define GST_CAT_DEFAULT gst_fd_src_debug |
94 #define GST_CAT_DEFAULT gst_fd_src_debug |
71 |
95 |
|
96 #define DEFAULT_FD 0 |
|
97 #define DEFAULT_TIMEOUT 0 |
|
98 |
72 enum |
99 enum |
73 { |
100 { |
74 PROP_0, |
101 PROP_0, |
|
102 |
75 PROP_FD, |
103 PROP_FD, |
|
104 PROP_TIMEOUT, |
|
105 |
|
106 PROP_LAST |
76 }; |
107 }; |
77 |
108 |
78 static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data); |
109 static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data); |
79 |
110 |
80 static void |
111 static void |
106 static gboolean gst_fd_src_unlock (GstBaseSrc * bsrc); |
137 static gboolean gst_fd_src_unlock (GstBaseSrc * bsrc); |
107 static gboolean gst_fd_src_unlock_stop (GstBaseSrc * bsrc); |
138 static gboolean gst_fd_src_unlock_stop (GstBaseSrc * bsrc); |
108 static gboolean gst_fd_src_is_seekable (GstBaseSrc * bsrc); |
139 static gboolean gst_fd_src_is_seekable (GstBaseSrc * bsrc); |
109 static gboolean gst_fd_src_get_size (GstBaseSrc * src, guint64 * size); |
140 static gboolean gst_fd_src_get_size (GstBaseSrc * src, guint64 * size); |
110 static gboolean gst_fd_src_do_seek (GstBaseSrc * src, GstSegment * segment); |
141 static gboolean gst_fd_src_do_seek (GstBaseSrc * src, GstSegment * segment); |
|
142 static gboolean gst_fd_src_query (GstBaseSrc * src, GstQuery * query); |
111 |
143 |
112 static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf); |
144 static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf); |
113 |
145 |
114 static void |
146 static void |
115 gst_fd_src_base_init (gpointer g_class) |
147 gst_fd_src_base_init (gpointer g_class) |
127 static void |
159 static void |
128 gst_fd_src_class_init (GstFdSrcClass * klass) |
160 gst_fd_src_class_init (GstFdSrcClass * klass) |
129 { |
161 { |
130 GObjectClass *gobject_class; |
162 GObjectClass *gobject_class; |
131 GstBaseSrcClass *gstbasesrc_class; |
163 GstBaseSrcClass *gstbasesrc_class; |
132 GstElementClass *gstelement_class; |
|
133 GstPushSrcClass *gstpush_src_class; |
164 GstPushSrcClass *gstpush_src_class; |
134 |
165 |
135 gobject_class = G_OBJECT_CLASS (klass); |
166 gobject_class = G_OBJECT_CLASS (klass); |
136 gstelement_class = GST_ELEMENT_CLASS (klass); |
|
137 gstbasesrc_class = GST_BASE_SRC_CLASS (klass); |
167 gstbasesrc_class = GST_BASE_SRC_CLASS (klass); |
138 gstpush_src_class = GST_PUSH_SRC_CLASS (klass); |
168 gstpush_src_class = GST_PUSH_SRC_CLASS (klass); |
139 |
169 |
140 parent_class = g_type_class_peek_parent (klass); |
170 parent_class = g_type_class_peek_parent (klass); |
141 |
171 |
143 gobject_class->get_property = gst_fd_src_get_property; |
173 gobject_class->get_property = gst_fd_src_get_property; |
144 gobject_class->dispose = gst_fd_src_dispose; |
174 gobject_class->dispose = gst_fd_src_dispose; |
145 |
175 |
146 g_object_class_install_property (gobject_class, PROP_FD, |
176 g_object_class_install_property (gobject_class, PROP_FD, |
147 g_param_spec_int ("fd", "fd", "An open file descriptor to read from", |
177 g_param_spec_int ("fd", "fd", "An open file descriptor to read from", |
148 0, G_MAXINT, 0, G_PARAM_READWRITE)); |
178 0, G_MAXINT, DEFAULT_FD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
179 /** |
|
180 * GstFdSrc:timeout |
|
181 * |
|
182 * Post a message after timeout microseconds |
|
183 * |
|
184 * Since: 0.10.21 |
|
185 */ |
|
186 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT, |
|
187 g_param_spec_uint64 ("timeout", "Timeout", |
|
188 "Post a message after timeout microseconds (0 = disabled)", 0, |
|
189 G_MAXUINT64, DEFAULT_TIMEOUT, |
|
190 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
149 |
191 |
150 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start); |
192 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start); |
151 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop); |
193 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop); |
152 gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_src_unlock); |
194 gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_src_unlock); |
153 gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_src_unlock_stop); |
195 gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_src_unlock_stop); |
154 gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fd_src_is_seekable); |
196 gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fd_src_is_seekable); |
155 gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fd_src_get_size); |
197 gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fd_src_get_size); |
156 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_fd_src_do_seek); |
198 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_fd_src_do_seek); |
|
199 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_fd_src_query); |
157 |
200 |
158 gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fd_src_create); |
201 gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fd_src_create); |
159 } |
202 } |
160 |
203 |
161 static void |
204 static void |
162 gst_fd_src_init (GstFdSrc * fdsrc, GstFdSrcClass * klass) |
205 gst_fd_src_init (GstFdSrc * fdsrc, GstFdSrcClass * klass) |
163 { |
206 { |
164 fdsrc->fd = -1; |
|
165 fdsrc->new_fd = 0; |
207 fdsrc->new_fd = 0; |
166 fdsrc->seekable_fd = FALSE; |
208 fdsrc->seekable_fd = FALSE; |
|
209 fdsrc->fd = DEFAULT_FD; |
|
210 fdsrc->timeout = DEFAULT_TIMEOUT; |
167 fdsrc->uri = g_strdup_printf ("fd://0"); |
211 fdsrc->uri = g_strdup_printf ("fd://0"); |
168 fdsrc->curoffset = 0; |
212 fdsrc->curoffset = 0; |
169 } |
213 } |
170 |
214 |
171 static void |
215 static void |
183 gst_fd_src_update_fd (GstFdSrc * src) |
227 gst_fd_src_update_fd (GstFdSrc * src) |
184 { |
228 { |
185 struct stat stat_results; |
229 struct stat stat_results; |
186 |
230 |
187 /* we need to always update the fdset since it may not have existed when |
231 /* we need to always update the fdset since it may not have existed when |
188 * gst_fd_src_update_fd() was called earlier */ |
232 * gst_fd_src_update_fd () was called earlier */ |
189 if (src->fdset != NULL) { |
233 if (src->fdset != NULL) { |
190 GstPollFD fd = GST_POLL_FD_INIT; |
234 GstPollFD fd = GST_POLL_FD_INIT; |
191 |
235 |
192 if (src->fd >= 0) { |
236 if (src->fd >= 0) { |
193 fd.fd = src->fd; |
237 fd.fd = src->fd; |
310 } else { |
354 } else { |
311 GST_DEBUG_OBJECT (src, "state above ready, not updating to new fd yet"); |
355 GST_DEBUG_OBJECT (src, "state above ready, not updating to new fd yet"); |
312 } |
356 } |
313 GST_OBJECT_UNLOCK (object); |
357 GST_OBJECT_UNLOCK (object); |
314 break; |
358 break; |
|
359 case PROP_TIMEOUT: |
|
360 src->timeout = g_value_get_uint64 (value); |
|
361 GST_DEBUG_OBJECT (src, "poll timeout set to %" GST_TIME_FORMAT, |
|
362 GST_TIME_ARGS (src->timeout)); |
|
363 break; |
315 default: |
364 default: |
316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
365 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
317 break; |
366 break; |
318 } |
367 } |
319 } |
368 } |
339 { |
391 { |
340 GstFdSrc *src; |
392 GstFdSrc *src; |
341 GstBuffer *buf; |
393 GstBuffer *buf; |
342 gssize readbytes; |
394 gssize readbytes; |
343 guint blocksize; |
395 guint blocksize; |
|
396 GstClockTime timeout; |
344 |
397 |
345 #ifndef HAVE_WIN32 |
398 #ifndef HAVE_WIN32 |
|
399 gboolean try_again; |
346 gint retval; |
400 gint retval; |
347 #endif |
401 #endif |
348 |
402 |
349 src = GST_FD_SRC (psrc); |
403 src = GST_FD_SRC (psrc); |
350 |
404 |
|
405 if (src->timeout > 0) { |
|
406 timeout = src->timeout * GST_USECOND; |
|
407 } else { |
|
408 timeout = GST_CLOCK_TIME_NONE; |
|
409 } |
|
410 |
351 #ifndef HAVE_WIN32 |
411 #ifndef HAVE_WIN32 |
352 do { |
412 do { |
353 retval = gst_poll_wait (src->fdset, GST_CLOCK_TIME_NONE); |
413 try_again = FALSE; |
354 } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); /* retry if interrupted */ |
414 |
355 |
415 GST_LOG_OBJECT (src, "doing poll, timeout %" GST_TIME_FORMAT, |
356 if (retval == -1) { |
416 GST_TIME_ARGS (src->timeout)); |
357 if (errno == EBUSY) |
417 |
358 goto stopped; |
418 retval = gst_poll_wait (src->fdset, timeout); |
359 else |
419 GST_LOG_OBJECT (src, "poll returned %d", retval); |
360 goto select_error; |
420 |
361 } |
421 if (G_UNLIKELY (retval == -1)) { |
|
422 if (errno == EINTR || errno == EAGAIN) { |
|
423 /* retry if interrupted */ |
|
424 try_again = TRUE; |
|
425 } else if (errno == EBUSY) { |
|
426 goto stopped; |
|
427 } else { |
|
428 goto poll_error; |
|
429 } |
|
430 } else if (G_UNLIKELY (retval == 0)) { |
|
431 try_again = TRUE; |
|
432 /* timeout, post element message */ |
|
433 gst_element_post_message (GST_ELEMENT_CAST (src), |
|
434 gst_message_new_element (GST_OBJECT_CAST (src), |
|
435 gst_structure_new ("GstFdSrcTimeout", |
|
436 "timeout", G_TYPE_UINT64, src->timeout, NULL))); |
|
437 } |
|
438 } while (G_UNLIKELY (try_again)); /* retry if interrupted or timeout */ |
362 #endif |
439 #endif |
363 |
440 |
364 blocksize = GST_BASE_SRC (src)->blocksize; |
441 blocksize = GST_BASE_SRC (src)->blocksize; |
365 |
442 |
366 /* create the buffer */ |
443 /* create the buffer */ |
367 buf = gst_buffer_new_and_alloc (blocksize); |
444 buf = gst_buffer_try_new_and_alloc (blocksize); |
|
445 if (G_UNLIKELY (buf == NULL)) { |
|
446 GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize); |
|
447 return GST_FLOW_ERROR; |
|
448 } |
368 |
449 |
369 do { |
450 do { |
370 readbytes = read (src->fd, GST_BUFFER_DATA (buf), blocksize); |
451 readbytes = read (src->fd, GST_BUFFER_DATA (buf), blocksize); |
371 GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes); |
452 GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes); |
372 } while (readbytes == -1 && errno == EINTR); /* retry if interrupted */ |
453 } while (readbytes == -1 && errno == EINTR); /* retry if interrupted */ |
389 |
470 |
390 return GST_FLOW_OK; |
471 return GST_FLOW_OK; |
391 |
472 |
392 /* ERRORS */ |
473 /* ERRORS */ |
393 #ifndef HAVE_WIN32 |
474 #ifndef HAVE_WIN32 |
394 select_error: |
475 poll_error: |
395 { |
476 { |
396 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), |
477 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), |
397 ("select on file descriptor: %s.", g_strerror (errno))); |
478 ("poll on file descriptor: %s.", g_strerror (errno))); |
398 GST_DEBUG_OBJECT (psrc, "Error during select"); |
479 GST_DEBUG_OBJECT (psrc, "Error during poll"); |
399 return GST_FLOW_ERROR; |
480 return GST_FLOW_ERROR; |
400 } |
481 } |
401 stopped: |
482 stopped: |
402 { |
483 { |
403 GST_DEBUG_OBJECT (psrc, "Select stopped"); |
484 GST_DEBUG_OBJECT (psrc, "Poll stopped"); |
404 return GST_FLOW_WRONG_STATE; |
485 return GST_FLOW_WRONG_STATE; |
405 } |
486 } |
406 #endif |
487 #endif |
407 eos: |
488 eos: |
408 { |
489 { |
419 return GST_FLOW_ERROR; |
500 return GST_FLOW_ERROR; |
420 } |
501 } |
421 } |
502 } |
422 |
503 |
423 static gboolean |
504 static gboolean |
|
505 gst_fd_src_query (GstBaseSrc * basesrc, GstQuery * query) |
|
506 { |
|
507 gboolean ret = FALSE; |
|
508 GstFdSrc *src = GST_FD_SRC (basesrc); |
|
509 |
|
510 switch (GST_QUERY_TYPE (query)) { |
|
511 case GST_QUERY_URI: |
|
512 gst_query_set_uri (query, src->uri); |
|
513 ret = TRUE; |
|
514 break; |
|
515 default: |
|
516 ret = FALSE; |
|
517 break; |
|
518 } |
|
519 |
|
520 if (!ret) |
|
521 ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); |
|
522 |
|
523 return ret; |
|
524 } |
|
525 |
|
526 static gboolean |
424 gst_fd_src_is_seekable (GstBaseSrc * bsrc) |
527 gst_fd_src_is_seekable (GstBaseSrc * bsrc) |
425 { |
528 { |
426 GstFdSrc *src = GST_FD_SRC (bsrc); |
529 GstFdSrc *src = GST_FD_SRC (bsrc); |
427 |
530 |
428 return src->seekable_fd; |
531 return src->seekable_fd; |
480 GST_DEBUG_OBJECT (src, "lseek returned %" G_GINT64_FORMAT, offset); |
583 GST_DEBUG_OBJECT (src, "lseek returned %" G_GINT64_FORMAT, offset); |
481 return FALSE; |
584 return FALSE; |
482 } |
585 } |
483 |
586 |
484 /*** GSTURIHANDLER INTERFACE *************************************************/ |
587 /*** GSTURIHANDLER INTERFACE *************************************************/ |
485 #ifdef __SYMBIAN32__ |
588 |
486 GstURIType |
589 static GstURIType |
487 #else |
|
488 static guint |
|
489 #endif |
|
490 |
|
491 gst_fd_src_uri_get_type (void) |
590 gst_fd_src_uri_get_type (void) |
492 { |
591 { |
493 return GST_URI_SRC; |
592 return GST_URI_SRC; |
494 } |
593 } |
|
594 |
495 static gchar ** |
595 static gchar ** |
496 gst_fd_src_uri_get_protocols (void) |
596 gst_fd_src_uri_get_protocols (void) |
497 { |
597 { |
498 static gchar *protocols[] = { "fd", NULL }; |
598 static gchar *protocols[] = { "fd", NULL }; |
499 |
599 |
500 return protocols; |
600 return protocols; |
501 } |
601 } |
|
602 |
502 static const gchar * |
603 static const gchar * |
503 gst_fd_src_uri_get_uri (GstURIHandler * handler) |
604 gst_fd_src_uri_get_uri (GstURIHandler * handler) |
504 { |
605 { |
505 GstFdSrc *src = GST_FD_SRC (handler); |
606 GstFdSrc *src = GST_FD_SRC (handler); |
506 |
607 |