mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-13 07:19:45 +03:00
libcamera: camera: Use invokeMethod() for pipe_->acquire() and pipe_->release()
The uvcvideo driver needs to open / close its /dev/video# node from pipe_->acquireDevices() / pipe_->releaseDevices(). V4L2VideoDevice::open() creates an EventNotifier and this notifier needs to be created from the CameraManager thread. Use invokeMethod() for pipe_->acquire() and pipe_->release() so that the EventNotifiers are created from the CameraManager thread context. Running pipe_->acquire() and pipe_->release() from the CameraManager thread context serializes all calls to them. Drop PipelineHandler::lock_ this now is no longer necessary and update the "\context" part of the documentation for acquire[Device]() and release[Device]() to match. Note the delayed opening of /dev/video# is a special case because the kernel uvcvideo driver powers on the USB device as soon as /dev/video# is opened. This behavior should *not* be copied by other pipeline handlers. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
c05e45ac77
commit
11e396bf9f
3 changed files with 11 additions and 12 deletions
|
@ -14,7 +14,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <libcamera/base/mutex.h>
|
|
||||||
#include <libcamera/base/object.h>
|
#include <libcamera/base/object.h>
|
||||||
|
|
||||||
#include <libcamera/controls.h>
|
#include <libcamera/controls.h>
|
||||||
|
@ -99,9 +98,7 @@ private:
|
||||||
std::queue<Request *> waitingRequests_;
|
std::queue<Request *> waitingRequests_;
|
||||||
|
|
||||||
const char *name_;
|
const char *name_;
|
||||||
|
unsigned int useCount_;
|
||||||
Mutex lock_;
|
|
||||||
unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);
|
|
||||||
|
|
||||||
friend class PipelineHandlerFactoryBase;
|
friend class PipelineHandlerFactoryBase;
|
||||||
};
|
};
|
||||||
|
|
|
@ -995,7 +995,8 @@ int Camera::acquire()
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret == -EACCES ? -EBUSY : ret;
|
return ret == -EACCES ? -EBUSY : ret;
|
||||||
|
|
||||||
if (!d->pipe_->acquire(this)) {
|
if (!d->pipe_->invokeMethod(&PipelineHandler::acquire,
|
||||||
|
ConnectionTypeBlocking, this)) {
|
||||||
LOG(Camera, Info)
|
LOG(Camera, Info)
|
||||||
<< "Pipeline handler in use by another process";
|
<< "Pipeline handler in use by another process";
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -1030,7 +1031,8 @@ int Camera::release()
|
||||||
return ret == -EACCES ? -EBUSY : ret;
|
return ret == -EACCES ? -EBUSY : ret;
|
||||||
|
|
||||||
if (d->isAcquired())
|
if (d->isAcquired())
|
||||||
d->pipe_->release(this);
|
d->pipe_->invokeMethod(&PipelineHandler::release,
|
||||||
|
ConnectionTypeBlocking, this);
|
||||||
|
|
||||||
d->setState(Private::CameraAvailable);
|
d->setState(Private::CameraAvailable);
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
|
||||||
* Pipeline handlers shall not call this function directly as the Camera class
|
* Pipeline handlers shall not call this function directly as the Camera class
|
||||||
* handles access internally.
|
* handles access internally.
|
||||||
*
|
*
|
||||||
* \context This function is \threadsafe.
|
* \context This function is called from the CameraManager thread.
|
||||||
*
|
*
|
||||||
* \return True if the pipeline handler was acquired, false if another process
|
* \return True if the pipeline handler was acquired, false if another process
|
||||||
* has already acquired it
|
* has already acquired it
|
||||||
|
@ -165,8 +165,6 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
|
||||||
*/
|
*/
|
||||||
bool PipelineHandler::acquire(Camera *camera)
|
bool PipelineHandler::acquire(Camera *camera)
|
||||||
{
|
{
|
||||||
MutexLocker locker(lock_);
|
|
||||||
|
|
||||||
if (useCount_ == 0) {
|
if (useCount_ == 0) {
|
||||||
for (std::shared_ptr<MediaDevice> &media : mediaDevices_) {
|
for (std::shared_ptr<MediaDevice> &media : mediaDevices_) {
|
||||||
if (!media->lock()) {
|
if (!media->lock()) {
|
||||||
|
@ -199,14 +197,12 @@ bool PipelineHandler::acquire(Camera *camera)
|
||||||
* Pipeline handlers shall not call this function directly as the Camera class
|
* Pipeline handlers shall not call this function directly as the Camera class
|
||||||
* handles access internally.
|
* handles access internally.
|
||||||
*
|
*
|
||||||
* \context This function is \threadsafe.
|
* \context This function is called from the CameraManager thread.
|
||||||
*
|
*
|
||||||
* \sa acquire()
|
* \sa acquire()
|
||||||
*/
|
*/
|
||||||
void PipelineHandler::release(Camera *camera)
|
void PipelineHandler::release(Camera *camera)
|
||||||
{
|
{
|
||||||
MutexLocker locker(lock_);
|
|
||||||
|
|
||||||
ASSERT(useCount_);
|
ASSERT(useCount_);
|
||||||
|
|
||||||
releaseDevice(camera);
|
releaseDevice(camera);
|
||||||
|
@ -230,6 +226,8 @@ void PipelineHandler::release(Camera *camera)
|
||||||
* powers on the USB device as soon as /dev/video# is opened. This behavior
|
* powers on the USB device as soon as /dev/video# is opened. This behavior
|
||||||
* should *not* be copied by other pipeline handlers.
|
* should *not* be copied by other pipeline handlers.
|
||||||
*
|
*
|
||||||
|
* \context This function is called from the CameraManager thread.
|
||||||
|
*
|
||||||
* \return True on success, false on failure
|
* \return True on success, false on failure
|
||||||
* \sa releaseDevice()
|
* \sa releaseDevice()
|
||||||
*/
|
*/
|
||||||
|
@ -250,6 +248,8 @@ bool PipelineHandler::acquireDevice([[maybe_unused]] Camera *camera)
|
||||||
* release them until releaseDevice() has been called for all previously
|
* release them until releaseDevice() has been called for all previously
|
||||||
* acquired cameras.
|
* acquired cameras.
|
||||||
*
|
*
|
||||||
|
* \context This function is called from the CameraManager thread.
|
||||||
|
*
|
||||||
* \sa acquireDevice()
|
* \sa acquireDevice()
|
||||||
*/
|
*/
|
||||||
void PipelineHandler::releaseDevice([[maybe_unused]] Camera *camera)
|
void PipelineHandler::releaseDevice([[maybe_unused]] Camera *camera)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue