Linux v4l2架构学习总链接
step 7 : 读取数据
1,poll或者select
这里使用select,对应代码如下
fd_set fds;
struct timeval tv;
int r;
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);
}
//ok
对于select其调用过程如下
SYSCALL_DEFINE5(select -- kernel/fs/select.c
kern_select
core_sys_select
do_select
vfs_poll
file->f_op->poll
...
vivi_poll
具体过程不分析,这里看vivi_poll
vivi_poll(struct file *file, struct poll_table_struct *wait)
{
struct vivi_dev *dev = video_drvdata(file);
struct vb2_queue *q = &dev->vb_vidq;
dprintk(dev, 1, "%s\n", __func__);
return vb2_poll(q, file, wait);
}
__poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
{
struct video_device *vfd = video_devdata(file);
__poll_t req_events = poll_requested_events(wait);
__poll_t res = 0;
/*
* 对于V4L2_FL_USES_V4L2_FH
* 具体的作用没有看明白
*/
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {struct v4l2_fh *fh = file->private_data;
/*
* 对于pending
* 就是判断fh->navailable的值
* 这里以后分析
*/
if (v4l2_event_pending(fh))
res = EPOLLPRI;
else if (req_events & EPOLLPRI)
/*
* 对于poll_wait这个暂时没有追着看
* 应用poll的时候走不到这里
* 只有select的时候才会走到
*/
poll_wait(file, &fh->wait, wait);
}
/*
* 分析 vb2_core_poll
*/
return res | vb2_core_poll(q, file, wait);
}
vivi_poll
vb2_poll
vb2_core_poll
__poll_t vb2_core_poll(struct vb2_queue *q, struct file *file,
poll_table *wait)
{
...
/*
* 之前分析过vivi stream_on后就会开始产生数据
* 产生数据后会调用vb2_buffer_done做2件事
* 1.将填充了数据的buffer挂载到done_list链表上
* 2.wake_up(&q->done_wq);
*
* 所以说如果if条件满足,说明还没有帧数据产生
* 那么就在这里等着就行
*/
if (list_empty(&q->done_list)) {
/*
* If the last buffer was dequeued from a capture queue,
* return immediately. DQBUF will return -EPIPE.
*/
if (q->last_buffer_dequeued)
return EPOLLIN | EPOLLRDNORM;
poll_wait(file, &q->done_wq, wait);
}
/*
* Take first buffer available for dequeuing.
*/
spin_lock_irqsave(&q->done_lock, flags);
/*
* 发现done_list上不为空,说明有数据
* 那么就取链表靠前的buffer
* 这里取buffer的目的只是判断当前buffer是不是有效的
* 如果无效,那么应用select继续等待
*/
if (!list_empty(&q->done_list))
vb = list_first_entry(&q->done_list, struct vb2_buffer,
done_entry);
spin_unlock_irqrestore(&q->done_lock, flags);
if (vb && (vb->state == VB2_BUF_STATE_DONE
|| vb->state == VB2_BUF_STATE_ERROR)) {
return (q->is_output) ?
EPOLLOUT | EPOLLWRNORM :
EPOLLIN | EPOLLRDNORM;
}
return 0;
}
select的应用代码这里先不编写,和后面的一起配合使用。
本文详细介绍了Linux V4L2架构下使用select进行数据读取的过程,包括select调用流程、vivi_poll和vb2_poll的具体实现,并分析了vb2_core_poll中如何判断是否有数据可读。

2745

被折叠的 条评论
为什么被折叠?



