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
This commit is contained in:
Thiago Santos 2010-12-05 11:18:09 -03:00
parent 87eddd54d5
commit 24bc280806
4 changed files with 142 additions and 95 deletions

View file

@ -34,6 +34,17 @@
#include "gstbasecamerasrc.h" #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); GST_DEBUG_CATEGORY (base_camera_src_debug);
#define GST_CAT_DEFAULT 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; 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 static void
gst_base_camera_src_dispose (GObject * object) 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); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
@ -305,6 +369,9 @@ gst_base_camera_src_get_property (GObject * object,
case ARG_MODE: case ARG_MODE:
g_value_set_enum (value, self->mode); g_value_set_enum (value, self->mode);
break; break;
case ARG_READY_FOR_CAPTURE:
g_value_set_boolean (value, !self->capturing);
break;
case ARG_ZOOM: case ARG_ZOOM:
g_value_set_int (value, g_atomic_int_get (&self->zoom)); g_value_set_int (value, g_atomic_int_get (&self->zoom));
break; break;
@ -431,8 +498,46 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass)
GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, GST_TYPE_CAMERABIN_MODE, MODE_IMAGE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 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 static void
@ -459,4 +564,7 @@ gst_base_camera_src_init (GstBaseCameraSrc * self,
self->fps_n = DEFAULT_FPS_N; self->fps_n = DEFAULT_FPS_N;
self->fps_d = DEFAULT_FPS_D; self->fps_d = DEFAULT_FPS_D;
self->capturing = FALSE;
self->capturing_mutex = g_mutex_new ();
} }

View file

