summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2005-07-22 15:25:29 +0000
committerBenjamin Otte <otte@gnome.org>2005-07-22 15:25:29 +0000
commit9b9b9d5c6f3d2507677f777ca4271d93730f1e6a (patch)
tree0737f47cb2e4b7e20070d9214a8bc91b0987c999
parenta427a79b61f9bb19a13f410ba1efde8daced28e4 (diff)
downloadgstreamer-plugins-bad-9b9b9d5c6f3d2507677f777ca4271d93730f1e6a.tar.gz
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
-rw-r--r--ChangeLog18
-rw-r--r--sys/v4l2/gstv4l2src.c96
-rw-r--r--sys/v4l2/v4l2_calls.c120
-rw-r--r--sys/v4l2/v4l2src_calls.c165
4 files changed, 254 insertions, 145 deletions
diff --git a/ChangeLog b/ChangeLog
index d8741e7ae..2cbcc9801 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2005-07-22 Benjamin Otte <otte@gnome.org>
+
+ * 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 <rbultje@ronald.bitfreak.net>
* gst-libs/gst/riff/riff-media.c:
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index b563d9c61..44eb76418 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <sys/time.h>
+#include <unistd.h>
#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 b630fc04b..b0a9e5f68 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 79d4aa7fa..a6c119554 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 */