diff options
author | Thiago Santos <thiago.sousa.santos@collabora.co.uk> | 2011-01-27 14:39:19 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.co.uk> | 2011-02-03 19:09:20 -0300 |
commit | 869a61343c415cee12fef7dd43d4c1a0114acf4c (patch) | |
tree | e1173509bf537cda76c95e4384abfbb78dff9b61 | |
parent | b2a45f6f21f44ca0d0c127c6a7f1fe25a206dea0 (diff) |
camerabin2: Add preview-filter property
Adds a property to select a custom element for preview pipeline
buffers processing
-rw-r--r-- | gst/camerabin2/camerabingeneral.c | 19 | ||||
-rw-r--r-- | gst/camerabin2/camerabingeneral.h | 3 | ||||
-rw-r--r-- | gst/camerabin2/gstcamerabin2.c | 31 | ||||
-rw-r--r-- | gst/camerabin2/gstcamerabin2.h | 1 | ||||
-rw-r--r-- | gst/camerabin2/gstwrappercamerabinsrc.c | 238 | ||||
-rw-r--r-- | gst/camerabin2/gstwrappercamerabinsrc.h | 2 |
6 files changed, 184 insertions, 110 deletions
diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index d6c1c8674..26edc12d0 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -317,20 +317,22 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink, return GST_FLOW_OK; } /** * gst_camerabin_create_preview_pipeline: * @element: Owner of this pipeline + * @filter: Custom filter to process preview data (an extra ref is taken) * * Creates a new previewing pipeline that can receive buffers * to be posted as camerabin preview messages for @element * * Returns: The newly created #GstCameraBinPreviewPipelineData */ GstCameraBinPreviewPipelineData * -gst_camerabin_create_preview_pipeline (GstElement * element) +gst_camerabin_create_preview_pipeline (GstElement * element, + GstElement * filter) { GstCameraBinPreviewPipelineData *data; GstElement *csp; GstElement *csp2; GstElement *vscale; gboolean added = FALSE; @@ -351,24 +353,33 @@ gst_camerabin_create_preview_pipeline (GstElement * element) !csp2 || !vscale) { goto error; } gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter, data->appsink, csp, csp2, vscale, NULL); + if (filter) + gst_bin_add (GST_BIN (data->pipeline), gst_object_ref (filter)); added = TRUE; - if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, data->capsfilter, - data->appsink, NULL)) - goto error; + if (filter) { + if (!gst_element_link_many (data->appsrc, filter, csp, vscale, csp2, + data->capsfilter, data->appsink, NULL)) + goto error; + } else { + if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, + data->capsfilter, data->appsink, NULL)) + goto error; + } callbacks.new_preroll = gst_camerabin_preview_pipeline_new_preroll; callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer; gst_app_sink_set_callbacks ((GstAppSink *) data->appsink, &callbacks, data, NULL); data->element = element; + data->filter = filter; return data; error: GST_WARNING ("Failed to create camerabin's preview pipeline"); if (!added) { if (csp) diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h index 4e0812a99..f39cbd77e 100644 --- a/gst/camerabin2/camerabingeneral.h +++ b/gst/camerabin2/camerabingeneral.h @@ -25,19 +25,20 @@ typedef struct { GstElement *pipeline; GstElement *appsrc; + GstElement *filter; GstElement *capsfilter; GstElement *appsink; GstElement *element; } GstCameraBinPreviewPipelineData; -GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstElement * element); +GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstElement * element, GstElement * filter); void gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData * preview); gboolean gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, GstBuffer * buffer); void gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps); gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 85a56967a..d7139a4ab 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -72,13 +72,14 @@ enum PROP_VIDEO_CAPTURE_CAPS, PROP_POST_PREVIEWS, PROP_PREVIEW_CAPS, PROP_VIDEO_ENCODING_PROFILE, PROP_IMAGE_FILTER, PROP_VIDEO_FILTER, - PROP_VIEWFINDER_FILTER + PROP_VIEWFINDER_FILTER, + PROP_PREVIEW_FILTER }; enum { /* action signals */ START_CAPTURE_SIGNAL, @@ -300,12 +301,16 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->video_profile) gst_encoding_profile_unref (camerabin->video_profile); if (camerabin->preview_caps) gst_caps_replace (&camerabin->preview_caps, NULL); + if (camerabin->preview_filter) { + gst_object_unref (camerabin->preview_filter); + camerabin->preview_filter = NULL; + } G_OBJECT_CLASS (parent_class)->dispose (object); } static void gst_camera_bin_finalize (GObject * object) @@ -429,12 +434,18 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) g_object_class_install_property (object_class, PROP_VIEWFINDER_FILTER, g_param_spec_object ("viewfinder-filter", "Viewfinder filter", "The element that will process frames going to the viewfinder." " (Should be set on NULL state)", GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_PREVIEW_FILTER, + g_param_spec_object ("preview-filter", "Preview filter", + "The element that will process preview buffers." + " (Should be set on NULL state)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstCameraBin::capture-start: * @camera: the camera bin element * * Starts image capture or video recording depending on the Mode. @@ -675,13 +686,14 @@ gst_camera_bin_create_elements (GstCameraBin * camera) g_assert (camera->src != NULL); g_object_set (camera->src, "mode", camera->mode, NULL); if (camera->src && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), "preview-caps")) { g_object_set (camera->src, "post-previews", camera->post_previews, - "preview-caps", camera->preview_caps, NULL); + "preview-caps", camera->preview_caps, "preview-filter", + camera->preview_filter, NULL); } if (new_src) { gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src)); camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src), "notify::ready-for-capture", G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); @@ -869,12 +881,23 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, case PROP_VIEWFINDER_FILTER: if (camera->user_viewfinder_filter) g_object_unref (camera->user_viewfinder_filter); camera->user_viewfinder_filter = g_value_dup_object (value); break; + case PROP_PREVIEW_FILTER: + if (camera->preview_filter) + g_object_unref (camera->preview_filter); + + camera->preview_filter = g_value_dup_object (value); + if (camera->src + && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), + "preview-filter")) + g_object_set (camera->src, "preview-filter", camera->preview_filter, + NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -969,12 +992,16 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, g_value_set_object (value, camera->image_filter); break; case PROP_VIEWFINDER_FILTER: if (camera->viewfinder_filter) g_value_set_object (value, camera->viewfinder_filter); break; + case PROP_PREVIEW_FILTER: + if (camera->preview_filter) + g_value_set_object (value, camera->preview_filter); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index f24417f1e..64828b49e 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -68,12 +68,13 @@ struct _GstCameraBin /* properties */ gint mode; gchar *video_location; gchar *image_location; gboolean post_previews; GstCaps *preview_caps; + GstElement *preview_filter; GstEncodingProfile *video_profile; gboolean elements_created; }; struct _GstCameraBinClass diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 864373bdc..c35fe8d77 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -36,13 +36,14 @@ enum { PROP_0, PROP_VIDEO_SRC, PROP_POST_PREVIEWS, - PROP_PREVIEW_CAPS + PROP_PREVIEW_CAPS, + PROP_PREVIEW_FILTER }; #define DEFAULT_POST_PREVIEWS TRUE /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 @@ -71,12 +72,17 @@ gst_wrapper_camera_bin_src_dispose (GObject * object) self->preview_pipeline = NULL; } if (self->preview_caps) gst_caps_replace (&self->preview_caps, NULL); + if (self->preview_filter) { + gst_object_unref (self->preview_filter); + self->preview_filter = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } static void gst_wrapper_camera_bin_src_finalize (GstWrapperCameraBinSrc * self) { @@ -110,12 +116,18 @@ gst_wrapper_camera_bin_src_set_property (GObject * object, gst_caps_replace (&self->preview_caps, (GstCaps *) gst_value_get_caps (value)); if (self->preview_pipeline) gst_camerabin_preview_set_caps (self->preview_pipeline, (GstCaps *) gst_value_get_caps (value)); break; + case PROP_PREVIEW_FILTER: + if (self->preview_filter) + gst_object_unref (self->preview_filter); + self->preview_filter = g_value_dup_object (value); + self->preview_filter_changed = TRUE; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } } @@ -136,12 +148,16 @@ gst_wrapper_camera_bin_src_get_property (GObject * object, g_value_set_boolean (value, self->post_previews); break; case PROP_PREVIEW_CAPS: if (self->preview_caps) gst_value_set_caps (value, self->preview_caps); break; + case PROP_PREVIEW_FILTER: + if (self->preview_filter) + g_value_set_object (value, self->preview_filter); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } } @@ -291,133 +307,144 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstElement *tee; gboolean ret = FALSE; GstElement *videoscale; GstPad *vf_pad; GstPad *tee_capture_pad; - if (self->elements_created) - return TRUE; + if (!self->elements_created) { - GST_DEBUG_OBJECT (self, "constructing pipeline"); + GST_DEBUG_OBJECT (self, "constructing pipeline"); - /* Add application set or default video src element */ - if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, - self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, - "camerasrc-real-src"))) { - self->src_vid_src = NULL; - goto done; - } else { - if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { + /* Add application set or default video src element */ + if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, + self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, + "camerasrc-real-src"))) { + self->src_vid_src = NULL; goto done; + } else { + if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { + goto done; + } } - } - /* we lost the reference */ - self->app_vid_src = NULL; + /* we lost the reference */ + self->app_vid_src = NULL; - /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ - { - GstPad *pad; - pad = gst_element_get_static_pad (self->src_vid_src, "src"); + /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ + { + GstPad *pad; + pad = gst_element_get_static_pad (self->src_vid_src, "src"); - self->src_event_probe_id = gst_pad_add_event_probe (pad, - (GCallback) gst_camerabin_drop_eos_probe, NULL); - gst_object_unref (pad); - } + self->src_event_probe_id = gst_pad_add_event_probe (pad, + (GCallback) gst_camerabin_drop_eos_probe, NULL); + gst_object_unref (pad); + } - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", - "src-colorspace")) - goto done; + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "src-colorspace")) + goto done; - if (!(self->src_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter", - "src-capsfilter"))) - goto done; + if (!(self->src_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "src-capsfilter"))) + goto done; - if (!(self->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop", - "zoom-crop"))) - goto done; - if (!(self->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale", - "zoom-scale"))) - goto done; - if (!(self->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter", - "zoom-capsfilter"))) - goto done; + if (!(self->src_zoom_crop = + gst_camerabin_create_and_add_element (cbin, "videocrop", + "zoom-crop"))) + goto done; + if (!(self->src_zoom_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale", + "zoom-scale"))) + goto done; + if (!(self->src_zoom_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "zoom-capsfilter"))) + goto done; - if (!(tee = - gst_camerabin_create_and_add_element (cbin, "tee", "camerasrc-tee"))) - goto done; + if (!(tee = + gst_camerabin_create_and_add_element (cbin, "tee", + "camerasrc-tee"))) + goto done; - /* viewfinder pad */ - vf_pad = gst_element_get_request_pad (tee, "src%d"); - g_object_set (tee, "alloc-pad", vf_pad, NULL); - gst_object_unref (vf_pad); + /* viewfinder pad */ + vf_pad = gst_element_get_request_pad (tee, "src%d"); + g_object_set (tee, "alloc-pad", vf_pad, NULL); + gst_object_unref (vf_pad); - /* the viewfinder should always work, so we add some converters to it */ - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", - "viewfinder-colorspace")) - goto done; - if (!(videoscale = - gst_camerabin_create_and_add_element (cbin, "videoscale", - "viewfinder-scale"))) - goto done; + /* the viewfinder should always work, so we add some converters to it */ + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "viewfinder-colorspace")) + goto done; + if (!(videoscale = + gst_camerabin_create_and_add_element (cbin, "videoscale", + "viewfinder-scale"))) + goto done; - /* image/video pad from tee */ - tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); + /* image/video pad from tee */ + tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); - self->output_selector = - gst_element_factory_make ("output-selector", "outsel"); - g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); - gst_bin_add (GST_BIN (self), self->output_selector); - { - GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); + self->output_selector = + gst_element_factory_make ("output-selector", "outsel"); + g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); + gst_bin_add (GST_BIN (self), self->output_selector); + { + GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); - /* check return TODO */ - gst_pad_link (tee_capture_pad, pad); - gst_object_unref (pad); + /* check return TODO */ + gst_pad_link (tee_capture_pad, pad); + gst_object_unref (pad); + } + gst_object_unref (tee_capture_pad); + + /* Create the 2 output pads for video and image */ + self->outsel_vidpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + self->outsel_imgpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + + g_assert (self->outsel_vidpad != NULL); + g_assert (self->outsel_imgpad != NULL); + + gst_pad_add_buffer_probe (self->outsel_imgpad, + G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); + gst_pad_add_buffer_probe (self->outsel_vidpad, + G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), + self->outsel_imgpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), + self->outsel_vidpad); + + if (bcamsrc->mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } + + /* hook-up the vf ghostpad */ + vf_pad = gst_element_get_static_pad (videoscale, "src"); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); + gst_object_unref (vf_pad); + + gst_pad_set_active (self->vfsrc, TRUE); + gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ + gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ } - gst_object_unref (tee_capture_pad); - - /* Create the 2 output pads for video and image */ - self->outsel_vidpad = - gst_element_get_request_pad (self->output_selector, "src%d"); - self->outsel_imgpad = - gst_element_get_request_pad (self->output_selector, "src%d"); - - g_assert (self->outsel_vidpad != NULL); - g_assert (self->outsel_imgpad != NULL); - - gst_pad_add_buffer_probe (self->outsel_imgpad, - G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); - gst_pad_add_buffer_probe (self->outsel_vidpad, - G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad); - - if (bcamsrc->mode == MODE_IMAGE) { - g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, - NULL); - } else { - g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, - NULL); + /* recreate the preview pipeline */ + if (self->preview_pipeline && self->preview_filter_changed) { + gst_camerabin_destroy_preview_pipeline (self->preview_pipeline); } - /* hook-up the vf ghostpad */ - vf_pad = gst_element_get_static_pad (videoscale, "src"); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); - gst_object_unref (vf_pad); - - gst_pad_set_active (self->vfsrc, TRUE); - gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ - gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ + if (self->preview_pipeline == NULL) + self->preview_pipeline = + gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self), + self->preview_filter); - /* create the preview pipeline */ - self->preview_pipeline = - gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self)); + g_assert (self->preview_pipeline != NULL); + self->preview_filter_changed = FALSE; if (self->preview_caps) gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); ret = TRUE; self->elements_created = TRUE; done: @@ -1022,12 +1049,17 @@ gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) g_object_class_install_property (gobject_class, PROP_PREVIEW_CAPS, g_param_spec_boxed ("preview-caps", "Preview caps", "The caps of the preview image to be posted", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PREVIEW_FILTER, + g_param_spec_object ("preview-filter", "Preview filter", + "A custom preview filter to process preview image data", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = gst_wrapper_camera_bin_src_change_state; gstbasecamerasrc_class->construct_pipeline = gst_wrapper_camera_bin_src_construct_pipeline; gstbasecamerasrc_class->set_zoom = gst_wrapper_camera_bin_src_set_zoom; gstbasecamerasrc_class->set_mode = gst_wrapper_camera_bin_src_set_mode; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index c74be279c..b2f4c7ae6 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -110,12 +110,14 @@ struct _GstWrapperCameraBinSrc gboolean video_renegotiate; /* Preview convert pipeline */ GstCameraBinPreviewPipelineData *preview_pipeline; gboolean post_previews; GstCaps *preview_caps; + GstElement *preview_filter; + gboolean preview_filter_changed; }; /** * GstWrapperCameraBinSrcClass: * |