From befab7af726524fed9739976a077c785eba1f953 Mon Sep 17 00:00:00 2001 From: Daniel Ulery Date: Tue, 20 Dec 2022 10:01:12 -0800 Subject: [PATCH] filesink: Adds rb+ file mode Adds rb+ file mode to filesink so that files can be pre-allocated. This can be use to keep reduce fragmentation over time with splitmuxsink. Fixes #955 Part-of: --- .vscode/settings.json | 6 +++ .../docs/plugins/gst_plugins_cache.json | 32 +++++++++++ .../gstreamer/plugins/elements/gstfilesink.c | 53 ++++++++++++++++++- .../gstreamer/plugins/elements/gstfilesink.h | 19 ++++++- 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..a6f568a877 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "fstream": "c", + "xlocmes": "c" + } +} \ No newline at end of file diff --git a/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json b/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json index cbe32ab038..bacf41e7b4 100644 --- a/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gstreamer/docs/plugins/gst_plugins_cache.json @@ -906,6 +906,18 @@ "type": "guint", "writable": true }, + "file-mode": { + "blurb": "Specify file mode used to open file", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "truncate (1)", + "mutable": "null", + "readable": true, + "type": "GstFileSinkFileMode", + "writable": true + }, "location": { "blurb": "Location of the file to write", "conditionally-available": false, @@ -2646,6 +2658,26 @@ } ] }, + "GstFileSinkFileMode": { + "kind": "enum", + "values": [ + { + "desc": "Truncate file (mode wb)", + "name": "truncate", + "value": "1" + }, + { + "desc": "Append file (mode ab)", + "name": "output", + "value": "2" + }, + { + "desc": "Overwrite file without truncating (mode rb+)", + "name": "overwrite", + "value": "3" + } + ] + }, "GstInputSelectorSyncMode": { "kind": "enum", "values": [ diff --git a/subprojects/gstreamer/plugins/elements/gstfilesink.c b/subprojects/gstreamer/plugins/elements/gstfilesink.c index d5808fd97f..0491080a72 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesink.c +++ b/subprojects/gstreamer/plugins/elements/gstfilesink.c @@ -81,6 +81,29 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); +#define GST_TYPE_FILE_SINK_FILE_MODE (gst_file_sink_file_mode_get_type()) +static GType +gst_file_sink_file_mode_get_type (void) +{ + static GType file_mode_type = 0; + + if (g_once_init_enter (&file_mode_type)) { + static const GEnumValue file_mode[] = { + {GST_FILE_SINK_FILE_MODE_TRUNC, "Truncate file (mode wb)", "truncate"}, + {GST_FILE_SINK_FILE_MODE_APPEND, "Append file (mode ab)", "output"}, + {GST_FILE_SINK_FILE_MODE_OVERWRITE, + "Overwrite file without truncating (mode rb+)", "overwrite"}, + {0, NULL, NULL} + }; + + GType new_file_mode_type = + g_enum_register_static ("GstFileSinkFileMode", file_mode); + + g_once_init_leave (&file_mode_type, new_file_mode_type); + } + return file_mode_type; +} + #define GST_TYPE_FILE_SINK_BUFFER_MODE (gst_file_sink_buffer_mode_get_type ()) static GType gst_file_sink_buffer_mode_get_type (void) @@ -111,6 +134,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_file_sink_debug); #define DEFAULT_APPEND FALSE #define DEFAULT_O_SYNC FALSE #define DEFAULT_MAX_TRANSIENT_ERROR_TIMEOUT 0 +#define DEFAULT_FILE_MODE GST_FILE_SINK_FILE_MODE_TRUNC enum { @@ -121,6 +145,7 @@ enum PROP_APPEND, PROP_O_SYNC, PROP_MAX_TRANSIENT_ERROR_TIMEOUT, + PROP_FILE_MODE, PROP_LAST }; @@ -145,6 +170,8 @@ gst_fopen (const gchar * filename, const gchar * mode, gboolean o_sync) flags |= O_TRUNC; else if (strcmp (mode, "ab") == 0) flags |= O_APPEND; + else if (strcmp (mode, "rb+") == 0) + flags |= O_RDWR; else g_assert_not_reached (); @@ -230,6 +257,18 @@ gst_file_sink_class_init (GstFileSinkClass * klass) G_MAXUINT, DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstFileSink:file-mode + * + * Ability to specify file mode. + * + * Since: 1.24 + */ + g_object_class_install_property (gobject_class, PROP_FILE_MODE, + g_param_spec_enum ("file-mode", "File Mode", + "Specify file mode used to open file", GST_TYPE_FILE_SINK_FILE_MODE, + DEFAULT_FILE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstFileSink:append * @@ -238,7 +277,7 @@ gst_file_sink_class_init (GstFileSinkClass * klass) g_object_class_install_property (gobject_class, PROP_APPEND, g_param_spec_boolean ("append", "Append", "Append to an already existing file", DEFAULT_APPEND, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED)); g_object_class_install_property (gobject_class, PROP_O_SYNC, g_param_spec_boolean ("o-sync", "Synchronous IO", @@ -276,6 +315,7 @@ gst_file_sink_class_init (GstFileSinkClass * klass) } gst_type_mark_as_plugin_api (GST_TYPE_FILE_SINK_BUFFER_MODE, 0); + gst_type_mark_as_plugin_api (GST_TYPE_FILE_SINK_FILE_MODE, 0); } static void @@ -287,6 +327,7 @@ gst_file_sink_init (GstFileSink * filesink) filesink->buffer_mode = DEFAULT_BUFFER_MODE; filesink->buffer_size = DEFAULT_BUFFER_SIZE; filesink->append = FALSE; + filesink->file_mode = DEFAULT_FILE_MODE; gst_base_sink_set_sync (GST_BASE_SINK (filesink), FALSE); } @@ -358,6 +399,9 @@ gst_file_sink_set_property (GObject * object, guint prop_id, case PROP_APPEND: sink->append = g_value_get_boolean (value); break; + case PROP_FILE_MODE: + sink->file_mode = g_value_get_enum (value); + break; case PROP_O_SYNC: sink->o_sync = g_value_get_boolean (value); break; @@ -389,6 +433,9 @@ gst_file_sink_get_property (GObject * object, guint prop_id, GValue * value, case PROP_APPEND: g_value_set_boolean (value, sink->append); break; + case PROP_FILE_MODE: + g_value_set_enum (value, sink->file_mode); + break; case PROP_O_SYNC: g_value_set_boolean (value, sink->o_sync); break; @@ -408,8 +455,10 @@ gst_file_sink_open_file (GstFileSink * sink) if (sink->filename == NULL || sink->filename[0] == '\0') goto no_filename; - if (sink->append) + if (sink->append || sink->file_mode == GST_FILE_SINK_FILE_MODE_APPEND) sink->file = gst_fopen (sink->filename, "ab", sink->o_sync); + else if (sink->file_mode == GST_FILE_SINK_FILE_MODE_OVERWRITE) + sink->file = gst_fopen (sink->filename, "rb+", sink->o_sync); else sink->file = gst_fopen (sink->filename, "wb", sink->o_sync); if (sink->file == NULL) diff --git a/subprojects/gstreamer/plugins/elements/gstfilesink.h b/subprojects/gstreamer/plugins/elements/gstfilesink.h index bc479c5430..aef04c8127 100644 --- a/subprojects/gstreamer/plugins/elements/gstfilesink.h +++ b/subprojects/gstreamer/plugins/elements/gstfilesink.h @@ -30,7 +30,6 @@ #include G_BEGIN_DECLS - #define GST_TYPE_FILE_SINK \ (gst_file_sink_get_type()) #define GST_FILE_SINK(obj) \ @@ -62,6 +61,22 @@ typedef enum { GST_FILE_SINK_BUFFER_MODE_UNBUFFERED = _IONBF } GstFileSinkBufferMode; +/** + * GstFileSinkFileMode: + * @FILESINK_FILE_MODE_TRUNC: Default file mode (wb) + * @FILESINK_FILE_MODE_APPEND: Append file mode (ab) + * @FILESINK_FILE_MODE_OVERWRITE: Overwrite file mode (rb+) + * + * File write mode. + * + * Since: 1.24 + */ +typedef enum { + GST_FILE_SINK_FILE_MODE_TRUNC = 1, + GST_FILE_SINK_FILE_MODE_APPEND = 2, + GST_FILE_SINK_FILE_MODE_OVERWRITE = 3, +} GstFileSinkFileMode; + /** * GstFileSink: * @@ -84,6 +99,8 @@ struct _GstFileSink { /* For default buffer mode */ GstBufferList *buffer_list; + gint file_mode; + /* For full buffer mode */ guint8 *buffer; gsize allocated_buffer_size;