struct vb2_queue {
	unsigned int			type;
	unsigned int			io_modes;
	struct device			*dev;
	unsigned long			dma_attrs;
	unsigned int			bidirectional:1;
	unsigned int			fileio_read_once:1;
	unsigned int			fileio_write_immediately:1;
	unsigned int			allow_zero_bytesused:1;
	unsigned int		   quirk_poll_must_check_waiting_for_buffers:1;
	unsigned int			supports_requests:1;
	unsigned int			requires_requests:1;
	unsigned int			uses_qbuf:1;
	unsigned int			uses_requests:1;
	unsigned int			allow_cache_hints:1;
	unsigned int			non_coherent_mem:1;

	struct mutex			*lock;
	void				*owner;

	const struct vb2_ops		*ops;
	const struct vb2_mem_ops	*mem_ops;
	const struct vb2_buf_ops	*buf_ops;

	void				*drv_priv;
	u32				subsystem_flags;
	unsigned int			buf_struct_size;
	u32				timestamp_flags;
	gfp_t				gfp_flags;
	u32				min_queued_buffers;
	u32				min_reqbufs_allocation;

	struct device			*alloc_devs[VB2_MAX_PLANES];

	/* private: internal use only */
	struct mutex			mmap_lock;
	unsigned int			memory;
	enum dma_data_direction		dma_dir;
	struct vb2_buffer		**bufs;
	unsigned long			*bufs_bitmap;
	unsigned int			max_num_buffers;

	struct list_head		queued_list;
	unsigned int			queued_count;

	atomic_t			owned_by_drv_count;
	struct list_head		done_list;
	spinlock_t			done_lock;
	wait_queue_head_t		done_wq;

	unsigned int			streaming:1;
	unsigned int			start_streaming_called:1;
	unsigned int			error:1;
	unsigned int			waiting_for_buffers:1;
	unsigned int			waiting_in_dqbuf:1;
	unsigned int			is_multiplanar:1;
	unsigned int			is_output:1;
	unsigned int			is_busy:1;
	unsigned int			copy_timestamp:1;
	unsigned int			last_buffer_dequeued:1;

	struct vb2_fileio_data		*fileio;
	struct vb2_threadio_data	*threadio;

	char				name[32];
};

type: buffer 的类型,enum v4l2_buf_type, vendor driver 初始化时设置。
io_modes: 支持的 io 模式,enum vb2_io_modes, vendor driver 初始化时设置。
dma_attrs: dma arrtributes, 可以使用 dma-mapping.h 中的一些宏设置。
bidirectional: 是否支持 dma 双向传输。
fileio_read_once/fileio_write_immediately:
min_queued_buffers: 由 driver 初始化,最少需要的 buffer 数。
min_reqbufs_allocation: 由 vb2_core_queue_init() 初始化,等于 min_queued_buffers+1.
alloc_devs:

min_queued_buffers 是在 driver 队列中的 buffer, 多的一个是 userspace 正在使用的 buffer.

done_list: 准备好 dequeue 给 userspace 的 buffer 链表,通过 vb2_buffer_done() 添加到链表中。

streaming: 是否在 streaming, 在调用 streamon ioctl 后会置 1.
start_streaming_called: 是否调用过 start_streaming.
error: waiting_for_buffers: 正在 dqbuf ioctrl 时会被置 1.
waiting_in_dqbuf:
is_multiplanar:
is_output:
is_busy:
copy_timestamp:
last_buffer_dequeued:


用户层交互的 buffer 结构体:

