From 91b7f2d99ed68f5c66aa3baf7a4cbfb9bd0bc5a8 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 15:49:26 -0300 Subject: [PATCH] v4l2camerasrc: Implement video capture Implements video capture on v4l2camerasrc by using the mode property, when mode is set to video, the pad probe pushes a new segment and starts pushing buffers on the pad, when it the property is sent back to preview, the pad probe pushes an EOS and stops pushing buffers. This is controlled by a Recording State variable, that is protected by the GST_OBJECT_LOCK. I don't think locking for every buffer is nice, so we could find an alternative lockless way here. --- gst/camerabin2/gstv4l2camerasrc.c | 67 ++++++++++++++++++++++++++----- gst/camerabin2/gstv4l2camerasrc.h | 10 +++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index d13e148e27..1b245e6be8 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -70,8 +70,8 @@ gst_v4l2_camera_src_set_property (GObject * object, switch (prop_id) { case ARG_MODE: - self->mode = g_value_get_enum (value); - gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), self->mode); + gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), + g_value_get_enum (value)); break; case ARG_FILTER_CAPS: GST_OBJECT_LOCK (self); @@ -168,8 +168,36 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + gboolean ret = FALSE; + GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_VIDEO); - return self->mode == MODE_VIDEO; + + /* TODO do we want to lock for every buffer? */ + /* + * Note that we can use gst_pad_push_event here because we are a buffer + * probe. + */ + if (self->mode == MODE_VIDEO) { + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { + /* send the newseg */ + gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; + ret = TRUE; + } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { + /* send eos */ + gst_pad_push_event (pad, gst_event_new_eos ()); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + self->mode = MODE_PREVIEW; + g_object_notify (G_OBJECT (self), "mode"); + } else { + ret = TRUE; + } + GST_OBJECT_UNLOCK (self); + } + + return ret; } /** @@ -678,6 +706,7 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); + gint ret = TRUE; if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), @@ -686,20 +715,34 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) } } - self->mode = mode; - switch (mode) { case MODE_PREVIEW: - return TRUE; // XXX + if (self->mode == MODE_VIDEO) { + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_RUNNING) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_FINISHING; + GST_OBJECT_UNLOCK (self); + } + break; case MODE_IMAGE: - return start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); + ret = start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); + break; case MODE_VIDEO: - return TRUE; // XXX + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; + GST_OBJECT_UNLOCK (self); + break; + default: + g_assert_not_reached (); + ret = FALSE; } - g_assert_not_reached (); - - return FALSE; + if (ret) + self->mode = mode; + return ret; } static gboolean @@ -1058,7 +1101,9 @@ static void gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, GstV4l2CameraSrcClass * klass) { + /* TODO where are variables reset? */ self->mode = MODE_PREVIEW; + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; } gboolean diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index f12dc8c00b..9e40ffaee5 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -41,6 +41,13 @@ G_BEGIN_DECLS typedef struct _GstV4l2CameraSrc GstV4l2CameraSrc; typedef struct _GstV4l2CameraSrcClass GstV4l2CameraSrcClass; +enum GstVideoRecordingStatus { + GST_VIDEO_RECORDING_STATUS_DONE, + GST_VIDEO_RECORDING_STATUS_STARTING, + GST_VIDEO_RECORDING_STATUS_RUNNING, + GST_VIDEO_RECORDING_STATUS_FINISHING +}; + /** * GstV4l2CameraSrc: @@ -52,6 +59,9 @@ struct _GstV4l2CameraSrc GstCameraBinMode mode; + /* video recording controls */ + gint video_rec_status; + /* source elements */ GstElement *src_vid_src; GstElement *src_filter;