summaryrefslogtreecommitdiffstats
path: root/sys/v4l2/gstv4l2src.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/v4l2/gstv4l2src.c')
-rw-r--r--sys/v4l2/gstv4l2src.c189
1 files changed, 66 insertions, 123 deletions
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index f16451a0..e53b5b06 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -293,18 +293,15 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
static void
gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
{
+ /* fixme: give an update_fps_function */
v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
- gst_v4l2_get_input, gst_v4l2_set_input, gst_v4l2src_update_fps);
+ gst_v4l2_get_input, gst_v4l2_set_input, NULL);
/* number of buffers requested */
- v4l2src->breq.count = 0;
+ v4l2src->num_buffers = 0;
v4l2src->formats = NULL;
- /* fps */
- v4l2src->fps_n = 0;
- v4l2src->fps_d = 1;
-
v4l2src->is_capturing = FALSE;
gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (v4l2src),
@@ -339,16 +336,13 @@ static void
gst_v4l2src_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
- GstV4l2Src *v4l2src;
-
- g_return_if_fail (GST_IS_V4L2SRC (object));
- v4l2src = GST_V4L2SRC (object);
+ GstV4l2Src *v4l2src = GST_V4L2SRC (object);
if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
prop_id, value, pspec)) {
switch (prop_id) {
case PROP_QUEUE_SIZE:
- v4l2src->breq.count = g_value_get_uint (value);
+ v4l2src->num_buffers = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -362,16 +356,13 @@ static void
gst_v4l2src_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
- GstV4l2Src *v4l2src;
-
- g_return_if_fail (GST_IS_V4L2SRC (object));
- v4l2src = GST_V4L2SRC (object);
+ GstV4l2Src *v4l2src = GST_V4L2SRC (object);
if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
prop_id, value, pspec)) {
switch (prop_id) {
case PROP_QUEUE_SIZE:
- g_value_set_uint (value, v4l2src->breq.count);
+ g_value_set_uint (value, v4l2src->num_buffers);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -420,7 +411,7 @@ gst_v4l2src_fixate (GstPad * pad, GstCaps * caps)
}
static GstStructure *
-gst_v4l2src_v4l2fourcc_to_caps (guint32 fourcc)
+gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc)
{
GstStructure *structure = NULL;
@@ -690,7 +681,8 @@ gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
}
static struct v4l2_fmtdesc *
-gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src * v4l2src, GstStructure * structure)
+gst_v4l2_structure_to_v4l2fourcc (GstV4l2Src * v4l2src,
+ GstStructure * structure)
{
return gst_v4l2src_get_format_from_fourcc (v4l2src,
gst_v4l2_fourcc_from_structure (structure));
@@ -707,7 +699,7 @@ gst_v4l2src_get_all_caps (void)
caps = gst_caps_new_empty ();
for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
- structure = gst_v4l2src_v4l2fourcc_to_caps (gst_v4l2_formats[i]);
+ structure = gst_v4l2src_v4l2fourcc_to_structure (gst_v4l2_formats[i]);
if (structure) {
gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
@@ -725,71 +717,49 @@ static GstCaps *
gst_v4l2src_get_caps (GstBaseSrc * src)
{
GstV4l2Src *v4l2src = GST_V4L2SRC (src);
- GstCaps *caps;
- struct v4l2_fmtdesc *format;
- int min_w, max_w, min_h, max_h;
+ GstCaps *ret;
GSList *walk;
- GstStructure *structure;
- guint fps_n, fps_d;
if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
+ /* FIXME: copy? */
return
gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
(v4l2src)));
}
+ if (v4l2src->probed_caps)
+ return gst_caps_ref (v4l2src->probed_caps);
+
if (!v4l2src->formats)
gst_v4l2src_fill_format_list (v4l2src);
- /* build our own capslist */
- caps = gst_caps_new_empty ();
- walk = v4l2src->formats;
- if (!gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d)) {
- GST_DEBUG_OBJECT (v4l2src, "frame rate is unknown.");
- fps_n = 0;
- fps_d = 1;
- }
- while (walk) {
+ ret = gst_caps_new_empty ();
+
+ for (walk = v4l2src->formats; walk; walk = walk->next) {
+ struct v4l2_fmtdesc *format;
+ GstStructure *template;
+
format = (struct v4l2_fmtdesc *) walk->data;
- walk = g_slist_next (walk);
- /* get size delimiters */
- if (!gst_v4l2src_get_size_limits (v4l2src, format,
- &min_w, &max_w, &min_h, &max_h)) {
- continue;
- }
- /* template, FIXME, why limit if the device reported correct results? */
- /* we are doing it right now to avoid unexpected results */
- min_w = CLAMP (min_w, 1, GST_V4L2_MAX_SIZE);
- min_h = CLAMP (min_h, 1, GST_V4L2_MAX_SIZE);
- max_w = CLAMP (max_w, min_w, GST_V4L2_MAX_SIZE);
- max_h = CLAMP (max_h, min_h, GST_V4L2_MAX_SIZE);
-
- /* add to list */
- structure = gst_v4l2src_v4l2fourcc_to_caps (format->pixelformat);
-
- if (structure) {
- gst_structure_set (structure,
- "width", GST_TYPE_INT_RANGE, min_w, max_w,
- "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
-
- /* FIXME, why random range? */
- /* AFAIK: in v4l2 standard we still don't have a good way to enum
- for a range. Currently it is on discussion on v4l2 forum.
- Currently, something more smart could be done for tvcard devices.
- The maximum value could be determined by 'v4l2_standard.frameperiod'
- and minimum also to the same if V4L2_CAP_TIMEPERFRAME is not set. */
- /* another approach for web-cams would be to try to set a very
- high(100/1) and low(1/1) FPSs and get the values returned */
- gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE,
- 0, 1, 100, 1, NULL);
-
- gst_caps_append_structure (caps, structure);
+ template = gst_v4l2src_v4l2fourcc_to_structure (format->pixelformat);
+
+ if (template) {
+ GstCaps *tmp;
+
+ tmp = gst_v4l2src_probe_caps_for_format (v4l2src, format->pixelformat,
+ template);
+ if (tmp)
+ gst_caps_append (ret, tmp);
+
+ gst_structure_free (template);
+ } else {
+ GST_DEBUG_OBJECT (v4l2src, "unknown format %u", format->pixelformat);
}
}
- GST_DEBUG_OBJECT (v4l2src, "returning caps: %" GST_PTR_FORMAT, caps);
- return caps;
+ v4l2src->probed_caps = gst_caps_ref (ret);
+
+ return ret;
}
static gboolean
@@ -820,42 +790,32 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0);
/* we want our own v4l2 type of fourcc codes */
- if (!(format = gst_v4l2_caps_to_v4l2fourcc (v4l2src, structure))) {
+ if (!(format = gst_v4l2_structure_to_v4l2fourcc (v4l2src, structure))) {
GST_DEBUG_OBJECT (v4l2src, "can't get capture format from caps %"
GST_PTR_FORMAT, caps);
return FALSE;
}
- gst_structure_get_int (structure, "width", &w);
- gst_structure_get_int (structure, "height", &h);
+ if (!gst_structure_get_int (structure, "width", &w))
+ return FALSE;
+
+ if (!gst_structure_get_int (structure, "height", &h))
+ return FALSE;
+
framerate = gst_structure_get_value (structure, "framerate");
+ if (!framerate)
+ return FALSE;
- GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d, format %s",
- w, h, format->description);
+ fps_n = gst_value_get_fraction_numerator (framerate);
+ fps_d = gst_value_get_fraction_denominator (framerate);
- if (framerate) {
- fps_n = gst_value_get_fraction_numerator (framerate);
- fps_d = gst_value_get_fraction_denominator (framerate);
- } else {
- fps_n = 0;
- fps_d = 1;
- }
+ GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
+ "format %s", w, h, fps_n, fps_d, format->description);
- if (!gst_v4l2src_set_capture (v4l2src, format, &w, &h, &fps_n, &fps_d)) {
- GST_WARNING_OBJECT (v4l2src, "could not set_capture %dx%d, format %s",
- w, h, format->description);
+ if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, fps_n,
+ fps_d))
+ /* error already posted */
return FALSE;
- }
-
- if (fps_n) {
- gst_structure_set (structure,
- "width", G_TYPE_INT, w,
- "height", G_TYPE_INT, h,
- "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
- } else {
- gst_structure_set (structure,
- "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL);
- }
if (!gst_v4l2src_capture_init (v4l2src))
return FALSE;
@@ -863,17 +823,6 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
if (!gst_v4l2src_capture_start (v4l2src))
return FALSE;
- if (v4l2src->fps_n != fps_n || v4l2src->fps_d != fps_d) {
- GST_WARNING_OBJECT (v4l2src,
- "framerate changed after start capturing from %u/%u to %u/%u", fps_n,
- fps_d, v4l2src->fps_n, v4l2src->fps_d);
- if (fps_n) {
- gst_structure_set (structure,
- "width", G_TYPE_INT, w,
- "height", G_TYPE_INT, h,
- "framerate", GST_TYPE_FRACTION, v4l2src->fps_n, v4l2src->fps_d, NULL);
- }
- }
return TRUE;
}
@@ -920,11 +869,11 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
gint amount;
gint buffersize;
- buffersize = v4l2src->format.fmt.pix.sizeimage;
+ buffersize = v4l2src->frame_byte_size;
- do {
- *buf = gst_v4l2src_buffer_new (v4l2src, buffersize, NULL, NULL);
+ *buf = gst_v4l2src_buffer_new (v4l2src, buffersize, NULL, NULL);
+ do {
amount =
read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf),
buffersize);
@@ -935,8 +884,10 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
continue;
} else
goto read_error;
- } else
- goto short_read;
+ } else {
+ /* short reads can happen if a signal interrupts the read */
+ continue;
+ }
} while (TRUE);
return GST_FLOW_OK;
@@ -950,16 +901,6 @@ read_error:
gst_buffer_unref (*buf);
return GST_FLOW_ERROR;
}
-short_read:
- {
- GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC,
- (_("Error reading from device '%s'"),
- v4l2src->v4l2object->videodev),
- ("Error read()ing a buffer on device %s: got only %d bytes instead of expected %d.",
- v4l2src->v4l2object->videodev, amount, buffersize));
- gst_buffer_unref (*buf);
- return GST_FLOW_ERROR;
- }
}
static GstFlowReturn
@@ -972,11 +913,13 @@ gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
if (num == -1)
goto grab_failed;
- i = v4l2src->format.fmt.pix.sizeimage;
+ i = v4l2src->frame_byte_size;
/* check if this is the last buffer in the queue. If so do a memcpy to put it back asap
to avoid framedrops and deadlocks because of stupid elements */
- if (g_atomic_int_get (&v4l2src->pool->refcount) == v4l2src->breq.count) {
+ /* FIXME: we should use the userptr interface instead, will remove this
+ problem */
+ if (g_atomic_int_get (&v4l2src->pool->refcount) == v4l2src->num_buffers) {
GST_LOG_OBJECT (v4l2src, "using memcpy'd buffer");
*buf = gst_v4l2src_buffer_new (v4l2src, i, NULL, NULL);
@@ -1017,7 +960,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
GstV4l2Src *v4l2src = GST_V4L2SRC (src);
GstFlowReturn ret;
- if (v4l2src->breq.memory == V4L2_MEMORY_MMAP) {
+ if (v4l2src->use_mmap) {
ret = gst_v4l2src_get_mmap (v4l2src, buf);
} else {
ret = gst_v4l2src_get_read (v4l2src, buf);