pipeline: uvcvideo: Implement acquireDevice() + releaseDevice()
The uvcvideo pipeline handler always keeps the uvcvideo /dev/video# node for a pipeline open after enumerating the camera. This is a problem for uvcvideo, as keeping the /dev/video# node open stops the underlying USB device and the USB bus controller from being able to enter runtime-suspend causing significant unnecessary power-usage. Implement acquireDevice() + releaseDevice(), openening /dev/video# on acquire and closing it on release to fix this. And make validate do a local video_->open() + close() around validate() when not open yet, to keep validate() working on unacquired cameras. Bug: https://bugs.libcamera.org/show_bug.cgi?id=168 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
11e396bf9f
commit
7a36d05795
1 changed files with 51 additions and 3 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include <libcamera/base/log.h>
|
#include <libcamera/base/log.h>
|
||||||
|
#include <libcamera/base/mutex.h>
|
||||||
#include <libcamera/base/utils.h>
|
#include <libcamera/base/utils.h>
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
|
@ -48,6 +49,7 @@ public:
|
||||||
|
|
||||||
const std::string &id() const { return id_; }
|
const std::string &id() const { return id_; }
|
||||||
|
|
||||||
|
Mutex openLock_;
|
||||||
std::unique_ptr<V4L2VideoDevice> video_;
|
std::unique_ptr<V4L2VideoDevice> video_;
|
||||||
Stream stream_;
|
Stream stream_;
|
||||||
std::map<PixelFormat, std::vector<SizeRange>> formats_;
|
std::map<PixelFormat, std::vector<SizeRange>> formats_;
|
||||||
|
@ -93,6 +95,9 @@ private:
|
||||||
const ControlValue &value);
|
const ControlValue &value);
|
||||||
int processControls(UVCCameraData *data, Request *request);
|
int processControls(UVCCameraData *data, Request *request);
|
||||||
|
|
||||||
|
bool acquireDevice(Camera *camera) override;
|
||||||
|
void releaseDevice(Camera *camera) override;
|
||||||
|
|
||||||
UVCCameraData *cameraData(Camera *camera)
|
UVCCameraData *cameraData(Camera *camera)
|
||||||
{
|
{
|
||||||
return static_cast<UVCCameraData *>(camera->_d());
|
return static_cast<UVCCameraData *>(camera->_d());
|
||||||
|
@ -158,9 +163,29 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()
|
||||||
format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);
|
format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);
|
||||||
format.size = cfg.size;
|
format.size = cfg.size;
|
||||||
|
|
||||||
int ret = data_->video_->tryFormat(&format);
|
/*
|
||||||
if (ret)
|
* For power-consumption reasons video_ is closed when the camera is not
|
||||||
return Invalid;
|
* acquired. Open it here if necessary.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
bool opened = false;
|
||||||
|
|
||||||
|
MutexLocker locker(data_->openLock_);
|
||||||
|
|
||||||
|
if (!data_->video_->isOpen()) {
|
||||||
|
int ret = data_->video_->open();
|
||||||
|
if (ret)
|
||||||
|
return Invalid;
|
||||||
|
|
||||||
|
opened = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = data_->video_->tryFormat(&format);
|
||||||
|
if (opened)
|
||||||
|
data_->video_->close();
|
||||||
|
if (ret)
|
||||||
|
return Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
cfg.stride = format.planes[0].bpl;
|
cfg.stride = format.planes[0].bpl;
|
||||||
cfg.frameSize = format.planes[0].size;
|
cfg.frameSize = format.planes[0].size;
|
||||||
|
@ -411,6 +436,23 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PipelineHandlerUVC::acquireDevice(Camera *camera)
|
||||||
|
{
|
||||||
|
UVCCameraData *data = cameraData(camera);
|
||||||
|
|
||||||
|
MutexLocker locker(data->openLock_);
|
||||||
|
|
||||||
|
return data->video_->open() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipelineHandlerUVC::releaseDevice(Camera *camera)
|
||||||
|
{
|
||||||
|
UVCCameraData *data = cameraData(camera);
|
||||||
|
|
||||||
|
MutexLocker locker(data->openLock_);
|
||||||
|
data->video_->close();
|
||||||
|
}
|
||||||
|
|
||||||
int UVCCameraData::init(MediaDevice *media)
|
int UVCCameraData::init(MediaDevice *media)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -512,6 +554,12 @@ int UVCCameraData::init(MediaDevice *media)
|
||||||
|
|
||||||
controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
|
controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Close to allow camera to go into runtime-suspend, video_ will be
|
||||||
|
* re-opened from acquireDevice() and validate().
|
||||||
|
*/
|
||||||
|
video_->close();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue