+ *outbuf = buf;
+
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+#ifndef HAVE_WIN32
+poll_error:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
+ ("poll on file descriptor: %s.", g_strerror (errno)));
+ GST_DEBUG_OBJECT (psrc, "Error during poll");
+ return GST_FLOW_ERROR;
+ }
+stopped:
+ {
+ GST_DEBUG_OBJECT (psrc, "Poll stopped");
+ return GST_FLOW_WRONG_STATE;
+ }
+#endif
+alloc_failed:
+ {
+ GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize);
+ return GST_FLOW_ERROR;
+ }
+eos:
+ {
+ GST_DEBUG_OBJECT (psrc, "Read 0 bytes. EOS.");
+ gst_buffer_unref (buf);
+ return GST_FLOW_UNEXPECTED;
+ }
+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_unref (buf);
+ return GST_FLOW_ERROR;
+ }
+}
+
+static gboolean
+gst_fd_src_query (GstBaseSrc * basesrc, GstQuery ** query)
+{
+ gboolean ret = FALSE;
+ GstFdSrc *src = GST_FD_SRC (basesrc);
+
+ switch (GST_QUERY_TYPE (*query)) {
+ case GST_QUERY_URI:
+ gst_query_set_uri (*query, src->uri);
+ ret = TRUE;
+ break;
+ default:
+ ret = FALSE;
+ break;
+ }
+
+ if (!ret)
+ ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+
+ return ret;
+}
+
+static gboolean
+gst_fd_src_is_seekable (GstBaseSrc * bsrc)
+{
+ GstFdSrc *src = GST_FD_SRC (bsrc);
+
+ return src->seekable_fd;
+}
+
+static gboolean
+gst_fd_src_get_size (GstBaseSrc * bsrc, guint64 * size)
+{
+ GstFdSrc *src = GST_FD_SRC (bsrc);
+ struct stat stat_results;
+
+ if (src->size != -1) {
+ *size = src->size;
+ return TRUE;
+ }
+
+ if (!src->seekable_fd) {
+ /* If it isn't seekable, we won't know the length (but fstat will still
+ * succeed, and wrongly say our length is zero. */
+ return FALSE;
+ }
+
+ if (fstat (src->fd, &stat_results) < 0)
+ goto could_not_stat;
+
+ *size = stat_results.st_size;
+
+ return TRUE;
+
+ /* ERROR */
+could_not_stat:
+ {
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_fd_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
+{
+ gint res;
+ gint64 offset;
+ GstFdSrc *src = GST_FD_SRC (bsrc);
+
+ offset = segment->start;
+
+ /* No need to seek to the current position */
+ if (offset == src->curoffset)
+ return TRUE;
+
+ res = lseek (src->fd, offset, SEEK_SET);
+ if (G_UNLIKELY (res < 0 || res != offset))
+ goto seek_failed;
+
+ segment->position = segment->start;
+ segment->time = segment->start;
+
+ return TRUE;
+
+seek_failed:
+ GST_DEBUG_OBJECT (src, "lseek returned %" G_GINT64_FORMAT, offset);
+ return FALSE;
+}
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static GstURIType
+gst_fd_src_uri_get_type (void)
+{
+ return GST_URI_SRC;
+}
+
+static gchar **
+gst_fd_src_uri_get_protocols (void)
+{
+ static gchar *protocols[] = { (char *) "fd", NULL };
+
+ return protocols;
+}
+
+static const gchar *
+gst_fd_src_uri_get_uri (GstURIHandler * handler)
+{
+ GstFdSrc *src = GST_FD_SRC (handler);
+
+ return src->uri;
+}
+
+static gboolean
+gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+{
+ gchar *protocol, *q;
+ GstFdSrc *src = GST_FD_SRC (handler);
+ gint fd;
+ guint64 size = -1;
+
+ GST_INFO_OBJECT (src, "checking uri %s", uri);
+
+ protocol = gst_uri_get_protocol (uri);
+ if (strcmp (protocol, "fd") != 0) {
+ g_free (protocol);
+ return FALSE;
+ }
+ g_free (protocol);
+
+ if (sscanf (uri, "fd://%d", &fd) != 1 || fd < 0)
+ return FALSE;
+
+ if ((q = g_strstr_len (uri, -1, "?"))) {
+ gchar *sp;
+
+ GST_INFO_OBJECT (src, "found ?");
+
+ if ((sp = g_strstr_len (q, -1, "size="))) {
+ if (sscanf (sp, "size=%" G_GUINT64_FORMAT, &size) != 1) {
+ GST_INFO_OBJECT (src, "parsing size failed");
+ size = -1;
+ } else {
+ GST_INFO_OBJECT (src, "found size %" G_GUINT64_FORMAT, size);
+ }
+ }
+ }
+
+ src->new_fd = fd;
+
+ GST_OBJECT_LOCK (src);
+ if (GST_STATE (GST_ELEMENT (src)) <= GST_STATE_READY) {
+ gst_fd_src_update_fd (src, size);
+ }
+ GST_OBJECT_UNLOCK (src);
+
+ return TRUE;
+}
+
+static void
+gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+ GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+ iface->get_type = gst_fd_src_uri_get_type;
+ iface->get_protocols = gst_fd_src_uri_get_protocols;
+ iface->get_uri = gst_fd_src_uri_get_uri;
+ iface->set_uri = gst_fd_src_uri_set_uri;