summaryrefslogtreecommitdiffstats
path: root/gst/multifile
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-09-11 12:16:18 +0200
committerWim Taymans <wim@metal.(none)>2009-09-11 12:17:21 +0200
commitf68cd7e7080a9221cae97d29289e6b8bb12f5fbc (patch)
tree9bc921a3bdbdb5fb6e882538afc5aa67487b1034 /gst/multifile
parent411c71da131c4ffc4e9a573807ba17771f2d3b15 (diff)
multifilesink: post messages for each buffer
Add a silent property that can be set to FALSE to post messages on the bus for each written file. Do some more cleanups. Add some docs. Fixes #594663
Diffstat (limited to 'gst/multifile')
-rw-r--r--gst/multifile/gstmultifilesink.c247
-rw-r--r--gst/multifile/gstmultifilesink.h4
2 files changed, 187 insertions, 64 deletions
diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c
index 3c92cf7c..9097c736 100644
--- a/gst/multifile/gstmultifilesink.c
+++ b/gst/multifile/gstmultifilesink.c
@@ -26,12 +26,90 @@
* @see_also: #GstFileSrc
*
* Write incoming data to a series of sequentially-named files.
+ *
+ * The filename property should contain a string with a %d placeholder that will
+ * be substituted with the index for each filename.
+ *
+ * If the #GstMultiFileSink:silent property is #FALSE, it sends an application
+ * message named
+ * <classname>&quot;GstMultiFileSink&quot;</classname> after writing each
+ * buffer.
+ *
+ * The message's structure contains these fields:
+ * <itemizedlist>
+ * <listitem>
+ * <para>
+ * #gchar *
+ * <classname>&quot;filename&quot;</classname>:
+ * the filename where the buffer was written.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #gint
+ * <classname>&quot;index&quot;</classname>:
+ * the index of the buffer.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #GstClockTime
+ * <classname>&quot;timestamp&quot;</classname>:
+ * the timestamp of the buffer.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #GstClockTime
+ * <classname>&quot;stream-time&quot;</classname>:
+ * the stream time of the buffer.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #GstClockTime
+ * <classname>&quot;running-time&quot;</classname>:
+ * the running_time of the buffer.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #GstClockTime
+ * <classname>&quot;duration&quot;</classname>:
+ * the duration of the buffer.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #guint64
+ * <classname>&quot;offset&quot;</classname>:
+ * the offset of the buffer that triggered the message.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * #guint64
+ * <classname>&quot;offset-end&quot;</classname>:
+ * the offset-end of the buffer that triggered the message.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
+ *
+ * <title>Example launch line</title>
+ * <refsect2>
+ * |[
+ * gst-launch audiotestsrc ! multifilesink
+ * gst-launch videotestsrc ! multifilesink silent=false filename="frame%d"
+ * ]|
+ * </refsect2>
+ *
+ * Last reviewed on 2009-09-11 (0.10.17)
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-
+#include <gst/base/gstbasetransform.h>
#include "gstmultifilesink.h"
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
@@ -48,17 +126,20 @@ GST_ELEMENT_DETAILS ("Multi-File Sink",
"Write buffers to a sequentially named set of files",
"David Schleef <ds@schleef.org>");
+#define DEFAULT_LOCATION "%05d"
+#define DEFAULT_INDEX 0
+#define DEFAULT_SILENT TRUE
+
enum
{
- ARG_0,
- ARG_LOCATION,
- ARG_INDEX
+ PROP_0,
+ PROP_LOCATION,
+ PROP_INDEX,
+ PROP_SILENT,
+ PROP_LAST
};
-#define DEFAULT_LOCATION "%05d"
-#define DEFAULT_INDEX 0
-
-static void gst_multi_file_sink_dispose (GObject * object);
+static void gst_multi_file_sink_finalize (GObject * object);
static void gst_multi_file_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@@ -68,8 +149,6 @@ static void gst_multi_file_sink_get_property (GObject * object, guint prop_id,
static GstFlowReturn gst_multi_file_sink_render (GstBaseSink * sink,
GstBuffer * buffer);
-
-
GST_BOILERPLATE (GstMultiFileSink, gst_multi_file_sink, GstBaseSink,
GST_TYPE_BASE_SINK);
@@ -96,16 +175,28 @@ gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass)
gobject_class->set_property = gst_multi_file_sink_set_property;
gobject_class->get_property = gst_multi_file_sink_get_property;
- g_object_class_install_property (gobject_class, ARG_LOCATION,
+ g_object_class_install_property (gobject_class, PROP_LOCATION,
g_param_spec_string ("location", "File Location",
"Location of the file to write", NULL, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_INDEX,
+
+ g_object_class_install_property (gobject_class, PROP_INDEX,
g_param_spec_int ("index", "Index",
"Index to use with location property to create file names. The "
- "index is incremented by one for each buffer read.",
- 0, INT_MAX, DEFAULT_INDEX, G_PARAM_READWRITE));
-
- gobject_class->dispose = gst_multi_file_sink_dispose;
+ "index is incremented by one for each buffer written.",
+ 0, G_MAXINT, DEFAULT_INDEX, G_PARAM_READWRITE));
+ /**
+ * GstMultiFileSink:silent
+ *
+ * Post a message on the GstBus for each file.
+ *
+ * Since: 0.10.17
+ */
+ g_object_class_install_property (gobject_class, PROP_SILENT,
+ g_param_spec_boolean ("silent", "Silent",
+ "Message to show a message for each file to save with the timestamp "
+ " of the buffer", DEFAULT_SILENT, G_PARAM_READWRITE));
+
+ gobject_class->finalize = gst_multi_file_sink_finalize;
gstbasesink_class->get_times = NULL;
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_file_sink_render);
@@ -117,19 +208,19 @@ gst_multi_file_sink_init (GstMultiFileSink * multifilesink,
{
multifilesink->filename = g_strdup (DEFAULT_LOCATION);
multifilesink->index = DEFAULT_INDEX;
+ multifilesink->silent = DEFAULT_SILENT;
- GST_BASE_SINK (multifilesink)->sync = FALSE;
+ gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE);
}
static void
-gst_multi_file_sink_dispose (GObject * object)
+gst_multi_file_sink_finalize (GObject * object)
{
GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
g_free (sink->filename);
- sink->filename = NULL;
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
@@ -137,12 +228,8 @@ gst_multi_file_sink_set_location (GstMultiFileSink * sink,
const gchar * location)
{
g_free (sink->filename);
- if (location != NULL) {
- /* FIXME: validate location to have just one %d */
- sink->filename = g_strdup (location);
- } else {
- sink->filename = NULL;
- }
+ /* FIXME: validate location to have just one %d */
+ sink->filename = g_strdup (location);
return TRUE;
}
@@ -154,12 +241,15 @@ gst_multi_file_sink_set_property (GObject * object, guint prop_id,
GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
switch (prop_id) {
- case ARG_LOCATION:
+ case PROP_LOCATION:
gst_multi_file_sink_set_location (sink, g_value_get_string (value));
break;
- case ARG_INDEX:
+ case PROP_INDEX:
sink->index = g_value_get_int (value);
break;
+ case PROP_SILENT:
+ sink->silent = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -173,65 +263,98 @@ gst_multi_file_sink_get_property (GObject * object, guint prop_id,
GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
switch (prop_id) {
- case ARG_LOCATION:
+ case PROP_LOCATION:
g_value_set_string (value, sink->filename);
break;
- case ARG_INDEX:
+ case PROP_INDEX:
g_value_set_int (value, sink->index);
break;
+ case PROP_SILENT:
+ g_value_set_boolean (value, sink->silent);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
-static gchar *
-gst_multi_file_sink_get_filename (GstMultiFileSink * multifilesink)
-{
- gchar *filename;
-
- filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
-
- return 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);
- filename = gst_multi_file_sink_get_filename (multifilesink);
-
- ret = g_file_set_contents (filename, (char *) GST_BUFFER_DATA (buffer),
- size, &error);
- if (ret) {
- multifilesink->index++;
- g_free (filename);
- return GST_FLOW_OK;
+ filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
+ ret = g_file_set_contents (filename, (char *) data, size, &error);
+
+ if (!ret)
+ goto write_error;
+
+ if (!multifilesink->silent) {
+ GstClockTime duration, timestamp;
+ GstClockTime running_time, stream_time;
+ guint64 offset, offset_end;
+ GstStructure *s;
+ GstSegment *segment;
+ GstFormat format;
+
+ segment = &sink->segment;
+ format = segment->format;
+
+ timestamp = GST_BUFFER_TIMESTAMP (buffer);
+ duration = GST_BUFFER_DURATION (buffer);
+ offset = GST_BUFFER_OFFSET (buffer);
+ offset_end = GST_BUFFER_OFFSET_END (buffer);
+
+ running_time = gst_segment_to_running_time (segment, format, timestamp);
+ stream_time = gst_segment_to_stream_time (segment, format, timestamp);
+
+ s = gst_structure_new ("GstMultiFileSink",
+ "filename", G_TYPE_STRING, filename,
+ "index", G_TYPE_INT, multifilesink->index,
+ "timestamp", G_TYPE_UINT64, timestamp,
+ "stream-time", G_TYPE_UINT64, stream_time,
+ "running-time", G_TYPE_UINT64, running_time,
+ "duration", G_TYPE_UINT64, duration,
+ "offset", G_TYPE_UINT64, offset,
+ "offset-end", G_TYPE_UINT64, offset_end, NULL);
+
+ gst_element_post_message (GST_ELEMENT_CAST (multifilesink),
+ gst_message_new_element (GST_OBJECT_CAST (multifilesink), s));
}
- switch (error->code) {
- case G_FILE_ERROR_NOSPC:{
- GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT, (NULL),
- (NULL));
- break;
- }
- default:{
- GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
- ("Error while writing to file \"%s\".", filename),
- ("%s", g_strerror (errno)));
- }
- }
- g_error_free (error);
+ multifilesink->index++;
g_free (filename);
- return GST_FLOW_ERROR;
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+write_error:
+ {
+ switch (error->code) {
+ case G_FILE_ERROR_NOSPC:{
+ GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT, (NULL),
+ (NULL));
+ break;
+ }
+ default:{
+ GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
+ ("Error while writing to file \"%s\".", filename),
+ ("%s", g_strerror (errno)));
+ }
+ }
+ g_error_free (error);
+ g_free (filename);
+
+ return GST_FLOW_ERROR;
+ }
}
diff --git a/gst/multifile/gstmultifilesink.h b/gst/multifile/gstmultifilesink.h
index c26a64a1..1751fb3d 100644
--- a/gst/multifile/gstmultifilesink.h
+++ b/gst/multifile/gstmultifilesink.h
@@ -56,8 +56,8 @@ struct _GstMultiFileSink
GstBaseSink parent;
gchar *filename;
- gchar *uri;
- int index;
+ gint index;
+ gboolean silent;
};
struct _GstMultiFileSinkClass