<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for your feedback.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 9 Mar 2023 at 01:14, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com">laurent.pinchart@ideasonboard.com</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">Hi Naush,<br>
<br>
Thank you for the patch.<br>
<br>
I know this has been merged, but I've noticed a few issues, which can be<br>
fixed in further patches.<br>
<br>
On Fri, Feb 24, 2023 at 07:30:23AM +0000, Naushir Patuck via libcamera-devel wrote:<br>
> <br>
> On Raspberry Pi Compute Module platforms, it is possible to attach a<br>
> single camera device only to the secondary Unicam port. The current<br>
> logic of PipelineHandlerRPi::match() will return a failure during<br>
> enumeration of the first Unicam media device (due to no sensor attached,<br>
> or sensor failure) and thus the second Unicam media device will never be<br>
> enumerated.<br>
> <br>
> Fix this by looping over all Unicam instances in PipelineHandlerRPi::match()<br>
> until a camera is correctly registered, or return a failure otherwise.<br>
> <br>
> Reported-on: <a href="https://github.com/raspberrypi/libcamera/issues/44" rel="noreferrer" target="_blank">https://github.com/raspberrypi/libcamera/issues/44</a><br>
> Signed-off-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com" target="_blank">naush@raspberrypi.com</a>><br>
> ---<br>
> .../pipeline/raspberrypi/raspberrypi.cpp | 67 +++++++++++--------<br>
> 1 file changed, 40 insertions(+), 27 deletions(-)<br>
> <br>
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> index 841209548350..ef01b7e166ba 100644<br>
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> @@ -1246,41 +1246,54 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request)<br>
> <br>
> bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> {<br>
> - DeviceMatch unicam("unicam");<br>
> - MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);<br>
> + constexpr unsigned int numUnicamDevices = 2;<br>
<br>
Constants should start with a k prefix, that is kNumUnicamDevices.<br>
<br>
> <br>
> - if (!unicamDevice) {<br>
> - LOG(RPI, Debug) << "Unable to acquire a Unicam instance";<br>
> - return false;<br>
> - }<br>
> + /*<br>
> + * Loop over all Unicam instances, but return out once a match is found.<br>
> + * This is to ensure we correctly enumrate the camera when an instance<br>
> + * of Unicam has registered with media controller, but has not registered<br>
> + * device nodes due to a sensor subdevice failure.<br>
> + */<br>
> + for (unsigned int i = 0; i < numUnicamDevices; i++) {<br>
> + DeviceMatch unicam("unicam");<br>
> + MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);<br>
> <br>
> - DeviceMatch isp("bcm2835-isp");<br>
> - MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);<br>
> + if (!unicamDevice) {<br>
> + LOG(RPI, Debug) << "Unable to acquire a Unicam instance";<br>
> + continue;<br>
<br>
This looks weird, if the unicam device can't be acquired, I don't see<br>
how the next iteration of the loop could successfully acquire another<br>
instance. I would thus break here.<br></blockquote><div><br></div><div>This is probably me not understanding how the media device enumeration stuff<br>works, but I thought the continue would be needed for situations where we want<br>simultaneous dual cameras running in separate processes. For example, process 0<br>acquires "Unicam 0" and starts running as normal. Process 1 starts and goes<br>through match() where "Unicam 0" still exists in the entity list, but fails to<br>acquire because it is locked by process 0. So we have to move on to "Unicam 1"<br>which is acquired correctly for process 1. Is that understanding wrong?<br></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">
<br>
> + }<br>
> <br>
> - if (!ispDevice) {<br>
> - LOG(RPI, Debug) << "Unable to acquire ISP instance";<br>
> - return false;<br>
> - }<br>
> + DeviceMatch isp("bcm2835-isp");<br>
> + MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);<br>
> <br>
> - /*<br>
> - * The loop below is used to register multiple cameras behind one or more<br>
> - * video mux devices that are attached to a particular Unicam instance.<br>
> - * Obviously these cameras cannot be used simultaneously.<br>
> - */<br>
> - unsigned int numCameras = 0;<br>
> - for (MediaEntity *entity : unicamDevice->entities()) {<br>
> - if (entity->function() != MEDIA_ENT_F_CAM_SENSOR)<br>
> + if (!ispDevice) {<br>
> + LOG(RPI, Debug) << "Unable to acquire ISP instance";<br>
> continue;<br>
<br>
Shouldn't you release the unicam device in this case ? I think it would<br>
be better to first loop over unicam instances, ignoring any instance<br>
than has no connected camera sensor, and then, if an instance with a<br>
connected sensor is found, acquire an ISP instance.<br></blockquote><div><br></div><div>I think we discussed this briefly in the github comments. There is no<br>compliment releaseMediaDevice() call that I can use to release the device.<br><br>Regarding the second part of the comment, yes, I could move the isp acquire bit<br>into the for (unicamDevice->entities()) loop to optimise this a bit.<br></div><div><br></div><div>Regards,</div><div>Naush</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">
<br>
> + }<br>
> <br>
> - int ret = registerCamera(unicamDevice, ispDevice, entity);<br>
> - if (ret)<br>
> - LOG(RPI, Error) << "Failed to register camera "<br>
> - << entity->name() << ": " << ret;<br>
> - else<br>
> - numCameras++;<br>
> + /*<br>
> + * The loop below is used to register multiple cameras behind one or more<br>
> + * video mux devices that are attached to a particular Unicam instance.<br>
> + * Obviously these cameras cannot be used simultaneously.<br>
> + */<br>
> + unsigned int numCameras = 0;<br>
> + for (MediaEntity *entity : unicamDevice->entities()) {<br>
> + if (entity->function() != MEDIA_ENT_F_CAM_SENSOR)<br>
> + continue;<br>
> +<br>
> + int ret = registerCamera(unicamDevice, ispDevice, entity);<br>
> + if (ret)<br>
> + LOG(RPI, Error) << "Failed to register camera "<br>
> + << entity->name() << ": " << ret;<br>
> + else<br>
> + numCameras++;<br>
> + }<br>
> +<br>
> + if (numCameras)<br>
> + return true;<br>
> }<br>
> <br>
> - return !!numCameras;<br>
> + return false;<br>
> }<br>
> <br>
> void PipelineHandlerRPi::releaseDevice(Camera *camera)<br>
<br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
</blockquote></div></div>