【genius_platform软件平台开发】第五十九讲:Linux系统之V4L2视频驱动-VIDIOC_QUERYBUF查询缓存信息

VIDIOC_QUERYBUF查询缓存信息代码详解

  • 1. 概述
  • 2 应用层
    • 2.1 struct v4l2_buffer结构体
  • 3. 驱动层
    • 3.1 vb2_ioctl_querybuf函数
    • 3.2 vb2_querybuf函数
    • 3.3 __fill_v4l2_buffer函数
    • 3.4 enum vb2_buffer_state枚举
    • 3.5 enum vb2_io_modes枚举
    • 3.6 struct vb2_plane结构体
    • 3.7 struct vb2_buffer结构体(*)
    • 3.8 struct vb2_ops结构体
    • 3.9 struct vb2_buf_ops 结构体
    • 3.10 struct vb2_queue 结构体

1. 概述

  • VIDIOC_QUERYBUF主要作用是查询分配好的 buffer 信息在内核空间中的长度length偏移量offset.查询已经分配好的V4L2视频缓冲区的相关信息,包括缓冲区的使用状态、在内核空间的偏移地址、缓冲区长度等,然后应用程序根据这些信息使用mmap把内核空间地址映射到用户空间。

2 应用层

2.1 struct v4l2_buffer结构体

struct v4l2_buffer
{
	__u32 index; //buffer 序号
	enum v4l2_buf_type type; //buffer 类型
	__u32 byteused; //buffer 中已使用的字节数
	__u32 flags; // 区分是MMAP 还是USERPTR
	enum v4l2_field field;
	struct timeval timestamp;// 获取第一个字节时的系统时间
	struct v4l2_timecode timecode;
	__u32 sequence; // 队列中的序号
	enum v4l2_memory memory;//IO 方式,被应用程序设置
	union m
	{
		__u32 offset;// 缓冲帧地址,只对MMAP 有效
		unsigned long userptr;
	};
	__u32 length;// 缓冲帧长度
	__u32 input;
	__u32 reserved;
};

v4l2_buffer buf;  
buf.index = i;  
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
buf.memory = V4L2_MEMORY_MMAP;  
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);  
if(ret < 0) {  
    LOG("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);  
    return ret;  

3. 驱动层

3.1 vb2_ioctl_querybuf函数

int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
        struct video_device *vdev = video_devdata(file);

        /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
        return vb2_querybuf(vdev->queue, p);
}
EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);

3.2 vb2_querybuf函数

int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)  
{  
    struct vb2_buffer *vb;  
    // 取出 buf  
    vb = q->bufs[b->index];  
    // 将 buf 信息写回用户空间传递的 b  
    return __fill_v4l2_buffer(vb, b);  
}  

3.3 __fill_v4l2_buffer函数

/**
 * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
 * returned to userspace
 */
