From: Alessandro Decina Date: Sun, 17 Jul 2011 21:56:04 +0000 (+0200) Subject: multifilesink: add flag to cut after a force key unit event X-Git-Tag: 1.19.3~509^2~7136^2~214 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ed987552415dad43041291f0210876e39e13c8cd;p=platform%2Fupstream%2Fgstreamer.git multifilesink: add flag to cut after a force key unit event --- diff --git a/gst/multifile/Makefile.am b/gst/multifile/Makefile.am index 519bd1bfca..e6f9016a54 100644 --- a/gst/multifile/Makefile.am +++ b/gst/multifile/Makefile.am @@ -8,7 +8,7 @@ libgstmultifile_la_SOURCES = \ gstsplitfilesrc.c \ patternspec.c libgstmultifile_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) -libgstmultifile_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) +libgstmultifile_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) -lgstvideo-@GST_MAJORMINOR@ libgstmultifile_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstmultifile_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c index a724d5d8c0..736ce18fe0 100644 --- a/gst/multifile/gstmultifilesink.c +++ b/gst/multifile/gstmultifilesink.c @@ -110,6 +110,7 @@ # include "config.h" #endif #include +#include #include #include "gstmultifilesink.h" @@ -156,6 +157,8 @@ static void gst_multi_file_sink_close_file (GstMultiFileSink * multifilesink, GstBuffer * buffer); static void gst_multi_file_sink_ensure_max_files (GstMultiFileSink * multifilesink); +static gboolean gst_multi_file_sink_event (GstBaseSink * sink, + GstEvent * event); #define GST_TYPE_MULTI_FILE_SINK_NEXT (gst_multi_file_sink_next_get_type ()) static GType @@ -168,6 +171,8 @@ gst_multi_file_sink_next_get_type (void) "discont"}, {GST_MULTI_FILE_SINK_NEXT_KEY_FRAME, "New file at each key frame " "(Useful for MPEG-TS segmenting)", "key-frame"}, + {GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT, + "New file after a force key unit event", "key-unit-event"}, {0, NULL, NULL} }; @@ -265,6 +270,7 @@ gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass) gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_file_sink_render); gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_multi_file_sink_set_caps); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_multi_file_sink_event); } static void @@ -281,6 +287,7 @@ gst_multi_file_sink_init (GstMultiFileSink * multifilesink, gst_base_sink_set_sync (GST_BASE_SINK (multifilesink), FALSE); multifilesink->next_segment = GST_CLOCK_TIME_NONE; + multifilesink->force_key_unit_count = -1; } static void @@ -383,46 +390,64 @@ gst_multi_file_sink_stop (GstBaseSink * sink) multifilesink->streamheaders = NULL; } + multifilesink->force_key_unit_count = -1; + return TRUE; } +static void +gst_multi_file_sink_post_message_full (GstMultiFileSink * multifilesink, + GstClockTime timestamp, GstClockTime duration, GstClockTime offset, + GstClockTime offset_end, GstClockTime running_time, + GstClockTime stream_time, const char *filename) +{ + GstStructure *s; + + if (!multifilesink->post_messages) + return; + + 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)); +} + + 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; - guint64 offset, offset_end; - GstStructure *s; - GstSegment *segment; - GstFormat format; - - segment = &GST_BASE_SINK (multifilesink)->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)); - } + GstClockTime duration, timestamp; + GstClockTime running_time, stream_time; + guint64 offset, offset_end; + GstSegment *segment; + GstFormat format; + + if (!multifilesink->post_messages) + return; + + segment = &GST_BASE_SINK (multifilesink)->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); + + gst_multi_file_sink_post_message_full (multifilesink, timestamp, duration, + offset, offset_end, running_time, stream_time, filename); } static GstFlowReturn @@ -508,6 +533,18 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer) } } + ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1, + multifilesink->file); + if (ret != 1) + goto stdio_write_error; + + break; + case GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT: + if (multifilesink->file == NULL) { + if (!gst_multi_file_sink_open_next_file (multifilesink)) + goto stdio_write_error; + } + ret = fwrite (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 1, multifilesink->file); if (ret != 1) @@ -601,6 +638,71 @@ gst_multi_file_sink_ensure_max_files (GstMultiFileSink * multifilesink) } } +static gboolean +gst_multi_file_sink_event (GstBaseSink * sink, GstEvent * event) +{ + GstMultiFileSink *multifilesink; + gchar *filename; + gboolean res = TRUE; + + multifilesink = GST_MULTI_FILE_SINK (sink); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + { + GstClockTime timestamp, duration; + GstClockTime running_time, stream_time; + guint64 offset, offset_end; + gboolean all_headers; + guint count; + + if (multifilesink->next_file != GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT || + !gst_video_event_is_force_key_unit (event)) + goto out; + + gst_video_event_parse_downstream_force_key_unit (event, ×tamp, + &stream_time, &running_time, &all_headers, &count); + + if (multifilesink->force_key_unit_count != -1 && + multifilesink->force_key_unit_count == count) + goto out; + + multifilesink->force_key_unit_count = count; + + if (multifilesink->file) { + duration = GST_CLOCK_TIME_NONE; + offset = offset_end = -1; + filename = g_strdup_printf (multifilesink->filename, + multifilesink->index); + gst_multi_file_sink_post_message_full (multifilesink, timestamp, + duration, offset, offset_end, running_time, stream_time, filename); + + g_free (filename); + + gst_multi_file_sink_close_file (multifilesink, NULL); + + } + + if (multifilesink->file == NULL) { + if (!gst_multi_file_sink_open_next_file (multifilesink)) + goto stdio_write_error; + } + + break; + } + default: + break; + } + +out: + return res; + +stdio_write_error: + GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE, + ("Error while writing to file."), (NULL)); + return FALSE; +} + static gboolean gst_multi_file_sink_open_next_file (GstMultiFileSink * multifilesink) { @@ -616,6 +718,7 @@ gst_multi_file_sink_open_next_file (GstMultiFileSink * multifilesink) return FALSE; } + GST_INFO_OBJECT (multifilesink, "opening file %s", filename); multifilesink->files = g_slist_append (multifilesink->files, filename); multifilesink->n_files += 1; diff --git a/gst/multifile/gstmultifilesink.h b/gst/multifile/gstmultifilesink.h index f2f005ff57..543834ed19 100644 --- a/gst/multifile/gstmultifilesink.h +++ b/gst/multifile/gstmultifilesink.h @@ -55,7 +55,8 @@ typedef struct _GstMultiFileSinkClass GstMultiFileSinkClass; typedef enum { GST_MULTI_FILE_SINK_NEXT_BUFFER, GST_MULTI_FILE_SINK_NEXT_DISCONT, - GST_MULTI_FILE_SINK_NEXT_KEY_FRAME + GST_MULTI_FILE_SINK_NEXT_KEY_FRAME, + GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT } GstMultiFileSinkNext; struct _GstMultiFileSink @@ -75,6 +76,7 @@ struct _GstMultiFileSink int n_streamheaders; GstBuffer **streamheaders; + guint force_key_unit_count; }; struct _GstMultiFileSinkClass diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index b466193629..bbee1e354c 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -237,6 +237,8 @@ elements_level_LDADD = $(LDADD) $(LIBM) elements_matroskamux_LDADD = $(GST_BASE_LIBS) $(LDADD) $(LIBM) +elements_multifile_LDADD = $(GST_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(LDADD) $(LIBM) + elements_qtmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) elements_qtmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstpbutils-@GST_MAJORMINOR@ \ $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CHECK_LIBS) diff --git a/tests/check/elements/multifile.c b/tests/check/elements/multifile.c index 52ce2ceb87..2a698a5a08 100644 --- a/tests/check/elements/multifile.c +++ b/tests/check/elements/multifile.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -71,10 +72,10 @@ GST_START_TEST (test_multifilesink_key_frame) pipeline = gst_parse_launch - ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink", + ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink name=mfs", NULL); fail_if (pipeline == NULL); - mfs = gst_bin_get_by_name (GST_BIN (pipeline), "multifilesink0"); + mfs = gst_bin_get_by_name (GST_BIN (pipeline), "mfs"); fail_if (mfs == NULL); mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL); g_object_set (G_OBJECT (mfs), "location", mfs_pattern, NULL); @@ -144,6 +145,65 @@ GST_START_TEST (test_multifilesink_max_files) g_free (mfs_pattern); g_free (my_tmpdir); } +GST_END_TEST; + +GST_START_TEST (test_multifilesink_key_unit) +{ + GstElement *mfs; + int i; + const gchar *tmpdir; + gchar *my_tmpdir; + gchar *template; + gchar *mfs_pattern; + GstBuffer *buf; + GstPad *sink; + + tmpdir = g_get_tmp_dir (); + template = g_build_filename (tmpdir, "multifile-test-XXXXXX", NULL); + my_tmpdir = g_mkdtemp (template); + fail_if (my_tmpdir == NULL); + + mfs = gst_element_factory_make ("multifilesink", NULL); + fail_if (mfs == NULL); + mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL); + g_object_set (G_OBJECT (mfs), "location", mfs_pattern, "next-file", 3, NULL); + fail_if (gst_element_set_state (mfs, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE); + + sink = gst_element_get_static_pad (mfs, "sink"); + buf = gst_buffer_new_and_alloc (4); + + memcpy (GST_BUFFER_DATA (buf), "foo", 4); + fail_if (gst_pad_chain (sink, gst_buffer_ref (buf)) != GST_FLOW_OK); + + memcpy (GST_BUFFER_DATA (buf), "bar", 4); + fail_if (gst_pad_chain (sink, gst_buffer_ref (buf)) != GST_FLOW_OK); + + fail_unless (gst_pad_send_event (sink, + gst_video_event_new_downstream_force_key_unit (GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, TRUE, 1))); + + memcpy (GST_BUFFER_DATA (buf), "baz", 4); + fail_if (gst_pad_chain (sink, buf) != GST_FLOW_OK); + + fail_if (gst_element_set_state (mfs, + GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE); + + for (i = 0; i < 2; i++) { + char *s; + + s = g_strdup_printf (mfs_pattern, i); + fail_if (g_remove (s) != 0); + g_free (s); + } + fail_if (g_remove (my_tmpdir) != 0); + + g_free (mfs_pattern); + g_free (my_tmpdir); + g_free (template); + gst_object_unref (sink); + gst_object_unref (mfs); +} GST_END_TEST; @@ -164,10 +224,10 @@ GST_START_TEST (test_multifilesrc) pipeline = gst_parse_launch - ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink", + ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink name=mfs", NULL); fail_if (pipeline == NULL); - mfs = gst_bin_get_by_name (GST_BIN (pipeline), "multifilesink0"); + mfs = gst_bin_get_by_name (GST_BIN (pipeline), "mfs"); fail_if (mfs == NULL); mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL); g_object_set (G_OBJECT (mfs), "location", mfs_pattern, NULL); @@ -214,6 +274,7 @@ libvisual_suite (void) tcase_add_test (tc_chain, test_multifilesink_key_frame); tcase_add_test (tc_chain, test_multifilesink_max_files); + tcase_add_test (tc_chain, test_multifilesink_key_unit); tcase_add_test (tc_chain, test_multifilesrc); return s;