From 9b9b9d5c6f3d2507677f777ca4271d93730f1e6a Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 22 Jul 2005 15:25:29 +0000 Subject: sys/v4l2/: implement read access. V4l2src will use read access if mmap doesn't work. Original commit message from CVS: * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_capture_init), (gst_v4l2src_capture_start), (gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit): * sys/v4l2/gstv4l2src.c: (gst_v4l2src_getcaps), (gst_v4l2src_get_read), (gst_v4l2src_get_mmap), (gst_v4l2src_get): implement read access. V4l2src will use read access if mmap doesn't work. * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), (gst_v4l2_get_norm), (gst_v4l2_set_norm), (gst_v4l2_get_input), (gst_v4l2_set_input), (gst_v4l2_get_output), (gst_v4l2_set_output), (gst_v4l2_get_frequency), (gst_v4l2_set_frequency), (gst_v4l2_signal_strength), (gst_v4l2_get_attribute), (gst_v4l2_set_attribute): don't GST_ELEMENT_ERROR on get/set functions. Fail silently instead, but do output a debugging message --- ChangeLog | 18 ++++++ sys/v4l2/gstv4l2src.c | 96 ++++++++++++++++++++------- sys/v4l2/v4l2_calls.c | 120 +++++++++++++++++++--------------- sys/v4l2/v4l2src_calls.c | 165 +++++++++++++++++++++++++++-------------------- 4 files changed, 254 insertions(+), 145 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8741e7a..2cbcc980 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2005-07-22 Benjamin Otte + + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_capture_init), + (gst_v4l2src_capture_start), (gst_v4l2src_capture_stop), + (gst_v4l2src_capture_deinit): + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_getcaps), + (gst_v4l2src_get_read), (gst_v4l2src_get_mmap), (gst_v4l2src_get): + implement read access. V4l2src will use read access if mmap doesn't + work. + * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), + (gst_v4l2_get_norm), (gst_v4l2_set_norm), (gst_v4l2_get_input), + (gst_v4l2_set_input), (gst_v4l2_get_output), (gst_v4l2_set_output), + (gst_v4l2_get_frequency), (gst_v4l2_set_frequency), + (gst_v4l2_signal_strength), (gst_v4l2_get_attribute), + (gst_v4l2_set_attribute): + don't GST_ELEMENT_ERROR on get/set functions. Fail silently instead, + but do output a debugging message + 2005-07-22 Ronald S. Bultje * gst-libs/gst/riff/riff-media.c: diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index b563d9c6..44eb7641 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -23,6 +23,7 @@ #include #include +#include #include "v4l2src_calls.h" #include "gstv4l2tuner.h" @@ -788,14 +789,10 @@ gst_v4l2src_getcaps (GstPad * pad) continue; } /* template */ - if (min_w < 1) - min_w = 1; - if (min_h < 1) - min_h = 1; - if (max_w > 4096) - max_w = 4096; - if (max_h > 4096) - max_h = 4096; + min_w = CLAMP (min_w, 1, 4096); + min_h = CLAMP (min_h, 1, 4096); + max_w = CLAMP (max_w, min_w, 4096); + max_h = CLAMP (max_h, min_h, 4096); /* add to list */ structure = gst_v4l2src_v4l2fourcc_to_caps (format->pixelformat); @@ -814,20 +811,51 @@ gst_v4l2src_getcaps (GstPad * pad) } static GstData * -gst_v4l2src_get (GstPad * pad) +gst_v4l2src_get_read (GstV4l2Src * v4l2src) { - GstV4l2Src *v4l2src; - GstBuffer *buf; - gint i, num = -1; - gdouble fps = 0; + gint amount; + gint buffersize; + + buffersize = v4l2src->format.fmt.pix.sizeimage; + do { + GstBuffer *buf = + gst_pad_alloc_buffer (v4l2src->srcpad, GST_BUFFER_OFFSET_NONE, + buffersize); + amount = + read (GST_V4L2ELEMENT (v4l2src)->video_fd, GST_BUFFER_DATA (buf), + buffersize); + if (amount == buffersize) { + gdouble fps = gst_v4l2src_get_fps (v4l2src); - v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad)); + GST_BUFFER_TIMESTAMP (buf) = v4l2src->handled * GST_SECOND / fps; + GST_BUFFER_DURATION (buf) = GST_SECOND / fps; + return GST_DATA (buf); + } else if (amount == -1) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } else { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL), + ("error read()ing a buffer on device %s: %s", + GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno))); + gst_data_unref (GST_DATA (buf)); + return NULL; + } + } else { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL), + ("error read()ing a buffer on device %s: got only %d bytes instead of expected %d", + GST_V4L2ELEMENT (v4l2src)->device, amount, buffersize)); + gst_data_unref (GST_DATA (buf)); + return NULL; + } + } while (TRUE); +} - if (v4l2src->use_fixed_fps && (fps = gst_v4l2src_get_fps (v4l2src)) == 0) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL), - ("could not get frame rate for element")); - return NULL; - } +static GstData * +gst_v4l2src_get_mmap (GstV4l2Src * v4l2src) +{ + GstBuffer *buf; + gint i, num = -1; + gdouble fps = gst_v4l2src_get_fps (v4l2src); if (v4l2src->need_writes > 0) { /* use last frame */ @@ -947,13 +975,35 @@ gst_v4l2src_get (GstPad * pad) } } - v4l2src->handled++; - g_signal_emit (G_OBJECT (v4l2src), gst_v4l2src_signals[SIGNAL_FRAME_CAPTURE], - 0); - return GST_DATA (buf); } +static GstData * +gst_v4l2src_get (GstPad * pad) +{ + GstV4l2Src *v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad)); + GstData *ret; + + if (v4l2src->use_fixed_fps && gst_v4l2src_get_fps (v4l2src) == 0) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL), + ("could not get frame rate for element")); + return NULL; + } + + if (v4l2src->breq.memory == V4L2_MEMORY_MMAP) { + ret = gst_v4l2src_get_mmap (v4l2src); + } else { + ret = gst_v4l2src_get_read (v4l2src); + } + + if (ret) { + v4l2src->handled++; + g_signal_emit (G_OBJECT (v4l2src), + gst_v4l2src_signals[SIGNAL_FRAME_CAPTURE], 0); + } + return ret; +} + static void gst_v4l2src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index b630fc04..b0a9e5f6 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -35,6 +35,8 @@ #include "gstv4l2colorbalance.h" #include "gstv4l2src.h" +/* until someone comes up with a general category... */ +#define GST_CAT_DEFAULT v4l2src_debug #define DEBUG(format, args...) \ GST_DEBUG_OBJECT (\ @@ -52,12 +54,12 @@ static gboolean gst_v4l2_get_capabilities (GstV4l2Element * v4l2element) { DEBUG ("getting capabilities"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Error getting %s capabilities: %s", - v4l2element->device, g_strerror (errno))); + GST_ERROR_OBJECT (v4l2element, "Error getting %s capabilities: %s", + v4l2element->device, g_strerror (errno)); return FALSE; } @@ -475,12 +477,13 @@ gboolean gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm) { DEBUG ("getting norm"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get the current norm for device %s: %s", - v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get the current norm for device %s: %s", v4l2element->device, + g_strerror (errno)); return FALSE; } @@ -498,13 +501,15 @@ gboolean gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm) { DEBUG ("trying to set norm to %llx", norm); - GST_V4L2_CHECK_OPEN (v4l2element); - GST_V4L2_CHECK_NOT_ACTIVE (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; + if (!GST_V4L2_IS_ACTIVE (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to set norm 0x%llx for device %s: %s", - norm, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to set norm 0x%llx for device %s: %s", norm, + v4l2element->device, g_strerror (errno)); return FALSE; } @@ -524,12 +529,13 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input) gint n; DEBUG ("trying to get input"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get current input on device %s: %s", - v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get current input on device %s: %s", v4l2element->device, + g_strerror (errno)); return FALSE; } @@ -549,13 +555,14 @@ gboolean gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input) { DEBUG ("trying to set input to %d", input); - GST_V4L2_CHECK_OPEN (v4l2element); - GST_V4L2_CHECK_NOT_ACTIVE (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; + if (!GST_V4L2_IS_ACTIVE (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to set input %d on device %s: %s", - input, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, "Failed to set input %d on device %s: %s", + input, v4l2element->device, g_strerror (errno)); return FALSE; } @@ -575,12 +582,13 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output) gint n; DEBUG ("trying to get output"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get current output on device %s: %s", - v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get current output on device %s: %s", v4l2element->device, + g_strerror (errno)); return FALSE; } @@ -600,13 +608,15 @@ gboolean gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output) { DEBUG ("trying to set output to %d", output); - GST_V4L2_CHECK_OPEN (v4l2element); - GST_V4L2_CHECK_NOT_ACTIVE (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; + if (!GST_V4L2_IS_ACTIVE (v4l2element)) + return FALSE; if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to set output %d on device %s: %s", - output, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to set current output on device %s to %d: %s", + v4l2element->device, output, g_strerror (errno)); return FALSE; } @@ -628,15 +638,16 @@ gst_v4l2_get_frequency (GstV4l2Element * v4l2element, GstTunerChannel *channel; DEBUG ("getting current tuner frequency"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; channel = gst_tuner_get_channel (GST_TUNER (v4l2element)); freq.tuner = tunernum; if (ioctl (v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get current tuner frequency for device %s: %s", - v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get current tuner frequency for device %s: %s", + v4l2element->device, g_strerror (errno)); return FALSE; } @@ -660,8 +671,10 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element, GstTunerChannel *channel; DEBUG ("setting current tuner frequency to %lu", frequency); - GST_V4L2_CHECK_OPEN (v4l2element); - GST_V4L2_CHECK_NOT_ACTIVE (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; + if (!GST_V4L2_IS_ACTIVE (v4l2element)) + return FALSE; channel = gst_tuner_get_channel (GST_TUNER (v4l2element)); @@ -671,9 +684,9 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element, freq.frequency = frequency / channel->freq_multiplicator; if (ioctl (v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to set tuner frequency to %lu for device %s: %s", - frequency, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to set current tuner frequency for device %s to %lu: %s", + v4l2element->device, frequency, g_strerror (errno)); return FALSE; } @@ -694,13 +707,14 @@ gst_v4l2_signal_strength (GstV4l2Element * v4l2element, struct v4l2_tuner tuner; DEBUG ("trying to get signal strength"); - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; tuner.index = tunernum; if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get signal strength for device %s: %s", - v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get signal strength for device %s: %s", v4l2element->device, + g_strerror (errno)); return FALSE; } @@ -722,16 +736,17 @@ gst_v4l2_get_attribute (GstV4l2Element * v4l2element, { struct v4l2_control control; - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; DEBUG ("getting value of attribute %d", attribute_num); control.id = attribute_num; if (ioctl (v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to get value for control %d on device %s: %s", - attribute_num, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to get value for control %d on device %s: %s", attribute_num, + v4l2element->device, g_strerror (errno)); return FALSE; } @@ -753,7 +768,8 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element, { struct v4l2_control control; - GST_V4L2_CHECK_OPEN (v4l2element); + if (!GST_V4L2_IS_OPEN (v4l2element)) + return FALSE; DEBUG ("setting value of attribute %d to %d", attribute_num, value); @@ -761,9 +777,9 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element, control.value = value; if (ioctl (v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL), - ("Failed to set value %d for control %d on device %s: %s", - value, attribute_num, v4l2element->device, g_strerror (errno))); + GST_WARNING_OBJECT (v4l2element, + "Failed to set value %d for control %d on device %s: %s", value, + attribute_num, v4l2element->device, g_strerror (errno)); return FALSE; } diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index 79d4aa7f..a6c11955 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -249,72 +249,92 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src) v4l2src->breq.count = GST_V4L2_MIN_BUFFERS; } v4l2src->breq.type = v4l2src->format.type; - v4l2src->breq.memory = V4L2_MEMORY_MMAP; - if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS, - &v4l2src->breq) < 0) { + if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_STREAMING) { + v4l2src->breq.memory = V4L2_MEMORY_MMAP; + if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS, + &v4l2src->breq) < 0) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, + (_("Could not get buffers from device \"%s\"."), + GST_V4L2ELEMENT (v4l2src)->device), + ("error requesting %d buffers: %s", v4l2src->breq.count, + g_strerror (errno))); + return FALSE; + } + GST_LOG_OBJECT (v4l2src, "using default mmap method"); + } else if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_READWRITE) { + v4l2src->breq.memory = 0; + GST_INFO_OBJECT (v4l2src, "using fallback read method"); + } else { GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, - (_("Could not get buffers from device \"%s\"."), + (_("the driver of device \"%s\" is broken."), GST_V4L2ELEMENT (v4l2src)->device), - ("error requesting %d buffers: %s", v4l2src->breq.count, - g_strerror (errno))); + ("no supported read capability from %s", + GST_V4L2ELEMENT (v4l2src)->device)); return FALSE; } - if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, - (_("Could not get enough buffers from device \"%s\"."), - GST_V4L2ELEMENT (v4l2src)->device), - ("we received %d, we want at least %d", v4l2src->breq.count, - GST_V4L2_MIN_BUFFERS)); - v4l2src->breq.count = buffers; - return FALSE; - } - if (v4l2src->breq.count != buffers) - g_object_notify (G_OBJECT (v4l2src), "num_buffers"); - - GST_INFO_OBJECT (v4l2src, - "Got %d buffers (" GST_FOURCC_FORMAT ") of size %d KB\n", - v4l2src->breq.count, - GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat), - v4l2src->format.fmt.pix.sizeimage / 1024); - - /* Map the buffers */ - v4l2src->pool = g_new (GstV4l2BufferPool, 1); - gst_atomic_int_init (&v4l2src->pool->refcount, 1); - v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd; - v4l2src->pool->buffer_count = v4l2src->breq.count; - v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count); - - for (n = 0; n < v4l2src->breq.count; n++) { - GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n]; - - gst_atomic_int_init (&buffer->refcount, 1); - buffer->pool = v4l2src->pool; - buffer->buffer.index = n; - buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF, - &buffer->buffer) < 0) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), - ("Could not get buffer properties of buffer %d: %s", n, - g_strerror (errno))); - gst_v4l2src_capture_deinit (v4l2src); - return FALSE; - } - buffer->start = - mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, - GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset); - if (buffer->start == MAP_FAILED) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), - ("Could not mmap video buffer %d: %s", n, g_strerror (errno))); - buffer->start = 0; - gst_v4l2src_capture_deinit (v4l2src); + if (v4l2src->breq.memory > 0) { + if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, + (_("Could not get enough buffers from device \"%s\"."), + GST_V4L2ELEMENT (v4l2src)->device), + ("we received %d, we want at least %d", v4l2src->breq.count, + GST_V4L2_MIN_BUFFERS)); + v4l2src->breq.count = buffers; return FALSE; } - buffer->length = buffer->buffer.length; - if (!gst_v4l2src_queue_frame (v4l2src, n)) { - gst_v4l2src_capture_deinit (v4l2src); - return FALSE; + if (v4l2src->breq.count != buffers) + g_object_notify (G_OBJECT (v4l2src), "num_buffers"); + + GST_INFO_OBJECT (v4l2src, + "Got %d buffers (" GST_FOURCC_FORMAT ") of size %d KB\n", + v4l2src->breq.count, + GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat), + v4l2src->format.fmt.pix.sizeimage / 1024); + + /* Map the buffers */ + GST_LOG_OBJECT (v4l2src, "initiating buffer pool"); + + v4l2src->pool = g_new (GstV4l2BufferPool, 1); + gst_atomic_int_init (&v4l2src->pool->refcount, 1); + v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd; + v4l2src->pool->buffer_count = v4l2src->breq.count; + v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count); + + for (n = 0; n < v4l2src->breq.count; n++) { + GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n]; + + gst_atomic_int_init (&buffer->refcount, 1); + buffer->pool = v4l2src->pool; + buffer->buffer.index = n; + buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF, + &buffer->buffer) < 0) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), + ("Could not get buffer properties of buffer %d: %s", n, + g_strerror (errno))); + gst_v4l2src_capture_deinit (v4l2src); + return FALSE; + } + buffer->start = + mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, + GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset); + if (buffer->start == MAP_FAILED) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), + ("Could not mmap video buffer %d: %s", n, g_strerror (errno))); + buffer->start = 0; + gst_v4l2src_capture_deinit (v4l2src); + return FALSE; + } + buffer->length = buffer->buffer.length; + if (!gst_v4l2src_queue_frame (v4l2src, n)) { + gst_v4l2src_capture_deinit (v4l2src); + return FALSE; + } } + } else { + GST_LOG_OBJECT (v4l2src, "no buffer pool used"); + v4l2src->pool = NULL; } GST_V4L2_SET_ACTIVE (GST_V4L2ELEMENT (v4l2src)); @@ -344,11 +364,13 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src) v4l2src->quit = FALSE; - if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL), - ("Error starting streaming capture from device %s: %s", - GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno))); - return FALSE; + if (v4l2src->breq.memory != 0) { + if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL), + ("Error starting streaming capture from device %s: %s", + GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno))); + return FALSE; + } } v4l2src->is_capturing = TRUE; @@ -372,13 +394,16 @@ gst_v4l2src_capture_stop (GstV4l2Src * v4l2src) GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src)); GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src)); - /* we actually need to sync on all queued buffers but not - * on the non-queued ones */ - if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF, &type) < 0) { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL), - ("Error stopping streaming capture from device %s: %s", - GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno))); - return FALSE; + if (v4l2src->breq.memory != 0) { + /* we actually need to sync on all queued buffers but not + * on the non-queued ones */ + if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF, + &type) < 0) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL), + ("Error stopping streaming capture from device %s: %s", + GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno))); + return FALSE; + } } /* make an optional pending wait stop */ -- cgit v1.2.1