<div dir="ltr"><div dir="ltr">Hi,</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, May 18, 2019 at 4:16 AM Niklas Söderlund <<a href="mailto:niklas.soderlund%2Brenesas@ragnatech.se">niklas.soderlund+renesas@ragnatech.se</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A sensor which is running is already part of a pipeline and trying to<br>
start a new pipeline is not possible. This prevents two capture devices<br>
connected to the same sensor from running at the same time.<br>
<br>
Instead of failing to start the second capture device allow it to join<br>
the already running pipeline by looking it up at the sensor. This allows<br>
two (or more) capture devices to independently be started and stopped<br>
while still being connected to the same sensor.<br>
<br>
Signed-off-by: Niklas Söderlund <<a href="mailto:niklas.soderlund@ragnatech.se" target="_blank">niklas.soderlund@ragnatech.se</a>><br>
---<br>
 drivers/media/platform/vimc/vimc-capture.c | 35 +++++++++++++++++++++-<br>
 1 file changed, 34 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c<br>
index e7d0fc2228a6f0c1..f9eb1e327e311b4a 100644<br>
--- a/drivers/media/platform/vimc/vimc-capture.c<br>
+++ b/drivers/media/platform/vimc/vimc-capture.c<br>
@@ -264,16 +264,49 @@ static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap,<br>
        spin_unlock(&vcap->qlock);<br>
 }<br>
<br>
+static struct media_entity *vimc_cap_get_sensor(struct vimc_cap_device *vcap)<br>
+{<br>
+       struct media_entity *entity = &vcap->vdev.entity;<br>
+       struct media_device *mdev = entity->graph_obj.mdev;<br>
+       struct media_graph graph;<br>
+<br>
+       mutex_lock(&mdev->graph_mutex);<br>
+       if (media_graph_walk_init(&graph, mdev)) {<br></blockquote><div>adding error debug?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+               mutex_unlock(&mdev->graph_mutex);<br>
+               return NULL;<br>
+       } </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+       media_graph_walk_start(&graph, entity);<br>
+<br>
+       while ((entity = media_graph_walk_next(&graph)))<br>
+               if (entity->function == MEDIA_ENT_F_CAM_SENSOR)<br>
+                       break;<br>
+<br>
+       mutex_unlock(&mdev->graph_mutex);<br>
+<br>
+       media_graph_walk_cleanup(&graph);<br>
+<br>
+       return entity;<br>
+}<br>
+<br></blockquote><div>Iterating the pipeline from the capture back to the source is already done int the function vimc_streamer_pipeline_init</div><div>but there it iterates it using the media_entity_remote_pad function and not with the graph_walk api, so better use the same</div><div>form of iteration in both places.</div><div>In addition, the vimc streamer code uses the function vimc_is_source to check that the source is reached instead of MEDIA_ENT_F_CAM_SENSOR</div><div>so better be consistent with that too.</div><div>Last, I think it is enough to iterate back until an entity with non NULL pipe pointer is reached.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)<br>
 {<br>
        struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);<br>
        struct media_entity *entity = &vcap->vdev.entity;<br>
+       struct media_pipeline *pipe = NULL;<br>
+       struct media_entity *sensorent;<br></blockquote><div>better call it sensor_ent,  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
        int ret;<br>
<br>
        vcap->sequence = 0;<br>
<br>
        /* Start the media pipeline */<br>
-       ret = media_pipeline_start(entity, &vcap->stream.pipe);<br>
+       sensorent = vimc_cap_get_sensor(vcap);<br>
+       if (sensorent && sensorent->pipe)<br></blockquote><div>if sensorent is null, this must be an error so better change the code to something like</div><div>if (!sensorent) {</div><div>        dev_err("err blabla");</div><div>        ret -EPIPE;</div><div>} </div><div>if(seneorent->pipe)</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+               pipe = sensorent->pipe;<br>
+       else<br>
+               pipe = &vcap->stream.pipe;<br>
+<br></blockquote><div>and with the new code this can be one line with the "? :" operator.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+       ret = media_pipeline_start(entity, pipe);<br>
        if (ret) {<br>
                vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);<br>
                return ret;<br>
-- <br></blockquote><div>Thanks,</div><div>Dafna </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
2.21.0<br>
<br>
</blockquote></div></div>