summaryrefslogtreecommitdiff
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>2011-01-27 17:39:19 (GMT)
committer Thiago Santos <thiago.sousa.santos@collabora.co.uk>2011-02-03 22:09:20 (GMT)
commit869a61343c415cee12fef7dd43d4c1a0114acf4c (patch) (side-by-side diff)
treee1173509bf537cda76c95e4384abfbb78dff9b61
parentb2a45f6f21f44ca0d0c127c6a7f1fe25a206dea0 (diff)
downloadgst-plugins-bad-869a61343c415cee12fef7dd43d4c1a0114acf4c.zip
gst-plugins-bad-869a61343c415cee12fef7dd43d4c1a0114acf4c.tar.gz
camerabin2: Add preview-filter property
Adds a property to select a custom element for preview pipeline buffers processing
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--gst/camerabin2/camerabingeneral.c19
-rw-r--r--gst/camerabin2/camerabingeneral.h3
-rw-r--r--gst/camerabin2/gstcamerabin2.c31
-rw-r--r--gst/camerabin2/gstcamerabin2.h1
-rw-r--r--gst/camerabin2/gstwrappercamerabinsrc.c238
-rw-r--r--gst/camerabin2/gstwrappercamerabinsrc.h2
6 files changed, 184 insertions, 110 deletions
diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c
index d6c1c86..26edc12 100644
--- a/gst/camerabin2/camerabingeneral.c
+++ b/gst/camerabin2/camerabingeneral.c
@@ -320,6 +320,7 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink,
/**
* 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
@@ -327,7 +328,8 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink,
* 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;
@@ -354,11 +356,19 @@ gst_camerabin_create_preview_pipeline (GstElement * element)
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;
@@ -366,6 +376,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element)
NULL);
data->element = element;
+ data->filter = filter;
return data;
error:
diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h
index 4e0812a..f39cbd7 100644
--- a/gst/camerabin2/camerabingeneral.h
+++ b/gst/camerabin2/camerabingeneral.h
@@ -28,13 +28,14 @@ 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);
diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c
index 85a5696..d7139a4 100644
--- a/gst/camerabin2/gstcamerabin2.c
+++ b/gst/camerabin2/gstcamerabin2.c
@@ -75,7 +75,8 @@ enum
PROP_VIDEO_ENCODING_PROFILE,
PROP_IMAGE_FILTER,
PROP_VIDEO_FILTER,
- PROP_VIEWFINDER_FILTER
+ PROP_VIEWFINDER_FILTER,
+ PROP_PREVIEW_FILTER
};
enum
@@ -303,6 +304,10 @@ gst_camera_bin_dispose (GObject * object)
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);
}
@@ -432,6 +437,12 @@ gst_camera_bin_class_init (GstCameraBinClass * klass)
" (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:
@@ -678,7 +689,8 @@ gst_camera_bin_create_elements (GstCameraBin * camera)
&& 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));
@@ -872,6 +884,17 @@ gst_camera_bin_set_property (GObject * object, guint prop_id,
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;
@@ -972,6 +995,10 @@ gst_camera_bin_get_property (GObject * object, guint prop_id,
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 f24417f..64828b4 100644
--- a/gst/camerabin2/gstcamerabin2.h
+++ b/gst/camerabin2/gstcamerabin2.h
@@ -71,6 +71,7 @@ struct _GstCameraBin
gchar *image_location;
gboolean post_previews;
GstCaps *preview_caps;
+ GstElement *preview_filter;
GstEncodingProfile *video_profile;
gboolean elements_created;
diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c
index 864373b..c35fe8d 100644
--- a/gst/camerabin2/gstwrappercamerabinsrc.c
+++ b/gst/camerabin2/gstwrappercamerabinsrc.c
@@ -39,7 +39,8 @@ enum
PROP_0,
PROP_VIDEO_SRC,
PROP_POST_PREVIEWS,
- PROP_PREVIEW_CAPS
+ PROP_PREVIEW_CAPS,
+ PROP_PREVIEW_FILTER
};
#define DEFAULT_POST_PREVIEWS TRUE
@@ -74,6 +75,11 @@ gst_wrapper_camera_bin_src_dispose (GObject * object)
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);
}
@@ -113,6 +119,12 @@ gst_wrapper_camera_bin_src_set_property (GObject * object,
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;
@@ -139,6 +151,10 @@ gst_wrapper_camera_bin_src_get_property (GObject * object,
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;
@@ -294,127 +310,138 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
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);
@@ -1025,6 +1052,11 @@ gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass)
"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 =
diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h
index c74be27..b2f4c7a 100644
--- a/gst/camerabin2/gstwrappercamerabinsrc.h
+++ b/gst/camerabin2/gstwrappercamerabinsrc.h
@@ -113,6 +113,8 @@ struct _GstWrapperCameraBinSrc
GstCameraBinPreviewPipelineData *preview_pipeline;
gboolean post_previews;
GstCaps *preview_caps;
+ GstElement *preview_filter;
+ gboolean preview_filter_changed;
};