struct v4l2_buffer {
	__u32			index;
	__u32			type;
	__u32			bytesused;
	__u32			flags;
	__u32			field;
	struct __kernel_v4l2_timeval timestamp;
	struct v4l2_timecode	timecode;
	__u32			sequence;
	__u32			memory;
	union {
		__u32           offset;
		unsigned long   userptr;
		struct v4l2_plane *planes;
		__s32		fd;
	} m;
	__u32			length;
	__u32			reserved2;
	union {
		__s32		request_fd;
		__u32		reserved;
	};
};
struct vb2_buffer {
	struct vb2_queue	*vb2_queue;
	unsigned int		index;
	unsigned int		type;
	unsigned int		memory;
	unsigned int		num_planes;
	u64			timestamp;
	struct media_request	*request;
	struct media_request_object	req_obj;
	enum vb2_buffer_state	state;
	unsigned int		synced:1;
	unsigned int		prepared:1;
	unsigned int		copied_timestamp:1;
	unsigned int		skip_cache_sync_on_prepare:1;
	unsigned int		skip_cache_sync_on_finish:1;
	struct vb2_plane	planes[VB2_MAX_PLANES];
	struct list_head	queued_entry;
	struct list_head	done_entry;
};

vb2_buffer 上层的 vb2_v4l2_buffer:

struct vb2_v4l2_buffer {
	struct vb2_buffer	vb2_buf;

	__u32			flags;
	__u32			field;
	struct v4l2_timecode	timecode;
	__u32			sequence;
	__s32			request_fd;
	bool			is_held;
	struct vb2_plane	planes[VB2_MAX_PLANES];
}
struct vb2_plane {
	void			*mem_priv;
	struct dma_buf		*dbuf;
	unsigned int		dbuf_mapped;
	unsigned int		bytesused;
	unsigned int		length;
	unsigned int		min_length;
	union {
		unsigned int	offset;
		unsigned long	userptr;
		int		fd;
	} m;
	unsigned int		data_offset;
}

vb2_buf: 指向 vb2_buffer 结构体。
flags: 标志位,用于描述 buffer 的状态。
field: 视频场,用于描述视频的场。
timecode: 时间码,用于描述视频的时间码。
sequence: 该帧的序号。
request_fd: 请求文件描述符,用于描述视频的请求文件描述符。
is_held: 是否持有 buffer,用于描述视频的 buffer 是否被持有。
planes: 平面数组,用于描述视频的平面数组。

vb2 queue 操作函数:

struct vb2_ops {
	int (*queue_setup)(struct vb2_queue *q,
			   unsigned int *num_buffers, unsigned int *num_planes,
			   unsigned int sizes[], struct device *alloc_devs[]);
	void (*wait_prepare)(struct vb2_queue *q);
	void (*wait_finish)(struct vb2_queue *q);
	int (*buf_out_validate)(struct vb2_buffer *vb);
	int (*buf_init)(struct vb2_buffer *vb);
	int (*buf_prepare)(struct vb2_buffer *vb);
	void (*buf_finish)(struct vb2_buffer *vb);
	void (*buf_cleanup)(struct vb2_buffer *vb);
	int (*prepare_streaming)(struct vb2_queue *q);
	int (*start_streaming)(struct vb2_queue *q, unsigned int count);
	void (*stop_streaming)(struct vb2_queue *q);
	void (*unprepare_streaming)(struct vb2_queue *q);
	void (*buf_queue)(struct vb2_buffer *vb);
	void (*buf_request_complete)(struct vb2_buffer *vb);
};

queue_setup: 在 CREATEBUF 和 REQBUF ioctl 中会被调用,在 createbuf ioctl 中负责检查传入的 num_planes 和 sizes 是否符合要求。在 reqbuf ioctl 中负责填充 num_planes 和 sizes.

buf_init: 在 allocate buffer 之后调用,执行 driver 自定义的一些初始化操作。

buf_prepare: 每次 qbuf 或者直接调用 VIDIOC_PREPARE_BUF 都会调用到,执行一些初始化操作。如果要支持 CREATE_BUFS ioctl 需要在这里检查 buffer size。

struct vb2_buf_ops {
	int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
	void (*init_buffer)(struct vb2_buffer *vb);
	void (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
	int (*fill_vb2_buffer)(struct vb2_buffer *vb, struct vb2_plane *planes);
	void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
};