diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 0ff4ab7d18..62e8272e68 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -35,6 +35,7 @@ #endif #include "gstimagecapturebin.h" +#include "camerabingeneral.h" /* prototypes */ @@ -42,10 +43,15 @@ enum { PROP_0, - PROP_LOCATION + PROP_LOCATION, + PROP_ENCODER }; #define DEFAULT_LOCATION "img_%d" +#define DEFAULT_COLORSPACE "ffmpegcolorspace" +#define DEFAULT_ENCODER "jpegenc" +#define DEFAULT_MUXER "jifmux" +#define DEFAULT_SINK "multifilesink" /* pad templates */ @@ -64,6 +70,22 @@ GST_BOILERPLATE (GstImageCaptureBin, gst_image_capture_bin, GstBin, static GstStateChangeReturn gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_image_capture_bin_set_encoder (GstImageCaptureBin * imagebin, + GstElement * encoder) +{ + GST_DEBUG_OBJECT (GST_OBJECT (imagebin), + "Setting image encoder %" GST_PTR_FORMAT, encoder); + + if (imagebin->user_encoder) + g_object_unref (imagebin->user_encoder); + + if (encoder) + g_object_ref (encoder); + + imagebin->user_encoder = encoder; +} + static void gst_image_capture_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -78,6 +100,9 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, g_object_set (imagebin, "location", imagebin->location, NULL); } break; + case PROP_ENCODER: + gst_image_capture_bin_set_encoder (imagebin, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -94,6 +119,9 @@ gst_image_capture_bin_get_property (GObject * object, guint prop_id, case PROP_LOCATION: g_value_set_string (value, imagebin->location); break; + case PROP_ENCODER: + g_value_set_object (value, imagebin->encoder); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -144,6 +172,11 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) "Location to save the captured files. A %%d can be used as a " "placeholder for a capture count", DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ENCODER, + g_param_spec_object ("image-encoder", "Image encoder", + "Image encoder GStreamer element (default is jpegenc)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -159,15 +192,14 @@ gst_image_capture_bin_init (GstImageCaptureBin * imagebin, gst_element_add_pad (GST_ELEMENT_CAST (imagebin), imagebin->ghostpad); imagebin->location = g_strdup (DEFAULT_LOCATION); + imagebin->encoder = NULL; + imagebin->user_encoder = NULL; } static gboolean gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) { GstElement *colorspace; - GstElement *encoder; - GstElement *muxer; - GstElement *sink; GstPad *pad = NULL; if (imagebin->elements_created) @@ -175,30 +207,36 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) /* create elements */ colorspace = - gst_element_factory_make ("ffmpegcolorspace", "imagebin-colorspace"); + gst_camerabin_create_and_add_element (GST_BIN (imagebin), + DEFAULT_COLORSPACE); if (!colorspace) goto error; - encoder = gst_element_factory_make ("jpegenc", "imagebin-encoder"); - if (!encoder) + if (imagebin->user_encoder) { + imagebin->encoder = imagebin->user_encoder; + if (!gst_camerabin_add_element (GST_BIN (imagebin), imagebin->encoder)) { + goto error; + } + } else { + imagebin->encoder = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), + DEFAULT_ENCODER); + if (!imagebin->encoder) + goto error; + } + + imagebin->muxer = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_MUXER); + if (!imagebin->muxer) goto error; - muxer = gst_element_factory_make ("jifmux", "imagebin-muxer"); - if (!muxer) + imagebin->sink = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_SINK); + if (!imagebin->sink) goto error; - sink = gst_element_factory_make ("multifilesink", "imagebin-sink"); - if (!sink) - goto error; - - imagebin->sink = sink; - g_object_set (sink, "location", imagebin->location, "async", FALSE, NULL); - - /* add and link */ - gst_bin_add_many (GST_BIN_CAST (imagebin), colorspace, encoder, muxer, sink, + g_object_set (imagebin->sink, "location", imagebin->location, "async", FALSE, NULL); - if (!gst_element_link_many (colorspace, encoder, muxer, sink, NULL)) - goto error; /* add ghostpad */ pad = gst_element_get_static_pad (colorspace, "sink"); diff --git a/gst/camerabin2/gstimagecapturebin.h b/gst/camerabin2/gstimagecapturebin.h index 912dec0992..63402dbf2d 100644 --- a/gst/camerabin2/gstimagecapturebin.h +++ b/gst/camerabin2/gstimagecapturebin.h @@ -39,9 +39,12 @@ struct _GstImageCaptureBin GstPad *ghostpad; GstElement *sink; + GstElement *muxer; /* props */ gchar *location; + GstElement *encoder; + GstElement *user_encoder; gboolean elements_created; }; diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 58331c1612..22197916eb 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -66,7 +66,7 @@ static gchar * make_test_file_name (void) { return g_strdup_printf ("%s" G_DIR_SEPARATOR_S - "imagecapturbintest_%%d.cap", g_get_tmp_dir ()); + "imagecapturebintest_%%d.cap", g_get_tmp_dir ()); } GST_START_TEST (test_simple_capture) @@ -119,6 +119,59 @@ GST_START_TEST (test_simple_capture) GST_END_TEST; +GST_START_TEST (test_setting_encoder) +{ + GstImageCaptureBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + GstElement *encoder; + gchar *test_file_name; + gint i; + + gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (); + g_object_set (ctx.icbin, "location", test_file_name, NULL); + + encoder = gst_element_factory_make ("jpegenc", NULL); + g_object_set (ctx.icbin, "image-encoder", encoder, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there are N_BUFFERS files */ + for (i = 0; i < N_BUFFERS; i++) { + gchar *filename; + FILE *f; + + filename = g_strdup_printf (test_file_name, i); + + fail_unless (g_file_test (filename, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (filename, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (filename, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + g_free (filename); + } + + gstimagecapturebin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + static Suite * imagecapturebin_suite (void) { @@ -127,6 +180,7 @@ imagecapturebin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_capture); + tcase_add_test (tc_chain, test_setting_encoder); return s; }