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.
This commit is contained in:
Wim Taymans 2007-09-04 16:40:05 +00:00
parent 5248639cc1
commit b4e5796a04
4 changed files with 282 additions and 131 deletions

View file

@ -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:

View file

@ -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

View file

@ -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;
GST_DEBUG_OBJECT (v4l2object->element, "getting enumerations");
e = v4l2object->element;
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 */

View file

@ -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");