mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-12 23:09:45 +03:00
libcamera: camera_sensor: Introduce CameraSensorFactory
Introduce a factory to create CameraSensor derived classes instances by inspecting the sensor media entity name and provide a convenience macro to register specialized sensor handlers. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
27cece6653
commit
6ba23735b9
12 changed files with 233 additions and 40 deletions
|
@ -38,7 +38,6 @@ enum class Orientation;
|
||||||
class CameraSensor : protected Loggable
|
class CameraSensor : protected Loggable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CameraSensor(const MediaEntity *entity);
|
|
||||||
~CameraSensor();
|
~CameraSensor();
|
||||||
|
|
||||||
int init();
|
int init();
|
||||||
|
@ -81,6 +80,7 @@ public:
|
||||||
int setTestPatternMode(controls::draft::TestPatternModeEnum mode);
|
int setTestPatternMode(controls::draft::TestPatternModeEnum mode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
explicit CameraSensor(const MediaEntity *entity);
|
||||||
std::string logPrefix() const override;
|
std::string logPrefix() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -122,4 +122,50 @@ private:
|
||||||
std::unique_ptr<CameraLens> focusLens_;
|
std::unique_ptr<CameraLens> focusLens_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CameraSensorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CameraSensorFactoryBase();
|
||||||
|
virtual ~CameraSensorFactoryBase() = default;
|
||||||
|
|
||||||
|
static std::unique_ptr<CameraSensor> create(MediaEntity *entity);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorFactoryBase)
|
||||||
|
|
||||||
|
static std::vector<CameraSensorFactoryBase *> &factories();
|
||||||
|
|
||||||
|
static void registerFactory(CameraSensorFactoryBase *factory);
|
||||||
|
|
||||||
|
virtual bool match(const MediaEntity *entity) const = 0;
|
||||||
|
|
||||||
|
virtual std::unique_ptr<CameraSensor>
|
||||||
|
createInstance(MediaEntity *entity) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename _CameraSensor>
|
||||||
|
class CameraSensorFactory final : public CameraSensorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CameraSensorFactory()
|
||||||
|
: CameraSensorFactoryBase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool match(const MediaEntity *entity) const override
|
||||||
|
{
|
||||||
|
return _CameraSensor::match(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CameraSensor>
|
||||||
|
createInstance(MediaEntity *entity) const override
|
||||||
|
{
|
||||||
|
return _CameraSensor::create(entity);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REGISTER_CAMERA_SENSOR(sensor) \
|
||||||
|
static CameraSensorFactory<sensor> global_##sensor##Factory{};
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -157,11 +157,10 @@ PipelineHandlerISI *ISICameraData::pipe()
|
||||||
/* Open and initialize pipe components. */
|
/* Open and initialize pipe components. */
|
||||||
int ISICameraData::init()
|
int ISICameraData::init()
|
||||||
{
|
{
|
||||||
int ret = sensor_->init();
|
if (!sensor_)
|
||||||
if (ret)
|
return -ENODEV;
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = csis_->open();
|
int ret = csis_->open();
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1057,7 +1056,7 @@ bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)
|
||||||
std::unique_ptr<ISICameraData> data =
|
std::unique_ptr<ISICameraData> data =
|
||||||
std::make_unique<ISICameraData>(this);
|
std::make_unique<ISICameraData>(this);
|
||||||
|
|
||||||
data->sensor_ = std::make_unique<CameraSensor>(sensor);
|
data->sensor_ = CameraSensorFactoryBase::create(sensor);
|
||||||
data->csis_ = std::make_unique<V4L2Subdevice>(csi);
|
data->csis_ = std::make_unique<V4L2Subdevice>(csi);
|
||||||
data->xbarSink_ = sink;
|
data->xbarSink_ = sink;
|
||||||
|
|
||||||
|
|
|
@ -134,10 +134,9 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index)
|
||||||
|
|
||||||
MediaLink *link = links[0];
|
MediaLink *link = links[0];
|
||||||
MediaEntity *sensorEntity = link->source()->entity();
|
MediaEntity *sensorEntity = link->source()->entity();
|
||||||
sensor_ = std::make_unique<CameraSensor>(sensorEntity);
|
sensor_ = CameraSensorFactoryBase::create(sensorEntity);
|
||||||
ret = sensor_->init();
|
if (!sensor_)
|
||||||
if (ret)
|
return -ENODEV;
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = link->setEnabled(true);
|
ret = link->setEnabled(true);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -141,9 +141,8 @@ int MaliC55CameraData::init()
|
||||||
* Register a CameraSensor if we connect to a sensor and create
|
* Register a CameraSensor if we connect to a sensor and create
|
||||||
* an entity for the connected CSI-2 receiver.
|
* an entity for the connected CSI-2 receiver.
|
||||||
*/
|
*/
|
||||||
sensor_ = std::make_unique<CameraSensor>(entity_);
|
sensor_ = CameraSensorFactoryBase::create(entity_);
|
||||||
ret = sensor_->init();
|
if (!sensor_)
|
||||||
if (ret)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
const MediaPad *sourcePad = entity_->getPadByIndex(0);
|
const MediaPad *sourcePad = entity_->getPadByIndex(0);
|
||||||
|
|
|
@ -1232,10 +1232,9 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
|
||||||
std::make_unique<RkISP1CameraData>(this, &mainPath_,
|
std::make_unique<RkISP1CameraData>(this, &mainPath_,
|
||||||
hasSelfPath_ ? &selfPath_ : nullptr);
|
hasSelfPath_ ? &selfPath_ : nullptr);
|
||||||
|
|
||||||
data->sensor_ = std::make_unique<CameraSensor>(sensor);
|
data->sensor_ = CameraSensorFactoryBase::create(sensor);
|
||||||
ret = data->sensor_->init();
|
if (!data->sensor_)
|
||||||
if (ret)
|
return -ENODEV;
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* Initialize the camera properties. */
|
/* Initialize the camera properties. */
|
||||||
data->properties_ = data->sensor_->properties();
|
data->properties_ = data->sensor_->properties();
|
||||||
|
|
|
@ -790,13 +790,10 @@ int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &camera
|
||||||
CameraData *data = cameraData.get();
|
CameraData *data = cameraData.get();
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
data->sensor_ = std::make_unique<CameraSensor>(sensorEntity);
|
data->sensor_ = CameraSensorFactoryBase::create(sensorEntity);
|
||||||
if (!data->sensor_)
|
if (!data->sensor_)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (data->sensor_->init())
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Populate the map of sensor supported formats and sizes. */
|
/* Populate the map of sensor supported formats and sizes. */
|
||||||
for (auto const mbusCode : data->sensor_->mbusCodes())
|
for (auto const mbusCode : data->sensor_->mbusCodes())
|
||||||
data->sensorFormats_.emplace(mbusCode,
|
data->sensorFormats_.emplace(mbusCode,
|
||||||
|
|
|
@ -388,8 +388,6 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,
|
||||||
MediaEntity *sensor)
|
MediaEntity *sensor)
|
||||||
: Camera::Private(pipe), streams_(numStreams)
|
: Camera::Private(pipe), streams_(numStreams)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the shortest path from the camera sensor to a video capture
|
* Find the shortest path from the camera sensor to a video capture
|
||||||
* device using the breadth-first search algorithm. This heuristic will
|
* device using the breadth-first search algorithm. This heuristic will
|
||||||
|
@ -480,12 +478,9 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally also remember the sensor. */
|
/* Finally also remember the sensor. */
|
||||||
sensor_ = std::make_unique<CameraSensor>(sensor);
|
sensor_ = CameraSensorFactoryBase::create(sensor);
|
||||||
ret = sensor_->init();
|
if (!sensor_)
|
||||||
if (ret) {
|
|
||||||
sensor_.reset();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
LOG(SimplePipeline, Debug)
|
LOG(SimplePipeline, Debug)
|
||||||
<< "Found pipeline: "
|
<< "Found pipeline: "
|
||||||
|
|
|
@ -532,10 +532,9 @@ int VimcCameraData::init()
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Create and open the camera sensor, debayer, scaler and video device. */
|
/* Create and open the camera sensor, debayer, scaler and video device. */
|
||||||
sensor_ = std::make_unique<CameraSensor>(media_->getEntityByName("Sensor B"));
|
sensor_ = CameraSensorFactoryBase::create(media_->getEntityByName("Sensor B"));
|
||||||
ret = sensor_->init();
|
if (!sensor_)
|
||||||
if (ret)
|
return -ENODEV;
|
||||||
return ret;
|
|
||||||
|
|
||||||
debayer_ = V4L2Subdevice::fromEntityName(media_, "Debayer B");
|
debayer_ = V4L2Subdevice::fromEntityName(media_, "Debayer B");
|
||||||
if (debayer_->open())
|
if (debayer_->open())
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <map>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <libcamera/base/utils.h>
|
#include <libcamera/base/utils.h>
|
||||||
|
@ -1202,4 +1203,165 @@ std::string CameraSensor::logPrefix() const
|
||||||
return "'" + entity_->name() + "'";
|
return "'" + entity_->name() + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* Transitory default camera sensor implementation */
|
||||||
|
class CameraSensorDefault : public CameraSensor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CameraSensorDefault(MediaEntity *entity)
|
||||||
|
: CameraSensor(entity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool match([[maybe_unused]] const MediaEntity *entity)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<CameraSensorDefault> create(MediaEntity *entity)
|
||||||
|
{
|
||||||
|
std::unique_ptr<CameraSensorDefault> sensor =
|
||||||
|
std::make_unique<CameraSensorDefault>(entity);
|
||||||
|
|
||||||
|
if (sensor->init())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return sensor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_CAMERA_SENSOR(CameraSensorDefault)
|
||||||
|
|
||||||
|
}; /* namespace */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CameraSensorFactoryBase
|
||||||
|
* \brief Base class for camera sensor factories
|
||||||
|
*
|
||||||
|
* The CameraSensorFactoryBase class is the base of all specializations of
|
||||||
|
* the CameraSensorFactory class template. It implements the factory
|
||||||
|
* registration, maintains a registry of factories, and provides access to the
|
||||||
|
* registered factories.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Construct a camera sensor factory base
|
||||||
|
*
|
||||||
|
* Creating an instance of the factory base registers it with the global list of
|
||||||
|
* factories, accessible through the factories() function.
|
||||||
|
*/
|
||||||
|
CameraSensorFactoryBase::CameraSensorFactoryBase()
|
||||||
|
{
|
||||||
|
registerFactory(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Create an instance of the CameraSensor corresponding to a media entity
|
||||||
|
* \param[in] entity The media entity on the source end of the sensor
|
||||||
|
*
|
||||||
|
* \return A unique pointer to a new instance of the CameraSensor subclass
|
||||||
|
* matching the entity, or a null pointer if no such factory exists
|
||||||
|
*/
|
||||||
|
std::unique_ptr<CameraSensor> CameraSensorFactoryBase::create(MediaEntity *entity)
|
||||||
|
{
|
||||||
|
const std::vector<CameraSensorFactoryBase *> &factories =
|
||||||
|
CameraSensorFactoryBase::factories();
|
||||||
|
|
||||||
|
for (const CameraSensorFactoryBase *factory : factories) {
|
||||||
|
if (!factory->match(entity))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::unique_ptr<CameraSensor> sensor = factory->createInstance(entity);
|
||||||
|
if (!sensor) {
|
||||||
|
LOG(CameraSensor, Error)
|
||||||
|
<< "Failed to create sensor for '"
|
||||||
|
<< entity->name();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve the list of all camera sensor factories
|
||||||
|
* \return The list of camera sensor factories
|
||||||
|
*/
|
||||||
|
std::vector<CameraSensorFactoryBase *> &CameraSensorFactoryBase::factories()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The static factories map is defined inside the function to ensure
|
||||||
|
* it gets initialized on first use, without any dependency on link
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
static std::vector<CameraSensorFactoryBase *> factories;
|
||||||
|
return factories;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a camera sensor class to the registry
|
||||||
|
* \param[in] factory Factory to use to construct the camera sensor
|
||||||
|
*/
|
||||||
|
void CameraSensorFactoryBase::registerFactory(CameraSensorFactoryBase *factory)
|
||||||
|
{
|
||||||
|
std::vector<CameraSensorFactoryBase *> &factories =
|
||||||
|
CameraSensorFactoryBase::factories();
|
||||||
|
|
||||||
|
factories.push_back(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CameraSensorFactory
|
||||||
|
* \brief Registration of CameraSensorFactory classes and creation of instances
|
||||||
|
* \tparam _CameraSensor The camera sensor class type for this factory
|
||||||
|
*
|
||||||
|
* To facilitate discovery and instantiation of CameraSensor classes, the
|
||||||
|
* CameraSensorFactory class implements auto-registration of camera sensors.
|
||||||
|
* Each CameraSensor subclass shall register itself using the
|
||||||
|
* REGISTER_CAMERA_SENSOR() macro, which will create a corresponding instance
|
||||||
|
* of a CameraSensorFactory subclass and register it with the static list of
|
||||||
|
* factories.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn CameraSensorFactory::CameraSensorFactory()
|
||||||
|
* \brief Construct a camera sensor factory
|
||||||
|
*
|
||||||
|
* Creating an instance of the factory registers it with the global list of
|
||||||
|
* factories, accessible through the CameraSensorFactoryBase::factories()
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn CameraSensorFactory::createInstance() const
|
||||||
|
* \brief Create an instance of the CameraSensor corresponding to the factory
|
||||||
|
*
|
||||||
|
* \return A unique pointer to a newly constructed instance of the CameraSensor
|
||||||
|
* subclass corresponding to the factory
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \def REGISTER_CAMERA_SENSOR(sensor)
|
||||||
|
* \brief Register a camera sensor type to the sensor factory
|
||||||
|
* \param[in] sensor Class name of the CameraSensor derived class to register
|
||||||
|
*
|
||||||
|
* Register a CameraSensor subclass with the factory and make it available to
|
||||||
|
* try and match sensors. The subclass needs to implement two static functions:
|
||||||
|
*
|
||||||
|
* \code{.cpp}
|
||||||
|
* static bool match(const MediaEntity *entity);
|
||||||
|
* static std::unique_ptr<sensor> create(MediaEntity *entity);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* The match() function tests if the sensor class supports the camera sensor
|
||||||
|
* identified by a MediaEntity.
|
||||||
|
*
|
||||||
|
* The create() function creates a new instance of the sensor class. It may
|
||||||
|
* return a null pointer if initialization of the instance fails. It will only
|
||||||
|
* be called if the match() function has returned true for the given entity.
|
||||||
|
*/
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -52,8 +52,8 @@ protected:
|
||||||
return TestFail;
|
return TestFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_ = new CameraSensor(entity);
|
sensor_ = CameraSensorFactoryBase::create(entity);
|
||||||
if (sensor_->init() < 0) {
|
if (!sensor_) {
|
||||||
cerr << "Unable to initialise camera sensor" << endl;
|
cerr << "Unable to initialise camera sensor" << endl;
|
||||||
return TestFail;
|
return TestFail;
|
||||||
}
|
}
|
||||||
|
@ -118,13 +118,12 @@ protected:
|
||||||
|
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
delete sensor_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<DeviceEnumerator> enumerator_;
|
std::unique_ptr<DeviceEnumerator> enumerator_;
|
||||||
std::shared_ptr<MediaDevice> media_;
|
std::shared_ptr<MediaDevice> media_;
|
||||||
CameraSensor *sensor_;
|
std::unique_ptr<CameraSensor> sensor_;
|
||||||
CameraLens *lens_;
|
CameraLens *lens_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,8 @@ int V4L2VideoDeviceTest::init()
|
||||||
format.size.height = 480;
|
format.size.height = 480;
|
||||||
|
|
||||||
if (driver_ == "vimc") {
|
if (driver_ == "vimc") {
|
||||||
sensor_ = new CameraSensor(media_->getEntityByName("Sensor A"));
|
sensor_ = CameraSensorFactoryBase::create(media_->getEntityByName("Sensor A"));
|
||||||
if (sensor_->init())
|
if (!sensor_)
|
||||||
return TestFail;
|
return TestFail;
|
||||||
|
|
||||||
debayer_ = new V4L2Subdevice(media_->getEntityByName("Debayer A"));
|
debayer_ = new V4L2Subdevice(media_->getEntityByName("Debayer A"));
|
||||||
|
@ -98,6 +98,5 @@ void V4L2VideoDeviceTest::cleanup()
|
||||||
capture_->close();
|
capture_->close();
|
||||||
|
|
||||||
delete debayer_;
|
delete debayer_;
|
||||||
delete sensor_;
|
|
||||||
delete capture_;
|
delete capture_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ protected:
|
||||||
std::string entity_;
|
std::string entity_;
|
||||||
std::unique_ptr<libcamera::DeviceEnumerator> enumerator_;
|
std::unique_ptr<libcamera::DeviceEnumerator> enumerator_;
|
||||||
std::shared_ptr<libcamera::MediaDevice> media_;
|
std::shared_ptr<libcamera::MediaDevice> media_;
|
||||||
libcamera::CameraSensor *sensor_;
|
std::unique_ptr<libcamera::CameraSensor> sensor_;
|
||||||
libcamera::V4L2Subdevice *debayer_;
|
libcamera::V4L2Subdevice *debayer_;
|
||||||
libcamera::V4L2VideoDevice *capture_;
|
libcamera::V4L2VideoDevice *capture_;
|
||||||
std::vector<std::unique_ptr<libcamera::FrameBuffer>> buffers_;
|
std::vector<std::unique_ptr<libcamera::FrameBuffer>> buffers_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue