diff options
Diffstat (limited to 'src/libcamera')
-rw-r--r-- | src/libcamera/camera_sensor.cpp | 4 | ||||
-rw-r--r-- | src/libcamera/include/camera_sensor.h | 7 | ||||
-rw-r--r-- | src/libcamera/include/v4l2_controls.h | 42 | ||||
-rw-r--r-- | src/libcamera/include/v4l2_device.h | 6 | ||||
-rw-r--r-- | src/libcamera/pipeline/ipu3/ipu3.cpp | 9 | ||||
-rw-r--r-- | src/libcamera/pipeline/uvcvideo.cpp | 24 | ||||
-rw-r--r-- | src/libcamera/pipeline/vimc.cpp | 25 | ||||
-rw-r--r-- | src/libcamera/v4l2_controls.cpp | 196 | ||||
-rw-r--r-- | src/libcamera/v4l2_device.cpp | 51 |
9 files changed, 97 insertions, 267 deletions
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index a7670b44..9e8b44a2 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -279,7 +279,7 @@ const V4L2ControlInfoMap &CameraSensor::controls() const * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int CameraSensor::getControls(V4L2ControlList *ctrls) +int CameraSensor::getControls(ControlList *ctrls) { return subdev_->getControls(ctrls); } @@ -309,7 +309,7 @@ int CameraSensor::getControls(V4L2ControlList *ctrls) * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int CameraSensor::setControls(V4L2ControlList *ctrls) +int CameraSensor::setControls(ControlList *ctrls) { return subdev_->setControls(ctrls); } diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index fe033fb3..f426e29b 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -13,11 +13,12 @@ #include <libcamera/geometry.h> #include "log.h" -#include "v4l2_controls.h" namespace libcamera { +class ControlList; class MediaEntity; +class V4L2ControlInfoMap; class V4L2Subdevice; struct V4L2SubdeviceFormat; @@ -43,8 +44,8 @@ public: int setFormat(V4L2SubdeviceFormat *format); const V4L2ControlInfoMap &controls() const; - int getControls(V4L2ControlList *ctrls); - int setControls(V4L2ControlList *ctrls); + int getControls(ControlList *ctrls); + int setControls(ControlList *ctrls); protected: std::string logPrefix() const; diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h index 8990e755..89cc7448 100644 --- a/src/libcamera/include/v4l2_controls.h +++ b/src/libcamera/include/v4l2_controls.h @@ -13,7 +13,6 @@ #include <string> #include <vector> -#include <linux/v4l2-controls.h> #include <linux/videodev2.h> #include <libcamera/controls.h> @@ -57,47 +56,20 @@ public: using std::map<unsigned int, V4L2ControlInfo>::size; using std::map<unsigned int, V4L2ControlInfo>::count; using std::map<unsigned int, V4L2ControlInfo>::find; -}; -class V4L2Control -{ -public: - V4L2Control(unsigned int id, const ControlValue &value = ControlValue()) - : id_(id), value_(value) - { - } - - unsigned int id() const { return id_; } - const ControlValue &value() const { return value_; } - ControlValue &value() { return value_; } + const ControlIdMap &idmap() const { return idmap_; } private: - unsigned int id_; - ControlValue value_; + ControlIdMap idmap_; }; -class V4L2ControlList +class V4L2ControlList : public ControlList { public: - using iterator = std::vector<V4L2Control>::iterator; - using const_iterator = std::vector<V4L2Control>::const_iterator; - - iterator begin() { return controls_.begin(); } - const_iterator begin() const { return controls_.begin(); } - iterator end() { return controls_.end(); } - const_iterator end() const { return controls_.end(); } - - bool empty() const { return controls_.empty(); } - std::size_t size() const { return controls_.size(); } - - void clear() { controls_.clear(); } - void add(unsigned int id, int64_t value = 0); - - V4L2Control *getByIndex(unsigned int index); - V4L2Control *operator[](unsigned int id); - -private: - std::vector<V4L2Control> controls_; + V4L2ControlList(const V4L2ControlInfoMap &info) + : ControlList(info.idmap()) + { + } }; } /* namespace libcamera */ diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 75a52c33..daa762d5 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -25,8 +25,8 @@ public: const V4L2ControlInfoMap &controls() const { return controls_; } - int getControls(V4L2ControlList *ctrls); - int setControls(V4L2ControlList *ctrls); + int getControls(ControlList *ctrls); + int setControls(ControlList *ctrls); const std::string &deviceNode() const { return deviceNode_; } @@ -43,7 +43,7 @@ protected: private: void listControls(); - void updateControls(V4L2ControlList *ctrls, + void updateControls(ControlList *ctrls, const V4L2ControlInfo **controlInfo, const struct v4l2_ext_control *v4l2Ctrls, unsigned int count); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 827906d5..9776b36b 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -199,6 +199,7 @@ class PipelineHandlerIPU3 : public PipelineHandler { public: static constexpr unsigned int V4L2_CID_IPU3_PIPE_MODE = 0x009819c1; + enum IPU3PipeModes { IPU3PipeModeVideo = 0, IPU3PipeModeStillCapture = 1, @@ -603,10 +604,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) return ret; /* Apply the "pipe_mode" control to the ImgU subdevice. */ - V4L2ControlList ctrls; - ctrls.add(V4L2_CID_IPU3_PIPE_MODE, vfStream->active_ ? - IPU3PipeModeVideo : - IPU3PipeModeStillCapture); + V4L2ControlList ctrls(imgu->imgu_->controls()); + ctrls.set(V4L2_CID_IPU3_PIPE_MODE, + static_cast<int32_t>(vfStream->active_ ? IPU3PipeModeVideo : + IPU3PipeModeStillCapture)); ret = imgu->imgu_->setControls(&ctrls); if (ret) { LOG(IPU3, Error) << "Unable to set pipe_mode control"; diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 88f7fb9b..547ad5ca 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -228,31 +228,30 @@ void PipelineHandlerUVC::stop(Camera *camera) int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request) { - V4L2ControlList controls; + V4L2ControlList controls(data->video_->controls()); for (auto it : request->controls()) { const ControlId &id = *it.first; ControlValue &value = it.second; if (id == controls::Brightness) { - controls.add(V4L2_CID_BRIGHTNESS, value.get<int32_t>()); + controls.set(V4L2_CID_BRIGHTNESS, value); } else if (id == controls::Contrast) { - controls.add(V4L2_CID_CONTRAST, value.get<int32_t>()); + controls.set(V4L2_CID_CONTRAST, value); } else if (id == controls::Saturation) { - controls.add(V4L2_CID_SATURATION, value.get<int32_t>()); + controls.set(V4L2_CID_SATURATION, value); } else if (id == controls::ManualExposure) { - controls.add(V4L2_CID_EXPOSURE_AUTO, 1); - controls.add(V4L2_CID_EXPOSURE_ABSOLUTE, value.get<int32_t>()); + controls.set(V4L2_CID_EXPOSURE_AUTO, static_cast<int32_t>(1)); + controls.set(V4L2_CID_EXPOSURE_ABSOLUTE, value); } else if (id == controls::ManualGain) { - controls.add(V4L2_CID_GAIN, value.get<int32_t>()); + controls.set(V4L2_CID_GAIN, value); } } - for (const V4L2Control &ctrl : controls) + for (const auto &ctrl : controls) LOG(UVC, Debug) - << "Setting control 0x" - << std::hex << std::setw(8) << ctrl.id() << std::dec - << " to " << ctrl.value().toString(); + << "Setting control " << ctrl.first->name() + << " to " << ctrl.second.toString(); int ret = data->video_->setControls(&controls); if (ret) { @@ -338,11 +337,10 @@ int UVCCameraData::init(MediaEntity *entity) /* Initialise the supported controls. */ const V4L2ControlInfoMap &controls = video_->controls(); for (const auto &ctrl : controls) { - unsigned int v4l2Id = ctrl.first; const V4L2ControlInfo &info = ctrl.second; const ControlId *id; - switch (v4l2Id) { + switch (info.id().id()) { case V4L2_CID_BRIGHTNESS: id = &controls::Brightness; break; diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index f1cfd0ed..53d00360 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -279,26 +279,24 @@ void PipelineHandlerVimc::stop(Camera *camera) int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) { - V4L2ControlList controls; + V4L2ControlList controls(data->sensor_->controls()); for (auto it : request->controls()) { const ControlId &id = *it.first; ControlValue &value = it.second; - if (id == controls::Brightness) { - controls.add(V4L2_CID_BRIGHTNESS, value.get<int32_t>()); - } else if (id == controls::Contrast) { - controls.add(V4L2_CID_CONTRAST, value.get<int32_t>()); - } else if (id == controls::Saturation) { - controls.add(V4L2_CID_SATURATION, value.get<int32_t>()); - } + if (id == controls::Brightness) + controls.set(V4L2_CID_BRIGHTNESS, value); + else if (id == controls::Contrast) + controls.set(V4L2_CID_CONTRAST, value); + else if (id == controls::Saturation) + controls.set(V4L2_CID_SATURATION, value); } - for (const V4L2Control &ctrl : controls) + for (const auto &ctrl : controls) LOG(VIMC, Debug) - << "Setting control 0x" - << std::hex << std::setw(8) << ctrl.id() << std::dec - << " to " << ctrl.value().toString(); + << "Setting control " << ctrl.first->name() + << " to " << ctrl.second.toString(); int ret = data->sensor_->setControls(&controls); if (ret) { @@ -415,11 +413,10 @@ int VimcCameraData::init(MediaDevice *media) /* Initialise the supported controls. */ const V4L2ControlInfoMap &controls = sensor_->controls(); for (const auto &ctrl : controls) { - unsigned int v4l2Id = ctrl.first; const V4L2ControlInfo &info = ctrl.second; const ControlId *id; - switch (v4l2Id) { + switch (info.id().id()) { case V4L2_CID_BRIGHTNESS: id = &controls::Brightness; break; diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 3be21997..c45d3fda 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -40,7 +40,7 @@ * sizes. * * The libcamera V4L2 Controls framework operates on lists of controls, wrapped - * by the V4L2ControlList class, to match the V4L2 extended controls API. The + * by the ControlList class, to match the V4L2 extended controls API. The * interface to set and get control is implemented by the V4L2Device class, and * this file only provides the data type definitions. * @@ -175,194 +175,42 @@ V4L2ControlInfoMap &V4L2ControlInfoMap::operator=(std::map<unsigned int, V4L2Con { std::map<unsigned int, V4L2ControlInfo>::operator=(std::move(info)); + idmap_.clear(); + for (const auto &ctrl : *this) + idmap_[ctrl.first] = &ctrl.second.id(); + return *this; } /** - * \class V4L2Control - * \brief A V4L2 control value - * - * The V4L2Control class represent the value of a V4L2 control. The class - * stores values that have been read from or will be applied to a V4L2 device. - * - * The value stored in the class instances does not reflect what is actually - * applied to the hardware but is a pure software cache optionally initialized - * at control creation time and modified by a control read or write operation. + * \fn const ControlIdMap &V4L2ControlInfoMap::idmap() const + * \brief Retrieve the ControlId map * - * The write and read controls the V4L2Control class instances are not meant - * to be directly used but are instead intended to be grouped in - * V4L2ControlList instances, which are then passed as parameters to - * V4L2Device::setControls() and V4L2Device::getControls() operations. - */ - -/** - * \fn V4L2Control::V4L2Control - * \brief Construct a V4L2 control with \a id and \a value - * \param id The V4L2 control ID - * \param value The control value - */ - -/** - * \fn V4L2Control::value() const - * \brief Retrieve the value of the control + * Constructing ControlList instances for V4L2 controls requires a ControlIdMap + * for the V4L2 device that the control list targets. This helper method + * returns a suitable idmap for that purpose. * - * This method is a const version of V4L2Control::value(), returning a const - * reference to the value. - * - * \return The V4L2 control value - */ - -/** - * \fn V4L2Control::value() - * \brief Retrieve the value of the control - * - * This method returns the cached control value, initially set by - * V4L2ControlList::add() and then updated when the controls are read or - * written with V4L2Device::getControls() and V4L2Device::setControls(). - * - * \return The V4L2 control value - */ - -/** - * \fn V4L2Control::id() - * \brief Retrieve the control ID this instance refers to - * \return The V4L2Control ID + * \return The ControlId map */ /** * \class V4L2ControlList - * \brief Container of V4L2Control instances - * - * The V4L2ControlList class works as a container for a list of V4L2Control - * instances. The class provides operations to add a new control to the list, - * get back a control value, and reset the list of controls it contains. - * - * In order to set and get controls, user of the libcamera V4L2 control - * framework should operate on instances of the V4L2ControlList class, and use - * them as argument for the V4L2Device::setControls() and - * V4L2Device::getControls() operations, which write and read a list of - * controls to or from a V4L2 device (a video device or a subdevice). - * - * Controls are added to a V4L2ControlList instance with the add() method, with - * or without a value. - * - * To write controls to a device, the controls of interest shall be added with - * an initial value by calling V4L2ControlList::add(unsigned int id, int64_t - * value) to prepare for a write operation. Once the values of all controls of - * interest have been added, the V4L2ControlList instance is passed to the - * V4L2Device::setControls(), which sets the controls on the device. + * \brief A list of controls for a V4L2 device * - * To read controls from a device, the desired controls are added with - * V4L2ControlList::add(unsigned int id) to prepare for a read operation. The - * V4L2ControlList instance is then passed to V4L2Device::getControls(), which - * reads the controls from the device and updates the values stored in - * V4L2ControlList. + * This class specialises the ControList class for use with V4L2 devices. It + * offers a convenience API to create a ControlList from a V4L2ControlInfoMap. * - * V4L2ControlList instances can be reset to remove all controls they contain - * and prepare to be re-used for a new control write/read sequence. - */ - -/** - * \typedef V4L2ControlList::iterator - * \brief Iterator on the V4L2 controls contained in the instance - */ - -/** - * \typedef V4L2ControlList::const_iterator - * \brief Const iterator on the V4L2 controls contained in the instance - */ - -/** - * \fn iterator V4L2ControlList::begin() - * \brief Retrieve an iterator to the first V4L2Control in the instance - * \return An iterator to the first V4L2 control - */ - -/** - * \fn const_iterator V4L2ControlList::begin() const - * \brief Retrieve a constant iterator to the first V4L2Control in the instance - * \return A constant iterator to the first V4L2 control + * V4L2ControlList allows easy construction of a ControlList containing V4L2 + * controls for a device. It can be used to construct the list of controls + * passed to the V4L2Device::getControls() and V4L2Device::setControls() + * methods. The class should however not be used in place of ControlList in + * APIs. */ /** - * \fn iterator V4L2ControlList::end() - * \brief Retrieve an iterator pointing to the past-the-end V4L2Control in the - * instance - * \return An iterator to the element following the last V4L2 control in the - * instance + * \fn V4L2ControlList::V4L2ControlList(const V4L2ControlInfoMap &info) + * \brief Construct a V4L2ControlList associated with a V4L2 device + * \param[in] info The V4L2 device control info map */ -/** - * \fn const_iterator V4L2ControlList::end() const - * \brief Retrieve a constant iterator pointing to the past-the-end V4L2Control - * in the instance - * \return A constant iterator to the element following the last V4L2 control - * in the instance - */ - -/** - * \fn V4L2ControlList::empty() - * \brief Verify if the instance does not contain any control - * \return True if the instance does not contain any control, false otherwise - */ - -/** - * \fn V4L2ControlList::size() - * \brief Retrieve the number on controls in the instance - * \return The number of V4L2Control stored in the instance - */ - -/** - * \fn V4L2ControlList::clear() - * \brief Remove all controls in the instance - */ - -/** - * \brief Add control with \a id and optional \a value to the instance - * \param id The V4L2 control ID (V4L2_CID_*) - * \param value The V4L2 control value - * - * This method adds a new V4L2 control to the V4L2ControlList. The newly - * inserted control shall not already be present in the control lists, otherwise - * this method, and further use of the control list lead to undefined behaviour. - */ -void V4L2ControlList::add(unsigned int id, int64_t value) -{ - controls_.emplace_back(id, value); -} - -/** - * \brief Retrieve the control at \a index - * \param[in] index The control index - * - * Controls are stored in a V4L2ControlList in order of insertion and this - * method retrieves the control at \a index. - * - * \return A pointer to the V4L2Control at \a index or nullptr if the - * index is larger than the number of controls - */ -V4L2Control *V4L2ControlList::getByIndex(unsigned int index) -{ - if (index >= controls_.size()) - return nullptr; - - return &controls_[index]; -} - -/** - * \brief Retrieve the control with \a id - * \param[in] id The V4L2 control ID (V4L2_CID_xx) - * \return A pointer to the V4L2Control with \a id or nullptr if the - * control ID is not part of this instance. - */ -V4L2Control *V4L2ControlList::operator[](unsigned int id) -{ - for (V4L2Control &ctrl : controls_) { - if (ctrl.id() == id) - return &ctrl; - } - - return nullptr; -} - } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 1f755f0f..b47ba448 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -163,7 +163,7 @@ void V4L2Device::close() * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int V4L2Device::getControls(V4L2ControlList *ctrls) +int V4L2Device::getControls(ControlList *ctrls) { unsigned int count = ctrls->size(); if (count == 0) @@ -173,18 +173,21 @@ int V4L2Device::getControls(V4L2ControlList *ctrls) struct v4l2_ext_control v4l2Ctrls[count]; memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); - for (unsigned int i = 0; i < count; ++i) { - const V4L2Control *ctrl = ctrls->getByIndex(i); - const auto iter = controls_.find(ctrl->id()); + unsigned int i = 0; + for (const auto &ctrl : *ctrls) { + const ControlId *id = ctrl.first; + const auto iter = controls_.find(id->id()); if (iter == controls_.end()) { LOG(V4L2, Error) - << "Control '" << ctrl->id() << "' not found"; + << "Control '" << id->name() << "' not found"; return -EINVAL; } const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = ctrl->id(); + v4l2Ctrls[i].id = id->id(); + + i++; } struct v4l2_ext_controls v4l2ExtCtrls = {}; @@ -238,7 +241,7 @@ int V4L2Device::getControls(V4L2ControlList *ctrls) * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int V4L2Device::setControls(V4L2ControlList *ctrls) +int V4L2Device::setControls(ControlList *ctrls) { unsigned int count = ctrls->size(); if (count == 0) @@ -248,32 +251,36 @@ int V4L2Device::setControls(V4L2ControlList *ctrls) struct v4l2_ext_control v4l2Ctrls[count]; memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); - for (unsigned int i = 0; i < count; ++i) { - const V4L2Control *ctrl = ctrls->getByIndex(i); - const auto iter = controls_.find(ctrl->id()); + unsigned int i = 0; + for (const auto &ctrl : *ctrls) { + const ControlId *id = ctrl.first; + const auto iter = controls_.find(id->id()); if (iter == controls_.end()) { LOG(V4L2, Error) - << "Control '" << ctrl->id() << "' not found"; + << "Control '" << id->name() << "' not found"; return -EINVAL; } const V4L2ControlInfo *info = &iter->second; controlInfo[i] = info; - v4l2Ctrls[i].id = ctrl->id(); + v4l2Ctrls[i].id = id->id(); /* Set the v4l2_ext_control value for the write operation. */ + const ControlValue &value = ctrl.second; switch (info->id().type()) { case ControlTypeInteger64: - v4l2Ctrls[i].value64 = ctrl->value().get<int64_t>(); + v4l2Ctrls[i].value64 = value.get<int64_t>(); break; default: /* * \todo To be changed when support for string and * compound controls will be added. */ - v4l2Ctrls[i].value = ctrl->value().get<int32_t>(); + v4l2Ctrls[i].value = value.get<int32_t>(); break; } + + i++; } struct v4l2_ext_controls v4l2ExtCtrls = {}; @@ -385,28 +392,34 @@ void V4L2Device::listControls() * \param[in] v4l2Ctrls List of V4L2 extended controls as returned by the driver * \param[in] count The number of controls to update */ -void V4L2Device::updateControls(V4L2ControlList *ctrls, +void V4L2Device::updateControls(ControlList *ctrls, const V4L2ControlInfo **controlInfo, const struct v4l2_ext_control *v4l2Ctrls, unsigned int count) { - for (unsigned int i = 0; i < count; ++i) { + unsigned int i = 0; + for (auto &ctrl : *ctrls) { + if (i == count) + break; + const struct v4l2_ext_control *v4l2Ctrl = &v4l2Ctrls[i]; const V4L2ControlInfo *info = controlInfo[i]; - V4L2Control *ctrl = ctrls->getByIndex(i); + ControlValue &value = ctrl.second; switch (info->id().type()) { case ControlTypeInteger64: - ctrl->value().set<int64_t>(v4l2Ctrl->value64); + value.set<int64_t>(v4l2Ctrl->value64); break; default: /* * \todo To be changed when support for string and * compound controls will be added. */ - ctrl->value().set<int32_t>(v4l2Ctrl->value); + value.set<int32_t>(v4l2Ctrl->value); break; } + + i++; } } |