static GstV4l2MemoryGroup *
gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index)
{
- gint video_fd = allocator->video_fd;
+ GstV4l2Object *obj = allocator->obj;
guint32 memory = allocator->memory;
- struct v4l2_format *format = &allocator->format;
+ struct v4l2_format *format = &obj->format;
GstV4l2MemoryGroup *group;
gsize img_size, buf_size;
group->n_mem = 1;
}
- if (v4l2_ioctl (video_fd, VIDIOC_QUERYBUF, &group->buffer) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_QUERYBUF, &group->buffer) < 0)
goto querybuf_failed;
if (group->buffer.index != index) {
/* Check that provided size matches the format we have negotiation. Failing
* there usually means a driver of libv4l bug. */
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
gint i;
for (i = 0; i < group->n_mem; i++) {
- img_size = allocator->format.fmt.pix_mp.plane_fmt[i].sizeimage;
+ img_size = obj->format.fmt.pix_mp.plane_fmt[i].sizeimage;
buf_size = group->planes[i].length;
if (buf_size < img_size)
goto buffer_too_short;
}
} else {
- img_size = allocator->format.fmt.pix.sizeimage;
+ img_size = obj->format.fmt.pix.sizeimage;
buf_size = group->buffer.length;
if (buf_size < img_size)
goto buffer_too_short;
gst_v4l2_allocator_free (GstAllocator * gallocator, GstMemory * gmem)
{
GstV4l2Allocator *allocator = (GstV4l2Allocator *) gallocator;
+ GstV4l2Object *obj = allocator->obj;
GstV4l2Memory *mem = (GstV4l2Memory *) gmem;
GstV4l2MemoryGroup *group = mem->group;
if (allocator->memory == V4L2_MEMORY_MMAP) {
if (mem->data)
- v4l2_munmap (mem->data, group->planes[mem->plane].length);
+ obj->munmap (mem->data, group->planes[mem->plane].length);
}
/* This apply for both mmap with expbuf, and dmabuf imported memory */
GST_LOG_OBJECT (obj, "called");
- v4l2_close (allocator->video_fd);
gst_atomic_queue_unref (allocator->free_queue);
G_OBJECT_CLASS (parent_class)->finalize (obj);
gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory,
guint32 breq_flag, guint32 bcreate_flag)
{
+ GstV4l2Object *obj = allocator->obj;
struct v4l2_requestbuffers breq = { 0 };
guint32 flags = 0;
- breq.type = allocator->type;
+ breq.type = obj->type;
breq.count = 0;
breq.memory = memory;
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) == 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) == 0) {
struct v4l2_create_buffers bcreate = { 0 };
flags |= breq_flag;
bcreate.memory = memory;
- bcreate.format = allocator->format;
+ bcreate.format = obj->format;
- if ((v4l2_ioctl (allocator->video_fd, VIDIOC_CREATE_BUFS, &bcreate) == 0))
+ if ((obj->ioctl (obj->video_fd, VIDIOC_CREATE_BUFS, &bcreate) == 0))
flags |= bcreate_flag;
}
static GstV4l2MemoryGroup *
gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator)
{
+ GstV4l2Object *obj = allocator->obj;
struct v4l2_create_buffers bcreate = { 0 };
GstV4l2MemoryGroup *group = NULL;
goto done;
bcreate.memory = allocator->memory;
- bcreate.format = allocator->format;
+ bcreate.format = obj->format;
bcreate.count = 1;
if (!allocator->can_allocate)
goto done;
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_CREATE_BUFS, &bcreate) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_CREATE_BUFS, &bcreate) < 0)
goto create_bufs_failed;
if (allocator->groups[bcreate.index] != NULL)
gst_v4l2_allocator_reset_size (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup * group)
{
+ GstV4l2Object *obj = allocator->obj;
gsize size;
gboolean imported = FALSE;
break;
}
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
gint i;
for (i = 0; i < group->n_mem; i++) {
- size = allocator->format.fmt.pix_mp.plane_fmt[i].sizeimage;
+ size = obj->format.fmt.pix_mp.plane_fmt[i].sizeimage;
if (imported)
group->mem[i]->maxsize = size;
}
} else {
- size = allocator->format.fmt.pix.sizeimage;
+ size = obj->format.fmt.pix.sizeimage;
if (imported)
group->mem[0]->maxsize = size;
GstV4l2Allocator *
-gst_v4l2_allocator_new (GstObject * parent, gint video_fd,
- struct v4l2_format *format)
+gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object)
{
GstV4l2Allocator *allocator;
guint32 flags = 0;
g_free (name);
/* Save everything */
- allocator->video_fd = v4l2_dup (video_fd);
- allocator->type = format->type;
- allocator->format = *format;
+ allocator->obj = v4l2object;
flags |= GST_V4L2_ALLOCATOR_PROBE (allocator, MMAP);
flags |= GST_V4L2_ALLOCATOR_PROBE (allocator, USERPTR);
gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count,
guint32 memory)
{
- struct v4l2_requestbuffers breq = { count, allocator->type, memory };
+ GstV4l2Object *obj = allocator->obj;
+ struct v4l2_requestbuffers breq = { count, obj->type, memory };
gboolean can_allocate;
gint i;
if (g_atomic_int_get (&allocator->active))
goto already_active;
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0)
goto reqbufs_failed;
if (breq.count < 1)
GstV4l2Return
gst_v4l2_allocator_stop (GstV4l2Allocator * allocator)
{
- struct v4l2_requestbuffers breq = { 0, allocator->type, allocator->memory };
+ GstV4l2Object *obj = allocator->obj;
+ struct v4l2_requestbuffers breq = { 0, obj->type, allocator->memory };
gint i = 0;
GstV4l2Return ret = GST_V4L2_OK;
}
/* Not all drivers support rebufs(0), so warn only */
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0)
GST_WARNING_OBJECT (allocator,
"error releasing buffers buffers: %s", g_strerror (errno));
GstV4l2MemoryGroup *
gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2MemoryGroup *group;
gint i;
for (i = 0; i < group->n_mem; i++) {
if (group->mem[i] == NULL) {
gpointer data;
- data = v4l2_mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE,
- MAP_SHARED, allocator->video_fd, group->planes[i].m.mem_offset);
+ data = obj->mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, obj->video_fd, group->planes[i].m.mem_offset);
if (data == MAP_FAILED)
goto mmap_failed;
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
GstAllocator * dmabuf_allocator)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2MemoryGroup *group;
gint i;
if (group->mem[i] == NULL) {
struct v4l2_exportbuffer expbuf = { 0 };
- expbuf.type = allocator->type;
+ expbuf.type = obj->type;
expbuf.index = group->buffer.index;
expbuf.plane = i;
expbuf.flags = O_CLOEXEC | O_RDWR;
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_EXPBUF, &expbuf) < 0)
goto expbuf_failed;
GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d",
gst_v4l2_allocator_clear_dmabufin (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup * group)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2Memory *mem;
gint i;
group->planes[i].data_offset = 0;
}
- if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
group->buffer.bytesused = 0;
group->buffer.length = 0;
group->buffer.m.fd = -1;
gst_v4l2_allocator_clear_userptr (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup * group)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2Memory *mem;
gint i;
group->planes[i].m.userptr = 0;
}
- if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
group->buffer.bytesused = 0;
group->buffer.length = 0;
group->buffer.m.userptr = 0;
gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup * group, gint n_mem, GstMemory ** dma_mem)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2Memory *mem;
gint i;
}
/* Copy into buffer structure if not using planes */
- if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
group->buffer.bytesused = group->planes[0].bytesused;
group->buffer.length = group->planes[0].length;
group->buffer.m.fd = group->planes[0].m.userptr;
GstV4l2MemoryGroup * group, gsize img_size, int n_planes,
gpointer * data, gsize * size)
{
+ GstV4l2Object *obj = allocator->obj;
GstV4l2Memory *mem;
gint i;
g_return_val_if_fail (allocator->memory == V4L2_MEMORY_USERPTR, FALSE);
/* TODO Support passing N plane from 1 memory to MPLANE v4l2 format */
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type) && n_planes != group->n_mem)
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type) && n_planes != group->n_mem)
goto n_mem_missmatch;
for (i = 0; i < group->n_mem; i++) {
gsize maxsize, psize;
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
- struct v4l2_pix_format_mplane *pix = &allocator->format.fmt.pix_mp;
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
+ struct v4l2_pix_format_mplane *pix = &obj->format.fmt.pix_mp;
maxsize = pix->plane_fmt[i].sizeimage;
psize = size[i];
} else {
- maxsize = allocator->format.fmt.pix.sizeimage;
+ maxsize = obj->format.fmt.pix.sizeimage;
psize = img_size;
}
}
/* Copy into buffer structure if not using planes */
- if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
group->buffer.bytesused = group->planes[0].bytesused;
group->buffer.length = group->planes[0].length;
group->buffer.m.userptr = group->planes[0].m.userptr;
gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup * group)
{
+ GstV4l2Object *obj = allocator->obj;
gboolean ret = TRUE;
gint i;
g_return_val_if_fail (g_atomic_int_get (&allocator->active), FALSE);
/* update sizes */
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
for (i = 0; i < group->n_mem; i++)
group->planes[i].bytesused =
gst_memory_get_sizes (group->mem[i], NULL, NULL);
for (i = 0; i < group->n_mem; i++)
gst_memory_ref (group->mem[i]);
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_QBUF, &group->buffer) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_QBUF, &group->buffer) < 0) {
GST_ERROR_OBJECT (allocator, "failed queueing buffer %i: %s",
group->buffer.index, g_strerror (errno));
gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator,
GstV4l2MemoryGroup ** group_out)
{
+ GstV4l2Object *obj = allocator->obj;
struct v4l2_buffer buffer = { 0 };
struct v4l2_plane planes[VIDEO_MAX_PLANES] = { {0} };
gint i;
g_return_val_if_fail (g_atomic_int_get (&allocator->active), GST_FLOW_ERROR);
- buffer.type = allocator->type;
+ buffer.type = obj->type;
buffer.memory = allocator->memory;
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
- buffer.length = allocator->format.fmt.pix_mp.num_planes;
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
+ buffer.length = obj->format.fmt.pix_mp.num_planes;
buffer.m.planes = planes;
}
- if (v4l2_ioctl (allocator->video_fd, VIDIOC_DQBUF, &buffer) < 0)
+ if (obj->ioctl (obj->video_fd, VIDIOC_DQBUF, &buffer) < 0)
goto error;
group = allocator->groups[buffer.index];
UNSET_QUEUED (group->buffer);
}
- if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
group->buffer.m.planes = group->planes;
memcpy (group->planes, buffer.m.planes, sizeof (planes));
} else {
}
/* And update memory size */
- if (V4L2_TYPE_IS_OUTPUT (allocator->type)) {
+ if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
gst_v4l2_allocator_reset_size (allocator, group);
} else {
/* for capture, simply read the size */
typedef struct _GstV4l2Memory GstV4l2Memory;
typedef enum _GstV4l2Capabilities GstV4l2Capabilities;
typedef enum _GstV4l2Return GstV4l2Return;
+typedef struct _GstV4l2Object GstV4l2Object;
enum _GstV4l2AllocatorFlags
{
struct _GstV4l2Allocator
{
GstAllocator parent;
- gint video_fd;
+ GstV4l2Object *obj;
guint32 count;
- guint32 type;
guint32 memory;
- struct v4l2_format format;
gboolean can_allocate;
gboolean active;
guint gst_v4l2_allocator_get_size (GstV4l2Allocator * allocator);
-GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, gint video_fd,
- struct v4l2_format * format);
+GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, GstV4l2Object * obj);
guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator,
guint32 count, guint32 memory);
case GST_V4L2_IO_DMABUF:
case GST_V4L2_IO_DMABUF_IMPORT:
if (!pool->streaming) {
- if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
+ if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
goto streamon_failed;
pool->streaming = TRUE;
case GST_V4L2_IO_DMABUF:
case GST_V4L2_IO_DMABUF_IMPORT:
if (pool->streaming) {
- if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
+ if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
errno, g_strerror (errno));
* queue to be initialized now. We only do this if we have a streaming
* driver. */
if (obj->device_caps & V4L2_CAP_STREAMING)
- v4l2_read (obj->video_fd, NULL, 0);
+ obj->read (obj->video_fd, NULL, 0);
#endif
break;
case GST_V4L2_IO_DMABUF:
pool->obj = obj;
pool->can_poll_device = TRUE;
- pool->vallocator =
- gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format);
+ pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj);
if (pool->vallocator == NULL)
goto allocator_failed;
if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
goto poll_error;
- amount = v4l2_read (obj->video_fd, map.data, toread);
+ amount = obj->read (obj->video_fd, map.data, toread);
if (amount == toread) {
break;
if (control.value < 0)
continue;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
GST_WARNING_OBJECT (ctx->self, "Failed to set H264 profile: '%s'",
g_strerror (errno));
break;
if (control.value < 0)
continue;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
GST_WARNING_OBJECT (ctx->self, "Failed to set H264 level: '%s'",
g_strerror (errno));
break;
control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed;
ctx.profile = v4l2_profile_to_string (control.value);
control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed;
ctx.level = v4l2_level_to_string (control.value);
#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
#ifdef HAVE_GUDEV
#include <gudev/gudev.h>
v4l2object->no_initial_format = FALSE;
+ /* We now disable libv4l2 by default, but have an env to enable it. */
+#ifdef HAVE_LIBV4L2
+ if (g_getenv ("GST_V4L2_USE_LIBV4L2")) {
+ v4l2object->fd_open = v4l2_fd_open;
+ v4l2object->close = v4l2_close;
+ v4l2object->dup = v4l2_dup;
+ v4l2object->ioctl = v4l2_ioctl;
+ v4l2object->read = v4l2_read;
+ v4l2object->mmap = v4l2_mmap;
+ v4l2object->munmap = v4l2_munmap;
+ } else
+#endif
+ {
+ v4l2object->fd_open = NULL;
+ v4l2object->close = close;
+ v4l2object->dup = dup;
+ v4l2object->ioctl = ioctl;
+ v4l2object->read = read;
+ v4l2object->mmap = mmap;
+ v4l2object->munmap = munmap;
+ }
+
return v4l2object;
}
else
control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) {
GST_DEBUG_OBJECT (v4l2object->element,
"driver requires a minimum of %d buffers", control.value);
v4l2object->min_buffers = control.value;
format->index = n;
format->type = type;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
if (errno == EINVAL) {
g_free (format);
break; /* end of enumeration */
int r;
memcpy (&fmt, try_fmt, sizeof (fmt));
- r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ r = v4l2object->ioctl (fd, VIDIOC_TRY_FMT, &fmt);
if (r < 0 && errno == ENOTTY) {
/* The driver might not implement TRY_FMT, in which case we will try
goto error;
memcpy (&fmt, try_fmt, sizeof (fmt));
- r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ r = v4l2object->ioctl (fd, VIDIOC_S_FMT, &fmt);
}
memcpy (try_fmt, &fmt, sizeof (fmt));
/* keep in mind that v4l2 gives us frame intervals (durations); we invert the
* fraction to get framerate */
- if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
goto enum_frameintervals_failed;
if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
gst_value_list_append_value (&rates, &rate);
ival.index++;
- } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
+ } while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
} else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
GValue min = { 0, };
GValue step = { 0, };
"Enumerating frame sizes for %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (pixelformat));
- if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
goto enum_framesizes_failed;
if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
}
size.index++;
- } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
+ } while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
GST_DEBUG_OBJECT (v4l2object->element,
"done iterating discrete frame sizes");
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
}
if (try_only) {
- if (v4l2_ioctl (fd, VIDIOC_TRY_FMT, &format) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_TRY_FMT, &format) < 0)
goto try_fmt_failed;
} else {
- if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_S_FMT, &format) < 0)
goto set_fmt_failed;
}
ctl.id = V4L2_CID_ALPHA_COMPONENT;
ctl.value = 0xff;
- if (v4l2_ioctl (fd, VIDIOC_S_CTRL, &ctl) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_S_CTRL, &ctl) < 0)
GST_WARNING_OBJECT (v4l2object->element,
"Failed to set alpha component value");
}
memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
streamparm.type = v4l2object->type;
- if (v4l2_ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
goto get_parm_failed;
if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
streamparm.parm.capture.timeperframe.denominator = fps_n;
/* some cheap USB cam's won't accept any change */
- if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
goto set_parm_failed;
if (streamparm.parm.capture.timeperframe.numerator > 0 &&
streamparm.parm.output.timeperframe.numerator = fps_d;
streamparm.parm.output.timeperframe.denominator = fps_n;
- if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
+ if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
goto set_parm_failed;
if (streamparm.parm.output.timeperframe.numerator > 0 &&
memset (&fmt, 0x00, sizeof (struct v4l2_format));
fmt.type = v4l2object->type;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0)
goto get_fmt_failed;
fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object,
memset (&sel, 0, sizeof (struct v4l2_selection));
sel.type = v4l2object->type;
sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_SELECTION, &sel) >= 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_SELECTION, &sel) >= 0) {
r = &sel.r;
} else {
/* For ancient kernels, fall back to G_CROP */
memset (&crop, 0, sizeof (struct v4l2_crop));
crop.type = v4l2object->type;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0)
r = &crop.c;
}
if (r) {
"Desired cropping left %u, top %u, size %ux%u", crop.c.left, crop.c.top,
crop.c.width, crop.c.height);
- if (v4l2_ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) {
GST_WARNING_OBJECT (obj->element, "VIDIOC_S_CROP failed");
return FALSE;
}
- if (v4l2_ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (obj->element, "VIDIOC_G_CROP failed");
return FALSE;
}
memset (&cropcap, 0, sizeof (cropcap));
cropcap.type = v4l2object->type;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
if (errno != ENOTTY)
GST_WARNING_OBJECT (v4l2object->element,
"Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s",
#ifndef __GST_V4L2_OBJECT_H__
#define __GST_V4L2_OBJECT_H__
+#include "ext/videodev2.h"
#ifdef HAVE_LIBV4L2
# include <libv4l2.h>
-#else
-# include "ext/videodev2.h"
-# include <sys/ioctl.h>
-# include <sys/mman.h>
-# include <unistd.h>
-# define v4l2_fd_open(fd, flags) (fd)
-# define v4l2_close close
-# define v4l2_dup dup
-# define v4l2_ioctl ioctl
-# define v4l2_read read
-# define v4l2_mmap mmap
-# define v4l2_munmap munmap
#endif
-#include "ext/videodev2.h"
#include "v4l2-utils.h"
#include <gst/gst.h>
GstV4l2SetInOutFunction set_in_out_func;
GstV4l2UpdateFpsFunction update_fps_func;
+ /* syscalls */
+ int (*fd_open) (int fd, int v4l2_flags);
+ int (*close) (int fd);
+ int (*dup) (int fd);
+ int (*ioctl) (int fd, unsigned long int request, ...);
+ ssize_t (*read) (int fd, void *buffer, size_t n);
+ void * (*mmap) (void *start, size_t length, int prot, int flags,
+ int fd, int64_t offset);
+ int (*munmap) (void *_start, size_t length);
+
/* Quirks */
/* Skips interlacing probes */
gboolean never_interlaced;
memset (&vc, 0, sizeof (vc));
- res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc);
+ res = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc);
if (res < 0)
goto caps_failed;
memset (&vtun, 0, sizeof (vtun));
vtun.index = 0;
- res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun);
+ res = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun);
if (res < 0)
goto tuner_failed;
if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
- gint fd = v4l2sink->v4l2object->video_fd;
+ GstV4l2Object *obj = v4l2sink->v4l2object;
struct v4l2_format format;
memset (&format, 0x00, sizeof (struct v4l2_format));
- if (v4l2sink->v4l2object->device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+ if (obj->device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
else
format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_G_FMT, &format) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed");
return;
}
if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET)
format.fmt.win.w.height = v4l2sink->overlay.height;
- if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_S_FMT, &format) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_FMT failed");
return;
}
if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
- gint fd = v4l2sink->v4l2object->video_fd;
+ GstV4l2Object *obj = v4l2sink->v4l2object;
struct v4l2_crop crop;
memset (&crop, 0x00, sizeof (struct v4l2_crop));
crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed");
return;
}
if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET)
crop.c.height = v4l2sink->crop.height;
- if (v4l2_ioctl (fd, VIDIOC_S_CROP, &crop) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_CROP failed");
return;
}
- if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) {
+ if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed");
return;
}
* ]| This pipeline shows the video captured from a webcam that delivers jpeg
* images.
* </refsect2>
+ *
+ * Since 1.14, the use of libv4l2 has been disabled due to major bugs in the
+ * emulation layer. To enable usage of this library, set the environment
+ * variable GST_V4L2_USE_LIBV4L2=1.
*/
#ifdef HAVE_CONFIG_H
dcmd.cmd = cmd;
dcmd.flags = flags;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
goto dcmd_failed;
return TRUE;
ecmd.cmd = cmd;
ecmd.flags = flags;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENCODER_CMD, &ecmd) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENCODER_CMD, &ecmd) < 0)
goto ecmd_failed;
return TRUE;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP,
+ &v4l2object->vcap) < 0)
goto cap_failed;
if (v4l2object->vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
memset (&input, 0, sizeof (input));
input.index = n;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
if (errno == EINVAL || errno == ENOTTY)
break; /* end of enumeration */
else {
channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
vtun.index = input.tuner;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed to get setting of tuner %d on device '%s'."),
input.tuner, v4l2object->videodev), GST_ERROR_SYSTEM);
standard.frameperiod.denominator = 0;
standard.index = n;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
if (errno == EINVAL || errno == ENOTTY)
break; /* end of enumeration */
#ifdef ENODATA
GST_DEBUG_OBJECT (e, "checking control %08x", n);
control.id = n | next;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL,
+ &control) < 0) {
if (next) {
if (n > 0) {
GST_DEBUG_OBJECT (e, "controls finished");
menu.id = n;
for (i = 0;; i++) {
menu.index = i;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYMENU, &menu) < 0) {
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYMENU,
+ &menu) < 0) {
if (errno == EINVAL)
break; /* end of enumeration */
else {
gst_v4l2_open (GstV4l2Object * v4l2object)
{
struct stat st;
- int libv4l2_fd;
+ int libv4l2_fd = -1;
GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s",
v4l2object->videodev);
if (!GST_V4L2_IS_OPEN (v4l2object))
goto not_open;
- libv4l2_fd = v4l2_fd_open (v4l2object->video_fd,
- V4L2_ENABLE_ENUM_FMT_EMULATION);
+#ifdef HAVE_LIBV4L2
+ if (v4l2object->fd_open)
+ libv4l2_fd = v4l2object->fd_open (v4l2object->video_fd,
+ V4L2_ENABLE_ENUM_FMT_EMULATION);
+#endif
+
/* Note the v4l2_xxx functions are designed so that if they get passed an
unknown fd, the will behave exactly as their regular xxx counterparts, so
if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom
{
if (GST_V4L2_IS_OPEN (v4l2object)) {
/* close device */
- v4l2_close (v4l2object->video_fd);
+ v4l2object->close (v4l2object->video_fd);
v4l2object->video_fd = -1;
}
/* empty lists */
v4l2object->device_caps = other->device_caps;
gst_v4l2_adjust_buf_type (v4l2object);
- v4l2object->video_fd = v4l2_dup (other->video_fd);
+ v4l2object->video_fd = v4l2object->dup (other->video_fd);
if (!GST_V4L2_IS_OPEN (v4l2object))
goto not_open;
GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
/* close device */
- v4l2_close (v4l2object->video_fd);
+ v4l2object->close (v4l2object->video_fd);
v4l2object->video_fd = -1;
/* empty lists */
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0)
goto std_failed;
return TRUE;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0)
goto std_failed;
return TRUE;
channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element));
freq.tuner = tunernum;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0)
goto freq_failed;
*frequency = freq.frequency * channel->freq_multiplicator;
freq.tuner = tunernum;
/* fill in type - ignore error */
- (void) v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq);
+ (void) v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq);
freq.frequency = frequency / channel->freq_multiplicator;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0)
goto freq_failed;
return TRUE;
return FALSE;
tuner.index = tunernum;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0)
goto tuner_failed;
*signal_strength = tuner.signal;
control.id = attribute_num;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto ctrl_failed;
*value = control.value;
control.id = attribute_num;
control.value = value;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0)
goto ctrl_failed;
return TRUE;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0)
goto input_failed;
*input = n;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0)
goto input_failed;
return TRUE;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0)
goto output_failed;
*output = n;
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
- if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0)
+ if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0)
goto output_failed;
return TRUE;