[libcamera-devel] media: vimc: VIMC multiple streams
Kaaira Gupta
kgupta at es.iitr.ac.in
Wed Jul 22 15:43:04 CEST 2020
This is a patchset by Niklas (https://patchwork.kernel.org/cover/10948831/)
that I have rebased on the current media-tree, I have not added anything
to it and it is just a compressed version of his patchset into a single
patch, based on the latest master to aid testing multiple stream support
in the VIMC pipeline.
Signed-off-by: Kaaira Gupta <kgupta at es.iitr.ac.in>
---
.../media/test-drivers/vimc/vimc-capture.c | 35 ++++++++++++++++++-
.../media/test-drivers/vimc/vimc-debayer.c | 8 +++++
drivers/media/test-drivers/vimc/vimc-scaler.c | 8 +++++
drivers/media/test-drivers/vimc/vimc-sensor.c | 8 +++++
.../media/test-drivers/vimc/vimc-streamer.c | 22 +++++++-----
5 files changed, 71 insertions(+), 10 deletions(-)
diff --git a/drivers/media/test-drivers/vimc/vimc-capture.c b/drivers/media/test-drivers/vimc/vimc-capture.c
index c63496b17b9a..5fc56582af83 100644
--- a/drivers/media/test-drivers/vimc/vimc-capture.c
+++ b/drivers/media/test-drivers/vimc/vimc-capture.c
@@ -237,16 +237,49 @@ static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap,
spin_unlock(&vcap->qlock);
}
+static struct media_entity *vimc_cap_get_sensor(struct vimc_cap_device *vcap)
+{
+ struct media_entity *entity = &vcap->vdev.entity;
+ struct media_device *mdev = entity->graph_obj.mdev;
+ struct media_graph graph;
+
+ mutex_lock(&mdev->graph_mutex);
+ if (media_graph_walk_init(&graph, mdev)) {
+ mutex_unlock(&mdev->graph_mutex);
+ return NULL;
+ }
+
+ media_graph_walk_start(&graph, entity);
+
+ while ((entity = media_graph_walk_next(&graph)))
+ if (entity->function == MEDIA_ENT_F_CAM_SENSOR)
+ break;
+
+ mutex_unlock(&mdev->graph_mutex);
+
+ media_graph_walk_cleanup(&graph);
+
+ return entity;
+}
+
static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
struct media_entity *entity = &vcap->vdev.entity;
+ struct media_pipeline *pipe = NULL;
+ struct media_entity *sensorent;
int ret;
vcap->sequence = 0;
/* Start the media pipeline */
- ret = media_pipeline_start(entity, &vcap->stream.pipe);
+ sensorent = vimc_cap_get_sensor(vcap);
+ if (sensorent && sensorent->pipe)
+ pipe = sensorent->pipe;
+ else
+ pipe = &vcap->stream.pipe;
+
+ ret = media_pipeline_start(entity, pipe);
if (ret) {
vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
return ret;
diff --git a/drivers/media/test-drivers/vimc/vimc-debayer.c b/drivers/media/test-drivers/vimc/vimc-debayer.c
index c3f6fef34f68..93fe19d8d2b4 100644
--- a/drivers/media/test-drivers/vimc/vimc-debayer.c
+++ b/drivers/media/test-drivers/vimc/vimc-debayer.c
@@ -29,6 +29,7 @@ struct vimc_deb_pix_map {
struct vimc_deb_device {
struct vimc_ent_device ved;
struct v4l2_subdev sd;
+ atomic_t use_count;
/* The active format */
struct v4l2_mbus_framefmt sink_fmt;
u32 src_code;
@@ -343,6 +344,9 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
const struct vimc_pix_map *vpix;
unsigned int frame_size;
+ if (atomic_inc_return(&vdeb->use_count) != 1)
+ return 0;
+
if (vdeb->src_frame)
return 0;
@@ -368,6 +372,9 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
return -ENOMEM;
} else {
+ if (atomic_dec_return(&vdeb->use_count) != 0)
+ return 0;
+
if (!vdeb->src_frame)
return 0;
@@ -595,6 +602,7 @@ static struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
vdeb->ved.process_frame = vimc_deb_process_frame;
vdeb->ved.dev = vimc->mdev.dev;
vdeb->mean_win_size = vimc_deb_ctrl_mean_win_size.def;
+ atomic_set(&vdeb->use_count, 0);
/* Initialize the frame format */
vdeb->sink_fmt = sink_fmt_default;
diff --git a/drivers/media/test-drivers/vimc/vimc-scaler.c b/drivers/media/test-drivers/vimc/vimc-scaler.c
index 121fa7d62a2e..9b8458dbe57c 100644
--- a/drivers/media/test-drivers/vimc/vimc-scaler.c
+++ b/drivers/media/test-drivers/vimc/vimc-scaler.c
@@ -25,6 +25,7 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier");
struct vimc_sca_device {
struct vimc_ent_device ved;
struct v4l2_subdev sd;
+ atomic_t use_count;
/* NOTE: the source fmt is the same as the sink
* with the width and hight multiplied by mult
*/
@@ -340,6 +341,9 @@ static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
const struct vimc_pix_map *vpix;
unsigned int frame_size;
+ if (atomic_inc_return(&vsca->use_count) != 1)
+ return 0;
+
if (vsca->src_frame)
return 0;
@@ -363,6 +367,9 @@ static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
return -ENOMEM;
} else {
+ if (atomic_dec_return(&vsca->use_count) != 0)
+ return 0;
+
if (!vsca->src_frame)
return 0;
@@ -506,6 +513,7 @@ static struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
vsca->ved.process_frame = vimc_sca_process_frame;
vsca->ved.dev = vimc->mdev.dev;
+ atomic_set(&vsca->use_count, 0);
/* Initialize the frame format */
vsca->sink_fmt = sink_fmt_default;
diff --git a/drivers/media/test-drivers/vimc/vimc-sensor.c b/drivers/media/test-drivers/vimc/vimc-sensor.c
index a2f09ac9a360..d68113886290 100644
--- a/drivers/media/test-drivers/vimc/vimc-sensor.c
+++ b/drivers/media/test-drivers/vimc/vimc-sensor.c
@@ -18,6 +18,7 @@ struct vimc_sen_device {
struct vimc_ent_device ved;
struct v4l2_subdev sd;
struct tpg_data tpg;
+ atomic_t use_count;
u8 *frame;
/* The active format */
struct v4l2_mbus_framefmt mbus_format;
@@ -201,6 +202,9 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
const struct vimc_pix_map *vpix;
unsigned int frame_size;
+ if (atomic_inc_return(&vsen->use_count) != 1)
+ return 0;
+
/* Calculate the frame size */
vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
frame_size = vsen->mbus_format.width * vpix->bpp *
@@ -219,6 +223,9 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
} else {
+ if (atomic_dec_return(&vsen->use_count) != 0)
+ return 0;
+
vfree(vsen->frame);
vsen->frame = NULL;
}
@@ -359,6 +366,7 @@ static struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc,
vsen->ved.process_frame = vimc_sen_process_frame;
vsen->ved.dev = vimc->mdev.dev;
+ atomic_set(&vsen->use_count, 0);
/* Initialize the frame format */
vsen->mbus_format = fmt_default;
diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
index 451a32c0d034..d5b966a99f7b 100644
--- a/drivers/media/test-drivers/vimc/vimc-streamer.c
+++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
@@ -192,33 +192,35 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
struct vimc_ent_device *ved,
int enable)
{
+ static DEFINE_MUTEX(vimc_streamer_lock);
int ret;
if (!stream || !ved)
return -EINVAL;
+ ret = mutex_lock_interruptible(&vimc_streamer_lock);
+ if (ret)
+ return ret;
+
if (enable) {
if (stream->kthread)
- return 0;
+ goto out;
ret = vimc_streamer_pipeline_init(stream, ved);
if (ret)
- return ret;
+ goto out;
stream->kthread = kthread_run(vimc_streamer_thread, stream,
"vimc-streamer thread");
if (IS_ERR(stream->kthread)) {
ret = PTR_ERR(stream->kthread);
- dev_err(ved->dev, "kthread_run failed with %d\n", ret);
- vimc_streamer_pipeline_terminate(stream);
- stream->kthread = NULL;
- return ret;
+ goto out;
}
} else {
if (!stream->kthread)
- return 0;
+ goto out;
ret = kthread_stop(stream->kthread);
/*
@@ -228,12 +230,14 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
* pipeline.
*/
if (ret)
- dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
+ goto out;
stream->kthread = NULL;
vimc_streamer_pipeline_terminate(stream);
}
+out:
+ mutex_unlock(&vimc_streamer_lock);
- return 0;
+ return ret;
}
--
2.17.1
More information about the libcamera-devel
mailing list