static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
{
        struct v4l2_buffer *b = pb;
        /*
         * 对于vb2_v4l2_buffer好像是第一次见到,这里分析一下来源
         * 先说一下这个函数的2个参数
         * vb是来源于bufs[index],申请buffer的时候填充的
         * pb则是来自于用户空间的地址
         * vbuf = to_vb2_v4l2_buffer(vb)
         * 说明和vb有关系
         * __vb2_queue_alloc中vb创建如下
         * vb = kzalloc(q->buf_struct_size, GFP_KERNEL);
         * 而q->buf_struct_size值在
         * vb2_queue_init
         * if (q->buf_struct_size == 0)
         *     q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
         * 也就是不为0的时候,这里会赋值
         * 但是vivi驱动中已经对其赋值了
         * q->buf_struct_size = sizeof(struct vivi_buffer);
         * 这样就找到了,对应的vb2_v4l2_buffer 
         * 实际看vivi_buffer,
         * struct vivi_buffer {
	 *    struct vb2_buffer	vb;
	 *    struct list_head	list;
	 *    struct vivi_fmt        *fmt;
         * }
         * 没看到vb2_v4l2_buffer相关的东西
         * 于是去看最新的vivi驱动代码,如下
         * struct vivid_buffer {
	 *     struct vb2_v4l2_buffer vb;
	 *     struct list_head	list;
         * };
         * 这里就可以看到vb2_v4l2_buffer的来源了
         * 其实主要原因还是vivi驱动太老,linux内核太新不匹配造成的
         * */
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct vb2_queue *q = vb->vb2_queue;
        unsigned int plane;

		// 直接填充数据成员信息
        /* Copy back data such as timestamp, flags, etc. */
        b->index = vb->index;
        b->type = vb->type;
        b->memory = vb->memory;
        b->bytesused = 0;

        b->flags = vbuf->flags;
        b->field = vbuf->field;
        b->timestamp = ns_to_timeval(vb->timestamp);
        b->timecode = vbuf->timecode;
        b->sequence = vbuf->sequence;
        b->reserved2 = 0;
        b->reserved = 0;

		// 多平面视频格式暂不做解释,还没细研究!!!
        if (q->is_multiplanar) {
                /*
                 * Fill in plane-related data if userspace provided an array
                 * for it. The caller has already verified memory and size.
                 */
                b->length = vb->num_planes;
                for (plane = 0; plane < vb->num_planes; ++plane) {
                        struct v4l2_plane *pdst = &b->m.planes[plane];
                        struct vb2_plane *psrc = &vb->planes[plane];

                        pdst->bytesused = psrc->bytesused;
                        pdst->length = psrc->length;
                        if (q->memory == VB2_MEMORY_MMAP)
                                pdst->m.mem_offset = psrc->m.offset;
                        else if (q->memory == VB2_MEMORY_USERPTR)
                                pdst->m.userptr = psrc->m.userptr;
                        else if (q->memory == VB2_MEMORY_DMABUF)
                                pdst->m.fd = psrc->m.fd;
                        pdst->data_offset = psrc->data_offset;
                        memset(pdst->reserved, 0, sizeof(pdst->reserved));
                }
        } else {
        /*
                 * length: 平面的大小,可能与真实的数据帧大小不一致,驱动为了page对齐会变大
                 * byteused: 帧数据的大小,这里为0,后面的分析中可以看到更新
                 * 应用代码中有时候可能会用length代表帧数据的大小,这个值有可能是不准确的
                 * 比如帧大小是4812Byte,那么驱动中有可能为了方便,将length设置为5000
                 * 所以最好使用byteused
				*/             
				 /*
                 * We use length and offset in v4l2_planes array even for
                 * single-planar buffers, but userspace does not.
                 */
                b->length = vb->planes[0].length;
                b->bytesused = vb->planes[0].bytesused;
                if (q->memory == VB2_MEMORY_MMAP)
                        b->m.offset = vb->planes[0].m.offset;
                else if (q->memory == VB2_MEMORY_USERPTR)
                        b->m.userptr = vb->planes[0].m.userptr;
                else if (q->memory == VB2_MEMORY_DMABUF)
                        b->m.fd = vb->planes[0].m.fd;
        }

        /*
         * Clear any buffer state related flags.
         */
        b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
        b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
        if (!q->copy_timestamp) {
                /*
                 * For non-COPY timestamps, drop timestamp source bits
                 * and obtain the timestamp source from the queue.
                 */
                b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
                b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
        }
		/*
         * 对于vb->state的值
         * 在使用reqbuf的时候VIDIOC_REQBUFS,看上一篇
         * vb->state = VB2_BUF_STATE_DEQUEUED
         * 表示该buffer在用户空间控制,直接break
		*/
      switch (vb->state) {
        case VB2_BUF_STATE_QUEUED:
        case VB2_BUF_STATE_ACTIVE:
                b->flags |= V4L2_BUF_FLAG_QUEUED;
                break;
        case VB2_BUF_STATE_ERROR:
                b->flags |= V4L2_BUF_FLAG_ERROR;
                /* fall through */
        case VB2_BUF_STATE_DONE:
                b->flags |= V4L2_BUF_FLAG_DONE;
                break;
        case VB2_BUF_STATE_PREPARED:
                b->flags |= V4L2_BUF_FLAG_PREPARED;
                break;
        case VB2_BUF_STATE_PREPARING:
        case VB2_BUF_STATE_DEQUEUED:
        case VB2_BUF_STATE_REQUEUEING:
                /* nothing */
                break;
        }

        if (vb2_buffer_in_use(q, vb))
                b->flags |= V4L2_BUF_FLAG_MAPPED;

        if (!q->is_output &&
                b->flags & V4L2_BUF_FLAG_DONE &&
                b->flags & V4L2_BUF_FLAG_LAST)
                q->last_buffer_dequeued = true;
}


