gstreamer_core/plugins/elements/gstfilesrc.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    20  * Boston, MA 02111-1307, USA.
    20  * Boston, MA 02111-1307, USA.
    21  */
    21  */
    22 /**
    22 /**
    23  * SECTION:element-filesrc
    23  * SECTION:element-filesrc
       
    24  * @short_description: read from arbitrary point in a file
    24  * @see_also: #GstFileSrc
    25  * @see_also: #GstFileSrc
    25  *
    26  *
    26  * Read data from a file in the local file system.
    27  * Read data from a file in the local file system.
    27  */
    28  */
    28 
    29 
    29 #ifdef HAVE_CONFIG_H
    30 #ifdef HAVE_CONFIG_H
    30 #  include "config.h"
    31 #  include "config.h"
    31 #endif
    32 #endif
       
    33 #ifdef __SYMBIAN32__
       
    34 #include <gst_global.h>
       
    35 #endif
    32 
    36 
    33 #include <gst/gst.h>
    37 #include <gst/gst.h>
    34 #include "gstfilesrc.h"
    38 #include "gstfilesrc.h"
    35 
    39 
    36 #include <stdio.h>
    40 #include <stdio.h>
    37 #include <sys/types.h>
    41 #include <sys/types.h>
    38 #ifdef G_OS_WIN32
       
    39 #include <io.h>                 /* lseek, open, close, read */
       
    40 /* On win32, stat* default to 32 bit; we need the 64-bit
       
    41  * variants, so explicitly define it that way. */
       
    42 #define stat __stat64
       
    43 #define fstat _fstat64
       
    44 #undef lseek
       
    45 #define lseek _lseeki64
       
    46 #undef off_t
       
    47 #define off_t guint64
       
    48 /* Prevent stat.h from defining the stat* functions as
       
    49  * _stat*, since we're explicitly overriding that */
       
    50 #undef _INC_STAT_INL
       
    51 #endif
       
    52 #include <sys/stat.h>
    42 #include <sys/stat.h>
    53 #include <fcntl.h>
    43 #include <fcntl.h>
    54 
    44 
       
    45 #ifdef __SYMBIAN32__
       
    46 #include <glib_global.h>
       
    47 #include <gobject_global.h>
       
    48 #endif
       
    49 
    55 #ifdef HAVE_UNISTD_H
    50 #ifdef HAVE_UNISTD_H
    56 #  include <unistd.h>
    51 #  include <unistd.h>
    57 #endif
    52 #endif
    58 
    53 
    59 #ifdef HAVE_MMAP
    54 #ifdef HAVE_MMAP
    60 # include <sys/mman.h>
    55 # include <sys/mman.h>
    61 #endif
    56 #endif
    62 
    57 
       
    58 #ifdef HAVE_WIN32
       
    59 #  include <io.h>               /* lseek, open, close, read */
       
    60 #endif
       
    61 
    63 #include <errno.h>
    62 #include <errno.h>
    64 #include <string.h>
    63 #include <string.h>
    65 
    64 
    66 #include "../../gst/gst-i18n-lib.h"
    65 #include "../../gst/gst-i18n-lib.h"
       
    66 #include <gstelement.h>
    67 
    67 
    68 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    68 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    69     GST_PAD_SRC,
    69     GST_PAD_SRC,
    70     GST_PAD_ALWAYS,
    70     GST_PAD_ALWAYS,
    71     GST_STATIC_CAPS_ANY);
    71     GST_STATIC_CAPS_ANY);
    81 #define S_ISSOCK(x) (0)
    81 #define S_ISSOCK(x) (0)
    82 #endif
    82 #endif
    83 #ifndef O_BINARY
    83 #ifndef O_BINARY
    84 #define O_BINARY (0)
    84 #define O_BINARY (0)
    85 #endif
    85 #endif
    86 
       
    87 /* Copy of glib's g_open due to win32 libc/cross-DLL brokenness: we can't
       
    88  * use the 'file descriptor' opened in glib (and returned from this function)
       
    89  * in this library, as they may have unrelated C runtimes. */
       
    90 #ifdef __SYMBIAN32__
       
    91 EXPORT_C
       
    92 #endif
       
    93 
       
    94 int
       
    95 gst_open (const gchar * filename, int flags, int mode)
       
    96 {
       
    97 #ifdef G_OS_WIN32
       
    98   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
       
    99   int retval;
       
   100   int save_errno;
       
   101 
       
   102   if (wfilename == NULL) {
       
   103     errno = EINVAL;
       
   104     return -1;
       
   105   }
       
   106 
       
   107   retval = _wopen (wfilename, flags, mode);
       
   108   save_errno = errno;
       
   109 
       
   110   g_free (wfilename);
       
   111 
       
   112   errno = save_errno;
       
   113   return retval;
       
   114 #else
       
   115   return open (filename, flags, mode);
       
   116 #endif
       
   117 }
       
   118 
    86 
   119 
    87 
   120 /**********************************************************************
    88 /**********************************************************************
   121  * GStreamer Default File Source
    89  * GStreamer Default File Source
   122  * Theory of Operation
    90  * Theory of Operation
   195 
   163 
   196 static gboolean gst_file_src_is_seekable (GstBaseSrc * src);
   164 static gboolean gst_file_src_is_seekable (GstBaseSrc * src);
   197 static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size);
   165 static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size);
   198 static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
   166 static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
   199     guint length, GstBuffer ** buffer);
   167     guint length, GstBuffer ** buffer);
   200 static gboolean gst_file_src_query (GstBaseSrc * src, GstQuery * query);
       
   201 
   168 
   202 static void gst_file_src_uri_handler_init (gpointer g_iface,
   169 static void gst_file_src_uri_handler_init (gpointer g_iface,
   203     gpointer iface_data);
   170     gpointer iface_data);
   204 
   171 
   205 static void
   172 static void
   235 
   202 
   236 static void
   203 static void
   237 gst_file_src_class_init (GstFileSrcClass * klass)
   204 gst_file_src_class_init (GstFileSrcClass * klass)
   238 {
   205 {
   239   GObjectClass *gobject_class;
   206   GObjectClass *gobject_class;
       
   207   GstElementClass *gstelement_class;
   240   GstBaseSrcClass *gstbasesrc_class;
   208   GstBaseSrcClass *gstbasesrc_class;
   241 
   209 
   242   gobject_class = G_OBJECT_CLASS (klass);
   210   gobject_class = G_OBJECT_CLASS (klass);
       
   211   gstelement_class = GST_ELEMENT_CLASS (klass);
   243   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
   212   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
   244 
   213 
   245   gobject_class->set_property = gst_file_src_set_property;
   214   gobject_class->set_property = gst_file_src_set_property;
   246   gobject_class->get_property = gst_file_src_get_property;
   215   gobject_class->get_property = gst_file_src_get_property;
   247 
   216 
   248   g_object_class_install_property (gobject_class, ARG_FD,
   217   g_object_class_install_property (gobject_class, ARG_FD,
   249       g_param_spec_int ("fd", "File-descriptor",
   218       g_param_spec_int ("fd", "File-descriptor",
   250           "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
   219           "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
   251           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   220           G_PARAM_READABLE));
   252   g_object_class_install_property (gobject_class, ARG_LOCATION,
   221   g_object_class_install_property (gobject_class, ARG_LOCATION,
   253       g_param_spec_string ("location", "File Location",
   222       g_param_spec_string ("location", "File Location",
   254           "Location of the file to read", NULL,
   223           "Location of the file to read", NULL, G_PARAM_READWRITE));
   255           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
       
   256           GST_PARAM_MUTABLE_READY));
       
   257   g_object_class_install_property (gobject_class, ARG_MMAPSIZE,
   224   g_object_class_install_property (gobject_class, ARG_MMAPSIZE,
   258       g_param_spec_ulong ("mmapsize", "mmap() Block Size",
   225       g_param_spec_ulong ("mmapsize", "mmap() Block Size",
   259           "Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
   226           "Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
   260           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
   227           G_PARAM_READWRITE));
   261           GST_PARAM_MUTABLE_PLAYING));
       
   262   g_object_class_install_property (gobject_class, ARG_TOUCH,
   228   g_object_class_install_property (gobject_class, ARG_TOUCH,
   263       g_param_spec_boolean ("touch", "Touch mapped region read data",
   229       g_param_spec_boolean ("touch", "Touch mapped region read data",
   264           "Touch mmapped data regions to force them to be read from disk",
   230           "Touch mmapped data regions to force them to be read from disk",
   265           DEFAULT_TOUCH,
   231           DEFAULT_TOUCH, G_PARAM_READWRITE));
   266           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
       
   267           GST_PARAM_MUTABLE_PLAYING));
       
   268   /**
   232   /**
   269    * GstFileSrc:use-mmap
   233    * GstFileSrc:use-mmap
   270    *
   234    *
   271    * Whether to use mmap(). Set to TRUE to force use of mmap() instead of
   235    * Whether to use mmap(). Set to TRUE to force use of mmap() instead of
   272    * read() for reading data.
   236    * read() for reading data.
   284    *
   248    *
   285    **/
   249    **/
   286   g_object_class_install_property (gobject_class, ARG_USEMMAP,
   250   g_object_class_install_property (gobject_class, ARG_USEMMAP,
   287       g_param_spec_boolean ("use-mmap", "Use mmap to read data",
   251       g_param_spec_boolean ("use-mmap", "Use mmap to read data",
   288           "Whether to use mmap() instead of read()",
   252           "Whether to use mmap() instead of read()",
   289           DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
   253           DEFAULT_USEMMAP, G_PARAM_READWRITE));
   290           GST_PARAM_MUTABLE_READY));
       
   291   g_object_class_install_property (gobject_class, ARG_SEQUENTIAL,
   254   g_object_class_install_property (gobject_class, ARG_SEQUENTIAL,
   292       g_param_spec_boolean ("sequential", "Optimise for sequential mmap access",
   255       g_param_spec_boolean ("sequential", "Optimise for sequential mmap access",
   293           "Whether to use madvise to hint to the kernel that access to "
   256           "Whether to use madvise to hint to the kernel that access to "
   294           "mmap pages will be sequential",
   257           "mmap pages will be sequential",
   295           DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
   258           DEFAULT_SEQUENTIAL, G_PARAM_READWRITE));
   296           GST_PARAM_MUTABLE_PLAYING));
       
   297 
   259 
   298   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize);
   260   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize);
   299 
   261 
   300   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start);
   262   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start);
   301   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop);
   263   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop);
   302   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
   264   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
   303   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
   265   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
   304   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
   266   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
   305   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_file_src_query);
       
   306 
   267 
   307   if (sizeof (off_t) < 8) {
   268   if (sizeof (off_t) < 8) {
   308     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
   269     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
   309         sizeof (off_t));
   270         sizeof (off_t));
   310   }
   271   }
   362   /* clear the filename if we get a NULL (is that possible?) */
   323   /* clear the filename if we get a NULL (is that possible?) */
   363   if (location == NULL) {
   324   if (location == NULL) {
   364     src->filename = NULL;
   325     src->filename = NULL;
   365     src->uri = NULL;
   326     src->uri = NULL;
   366   } else {
   327   } else {
   367     /* we store the filename as received by the application. On Windoes this
       
   368      * should be UTF8 */
       
   369     src->filename = g_strdup (location);
   328     src->filename = g_strdup (location);
   370     src->uri = gst_uri_construct ("file", src->filename);
   329     src->uri = gst_uri_construct ("file", src->filename);
   371   }
   330   }
   372   g_object_notify (G_OBJECT (src), "location");
   331   g_object_notify (G_OBJECT (src), "location");
   373   gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
   332   gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
   375   return TRUE;
   334   return TRUE;
   376 
   335 
   377   /* ERROR */
   336   /* ERROR */
   378 wrong_state:
   337 wrong_state:
   379   {
   338   {
   380     g_warning ("Changing the `location' property on filesink when a file is "
   339     GST_DEBUG_OBJECT (src, "setting location in wrong state");
   381         "open is not supported.");
       
   382     GST_OBJECT_UNLOCK (src);
   340     GST_OBJECT_UNLOCK (src);
   383     return FALSE;
   341     return FALSE;
   384   }
   342   }
   385 }
   343 }
   386 
   344 
   574   /* cast to unsigned long, since there's no gportable way to print
   532   /* cast to unsigned long, since there's no gportable way to print
   575    * guint64 as hex */
   533    * guint64 as hex */
   576   GST_LOG ("unmapped region %08lx+%08lx at %p",
   534   GST_LOG ("unmapped region %08lx+%08lx at %p",
   577       (gulong) offset, (gulong) size, data);
   535       (gulong) offset, (gulong) size, data);
   578 
   536 
   579   GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->finalize (GST_MINI_OBJECT
   537   GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->
   580       (mmap_buffer));
   538       finalize (GST_MINI_OBJECT (mmap_buffer));
   581 }
   539 }
   582 
   540 
   583 static GstBuffer *
   541 static GstBuffer *
   584 gst_file_src_map_region (GstFileSrc * src, off_t offset, gsize size,
   542 gst_file_src_map_region (GstFileSrc * src, off_t offset, gsize size,
   585     gboolean testonly)
   543     gboolean testonly)
   607   GST_MMAP_BUFFER (buf)->filesrc = src;
   565   GST_MMAP_BUFFER (buf)->filesrc = src;
   608 
   566 
   609 #ifdef MADV_SEQUENTIAL
   567 #ifdef MADV_SEQUENTIAL
   610   if (src->sequential) {
   568   if (src->sequential) {
   611     /* madvise to tell the kernel what to do with it */
   569     /* madvise to tell the kernel what to do with it */
       
   570   #ifndef __SYMBIAN32__
   612     if (madvise (mmapregion, size, MADV_SEQUENTIAL) < 0) {
   571     if (madvise (mmapregion, size, MADV_SEQUENTIAL) < 0) {
   613       GST_WARNING_OBJECT (src, "warning: madvise failed: %s",
   572       GST_WARNING_OBJECT (src, "warning: madvise failed: %s",
   614           g_strerror (errno));
   573           g_strerror (errno));
   615     }
   574     }
   616   }
   575   #endif
   617 #endif
   576 #endif
   618 
   577 
   619   /* fill in the rest of the fields */
   578   /* fill in the rest of the fields */
   620   GST_BUFFER_SIZE (buf) = size;
   579   GST_BUFFER_SIZE (buf) = size;
   621   GST_BUFFER_OFFSET (buf) = offset;
   580   GST_BUFFER_OFFSET (buf) = offset;
   831       goto seek_failed;
   790       goto seek_failed;
   832 
   791 
   833     src->read_position = offset;
   792     src->read_position = offset;
   834   }
   793   }
   835 
   794 
   836   buf = gst_buffer_try_new_and_alloc (length);
   795   buf = gst_buffer_new_and_alloc (length);
   837   if (G_UNLIKELY (buf == NULL && length > 0)) {
   796 
   838     GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
   797   GST_LOG_OBJECT (src, "Reading %d bytes", length);
   839     return GST_FLOW_ERROR;
       
   840   }
       
   841 
       
   842   GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
       
   843       length, offset);
       
   844   ret = read (src->fd, GST_BUFFER_DATA (buf), length);
   798   ret = read (src->fd, GST_BUFFER_DATA (buf), length);
   845   if (G_UNLIKELY (ret < 0))
   799   if (G_UNLIKELY (ret < 0))
   846     goto could_not_read;
   800     goto could_not_read;
   847 
   801 
   848   /* seekable regular files should have given us what we expected */
   802   /* seekable regular files should have given us what we expected */
   913 
   867 
   914   return ret;
   868   return ret;
   915 }
   869 }
   916 
   870 
   917 static gboolean
   871 static gboolean
   918 gst_file_src_query (GstBaseSrc * basesrc, GstQuery * query)
       
   919 {
       
   920   gboolean ret = FALSE;
       
   921   GstFileSrc *src = GST_FILE_SRC (basesrc);
       
   922 
       
   923   switch (GST_QUERY_TYPE (query)) {
       
   924     case GST_QUERY_URI:
       
   925       gst_query_set_uri (query, src->uri);
       
   926       ret = TRUE;
       
   927       break;
       
   928     default:
       
   929       ret = FALSE;
       
   930       break;
       
   931   }
       
   932 
       
   933   if (!ret)
       
   934     ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
       
   935 
       
   936   return ret;
       
   937 }
       
   938 
       
   939 static gboolean
       
   940 gst_file_src_is_seekable (GstBaseSrc * basesrc)
   872 gst_file_src_is_seekable (GstBaseSrc * basesrc)
   941 {
   873 {
   942   GstFileSrc *src = GST_FILE_SRC (basesrc);
   874   GstFileSrc *src = GST_FILE_SRC (basesrc);
   943 
   875 
   944   return src->seekable;
   876   return src->seekable;
   983     goto no_filename;
   915     goto no_filename;
   984 
   916 
   985   GST_INFO_OBJECT (src, "opening file %s", src->filename);
   917   GST_INFO_OBJECT (src, "opening file %s", src->filename);
   986 
   918 
   987   /* open the file */
   919   /* open the file */
   988   src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0);
   920   src->fd = open (src->filename, O_RDONLY | O_BINARY);
   989 
       
   990   if (src->fd < 0)
   921   if (src->fd < 0)
   991     goto open_failed;
   922     goto open_failed;
   992 
   923 
   993   /* check if it is a regular file, otherwise bail out */
   924   /* check if it is a regular file, otherwise bail out */
   994   if (fstat (src->fd, &stat_results) < 0)
   925   if (fstat (src->fd, &stat_results) < 0)
  1106 
  1037 
  1107   return TRUE;
  1038   return TRUE;
  1108 }
  1039 }
  1109 
  1040 
  1110 /*** GSTURIHANDLER INTERFACE *************************************************/
  1041 /*** GSTURIHANDLER INTERFACE *************************************************/
  1111 
       
  1112 #ifdef __SYMBIAN32__
  1042 #ifdef __SYMBIAN32__
  1113 GstURIType
  1043 GstURIType
  1114 #else
  1044 #else
  1115 static GstURIType
  1045 static guint
  1116 #endif 
  1046 #endif 
  1117 gst_file_src_uri_get_type (void)
  1047 gst_file_src_uri_get_type (void)
  1118 {
  1048 {
  1119   return GST_URI_SRC;
  1049   return GST_URI_SRC;
  1120 }
  1050 }
  1121 
       
  1122 static gchar **
  1051 static gchar **
  1123 gst_file_src_uri_get_protocols (void)
  1052 gst_file_src_uri_get_protocols (void)
  1124 {
  1053 {
  1125   static gchar *protocols[] = { "file", NULL };
  1054   static gchar *protocols[] = { "file", NULL };
  1126 
  1055 
  1127   return protocols;
  1056   return protocols;
  1128 }
  1057 }
  1129 
       
  1130 static const gchar *
  1058 static const gchar *
  1131 gst_file_src_uri_get_uri (GstURIHandler * handler)
  1059 gst_file_src_uri_get_uri (GstURIHandler * handler)
  1132 {
  1060 {
  1133   GstFileSrc *src = GST_FILE_SRC (handler);
  1061   GstFileSrc *src = GST_FILE_SRC (handler);
  1134 
  1062 
  1136 }
  1064 }
  1137 
  1065 
  1138 static gboolean
  1066 static gboolean
  1139 gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
  1067 gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
  1140 {
  1068 {
  1141   gchar *location, *hostname = NULL;
  1069   gchar *protocol, *location;
  1142   gboolean ret = FALSE;
  1070   gboolean ret;
  1143   GstFileSrc *src = GST_FILE_SRC (handler);
  1071   GstFileSrc *src = GST_FILE_SRC (handler);
  1144   GError *error = NULL;
  1072 
  1145 
  1073   protocol = gst_uri_get_protocol (uri);
  1146   if (strcmp (uri, "file://") == 0) {
  1074   if (strcmp (protocol, "file") != 0) {
       
  1075     g_free (protocol);
       
  1076     return FALSE;
       
  1077   }
       
  1078   g_free (protocol);
       
  1079 
       
  1080   /* allow file://localhost/foo/bar by stripping localhost but fail
       
  1081    * for every other hostname */
       
  1082   if (g_str_has_prefix (uri, "file://localhost/")) {
       
  1083     char *tmp;
       
  1084 
       
  1085     /* 16 == strlen ("file://localhost") */
       
  1086     tmp = g_strconcat ("file://", uri + 16, NULL);
       
  1087     /* we use gst_uri_get_location() although we already have the
       
  1088      * "location" with uri + 16 because it provides unescaping */
       
  1089     location = gst_uri_get_location (tmp);
       
  1090     g_free (tmp);
       
  1091   } else if (strcmp (uri, "file://") == 0) {
  1147     /* Special case for "file://" as this is used by some applications
  1092     /* Special case for "file://" as this is used by some applications
  1148      *  to test with gst_element_make_from_uri if there's an element
  1093      *  to test with gst_element_make_from_uri if there's an element
  1149      *  that supports the URI protocol. */
  1094      *  that supports the URI protocol. */
  1150     gst_file_src_set_location (src, NULL);
  1095     gst_file_src_set_location (src, NULL);
  1151     return TRUE;
  1096     return TRUE;
  1152   }
  1097   } else {
  1153 
  1098     location = gst_uri_get_location (uri);
  1154   location = g_filename_from_uri (uri, &hostname, &error);
  1099   }
  1155 
  1100 
  1156   if (!location || error) {
  1101   if (!location)
  1157     if (error) {
  1102     return FALSE;
  1158       GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
  1103   if (!g_path_is_absolute (location)) {
  1159           error->message);
  1104     g_free (location);
  1160       g_error_free (error);
  1105     return FALSE;
  1161     } else {
  1106   }
  1162       GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
       
  1163     }
       
  1164     goto beach;
       
  1165   }
       
  1166 
       
  1167   if ((hostname) && (strcmp (hostname, "localhost"))) {
       
  1168     /* Only 'localhost' is permitted */
       
  1169     GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
       
  1170     goto beach;
       
  1171   }
       
  1172 #ifdef G_OS_WIN32
       
  1173   /* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths
       
  1174    * correctly on windows, it leaves them with an extra backslash
       
  1175    * at the start if they're of the mozilla-style file://///host/path/file 
       
  1176    * form. Correct this.
       
  1177    */
       
  1178   if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\')
       
  1179     g_memmove (location, location + 1, strlen (location + 1) + 1);
       
  1180 #endif
       
  1181 
  1107 
  1182   ret = gst_file_src_set_location (src, location);
  1108   ret = gst_file_src_set_location (src, location);
  1183 
  1109   g_free (location);
  1184 beach:
       
  1185   if (location)
       
  1186     g_free (location);
       
  1187   if (hostname)
       
  1188     g_free (hostname);
       
  1189 
  1110 
  1190   return ret;
  1111   return ret;
  1191 }
  1112 }
  1192 
  1113 
  1193 static void
  1114 static void