From de138dbc57c5928a25e10d440ff2bb0ac6ae4b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tommi=20My=C3=B6h=C3=A4nen?= Date: Mon, 31 Oct 2011 06:59:53 -0300 Subject: [PATCH] basecamerasrc: optimize state changing speed Create preview pipeline already in initialization phase. This speeds up NULL_TO_READY state change. Also implement a separate function for setting the preview filter element. This also restricts the preview filter property to work only on NULL state. --- .../gst/basecamerabinsrc/gstbasecamerasrc.c | 21 ++---- .../gst/basecamerabinsrc/gstbasecamerasrc.h | 1 - .../basecamerabinsrc/gstcamerabinpreview.c | 75 +++++++++++++++++++ .../basecamerabinsrc/gstcamerabinpreview.h | 2 + 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index 7d159e04db..904eba0eb5 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c @@ -350,7 +350,11 @@ gst_base_camera_src_set_property (GObject * object, if (self->preview_filter) gst_object_unref (self->preview_filter); self->preview_filter = g_value_dup_object (value); - self->preview_filter_changed = TRUE; + if (!gst_camerabin_preview_set_filter (self->preview_pipeline, + self->preview_filter)) { + GST_WARNING_OBJECT (self, + "Cannot change preview filter, is element in NULL state?"); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); @@ -434,23 +438,11 @@ gst_base_camera_src_change_state (GstElement * element, if (!construct_pipeline (self)) return GST_STATE_CHANGE_FAILURE; - /* recreate the preview pipeline */ - if (self->preview_pipeline && self->preview_filter_changed) { - gst_camerabin_destroy_preview_pipeline (self->preview_pipeline); - self->preview_pipeline = NULL; - } - - if (self->preview_pipeline == NULL) - self->preview_pipeline = - gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self), - self->preview_filter); - if (self->preview_pipeline == NULL) { /* failed to create preview pipeline, fail state change */ return GST_STATE_CHANGE_FAILURE; } - self->preview_filter_changed = FALSE; if (self->preview_caps) { GST_DEBUG_OBJECT (self, "Setting preview pipeline caps %" GST_PTR_FORMAT, @@ -610,6 +602,9 @@ gst_base_camera_src_init (GstBaseCameraSrc * self, self->capturing_mutex = g_mutex_new (); self->post_preview = DEFAULT_POST_PREVIEW; + + self->preview_pipeline = + gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self), NULL); } void diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h index e5e19535ab..9cd5a0011b 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h @@ -77,7 +77,6 @@ struct _GstBaseCameraSrc gboolean post_preview; GstElement *preview_filter; GstCameraBinPreviewPipelineData *preview_pipeline; - gboolean preview_filter_changed; /* Resolution of the buffers configured to camerabin */ gint width; diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c index 88162ff3e7..4273c71096 100644 --- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c +++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c @@ -31,6 +31,9 @@ #include "gstcamerabinpreview.h" #include "gstbasecamerasrc.h" +GST_DEBUG_CATEGORY_EXTERN (base_camera_src_debug); +#define GST_CAT_DEFAULT base_camera_src_debug + static void _gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps); @@ -190,6 +193,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element, data->element = element; data->filter = filter; + data->vscale = vscale; data->processing_lock = g_mutex_new (); data->processing_cond = g_cond_new (); @@ -327,3 +331,74 @@ gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, } g_mutex_unlock (preview->processing_lock); } + +/** + * gst_camerabin_preview_set_filter: + * @preview: the #GstCameraBinPreviewPipelineData + * @filter: Custom filter to process preview data (an extra ref is taken) + * + * Set the filter element into preview pipeline. + * + * Returns: %TRUE on success + */ +gboolean +gst_camerabin_preview_set_filter (GstCameraBinPreviewPipelineData * preview, + GstElement * filter) +{ + gboolean ret = TRUE; + GstState current; + + g_return_val_if_fail (preview != NULL, FALSE); + + GST_DEBUG ("Preview pipeline setting new filter %p", filter); + + g_mutex_lock (preview->processing_lock); + + gst_element_get_state (preview->pipeline, ¤t, NULL, 0); + + if (preview->processing == 0 && current == GST_STATE_NULL) { + gboolean linkfail = FALSE; + + if (preview->filter) { + /* Unlink and remove old filter */ + gst_element_unlink (preview->appsrc, preview->filter); + gst_element_unlink (preview->filter, preview->vscale); + gst_bin_remove (GST_BIN (preview->pipeline), preview->filter); + } else { + /* Make room for filter by breaking the link between appsrc and vcale */ + gst_element_unlink (preview->appsrc, preview->vscale); + } + + if (filter) { + /* Add and link the new filter between appsrc and vscale */ + gst_bin_add (GST_BIN (preview->pipeline), gst_object_ref (filter)); + + linkfail |= + GST_PAD_LINK_FAILED (gst_element_link_pads_full (preview->appsrc, + "src", filter, NULL, GST_PAD_LINK_CHECK_NOTHING)); + + linkfail |= + GST_PAD_LINK_FAILED (gst_element_link_pads_full (filter, NULL, + preview->vscale, "sink", GST_PAD_LINK_CHECK_CAPS)); + } else { + /* No filter was given. Just link the appsrc to vscale directly */ + linkfail |= + GST_PAD_LINK_FAILED (gst_element_link_pads_full (preview->appsrc, + "src", preview->vscale, "sink", GST_PAD_LINK_CHECK_NOTHING)); + } + + if (linkfail) { + GST_WARNING ("Linking the filter to pipeline failed"); + ret = FALSE; + } else { + GST_DEBUG ("Linking the filter to pipeline successful"); + preview->filter = filter; + } + } else { + GST_WARNING ("Cannot change filter when pipeline is running"); + ret = FALSE; + } + g_mutex_unlock (preview->processing_lock); + + return ret; +} diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h index ef9cd96670..eb4a45f335 100644 --- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h +++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h @@ -36,6 +36,7 @@ typedef struct GstElement *appsrc; GstElement *filter; GstElement *appsink; + GstElement *vscale; GstElement *element; @@ -50,5 +51,6 @@ GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstEleme 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_preview_set_filter (GstCameraBinPreviewPipelineData * preview, GstElement * filter); #endif /* #ifndef __CAMERABIN_PREVIEW_H_ */