From 24bc280806235dc3d756750ca0b922c7f7090e39 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 5 Dec 2010 11:18:09 -0300 Subject: [PATCH] basecamerasrc: Move start/stop capture signals to basecamerasrc Move start/stop signals and ready-for-capture to basecamerasrc as this should be present on all camera sources --- gst/camerabin2/gstbasecamerasrc.c | 110 +++++++++++++++++++++++++++++- gst/camerabin2/gstbasecamerasrc.h | 12 ++++ gst/camerabin2/gstv4l2camerasrc.c | 109 ++++++----------------------- gst/camerabin2/gstv4l2camerasrc.h | 6 -- 4 files changed, 142 insertions(+), 95 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index fd4dc4b6f7..87cec67fd8 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -34,6 +34,17 @@ #include "gstbasecamerasrc.h" +enum +{ + /* action signals */ + START_CAPTURE_SIGNAL, + STOP_CAPTURE_SIGNAL, + /* emit signals */ + LAST_SIGNAL +}; + +static guint basecamerasrc_signals[LAST_SIGNAL]; + GST_DEBUG_CATEGORY (base_camera_src_debug); #define GST_CAT_DEFAULT base_camera_src_debug @@ -256,12 +267,65 @@ gst_base_camera_src_find_better_framerate (GstBaseCameraSrc * self, return framerate; } +static void +gst_base_camera_src_start_capture (GstBaseCameraSrc * src) +{ + GstBaseCameraSrcClass *klass = GST_BASE_CAMERA_SRC_GET_CLASS (src); + + g_return_if_fail (klass->start_capture != NULL); + + g_mutex_lock (src->capturing_mutex); + if (src->capturing) { + GST_WARNING_OBJECT (src, "Capturing already ongoing"); + g_mutex_unlock (src->capturing_mutex); + return; + } + + if (klass->start_capture (src)) { + src->capturing = TRUE; + g_object_notify (G_OBJECT (src), "ready-for-capture"); + } else { + GST_WARNING_OBJECT (src, "Failed to start capture"); + } + g_mutex_unlock (src->capturing_mutex); +} + +static void +gst_base_camera_src_stop_capture (GstBaseCameraSrc * src) +{ + GstBaseCameraSrcClass *klass = GST_BASE_CAMERA_SRC_GET_CLASS (src); + + g_return_if_fail (klass->stop_capture != NULL); + + g_mutex_lock (src->capturing_mutex); + if (!src->capturing) { + GST_DEBUG_OBJECT (src, "No ongoing capture"); + g_mutex_unlock (src->capturing_mutex); + return; + } + klass->stop_capture (src); + g_mutex_unlock (src->capturing_mutex); +} + +void +gst_base_camera_src_finish_capture (GstBaseCameraSrc * self) +{ + g_return_if_fail (self->capturing); + self->capturing = FALSE; + g_object_notify (G_OBJECT (self), "ready-for-capture"); +} + + /** * */ static void gst_base_camera_src_dispose (GObject * object) { + GstBaseCameraSrc *src = GST_BASE_CAMERA_SRC_CAST (object); + + g_mutex_free (src->capturing_mutex); + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -305,6 +369,9 @@ gst_base_camera_src_get_property (GObject * object, case ARG_MODE: g_value_set_enum (value, self->mode); break; + case ARG_READY_FOR_CAPTURE: + g_value_set_boolean (value, !self->capturing); + break; case ARG_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; @@ -431,8 +498,46 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gstelement_class->change_state = gst_base_camera_src_change_state; + /** + * GstBaseCameraSrc:ready-for-capture: + * + * When TRUE new capture can be prepared. If FALSE capturing is ongoing + * and starting a new capture immediately is not possible. + * + * Note that calling start-capture from the notify callback of this property + * will cause a deadlock. If you need to react like this on the notify + * function, please schedule a new thread to do it. If you're using glib's + * mainloop you can use g_idle_add() for example. + */ + g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, + g_param_spec_boolean ("ready-for-capture", "Ready for capture", + "Informs this element is ready for starting another capture", + TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* Signals */ + basecamerasrc_signals[START_CAPTURE_SIGNAL] = + g_signal_new ("start-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstBaseCameraSrcClass, private_start_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + basecamerasrc_signals[STOP_CAPTURE_SIGNAL] = + g_signal_new ("stop-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstBaseCameraSrcClass, private_stop_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* TODO these should be moved to a private struct + * that is allocated sequentially to the main struct as said at: + * http://library.gnome.org/devel/gobject/unstable/gobject-Type-Information.html#g-type-add-class-private + */ + klass->private_start_capture = gst_base_camera_src_start_capture; + klass->private_stop_capture = gst_base_camera_src_stop_capture; + + gstelement_class->change_state = gst_base_camera_src_change_state; } static void @@ -459,4 +564,7 @@ gst_base_camera_src_init (GstBaseCameraSrc * self, self->fps_n = DEFAULT_FPS_N; self->fps_d = DEFAULT_FPS_D; + + self->capturing = FALSE; + self->capturing_mutex = g_mutex_new (); } diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 2f22d813da..8a212b158d 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -62,6 +62,9 @@ struct _GstBaseCameraSrc gint mode; + gboolean capturing; + GMutex *capturing_mutex; + /* XXX preview pads? */ /* Resolution of the buffers configured to camerabin */ @@ -127,6 +130,12 @@ struct _GstBaseCameraSrcClass void (*finish_image_capture) (GstBaseCameraSrc * self); + void (*private_start_capture) (GstBaseCameraSrc * src); + void (*private_stop_capture) (GstBaseCameraSrc * src); + gboolean (*start_capture) (GstBaseCameraSrc * src); + void (*stop_capture) (GstBaseCameraSrc * src); + + gpointer _gst_reserved[GST_PADDING_LARGE]; }; @@ -145,6 +154,9 @@ void gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self); const GValue * gst_base_camera_src_find_better_framerate ( GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_framerate); +void gst_base_camera_src_finish_capture (GstBaseCameraSrc *self); + + // XXX add methods to get/set img capture and vid capture caps.. #endif /* __GST_BASE_CAMERA_SRC_H__ */ diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 00b6a50ab3..a85d83b6ab 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -35,16 +35,6 @@ #include "camerabingeneral.h" #include "gstcamerabin-enum.h" -enum -{ - /* action signals */ - START_CAPTURE_SIGNAL, - STOP_CAPTURE_SIGNAL, - /* emit signals */ - IMG_DONE_SIGNAL, - LAST_SIGNAL -}; - #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" /* Using "bilinear" as default zoom method */ @@ -53,8 +43,6 @@ enum GST_DEBUG_CATEGORY (v4l2_camera_src_debug); #define GST_CAT_DEFAULT v4l2_camera_src_debug -static guint v4l2camerasrc_signals[LAST_SIGNAL]; - GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); @@ -64,9 +52,6 @@ static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps); static void gst_v4l2_camera_src_dispose (GObject * object) { - GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (object); - - g_mutex_free (src->capturing_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -126,9 +111,6 @@ gst_v4l2_camera_src_get_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_READY_FOR_CAPTURE: - g_value_set_boolean (value, !self->capturing); - break; case ARG_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; @@ -157,18 +139,18 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; - g_mutex_lock (self->capturing_mutex); + g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; if (self->image_capture_count == 0) { - self->capturing = FALSE; - g_object_notify (G_OBJECT (self), "ready-for-capture"); + gst_base_camera_src_finish_capture (camerasrc); } } - g_mutex_unlock (self->capturing_mutex); + g_mutex_unlock (camerasrc->capturing_mutex); return ret; } @@ -182,6 +164,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; /* TODO do we want to lock for every buffer? */ @@ -189,7 +172,8 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, * Note that we can use gst_pad_push_event here because we are a buffer * probe. */ - g_mutex_lock (self->capturing_mutex); + /* TODO shouldn't access this directly */ + g_mutex_lock (camerasrc->capturing_mutex); if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { @@ -204,12 +188,11 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, GST_DEBUG_OBJECT (self, "Finishing video recording, pushing eos"); gst_pad_push_event (pad, gst_event_new_eos ()); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - self->capturing = FALSE; - g_object_notify (G_OBJECT (self), "ready-for-capture"); + gst_base_camera_src_finish_capture (camerasrc); } else { ret = TRUE; } - g_mutex_unlock (self->capturing_mutex); + g_mutex_unlock (camerasrc->capturing_mutex); return ret; } @@ -1034,19 +1017,12 @@ gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) } } -static void -gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) +static gboolean +gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc) { - GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); - g_mutex_lock (src->capturing_mutex); - if (src->capturing) { - GST_WARNING_OBJECT (src, "Capturing already ongoing"); - g_mutex_unlock (src->capturing_mutex); - return; - } + GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); - src->capturing = TRUE; - /* TODO should we use a macro? */ + /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_IMAGE) { src->image_capture_count = 1; start_image_capture (src); @@ -1056,23 +1032,17 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) } } else { g_assert_not_reached (); - src->capturing = FALSE; + return FALSE; } - if (src->capturing) - g_object_notify (G_OBJECT (src), "ready-for-capture"); - g_mutex_unlock (src->capturing_mutex); + return TRUE; } static void -gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) +gst_v4l2_camera_src_stop_capture (GstBaseCameraSrc * camerasrc) { - GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); - g_mutex_lock (src->capturing_mutex); - if (!src->capturing) { - GST_DEBUG_OBJECT (src, "No ongoing capture"); - g_mutex_unlock (src->capturing_mutex); - return; - } + GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); + + /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); @@ -1084,10 +1054,7 @@ gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) } } else { src->image_capture_count = 0; - src->capturing = FALSE; - g_object_notify (G_OBJECT (src), "ready-for-capture"); } - g_mutex_unlock (src->capturing_mutex); } static void @@ -1119,40 +1086,6 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) /* g_object_class_install_property .... */ - /** - * GstV4l2CameraSrc:ready-for-capture: - * - * When TRUE new capture can be prepared. If FALSE capturing is ongoing - * and starting a new capture immediately is not possible. - * - * Note that calling start-capture from the notify callback of this property - * will cause a deadlock. If you need to react like this on the notify - * function, please schedule a new thread to do it. If you're using glib's - * mainloop you can use g_idle_add() for example. - */ - g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, - g_param_spec_boolean ("ready-for-capture", "Ready for capture", - "Informs this element is ready for starting another capture", - TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /* Signals */ - v4l2camerasrc_signals[START_CAPTURE_SIGNAL] = - g_signal_new ("start-capture", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstV4l2CameraSrcClass, start_capture), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - v4l2camerasrc_signals[STOP_CAPTURE_SIGNAL] = - g_signal_new ("stop-capture", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstV4l2CameraSrcClass, stop_capture), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - klass->start_capture = gst_v4l2_camera_src_start_capture; - klass->stop_capture = gst_v4l2_camera_src_stop_capture; - gstbasecamerasrc_class->construct_pipeline = gst_v4l2_camera_src_construct_pipeline; gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_pipeline; @@ -1162,6 +1095,8 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gst_v4l2_camera_src_get_allowed_input_caps; gstbasecamerasrc_class->finish_image_capture = gst_v4l2_camera_src_finish_image_capture; + gstbasecamerasrc_class->start_capture = gst_v4l2_camera_src_start_capture; + gstbasecamerasrc_class->stop_capture = gst_v4l2_camera_src_stop_capture; } static void @@ -1171,8 +1106,6 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, /* TODO where are variables reset? */ self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - self->capturing_mutex = g_mutex_new (); - self->capturing = FALSE; } gboolean diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index e996920fff..7bc8285c0d 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -57,9 +57,6 @@ struct _GstV4l2CameraSrc { GstBaseCameraSrc parent; - gboolean capturing; - GMutex *capturing_mutex; - /* video recording controls */ gint video_rec_status; @@ -108,9 +105,6 @@ struct _GstV4l2CameraSrc struct _GstV4l2CameraSrcClass { GstBaseCameraSrcClass parent; - - void (*start_capture) (GstV4l2CameraSrc * src); - void (*stop_capture) (GstV4l2CameraSrc * src); }; gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin);