diff options
Diffstat (limited to 'src/qcam/assets/feathericons/meh.svg')
0 files changed, 0 insertions, 0 deletions
index : libcamera/vivid.git | ||
libcamera pipeline handler for VIVID | git repository hosting on libcamera.org |
summaryrefslogtreecommitdiff |
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2018, Google Inc.
*
* camera_manager.h - Camera management
*/
#include <libcamera/camera_manager.h>
#include <condition_variable>
#include <map>
#include <libcamera/camera.h>
#include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/process.h"
#include "libcamera/internal/thread.h"
#include "libcamera/internal/utils.h"
/**
* \file camera_manager.h
* \brief The camera manager
*/
/**
* \brief Top-level libcamera namespace
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(Camera)
class CameraManager::Private : public Extensible::Private, public Thread
{
LIBCAMERA_DECLARE_PUBLIC(CameraManager)
public:
Private(CameraManager *cm);
int start();
void addCamera(std::shared_ptr<Camera> camera,
const std::vector<dev_t> &devnums);
void removeCamera(Camera *camera);
/*
* This mutex protects
*
* - initialized_ and status_ during initialization
* - cameras_ and camerasByDevnum_ after initialization
*/
mutable Mutex mutex_;
std::vector<std::shared_ptr<Camera>> cameras_;
std::map<dev_t, std::weak_ptr<Camera>> camerasByDevnum_;
protected:
void run() override;
private:
int init();
void createPipelineHandlers();
void cleanup();
std::condition_variable cv_;
bool initialized_;
int status_;
std::unique_ptr<DeviceEnumerator> enumerator_;
IPAManager ipaManager_;
ProcessManager processManager_;
};
CameraManager::Private::Private(CameraManager *cm)
: Extensible::Private(cm), initialized_(false)
{
}
int CameraManager::Private::start()
{
int status;
/* Start the thread and wait for initialization to complete. */
Thread::start();
{
MutexLocker locker(mutex_);
cv_.wait(locker, [&] { return initialized_; });
status = status_;
}
/* If a failure happened during initialization, stop the thread. */
if (status < 0) {
exit();
wait();
return status;
}
return 0;
}
void CameraManager::Private::run()
{
LOG(Camera, Debug) << "Starting camera manager";
int ret = init();
mutex_.lock();
status_ = ret;
initialized_ = true;
mutex_.unlock();
cv_.notify_one();
if (ret < 0)
return;
/* Now start processing events and messages. */
exec();
cleanup();
}
int CameraManager::Private::init()
{
enumerator_ = DeviceEnumerator::create();
if (!enumerator_ || enumerator_->enumerate())
return -ENODEV;
createPipelineHandlers();
return 0;
}
void CameraManager::Private::createPipelineHandlers()
{
CameraManager *const o = LIBCAMERA_O_PTR();
/*
* \todo Try to read handlers and order from configuration
* file and only fallback on all handlers if there is no
* configuration file.
*/
std::vector<PipelineHandlerFactory *> &factories =
PipelineHandlerFactory::factories();
for (PipelineHandlerFactory *factory : factories) {
LOG(Camera, Debug)
<< "Found registered pipeline handler '"
<< factory->name() << "'";
/*
* Try each pipeline handler until it exhaust
* all pipelines it can provide.
*/
while (1) {
std::shared_ptr<PipelineHandler> pipe = factory->create(o);
if (!pipe->match(enumerator_.get()))
break;
LOG(Camera, Debug)
<< "Pipeline handler \"" << factory->name()
<< "\" matched";
}
}
enumerator_->devicesAdded.connect(this, &Private::createPipelineHandlers);
}
void CameraManager::Private::cleanup()
{
enumerator_->devicesAdded.disconnect(this, &Private::createPipelineHandlers);
/*
* Release all references to cameras to ensure they all get destroyed
* before the device enumerator deletes the media devices. Cameras are
* destroyed via Object::deleteLater() API, hence we need to explicitly
* process deletion requests from the thread's message queue as the event
* loop is not in action here.
*/
cameras_.clear();
dispatchMessages(Message::Type::DeferredDelete);
enumerator_.reset(nullptr);
}
void CameraManager::Private::addCamera(std::shared_ptr<Camera> camera,
const std::vector<dev_t> &devnums)
{
MutexLocker locker(mutex_);
for (std::shared_ptr<Camera> c : cameras_) {
if (c->id() == camera->id()) {
LOG(Camera, Fatal)
<< "Trying to register a camera with a duplicated ID '"
<< camera->id() << "'";
return;
}
}
cameras_.push_back(std::move(camera));
unsigned int index = cameras_.size() - 1;
for (dev_t devnum : devnums)
camerasByDevnum_[devnum] = cameras_[index];
}
void CameraManager::Private::removeCamera(Camera *camera)
{
MutexLocker locker(mutex_);
auto iter = std::find_if(cameras_.begin(), cameras_.end(),
[camera](std::shared_ptr<Camera> &c) {
return c.get() == camera;
});
if (iter == cameras_.end())
return;
LOG(Camera, Debug)
<< "Unregistering camera '" << camera->id() << "'";
auto iter_d = std::find_if(camerasByDevnum_.begin(), camerasByDevnum_.end(),
[camera](const std::pair<dev_t, std::weak_ptr<Camera>> &p) {
return p.second.lock().get() == camera;
});
if (iter_d != camerasByDevnum_.end())
camerasByDevnum_.erase(iter_d);
cameras_.erase(iter);
}
/**
* \class CameraManager
* \brief Provide access and manage all cameras in the system
*
* The camera manager is the entry point to libcamera. It enumerates devices,
* associates them with pipeline managers, and provides access to the cameras
* in the system to applications. The manager owns all Camera objects and
* handles hot-plugging and hot-unplugging to manage the lifetime of cameras.
*
* To interact with libcamera, an application starts by creating a camera
* manager instance. Only a single instance of the camera manager may exist at
* a time. Attempting to create a second instance without first deleting the
* existing instance results in undefined behaviour.
*
* The manager is initially stopped, and shall be started with start(). This
* will enumerate all the cameras present in the system, which can then be
* listed with list() and retrieved with get().
*
* Cameras are shared through std::shared_ptr<>, ensuring that a camera will
* stay valid until the last reference is released without requiring any special
* action from the application. Once the application has released all the
* references it held to cameras, the camera manager can be stopped with
* stop().
*