Merge branch 'filesrc-fp' into 'main'

filesrc: Add buffer-size property

See merge request gstreamer/gstreamer!1480
This commit is contained in:
Seungha Yang 2024-05-18 07:01:48 +00:00
commit 54c6ca3ffe
3 changed files with 89 additions and 41 deletions

View file

@ -995,6 +995,20 @@
}
},
"properties": {
"buffer-size": {
"blurb": "Size of the buffer passed to setvbuf(). If a non-zero value is set, it will be rounded down to the nearest multiple of 2.",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "0",
"max": "2147483647",
"min": "0",
"mutable": "ready",
"readable": true,
"type": "guint",
"writable": true
},
"location": {
"blurb": "Location of the file to read",
"conditionally-available": false,

View file

@ -38,7 +38,6 @@
#endif
#include <gst/gst.h>
#include <glib/gstdio.h>
#include "gstfilesrc.h"
#include "gstcoreelementselements.h"
@ -52,6 +51,10 @@
* variants, so explicitly define it that way. */
#undef lseek
#define lseek _lseeki64
#ifndef HAVE_FSEEKO
/* fseeko is not defined in Windows SDK's stdio.h */
#define fseeko _fseeki64
#endif
#undef off_t
#define off_t guint64
/* Prevent stat.h from defining the stat* functions as
@ -110,11 +113,13 @@ enum
};
#define DEFAULT_BLOCKSIZE 4*1024
#define DEFAULT_BUFFER_SIZE 0
enum
{
PROP_0,
PROP_LOCATION
PROP_LOCATION,
PROP_BUFFER_SIZE,
};
static void gst_file_src_finalize (GObject * object);
@ -163,6 +168,24 @@ gst_file_src_class_init (GstFileSrcClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
/**
* GstFileSrc:buffer-size:
*
* Size of the buffer passed to setvbuf POSIX function. Depending on system,
* or read pattern (e.g., sequencial or randon-access), larger buffer size can
* improve throughput or reduce file access overhead.
*
* Since: 1.22
*/
g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
g_param_spec_uint ("buffer-size", "Buffer Size",
"Size of the buffer passed to setvbuf(). If a non-zero value is set, "
"it will be rounded down to the nearest multiple of 2.",
/* NOTE: allowed max size on Windows is INT_MAX */
0, G_MAXINT32, DEFAULT_BUFFER_SIZE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
gobject_class->finalize = gst_file_src_finalize;
gst_element_class_set_static_metadata (gstelement_class,
@ -187,11 +210,7 @@ gst_file_src_class_init (GstFileSrcClass * klass)
static void
gst_file_src_init (GstFileSrc * src)
{
src->filename = NULL;
src->fd = 0;
src->uri = NULL;
src->is_regular = FALSE;
src->buffer_size = DEFAULT_BUFFER_SIZE;
gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE);
}
@ -203,6 +222,7 @@ gst_file_src_finalize (GObject * object)
src = GST_FILE_SRC (object);
g_free (src->buffer);
g_free (src->filename);
g_free (src->uri);
@ -270,6 +290,11 @@ gst_file_src_set_property (GObject * object, guint prop_id,
case PROP_LOCATION:
gst_file_src_set_location (src, g_value_get_string (value), NULL);
break;
case PROP_BUFFER_SIZE:
src->buffer_size = g_value_get_uint (value);
if (src->buffer_size > 0)
src->buffer_size = GST_ROUND_DOWN_2 (src->buffer_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -290,6 +315,9 @@ 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_BUFFER_SIZE:
g_value_set_uint (value, src->buffer_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -312,7 +340,7 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
{
GstFileSrc *src;
guint to_read, bytes_read;
int ret;
gsize ret;
GstMapInfo info;
guint8 *data;
@ -321,8 +349,8 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
if (G_UNLIKELY (offset != -1 && src->read_position != offset)) {
off_t res;
res = lseek (src->fd, offset, SEEK_SET);
if (G_UNLIKELY (res < 0 || res != offset))
res = fseeko (src->fp, offset, SEEK_SET);
if (G_UNLIKELY (res != 0))
goto seek_failed;
src->read_position = offset;
@ -338,7 +366,7 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
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);
ret = fread (data + bytes_read, 1, to_read, src->fp);
if (G_UNLIKELY (ret < 0)) {
if (errno == EAGAIN || errno == EINTR)
continue;
@ -415,38 +443,39 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size)
* succeed, and wrongly say our length is zero. */
return FALSE;
}
if (!src->fp)
return FALSE;
#ifdef G_OS_WIN32
{
HANDLE h = (HANDLE) _get_osfhandle (src->fd);
HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp));
LARGE_INTEGER file_size;
if (h == INVALID_HANDLE_VALUE)
goto could_not_stat;
return FALSE;
if (!GetFileSizeEx (h, &file_size)) {
goto could_not_stat;
}
if (!GetFileSizeEx (h, &file_size))
return FALSE;
*size = file_size.QuadPart;
}
#else
{
struct_stat stat_results;
int fd = fileno (src->fp);
if (fstat (src->fd, &stat_results) < 0)
goto could_not_stat;
if (fd == -1)
return FALSE;
if (fstat (fileno (src->fp), &stat_results) < 0)
return FALSE;
*size = stat_results.st_size;
}
#endif
return TRUE;
/* ERROR */
could_not_stat:
{
return FALSE;
}
}
/* open the file, necessary to go to READY state */
@ -454,10 +483,6 @@ static gboolean
gst_file_src_start (GstBaseSrc * basesrc)
{
GstFileSrc *src = GST_FILE_SRC (basesrc);
int flags = O_RDONLY | O_BINARY;
#if defined (__BIONIC__)
flags |= O_LARGEFILE;
#endif
if (src->filename == NULL || src->filename[0] == '\0')
goto no_filename;
@ -465,14 +490,14 @@ gst_file_src_start (GstBaseSrc * basesrc)
GST_INFO_OBJECT (src, "opening file %s", src->filename);
/* open the file */
src->fd = g_open (src->filename, flags, 0);
src->fp = fopen (src->filename, "rb");
if (src->fd < 0)
if (!src->fp)
goto open_failed;
#ifdef G_OS_WIN32
{
HANDLE h = (HANDLE) _get_osfhandle (src->fd);
HANDLE h = (HANDLE) _get_osfhandle (_fileno (src->fp));
FILE_STANDARD_INFO file_info;
if (h == INVALID_HANDLE_VALUE)
@ -493,7 +518,7 @@ gst_file_src_start (GstBaseSrc * basesrc)
struct_stat stat_results;
/* check if it is a regular file, otherwise bail out */
if (fstat (src->fd, &stat_results) < 0)
if (fstat (fileno (src->fp), &stat_results) < 0)
goto no_stat;
if (S_ISDIR (stat_results.st_mode))
@ -512,14 +537,14 @@ gst_file_src_start (GstBaseSrc * basesrc)
/* We need to check if the underlying file is seekable. */
{
off_t res = lseek (src->fd, 0, SEEK_END);
off_t res = fseeko (src->fp, 0, SEEK_END);
if (res < 0) {
GST_LOG_OBJECT (src, "disabling seeking, lseek failed: %s",
g_strerror (errno));
src->seekable = FALSE;
} else {
res = lseek (src->fd, 0, SEEK_SET);
res = fseeko (src->fp, 0, SEEK_SET);
if (res < 0) {
/* We really don't like not being able to go back to 0 */
@ -537,6 +562,14 @@ gst_file_src_start (GstBaseSrc * basesrc)
gst_base_src_set_dynamic_size (basesrc, src->seekable);
if (src->buffer_size) {
src->buffer = g_malloc (src->buffer_size);
if (setvbuf (src->fp, (char *) src->buffer, _IOFBF, src->buffer_size) != 0) {
GST_WARNING_OBJECT (src, "setvbuf() failed");
g_clear_pointer (&src->buffer, g_free);
}
}
return TRUE;
/* ERROR */
@ -589,7 +622,7 @@ lseek_wonky:
goto error_close;
}
error_close:
close (src->fd);
g_clear_pointer (&src->fp, fclose);
error_exit:
return FALSE;
}
@ -600,11 +633,9 @@ gst_file_src_stop (GstBaseSrc * basesrc)
{
GstFileSrc *src = GST_FILE_SRC (basesrc);
/* close the file */
g_close (src->fd, NULL);
g_clear_pointer (&src->fp, fclose);
g_clear_pointer (&src->buffer, g_free);
/* zero out a lot of our state */
src->fd = 0;
src->is_regular = FALSE;
return TRUE;

View file

@ -28,6 +28,7 @@
#include <gst/gst.h>
#include <gst/base/gstbasesrc.h>
#include <stdio.h>
G_BEGIN_DECLS
@ -57,12 +58,14 @@ struct _GstFileSrc {
/*< private >*/
gchar *filename; /* filename */
gchar *uri; /* caching the URI */
gint fd; /* open file descriptor */
guint64 read_position; /* position of fd */
FILE *fp;
guint64 read_position; /* position of file stream */
gboolean seekable; /* whether the file is seekable */
gboolean is_regular; /* whether it's a (symlink to a)
regular file */
gsize buffer_size;
guint8 *buffer;
};
struct _GstFileSrcClass {