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_static_metadata (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++) {
493 hdr = sink->streamheaders[i];
494 gst_buffer_map (hdr, &map, GST_MAP_READ);
495 ret = fwrite (map.data, map.size, 1, sink->file);
496 gst_buffer_unmap (hdr, &map);
501 sink->cur_file_size += map.size;
508 gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
510 GstMultiFileSink *multifilesink;
514 GError *error = NULL;
516 gst_buffer_map (buffer, &map, GST_MAP_READ);
518 multifilesink = GST_MULTI_FILE_SINK (sink);
520 switch (multifilesink->next_file) {
521 case GST_MULTI_FILE_SINK_NEXT_BUFFER:
522 gst_multi_file_sink_ensure_max_files (multifilesink);
524 filename = g_strdup_printf (multifilesink->filename,
525 multifilesink->index);
526 ret = g_file_set_contents (filename, (char *) map.data, map.size, &error);
530 multifilesink->files = g_slist_append (multifilesink->files, filename);
531 multifilesink->n_files += 1;
533 gst_multi_file_sink_post_message (multifilesink, buffer, filename);
534 multifilesink->index++;
537 case GST_MULTI_FILE_SINK_NEXT_DISCONT:
538 if (GST_BUFFER_IS_DISCONT (buffer)) {
539 if (multifilesink->file)
540 gst_multi_file_sink_close_file (multifilesink, buffer);
543 if (multifilesink->file == NULL) {
544 if (!gst_multi_file_sink_open_next_file (multifilesink))
545 goto stdio_write_error;
548 ret = fwrite (map.data, map.size, 1, multifilesink->file);
550 goto stdio_write_error;
553 case GST_MULTI_FILE_SINK_NEXT_KEY_FRAME:
554 if (multifilesink->next_segment == GST_CLOCK_TIME_NONE) {
555 if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
556 multifilesink->next_segment = GST_BUFFER_TIMESTAMP (buffer) +
561 if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
562 GST_BUFFER_TIMESTAMP (buffer) >= multifilesink->next_segment &&
563 !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
564 if (multifilesink->file)
565 gst_multi_file_sink_close_file (multifilesink, buffer);
567 multifilesink->next_segment += 10 * GST_SECOND;
570 if (multifilesink->file == NULL) {
571 if (!gst_multi_file_sink_open_next_file (multifilesink))
572 goto stdio_write_error;
574 gst_multi_file_sink_write_stream_headers (multifilesink);
577 ret = fwrite (map.data, map.size, 1, multifilesink->file);
579 goto stdio_write_error;
582 case GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT:
583 if (multifilesink->file == NULL) {
584 if (!gst_multi_file_sink_open_next_file (multifilesink))
585 goto stdio_write_error;
588 if (!gst_multi_file_sink_write_stream_headers (multifilesink))
589 goto stdio_write_error;
591 ret = fwrite (map.data, map.size, 1, multifilesink->file);
594 goto stdio_write_error;
597 case GST_MULTI_FILE_SINK_NEXT_MAX_SIZE:{
600 new_size = multifilesink->cur_file_size + map.size;
601 if (new_size > multifilesink->max_file_size) {
603 GST_INFO_OBJECT (multifilesink, "current size: %" G_GUINT64_FORMAT
604 ", new_size: %" G_GUINT64_FORMAT ", max. size %" G_GUINT64_FORMAT,
605 multifilesink->cur_file_size, new_size,
606 multifilesink->max_file_size);
608 if (multifilesink->file != NULL)
609 gst_multi_file_sink_close_file (multifilesink, NULL);
612 if (multifilesink->file == NULL) {
613 if (!gst_multi_file_sink_open_next_file (multifilesink))
614 goto stdio_write_error;
616 gst_multi_file_sink_write_stream_headers (multifilesink);
619 ret = fwrite (map.data, map.size, 1, multifilesink->file);
622 goto stdio_write_error;
624 multifilesink->cur_file_size += map.size;
628 g_assert_not_reached ();
631 gst_buffer_unmap (buffer, &map);
637 switch (error->code) {
638 case G_FILE_ERROR_NOSPC:{
639 GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT, (NULL),
644 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
645 ("Error while writing to file \"%s\".", filename),
646 ("%s", g_strerror (errno)));
649 g_error_free (error);
652 gst_buffer_unmap (buffer, &map);
653 return GST_FLOW_ERROR;
658 GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT,
659 ("Error while writing to file."), ("%s", g_strerror (errno)));
662 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
663 ("Error while writing to file."), ("%s", g_strerror (errno)));
665 gst_buffer_unmap (buffer, &map);
666 return GST_FLOW_ERROR;
670 buffer_list_calc_size (GstBuffer ** buf, guint idx, gpointer data)
672 guint *p_size = data;
675 buf_size = gst_buffer_get_size (*buf);
676 GST_TRACE ("buffer %u has size %" G_GSIZE_FORMAT, idx, buf_size);
683 buffer_list_copy_data (GstBuffer ** buf, guint idx, gpointer data)
685 GstBuffer *dest = data;
689 gst_buffer_copy_into (dest, *buf, GST_BUFFER_COPY_METADATA, 0, -1);
691 num = gst_buffer_n_memory (*buf);
692 for (i = 0; i < num; ++i) {
695 mem = gst_buffer_get_memory (*buf, i);
696 gst_buffer_append_memory (dest, mem);
702 /* Our assumption for now is that the buffers in a buffer list should always
703 * end up in the same file. If someone wants different behaviour, they'll just
704 * have to add a property for that. */
706 gst_multi_file_sink_render_list (GstBaseSink * sink, GstBufferList * list)
711 gst_buffer_list_foreach (list, buffer_list_calc_size, &size);
712 GST_LOG_OBJECT (sink, "total size of buffer list %p: %u", list, size);
714 /* copy all buffers in the list into one single buffer, so we can use
715 * the normal render function (FIXME: optimise to avoid the memcpy) */
716 buf = gst_buffer_new ();
717 gst_buffer_list_foreach (list, buffer_list_copy_data, buf);
718 g_assert (gst_buffer_get_size (buf) == size);
720 gst_multi_file_sink_render (sink, buf);
721 gst_buffer_unref (buf);
727 gst_multi_file_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
729 GstMultiFileSink *multifilesink;
730 GstStructure *structure;
732 multifilesink = GST_MULTI_FILE_SINK (sink);
734 structure = gst_caps_get_structure (caps, 0);
738 value = gst_structure_get_value (structure, "streamheader");
740 if (GST_VALUE_HOLDS_ARRAY (value)) {
743 if (multifilesink->streamheaders) {
744 for (i = 0; i < multifilesink->n_streamheaders; i++) {
745 gst_buffer_unref (multifilesink->streamheaders[i]);
747 g_free (multifilesink->streamheaders);
750 multifilesink->n_streamheaders = gst_value_array_get_size (value);
751 multifilesink->streamheaders =
752 g_malloc (sizeof (GstBuffer *) * multifilesink->n_streamheaders);
754 for (i = 0; i < multifilesink->n_streamheaders; i++) {
755 multifilesink->streamheaders[i] =
756 gst_buffer_ref (gst_value_get_buffer (gst_value_array_get_value
766 gst_multi_file_sink_ensure_max_files (GstMultiFileSink * multifilesink)
770 while (multifilesink->max_files &&
771 multifilesink->n_files >= multifilesink->max_files) {
772 filename = multifilesink->files->data;
775 multifilesink->files = g_slist_delete_link (multifilesink->files,
776 multifilesink->files);
777 multifilesink->n_files -= 1;
782 gst_multi_file_sink_event (GstBaseSink * sink, GstEvent * event)
784 GstMultiFileSink *multifilesink;
787 multifilesink = GST_MULTI_FILE_SINK (sink);
789 switch (GST_EVENT_TYPE (event)) {
790 case GST_EVENT_CUSTOM_DOWNSTREAM:
792 GstClockTime timestamp, duration;
793 GstClockTime running_time, stream_time;
794 guint64 offset, offset_end;
795 gboolean all_headers;
798 if (multifilesink->next_file != GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT ||
799 !gst_video_event_is_force_key_unit (event))
802 gst_video_event_parse_downstream_force_key_unit (event, ×tamp,
803 &stream_time, &running_time, &all_headers, &count);
805 if (multifilesink->force_key_unit_count != -1 &&
806 multifilesink->force_key_unit_count == count)
809 multifilesink->force_key_unit_count = count;
811 if (multifilesink->file) {
812 duration = GST_CLOCK_TIME_NONE;
813 offset = offset_end = -1;
814 filename = g_strdup_printf (multifilesink->filename,
815 multifilesink->index);
816 gst_multi_file_sink_post_message_full (multifilesink, timestamp,
817 duration, offset, offset_end, running_time, stream_time, filename);
821 gst_multi_file_sink_close_file (multifilesink, NULL);
825 if (multifilesink->file == NULL) {
826 if (!gst_multi_file_sink_open_next_file (multifilesink))
827 goto stdio_write_error;
837 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
842 GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
843 ("Error while writing to file."), (NULL));
844 gst_event_unref (event);
850 gst_multi_file_sink_open_next_file (GstMultiFileSink * multifilesink)
854 g_return_val_if_fail (multifilesink->file == NULL, FALSE);
856 gst_multi_file_sink_ensure_max_files (multifilesink);
857 filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
858 multifilesink->file = g_fopen (filename, "wb");
859 if (multifilesink->file == NULL) {
864 GST_INFO_OBJECT (multifilesink, "opening file %s", filename);
865 multifilesink->files = g_slist_append (multifilesink->files, filename);
866 multifilesink->n_files += 1;
868 multifilesink->cur_file_size = 0;
873 gst_multi_file_sink_close_file (GstMultiFileSink * multifilesink,
878 fclose (multifilesink->file);
879 multifilesink->file = NULL;
882 filename = g_strdup_printf (multifilesink->filename, multifilesink->index);
883 gst_multi_file_sink_post_message (multifilesink, buffer, filename);
887 multifilesink->index++;