mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
camerabin2: Add preview-filter property
Adds a property to select a custom element for preview pipeline buffers processing
This commit is contained in:
parent
b2a45f6f21
commit
869a61343c
6 changed files with 195 additions and 121 deletions
|
@ -320,6 +320,7 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink,
|
||||||
/**
|
/**
|
||||||
* gst_camerabin_create_preview_pipeline:
|
* gst_camerabin_create_preview_pipeline:
|
||||||
* @element: Owner of this 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
|
* Creates a new previewing pipeline that can receive buffers
|
||||||
* to be posted as camerabin preview messages for @element
|
* 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
|
* Returns: The newly created #GstCameraBinPreviewPipelineData
|
||||||
*/
|
*/
|
||||||
GstCameraBinPreviewPipelineData *
|
GstCameraBinPreviewPipelineData *
|
||||||
gst_camerabin_create_preview_pipeline (GstElement * element)
|
gst_camerabin_create_preview_pipeline (GstElement * element,
|
||||||
|
GstElement * filter)
|
||||||
{
|
{
|
||||||
GstCameraBinPreviewPipelineData *data;
|
GstCameraBinPreviewPipelineData *data;
|
||||||
GstElement *csp;
|
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,
|
gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter,
|
||||||
data->appsink, csp, csp2, vscale, NULL);
|
data->appsink, csp, csp2, vscale, NULL);
|
||||||
|
if (filter)
|
||||||
|
gst_bin_add (GST_BIN (data->pipeline), gst_object_ref (filter));
|
||||||
added = TRUE;
|
added = TRUE;
|
||||||
|
|
||||||
if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, data->capsfilter,
|
if (filter) {
|
||||||
data->appsink, NULL))
|
if (!gst_element_link_many (data->appsrc, filter, csp, vscale, csp2,
|
||||||
goto error;
|
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_preroll = gst_camerabin_preview_pipeline_new_preroll;
|
||||||
callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer;
|
callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer;
|
||||||
|
@ -366,6 +376,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element)
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
data->element = element;
|
data->element = element;
|
||||||
|
data->filter = filter;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -28,13 +28,14 @@ typedef struct
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
|
|
||||||
GstElement *appsrc;
|
GstElement *appsrc;
|
||||||
|
GstElement *filter;
|
||||||
GstElement *capsfilter;
|
GstElement *capsfilter;
|
||||||
GstElement *appsink;
|
GstElement *appsink;
|
||||||
|
|
||||||
GstElement *element;
|
GstElement *element;
|
||||||
} GstCameraBinPreviewPipelineData;
|
} 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);
|
void gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData * preview);
|
||||||
gboolean gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, GstBuffer * buffer);
|
gboolean gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, GstBuffer * buffer);
|
||||||
void gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps);
|
void gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps);
|
||||||
|
|
|
@ -75,7 +75,8 @@ enum
|
||||||
PROP_VIDEO_ENCODING_PROFILE,
|
PROP_VIDEO_ENCODING_PROFILE,
|
||||||
PROP_IMAGE_FILTER,
|
PROP_IMAGE_FILTER,
|
||||||
PROP_VIDEO_FILTER,
|
PROP_VIDEO_FILTER,
|
||||||
PROP_VIEWFINDER_FILTER
|
PROP_VIEWFINDER_FILTER,
|
||||||
|
PROP_PREVIEW_FILTER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -303,6 +304,10 @@ gst_camera_bin_dispose (GObject * object)
|
||||||
|
|
||||||
if (camerabin->preview_caps)
|
if (camerabin->preview_caps)
|
||||||
gst_caps_replace (&camerabin->preview_caps, NULL);
|
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);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@ -432,6 +437,12 @@ gst_camera_bin_class_init (GstCameraBinClass * klass)
|
||||||
" (Should be set on NULL state)",
|
" (Should be set on NULL state)",
|
||||||
GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
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:
|
* 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),
|
&& g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src),
|
||||||
"preview-caps")) {
|
"preview-caps")) {
|
||||||
g_object_set (camera->src, "post-previews", camera->post_previews,
|
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) {
|
if (new_src) {
|
||||||
gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->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);
|
camera->user_viewfinder_filter = g_value_dup_object (value);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -972,6 +995,10 @@ gst_camera_bin_get_property (GObject * object, guint prop_id,
|
||||||
if (camera->viewfinder_filter)
|
if (camera->viewfinder_filter)
|
||||||
g_value_set_object (value, camera->viewfinder_filter);
|
g_value_set_object (value, camera->viewfinder_filter);
|
||||||
break;
|
break;
|
||||||
|
case PROP_PREVIEW_FILTER:
|
||||||
|
if (camera->preview_filter)
|
||||||
|
g_value_set_object (value, camera->preview_filter);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct _GstCameraBin
|
||||||
gchar *image_location;
|
gchar *image_location;
|
||||||
gboolean post_previews;
|
gboolean post_previews;
|
||||||
GstCaps *preview_caps;
|
GstCaps *preview_caps;
|
||||||
|
GstElement *preview_filter;
|
||||||
GstEncodingProfile *video_profile;
|
GstEncodingProfile *video_profile;
|
||||||
|
|
||||||
gboolean elements_created;
|
gboolean elements_created;
|
||||||
|
|
|
@ -39,7 +39,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_VIDEO_SRC,
|
PROP_VIDEO_SRC,
|
||||||
PROP_POST_PREVIEWS,
|
PROP_POST_PREVIEWS,
|
||||||
PROP_PREVIEW_CAPS
|
PROP_PREVIEW_CAPS,
|
||||||
|
PROP_PREVIEW_FILTER
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_POST_PREVIEWS TRUE
|
#define DEFAULT_POST_PREVIEWS TRUE
|
||||||
|
@ -74,6 +75,11 @@ gst_wrapper_camera_bin_src_dispose (GObject * object)
|
||||||
if (self->preview_caps)
|
if (self->preview_caps)
|
||||||
gst_caps_replace (&self->preview_caps, NULL);
|
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);
|
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,
|
gst_camerabin_preview_set_caps (self->preview_pipeline,
|
||||||
(GstCaps *) gst_value_get_caps (value));
|
(GstCaps *) gst_value_get_caps (value));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -139,6 +151,10 @@ gst_wrapper_camera_bin_src_get_property (GObject * object,
|
||||||
if (self->preview_caps)
|
if (self->preview_caps)
|
||||||
gst_value_set_caps (value, self->preview_caps);
|
gst_value_set_caps (value, self->preview_caps);
|
||||||
break;
|
break;
|
||||||
|
case PROP_PREVIEW_FILTER:
|
||||||
|
if (self->preview_filter)
|
||||||
|
g_value_set_object (value, self->preview_filter);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -294,127 +310,138 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
|
||||||
GstPad *vf_pad;
|
GstPad *vf_pad;
|
||||||
GstPad *tee_capture_pad;
|
GstPad *tee_capture_pad;
|
||||||
|
|
||||||
if (self->elements_created)
|
if (!self->elements_created) {
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "constructing pipeline");
|
GST_DEBUG_OBJECT (self, "constructing pipeline");
|
||||||
|
|
||||||
/* Add application set or default video src element */
|
/* Add application set or default video src element */
|
||||||
if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin,
|
if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin,
|
||||||
self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC,
|
self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC,
|
||||||
"camerasrc-real-src"))) {
|
"camerasrc-real-src"))) {
|
||||||
self->src_vid_src = NULL;
|
self->src_vid_src = NULL;
|
||||||
goto done;
|
|
||||||
} else {
|
|
||||||
if (!gst_camerabin_add_element (cbin, self->src_vid_src)) {
|
|
||||||
goto done;
|
goto done;
|
||||||
|
} else {
|
||||||
|
if (!gst_camerabin_add_element (cbin, self->src_vid_src)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* 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");
|
||||||
|
|
||||||
|
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 (!(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 (!(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);
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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 ??? */
|
||||||
}
|
}
|
||||||
/* we lost the reference */
|
/* recreate the preview pipeline */
|
||||||
self->app_vid_src = NULL;
|
if (self->preview_pipeline && self->preview_filter_changed) {
|
||||||
|
gst_camerabin_destroy_preview_pipeline (self->preview_pipeline);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace",
|
if (self->preview_pipeline == NULL)
|
||||||
"src-colorspace"))
|
self->preview_pipeline =
|
||||||
goto done;
|
gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self),
|
||||||
|
self->preview_filter);
|
||||||
|
|
||||||
if (!(self->src_filter =
|
g_assert (self->preview_pipeline != NULL);
|
||||||
gst_camerabin_create_and_add_element (cbin, "capsfilter",
|
self->preview_filter_changed = FALSE;
|
||||||
"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 (!(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);
|
|
||||||
|
|
||||||
/* 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");
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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 ??? */
|
|
||||||
|
|
||||||
/* create the preview pipeline */
|
|
||||||
self->preview_pipeline =
|
|
||||||
gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self));
|
|
||||||
if (self->preview_caps)
|
if (self->preview_caps)
|
||||||
gst_camerabin_preview_set_caps (self->preview_pipeline, 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",
|
"The caps of the preview image to be posted",
|
||||||
GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
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;
|
gstelement_class->change_state = gst_wrapper_camera_bin_src_change_state;
|
||||||
|
|
||||||
gstbasecamerasrc_class->construct_pipeline =
|
gstbasecamerasrc_class->construct_pipeline =
|
||||||
|
|
|
@ -113,6 +113,8 @@ struct _GstWrapperCameraBinSrc
|
||||||
GstCameraBinPreviewPipelineData *preview_pipeline;
|
GstCameraBinPreviewPipelineData *preview_pipeline;
|
||||||
gboolean post_previews;
|
gboolean post_previews;
|
||||||
GstCaps *preview_caps;
|
GstCaps *preview_caps;
|
||||||
|
GstElement *preview_filter;
|
||||||
|
gboolean preview_filter_changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue