libcamera: Allow concurrent use of cameras from same pipeline handler

libcamera implements a pipeline handler locking mechanism based on
advisory locks on media devices, to prevent concurrent access to cameras
from the same pipeline handler from different processes (this only works
between multiple libcamera instances, as other processes won't use
advisory locks on media devices).

A side effect of the implementation prevents multiple cameras created by
the same pipeline handler from being used concurrently. Fix this by
turning the PipelineHandler lock() and unlock() functions into acquire()
and release(), with a use count to replace the boolean lock flag. The
Camera class is updated accordingly.

As a consequence of this change, the IPU3 pipeline handler will fail to
operate properly when the cameras it exposes are operated concurrently.
The android.hardware.camera2.cts.MultiViewTest#testDualCameraPreview
test fails as a result. This should be fixed in the IPU3 pipeline
handler to implement mutual exclusion between cameras.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-by: David Plowman <david.plowman@raspberrypi.com>
This commit is contained in:
Laurent Pinchart
2022-08-10 20:33:28 +03:00
parent 434edb7b44
commit dfc6d711c9
4 changed files with 55 additions and 29 deletions
+9 -3
View File
@@ -508,6 +508,11 @@ static const char *const camera_state_names[] = {
"Running",
};
bool Camera::Private::isAcquired() const
{
return state_.load(std::memory_order_acquire) == CameraRunning;
}
bool Camera::Private::isRunning() const
{
return state_.load(std::memory_order_acquire) == CameraRunning;
@@ -811,7 +816,7 @@ int Camera::exportFrameBuffers(Stream *stream,
* not blocking, if the device has already been acquired (by the same or another
* process) the -EBUSY error code is returned.
*
* Acquiring a camera will limit usage of any other camera(s) provided by the
* Acquiring a camera may limit usage of any other camera(s) provided by the
* same pipeline handler to the same instance of libcamera. The limit is in
* effect until all cameras from the pipeline handler are released. Other
* instances of libcamera can still list and examine the cameras but will fail
@@ -839,7 +844,7 @@ int Camera::acquire()
if (ret < 0)
return ret == -EACCES ? -EBUSY : ret;
if (!d->pipe_->lock()) {
if (!d->pipe_->acquire()) {
LOG(Camera, Info)
<< "Pipeline handler in use by another process";
return -EBUSY;
@@ -873,7 +878,8 @@ int Camera::release()
if (ret < 0)
return ret == -EACCES ? -EBUSY : ret;
d->pipe_->unlock();
if (d->isAcquired())
d->pipe_->release();
d->setState(Private::CameraAvailable);