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.
This commit is contained in:
Tommi Myöhänen 2011-10-31 06:59:53 -03:00 committed by Thiago Santos
parent 48275dc071
commit de138dbc57
4 changed files with 85 additions and 14 deletions

View file

@ -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

View file

@ -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;

View file

@ -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, &current, 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;
}

View file

@ -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_ */