mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
support nonregular files (#140734)
Original commit message from CVS: support nonregular files (#140734)
This commit is contained in:
parent
e40680565f
commit
48e3fbd44f
5 changed files with 141 additions and 50 deletions
|
@ -1,3 +1,12 @@
|
|||
2004-04-21 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* gst/elements/gstfilesrc.c: (gst_filesrc_init),
|
||||
(gst_filesrc_get_mmap), (gst_filesrc_get_read), (gst_filesrc_get),
|
||||
(gst_filesrc_open_file), (gst_filesrc_close_file),
|
||||
(gst_filesrc_srcpad_query), (gst_filesrc_srcpad_event):
|
||||
* gst/elements/gstfilesrc.h:
|
||||
add support for non-regular files (#140734)
|
||||
|
||||
2004-04-21 Benjamin Otte <otte@gnome.org>
|
||||
|
||||
* gst/gstpad.c: (gst_pad_link_fixate):
|
||||
|
|
|
@ -245,6 +245,8 @@ gst_filesrc_init (GstFileSrc * src)
|
|||
|
||||
src->mapbuf = NULL;
|
||||
src->mapsize = DEFAULT_MMAPSIZE; /* default is 4MB */
|
||||
|
||||
src->is_regular = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -470,11 +472,11 @@ gst_filesrc_map_small_region (GstFileSrc * src, off_t offset, size_t size)
|
|||
#ifdef HAVE_MMAP
|
||||
/**
|
||||
* gst_filesrc_get_mmap:
|
||||
* @pad: #GstPad to push a buffer from
|
||||
* @src: #GstElement to get data from
|
||||
*
|
||||
* Push a new buffer from the filesrc at the current offset.
|
||||
* Returns: a new #GstData from the mmap'd source.
|
||||
*/
|
||||
static GstBuffer *
|
||||
static GstData *
|
||||
gst_filesrc_get_mmap (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
|
@ -601,11 +603,11 @@ gst_filesrc_get_mmap (GstFileSrc * src)
|
|||
/* we're done, return the buffer */
|
||||
g_assert (src->curoffset == GST_BUFFER_OFFSET (buf));
|
||||
src->curoffset += GST_BUFFER_SIZE (buf);
|
||||
return buf;
|
||||
return GST_DATA (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static GstBuffer *
|
||||
static GstData *
|
||||
gst_filesrc_get_read (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
|
@ -613,26 +615,40 @@ gst_filesrc_get_read (GstFileSrc * src)
|
|||
int ret;
|
||||
|
||||
readsize = src->block_size;
|
||||
if (src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| src->curoffset + readsize > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
/* for regular files, we can use the filesize to check how much we
|
||||
can read */
|
||||
if (src->is_regular) {
|
||||
if (src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| src->curoffset + readsize > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (readsize);
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
GST_LOG_OBJECT (src, "Reading %d bytes", readsize);
|
||||
ret = read (src->fd, GST_BUFFER_DATA (buf), readsize);
|
||||
if (ret < 0) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
|
||||
return NULL;
|
||||
}
|
||||
if (ret < readsize) {
|
||||
/* regular files should have given us what we expected */
|
||||
if (ret < readsize && src->is_regular) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||
("unexpected end of file."));
|
||||
return NULL;
|
||||
}
|
||||
/* other files should eos if they read 0 */
|
||||
if (ret == 0) {
|
||||
GST_DEBUG ("non-regular file hits EOS");
|
||||
gst_buffer_unref (buf);
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
readsize = ret;
|
||||
|
||||
GST_BUFFER_SIZE (buf) = readsize;
|
||||
GST_BUFFER_MAXSIZE (buf) = readsize;
|
||||
|
@ -640,7 +656,7 @@ gst_filesrc_get_read (GstFileSrc * src)
|
|||
GST_BUFFER_OFFSET_END (buf) = src->curoffset + readsize;
|
||||
src->curoffset += readsize;
|
||||
|
||||
return buf;
|
||||
return GST_DATA (buf);
|
||||
}
|
||||
|
||||
static GstData *
|
||||
|
@ -670,24 +686,27 @@ gst_filesrc_get (GstPad * pad)
|
|||
return GST_DATA (event);
|
||||
}
|
||||
|
||||
/* check for EOF */
|
||||
g_assert (src->curoffset <= src->filelen);
|
||||
if (src->curoffset == src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset >= src->filelen) {
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
/* check for EOF if it's a regular file */
|
||||
if (src->is_regular) {
|
||||
g_assert (src->curoffset <= src->filelen);
|
||||
if (src->curoffset == src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset >= src->filelen) {
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
}
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MMAP
|
||||
if (src->using_mmap) {
|
||||
return GST_DATA (gst_filesrc_get_mmap (src));
|
||||
return gst_filesrc_get_mmap (src);
|
||||
} else {
|
||||
return GST_DATA (gst_filesrc_get_read (src));
|
||||
return gst_filesrc_get_read (src);
|
||||
}
|
||||
#else
|
||||
return GST_DATA (gst_filesrc_get_read (src));
|
||||
return gst_filesrc_get_read (src);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -740,9 +759,15 @@ gst_filesrc_open_file (GstFileSrc * src)
|
|||
|
||||
fstat (src->fd, &stat_results);
|
||||
|
||||
if (!S_ISREG (stat_results.st_mode)) {
|
||||
if (S_ISDIR (stat_results.st_mode)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("File \"%s\" isn't a regular file."), src->filename), (NULL));
|
||||
(_("\"%s\" is a directory."), src->filename), (NULL));
|
||||
close (src->fd);
|
||||
return FALSE;
|
||||
}
|
||||
if (S_ISSOCK (stat_results.st_mode)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("File \"%s\" is a socket."), src->filename), (NULL));
|
||||
close (src->fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -751,15 +776,20 @@ gst_filesrc_open_file (GstFileSrc * src)
|
|||
src->filelen = stat_results.st_size;
|
||||
|
||||
src->using_mmap = FALSE;
|
||||
|
||||
/* record if it's a regular (hence seekable and lengthable) file */
|
||||
if (S_ISREG (stat_results.st_mode))
|
||||
src->is_regular = TRUE;
|
||||
#ifdef HAVE_MMAP
|
||||
/* allocate the first mmap'd region */
|
||||
/* FIXME: maybe we should only try to mmap if it's a regular file */
|
||||
/* allocate the first mmap'd region if it's a regular file ? */
|
||||
src->mapbuf = gst_filesrc_map_region (src, 0, src->mapsize);
|
||||
if (src->mapbuf != NULL) {
|
||||
GST_DEBUG_OBJECT (src, "using mmap for file");
|
||||
src->using_mmap = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
src->curoffset = 0;
|
||||
|
||||
GST_FLAG_SET (src, GST_FILESRC_OPEN);
|
||||
|
@ -780,6 +810,7 @@ gst_filesrc_close_file (GstFileSrc * src)
|
|||
src->fd = 0;
|
||||
src->filelen = 0;
|
||||
src->curoffset = 0;
|
||||
src->is_regular = FALSE;
|
||||
|
||||
if (src->mapbuf) {
|
||||
gst_buffer_unref (src->mapbuf);
|
||||
|
@ -833,6 +864,8 @@ gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
|||
if (*format != GST_FORMAT_BYTES) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!src->is_regular)
|
||||
return FALSE;
|
||||
gst_filesrc_check_filesize (src);
|
||||
*value = src->filelen;
|
||||
break;
|
||||
|
@ -844,6 +877,8 @@ gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
|||
case GST_FORMAT_PERCENT:
|
||||
if (src->filelen == 0)
|
||||
return FALSE;
|
||||
if (!src->is_regular)
|
||||
return FALSE;
|
||||
*value = src->curoffset * GST_FORMAT_PERCENT_MAX / src->filelen;
|
||||
break;
|
||||
default:
|
||||
|
@ -872,6 +907,10 @@ gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event)
|
|||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
goto error;
|
||||
}
|
||||
if (!src->is_regular) {
|
||||
GST_DEBUG ("can't handle seek on a non-regular file");
|
||||
goto error;
|
||||
}
|
||||
|
||||
offset = GST_EVENT_SEEK_OFFSET (event);
|
||||
|
||||
|
|
|
@ -65,7 +65,9 @@ struct _GstFileSrc {
|
|||
off_t curoffset; /* current offset in file*/
|
||||
off_t block_size; /* bytes per read */
|
||||
gboolean touch; /* whether to touch every page */
|
||||
gboolean using_mmap;
|
||||
gboolean using_mmap; /* whether we opened it with mmap */
|
||||
gboolean is_regular; /* whether it's (symlink to)
|
||||
a regular file */
|
||||
|
||||
GstBuffer *mapbuf;
|
||||
size_t mapsize;
|
||||
|
|
|
@ -245,6 +245,8 @@ gst_filesrc_init (GstFileSrc * src)
|
|||
|
||||
src->mapbuf = NULL;
|
||||
src->mapsize = DEFAULT_MMAPSIZE; /* default is 4MB */
|
||||
|
||||
src->is_regular = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -470,11 +472,11 @@ gst_filesrc_map_small_region (GstFileSrc * src, off_t offset, size_t size)
|
|||
#ifdef HAVE_MMAP
|
||||
/**
|
||||
* gst_filesrc_get_mmap:
|
||||
* @pad: #GstPad to push a buffer from
|
||||
* @src: #GstElement to get data from
|
||||
*
|
||||
* Push a new buffer from the filesrc at the current offset.
|
||||
* Returns: a new #GstData from the mmap'd source.
|
||||
*/
|
||||
static GstBuffer *
|
||||
static GstData *
|
||||
gst_filesrc_get_mmap (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
|
@ -601,11 +603,11 @@ gst_filesrc_get_mmap (GstFileSrc * src)
|
|||
/* we're done, return the buffer */
|
||||
g_assert (src->curoffset == GST_BUFFER_OFFSET (buf));
|
||||
src->curoffset += GST_BUFFER_SIZE (buf);
|
||||
return buf;
|
||||
return GST_DATA (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static GstBuffer *
|
||||
static GstData *
|
||||
gst_filesrc_get_read (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
|
@ -613,26 +615,40 @@ gst_filesrc_get_read (GstFileSrc * src)
|
|||
int ret;
|
||||
|
||||
readsize = src->block_size;
|
||||
if (src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| src->curoffset + readsize > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
/* for regular files, we can use the filesize to check how much we
|
||||
can read */
|
||||
if (src->is_regular) {
|
||||
if (src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| src->curoffset + readsize > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (readsize);
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
GST_LOG_OBJECT (src, "Reading %d bytes", readsize);
|
||||
ret = read (src->fd, GST_BUFFER_DATA (buf), readsize);
|
||||
if (ret < 0) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
|
||||
return NULL;
|
||||
}
|
||||
if (ret < readsize) {
|
||||
/* regular files should have given us what we expected */
|
||||
if (ret < readsize && src->is_regular) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||
("unexpected end of file."));
|
||||
return NULL;
|
||||
}
|
||||
/* other files should eos if they read 0 */
|
||||
if (ret == 0) {
|
||||
GST_DEBUG ("non-regular file hits EOS");
|
||||
gst_buffer_unref (buf);
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
readsize = ret;
|
||||
|
||||
GST_BUFFER_SIZE (buf) = readsize;
|
||||
GST_BUFFER_MAXSIZE (buf) = readsize;
|
||||
|
@ -640,7 +656,7 @@ gst_filesrc_get_read (GstFileSrc * src)
|
|||
GST_BUFFER_OFFSET_END (buf) = src->curoffset + readsize;
|
||||
src->curoffset += readsize;
|
||||
|
||||
return buf;
|
||||
return GST_DATA (buf);
|
||||
}
|
||||
|
||||
static GstData *
|
||||
|
@ -670,24 +686,27 @@ gst_filesrc_get (GstPad * pad)
|
|||
return GST_DATA (event);
|
||||
}
|
||||
|
||||
/* check for EOF */
|
||||
g_assert (src->curoffset <= src->filelen);
|
||||
if (src->curoffset == src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset >= src->filelen) {
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
/* check for EOF if it's a regular file */
|
||||
if (src->is_regular) {
|
||||
g_assert (src->curoffset <= src->filelen);
|
||||
if (src->curoffset == src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset >= src->filelen) {
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
}
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MMAP
|
||||
if (src->using_mmap) {
|
||||
return GST_DATA (gst_filesrc_get_mmap (src));
|
||||
return gst_filesrc_get_mmap (src);
|
||||
} else {
|
||||
return GST_DATA (gst_filesrc_get_read (src));
|
||||
return gst_filesrc_get_read (src);
|
||||
}
|
||||
#else
|
||||
return GST_DATA (gst_filesrc_get_read (src));
|
||||
return gst_filesrc_get_read (src);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -740,9 +759,15 @@ gst_filesrc_open_file (GstFileSrc * src)
|
|||
|
||||
fstat (src->fd, &stat_results);
|
||||
|
||||
if (!S_ISREG (stat_results.st_mode)) {
|
||||
if (S_ISDIR (stat_results.st_mode)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("File \"%s\" isn't a regular file."), src->filename), (NULL));
|
||||
(_("\"%s\" is a directory."), src->filename), (NULL));
|
||||
close (src->fd);
|
||||
return FALSE;
|
||||
}
|
||||
if (S_ISSOCK (stat_results.st_mode)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("File \"%s\" is a socket."), src->filename), (NULL));
|
||||
close (src->fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -751,15 +776,20 @@ gst_filesrc_open_file (GstFileSrc * src)
|
|||
src->filelen = stat_results.st_size;
|
||||
|
||||
src->using_mmap = FALSE;
|
||||
|
||||
/* record if it's a regular (hence seekable and lengthable) file */
|
||||
if (S_ISREG (stat_results.st_mode))
|
||||
src->is_regular = TRUE;
|
||||
#ifdef HAVE_MMAP
|
||||
/* allocate the first mmap'd region */
|
||||
/* FIXME: maybe we should only try to mmap if it's a regular file */
|
||||
/* allocate the first mmap'd region if it's a regular file ? */
|
||||
src->mapbuf = gst_filesrc_map_region (src, 0, src->mapsize);
|
||||
if (src->mapbuf != NULL) {
|
||||
GST_DEBUG_OBJECT (src, "using mmap for file");
|
||||
src->using_mmap = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
src->curoffset = 0;
|
||||
|
||||
GST_FLAG_SET (src, GST_FILESRC_OPEN);
|
||||
|
@ -780,6 +810,7 @@ gst_filesrc_close_file (GstFileSrc * src)
|
|||
src->fd = 0;
|
||||
src->filelen = 0;
|
||||
src->curoffset = 0;
|
||||
src->is_regular = FALSE;
|
||||
|
||||
if (src->mapbuf) {
|
||||
gst_buffer_unref (src->mapbuf);
|
||||
|
@ -833,6 +864,8 @@ gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
|||
if (*format != GST_FORMAT_BYTES) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!src->is_regular)
|
||||
return FALSE;
|
||||
gst_filesrc_check_filesize (src);
|
||||
*value = src->filelen;
|
||||
break;
|
||||
|
@ -844,6 +877,8 @@ gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
|||
case GST_FORMAT_PERCENT:
|
||||
if (src->filelen == 0)
|
||||
return FALSE;
|
||||
if (!src->is_regular)
|
||||
return FALSE;
|
||||
*value = src->curoffset * GST_FORMAT_PERCENT_MAX / src->filelen;
|
||||
break;
|
||||
default:
|
||||
|
@ -872,6 +907,10 @@ gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event)
|
|||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
|
||||
goto error;
|
||||
}
|
||||
if (!src->is_regular) {
|
||||
GST_DEBUG ("can't handle seek on a non-regular file");
|
||||
goto error;
|
||||
}
|
||||
|
||||
offset = GST_EVENT_SEEK_OFFSET (event);
|
||||
|
||||
|
|
|
@ -65,7 +65,9 @@ struct _GstFileSrc {
|
|||
off_t curoffset; /* current offset in file*/
|
||||
off_t block_size; /* bytes per read */
|
||||
gboolean touch; /* whether to touch every page */
|
||||
gboolean using_mmap;
|
||||
gboolean using_mmap; /* whether we opened it with mmap */
|
||||
gboolean is_regular; /* whether it's (symlink to)
|
||||
a regular file */
|
||||
|
||||
GstBuffer *mapbuf;
|
||||
size_t mapsize;
|
||||
|
|
Loading…
Reference in a new issue