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);
};