参照元

説明

引数

返り値

参考

実装

/**
 * vb2_core_reqbufs() - Initiate streaming
 * @q:          videobuf2 queue
 * @memory: memory type
 * @count: requested buffer count
 *
 * Should be called from vidioc_reqbufs ioctl handler of a driver.
 * This function:
 * 1) verifies streaming parameters passed from the userspace,
 * 2) sets up the queue,
 * 3) negotiates number of buffers and planes per buffer with the driver
 *    to be used during streaming,
 * 4) allocates internal buffer structures (struct vb2_buffer), according to
 *    the agreed parameters,
 * 5) for MMAP memory type, allocates actual video memory, using the
 *    memory handling/allocation routines provided during queue initialization
 *
 * If req->count is 0, all the memory will be freed instead.
 * If the queue has been allocated previously (by a previous vb2_reqbufs) call
 * and the queue is not busy, memory will be reallocated.
 *
 * The return values from this function are intended to be directly returned
 * from vidioc_reqbufs handler in driver.
 */
int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
                unsigned int *count)
{
        unsigned int num_buffers, allocated_buffers, num_planes = 0;
        int ret;

        if (q->streaming) {
                dprintk(1, "streaming active\n");
                return -EBUSY;
        }
        if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
                /*
                 * We already have buffers allocated, so first check if they
                 * are not in use and can be freed.
                 */
                mutex_lock(&q->mmap_lock);
                if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
                        mutex_unlock(&q->mmap_lock);
                        dprintk(1, "memory in use, cannot free\n");
                        return -EBUSY;
                }
                /*
                 * Call queue_cancel to clean up any buffers in the PREPARED or
                 * QUEUED state which is possible if buffers were prepared or
                 * queued without ever calling STREAMON.
                 */
                __vb2_queue_cancel(q);
                ret = __vb2_queue_free(q, q->num_buffers);
                mutex_unlock(&q->mmap_lock);
                if (ret)
                        return ret;
                /*
                 * In case of REQBUFS(0) return immediately without calling
                 * driver's queue_setup() callback and allocating resources.
                 */
                if (*count == 0)
                        return 0;
        }

        /*
         * Make sure the requested values and current defaults are sane.
         */
        num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
        num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
        memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
        memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
        q->memory = memory;
        /*
         * Ask the driver how many buffers and planes per buffer it requires.
         * Driver also sets the size and allocator context for each plane.
         */
        ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
                       q->plane_sizes, q->alloc_ctx);
        if (ret)
                return ret;
        /* Finally, allocate buffers and video memory */
        allocated_buffers =
                __vb2_queue_alloc(q, memory, num_buffers, num_planes);
        if (allocated_buffers == 0) {
                dprintk(1, "memory allocation failed\n");
                return -ENOMEM;
        }
        /*
         * There is no point in continuing if we can't allocate the minimum
         * number of buffers needed by this vb2_queue.
         */
        if (allocated_buffers < q->min_buffers_needed)
                ret = -ENOMEM;

        /*
         * Check if driver can handle the allocated number of buffers.
         */
        if (!ret && allocated_buffers < num_buffers) {
                num_buffers = allocated_buffers;

                ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
                               &num_planes, q->plane_sizes, q->alloc_ctx);
                if (!ret && allocated_buffers < num_buffers)
                        ret = -ENOMEM;

                /*
                 * Either the driver has accepted a smaller number of buffers,
                 * or .queue_setup() returned an error
                 */
        }

        mutex_lock(&q->mmap_lock);
        q->num_buffers = allocated_buffers;

        if (ret < 0) {
                /*
                 * Note: __vb2_queue_free() will subtract 'allocated_buffers'
                 * from q->num_buffers.
                 */
                __vb2_queue_free(q, allocated_buffers);
                mutex_unlock(&q->mmap_lock);
                return ret;
        }
        mutex_unlock(&q->mmap_lock);
        /*
         * Return the number of successfully allocated buffers
         * to the userspace.
         */
        *count = allocated_buffers;
        q->waiting_for_buffers = !q->is_output;

        return 0;
}
EXPORT_SYMBOL_GPL(vb2_core_reqbufs);

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-02-09 (火) 11:22:13