From 5fb8c95eb19a922e76c8210b48af7a145baef704 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 25 Oct 2007 23:42:52 +0000 Subject: [PATCH] Improve documentation, write some tests for multifilesrc/sink for upcoming ->good review. Original commit message from CVS: * gst/multifile/Makefile.am: * gst/multifile/gstmultifilesink.c: * gst/multifile/gstmultifilesrc.c: * tests/check/Makefile.am: * tests/check/elements/multifile.c: Improve documentation, write some tests for multifilesrc/sink for upcoming ->good review. --- ChangeLog | 10 ++++ gst/multifile/Makefile.am | 4 +- gst/multifile/gstmultifilesink.c | 68 ++++++++++++------------ gst/multifile/gstmultifilesrc.c | 67 +++++++++++++++--------- tests/check/Makefile.am | 1 + tests/check/elements/multifile.c | 110 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 60 deletions(-) create mode 100644 tests/check/elements/multifile.c diff --git a/ChangeLog b/ChangeLog index 41cee0b..ebd780f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-10-25 David Schleef + + * gst/multifile/Makefile.am: + * gst/multifile/gstmultifilesink.c: + * gst/multifile/gstmultifilesrc.c: + * tests/check/Makefile.am: + * tests/check/elements/multifile.c: + Improve documentation, write some tests for multifilesrc/sink + for upcoming ->good review. + 2007-10-23 Zaheer Abbas Merali * sys/dvb/gstdvbsrc.c: diff --git a/gst/multifile/Makefile.am b/gst/multifile/Makefile.am index 2863d85..98eb6fd 100644 --- a/gst/multifile/Makefile.am +++ b/gst/multifile/Makefile.am @@ -2,8 +2,8 @@ plugin_LTLIBRARIES = libgstmultifile.la libgstmultifile_la_SOURCES = gstmultifilesink.c gstmultifilesrc.c gstmultifile.c -libgstmultifile_la_CFLAGS = $(GST_CFLAGS) -libgstmultifile_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstmultifile_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstmultifile_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgstmultifile_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstmultifilesrc.h gstmultifilesink.h diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c index 9280f1f..ad615f7 100644 --- a/gst/multifile/gstmultifilesink.c +++ b/gst/multifile/gstmultifilesink.c @@ -23,10 +23,13 @@ */ /** * SECTION:element-multifilesink - * @short_description: write buffers to sequentially-named files + * @short_description: Writes buffers to sequentially-named files * @see_also: #GstFileSrc * - * Write incoming data to a series of files in the local file system. + * + * Write incoming data to a series of sequentially-named files. + * + * */ #ifdef HAVE_CONFIG_H @@ -52,9 +55,13 @@ GST_ELEMENT_DETAILS ("Multi-File Sink", enum { ARG_0, - ARG_LOCATION + ARG_LOCATION, + ARG_INDEX }; +#define DEFAULT_LOCATION "%05d" +#define DEFAULT_INDEX 0 + static void gst_multi_file_sink_dispose (GObject * object); static void gst_multi_file_sink_set_property (GObject * object, guint prop_id, @@ -62,20 +69,9 @@ 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_open_file (GstMultiFileSink * sink); -//static void gst_multi_file_sink_close_file (GstMultiFileSink * sink); - -//static gboolean gst_multi_file_sink_start (GstBaseSink * sink); -//static gboolean gst_multi_file_sink_stop (GstBaseSink * sink); -//static gboolean gst_multi_file_sink_event (GstBaseSink * sink, GstEvent * event); static GstFlowReturn gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer); -//static gboolean gst_multi_file_sink_do_seek (GstMultiFileSink * filesink, -// guint64 new_offset); - -//static gboolean gst_multi_file_sink_query (GstPad * pad, GstQuery * query); - GST_BOILERPLATE (GstMultiFileSink, gst_multi_file_sink, GstBaseSink, @@ -107,14 +103,16 @@ gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass) g_object_class_install_property (gobject_class, ARG_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_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; gstbasesink_class->get_times = NULL; - //gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_multi_file_sink_start); - //gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_multi_file_sink_stop); gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_file_sink_render); - //gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_multi_file_sink_event); if (sizeof (off_t) < 8) { GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT, @@ -123,18 +121,17 @@ gst_multi_file_sink_class_init (GstMultiFileSinkClass * klass) } static void -gst_multi_file_sink_init (GstMultiFileSink * filesink, +gst_multi_file_sink_init (GstMultiFileSink * multifilesink, GstMultiFileSinkClass * g_class) { GstPad *pad; - pad = GST_BASE_SINK_PAD (filesink); - - //gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_multi_file_sink_query)); + pad = GST_BASE_SINK_PAD (multifilesink); - filesink->filename = g_strdup ("output-%05d"); + multifilesink->filename = g_strdup (DEFAULT_LOCATION); + multifilesink->index = DEFAULT_INDEX; - GST_BASE_SINK (filesink)->sync = FALSE; + GST_BASE_SINK (multifilesink)->sync = FALSE; } static void @@ -171,6 +168,9 @@ gst_multi_file_sink_set_property (GObject * object, guint prop_id, case ARG_LOCATION: gst_multi_file_sink_set_location (sink, g_value_get_string (value)); break; + case ARG_INDEX: + sink->index = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -187,6 +187,9 @@ gst_multi_file_sink_get_property (GObject * object, guint prop_id, case ARG_LOCATION: g_value_set_string (value, sink->filename); break; + case ARG_INDEX: + g_value_set_int (value, sink->index); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -200,11 +203,11 @@ gst_multi_file_sink_get_property (GObject * object, guint prop_id, #endif static gchar * -gst_multi_file_sink_get_filename (GstMultiFileSink * filesink) +gst_multi_file_sink_get_filename (GstMultiFileSink * multifilesink) { gchar *filename; - filename = g_strdup_printf (filesink->filename, filesink->index); + filename = g_strdup_printf (multifilesink->filename, multifilesink->index); return filename; } @@ -212,16 +215,16 @@ gst_multi_file_sink_get_filename (GstMultiFileSink * filesink) static GstFlowReturn gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer) { - GstMultiFileSink *filesink; + GstMultiFileSink *multifilesink; guint size; gchar *filename; FILE *file; size = GST_BUFFER_SIZE (buffer); - filesink = GST_MULTI_FILE_SINK (sink); + multifilesink = GST_MULTI_FILE_SINK (sink); - filename = gst_multi_file_sink_get_filename (filesink); + filename = gst_multi_file_sink_get_filename (multifilesink); file = fopen (filename, "wb"); if (!file) { @@ -235,7 +238,7 @@ gst_multi_file_sink_render (GstBaseSink * sink, GstBuffer * buffer) goto handle_error; } - filesink->index++; + multifilesink->index++; fclose (file); @@ -245,12 +248,13 @@ handle_error: { switch (errno) { case ENOSPC:{ - GST_ELEMENT_ERROR (filesink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL)); + GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT, (NULL), + (NULL)); break; } default:{ - GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, - ("Error while writing to file \"%s\".", filesink->filename), + GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE, + ("Error while writing to file \"%s\".", multifilesink->filename), ("%s", g_strerror (errno))); } } diff --git a/gst/multifile/gstmultifilesrc.c b/gst/multifile/gstmultifilesrc.c index 57d02c6..f347257 100644 --- a/gst/multifile/gstmultifilesrc.c +++ b/gst/multifile/gstmultifilesrc.c @@ -20,24 +20,30 @@ */ /** * SECTION:element-multifilesrc - * @short_description: reads buffers from sequentially-named files + * @short_description: Read buffers from sequentially-named files * @see_also: #GstFileSrc * * * * Reads buffers from sequentially named files. If used together with an image - * decoder one needs to use the GstMultiFileSrc::caps property or a capsfilter - * to force to caps containing a framerate. Otherwise imagedecoders send EOS + * decoder, one needs to use the GstMultiFileSrc::caps property or a capsfilter + * to force to caps containing a framerate. Otherwise image decoders send EOS * after the first picture. * * Example launch line * * - * gst-launch multifilesrc location="img.%04d.png" index=0 ! image/png,framerate='(fraction)'1/1 ! pngdec ! ffmpegcolorspace ! ffenc_mpeg4 ! avimux ! filesink location="images.avi" + * gst-launch multifilesrc location="img.%04d.png" index=0 caps="image/png,framerate=\(fraction\)12/1" ! \ + * pngdec ! ffmpegcolorspace ! theoraenc ! oggmux ! \ + * filesink location="images.ogg" * - * This pipeline joins multiple frames into one video. + * This pipeline creates a video file "images.ogg" by joining multiple PNG + * files named img.0000.png, img.0001.png, etc. * - * + * + * File names are created by replacing "%%d" with the index using printf(). + * + * */ #ifdef HAVE_CONFIG_H @@ -82,6 +88,9 @@ enum ARG_CAPS }; +#define DEFAULT_LOCATION "%05d" +#define DEFAULT_INDEX 0 + GST_BOILERPLATE (GstMultiFileSrc, gst_multi_file_src, GstPushSrc, GST_TYPE_PUSH_SRC); @@ -111,13 +120,18 @@ gst_multi_file_src_class_init (GstMultiFileSrcClass * klass) g_object_class_install_property (gobject_class, ARG_LOCATION, g_param_spec_string ("location", "File Location", - "Location of the file to read", NULL, G_PARAM_READWRITE)); + "Pattern to create file names of input files. File names are " + "created by calling sprintf() with the pattern and the current " + "index.", DEFAULT_LOCATION, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, ARG_INDEX, g_param_spec_int ("index", "File Index", - "Index of file to read", 0, INT_MAX, 0, G_PARAM_READWRITE)); + "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)); g_object_class_install_property (gobject_class, ARG_CAPS, g_param_spec_boxed ("caps", "Caps", - "Caps of source pad", GST_TYPE_CAPS, G_PARAM_READWRITE)); + "Caps describing the format of the data.", + GST_TYPE_CAPS, G_PARAM_READWRITE)); gobject_class->dispose = gst_multi_file_src_dispose; @@ -132,14 +146,15 @@ gst_multi_file_src_class_init (GstMultiFileSrcClass * klass) } static void -gst_multi_file_src_init (GstMultiFileSrc * filesrc, +gst_multi_file_src_init (GstMultiFileSrc * multifilesrc, GstMultiFileSrcClass * g_class) { GstPad *pad; - pad = GST_BASE_SRC_PAD (filesrc); + pad = GST_BASE_SRC_PAD (multifilesrc); - filesrc->filename = g_strdup ("output-%05d"); + multifilesrc->index = DEFAULT_INDEX; + multifilesrc->filename = g_strdup (DEFAULT_LOCATION); } static void @@ -160,7 +175,7 @@ gst_multi_file_src_getcaps (GstBaseSrc * src) { GstMultiFileSrc *multi_file_src = GST_MULTI_FILE_SRC (src); - GST_DEBUG ("returning %" GST_PTR_FORMAT, multi_file_src->caps); + GST_DEBUG_OBJECT (src, "returning %" GST_PTR_FORMAT, multi_file_src->caps); if (multi_file_src->caps) { return gst_caps_ref (multi_file_src->caps); @@ -237,11 +252,11 @@ gst_multi_file_src_get_property (GObject * object, guint prop_id, } static gchar * -gst_multi_file_src_get_filename (GstMultiFileSrc * filesrc) +gst_multi_file_src_get_filename (GstMultiFileSrc * multifilesrc) { gchar *filename; - filename = g_strdup_printf (filesrc->filename, filesrc->index); + filename = g_strdup_printf (multifilesrc->filename, multifilesrc->index); return filename; } @@ -249,18 +264,18 @@ gst_multi_file_src_get_filename (GstMultiFileSrc * filesrc) static GstFlowReturn gst_multi_file_src_create (GstPushSrc * src, GstBuffer ** buffer) { - GstMultiFileSrc *filesrc; + GstMultiFileSrc *multifilesrc; guint size; gchar *filename; FILE *file; GstBuffer *buf; int ret; - filesrc = GST_MULTI_FILE_SRC (src); + multifilesrc = GST_MULTI_FILE_SRC (src); - filename = gst_multi_file_src_get_filename (filesrc); + filename = gst_multi_file_src_get_filename (multifilesrc); - GST_DEBUG_OBJECT (filesrc, "reading from file \"%s\".", filename); + GST_DEBUG_OBJECT (multifilesrc, "reading from file \"%s\".", filename); file = fopen (filename, "rb"); if (!file) { @@ -278,15 +293,15 @@ gst_multi_file_src_create (GstPushSrc * src, GstBuffer ** buffer) goto handle_error; } - filesrc->index++; + multifilesrc->index++; GST_BUFFER_SIZE (buf) = size; - GST_BUFFER_OFFSET (buf) = filesrc->offset; - GST_BUFFER_OFFSET_END (buf) = filesrc->offset + size; - filesrc->offset += size; - gst_buffer_set_caps (buf, filesrc->caps); + GST_BUFFER_OFFSET (buf) = multifilesrc->offset; + GST_BUFFER_OFFSET_END (buf) = multifilesrc->offset + size; + multifilesrc->offset += size; + gst_buffer_set_caps (buf, multifilesrc->caps); - GST_DEBUG_OBJECT (filesrc, "read file \"%s\".", filename); + GST_DEBUG_OBJECT (multifilesrc, "read file \"%s\".", filename); fclose (file); g_free (filename); @@ -297,7 +312,7 @@ handle_error: { switch (errno) { default:{ - GST_ELEMENT_ERROR (filesrc, RESOURCE, READ, + GST_ELEMENT_ERROR (multifilesrc, RESOURCE, READ, ("Error while reading from file \"%s\".", filename), ("%s", g_strerror (errno))); } diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 80a94e6..8da6678 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -60,6 +60,7 @@ check_PROGRAMS = \ $(check_timidity) \ elements/bpwsinc \ elements/lpwsinc \ + elements/multifile \ elements/rganalysis \ elements/rglimiter \ elements/rgvolume \ diff --git a/tests/check/elements/multifile.c b/tests/check/elements/multifile.c new file mode 100644 index 0000000..4b5a28f --- /dev/null +++ b/tests/check/elements/multifile.c @@ -0,0 +1,110 @@ +/* GStreamer unit test for multifile plugin + * + * Copyright (C) 2007 David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +static void +run_pipeline (GstElement * pipeline) +{ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_get_state (pipeline, NULL, NULL, -1); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + /* FIXME too lazy */ + g_usleep (1000000); + gst_element_set_state (pipeline, GST_STATE_NULL); +} + +GST_START_TEST (test_multifilesink) +{ + GstElement *pipeline; + int i; + + g_mkdir ("tmpdir", 0700); + + pipeline = + gst_parse_launch + ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink location=tmpdir/%05d", + NULL); + fail_if (pipeline == NULL); + run_pipeline (pipeline); + gst_object_unref (pipeline); + + for (i = 0; i < 10; i++) { + char s[20]; + + sprintf (s, "tmpdir/%05d", i); + fail_if (g_remove (s) != 0); + } + fail_if (g_remove ("tmpdir") != 0); + +} + +GST_END_TEST; + +GST_START_TEST (test_multifilesrc) +{ + GstElement *pipeline; + int i; + + g_mkdir ("tmpdir", 0700); + + pipeline = + gst_parse_launch + ("videotestsrc num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! multifilesink location=tmpdir/%05d", + NULL); + fail_if (pipeline == NULL); + run_pipeline (pipeline); + gst_object_unref (pipeline); + + pipeline = + gst_parse_launch + ("multifilesrc location=tmpdir/%05d ! video/x-raw-yuv,format=(fourcc)I420,width=320,height=240,framerate=10/1 ! fakesink", + NULL); + fail_if (pipeline == NULL); + run_pipeline (pipeline); + gst_object_unref (pipeline); + + for (i = 0; i < 10; i++) { + char s[20]; + + sprintf (s, "tmpdir/%05d", i); + fail_if (g_remove (s) != 0); + } + fail_if (g_remove ("tmpdir") != 0); + +} + +GST_END_TEST; + +static Suite * +libvisual_suite (void) +{ + Suite *s = suite_create ("multifile"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_multifilesink); + tcase_add_test (tc_chain, test_multifilesrc); + + return s; +} + +GST_CHECK_MAIN (libvisual); -- 2.7.4