Linux v4l2架构学习总链接
gitee源码
VIDIOC_DQBUF
同样的先去看从应用调用vivi驱动分析v4l2 – 缓存放入队列(VIDIOC_QBUF)
那到缓冲区信息的代码可以看__fill_v4l2_buffer
/* 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"); }