Commit a10b2153 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

media: vb2: add (un)prepare_streaming queue ops



When userspace called VIDIOC_STREAMON, then you want to claim any streaming
resources needed and validate the video pipeline. Waiting for
start_streaming to be called is too late, since that can be postponed
until the required minimum of buffers is queued.

So add a prepare_streaming op (optional) that can be used for that
purpose, and a matching unprepare_streaming op (optional) that can
release any claimed resources. The unprepare_streaming op is called
when VIDIOC_STREAMOFF is called and q->streaming is 1, or when the
filehandle is closed while q->streaming is 1.

Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent e9305a00
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -544,6 +544,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
	 */
	if (q->num_buffers) {
		bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
				  q->cnt_prepare_streaming != q->cnt_unprepare_streaming ||
				  q->cnt_wait_prepare != q->cnt_wait_finish;

		if (unbalanced || debug) {
@@ -552,14 +553,18 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
			pr_info("     setup: %u start_streaming: %u stop_streaming: %u\n",
				q->cnt_queue_setup, q->cnt_start_streaming,
				q->cnt_stop_streaming);
			pr_info("     prepare_streaming: %u unprepare_streaming: %u\n",
				q->cnt_prepare_streaming, q->cnt_unprepare_streaming);
			pr_info("     wait_prepare: %u wait_finish: %u\n",
				q->cnt_wait_prepare, q->cnt_wait_finish);
		}
		q->cnt_queue_setup = 0;
		q->cnt_wait_prepare = 0;
		q->cnt_wait_finish = 0;
		q->cnt_prepare_streaming = 0;
		q->cnt_start_streaming = 0;
		q->cnt_stop_streaming = 0;
		q->cnt_unprepare_streaming = 0;
	}
	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
		struct vb2_buffer *vb = q->bufs[buffer];
@@ -1991,6 +1996,9 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
	if (q->start_streaming_called)
		call_void_qop(q, stop_streaming, q);

	if (q->streaming)
		call_void_qop(q, unprepare_streaming, q);

	/*
	 * If you see this warning, then the driver isn't cleaning up properly
	 * in stop_streaming(). See the stop_streaming() documentation in
@@ -2102,6 +2110,12 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
		return -EINVAL;
	}

	ret = call_qop(q, prepare_streaming, q);
	if (ret)
		return ret;

	q->streaming = 1;

	/*
	 * Tell driver to start streaming provided sufficient buffers
	 * are available.
@@ -2109,16 +2123,19 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
	if (q->queued_count >= q->min_buffers_needed) {
		ret = v4l_vb2q_enable_media_source(q);
		if (ret)
			return ret;
			goto unprepare;
		ret = vb2_start_streaming(q);
		if (ret)
			return ret;
			goto unprepare;
	}

	q->streaming = 1;

	dprintk(q, 3, "successful\n");
	return 0;

unprepare:
	call_void_qop(q, unprepare_streaming, q);
	q->streaming = 0;
	return ret;
}
EXPORT_SYMBOL_GPL(vb2_core_streamon);

+14 −0
Original line number Diff line number Diff line
@@ -386,6 +386,12 @@ struct vb2_buffer {
 *			the buffer contents will be ignored anyway.
 * @buf_cleanup:	called once before the buffer is freed; drivers may
 *			perform any additional cleanup; optional.
 * @prepare_streaming:	called once to prepare for 'streaming' state; this is
 *			where validation can be done to verify everything is
 *			okay and streaming resources can be claimed. It is
 *			called when the VIDIOC_STREAMON ioctl is called. The
 *			actual streaming starts when @start_streaming is called.
 *			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
@@ -405,6 +411,10 @@ struct vb2_buffer {
 *			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
 * @unprepare_streaming:called as counterpart to @prepare_streaming; any claimed
 *			streaming resources can be released here. It is
 *			called when the VIDIOC_STREAMOFF ioctls is called or
 *			when the streaming filehandle is closed. Optional.
 * @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;
@@ -432,8 +442,10 @@ struct vb2_ops {
	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);

@@ -641,8 +653,10 @@ struct vb2_queue {
	u32				cnt_queue_setup;
	u32				cnt_wait_prepare;
	u32				cnt_wait_finish;
	u32				cnt_prepare_streaming;
	u32				cnt_start_streaming;
	u32				cnt_stop_streaming;
	u32				cnt_unprepare_streaming;
#endif
};