aboutsummaryrefslogtreecommitdiff
path: root/plugins/elements/gstfilesrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/elements/gstfilesrc.c')
-rw-r--r--plugins/elements/gstfilesrc.c129
1 files changed, 65 insertions, 64 deletions
diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c
index 803530f..8f55d1f 100644
--- a/plugins/elements/gstfilesrc.c
+++ b/plugins/elements/gstfilesrc.c
@@ -130,8 +130,7 @@ enum
enum
{
PROP_0,
- PROP_LOCATION,
- PROP_FD
+ PROP_LOCATION
};
static void gst_file_src_finalize (GObject * object);
@@ -173,10 +172,6 @@ gst_file_src_class_init (GstFileSrcClass * klass)
gobject_class->set_property = gst_file_src_set_property;
gobject_class->get_property = gst_file_src_get_property;
- g_object_class_install_property (gobject_class, PROP_FD,
- g_param_spec_int ("fd", "File-descriptor",
- "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_LOCATION,
g_param_spec_string ("location", "File Location",
"Location of the file to read", NULL,
@@ -185,7 +180,7 @@ gst_file_src_class_init (GstFileSrcClass * klass)
gobject_class->finalize = gst_file_src_finalize;
- gst_element_class_set_details_simple (gstelement_class,
+ gst_element_class_set_static_metadata (gstelement_class,
"File Source",
"Source/File",
"Read from arbitrary point in a file",
@@ -214,6 +209,8 @@ gst_file_src_init (GstFileSrc * src)
src->uri = NULL;
src->is_regular = FALSE;
+
+ gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE);
}
static void
@@ -257,7 +254,7 @@ gst_file_src_set_location (GstFileSrc * src, const gchar * location)
GST_INFO ("uri : %s", src->uri);
}
g_object_notify (G_OBJECT (src), "location");
- gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
+ /* FIXME 0.11: notify "uri" property once there is one */
return TRUE;
@@ -305,9 +302,6 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_LOCATION:
g_value_set_string (value, src->filename);
break;
- case PROP_FD:
- g_value_set_int (value, src->fd);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -329,7 +323,9 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
GstBuffer * buf)
{
GstFileSrc *src;
+ guint to_read, bytes_read;
int ret;
+ GstMapInfo info;
guint8 *data;
src = GST_FILE_SRC_CAST (basesrc);
@@ -344,31 +340,42 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
src->read_position = offset;
}
- data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
-
- GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
- length, offset);
-
- ret = read (src->fd, data, length);
- if (G_UNLIKELY (ret < 0))
- goto could_not_read;
+ gst_buffer_map (buf, &info, GST_MAP_WRITE);
+ data = info.data;
+
+ bytes_read = 0;
+ to_read = length;
+ while (to_read > 0) {
+ GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
+ to_read, offset + bytes_read);
+ errno = 0;
+ ret = read (src->fd, data + bytes_read, to_read);
+ if (G_UNLIKELY (ret < 0)) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ goto could_not_read;
+ }
- /* seekable regular files should have given us what we expected */
- if (G_UNLIKELY ((guint) ret < length && src->seekable))
- goto unexpected_eos;
+ /* files should eos if they read 0 and more was requested */
+ if (G_UNLIKELY (ret == 0)) {
+ /* .. but first we should return any remaining data */
+ if (bytes_read > 0)
+ break;
+ goto eos;
+ }
- /* other files should eos if they read 0 and more was requested */
- if (G_UNLIKELY (ret == 0))
- goto eos;
+ to_read -= ret;
+ bytes_read += ret;
- length = ret;
+ src->read_position += ret;
+ }
- gst_buffer_unmap (buf, data, length);
+ gst_buffer_unmap (buf, &info);
+ if (bytes_read != length)
+ gst_buffer_resize (buf, 0, bytes_read);
GST_BUFFER_OFFSET (buf) = offset;
- GST_BUFFER_OFFSET_END (buf) = offset + length;
-
- src->read_position += length;
+ GST_BUFFER_OFFSET_END (buf) = offset + bytes_read;
return GST_FLOW_OK;
@@ -381,21 +388,16 @@ seek_failed:
could_not_read:
{
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
- gst_buffer_unmap (buf, data, 0);
- return GST_FLOW_ERROR;
- }
-unexpected_eos:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
- ("unexpected end of file."));
- gst_buffer_unmap (buf, data, 0);
+ gst_buffer_unmap (buf, &info);
+ gst_buffer_resize (buf, 0, 0);
return GST_FLOW_ERROR;
}
eos:
{
- GST_DEBUG ("non-regular file hits EOS");
- gst_buffer_unmap (buf, data, 0);
- return GST_FLOW_UNEXPECTED;
+ GST_DEBUG ("EOS");
+ gst_buffer_unmap (buf, &info);
+ gst_buffer_resize (buf, 0, 0);
+ return GST_FLOW_EOS;
}
}
@@ -518,7 +520,7 @@ no_filename:
{
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
(_("No file name specified for reading.")), (NULL));
- return FALSE;
+ goto error_exit;
}
open_failed:
{
@@ -533,29 +535,30 @@ open_failed:
GST_ERROR_SYSTEM);
break;
}
- return FALSE;
+ goto error_exit;
}
no_stat:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
(_("Could not get info on \"%s\"."), src->filename), (NULL));
- close (src->fd);
- return FALSE;
+ goto error_close;
}
was_directory:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
(_("\"%s\" is a directory."), src->filename), (NULL));
- close (src->fd);
- return FALSE;
+ goto error_close;
}
was_socket:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
(_("File \"%s\" is a socket."), src->filename), (NULL));
- close (src->fd);
- return FALSE;
+ goto error_close;
}
+error_close:
+ close (src->fd);
+error_exit:
+ return FALSE;
}
/* unmap and close the file */
@@ -582,29 +585,30 @@ gst_file_src_uri_get_type (GType type)
return GST_URI_SRC;
}
-static gchar **
+static const gchar *const *
gst_file_src_uri_get_protocols (GType type)
{
- static gchar *protocols[] = { (char *) "file", NULL };
+ static const gchar *protocols[] = { "file", NULL };
return protocols;
}
-static const gchar *
+static gchar *
gst_file_src_uri_get_uri (GstURIHandler * handler)
{
GstFileSrc *src = GST_FILE_SRC (handler);
- return src->uri;
+ /* FIXME: make thread-safe */
+ return g_strdup (src->uri);
}
static gboolean
-gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+ GError ** err)
{
gchar *location, *hostname = NULL;
gboolean ret = FALSE;
GstFileSrc *src = GST_FILE_SRC (handler);
- GError *error = NULL;
if (strcmp (uri, "file://") == 0) {
/* Special case for "file://" as this is used by some applications
@@ -614,22 +618,19 @@ gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
return TRUE;
}
- location = g_filename_from_uri (uri, &hostname, &error);
+ location = g_filename_from_uri (uri, &hostname, err);
- if (!location || error) {
- if (error) {
- GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
- error->message);
- g_error_free (error);
- } else {
- GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
- }
+ if (!location || (err != NULL && *err != NULL)) {
+ GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
+ (err != NULL && *err != NULL) ? (*err)->message : "unknown error");
goto beach;
}
if ((hostname) && (strcmp (hostname, "localhost"))) {
/* Only 'localhost' is permitted */
GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
+ g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+ "File URI with invalid hostname '%s'", hostname);
goto beach;
}
#ifdef G_OS_WIN32