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"
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 ();
}

View file

@ -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__ */

View file

@ -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

View file

@ -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);