3.4 enum vb2_buffer_state枚举

/**
 * enum vb2_buffer_state - current video buffer state
 * @VB2_BUF_STATE_DEQUEUED:     buffer under userspace control
 * @VB2_BUF_STATE_PREPARING:    buffer is being prepared in videobuf
 * @VB2_BUF_STATE_PREPARED:     buffer prepared in videobuf and by the driver
 * @VB2_BUF_STATE_QUEUED:       buffer queued in videobuf, but not in driver
 * @VB2_BUF_STATE_REQUEUEING:   re-queue a buffer to the driver
 * @VB2_BUF_STATE_ACTIVE:       buffer queued in driver and possibly used
 *                              in a hardware operation
 * @VB2_BUF_STATE_DONE:         buffer returned from driver to videobuf, but
 *                              not yet dequeued to userspace
 * @VB2_BUF_STATE_ERROR:        same as above, but the operation on the buffer
 *                              has ended with an error, which will be reported
 *                              to the userspace when it is dequeued
 */
enum vb2_buffer_state {
        VB2_BUF_STATE_DEQUEUED,
        VB2_BUF_STATE_PREPARING,
        VB2_BUF_STATE_PREPARED,
        VB2_BUF_STATE_QUEUED,
        VB2_BUF_STATE_REQUEUEING,
        VB2_BUF_STATE_ACTIVE,
        VB2_BUF_STATE_DONE,
        VB2_BUF_STATE_ERROR,
};

3.5 enum vb2_io_modes枚举

/**
 * enum vb2_io_modes - queue access methods
 * @VB2_MMAP:           driver supports MMAP with streaming API
 * @VB2_USERPTR:        driver supports USERPTR with streaming API
 * @VB2_READ:           driver supports read() style access
 * @VB2_WRITE:          driver supports write() style access
 * @VB2_DMABUF:         driver supports DMABUF with streaming API
 */
enum vb2_io_modes {
        VB2_MMAP        = (1 << 0),
        VB2_USERPTR     = (1 << 1),
        VB2_READ        = (1 << 2),
        VB2_WRITE       = (1 << 3),
        VB2_DMABUF      = (1 << 4),
}

3.6 struct vb2_plane结构体


/**
 * struct vb2_plane - plane information
 * @mem_priv:   private data with this plane
 * @dbuf:       dma_buf - shared buffer object
 * @dbuf_mapped:        flag to show whether dbuf is mapped or not
 * @bytesused:  number of bytes occupied by data in the plane (payload)
 * @length:     size of this plane (NOT the payload) in bytes
 * @min_length: minimum required size of this plane (NOT the payload) in bytes.
 *              @length is always greater or equal to @min_length.
 * @offset:     when memory in the associated struct vb2_buffer is
 *              VB2_MEMORY_MMAP, equals the offset from the start of
 *              the device memory for this plane (or is a "cookie" that
 *              should be passed to mmap() called on the video node)
 * @userptr:    when memory is VB2_MEMORY_USERPTR, a userspace pointer
 *              pointing to this plane
 * @fd:         when memory is VB2_MEMORY_DMABUF, a userspace file
 *              descriptor associated with this plane
 * @m:          Union with memtype-specific data (@offset, @userptr or
 *              @fd).
 * @data_offset:        offset in the plane to the start of data; usually 0,
 *              unless there is a header in front of the data
 * Should contain enough information to be able to cover all the fields
                                                                                                                                                                                                                                              89,2           8%
 *              unless there is a header in front of the data
 * Should contain enough information to be able to cover all the fields
 * of struct v4l2_plane at videodev2.h
 */
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;
};

3.7 struct vb2_buffer结构体(*)

 * struct vb2_buffer - represents a video buffer
 * @vb2_queue:          the queue to which this driver belongs
 * @index:              id number of the buffer
 * @type:               buffer type
 * @memory:             the method, in which the actual data is passed
 * @num_planes:         number of planes in the buffer
 *                      on an internal driver queue
 * @planes:             private per-plane information; do not change
 * @timestamp:          frame timestamp in ns
 */
struct vb2_buffer {
        struct vb2_queue        *vb2_queue;
        unsigned int            index;
        unsigned int            type;
        unsigned int            memory;
        unsigned int            num_planes;
        struct vb2_plane        planes[VB2_MAX_PLANES];
        u64                     timestamp;

