Commit 0dcf0aeb authored by Wim Taymans's avatar Wim Taymans

v4l2: Let the bufferpool own the V4l2Object

Keep track of the currently configured format and setting in the
v4l2object.
Pass the v4l2object to the bufferpool constructor so that the bufferpool can
know everything about the currently configured settings. This also allows us
to remove some awkward code.
parent f55656dc
This diff is collapsed.
......@@ -47,7 +47,7 @@ struct _GstV4l2BufferPool
{
GObject parent;
GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */
GstV4l2Object *obj; /* the v4l2 object */
gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */
enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
......@@ -83,8 +83,7 @@ const GstMetaInfo * gst_meta_v4l2_get_info (void);
#define GST_META_V4L2_ADD(buf) ((GstMetaV4l2 *)gst_buffer_add_meta(buf,gst_meta_v4l2_get_info(),NULL))
void gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool);
GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, gboolean requeuebuf, enum v4l2_buf_type type);
GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstV4l2Object *obj, gint num_buffers, gboolean requeuebuf);
GstBuffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking);
gboolean gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool *pool, GstBuffer *buf);
......
......@@ -2061,10 +2061,10 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
gboolean
gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
guint32 width, guint32 height, gboolean interlaced, guint32 * bytesperline)
guint32 width, guint32 height, gboolean interlaced)
{
gint fd = v4l2object->video_fd;
struct v4l2_format format;
struct v4l2_format *format;
enum v4l2_field field;
if (interlaced) {
......@@ -2089,22 +2089,24 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
(pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G')))
return TRUE;
memset (&format, 0x00, sizeof (struct v4l2_format));
format.type = v4l2object->type;
format = &v4l2object->format;
if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
memset (format, 0x00, sizeof (struct v4l2_format));
format->type = v4l2object->type;
if (v4l2_ioctl (fd, VIDIOC_G_FMT, format) < 0)
goto get_fmt_failed;
GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
"%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
format.fmt.pix.bytesperline);
if (format.type == v4l2object->type &&
format.fmt.pix.width == width &&
format.fmt.pix.height == height &&
format.fmt.pix.pixelformat == pixelformat &&
format.fmt.pix.field == field) {
"%" GST_FOURCC_FORMAT " stride %d", format->fmt.pix.width,
format->fmt.pix.height, GST_FOURCC_ARGS (format->fmt.pix.pixelformat),
format->fmt.pix.bytesperline);
if (format->type == v4l2object->type &&
format->fmt.pix.width == width &&
format->fmt.pix.height == height &&
format->fmt.pix.pixelformat == pixelformat &&
format->fmt.pix.field == field) {
GST_DEBUG_OBJECT (v4l2object->element, "format was good");
/* Nothing to do. We want to succeed immediately
* here because setting the same format back
......@@ -2115,35 +2117,32 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
* any caps change would require us to go to NULL
* state to close the device and set format.
*/
*bytesperline = format.fmt.pix.bytesperline;
return TRUE;
}
GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
"%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
format.type = v4l2object->type;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = pixelformat;
format.fmt.pix.field = field;
format->type = v4l2object->type;
format->fmt.pix.width = width;
format->fmt.pix.height = height;
format->fmt.pix.pixelformat = pixelformat;
format->fmt.pix.field = field;
if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
if (v4l2_ioctl (fd, VIDIOC_S_FMT, format) < 0)
goto set_fmt_failed;
GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
"%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
format.fmt.pix.bytesperline);
"%" GST_FOURCC_FORMAT " stride %d", format->fmt.pix.width,
format->fmt.pix.height, GST_FOURCC_ARGS (format->fmt.pix.pixelformat),
format->fmt.pix.bytesperline);
if (format.fmt.pix.width != width || format.fmt.pix.height != height)
if (format->fmt.pix.width != width || format->fmt.pix.height != height)
goto invalid_dimensions;
if (format.fmt.pix.pixelformat != pixelformat)
if (format->fmt.pix.pixelformat != pixelformat)
goto invalid_pixelformat;
*bytesperline = format.fmt.pix.bytesperline;
return TRUE;
/* ERRORS */
......@@ -2170,7 +2169,7 @@ invalid_dimensions:
(_("Device '%s' cannot capture at %dx%d"),
v4l2object->videodev, width, height),
("Tried to capture at %dx%d, but device returned size %dx%d",
width, height, format.fmt.pix.width, format.fmt.pix.height));
width, height, format->fmt.pix.width, format->fmt.pix.height));
return FALSE;
}
invalid_pixelformat:
......@@ -2181,7 +2180,7 @@ invalid_pixelformat:
("Tried to capture in %" GST_FOURCC_FORMAT
", but device returned format" " %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (pixelformat),
GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
GST_FOURCC_ARGS (format->fmt.pix.pixelformat)));
return FALSE;
}
}
......
......@@ -91,6 +91,9 @@ struct _GstV4l2Object {
enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
/* the current format */
struct v4l2_format format;
/* the video device's capabilities */
struct v4l2_capability vcap;
......@@ -190,7 +193,7 @@ GstCaps* gst_v4l2_object_get_all_caps (void);
GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height, gboolean interlaced, guint32 *bytesperline);
gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height, gboolean interlaced);
gboolean gst_v4l2_object_start_streaming (GstV4l2Object *v4l2object);
gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object);
......
......@@ -623,7 +623,6 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
guint fps_n, fps_d;
guint size;
GstV4l2BufferPool *newpool;
guint bytesperline;
LOG_CAPS (v4l2sink, caps);
......@@ -660,15 +659,14 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
}
if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat,
w, h, interlaced, &bytesperline))
w, h, interlaced))
goto invalid_format;
if (!(v4l2sink->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING))
goto no_streaming;
newpool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2sink),
v4l2sink->v4l2object->video_fd,
v4l2sink->num_buffers, FALSE, V4L2_BUF_TYPE_VIDEO_OUTPUT);
newpool = gst_v4l2_buffer_pool_new (v4l2sink->v4l2object,
v4l2sink->num_buffers, FALSE);
if (newpool == NULL)
goto no_pool;
......
......@@ -131,7 +131,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
if (pool_buffer)
break;
GST_WARNING_OBJECT (pool->v4l2elem, "trials=%d", trials);
GST_WARNING_OBJECT (v4l2src, "trials=%d", trials);
/* if the sync() got interrupted, we can retry */
switch (errno) {
......@@ -182,7 +182,7 @@ no_buffer_pool:
}
select_error:
{
GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, READ, (NULL),
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
("select error %d: %s (%d)", ret, g_strerror (errno), errno));
return GST_FLOW_ERROR;
}
......@@ -193,7 +193,7 @@ stopped:
}
too_many_trials:
{
GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
(_("Failed trying to get video frames from device '%s'."),
v4l2object->videodev),
(_("Failed after %d tries. device %s. system error: %s"),
......@@ -219,13 +219,12 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
{
gint fd = v4l2src->v4l2object->video_fd;
struct v4l2_streamparm stream;
guint32 bytesperline;
if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
return TRUE;
if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width,
height, interlaced, &bytesperline)) {
height, interlaced)) {
/* error already reported */
return FALSE;
}
......@@ -308,9 +307,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps * caps)
/* Map the buffers */
GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2src),
v4l2src->v4l2object->video_fd,
v4l2src->num_buffers, TRUE, V4L2_BUF_TYPE_VIDEO_CAPTURE)))
if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (v4l2src->v4l2object,
v4l2src->num_buffers, TRUE)))
goto buffer_pool_new_failed;
GST_INFO_OBJECT (v4l2src, "capturing buffers via mmap()");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment