summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2007-09-04 16:40:05 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-09-04 16:40:05 +0000
commitb4e5796a04dd2ba7c176024d9bf5d51dd3ee917b (patch)
treee20791a6c977b130eea4c38e516afccc4ece19ef
parent5248639cc180189ff3cc7acde83f8b041c1b8f78 (diff)
sys/v4l2/gstv4l2src.c: Restructure the setcaps function so that we can also compute the expected GStreamer output siz...
Original commit message from CVS: * sys/v4l2/gstv4l2src.c: (gst_v4l2_get_caps_info), (gst_v4l2src_set_caps), (gst_v4l2src_get_mmap): Restructure the setcaps function so that we can also compute the expected GStreamer output size of the video frames. Set frame_byte_size correctly so that read-based devices have a chance of working correctly. When grabbing a frame, discard frames that are not of the expected size. Some cameras don't output the right framesize for the first buffer. Try only a couple of times to get a valid frame, else error out. * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), (gst_v4l2_fill_lists), (gst_v4l2_get_input): Add some more debug info when scanning the device. * sys/v4l2/v4l2src_calls.c: (gst_v4l2_buffer_new), (gst_v4l2_buffer_pool_new), (gst_v4l2_buffer_pool_activate), (gst_v4l2src_fill_format_list), (gst_v4l2src_grab_frame), (gst_v4l2src_set_capture), (gst_v4l2src_capture_init): Add some more debug info when dequeing a frame.
-rw-r--r--ChangeLog22
-rw-r--r--sys/v4l2/gstv4l2src.c263
-rw-r--r--sys/v4l2/v4l2_calls.c58
-rw-r--r--sys/v4l2/v4l2src_calls.c70
4 files changed, 282 insertions, 131 deletions
diff --git a/ChangeLog b/ChangeLog
index 2b9a4ba7..99866787 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2007-09-04 Wim Taymans <wim.taymans@gmail.com>
+
+ * sys/v4l2/gstv4l2src.c: (gst_v4l2_get_caps_info),
+ (gst_v4l2src_set_caps), (gst_v4l2src_get_mmap):
+ Restructure the setcaps function so that we can also compute the
+ expected GStreamer output size of the video frames.
+ Set frame_byte_size correctly so that read-based devices have a chance
+ of working correctly.
+ When grabbing a frame, discard frames that are not of the expected size.
+ Some cameras don't output the right framesize for the first buffer.
+ Try only a couple of times to get a valid frame, else error out.
+
+ * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
+ (gst_v4l2_fill_lists), (gst_v4l2_get_input):
+ Add some more debug info when scanning the device.
+
+ * sys/v4l2/v4l2src_calls.c: (gst_v4l2_buffer_new),
+ (gst_v4l2_buffer_pool_new), (gst_v4l2_buffer_pool_activate),
+ (gst_v4l2src_fill_format_list), (gst_v4l2src_grab_frame),
+ (gst_v4l2src_set_capture), (gst_v4l2src_capture_init):
+ Add some more debug info when dequeing a frame.
+
2007-09-04 Stefan Kost <ensonic@users.sf.net>
* gst/wavparse/gstwavparse.c:
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 5cc184ab..d0c1ddb0 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -595,74 +595,6 @@ gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc)
return structure;
}
-static guint32
-gst_v4l2_fourcc_from_structure (GstStructure * structure)
-{
- guint32 fourcc = 0;
- const gchar *mimetype = gst_structure_get_name (structure);
-
- if (!strcmp (mimetype, "video/x-raw-yuv")) {
- gst_structure_get_fourcc (structure, "format", &fourcc);
-
- switch (fourcc) {
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
- fourcc = V4L2_PIX_FMT_YUV420;
- break;
- case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
- fourcc = V4L2_PIX_FMT_YUYV;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
- fourcc = V4L2_PIX_FMT_Y41P;
- break;
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- fourcc = V4L2_PIX_FMT_UYVY;
- break;
- case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
- fourcc = V4L2_PIX_FMT_YVU420;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
- fourcc = V4L2_PIX_FMT_YUV411P;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
- fourcc = V4L2_PIX_FMT_YUV422P;
- break;
- }
- } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
- gint depth, endianness, r_mask;
-
- gst_structure_get_int (structure, "depth", &depth);
- gst_structure_get_int (structure, "endianness", &endianness);
- gst_structure_get_int (structure, "red_mask", &r_mask);
-
- switch (depth) {
- case 8:
- fourcc = V4L2_PIX_FMT_RGB332;
- break;
- case 15:
- fourcc = (endianness == G_LITTLE_ENDIAN) ?
- V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
- break;
- case 16:
- fourcc = (endianness == G_LITTLE_ENDIAN) ?
- V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
- break;
- case 24:
- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
- break;
- case 32:
- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
- break;
- }
- } else if (strcmp (mimetype, "video/x-dv") == 0) {
- fourcc = V4L2_PIX_FMT_DV;
- } else if (strcmp (mimetype, "image/jpeg") == 0) {
- fourcc = V4L2_PIX_FMT_JPEG;
- }
-
- return fourcc;
-}
-
static struct v4l2_fmtdesc *
gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
{
@@ -689,14 +621,6 @@ gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
return NULL;
}
-static struct v4l2_fmtdesc *
-gst_v4l2_structure_to_v4l2fourcc (GstV4l2Src * v4l2src,
- GstStructure * structure)
-{
- return gst_v4l2src_get_format_from_fourcc (v4l2src,
- gst_v4l2_fourcc_from_structure (structure));
-}
-
static GstCaps *
gst_v4l2src_get_all_caps (void)
{
@@ -771,15 +695,132 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
return ret;
}
+/* collect data for the given caps
+ * @caps: given input caps
+ * @format: location for the v4l format
+ * @w/@h: location for width and height
+ * @fps_n/@fps_d: location for framerate
+ * @size: location for expected size of the frame or 0 if unknown
+ */
+static gboolean
+gst_v4l2_get_caps_info (GstV4l2Src * v4l2src, GstCaps * caps,
+ struct v4l2_fmtdesc **format, gint * w, gint * h, guint * fps_n,
+ guint * fps_d, guint * size)
+{
+ GstStructure *structure;
+ const GValue *framerate;
+ guint32 fourcc;
+ const gchar *mimetype;
+ guint outsize;
+
+ /* default unknown values */
+ fourcc = 0;
+ outsize = 0;
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ 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;
+
+ *fps_n = gst_value_get_fraction_numerator (framerate);
+ *fps_d = gst_value_get_fraction_denominator (framerate);
+
+ mimetype = gst_structure_get_name (structure);
+
+ if (!strcmp (mimetype, "video/x-raw-yuv")) {
+ gst_structure_get_fourcc (structure, "format", &fourcc);
+
+ switch (fourcc) {
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
+ fourcc = V4L2_PIX_FMT_YUV420;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+ break;
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+ fourcc = V4L2_PIX_FMT_YUYV;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
+ fourcc = V4L2_PIX_FMT_Y41P;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+ fourcc = V4L2_PIX_FMT_UYVY;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+ fourcc = V4L2_PIX_FMT_YVU420;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
+ fourcc = V4L2_PIX_FMT_YUV411P;
+ outsize = GST_ROUND_UP_4 (*w) * *h;
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
+ fourcc = V4L2_PIX_FMT_YUV422P;
+ outsize = GST_ROUND_UP_4 (*w) * *h;
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
+ break;
+ }
+ } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
+ gint depth, endianness, r_mask;
+
+ gst_structure_get_int (structure, "depth", &depth);
+ gst_structure_get_int (structure, "endianness", &endianness);
+ gst_structure_get_int (structure, "red_mask", &r_mask);
+
+ switch (depth) {
+ case 8:
+ fourcc = V4L2_PIX_FMT_RGB332;
+ break;
+ case 15:
+ fourcc = (endianness == G_LITTLE_ENDIAN) ?
+ V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
+ break;
+ case 16:
+ fourcc = (endianness == G_LITTLE_ENDIAN) ?
+ V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
+ break;
+ case 24:
+ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
+ break;
+ case 32:
+ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
+ break;
+ }
+ } else if (strcmp (mimetype, "video/x-dv") == 0) {
+ fourcc = V4L2_PIX_FMT_DV;
+ } else if (strcmp (mimetype, "image/jpeg") == 0) {
+ fourcc = V4L2_PIX_FMT_JPEG;
+ }
+
+ if (fourcc == 0)
+ return FALSE;
+
+ *format = gst_v4l2src_get_format_from_fourcc (v4l2src, fourcc);
+ *size = outsize;
+
+ return TRUE;
+}
+
static gboolean
gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
{
GstV4l2Src *v4l2src;
gint w = 0, h = 0;
- GstStructure *structure;
struct v4l2_fmtdesc *format;
- const GValue *framerate;
guint fps_n, fps_d;
+ guint size;
v4l2src = GST_V4L2SRC (src);
@@ -796,28 +837,14 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
return FALSE;
}
- structure = gst_caps_get_structure (caps, 0);
-
/* we want our own v4l2 type of fourcc codes */
- if (!(format = gst_v4l2_structure_to_v4l2fourcc (v4l2src, structure))) {
- GST_DEBUG_OBJECT (v4l2src, "can't get capture format from caps %"
- GST_PTR_FORMAT, caps);
+ if (!gst_v4l2_get_caps_info (v4l2src, caps, &format, &w, &h, &fps_n, &fps_d,
+ &size)) {
+ GST_DEBUG_OBJECT (v4l2src,
+ "can't get capture format from caps %" GST_PTR_FORMAT, caps);
return FALSE;
}
- 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;
-
- fps_n = gst_value_get_fraction_numerator (framerate);
- fps_d = gst_value_get_fraction_denominator (framerate);
-
GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
"format %s", w, h, fps_n, fps_d, format->description);
@@ -832,6 +859,9 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
if (!gst_v4l2src_capture_start (v4l2src))
return FALSE;
+ /* now store the expected output size */
+ v4l2src->frame_byte_size = size;
+
return TRUE;
}
@@ -945,7 +975,46 @@ read_error:
static GstFlowReturn
gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
{
- return gst_v4l2src_grab_frame (v4l2src, buf);
+ GstBuffer *temp;
+ GstFlowReturn ret;
+ guint size;
+ guint count;
+
+ count = 0;
+
+again:
+ ret = gst_v4l2src_grab_frame (v4l2src, &temp);
+ if (ret != GST_FLOW_OK)
+ goto done;
+
+ if (v4l2src->frame_byte_size > 0) {
+ size = GST_BUFFER_SIZE (temp);
+
+ /* if size does not match what we expected, try again */
+ if (size != v4l2src->frame_byte_size) {
+ GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ,
+ (_("Got unexpected frame size of %u instead of %u."),
+ size, v4l2src->frame_byte_size), (NULL));
+ gst_buffer_unref (temp);
+ if (count++ > 50)
+ goto size_error;
+
+ goto again;
+ }
+ }
+
+ *buf = temp;
+done:
+ return ret;
+
+ /* ERRORS */
+size_error:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Error read()ing %d bytes on device '%s'."),
+ v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL));
+ return GST_FLOW_ERROR;
+ }
}
static GstFlowReturn
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index 0721a2ea..6233d010 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -51,7 +51,11 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
gboolean
gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
{
- GST_DEBUG_OBJECT (v4l2object->element, "getting capabilities");
+ GstElement *e;
+
+ e = v4l2object->element;
+
+ GST_DEBUG_OBJECT (e, "getting capabilities");
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
@@ -59,6 +63,12 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
if (ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
goto cap_failed;
+ GST_LOG_OBJECT (e, "driver: '%s'", v4l2object->vcap.driver);
+ GST_LOG_OBJECT (e, "card: '%s'", v4l2object->vcap.card);
+ GST_LOG_OBJECT (e, "bus_info: '%s'", v4l2object->vcap.bus_info);
+ GST_LOG_OBJECT (e, "version: %08x", v4l2object->vcap.version);
+ GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->vcap.capabilities);
+
return TRUE;
/* ERRORS */
@@ -82,11 +92,14 @@ static gboolean
gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
{
gint n;
+ GstElement *e;
+
+ e = v4l2object->element;
- GST_DEBUG_OBJECT (v4l2object->element, "getting enumerations");
+ GST_DEBUG_OBJECT (e, "getting enumerations");
GST_V4L2_CHECK_OPEN (v4l2object);
- GST_DEBUG_OBJECT (v4l2object->element, " channels");
+ GST_DEBUG_OBJECT (e, " channels");
/* and now, the channels */
for (n = 0;; n++) {
struct v4l2_input input;
@@ -98,7 +111,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
if (errno == EINVAL)
break; /* end of enumeration */
else {
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed to query attributes of input %d in device %s"),
n, v4l2object->videodev),
("Failed to get %d in input enumeration for %s. (%d - %s)",
@@ -107,13 +120,19 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
}
}
- GST_DEBUG_OBJECT (v4l2object->element, " '%s'", input.name);
+ GST_LOG_OBJECT (e, " index: %d", input.index);
+ GST_LOG_OBJECT (e, " name: '%s'", input.name);
+ GST_LOG_OBJECT (e, " type: %08x", input.type);
+ GST_LOG_OBJECT (e, " audioset: %08x", input.audioset);
+ GST_LOG_OBJECT (e, " std: %016x", input.std);
+ GST_LOG_OBJECT (e, " status: %08x", input.status);
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
channel = GST_TUNER_CHANNEL (v4l2channel);
channel->label = g_strdup ((const gchar *) input.name);
channel->flags = GST_TUNER_CHANNEL_INPUT;
v4l2channel->index = n;
+
if (input.type == V4L2_INPUT_TYPE_TUNER) {
struct v4l2_tuner vtun;
@@ -122,12 +141,13 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
vtun.index = input.tuner;
if (ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed to get setting of tuner %d on device '%s'."),
input.tuner, v4l2object->videodev), GST_ERROR_SYSTEM);
g_object_unref (G_OBJECT (channel));
return FALSE;
}
+
channel->freq_multiplicator =
62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) ? 1 : 1000);
channel->min_frequency = vtun.rangelow * channel->freq_multiplicator;
@@ -147,7 +167,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
g_list_append (v4l2object->channels, (gpointer) channel);
}
- GST_DEBUG_OBJECT (v4l2object->element, " norms");
+ GST_DEBUG_OBJECT (e, " norms");
/* norms... */
for (n = 0;; n++) {
struct v4l2_standard standard;
@@ -158,11 +178,12 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
standard.frameperiod.numerator = 1;
standard.frameperiod.denominator = 0;
standard.index = n;
+
if (ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
if (errno == EINVAL)
break; /* end of enumeration */
else {
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed to query norm on device '%s'."),
v4l2object->videodev),
("Failed to get attributes for norm %d on devide '%s'. (%d - %s)",
@@ -171,7 +192,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
}
}
- GST_DEBUG_OBJECT (v4l2object->element, " '%s', fps: %d / %d",
+ GST_DEBUG_OBJECT (e, " '%s', fps: %d / %d",
standard.name, standard.frameperiod.denominator,
standard.frameperiod.numerator);
@@ -185,7 +206,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
v4l2object->norms = g_list_append (v4l2object->norms, (gpointer) norm);
}
- GST_DEBUG_OBJECT (v4l2object->element, " controls+menus");
+ GST_DEBUG_OBJECT (e, " controls+menus");
/* and lastly, controls+menus (if appropriate) */
for (n = V4L2_CID_BASE;; n++) {
struct v4l2_queryctrl control;
@@ -194,7 +215,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
/* when we reached the last official CID, continue with private CIDs */
if (n == V4L2_CID_LASTP1) {
- GST_DEBUG_OBJECT (v4l2object->element, "checking private CIDs");
+ GST_DEBUG_OBJECT (e, "checking private CIDs");
n = V4L2_CID_PRIVATE_BASE;
/* FIXME: We are still not handling private controls. We need a new GstInterface
to export those controls */
@@ -210,7 +231,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
else
break;
} else {
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed getting controls attributes on device '%s.'"),
v4l2object->videodev),
("Failed querying control %d on device '%s'. (%d - %s)",
@@ -253,7 +274,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
/* FIXME: We should implement GstMixer interface */
/* fall through */
default:
- GST_DEBUG_OBJECT (v4l2object->element,
+ GST_DEBUG_OBJECT (e,
"ControlID %s (%x) unhandled, FIXME", control.name, n);
control.id++;
break;
@@ -261,8 +282,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
if (n != control.id)
continue;
- GST_DEBUG_OBJECT (v4l2object->element,
- "Adding ControlID %s (%x)", control.name, n);
+ GST_DEBUG_OBJECT (e, "Adding ControlID %s (%x)", control.name, n);
v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
channel->label = g_strdup ((const gchar *) control.name);
@@ -281,7 +301,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
if (errno == EINVAL)
break; /* end of enumeration */
else {
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed getting controls attributes on device '%s'."),
v4l2object->videodev),
("Failed to get %d in menu enumeration for %s. (%d - %s)",
@@ -310,7 +330,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
/* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
unset (0), but can't be queried */
- GST_DEBUG_OBJECT (v4l2object->element,
+ GST_DEBUG_OBJECT (e,
"Control with non supported type %s (%x), type=%d",
control.name, n, control.type);
channel->min_value = channel->max_value = 0;
@@ -320,7 +340,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
v4l2object->colors = g_list_append (v4l2object->colors, (gpointer) channel);
}
- GST_DEBUG_OBJECT (v4l2object->element, "done");
+ GST_DEBUG_OBJECT (e, "done");
return TRUE;
}
@@ -720,6 +740,8 @@ gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
*input = n;
+ GST_DEBUG_OBJECT (v4l2object->element, "input: %d", n);
+
return TRUE;
/* ERRORS */
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
index 0006f0e0..5483e6da 100644
--- a/sys/v4l2/v4l2src_calls.c
+++ b/sys/v4l2/v4l2src_calls.c
@@ -138,12 +138,16 @@ static GstV4l2Buffer *
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
{
GstV4l2Buffer *ret;
+ guint8 *data;
ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER);
+ GST_LOG ("creating buffer %u, %p in pool %p", index, ret, pool);
+
ret->pool = pool;
gst_mini_object_ref (GST_MINI_OBJECT (pool));
memset (&ret->vbuffer, 0x00, sizeof (ret->vbuffer));
+
ret->vbuffer.index = index;
ret->vbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret->vbuffer.memory = V4L2_MEMORY_MMAP;
@@ -151,18 +155,34 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0)
goto querybuf_failed;
- GST_BUFFER_DATA (ret) = mmap (0, ret->vbuffer.length,
+ GST_LOG (" index: %u", ret->vbuffer.index);
+ GST_LOG (" type: %d", ret->vbuffer.type);
+ GST_LOG (" bytesused: %u", ret->vbuffer.bytesused);
+ GST_LOG (" flags: %08x", ret->vbuffer.flags);
+ GST_LOG (" field: %d", ret->vbuffer.field);
+ GST_LOG (" memory: %d", ret->vbuffer.memory);
+ if (ret->vbuffer.memory == V4L2_MEMORY_MMAP)
+ GST_LOG (" MMAP offset: %u", ret->vbuffer.m.offset);
+ GST_LOG (" length: %u", ret->vbuffer.length);
+ GST_LOG (" input: %u", ret->vbuffer.input);
+
+ data = mmap (0, ret->vbuffer.length,
PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
ret->vbuffer.m.offset);
- if (GST_BUFFER_DATA (ret) == MAP_FAILED)
+ if (data == MAP_FAILED)
goto mmap_failed;
+ GST_BUFFER_DATA (ret) = data;
+ GST_BUFFER_SIZE (ret) = ret->vbuffer.length;
+
GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
+
gst_buffer_set_caps (GST_BUFFER (ret), caps);
return ret;
+ /* ERRORS */
querybuf_failed:
{
gint errnosave = errno;
@@ -266,6 +286,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Src * v4l2src, gint fd, gint num_buffers,
return pool;
+ /* ERRORS */
dup_failed:
{
gint errnosave = errno;
@@ -296,18 +317,22 @@ gst_v4l2_buffer_pool_activate (GstV4l2BufferPool * pool, GstV4l2Src * v4l2src)
g_mutex_lock (pool->lock);
for (n = 0; n < pool->buffer_count; n++) {
- struct v4l2_buffer *buf = &pool->buffers[n]->vbuffer;
+ struct v4l2_buffer *buf;
+
+ buf = &pool->buffers[n]->vbuffer;
+
+ GST_LOG ("enqueue pool buffer %d", n);
if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
goto queue_failed;
}
-
pool->running = TRUE;
g_mutex_unlock (pool->lock);
return TRUE;
+ /* ERRORS */
queue_failed:
{
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
@@ -367,19 +392,27 @@ gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
format->index = n;
format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
- if (errno == EINVAL) {
+ if (errno == EINVAL)
break; /* end of enumeration */
- } else
+ else
goto failed;
}
- GST_DEBUG_OBJECT (v4l2src, "got format %" GST_FOURCC_FORMAT,
+
+ GST_LOG_OBJECT (v4l2src, "index: %u", format->index);
+ GST_LOG_OBJECT (v4l2src, "type: %d", format->type);
+ GST_LOG_OBJECT (v4l2src, "flags: %08x", format->flags);
+ GST_LOG_OBJECT (v4l2src, "description: '%s'", format->description);
+ GST_LOG_OBJECT (v4l2src, "pixelformat: %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (format->pixelformat));
v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
}
v4l2src->formats = g_slist_reverse (v4l2src->formats);
+
GST_DEBUG_OBJECT (v4l2src, "got %d format(s)", n);
+
return TRUE;
/* ERRORS */
@@ -803,8 +836,9 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
*buf = pool_buffer;
}
- GST_LOG_OBJECT (v4l2src, "grabbed frame %d (ix=%d), pool-ct=%d",
- buffer.sequence, buffer.index, v4l2src->pool->num_live_buffers);
+ GST_LOG_OBJECT (v4l2src, "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d",
+ buffer.sequence, buffer.index, buffer.flags,
+ v4l2src->pool->num_live_buffers);
return GST_FLOW_OK;
@@ -910,11 +944,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
if (stream.parm.capture.timeperframe.numerator != fps_d
|| stream.parm.capture.timeperframe.denominator != fps_n)
goto invalid_framerate;
-
}
}
-
return TRUE;
/* ERRORS */
@@ -986,24 +1018,30 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps * caps)
GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
- breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- breq.count = v4l2src->num_buffers;
+ GST_DEBUG_OBJECT (v4l2src, "STREAMING, requesting %d MMAP CAPTURE buffers",
+ v4l2src->num_buffers);
+
+ breq.count = v4l2src->num_buffers;
+ breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
breq.memory = V4L2_MEMORY_MMAP;
+
if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
goto reqbufs_failed;
+ GST_LOG_OBJECT (v4l2src, " count: %u", breq.count);
+ GST_LOG_OBJECT (v4l2src, " type: %d", breq.type);
+ GST_LOG_OBJECT (v4l2src, " memory: %d", breq.memory);
+
if (breq.count < GST_V4L2_MIN_BUFFERS)
goto no_buffers;
if (v4l2src->num_buffers != breq.count) {
+ GST_WARNING_OBJECT (v4l2src, "using %u buffers instead", breq.count);
v4l2src->num_buffers = breq.count;
g_object_notify (G_OBJECT (v4l2src), "queue-size");
}
- GST_INFO_OBJECT (v4l2src, "Got %d buffers of size %d kB",
- breq.count, v4l2src->frame_byte_size / 1024);
-
/* Map the buffers */
GST_LOG_OBJECT (v4l2src, "initiating buffer pool");