2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 * 2006 Wim Taymans <wim@fluendo.com>
5 * 2006 David A. Schleef <ds@schleef.org>
6 * 2011 Collabora Ltd. <tim.muller@collabora.co.uk>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
26 * SECTION:element-multifilesink
27 * @see_also: #GstFileSrc
29 * Write incoming data to a series of sequentially-named files.
31 * The filename property should contain a string with a \%d placeholder that will
32 * be substituted with the index for each filename.
34 * If the #GstMultiFileSink:post-messages property is #TRUE, it sends an application
36 * <classname>"GstMultiFileSink"</classname> after writing each
39 * The message's structure contains these fields:
44 * <classname>"filename"</classname>:
45 * the filename where the buffer was written.
51 * <classname>"index"</classname>:
52 * the index of the buffer.
58 * <classname>"timestamp"</classname>:
59 * the timestamp of the buffer.
65 * <classname>"stream-time"</classname>:
66 * the stream time of the buffer.
72 * <classname>"running-time"</classname>:
73 * the running_time of the buffer.
79 * <classname>"duration"</classname>:
80 * the duration of the buffer.
86 * <classname>"offset"</classname>:
87 * the offset of the buffer that triggered the message.
93 * <classname>"offset-end"</classname>:
94 * the offset-end of the buffer that triggered the message.
100 * <title>Example launch line</title>
102 * gst-launch audiotestsrc ! multifilesink
103 * gst-launch videotestsrc ! multifilesink post-messages=true filename="frame%d"
107 * Last reviewed on 2009-09-11 (0.10.17)
113 #include <gst/base/gstbasetransform.h>
114 #include <gst/video/video.h>
115 #include <glib/gstdio.h>
116 #include "gstmultifilesink.h"
118 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
121 GST_STATIC_CAPS_ANY);
123 GST_DEBUG_CATEGORY_STATIC (gst_multi_file_sink_debug);
124 #define GST_CAT_DEFAULT gst_multi_file_sink_debug
126 #define DEFAULT_LOCATION "%05d"
127 #define DEFAULT_INDEX 0
128 #define DEFAULT_POST_MESSAGES FALSE
129 #define DEFAULT_NEXT_FILE GST_MULTI_FILE_SINK_NEXT_BUFFER
130 #define DEFAULT_MAX_FILES 0
131 #define DEFAULT_MAX_FILE_SIZE G_GUINT64_CONSTANT(2*1024*1024*1024)
145 static void gst_multi_file_sink_finalize (GObject * object);
147 static void gst_multi_file_sink_set_property (GObject * object, guint prop_id,
148 const GValue * value, GParamSpec * pspec);
149 static void gst_multi_file_sink_get_property (GObject * object, guint prop_id,
150 GValue * value, GParamSpec * pspec);
152 static gboolean gst_multi_file_sink_stop (GstBaseSink * sink);
153 static GstFlowReturn gst_multi_file_sink_render (GstBaseSink * sink,
155 static GstFlowReturn gst_multi_file_sink_render_list (GstBaseSink * sink,
156 GstBufferList * buffer_list);
157 static gboolean gst_multi_file_sink_set_caps (GstBaseSink * sink,
159 static gboolean gst_multi_file_sink_open_next_file (GstMultiFileSink *
161 static void gst_multi_file_sink_close_file (GstMultiFileSink * multifilesink,
163 static void gst_multi_file_sink_ensure_max_files (GstMultiFileSink *
165 static gboolean gst_multi_file_sink_event (GstBaseSink * sink,
168 #define GST_TYPE_MULTI_FILE_SINK_NEXT (gst_multi_file_sink_next_get_type ())
170 gst_multi_file_sink_next_get_type (void)
172 static GType multi_file_sync_next_type = 0;
173 static const GEnumValue next_types[] = {
174 {GST_MULTI_FILE_SINK_NEXT_BUFFER, "New file for each buffer", "buffer"},
175 {GST_MULTI_FILE_SINK_NEXT_DISCONT, "New file after each discontinuity",
177 {GST_MULTI_FILE_SINK_NEXT_KEY_FRAME, "New file at each key frame "
178 "(Useful for MPEG-TS segmenting)", "key-frame"},
179 {GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT,
180 "New file after a force key unit event", "key-unit-event"},
181 {GST_MULTI_FILE_SINK_NEXT_MAX_SIZE, "New file when the configured maximum "
182 "file size would be exceeded with the next buffer or buffer list",
187 if (!multi_file_sync_next_type) {
188 multi_file_sync_next_type =
189 g_enum_register_static ("GstMultiFileSinkNext", next_types);
192 return multi_file_sync_next_type;
195 #define gst_multi_file_sink_parent_class parent_class
196 G_DEFINE_TYPE (GstMultiFileSink, gst_multi_file_sink, GST_TYPE_BASE_SINK);
199 gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass)
201 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
202 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
203 GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
205 gobject_class->set_property = gst_multi_file_sink_set_property;
206 gobject_class->get_property = gst_multi_file_sink_get_property;
208 g_object_class_install_property (gobject_class, PROP_LOCATION,
209 g_param_spec_string ("location", "File Location",
210 "Location of the file to write", NULL,
211 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213 g_object_class_install_property (gobject_class, PROP_INDEX,
214 g_param_spec_int ("index", "Index",
215 "Index to use with location property to create file names. The "
216 "index is incremented by one for each buffer written.",
217 0, G_MAXINT, DEFAULT_INDEX,
218 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
220 * GstMultiFileSink:post-messages
222 * Post a message on the GstBus for each file.
226 g_object_class_install_property (gobject_class, PROP_POST_MESSAGES,
227 g_param_spec_boolean ("post-messages", "Post Messages",
228 "Post a message for each file with information of the buffer",
229 DEFAULT_POST_MESSAGES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231 * GstMultiFileSink:next-file
233 * When to start a new file.
237 g_object_class_install_property (gobject_class, PROP_NEXT_FILE,
238 g_param_spec_enum ("next-file", "Next File",
239 "When to start a new file",
240 GST_TYPE_MULTI_FILE_SINK_NEXT, DEFAULT_NEXT_FILE,
241 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS));
245 * GstMultiFileSink:max-files
247 * Maximum number of files to keep on disk. Once the maximum is reached, old
248 * files start to be deleted to make room for new ones.
252 g_object_class_install_property (gobject_class, PROP_MAX_FILES,
253 g_param_spec_uint ("max-files", "Max files",
254 "Maximum number of files to keep on disk. Once the maximum is reached,"
255 "old files start to be deleted to make room for new ones.",
256 0, G_MAXUINT, DEFAULT_MAX_FILES,
257 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
260 * GstMultiFileSink:max-file-size
262 * Maximum file size before starting a new file in max-size mode.
266 g_object_class_install_property (gobject_class, PROP_MAX_FILE_SIZE,
267 g_param_spec_uint64 ("max-file-size", "Maximum File Size",
268 "Maximum file size before starting a new file in max-size mode",
269 0, G_MAXUINT64, DEFAULT_MAX_FILE_SIZE,
270 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
272 gobject_class->finalize = gst_multi_file_sink_finalize;
274 gstbasesink_class->get_times = NULL;
275 gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_multi_file_sink_stop);
276 gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_file_sink_render);
277 gstbasesink_class->render_list =
278 GST_DEBUG_FUNCPTR (gst_multi_file_sink_render_list);
279 gstbasesink_class->set_caps =
280 GST_DEBUG_FUNCPTR (gst_multi_file_sink_set_caps);
281 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_multi_file_sink_event);
283 GST_DEBUG_CATEGORY_INIT (gst_multi_file_sink_debug, "multifilesink", 0,
284 "multifilesink element");
286 gst_element_class_add_pad_template (gstelement_class,
287 gst_static_pad_template_get (&sinktemplate));
288 gst_element_class_set_details_simple (gstelement_class, "Multi-File Sink",
290 "Write buffers to a sequentially named set of files",
291 "David Schleef <ds@schleef.org>");
295 gst_multi_file_sink_init (GstMultiFileSink * multifilesink)
297 multifilesink->filename = g_strdup (DEFAULT_LOCATION);
298 multifilesink->index = DEFAULT_INDEX;
299 multifilesink->post_messages = DEFAULT_POST_MESSAGES;
300 multifilesink->max_files = DEFAULT_MAX_FILES;
301 multifilesink->max_file_size = DEFAULT_MAX_FILE_SIZE;
302 multifilesink->files = NULL;
303 multifilesink->n_files = 0;
305 gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE);
307 multifilesink->next_segment = GST_CLOCK_TIME_NONE;
308 multifilesink->force_key_unit_count = -1;
312 gst_multi_file_sink_finalize (GObject * object)
314 GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
316 g_free (sink->filename);
317 g_slist_foreach (sink->files, (GFunc) g_free, NULL);
318 g_slist_free (sink->files);
320 G_OBJECT_CLASS (parent_class)->finalize (object);
324 gst_multi_file_sink_set_location (GstMultiFileSink * sink,
325 const gchar * location)
327 g_free (sink->filename);
328 /* FIXME: validate location to have just one %d */
329 sink->filename = g_strdup (location);
335 gst_multi_file_sink_set_property (GObject * object, guint prop_id,
336 const GValue * value, GParamSpec * pspec)
338 GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
342 gst_multi_file_sink_set_location (sink, g_value_get_string (value));
345 sink->index = g_value_get_int (value);
347 case PROP_POST_MESSAGES:
348 sink->post_messages = g_value_get_boolean (value);
351 sink->next_file = g_value_get_enum (value);
354 sink->max_files = g_value_get_uint (value);
356 case PROP_MAX_FILE_SIZE:
357 sink->max_file_size = g_value_get_uint64 (value);
360 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
366 gst_multi_file_sink_get_property (GObject * object, guint prop_id,
367 GValue * value, GParamSpec * pspec)
369 GstMultiFileSink *sink = GST_MULTI_FILE_SINK (object);
373 g_value_set_string (value, sink->filename);
376 g_value_set_int (value, sink->index);
378 case PROP_POST_MESSAGES:
379 g_value_set_boolean (value, sink->post_messages);
382 g_value_set_enum (value, sink->next_file);
385 g_value_set_uint (value, sink->max_files);
387 case PROP_MAX_FILE_SIZE:
388 g_value_set_uint64 (value, sink->max_file_size);
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397 gst_multi_file_sink_stop (GstBaseSink * sink)
399 GstMultiFileSink *multifilesink;
402 multifilesink = GST_MULTI_FILE_SINK (sink);
404 if (multifilesink->file != NULL) {
405 fclose (multifilesink->file);
406 multifilesink->file = NULL;
409 if (multifilesink->streamheaders) {
410 for (i = 0; i < multifilesink->n_streamheaders; i++) {
411 gst_buffer_unref (multifilesink->streamheaders[i]);
413 g_free (multifilesink->streamheaders);
414 multifilesink->streamheaders = NULL;
417 multifilesink->force_key_unit_count = -1;
424 gst_multi_file_sink_post_message_full (GstMultiFileSink * multifilesink,
425 GstClockTime timestamp, GstClockTime duration, GstClockTime offset,
426 GstClockTime offset_end, GstClockTime running_time,
427 GstClockTime stream_time, const char *filename)
431 if (!multifilesink->post_messages)
434 s = gst_structure_new ("GstMultiFileSink",
435 "filename", G_TYPE_STRING, filename,
436 "index", G_TYPE_INT, multifilesink->index,
437 "timestamp", G_TYPE_UINT64, timestamp,
438 "stream-time", G_TYPE_UINT64, stream_time,
439 "running-time", G_TYPE_UINT64, running_time,
440 "duration", G_TYPE_UINT64, duration,
441 "offset", G_TYPE_UINT64, offset,
442 "offset-end", G_TYPE_UINT64, offset_end, NULL);
444 gst_element_post_message (GST_ELEMENT_CAST (multifilesink),
445 gst_message_new_element (GST_OBJECT_CAST (multifilesink), s));
450 gst_multi_file_sink_post_message (GstMultiFileSink * multifilesink,
451 GstBuffer * buffer, const char *filename)
453 GstClockTime duration, timestamp;
454 GstClockTime running_time, stream_time;
455 guint64 offset, offset_end;
459 if (!multifilesink->post_messages)
462 segment = &GST_BASE_SINK (multifilesink)->segment;
463 format = segment->format;
465 timestamp = GST_BUFFER_TIMESTAMP (buffer);
466 duration = GST_BUFFER_DURATION (buffer);
467 offset = GST_BUFFER_OFFSET (buffer);
468 offset_end = GST_BUFFER_OFFSET_END (buffer);
470 running_time = gst_segment_to_running_time (segment, format, timestamp);
471 stream_time = gst_segment_to_stream_time (segment, format, timestamp);
473 gst_multi_file_sink_post_message_full (multifilesink, timestamp, duration,
474 offset, offset_end, running_time, stream_time, filename);
478 gst_multi_file_sink_write_stream_headers (GstMultiFileSink * sink)
482 if (sink->streamheaders == NULL)
485 /* we want to write these at the beginning */
486 g_assert (sink->cur_file_size == 0);
488 for (i = 0; i < sink->n_streamheaders; i++) {
494 hdr = sink->streamheaders[i];
495 sdata = gst_buffer_map (hdr, &ssize, NULL, GST_MAP_READ);
496 ret = fwrite (sdata, ssize, 1, sink->file);
497 gst_buffer_unmap (hdr, sdata, ssize);
502 sink->cur_file_size += ssize;
509 gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
511 GstMultiFileSink *multifilesink;
516 GError *error = NULL;
518 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
520 multifilesink = GST_MULTI_FILE_SINK (sink);
522 switch (multifilesink->next_file) {
523 case GST_MULTI_FILE_SINK_NEXT_BUFFER:
524 gst_multi_file_sink_ensure_max_files (multifilesink);
526 filename = g_strdup_printf (multifilesink->filename,
527 multifilesink->index);
528 ret = g_file_set_contents (filename, (char *) data, size, &error);
532 multifilesink->files = g_slist_append (multifilesink->files, filename);
533 multifilesink->n_files += 1;
535 gst_multi_file_sink_post_message (multifilesink, buffer, filename);
536 multifilesink->index++;
539 case GST_MULTI_FILE_SINK_NEXT_DISCONT:
540 if (GST_BUFFER_IS_DISCONT (buffer)) {
541 if (multifilesink->file)
542 gst_multi_file_sink_close_file (multifilesink, buffer);
545 if (multifilesink->file == NULL) {
546 if (!gst_multi_file_sink_open_next_file (multifilesink))
547 goto stdio_write_error;
550 ret = fwrite (data, size, 1, multifilesink->file);
552 goto stdio_write_error;
555 case GST_MULTI_FILE_SINK_NEXT_KEY_FRAME:
556 if (multifilesink->next_segment == GST_CLOCK_TIME_NONE) {
557 if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
558 multifilesink->next_segment = GST_BUFFER_TIMESTAMP (buffer) +
563 if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
564 GST_BUFFER_TIMESTAMP (buffer) >= multifilesink->next_segment &&
565 !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
566 if (multifilesink->file)
567 gst_multi_file_sink_close_file (multifilesink, buffer);
569 multifilesink->next_segment += 10 * GST_SECOND;
572 if (multifilesink->file == NULL) {
573 if (!gst_multi_file_sink_open_next_file (multifilesink))
574 goto stdio_write_error;
576 gst_multi_file_sink_write_stream_headers (multifilesink);
579 ret = fwrite (data, size, 1, multifilesink->file);
581 goto stdio_write_error;
584 case GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT:
585 if (multifilesink->file == NULL) {
586 if (!gst_multi_file_sink_open_next_file (multifilesink))
587 goto stdio_write_error;
590 if (!gst_multi_file_sink_write_stream_headers (multifilesink))
591 goto stdio_write_error;
593 ret = fwrite (data, size, 1, multifilesink->file);
596 goto stdio_write_error;
599 case GST_MULTI_FILE_SINK_NEXT_MAX_SIZE:{
602 new_size = multifilesink->cur_file_size + size;
603 if (new_size > multifilesink->max_file_size) {
605 GST_INFO_OBJECT (multifilesink, "current size: %" G_GUINT64_FORMAT
606 ", new_size: %" G_GUINT64_FORMAT ", max. size %" G_GUINT64_FORMAT,
607 multifilesink->cur_file_size, new_size,
608 multifilesink->max_file_size);
610 if (multifilesink->file != NULL)
611 gst_multi_file_sink_close_file (multifilesink, NULL);
614 if (multifilesink->file == NULL) {
615 if (!gst_multi_file_sink_open_next_file (multifilesink))
616 goto stdio_write_error;
618 gst_multi_file_sink_write_stream_headers (multifilesink);
621 ret = fwrite (data, size, 1, multifilesink->file);
624 goto stdio_write_error;
626 multifilesink->cur_file_size += size;
630 g_assert_not_reached ();
633 gst_buffer_unmap (buffer, data, size);
639 switch (error->code) {
640 case G_FILE_ERROR_NOSPC:{
641 GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT, (NULL),
646 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
647 ("Error while writing to file \"%s\".", filename),
648 ("%s", g_strerror (errno)));
651 g_error_free (error);
654 gst_buffer_unmap (buffer, data, size);
655 return GST_FLOW_ERROR;
659 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
660 ("Error while writing to file."), (NULL));
661 gst_buffer_unmap (buffer, data, size);
662 return GST_FLOW_ERROR;
667 buffer_list_calc_size (GstBuffer ** buf, guint idx, gpointer data)
669 guint *p_size = data;
672 buf_size = gst_buffer_get_size (*buf);
673 GST_TRACE ("buffer %u has size %" G_GSIZE_FORMAT, idx, buf_size);
680 buffer_list_copy_data (GstBuffer ** buf, guint idx, gpointer data)
682 GstBuffer *dest = data;
686 gst_buffer_copy_into (dest, *buf, GST_BUFFER_COPY_METADATA, 0, -1);
688 num = gst_buffer_n_memory (*buf);
689 for (i = 0; i < num; ++i) {
692 mem = gst_buffer_peek_memory (*buf, i, GST_MAP_READ);
693 gst_buffer_take_memory (dest, -1, gst_memory_ref (mem));
699 /* Our assumption for now is that the buffers in a buffer list should always
700 * end up in the same file. If someone wants different behaviour, they'll just
701 * have to add a property for that. */
703 gst_multi_file_sink_render_list (GstBaseSink * sink, GstBufferList * list)
708 gst_buffer_list_foreach (list, buffer_list_calc_size, &size);
709 GST_LOG_OBJECT (sink, "total size of buffer list %p: %u", list, size);
711 /* copy all buffers in the list into one single buffer, so we can use
712 * the normal render function (FIXME: optimise to avoid the memcpy) */
713 buf = gst_buffer_new ();
714 gst_buffer_list_foreach (list, buffer_list_copy_data, buf);
715 g_assert (gst_buffer_get_size (buf) == size);
717 gst_multi_file_sink_render (sink, buf);
718 gst_buffer_unref (buf);
724 gst_multi_file_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
726 GstMultiFileSink *multifilesink;
727 GstStructure *structure;
729 multifilesink = GST_MULTI_FILE_SINK (sink);
731 structure = gst_caps_get_structure (caps, 0);
735 value = gst_structure_get_value (structure, "streamheader");
737 if (GST_VALUE_HOLDS_ARRAY (value)) {
740 if (multifilesink->streamheaders) {
741 for (i = 0; i < multifilesink->n_streamheaders; i++) {
742 gst_buffer_unref (multifilesink->streamheaders[i]);
744 g_free (multifilesink->streamheaders);
747 multifilesink->n_streamheaders = gst_value_array_get_size (value);
748 multifilesink->streamheaders =
749 g_malloc (sizeof (GstBuffer *) * multifilesink->n_streamheaders);
751 for (i = 0; i < multifilesink->n_streamheaders; i++) {
752 multifilesink->streamheaders[i] =
753 gst_buffer_ref (gst_value_get_buffer (gst_value_array_get_value
763 gst_multi_file_sink_ensure_max_files (GstMultiFileSink * multifilesink)
767 while (multifilesink->max_files &&
768 multifilesink->n_files >= multifilesink->max_files) {
769 filename = multifilesink->files->data;
772 multifilesink->files = g_slist_delete_link (multifilesink->files,
773 multifilesink->files);
774 multifilesink->n_files -= 1;
779 gst_multi_file_sink_event (GstBaseSink * sink, GstEvent * event)
781 GstMultiFileSink *multifilesink;
784 multifilesink = GST_MULTI_FILE_SINK (sink);
786 switch (GST_EVENT_TYPE (event)) {
787 case GST_EVENT_CUSTOM_DOWNSTREAM:
789 GstClockTime timestamp, duration;
790 GstClockTime running_time, stream_time;
791 guint64 offset, offset_end;
792 gboolean all_headers;
795 if (multifilesink->next_file != GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT ||
796 !gst_video_event_is_force_key_unit (event))
799 gst_video_event_parse_downstream_force_key_unit (event, ×tamp,
800 &stream_time, &running_time, &all_headers, &count);
802 if (multifilesink->force_key_unit_count != -1 &&
803 multifilesink->force_key_unit_count == count)
806 multifilesink->force_key_unit_count = count;
808 if (multifilesink->file) {
809 duration = GST_CLOCK_TIME_NONE;
810 offset = offset_end = -1;
811 filename = g_strdup_printf (multifilesink->filename,
812 multifilesink->index);
813 gst_multi_file_sink_post_message_full (multifilesink, timestamp,
814 duration, offset, offset_end, running_time, stream_time, filename);
818 gst_multi_file_sink_close_file (multifilesink, NULL);
822 if (multifilesink->file == NULL) {
823 if (!gst_multi_file_sink_open_next_file (multifilesink))
824 goto stdio_write_error;
834 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
839 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
840 ("Error while writing to file."), (NULL));
841 gst_event_unref (event);
847 gst_multi_file_sink_open_next_file (GstMultiFileSink * multifilesink)
851 g_return_val_if_fail (multifilesink->file == NULL, FALSE);
853 gst_multi_file_sink_ensure_max_files (multifilesink);
854 filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
855 multifilesink->file = g_fopen (filename, "wb");
856 if (multifilesink->file == NULL) {
861 GST_INFO_OBJECT (multifilesink, "opening file %s", filename);
862 multifilesink->files = g_slist_append (multifilesink->files, filename);
863 multifilesink->n_files += 1;
865 multifilesink->cur_file_size = 0;
870 gst_multi_file_sink_close_file (GstMultiFileSink * multifilesink,
875 fclose (multifilesink->file);
876 multifilesink->file = NULL;
879 filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
880 gst_multi_file_sink_post_message (multifilesink, buffer, filename);
884 multifilesink->index++;