Linux&UVC驱动
+ -

LINUX&UVC驱动队列层级结构

2024-04-02 11 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,
};

这些各个模块的关系如下:
095931991706

  • struct uvc_streaming :代表一个设备节点
  • struct uvc_video_queue queue:该设备节点下的数据队列
  • struct vb2_queue queue;:数据队列使用的是vb2提供的队列模块
  • vb2_ops:驱动提供给VB2模块相应的回调函数。

0 篇笔记 写笔记

关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!