summaryrefslogtreecommitdiffstats
path: root/gst/multifile
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2009-09-13 12:30:34 -0700
committerDavid Schleef <ds@schleef.org>2009-09-13 20:00:53 -0700
commit78eeb6636e3e8297a9d739c8dd1196f57f91a085 (patch)
treecf1c591a928e1946cb68f541d7c4800dc6f1f6dd /gst/multifile
parent903c79e7673666957467c1dccb6a19e2e22e90c0 (diff)
multifilesink: Add next-file property
Add a property to allow control over what event causes a file to finish being written and a new file start. The default is the same as before -- each buffer causes a new file to be written. Added is a case where buffers are written to the same file until a discontinuity in the stream.
Diffstat (limited to 'gst/multifile')
-rw-r--r--gst/multifile/gstmultifilesink.c141
-rw-r--r--gst/multifile/gstmultifilesink.h7
2 files changed, 131 insertions, 17 deletions
diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c
index f8c604aa..e11e7094 100644
--- a/gst/multifile/gstmultifilesink.c
+++ b/gst/multifile/gstmultifilesink.c
@@ -110,6 +110,7 @@
# include "config.h"
#endif
#include <gst/base/gstbasetransform.h>
+#include <glib/gstdio.h>
#include "gstmultifilesink.h"
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
@@ -129,6 +130,7 @@ GST_ELEMENT_DETAILS ("Multi-File Sink",
#define DEFAULT_LOCATION "%05d"
#define DEFAULT_INDEX 0
#define DEFAULT_POST_MESSAGES FALSE
+#define DEFAULT_NEXT_FILE GST_MULTI_FILE_SINK_NEXT_BUFFER
enum
{
@@ -136,6 +138,7 @@ enum
PROP_LOCATION,
PROP_INDEX,
PROP_POST_MESSAGES,
+ PROP_NEXT_FILE,
PROP_LAST
};
@@ -146,9 +149,30 @@ static void gst_multi_file_sink_set_property (GObject * object, guint prop_id,
static void gst_multi_file_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static gboolean gst_multi_file_sink_stop (GstBaseSink * sink);
static GstFlowReturn gst_multi_file_sink_render (GstBaseSink * sink,
GstBuffer * buffer);
+#define GST_TYPE_MULTI_FILE_SINK_NEXT (gst_multi_file_sink_next_get_type ())
+static GType
+gst_multi_file_sink_next_get_type (void)
+{
+ static GType multi_file_sync_next_type = 0;
+ static const GEnumValue next_types[] = {
+ {GST_MULTI_FILE_SINK_NEXT_BUFFER, "New file for each buffer", "buffer"},
+ {GST_MULTI_FILE_SINK_NEXT_DISCONT, "New file after each discontinuity",
+ "discont"},
+ {0, NULL, NULL}
+ };
+
+ if (!multi_file_sync_next_type) {
+ multi_file_sync_next_type =
+ g_enum_register_static ("GstMultiFileSinkNext", next_types);
+ }
+
+ return multi_file_sync_next_type;
+}
+
GST_BOILERPLATE (GstMultiFileSink, gst_multi_file_sink, GstBaseSink,
GST_TYPE_BASE_SINK);
@@ -195,10 +219,23 @@ gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass)
g_param_spec_boolean ("post-messages", "Post Messages",
"Post a message for each file with information of the buffer",
DEFAULT_POST_MESSAGES, G_PARAM_READWRITE));
+ /**
+ * GstMultiFileSink:next-file
+ *
+ * When to start a new file.
+ *
+ * Since: 0.10.17
+ */
+ g_object_class_install_property (gobject_class, PROP_NEXT_FILE,
+ g_param_spec_enum ("next-file", "Next File",
+ "When to start a new file",
+ GST_TYPE_MULTI_FILE_SINK_NEXT, DEFAULT_NEXT_FILE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gobject_class->finalize = gst_multi_file_sink_finalize;
gstbasesink_class->get_times = NULL;
+ gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_multi_file_sink_stop);
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_file_sink_render);
}
@@ -250,6 +287,9 @@ gst_multi_file_sink_set_property (GObject * object, guint prop_id,
case PROP_POST_MESSAGES:
sink->post_messages = g_value_get_boolean (value);
break;
+ case PROP_NEXT_FILE:
+ sink->next_file = g_value_get_enum (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -272,33 +312,35 @@ gst_multi_file_sink_get_property (GObject * object, guint prop_id,
case PROP_POST_MESSAGES:
g_value_set_boolean (value, sink->post_messages);
break;
+ case PROP_NEXT_FILE:
+ g_value_set_enum (value, sink->next_file);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
-static GstFlowReturn
-gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
+static gboolean
+gst_multi_file_sink_stop (GstBaseSink * sink)
{
GstMultiFileSink *multifilesink;
- guint size;
- guint8 *data;
- gchar *filename;
- gboolean ret;
- GError *error = NULL;
-
- size = GST_BUFFER_SIZE (buffer);
- data = GST_BUFFER_DATA (buffer);
multifilesink = GST_MULTI_FILE_SINK (sink);
- filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
- ret = g_file_set_contents (filename, (char *) data, size, &error);
+ if (multifilesink->file != NULL) {
+ fclose (multifilesink->file);
+ multifilesink->file = NULL;
+ }
- if (!ret)
- goto write_error;
+ return TRUE;
+}
+
+static void
+gst_multi_file_sink_post_message (GstMultiFileSink * multifilesink,
+ GstBuffer * buffer, const char *filename)
+{
if (multifilesink->post_messages) {
GstClockTime duration, timestamp;
GstClockTime running_time, stream_time;
@@ -307,7 +349,7 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
GstSegment *segment;
GstFormat format;
- segment = &sink->segment;
+ segment = &GST_BASE_SINK (multifilesink)->segment;
format = segment->format;
timestamp = GST_BUFFER_TIMESTAMP (buffer);
@@ -331,9 +373,70 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
gst_element_post_message (GST_ELEMENT_CAST (multifilesink),
gst_message_new_element (GST_OBJECT_CAST (multifilesink), s));
}
+}
- multifilesink->index++;
- g_free (filename);
+static GstFlowReturn
+gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
+{
+ GstMultiFileSink *multifilesink;
+ guint size;
+ guint8 *data;
+ gchar *filename;
+ gboolean ret;
+ GError *error = NULL;
+
+ size = GST_BUFFER_SIZE (buffer);
+ data = GST_BUFFER_DATA (buffer);
+
+ multifilesink = GST_MULTI_FILE_SINK (sink);
+
+ switch (multifilesink->next_file) {
+ case GST_MULTI_FILE_SINK_NEXT_BUFFER:
+ filename = g_strdup_printf (multifilesink->filename,
+ multifilesink->index);
+
+ ret = g_file_set_contents (filename, (char *) data, size, &error);
+ if (!ret)
+ goto write_error;
+
+ gst_multi_file_sink_post_message (multifilesink, buffer, filename);
+ multifilesink->index++;
+
+ g_free (filename);
+ break;
+ case GST_MULTI_FILE_SINK_NEXT_DISCONT:
+ if (GST_BUFFER_IS_DISCONT (buffer)) {
+ if (multifilesink->file) {
+ fclose (multifilesink->file);
+ multifilesink->file = NULL;
+
+ filename = g_strdup_printf (multifilesink->filename,
+ multifilesink->index);
+ gst_multi_file_sink_post_message (multifilesink, buffer, filename);
+ g_free (filename);
+ multifilesink->index++;
+ }
+ }
+
+ if (multifilesink->file == NULL) {
+ filename = g_strdup_printf (multifilesink->filename,
+ multifilesink->index);
+ multifilesink->file = g_fopen (filename, "wb");
+ g_free (filename);
+
+ if (multifilesink->file == NULL)
+ goto stdio_write_error;
+ }
+
+ ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1,
+ multifilesink->file);
+ if (ret != 1)
+ goto stdio_write_error;
+
+ break;
+ default:
+ g_assert_not_reached ();
+ }
return GST_FLOW_OK;
@@ -357,4 +460,8 @@ write_error:
return GST_FLOW_ERROR;
}
+stdio_write_error:
+ GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
+ ("Error while writing to file."), (NULL));
+ return GST_FLOW_ERROR;
}
diff --git a/gst/multifile/gstmultifilesink.h b/gst/multifile/gstmultifilesink.h
index b0bbfac3..b95988f0 100644
--- a/gst/multifile/gstmultifilesink.h
+++ b/gst/multifile/gstmultifilesink.h
@@ -51,6 +51,11 @@ G_BEGIN_DECLS
typedef struct _GstMultiFileSink GstMultiFileSink;
typedef struct _GstMultiFileSinkClass GstMultiFileSinkClass;
+typedef enum {
+ GST_MULTI_FILE_SINK_NEXT_BUFFER,
+ GST_MULTI_FILE_SINK_NEXT_DISCONT
+} GstMultiFileSinkNext;
+
struct _GstMultiFileSink
{
GstBaseSink parent;
@@ -58,6 +63,8 @@ struct _GstMultiFileSink
gchar *filename;
gint index;
gboolean post_messages;
+ GstMultiFileSinkNext next_file;
+ FILE *file;
};
struct _GstMultiFileSinkClass