diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index cf332be005..98d594e1d1 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c @@ -191,14 +191,11 @@ void gst_base_camera_src_setup_zoom (GstBaseCameraSrc * self) { GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); - gint zoom; - zoom = g_atomic_int_get (&self->zoom); - - g_return_if_fail (zoom); + g_return_if_fail (self->zoom); g_return_if_fail (bclass->set_zoom); - bclass->set_zoom (self, zoom); + bclass->set_zoom (self, self->zoom); } /** @@ -337,7 +334,7 @@ gst_base_camera_src_set_property (GObject * object, g_value_get_enum (value)); break; case PROP_ZOOM:{ - g_atomic_int_set (&self->zoom, g_value_get_int (value)); + self->zoom = g_value_get_float (value); /* does not set it if in NULL, the src is not created yet */ if (GST_STATE (self) != GST_STATE_NULL) gst_base_camera_src_setup_zoom (self); @@ -378,7 +375,7 @@ gst_base_camera_src_get_property (GObject * object, g_value_set_boolean (value, !self->capturing); break; case PROP_ZOOM: - g_value_set_int (value, g_atomic_int_get (&self->zoom)); + g_value_set_float (value, self->zoom); break; case PROP_POST_PREVIEW: g_value_set_boolean (value, self->post_preview); @@ -522,6 +519,11 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ZOOM, + g_param_spec_float ("zoom", "Zoom", + "Digital zoom factor (e.g. 1.5 means 1.5x)", MIN_ZOOM, MAX_ZOOM, + DEFAULT_ZOOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstBaseCameraSrc:post-previews: * diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h index ef9ae9e871..b48628f052 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h @@ -79,7 +79,7 @@ struct _GstBaseCameraSrc gint height; /* The digital zoom (from 100% to 1000%) */ - gint zoom; + gfloat zoom; gpointer _gst_reserved[GST_PADDING_LARGE]; }; @@ -103,7 +103,7 @@ struct _GstBaseCameraSrcClass gboolean (*setup_pipeline) (GstBaseCameraSrc *self); /* set the zoom */ - void (*set_zoom) (GstBaseCameraSrc *self, gint zoom); + void (*set_zoom) (GstBaseCameraSrc *self, gfloat zoom); /* set the mode */ gboolean (*set_mode) (GstBaseCameraSrc *self, @@ -125,8 +125,8 @@ struct _GstBaseCameraSrcClass }; -#define MIN_ZOOM 100 -#define MAX_ZOOM 1000 +#define MIN_ZOOM 1.0f +#define MAX_ZOOM 10.0f #define ZOOM_1X MIN_ZOOM GstPhotography * gst_base_camera_src_get_photography (GstBaseCameraSrc *self); diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index b8c32a5370..8c2bb20c8b 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -85,7 +85,8 @@ enum PROP_AUDIO_SRC, PROP_MUTE_AUDIO, PROP_AUDIO_CAPTURE_SUPPORTED_CAPS, - PROP_AUDIO_CAPTURE_CAPS + PROP_AUDIO_CAPTURE_CAPS, + PROP_ZOOM }; enum @@ -531,6 +532,11 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "Restricts the caps that can be used on the viewfinder", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_ZOOM, + g_param_spec_float ("zoom", "Zoom", + "Digital zoom factor (e.g. 1.5 means 1.5x)", MIN_ZOOM, MAX_ZOOM, + DEFAULT_ZOOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* TODO review before going stable * We have viewfinder-supported-caps that returns the caps that the * camerasrc can produce on its viewfinder pad, this could easily be @@ -579,6 +585,7 @@ gst_camera_bin_init (GstCameraBin * camera) camera->video_location = g_strdup (DEFAULT_VID_LOCATION); camera->image_location = g_strdup (DEFAULT_IMG_LOCATION); camera->viewfinderbin = gst_element_factory_make ("viewfinderbin", "vf-bin"); + camera->zoom = DEFAULT_ZOOM; /* capsfilters are created here as we proxy their caps properties and * this way we avoid having to store the caps while on NULL state to @@ -917,12 +924,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, "preview-filter", - camera->preview_filter, NULL); + if (camera->src) { + if (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, "preview-filter", + camera->preview_filter, NULL); + } + g_object_set (camera->src, "zoom", camera->zoom, NULL); } if (new_src) { gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src)); @@ -1252,6 +1261,11 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, g_object_set (camera->viewfinderbin, "video-sink", g_value_get_object (value), NULL); break; + case PROP_ZOOM: + camera->zoom = g_value_get_float (value); + if (camera->src) + g_object_set (camera->src, "zoom", camera->zoom, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1398,6 +1412,9 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, g_value_take_object (value, sink); break; } + case PROP_ZOOM: + g_value_set_float (value, camera->zoom); + 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 66e7ba8e22..8d5c660ca0 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -81,6 +81,7 @@ struct _GstCameraBin GstCaps *preview_caps; GstElement *preview_filter; GstEncodingProfile *video_profile; + gfloat zoom; gboolean elements_created; }; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 81baca3374..057063f432 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -295,6 +295,46 @@ gst_wrapper_camera_src_src_event_probe (GstPad * pad, GstEvent * evt, return ret; } +static void +gst_wrapper_camera_bin_src_caps_cb (GObject * gobject, GParamSpec * pspec, + gpointer user_data) +{ + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (user_data); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (user_data); + GstPad *src_caps_src_pad; + GstCaps *caps = NULL; + GstStructure *in_st = NULL; + + /* get the new caps that were set on the capsfilter that configures the + * source */ + src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src"); + caps = gst_pad_get_caps_reffed (src_caps_src_pad); + gst_object_unref (src_caps_src_pad); + GST_DEBUG_OBJECT (self, "src-filter caps changed to %s", + gst_caps_to_string (caps)); + + if (gst_caps_get_size (caps)) { + in_st = gst_caps_get_structure (caps, 0); + if (in_st) { + gst_structure_get_int (in_st, "width", &bcamsrc->width); + gst_structure_get_int (in_st, "height", &bcamsrc->height); + + GST_DEBUG_OBJECT (self, "Source dimensions now: %dx%d", bcamsrc->width, + bcamsrc->height); + } + } + + /* Update zoom */ + gst_base_camera_src_setup_zoom (bcamsrc); + + /* Update post-zoom capsfilter */ + if (self->src_zoom_filter) + g_object_set (G_OBJECT (self->src_zoom_filter), "caps", caps, NULL); + + /* drop our ref on the caps */ + gst_caps_unref (caps); +}; + /** * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object @@ -318,6 +358,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstElement *videoscale; GstPad *vf_pad; GstPad *tee_capture_pad; + GstPad *src_caps_src_pad; if (!self->elements_created) { @@ -356,6 +397,14 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) "src-capsfilter"))) goto done; + /* attach to notify::caps on the first capsfilter and use a callback + * to recalculate the zoom properties when these caps change and to + * propagate the caps to the second capsfilter */ + src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src"); + g_signal_connect (src_caps_src_pad, "notify::caps", + G_CALLBACK (gst_wrapper_camera_bin_src_caps_cb), self); + gst_object_unref (src_caps_src_pad); + if (!(self->src_zoom_crop = gst_camerabin_create_and_add_element (cbin, "videocrop", "zoom-crop"))) @@ -650,21 +699,20 @@ gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, } static gboolean -set_videosrc_zoom (GstWrapperCameraBinSrc * self, gint zoom) +set_videosrc_zoom (GstWrapperCameraBinSrc * self, gfloat zoom) { gboolean ret = FALSE; if (g_object_class_find_property (G_OBJECT_GET_CLASS (self->src_vid_src), "zoom")) { - g_object_set (G_OBJECT (self->src_vid_src), "zoom", - (gfloat) zoom / 100, NULL); + g_object_set (G_OBJECT (self->src_vid_src), "zoom", zoom, NULL); ret = TRUE; } return ret; } static gboolean -set_element_zoom (GstWrapperCameraBinSrc * self, gint zoom) +set_element_zoom (GstWrapperCameraBinSrc * self, gfloat zoom) { gboolean ret = FALSE; GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); @@ -677,12 +725,13 @@ set_element_zoom (GstWrapperCameraBinSrc * self, gint zoom) if (self->src_zoom_crop) { /* Update capsfilters to apply the zoom */ - GST_INFO_OBJECT (self, "zoom: %d, orig size: %dx%d", zoom, + GST_INFO_OBJECT (self, "zoom: %f, orig size: %dx%d", zoom, bcamsrc->width, bcamsrc->height); if (zoom != ZOOM_1X) { - w2_crop = (bcamsrc->width - (bcamsrc->width * ZOOM_1X / zoom)) / 2; - h2_crop = (bcamsrc->height - (bcamsrc->height * ZOOM_1X / zoom)) / 2; + w2_crop = (bcamsrc->width - (gint) (bcamsrc->width * ZOOM_1X / zoom)) / 2; + h2_crop = + (bcamsrc->height - (gint) (bcamsrc->height * ZOOM_1X / zoom)) / 2; left += w2_crop; right += w2_crop; @@ -711,11 +760,11 @@ set_element_zoom (GstWrapperCameraBinSrc * self, gint zoom) } static void -gst_wrapper_camera_bin_src_set_zoom (GstBaseCameraSrc * bcamsrc, gint zoom) +gst_wrapper_camera_bin_src_set_zoom (GstBaseCameraSrc * bcamsrc, gfloat zoom) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); - GST_INFO_OBJECT (self, "setting zoom %d", zoom); + GST_INFO_OBJECT (self, "setting zoom %f", zoom); if (set_videosrc_zoom (self, zoom)) { set_element_zoom (self, ZOOM_1X); @@ -904,7 +953,7 @@ set_capsfilter_caps (GstWrapperCameraBinSrc * self, GstCaps * new_caps) if (self->src_zoom_filter) g_object_set (G_OBJECT (self->src_zoom_filter), "caps", new_caps, NULL); update_aspect_filter (self, new_caps); - GST_INFO_OBJECT (self, "udpated"); + GST_INFO_OBJECT (self, "updated"); } static gboolean diff --git a/tests/examples/camerabin2/gst-camerabin2-test.c b/tests/examples/camerabin2/gst-camerabin2-test.c index 1fd5e0aab5..d018afbefe 100644 --- a/tests/examples/camerabin2/gst-camerabin2-test.c +++ b/tests/examples/camerabin2/gst-camerabin2-test.c @@ -666,9 +666,7 @@ run_pipeline (gpointer user_data) } g_object_unref (video_source); } -#if 0 g_object_set (camerabin, "zoom", zoom / 100.0f, NULL); -#endif capture_count++; g_timer_start (timer);