diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-03-01 19:55:26 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-03-01 19:55:26 +0100 |
commit | b6755a70004a445a475e6c4b1c2d289e908cf2a9 (patch) | |
tree | d6e4111b21d477cdfdbc4e3f84af1ead54ec2550 /sys/v4l2/gstv4l2src.c | |
parent | 7087da96dc850a931f7fca4c036fb0a2c58f04ac (diff) |
Wait for a frame to become available before capturing it
Use GstPoll to wait for the fd of the video device to become readable before
trying to capture a frame. This speeds up stopping v4l2src a lot as it no
longer has to wait for the next frame, especially when capturing with low
framerates or when the video device just never generates a frame (which seems a
common issue for uvcvideo devices)
Fixes bug #563574.
Diffstat (limited to 'sys/v4l2/gstv4l2src.c')
-rw-r--r-- | sys/v4l2/gstv4l2src.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 9f96a211..141fb7bb 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -240,6 +240,10 @@ static void gst_v4l2src_finalize (GstV4l2Src * v4l2src); /* basesrc methods */ static gboolean gst_v4l2src_start (GstBaseSrc * src); +static gboolean gst_v4l2src_unlock (GstBaseSrc * src); + +static gboolean gst_v4l2src_unlock_stop (GstBaseSrc * src); + static gboolean gst_v4l2src_stop (GstBaseSrc * src); static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps); @@ -312,6 +316,8 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass) basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps); basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps); basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start); + basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock); + basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock_stop); basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2src_stop); basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query); basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_v4l2src_fixate); @@ -1176,6 +1182,29 @@ gst_v4l2src_start (GstBaseSrc * src) } static gboolean +gst_v4l2src_unlock (GstBaseSrc * src) +{ + GstV4l2Src *v4l2src = GST_V4L2SRC (src); + + GST_LOG_OBJECT (src, "Flushing"); + gst_poll_set_flushing (v4l2src->v4l2object->poll, TRUE); + + return TRUE; +} + +static gboolean +gst_v4l2src_unlock_stop (GstBaseSrc * src) +{ + GstV4l2Src *v4l2src = GST_V4L2SRC (src); + + GST_LOG_OBJECT (src, "No longer flushing"); + gst_poll_set_flushing (v4l2src->v4l2object->poll, FALSE); + + return TRUE; +} + + +static gboolean gst_v4l2src_stop (GstBaseSrc * src) { GstV4l2Src *v4l2src = GST_V4L2SRC (src); @@ -1203,6 +1232,7 @@ static GstFlowReturn gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf) { gint amount; + gint ret; gint buffersize; @@ -1211,6 +1241,18 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf) *buf = gst_buffer_new_and_alloc (buffersize); do { + ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE); + if (G_UNLIKELY (ret < 0)) { + if (errno == EBUSY) + goto stopped; +#ifdef G_OS_WIN32 + if (WSAGetLastError () != WSAEINTR) + goto select_error; +#else + if (errno != EAGAIN && errno != EINTR) + goto select_error; +#endif + } amount = v4l2_read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf), buffersize); @@ -1270,6 +1312,17 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf) return GST_FLOW_OK; /* ERRORS */ +select_error: + { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), + ("select error %d: %s (%d)", ret, g_strerror (errno), errno)); + return GST_FLOW_ERROR; + } +stopped: + { + GST_DEBUG ("stop called"); + return GST_FLOW_WRONG_STATE; + } read_error: { GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, |