summaryrefslogtreecommitdiffstats
path: root/drivers/media/common/videobuf2/videobuf2-core.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2022-06-22 10:31:44 +0100
committerMauro Carvalho Chehab <mchehab@kernel.org>2022-11-25 07:39:46 +0000
commita10b215325740376ed551814a37d1f8e9d6b1ced (patch)
tree2c0f345e5012b738848cf740aedc4e1386e7e977 /drivers/media/common/videobuf2/videobuf2-core.c
parente9305a003ffeb2adfdd860a659fc65ec82320acc (diff)
downloadlinux-a10b215325740376ed551814a37d1f8e9d6b1ced.tar.bz2
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: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/common/videobuf2/videobuf2-core.c')
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index ab9697f3b5f1..17e2463c054c 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -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);