From f0f8df1a309007776fe81c7eea3eebae4d2e21fc Mon Sep 17 00:00:00 2001 From: Hoseok Chang Date: Mon, 21 Jun 2010 16:17:24 +0300 Subject: [PATCH] camerabin: add "preview-source-filter" property Adds 'preview-source-filter' for adding an element to proccess the preview images before posting them to the bus. --- gst/camerabin/camerabinpreview.c | 23 +++++++++--- gst/camerabin/camerabinpreview.h | 2 +- gst/camerabin/gstcamerabin-enum.h | 3 +- gst/camerabin/gstcamerabin.c | 75 ++++++++++++++++++++++++++++++++++++++- gst/camerabin/gstcamerabin.h | 2 ++ 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/gst/camerabin/camerabinpreview.c b/gst/camerabin/camerabinpreview.c index b7776b9..22fd1ec 100644 --- a/gst/camerabin/camerabinpreview.c +++ b/gst/camerabin/camerabinpreview.c @@ -68,7 +68,8 @@ create_element (const gchar * factory_name, const gchar * elem_name, * Returns: New pipeline, or NULL if error occured. */ GstElement * -gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps) +gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps, + GstElement * src_filter) { GstElement *pipe, *src, *csp, *filter, *vscale, *sink; GError *error = NULL; @@ -93,6 +94,9 @@ gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps) GST_DEBUG ("adding elements"); gst_bin_add_many (GST_BIN (pipe), src, csp, filter, vscale, sink, NULL); + if (src_filter) { + gst_bin_add (GST_BIN (pipe), src_filter); + } GST_DEBUG ("preview format is: %" GST_PTR_FORMAT, caps); @@ -105,9 +109,20 @@ gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps) if (!gst_element_link_pads (src, "src", vscale, "sink")) return FALSE; - GST_DEBUG ("linking vscale->csp"); - if (!gst_element_link_pads (vscale, "src", csp, "sink")) - return FALSE; + if (src_filter) { + GST_DEBUG ("linking vscale->filter"); + if (!gst_element_link_pads (vscale, "src", src_filter, "sink")) { + return FALSE; + } + GST_DEBUG ("linking filter->csp"); + if (!gst_element_link_pads (src_filter, "src", csp, "sink")) { + return FALSE; + } + } else { + GST_DEBUG ("linking vscale->csp"); + if (!gst_element_link_pads (vscale, "src", csp, "sink")) + return FALSE; + } GST_DEBUG ("linking csp->capsfilter"); if (!gst_element_link_pads (csp, "src", filter, "sink")) diff --git a/gst/camerabin/camerabinpreview.h b/gst/camerabin/camerabinpreview.h index 06dedfd..4b4157d 100644 --- a/gst/camerabin/camerabinpreview.h +++ b/gst/camerabin/camerabinpreview.h @@ -27,7 +27,7 @@ G_BEGIN_DECLS GstElement * gst_camerabin_preview_create_pipeline (GstCameraBin * camera, - GstCaps * caps); + GstCaps * caps, GstElement * src_filter); void gst_camerabin_preview_destroy_pipeline (GstCameraBin * camera, GstElement * pipeline); diff --git a/gst/camerabin/gstcamerabin-enum.h b/gst/camerabin/gstcamerabin-enum.h index d169559..4a7e7f3 100644 --- a/gst/camerabin/gstcamerabin-enum.h +++ b/gst/camerabin/gstcamerabin-enum.h @@ -66,7 +66,8 @@ enum ARG_IMAGE_CAPTURE_HEIGHT, ARG_VIDEO_CAPTURE_WIDTH, ARG_VIDEO_CAPTURE_HEIGHT, - ARG_VIDEO_CAPTURE_FRAMERATE + ARG_VIDEO_CAPTURE_FRAMERATE, + ARG_PREVIEW_SOURCE_FILTER }; /** diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 21cea92..4b4960b 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -890,6 +890,16 @@ camerabin_dispose_elements (GstCameraBin * camera) camera->app_viewfinder_filter = NULL; } + if (camera->app_preview_source_filter) { + gst_object_unref (camera->app_preview_source_filter); + camera->app_preview_source_filter = NULL; + } + + if (camera->app_video_preview_source_filter) { + gst_object_unref (camera->app_video_preview_source_filter); + camera->app_video_preview_source_filter = NULL; + } + /* Free caps */ gst_caps_replace (&camera->image_capture_caps, NULL); gst_caps_replace (&camera->view_finder_caps, NULL); @@ -2857,6 +2867,22 @@ gst_camerabin_class_init (GstCameraBinClass * klass) GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** + * GstCameraBin:preview-source-filter: + * Set up preview filter element, all frames coming from appsrc + * element will be processed by this element. + * Applications can use this to overlay text/images for preview frame, + * for example. + * This property can only be set while #GstCameraBin is in NULL state. + * The ownership of the element will be taken by #GstCameraBin. + */ + + g_object_class_install_property (gobject_class, ARG_PREVIEW_SOURCE_FILTER, + g_param_spec_object ("preview-source-filter", + "preview source filter element", + "Optional preview source filter GStreamer element", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** * GstCameraBin:viewfinder-filter: * Set up viewfinder filter element, all frames going to viewfinder sink * element will be processed by this element. @@ -3155,6 +3181,10 @@ gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass) camera->app_vf_sink = NULL; camera->app_viewfinder_filter = NULL; + /* preview elements */ + camera->app_preview_source_filter = NULL; + camera->app_video_preview_source_filter = NULL; + /* source elements */ camera->src_vid_src = NULL; camera->src_filter = NULL; @@ -3337,14 +3367,17 @@ gst_camerabin_set_property (GObject * object, guint prop_id, case ARG_PREVIEW_CAPS: { GstElement **prev_pipe = NULL; + GstElement **preview_source_filter = NULL; GstCaps **prev_caps = NULL; GstCaps *new_caps = NULL; if (camera->mode == MODE_IMAGE) { prev_pipe = &camera->preview_pipeline; + preview_source_filter = &camera->app_preview_source_filter; prev_caps = &camera->preview_caps; } else if (camera->mode == MODE_VIDEO) { prev_pipe = &camera->video_preview_pipeline; + preview_source_filter = &camera->app_video_preview_source_filter; prev_caps = &camera->video_preview_caps; } @@ -3363,11 +3396,45 @@ gst_camerabin_set_property (GObject * object, guint prop_id, if (new_caps && !gst_caps_is_any (new_caps) && !gst_caps_is_empty (new_caps)) { - *prev_pipe = gst_camerabin_preview_create_pipeline (camera, new_caps); + *prev_pipe = + gst_camerabin_preview_create_pipeline (camera, new_caps, + *preview_source_filter); } } break; } + case ARG_PREVIEW_SOURCE_FILTER: + if (GST_STATE (camera) != GST_STATE_NULL) { + GST_ELEMENT_ERROR (camera, CORE, FAILED, + ("camerabin must be in NULL state when setting the preview source filter element"), + (NULL)); + } else { + GstElement **preview_pipe = NULL; + GstElement **preview_source_filter = NULL; + GstCaps *preview_caps = NULL; + + if (camera->mode == MODE_IMAGE) { + preview_pipe = &camera->preview_pipeline; + preview_source_filter = &camera->app_preview_source_filter; + preview_caps = camera->preview_caps; + } else if (camera->mode == MODE_VIDEO) { + preview_pipe = &camera->video_preview_pipeline; + preview_source_filter = &camera->app_video_preview_source_filter; + preview_caps = camera->video_preview_caps; + } + + if (*preview_source_filter) + gst_object_unref (*preview_source_filter); + *preview_source_filter = g_value_dup_object (value); + + if (*preview_pipe) { + gst_camerabin_preview_destroy_pipeline (camera, *preview_pipe); + *preview_pipe = + gst_camerabin_preview_create_pipeline (camera, preview_caps, + *preview_source_filter); + } + } + break; case ARG_VIEWFINDER_FILTER: if (GST_STATE (camera) != GST_STATE_NULL) { GST_ELEMENT_ERROR (camera, CORE, FAILED, @@ -3526,6 +3593,12 @@ gst_camerabin_get_property (GObject * object, guint prop_id, else if (camera->mode == MODE_VIDEO) gst_value_set_caps (value, camera->video_preview_caps); break; + case ARG_PREVIEW_SOURCE_FILTER: + if (camera->mode == MODE_IMAGE) + g_value_set_object (value, camera->app_preview_source_filter); + else if (camera->mode == MODE_VIDEO) + g_value_set_object (value, camera->app_video_preview_source_filter); + break; case ARG_VIEWFINDER_FILTER: g_value_set_object (value, camera->app_viewfinder_filter); break; diff --git a/gst/camerabin/gstcamerabin.h b/gst/camerabin/gstcamerabin.h index 90c682d..0074fdc 100644 --- a/gst/camerabin/gstcamerabin.h +++ b/gst/camerabin/gstcamerabin.h @@ -162,6 +162,8 @@ struct _GstCameraBin GstElement *app_vf_sink; GstElement *app_video_filter; GstElement *app_viewfinder_filter; + GstElement *app_preview_source_filter; + GstElement *app_video_preview_source_filter; /* Night mode handling */ gboolean night_mode; -- 2.7.4