        /* private: internal use only
         *
         * state:               current buffer state; do not change
         * queued_entry:        entry on the queued buffers list, which holds
         *                      all buffers queued from userspace
         * done_entry:          entry on the list that stores all buffers ready
         *                      to be dequeued to userspace
         */
        enum vb2_buffer_state   state;

        struct list_head        queued_entry;
        struct list_head        done_entry;
#ifdef CONFIG_VIDEO_ADV_DEBUG
        /*
         * Counters for how often these buffer-related ops are
         * called. Used to check for unbalanced ops.
         */
        u32             cnt_mem_alloc;
        u32             cnt_mem_put;
        u32             cnt_mem_get_dmabuf;
        u32             cnt_mem_get_userptr;
        u32             cnt_mem_put_userptr;
        u32             cnt_mem_prepare;
        u32             cnt_mem_finish;
        u32             cnt_mem_attach_dmabuf;
        u32             cnt_mem_detach_dmabuf;
        u32             cnt_mem_map_dmabuf;
        u32             cnt_mem_unmap_dmabuf;
        u32             cnt_mem_vaddr;
        u32             cnt_mem_cookie;
        u32             cnt_mem_num_users;
        u32             cnt_mem_mmap;

        u32             cnt_buf_init;
        u32             cnt_buf_prepare;
        u32             cnt_buf_finish;
        u32             cnt_buf_cleanup;
        u32             cnt_buf_queue;

        /* This counts the number of calls to vb2_buffer_done() */
        u32             cnt_buf_done;
#endif
};

3.8 struct vb2_ops结构体


/**
 * struct vb2_ops - driver-specific callbacks
 *
 * @queue_setup:	called from VIDIOC_REQBUFS() and VIDIOC_CREATE_BUFS()
 *			handlers before memory allocation. It can be called
 *			twice: if the original number of requested buffers
 *			could not be allocated, then it will be called a
 *			second time with the actually allocated number of
 *			buffers to verify if that is OK.
 *			The driver should return the required number of buffers
 *			in \*num_buffers, the required number of planes per
 *			buffer in \*num_planes, the size of each plane should be
 *			set in the sizes\[\] array and optional per-plane
 *			allocator specific device in the alloc_devs\[\] array.
 *			When called from VIDIOC_REQBUFS(), \*num_planes == 0,
 *			the driver has to use the currently configured format to
 *			determine the plane sizes and \*num_buffers is the total
 *			number of buffers that are being allocated. When called
 *			from VIDIOC_CREATE_BUFS(), \*num_planes != 0 and it
 *			describes the requested number of planes and sizes\[\]
 *			contains the requested plane sizes. In this case
 *			\*num_buffers are being allocated additionally to
 *			q->num_buffers. If either \*num_planes or the requested
 *			sizes are invalid callback must return %-EINVAL.
 * @wait_prepare:	release any locks taken while calling vb2 functions;
 *			it is called before an ioctl needs to wait for a new
 *			buffer to arrive; required to avoid a deadlock in
 *			blocking access type.
 * @wait_finish:	reacquire all locks released in the previous callback;
 *			required to continue operation after sleeping while
 *			waiting for a new buffer to arrive.
 * @buf_init:		called once after allocating a buffer (in MMAP case)
 *			or after acquiring a new USERPTR buffer; drivers may
 *			perform additional buffer-related initialization;
 *			initialization failure (return != 0) will prevent
 *			queue setup from completing successfully; optional.
 * @buf_prepare:	called every time the buffer is queued from userspace
 *			and from the VIDIOC_PREPARE_BUF() ioctl; drivers may
 *			perform any initialization required before each
 *			hardware operation in this callback; drivers can
 *			access/modify the buffer here as it is still synced for
 *			the CPU; drivers that support VIDIOC_CREATE_BUFS() must
 *			also validate the buffer size; if an error is returned,
 *			the buffer will not be queued in driver; optional.
 * @buf_finish:		called before every dequeue of the buffer back to
 *			userspace; the buffer is synced for the CPU, so drivers
 *			can access/modify the buffer contents; drivers may
 *			perform any operations required before userspace
 *			accesses the buffer; optional. The buffer state can be
 *			one of the following: %DONE and %ERROR occur while
 *			streaming is in progress, and the %PREPARED state occurs
 *			when the queue has been canceled and all pending
 *			buffers are being returned to their default %DEQUEUED
 *			state. Typically you only have to do something if the
 *			state is %VB2_BUF_STATE_DONE, since in all other cases
 *			the buffer contents will be ignored anyway.
 * @buf_cleanup:	called once before the buffer is freed; drivers may
 *			perform any additional cleanup; optional.
 * @start_streaming:	called once to enter 'streaming' state; the driver may
 *			receive buffers with @buf_queue callback
 *			before @start_streaming is called; the driver gets the
 *			number of already queued buffers in count parameter;
 *			driver can return an error if hardware fails, in that
 *			case all buffers that have been already given by
 *			the @buf_queue callback are to be returned by the driver
 *			by calling vb2_buffer_done() with %VB2_BUF_STATE_QUEUED.
 *			If you need a minimum number of buffers before you can
 *			start streaming, then set @min_buffers_needed in the
 *			vb2_queue structure. If that is non-zero then
 *			@start_streaming won't be called until at least that
 *			many buffers have been queued up by userspace.
 * @stop_streaming:	called when 'streaming' state must be disabled; driver
 *			should stop any DMA transactions or wait until they
 *			finish and give back all buffers it got from &buf_queue
 *			callback by calling vb2_buffer_done() with either
 *			%VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use
 *			vb2_wait_for_all_buffers() function
 * @buf_queue:		passes buffer vb to the driver; driver may start
 *			hardware operation on this buffer; driver should give
 *			the buffer back by calling vb2_buffer_done() function;
 *			it is allways called after calling VIDIOC_STREAMON()
 *			ioctl; might be called before @start_streaming callback
 *			if user pre-queued buffers before calling
 *			VIDIOC_STREAMON().
 */
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_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 (*start_streaming)(struct vb2_queue *q, unsigned int count);
	void (*stop_streaming)(struct vb2_queue *q);

	void (*buf_queue)(struct vb2_buffer *vb);
};

