typefind: Use gst_query_has_scheduling_mode_with_flags() convenience function
[platform/upstream/gstreamer.git] / plugins / elements / gstfdsrc.c
index 5fd1b72..469a614 100644 (file)
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 /**
  * SECTION:element-fdsrc
  * @see_also: #GstFdSink
  *
  * Read data from a unix file descriptor.
- * 
- * To generate data, enter some data on the console folowed by enter.
+ *
+ * To generate data, enter some data on the console followed by enter.
  * The above mentioned pipeline should dump data packets to the console.
- * 
+ *
  * If the #GstFdSrc:timeout property is set to a value bigger than 0, fdsrc will
- * generate an element message named
- * <classname>&quot;GstFdSrcTimeout&quot;</classname>
- * if no data was recieved in the given timeout.
+ * generate an element message named <classname>&quot;GstFdSrcTimeout&quot;</classname>
+ * if no data was received in the given timeout.
+ *
  * The message's structure contains one field:
  * <itemizedlist>
  * <listitem>
  *   </para>
  * </listitem>
  * </itemizedlist>
- * 
+ *
  * <refsect2>
  * <title>Example launch line</title>
  * |[
- * echo "Hello GStreamer" | gst-launch -v fdsrc ! fakesink dump=true
+ * echo "Hello GStreamer" | gst-launch-1.0 -v fdsrc ! fakesink dump=true
  * ]| A simple pipeline to read from the standard input and dump the data
  * with a fakesink as hex ascii block.
  * </refsect2>
- * 
- * Last reviewed on 2008-06-20 (0.10.21)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -66,8 +64,6 @@
 #include <io.h>                 /* lseek, open, close, read */
 #undef lseek
 #define lseek _lseeki64
-#undef off_t
-#define off_t guint64
 #endif
 
 #include <sys/stat.h>
 
 #include "gstfdsrc.h"
 
+#ifdef __BIONIC__               /* Android */
+#undef lseek
+#define lseek lseek64
+#undef fstat
+#define fstat fstat64
+#endif
+
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
@@ -160,8 +163,6 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
    * GstFdSrc:timeout
    *
    * Post a message after timeout microseconds
-   *
-   * Since: 0.10.21
    */
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT,
       g_param_spec_uint64 ("timeout", "Timeout",
@@ -169,12 +170,11 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
           G_MAXUINT64, DEFAULT_TIMEOUT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  gst_element_class_set_details_simple (gstelement_class,
+  gst_element_class_set_static_metadata (gstelement_class,
       "Filedescriptor Source",
       "Source/File",
       "Read from a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
 
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop);
@@ -392,24 +392,23 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
   GstBuffer *buf;
   gssize readbytes;
   guint blocksize;
-  GstClockTime timeout;
-  guint8 *data;
-  gsize maxsize;
+  GstMapInfo info;
 
 #ifndef HAVE_WIN32
+  GstClockTime timeout;
   gboolean try_again;
   gint retval;
 #endif
 
   src = GST_FD_SRC (psrc);
 
+#ifndef HAVE_WIN32
   if (src->timeout > 0) {
     timeout = src->timeout * GST_USECOND;
   } else {
     timeout = GST_CLOCK_TIME_NONE;
   }
 
-#ifndef HAVE_WIN32
   do {
     try_again = FALSE;
 
@@ -442,21 +441,23 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
   blocksize = GST_BASE_SRC (src)->blocksize;
 
   /* create the buffer */
-  buf = gst_buffer_new_allocate (NULL, blocksize, 0);
+  buf = gst_buffer_new_allocate (NULL, blocksize, NULL);
   if (G_UNLIKELY (buf == NULL))
     goto alloc_failed;
 
-  data = gst_buffer_map (buf, NULL, &maxsize, GST_MAP_WRITE);
+  if (!gst_buffer_map (buf, &info, GST_MAP_WRITE))
+    goto buffer_read_error;
 
   do {
-    readbytes = read (src->fd, data, blocksize);
+    readbytes = read (src->fd, info.data, blocksize);
     GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes);
   } while (readbytes == -1 && errno == EINTR);  /* retry if interrupted */
 
   if (readbytes < 0)
     goto read_error;
 
-  gst_buffer_unmap (buf, data, readbytes);
+  gst_buffer_unmap (buf, &info);
+  gst_buffer_resize (buf, 0, readbytes);
 
   if (readbytes == 0)
     goto eos;
@@ -484,7 +485,7 @@ poll_error:
 stopped:
   {
     GST_DEBUG_OBJECT (psrc, "Poll stopped");
-    return GST_FLOW_WRONG_STATE;
+    return GST_FLOW_FLUSHING;
   }
 #endif
 alloc_failed:
@@ -503,7 +504,13 @@ read_error:
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
         ("read on file descriptor: %s.", g_strerror (errno)));
     GST_DEBUG_OBJECT (psrc, "Error reading from fd");
-    gst_buffer_unmap (buf, data, 0);
+    gst_buffer_unmap (buf, &info);
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+buffer_read_error:
+  {
+    GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Can't write to buffer"));
     gst_buffer_unref (buf);
     return GST_FLOW_ERROR;
   }
@@ -605,49 +612,58 @@ gst_fd_src_uri_get_type (GType type)
   return GST_URI_SRC;
 }
 
-static gchar **
+static const gchar *const *
 gst_fd_src_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "fd", NULL };
+  static const gchar *protocols[] = { "fd", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_fd_src_uri_get_uri (GstURIHandler * handler)
 {
   GstFdSrc *src = GST_FD_SRC (handler);
 
-  return src->uri;
+  /* FIXME: make thread-safe */
+  return g_strdup (src->uri);
 }
 
 static gboolean
-gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** err)
 {
   gchar *protocol, *q;
   GstFdSrc *src = GST_FD_SRC (handler);
   gint fd;
-  guint64 size = -1;
+  guint64 size = (guint64) - 1;
 
   GST_INFO_OBJECT (src, "checking uri %s", uri);
 
   protocol = gst_uri_get_protocol (uri);
   if (strcmp (protocol, "fd") != 0) {
+    g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "Wrong protocol for fdsrc in uri: '%s'", uri);
     g_free (protocol);
     return FALSE;
   }
   g_free (protocol);
 
-  if (sscanf (uri, "fd://%d", &fd) != 1 || fd < 0)
+  if (sscanf (uri, "fd://%d", &fd) != 1 || fd < 0) {
+    g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "Bad file descriptor number in uri: '%s'", uri);
     return FALSE;
+  }
 
   if ((q = g_strstr_len (uri, -1, "?"))) {
-    gchar *sp;
+    gchar *sp, *end = NULL;
 
     GST_INFO_OBJECT (src, "found ?");
 
     if ((sp = g_strstr_len (q, -1, "size="))) {
-      if (sscanf (sp, "size=%" G_GUINT64_FORMAT, &size) != 1) {
+      sp += strlen ("size=");
+      size = g_ascii_strtoull (sp, &end, 10);
+      if ((size == 0 && errno == EINVAL) || size == G_MAXUINT64 || end == sp) {
         GST_INFO_OBJECT (src, "parsing size failed");
         size = -1;
       } else {