@ -62,6 +62,9 @@ struct _GstBaseCameraSrc
gint mode; gint mode;
gboolean capturing;
GMutex *capturing_mutex;
/* XXX preview pads? */ /* XXX preview pads? */
/* Resolution of the buffers configured to camerabin */ /* Resolution of the buffers configured to camerabin */
@ -127,6 +130,12 @@ struct _GstBaseCameraSrcClass
void (*finish_image_capture) (GstBaseCameraSrc * self); 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]; 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 ( const GValue * gst_base_camera_src_find_better_framerate (
GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_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.. // XXX add methods to get/set img capture and vid capture caps..
#endif /* __GST_BASE_CAMERA_SRC_H__ */ #endif /* __GST_BASE_CAMERA_SRC_H__ */

View file

@ -35,16 +35,6 @@
#include "camerabingeneral.h" #include "camerabingeneral.h"
#include "gstcamerabin-enum.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" #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420"
/* Using "bilinear" as default zoom method */ /* Using "bilinear" as default zoom method */
@ -53,8 +43,6 @@ enum
GST_DEBUG_CATEGORY (v4l2_camera_src_debug); GST_DEBUG_CATEGORY (v4l2_camera_src_debug);
#define GST_CAT_DEFAULT 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_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc,
GST_TYPE_BASE_CAMERA_SRC); GST_TYPE_BASE_CAMERA_SRC);
@ -64,9 +52,6 @@ static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps);
static void static void
gst_v4l2_camera_src_dispose (GObject * object) 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); 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); GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object);
switch (prop_id) { switch (prop_id) {
case ARG_READY_FOR_CAPTURE:
g_value_set_boolean (value, !self->capturing);
break;
case ARG_FILTER_CAPS: case ARG_FILTER_CAPS:
gst_value_set_caps (value, self->view_finder_caps); gst_value_set_caps (value, self->view_finder_caps);
break; break;
@ -157,18 +139,18 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer,
gpointer data) gpointer data)
{ {
GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data);
GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data);
gboolean ret = FALSE; gboolean ret = FALSE;
g_mutex_lock (self->capturing_mutex); g_mutex_lock (camerasrc->capturing_mutex);
if (self->image_capture_count > 0) { if (self->image_capture_count > 0) {
ret = TRUE; ret = TRUE;
self->image_capture_count--; self->image_capture_count--;
if (self->image_capture_count == 0) { if (self->image_capture_count == 0) {
self->capturing = FALSE; gst_base_camera_src_finish_capture (camerasrc);
g_object_notify (G_OBJECT (self), "ready-for-capture");
} }
} }
g_mutex_unlock (self->capturing_mutex); g_mutex_unlock (camerasrc->capturing_mutex);
return ret; return ret;
} }
@ -182,6 +164,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer,
gpointer data) gpointer data)
{ {
GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data);
GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self);
gboolean ret = FALSE; gboolean ret = FALSE;
/* TODO do we want to lock for every buffer? */ /* 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 * Note that we can use gst_pad_push_event here because we are a buffer
* probe. * 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) { if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) {
/* NOP */ /* NOP */
} else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { } 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_DEBUG_OBJECT (self, "Finishing video recording, pushing eos");
gst_pad_push_event (pad, gst_event_new_eos ()); gst_pad_push_event (pad, gst_event_new_eos ());
self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE;
self->capturing = FALSE; gst_base_camera_src_finish_capture (camerasrc);
g_object_notify (G_OBJECT (self), "ready-for-capture");
} else { } else {
ret = TRUE; ret = TRUE;
} }
g_mutex_unlock (self->capturing_mutex); g_mutex_unlock (camerasrc->capturing_mutex);
return ret; return ret;
} }
@ -1034,19 +1017,12 @@ gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc)
} }
} }
static void static gboolean
gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc)
{ {
GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc);
g_mutex_lock (src->capturing_mutex);
if (src->capturing) {
GST_WARNING_OBJECT (src, "Capturing already ongoing");
g_mutex_unlock (src->capturing_mutex);
return;
}
src->capturing = TRUE; /* TODO shoud we access this directly? Maybe a macro is better? */
/* TODO should we use a macro? */
if (camerasrc->mode == MODE_IMAGE) { if (camerasrc->mode == MODE_IMAGE) {
src->image_capture_count = 1; src->image_capture_count = 1;
start_image_capture (src); start_image_capture (src);
@ -1056,23 +1032,17 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src)
} }
} else { } else {
g_assert_not_reached (); g_assert_not_reached ();
src->capturing = FALSE; return FALSE;
} }
if (src->capturing) return TRUE;
g_object_notify (G_OBJECT (src), "ready-for-capture");
g_mutex_unlock (src->capturing_mutex);
} }
static void 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); GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc);
g_mutex_lock (src->capturing_mutex);
if (!src->capturing) { /* TODO shoud we access this directly? Maybe a macro is better? */
GST_DEBUG_OBJECT (src, "No ongoing capture");
g_mutex_unlock (src->capturing_mutex);
return;
}
if (camerasrc->mode == MODE_VIDEO) { if (camerasrc->mode == MODE_VIDEO) {
if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) {
GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); GST_DEBUG_OBJECT (src, "Aborting, had not started recording");
@ -1084,10 +1054,7 @@ gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src)
} }
} else { } else {
src->image_capture_count = 0; 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 static void
@ -1119,40 +1086,6 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass)
/* g_object_class_install_property .... */ /* 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 = gstbasecamerasrc_class->construct_pipeline =
gst_v4l2_camera_src_construct_pipeline; gst_v4l2_camera_src_construct_pipeline;
gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_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; gst_v4l2_camera_src_get_allowed_input_caps;
gstbasecamerasrc_class->finish_image_capture = gstbasecamerasrc_class->finish_image_capture =
gst_v4l2_camera_src_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 static void
@ -1171,8 +1106,6 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self,
/* TODO where are variables reset? */ /* TODO where are variables reset? */
self->image_capture_count = 0; self->image_capture_count = 0;
self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE;
self->capturing_mutex = g_mutex_new ();
self->capturing = FALSE;
} }
gboolean gboolean

View file

@ -57,9 +57,6 @@ struct _GstV4l2CameraSrc
{ {
GstBaseCameraSrc parent; GstBaseCameraSrc parent;
gboolean capturing;
GMutex *capturing_mutex;
/* video recording controls */ /* video recording controls */
gint video_rec_status; gint video_rec_status;
@ -108,9 +105,6 @@ struct _GstV4l2CameraSrc
struct _GstV4l2CameraSrcClass struct _GstV4l2CameraSrcClass
{ {
GstBaseCameraSrcClass parent; GstBaseCameraSrcClass parent;
void (*start_capture) (GstV4l2CameraSrc * src);
void (*stop_capture) (GstV4l2CameraSrc * src);
}; };
gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin);