Linux v4l2架构学习总链接
gitee源码
VIDIOC_DQBUF
同样的先去看从应用调用vivi驱动分析v4l2 – 缓存放入队列(VIDIOC_QBUF)
那到缓冲区信息的代码可以看__fill_v4l2_buffer
static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
{
struct v4l2_buffer *b = pb;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
/* Copy back data such as timestamp, flags, etc. */
b->index = vb->index;
b->type = vb->type;
b->memory = vb->memory;
b->bytesused = 0;
b->flags = vbuf->flags;
b->field = vbuf->field;
b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
b->reserved2 = 0;
b->reserved = 0;
if (q->is_multiplanar) {
/*
* Fill in plane-related data if userspace provided an array
* for it. The caller has already verified memory and size.
*/
b->length = vb->num_planes;
for (plane = 0; plane < vb->num_planes; ++plane) {
struct v4l2_plane *pdst = &b->m.planes[plane];
struct vb2_plane *psrc = &vb->planes[plane];
pdst->bytesused = psrc->bytesused;
pdst->length = psrc->length;
if (q->memory == VB2_MEMORY_MMAP)
pdst->m.mem_offset = psrc->m.offset;
else if (q->memory == VB2_MEMORY_USERPTR)
pdst->m.userptr = psrc->m.userptr;
else if (q->memory == VB2_MEMORY_DMABUF)
pdst->m.fd = psrc->m.fd;
pdst->data_offset = psrc->data_offset;
memset(pdst->reserved, 0, sizeof(pdst->reserved));
}
} else { ... }
这里可以看到,本次ioctl实际上是填充了所有的plane的信息,也就是说当前buffer中的所有plane对应的缓冲区中都填充了framebuff的数据。
编写对应的应用代码
struct v4l2_plane *tmp_plane;
tmp_plane = calloc(num_planes, sizeof(*tmp_plane));
while (1)
{
FD_ZERO (&fds);
FD_SET(fd, &fds);
tv.tv_sec = 5;
tv.tv_usec = 0;
r = select (fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r)
{
if (EINTR == errno)
continue;
printf ("select err\n");
}
if (0 == r)
{
fprintf (stderr, "select timeout\n");
exit (EXIT_FAILURE);
}
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.m.planes = tmp_plane;
/* 注意这个length 内核代码中还是会检测的 */
buf.length = num_planes;
if (ioctl (fd, VIDIOC_DQBUF, &buf) < 0)
printf("dqbuf fail\n");
for (j = 0; j < num_planes; j++) {
printf("plane[%d] start = %p, bytesused = %d\n", j, ((buffers + buf.index)->plane_start + j)->start, (tmp_plane + j)->bytesused);
}
if (ioctl (fd, VIDIOC_QBUF, &buf) < 0)
printf("failture VIDIOC_QBUF\n");
}