3.9 struct vb2_buf_ops 结构体

/**
 * struct vb2_buf_ops - driver-specific callbacks
 *
 * @verify_planes_array: Verify that a given user space structure contains
 *			enough planes for the buffer. This is called
 *			for each dequeued buffer.
 * @fill_user_buffer:	given a vb2_buffer fill in the userspace structure.
 *			For V4L2 this is a struct v4l2_buffer.
 * @fill_vb2_buffer:	given a userspace structure, fill in the vb2_buffer.
 *			If the userspace structure is invalid, then this op
 *			will return an error.
 * @copy_timestamp:	copy the timestamp from a userspace structure to
 *			the vb2_buffer struct.
 */
struct vb2_buf_ops {
	int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
	void (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
	int (*fill_vb2_buffer)(struct vb2_buffer *vb, const void *pb,
				struct vb2_plane *planes);
	void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
};

3.10 struct vb2_queue 结构体

/**
 * struct vb2_queue - a videobuf queue
 *
 * @type:	private buffer type whose content is defined by the vb2-core
 *		caller. For example, for V4L2, it should match
 *		the types defined on enum &v4l2_buf_type
 * @io_modes:	supported io methods (see vb2_io_modes enum)
 * @dev:	device to use for the default allocation context if the driver
 *		doesn't fill in the @alloc_devs array.
 * @dma_attrs:	DMA attributes to use for the DMA.
 * @bidirectional: when this flag is set the DMA direction for the buffers of
 *		this queue will be overridden with DMA_BIDIRECTIONAL direction.
 *		This is useful in cases where the hardware (firmware) writes to
 *		a buffer which is mapped as read (DMA_TO_DEVICE), or reads from
 *		buffer which is mapped for write (DMA_FROM_DEVICE) in order
 *		to satisfy some internal hardware restrictions or adds a padding
 *		needed by the processing algorithm. In case the DMA mapping is
 *		not bidirectional but the hardware (firmware) trying to access
 *		the buffer (in the opposite direction) this could lead to an
 *		IOMMU protection faults.
 * @fileio_read_once:		report EOF after reading the first buffer
 * @fileio_write_immediately:	queue buffer after each write() call
 * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
 * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
 *              has not been called. This is a vb1 idiom that has been adopted
 *              also by vb2.
 * @lock:	pointer to a mutex that protects the vb2_queue struct. The
 *		driver can set this to a mutex to let the v4l2 core serialize
 *		the queuing ioctls. If the driver wants to handle locking
 *		itself, then this should be set to NULL. This lock is not used
 *		by the videobuf2 core API.
 * @owner:	The filehandle that 'owns' the buffers, i.e. the filehandle
 *		that called reqbufs, create_buffers or started fileio.
 *		This field is not used by the videobuf2 core API, but it allows
 *		drivers to easily associate an owner filehandle with the queue.
 * @ops:	driver-specific callbacks
 * @mem_ops:	memory allocator specific callbacks
 * @buf_ops:	callbacks to deliver buffer information
 *		between user-space and kernel-space
 * @drv_priv:	driver private data
 * @buf_struct_size: size of the driver-specific buffer structure;
 *		"0" indicates the driver doesn't want to use a custom buffer
 *		structure type. for example, sizeof(struct vb2_v4l2_buffer)
 *		will be used for v4l2.
 * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
 *		V4L2_BUF_FLAG_TSTAMP_SRC_*
 * @gfp_flags:	additional gfp flags used when allocating the buffers.
 *		Typically this is 0, but it may be e.g. GFP_DMA or __GFP_DMA32
 *		to force the buffer allocation to a specific memory zone.
 * @min_buffers_needed: the minimum number of buffers needed before
 *		@start_streaming can be called. Used when a DMA engine
 *		cannot be started unless at least this number of buffers
 *		have been queued into the driver.
 */
/*
 * Private elements (won't appear at the uAPI book):
 * @mmap_lock:	private mutex used when buffers are allocated/freed/mmapped
 * @memory:	current memory type used
 * @dma_dir:	DMA mapping direction.
 * @bufs:	videobuf buffer structures
 * @num_buffers: number of allocated/used buffers
 * @queued_list: list of buffers currently queued from userspace
 * @queued_count: number of buffers queued and ready for streaming.
 * @owned_by_drv_count: number of buffers owned by the driver
 * @done_list:	list of buffers ready to be dequeued to userspace
 * @done_lock:	lock to protect done_list list
 * @done_wq:	waitqueue for processes waiting for buffers ready to be dequeued
 * @alloc_devs:	memory type/allocator-specific per-plane device
 * @streaming:	current streaming state
 * @start_streaming_called: @start_streaming was called successfully and we
 *		started streaming.
 * @error:	a fatal error occurred on the queue
 * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
 *		buffers. Only set for capture queues if qbuf has not yet been
 *		called since poll() needs to return POLLERR in that situation.
 * @is_multiplanar: set if buffer type is multiplanar
 * @is_output:	set if buffer type is output
 * @copy_timestamp: set if vb2-core should set timestamps
 * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
 *		last decoded buffer was already dequeued. Set for capture queues
 *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
 * @fileio:	file io emulator internal data, used only if emulator is active
 * @threadio:	thread io internal data, used only if thread is active
 */
struct vb2_queue {
	unsigned int			type;
	unsigned int			io_modes;
	struct device			*dev;
	unsigned long			dma_attrs;
	unsigned			bidirectional:1;
	unsigned			fileio_read_once:1;
	unsigned			fileio_write_immediately:1;
	unsigned			allow_zero_bytesused:1;
	unsigned		   quirk_poll_must_check_waiting_for_buffers: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;
	unsigned int			buf_struct_size;
	u32				timestamp_flags;
	gfp_t				gfp_flags;
	u32				min_buffers_needed;

	/* private: internal use only */
	struct mutex			mmap_lock;
	unsigned int			memory;
	enum dma_data_direction		dma_dir;
	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
	unsigned int			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;

	struct device			*alloc_devs[VB2_MAX_PLANES];

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

	struct vb2_fileio_data		*fileio;
	struct vb2_threadio_data	*threadio;

#ifdef CONFIG_VIDEO_ADV_DEBUG
	/*
	 * Counters for how often these queue-related ops are
	 * called. Used to check for unbalanced ops.
	 */
	u32				cnt_queue_setup;
	u32				cnt_wait_prepare;
	u32				cnt_wait_finish;
	u32				cnt_start_streaming;
	u32				cnt_stop_streaming;
#endif
};

你可能感兴趣的:(linux系统V4L2视频驱动,3,VIDIOC_QUERYBUF,v4l2)