LINUX&UVC驱动队列层级结构
2024-04-02
58
0
在LINUX&UVC驱动中单独有一个文件命名为uvc_queue.c,其实现的就是管理UVC驱动中视频数据缓冲区队列的,即Video buffers queue management。
UVC视频队列实始化的函数是uvc_queue_init(),并且永远不能失败。
视频缓冲区(Video buffers)由videobuf2模块实现并管理。当然对队列的一些操作,需要一些必要的锁来保护队列。
对于LINUX&UVC驱动中的视频设备节点(无论是视频节点还是MetaData节点设备),其struct uvc_streaming成员的struct uvc_video_queue queue就是队列。
struct uvc_streaming {
...
/* Buffers queue. */
unsigned int frozen : 1;
struct uvc_video_queue queue;
...
}
struct uvc_video_queue {
struct vb2_queue queue;
struct mutex mutex; /* Protects queue */
unsigned int flags;
unsigned int buf_used;
spinlock_t irqlock; /* Protects irqqueue */
struct list_head irqqueue;
};
UVC队列的初始化使用uvc_queue_init,其根据不同的设备类型,其设置的回调函数集不同。对于METADATA类型的为uvc_meta_queue_qops,而视频节点的为uvc_queue_qops。
int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
int drop_corrupted)
{
int ret;
queue->queue.type = type;
queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
queue->queue.drv_priv = queue;
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.mem_ops = &vb2_vmalloc_memops;
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
queue->queue.lock = &queue->mutex;
switch (type) {
case V4L2_BUF_TYPE_META_CAPTURE:
queue->queue.ops = &uvc_meta_queue_qops;
break;
default:
queue->queue.io_modes |= VB2_DMABUF;
queue->queue.ops = &uvc_queue_qops;
break;
}
ret = vb2_queue_init(&queue->queue);
if (ret)
return ret;
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->irqqueue);
queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
return 0;
}
这些函数其实是VB2模块的对应回调函数:
static const struct vb2_ops uvc_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
.buf_finish = uvc_buffer_finish,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.start_streaming = uvc_start_streaming,
.stop_streaming = uvc_stop_streaming,
};
static const struct vb2_ops uvc_meta_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.stop_streaming = uvc_stop_streaming,
};
这些各个模块的关系如下:
- struct uvc_streaming :代表一个设备节点
- struct uvc_video_queue queue:该设备节点下的数据队列
- struct vb2_queue queue;:数据队列使用的是vb2提供的队列模块
- vb2_ops:驱动提供给VB2模块相应的回调函数。