--- a/gstreamer_core/plugins/elements/gstfilesrc.c Tue Aug 31 15:30:33 2010 +0300
+++ b/gstreamer_core/plugins/elements/gstfilesrc.c Wed Sep 01 12:16:41 2010 +0100
@@ -21,6 +21,7 @@
*/
/**
* SECTION:element-filesrc
+ * @short_description: read from arbitrary point in a file
* @see_also: #GstFileSrc
*
* Read data from a file in the local file system.
@@ -29,29 +30,23 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#ifdef __SYMBIAN32__
+#include <gst_global.h>
+#endif
#include <gst/gst.h>
#include "gstfilesrc.h"
#include <stdio.h>
#include <sys/types.h>
-#ifdef G_OS_WIN32
-#include <io.h> /* lseek, open, close, read */
-/* On win32, stat* default to 32 bit; we need the 64-bit
- * variants, so explicitly define it that way. */
-#define stat __stat64
-#define fstat _fstat64
-#undef lseek
-#define lseek _lseeki64
-#undef off_t
-#define off_t guint64
-/* Prevent stat.h from defining the stat* functions as
- * _stat*, since we're explicitly overriding that */
-#undef _INC_STAT_INL
-#endif
#include <sys/stat.h>
#include <fcntl.h>
+#ifdef __SYMBIAN32__
+#include <glib_global.h>
+#include <gobject_global.h>
+#endif
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -60,10 +55,15 @@
# include <sys/mman.h>
#endif
+#ifdef HAVE_WIN32
+# include <io.h> /* lseek, open, close, read */
+#endif
+
#include <errno.h>
#include <string.h>
#include "../../gst/gst-i18n-lib.h"
+#include <gstelement.h>
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
@@ -84,38 +84,6 @@
#define O_BINARY (0)
#endif
-/* Copy of glib's g_open due to win32 libc/cross-DLL brokenness: we can't
- * use the 'file descriptor' opened in glib (and returned from this function)
- * in this library, as they may have unrelated C runtimes. */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-int
-gst_open (const gchar * filename, int flags, int mode)
-{
-#ifdef G_OS_WIN32
- wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
- int retval;
- int save_errno;
-
- if (wfilename == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- retval = _wopen (wfilename, flags, mode);
- save_errno = errno;
-
- g_free (wfilename);
-
- errno = save_errno;
- return retval;
-#else
- return open (filename, flags, mode);
-#endif
-}
-
/**********************************************************************
* GStreamer Default File Source
@@ -197,7 +165,6 @@
static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size);
static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
guint length, GstBuffer ** buffer);
-static gboolean gst_file_src_query (GstBaseSrc * src, GstQuery * query);
static void gst_file_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
@@ -237,9 +204,11 @@
gst_file_src_class_init (GstFileSrcClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
gobject_class = G_OBJECT_CLASS (klass);
+ gstelement_class = GST_ELEMENT_CLASS (klass);
gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
gobject_class->set_property = gst_file_src_set_property;
@@ -248,23 +217,18 @@
g_object_class_install_property (gobject_class, ARG_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_PARAM_READABLE));
g_object_class_install_property (gobject_class, ARG_LOCATION,
g_param_spec_string ("location", "File Location",
- "Location of the file to read", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
- GST_PARAM_MUTABLE_READY));
+ "Location of the file to read", NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_MMAPSIZE,
g_param_spec_ulong ("mmapsize", "mmap() Block Size",
"Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
- GST_PARAM_MUTABLE_PLAYING));
+ G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_TOUCH,
g_param_spec_boolean ("touch", "Touch mapped region read data",
"Touch mmapped data regions to force them to be read from disk",
- DEFAULT_TOUCH,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
- GST_PARAM_MUTABLE_PLAYING));
+ DEFAULT_TOUCH, G_PARAM_READWRITE));
/**
* GstFileSrc:use-mmap
*
@@ -286,14 +250,12 @@
g_object_class_install_property (gobject_class, ARG_USEMMAP,
g_param_spec_boolean ("use-mmap", "Use mmap to read data",
"Whether to use mmap() instead of read()",
- DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
- GST_PARAM_MUTABLE_READY));
+ DEFAULT_USEMMAP, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_SEQUENTIAL,
g_param_spec_boolean ("sequential", "Optimise for sequential mmap access",
"Whether to use madvise to hint to the kernel that access to "
"mmap pages will be sequential",
- DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
- GST_PARAM_MUTABLE_PLAYING));
+ DEFAULT_SEQUENTIAL, G_PARAM_READWRITE));
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize);
@@ -302,7 +264,6 @@
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
- gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_file_src_query);
if (sizeof (off_t) < 8) {
GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
@@ -364,8 +325,6 @@
src->filename = NULL;
src->uri = NULL;
} else {
- /* we store the filename as received by the application. On Windoes this
- * should be UTF8 */
src->filename = g_strdup (location);
src->uri = gst_uri_construct ("file", src->filename);
}
@@ -377,8 +336,7 @@
/* ERROR */
wrong_state:
{
- g_warning ("Changing the `location' property on filesink when a file is "
- "open is not supported.");
+ GST_DEBUG_OBJECT (src, "setting location in wrong state");
GST_OBJECT_UNLOCK (src);
return FALSE;
}
@@ -576,8 +534,8 @@
GST_LOG ("unmapped region %08lx+%08lx at %p",
(gulong) offset, (gulong) size, data);
- GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->finalize (GST_MINI_OBJECT
- (mmap_buffer));
+ GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->
+ finalize (GST_MINI_OBJECT (mmap_buffer));
}
static GstBuffer *
@@ -609,11 +567,12 @@
#ifdef MADV_SEQUENTIAL
if (src->sequential) {
/* madvise to tell the kernel what to do with it */
+ #ifndef __SYMBIAN32__
if (madvise (mmapregion, size, MADV_SEQUENTIAL) < 0) {
GST_WARNING_OBJECT (src, "warning: madvise failed: %s",
g_strerror (errno));
}
- }
+ #endif
#endif
/* fill in the rest of the fields */
@@ -833,14 +792,9 @@
src->read_position = offset;
}
- buf = gst_buffer_try_new_and_alloc (length);
- if (G_UNLIKELY (buf == NULL && length > 0)) {
- GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
- return GST_FLOW_ERROR;
- }
+ buf = gst_buffer_new_and_alloc (length);
- GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
- length, offset);
+ GST_LOG_OBJECT (src, "Reading %d bytes", length);
ret = read (src->fd, GST_BUFFER_DATA (buf), length);
if (G_UNLIKELY (ret < 0))
goto could_not_read;
@@ -915,28 +869,6 @@
}
static gboolean
-gst_file_src_query (GstBaseSrc * basesrc, GstQuery * query)
-{
- gboolean ret = FALSE;
- GstFileSrc *src = GST_FILE_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_file_src_is_seekable (GstBaseSrc * basesrc)
{
GstFileSrc *src = GST_FILE_SRC (basesrc);
@@ -985,8 +917,7 @@
GST_INFO_OBJECT (src, "opening file %s", src->filename);
/* open the file */
- src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0);
-
+ src->fd = open (src->filename, O_RDONLY | O_BINARY);
if (src->fd < 0)
goto open_failed;
@@ -1108,17 +1039,15 @@
}
/*** GSTURIHANDLER INTERFACE *************************************************/
-
#ifdef __SYMBIAN32__
GstURIType
#else
-static GstURIType
+static guint
#endif
gst_file_src_uri_get_type (void)
{
return GST_URI_SRC;
}
-
static gchar **
gst_file_src_uri_get_protocols (void)
{
@@ -1126,7 +1055,6 @@
return protocols;
}
-
static const gchar *
gst_file_src_uri_get_uri (GstURIHandler * handler)
{
@@ -1138,54 +1066,47 @@
static gboolean
gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
- gchar *location, *hostname = NULL;
- gboolean ret = FALSE;
+ gchar *protocol, *location;
+ gboolean ret;
GstFileSrc *src = GST_FILE_SRC (handler);
- GError *error = NULL;
+
+ protocol = gst_uri_get_protocol (uri);
+ if (strcmp (protocol, "file") != 0) {
+ g_free (protocol);
+ return FALSE;
+ }
+ g_free (protocol);
- if (strcmp (uri, "file://") == 0) {
+ /* allow file://localhost/foo/bar by stripping localhost but fail
+ * for every other hostname */
+ if (g_str_has_prefix (uri, "file://localhost/")) {
+ char *tmp;
+
+ /* 16 == strlen ("file://localhost") */
+ tmp = g_strconcat ("file://", uri + 16, NULL);
+ /* we use gst_uri_get_location() although we already have the
+ * "location" with uri + 16 because it provides unescaping */
+ location = gst_uri_get_location (tmp);
+ g_free (tmp);
+ } else if (strcmp (uri, "file://") == 0) {
/* Special case for "file://" as this is used by some applications
* to test with gst_element_make_from_uri if there's an element
* that supports the URI protocol. */
gst_file_src_set_location (src, NULL);
return TRUE;
- }
-
- location = g_filename_from_uri (uri, &hostname, &error);
-
- 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);
- }
- goto beach;
+ } else {
+ location = gst_uri_get_location (uri);
}
- if ((hostname) && (strcmp (hostname, "localhost"))) {
- /* Only 'localhost' is permitted */
- GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
- goto beach;
+ if (!location)
+ return FALSE;
+ if (!g_path_is_absolute (location)) {
+ g_free (location);
+ return FALSE;
}
-#ifdef G_OS_WIN32
- /* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths
- * correctly on windows, it leaves them with an extra backslash
- * at the start if they're of the mozilla-style file://///host/path/file
- * form. Correct this.
- */
- if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\')
- g_memmove (location, location + 1, strlen (location + 1) + 1);
-#endif
ret = gst_file_src_set_location (src, location);
-
-beach:
- if (location)
- g_free (location);
- if (hostname)
- g_free (hostname);
+ g_free (location);
return ret;
}