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

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
...@@ -544,6 +544,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) ...@@ -544,6 +544,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
*/ */
if (q->num_buffers) { if (q->num_buffers) {
bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming || 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; q->cnt_wait_prepare != q->cnt_wait_finish;
if (unbalanced || debug) { if (unbalanced || debug) {
...@@ -552,14 +553,18 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) ...@@ -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", pr_info(" setup: %u start_streaming: %u stop_streaming: %u\n",
q->cnt_queue_setup, q->cnt_start_streaming, q->cnt_queue_setup, q->cnt_start_streaming,
q->cnt_stop_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", pr_info(" wait_prepare: %u wait_finish: %u\n",
q->cnt_wait_prepare, q->cnt_wait_finish); q->cnt_wait_prepare, q->cnt_wait_finish);
} }
q->cnt_queue_setup = 0; q->cnt_queue_setup = 0;
q->cnt_wait_prepare = 0; q->cnt_wait_prepare = 0;
q->cnt_wait_finish = 0; q->cnt_wait_finish = 0;
q->cnt_prepare_streaming = 0;
q->cnt_start_streaming = 0; q->cnt_start_streaming = 0;
q->cnt_stop_streaming = 0; q->cnt_stop_streaming = 0;
q->cnt_unprepare_streaming = 0;
} }
for (buffer = 0; buffer < q->num_buffers; ++buffer) { for (buffer = 0; buffer < q->num_buffers; ++buffer) {
struct vb2_buffer *vb = q->bufs[buffer]; struct vb2_buffer *vb = q->bufs[buffer];
...@@ -1991,6 +1996,9 @@ static void __vb2_queue_cancel(struct vb2_queue *q) ...@@ -1991,6 +1996,9 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
if (q->start_streaming_called) if (q->start_streaming_called)
call_void_qop(q, stop_streaming, q); 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 * If you see this warning, then the driver isn't cleaning up properly
* in stop_streaming(). See the stop_streaming() documentation in * in stop_streaming(). See the stop_streaming() documentation in
...@@ -2102,6 +2110,12 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type) ...@@ -2102,6 +2110,12 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
return -EINVAL; return -EINVAL;
} }
ret = call_qop(q, prepare_streaming, q);
if (ret)
return ret;
q->streaming = 1;
/* /*
* Tell driver to start streaming provided sufficient buffers * Tell driver to start streaming provided sufficient buffers
* are available. * are available.
...@@ -2109,16 +2123,19 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type) ...@@ -2109,16 +2123,19 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
if (q->queued_count >= q->min_buffers_needed) { if (q->queued_count >= q->min_buffers_needed) {
ret = v4l_vb2q_enable_media_source(q); ret = v4l_vb2q_enable_media_source(q);
if (ret) if (ret)
return ret; goto unprepare;
ret = vb2_start_streaming(q); ret = vb2_start_streaming(q);
if (ret) if (ret)
return ret; goto unprepare;
} }
q->streaming = 1;
dprintk(q, 3, "successful\n"); dprintk(q, 3, "successful\n");
return 0; return 0;
unprepare:
call_void_qop(q, unprepare_streaming, q);
q->streaming = 0;
return ret;
} }
EXPORT_SYMBOL_GPL(vb2_core_streamon); EXPORT_SYMBOL_GPL(vb2_core_streamon);
......
...@@ -386,6 +386,12 @@ struct vb2_buffer { ...@@ -386,6 +386,12 @@ struct vb2_buffer {
* the buffer contents will be ignored anyway. * the buffer contents will be ignored anyway.
* @buf_cleanup: called once before the buffer is freed; drivers may * @buf_cleanup: called once before the buffer is freed; drivers may
* perform any additional cleanup; optional. * 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 * @start_streaming: called once to enter 'streaming' state; the driver may
* receive buffers with @buf_queue callback * receive buffers with @buf_queue callback
* before @start_streaming is called; the driver gets the * before @start_streaming is called; the driver gets the
...@@ -405,6 +411,10 @@ struct vb2_buffer { ...@@ -405,6 +411,10 @@ struct vb2_buffer {
* callback by calling vb2_buffer_done() with either * callback by calling vb2_buffer_done() with either
* %VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use * %VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use
* vb2_wait_for_all_buffers() function * 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 * @buf_queue: passes buffer vb to the driver; driver may start
* hardware operation on this buffer; driver should give * hardware operation on this buffer; driver should give
* the buffer back by calling vb2_buffer_done() function; * the buffer back by calling vb2_buffer_done() function;
...@@ -432,8 +442,10 @@ struct vb2_ops { ...@@ -432,8 +442,10 @@ struct vb2_ops {
void (*buf_finish)(struct vb2_buffer *vb); void (*buf_finish)(struct vb2_buffer *vb);
void (*buf_cleanup)(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); int (*start_streaming)(struct vb2_queue *q, unsigned int count);
void (*stop_streaming)(struct vb2_queue *q); void (*stop_streaming)(struct vb2_queue *q);
void (*unprepare_streaming)(struct vb2_queue *q);
void (*buf_queue)(struct vb2_buffer *vb); void (*buf_queue)(struct vb2_buffer *vb);
...@@ -641,8 +653,10 @@ struct vb2_queue { ...@@ -641,8 +653,10 @@ struct vb2_queue {
u32 cnt_queue_setup; u32 cnt_queue_setup;
u32 cnt_wait_prepare; u32 cnt_wait_prepare;
u32 cnt_wait_finish; u32 cnt_wait_finish;
u32 cnt_prepare_streaming;
u32 cnt_start_streaming; u32 cnt_start_streaming;
u32 cnt_stop_streaming; u32 cnt_stop_streaming;
u32 cnt_unprepare_streaming;
#endif #endif
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment