diff options
Diffstat (limited to 'sys/v4l2')
-rw-r--r-- | sys/v4l2/gstv4l2object.c | 4 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2object.h | 1 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.c | 70 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.c | 8 | ||||
-rw-r--r-- | sys/v4l2/v4l2src_calls.c | 33 |
5 files changed, 114 insertions, 2 deletions
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index ffc1046d..d848ccf3 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -270,6 +270,7 @@ gst_v4l2_object_new (GstElement * element, v4l2object->update_fps_func = update_fps_func; v4l2object->video_fd = -1; + v4l2object->poll = gst_poll_new (TRUE); v4l2object->buffer = NULL; v4l2object->videodev = g_strdup (DEFAULT_PROP_DEVICE); @@ -290,6 +291,9 @@ gst_v4l2_object_destroy (GstV4l2Object * v4l2object) if (v4l2object->videodev) g_free (v4l2object->videodev); + if (v4l2object->poll) + gst_poll_free (v4l2object->poll); + if (v4l2object->channel) g_free (v4l2object->channel); diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 5eb557ed..c5bc3cb7 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -71,6 +71,7 @@ struct _GstV4l2Object { /* the video-device's file descriptor */ gint video_fd; + GstPoll * poll; /* the video buffer (mmap()'ed) */ guint8 **buffer; diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index a90ddf81..141fb7bb 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -129,6 +129,9 @@ static const guint32 gst_v4l2_formats[] = { #ifdef V4L2_PIX_FMT_PWC2 V4L2_PIX_FMT_PWC2, #endif +#ifdef V4L2_PIX_FMT_YVYU + V4L2_PIX_FMT_YVYU, +#endif }; #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats)) @@ -237,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); @@ -309,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); @@ -688,6 +697,9 @@ gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc) case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_Y41P: case V4L2_PIX_FMT_YUV422P: +#ifdef V4L2_PIX_FMT_YVYU + case V4L2_PIX_FMT_YVYU: +#endif case V4L2_PIX_FMT_YUV411P:{ guint32 fcc = 0; @@ -725,6 +737,11 @@ gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc) case V4L2_PIX_FMT_YUV422P: fcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B'); break; +#ifdef V4L2_PIX_FMT_YVYU + case V4L2_PIX_FMT_YVYU: + fcc = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); + break; +#endif default: g_assert_not_reached (); break; @@ -969,6 +986,12 @@ gst_v4l2_get_caps_info (GstV4l2Src * v4l2src, GstCaps * caps, outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h); outsize += (GST_ROUND_UP_4 (*w) * *h) / 2; break; +#ifdef V4L2_PIX_FMT_YVYU + case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): + fourcc = V4L2_PIX_FMT_YVYU; + outsize = (GST_ROUND_UP_2 (*w) * 2) * *h; + break; +#endif } } else if (!strcmp (mimetype, "video/x-raw-rgb")) { gint depth, endianness, r_mask; @@ -1159,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); @@ -1186,6 +1232,7 @@ static GstFlowReturn gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf) { gint amount; + gint ret; gint buffersize; @@ -1194,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); @@ -1253,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, diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index a6b4b7dc..b1875a88 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -400,6 +400,7 @@ gst_v4l2_open (GstV4l2Object * v4l2object) { struct stat st; int libv4l2_fd; + GstPollFD pollfd = GST_POLL_FD_INIT; GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s", v4l2object->videodev); @@ -453,6 +454,10 @@ gst_v4l2_open (GstV4l2Object * v4l2object) "Opened device '%s' (%s) successfully", v4l2object->vcap.card, v4l2object->videodev); + pollfd.fd = v4l2object->video_fd; + gst_poll_add_fd (v4l2object->poll, &pollfd); + gst_poll_fd_ctl_read (v4l2object->poll, &pollfd, TRUE); + return TRUE; /* ERRORS */ @@ -508,6 +513,7 @@ error: gboolean gst_v4l2_close (GstV4l2Object * v4l2object) { + GstPollFD pollfd = GST_POLL_FD_INIT; GST_DEBUG_OBJECT (v4l2object->element, "Trying to close %s", v4l2object->videodev); @@ -516,6 +522,8 @@ gst_v4l2_close (GstV4l2Object * v4l2object) /* close device */ v4l2_close (v4l2object->video_fd); + pollfd.fd = v4l2object->video_fd; + gst_poll_remove_fd (v4l2object->poll, &pollfd); v4l2object->video_fd = -1; /* empty lists */ diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index c247c497..5abfda31 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -771,6 +771,7 @@ unknown_type: } #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */ +#ifdef VIDIOC_ENUM_FRAMESIZES static gint sort_by_frame_size (GstStructure * s1, GstStructure * s2) { @@ -784,6 +785,7 @@ sort_by_frame_size (GstStructure * s1, GstStructure * s2) /* I think it's safe to assume that this won't overflow for a while */ return ((w2 * h2) - (w1 * h1)); } +#endif GstCaps * gst_v4l2src_probe_caps_for_format (GstV4l2Src * v4l2src, guint32 pixelformat, @@ -974,7 +976,7 @@ default_frame_sizes: /****************************************************** * gst_v4l2src_grab_frame (): * grab a frame for capturing - * return value: GST_FLOW_OK or GST_FLOW_ERROR + * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR ******************************************************/ GstFlowReturn gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) @@ -985,12 +987,28 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) GstBuffer *pool_buffer; gboolean need_copy; gint index; + gint ret; memset (&buffer, 0x00, sizeof (buffer)); buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; - while (v4l2_ioctl (v4l2src->v4l2object->video_fd, VIDIOC_DQBUF, &buffer) < 0) { + for (;;) { + 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 + } + + if (v4l2_ioctl (v4l2src->v4l2object->video_fd, VIDIOC_DQBUF, &buffer) >= 0) + break; GST_WARNING_OBJECT (v4l2src, "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d", @@ -1133,6 +1151,17 @@ gst_v4l2src_grab_frame (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; + } einval: { GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED, |