libcamera: controls: Use ControlValidator to validate ControlList

Replace the manual validation of controls against a Camera with usage of
the new ControlValidator interface.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Laurent Pinchart 2019-09-28 02:45:49 +03:00
parent f671d84ceb
commit ecf1c2e57b
5 changed files with 43 additions and 26 deletions

View file

@ -13,7 +13,7 @@
namespace libcamera { namespace libcamera {
class Camera; class ControlValidator;
enum ControlType { enum ControlType {
ControlTypeNone, ControlTypeNone,
@ -119,7 +119,7 @@ private:
using ControlListMap = std::unordered_map<const ControlId *, ControlValue>; using ControlListMap = std::unordered_map<const ControlId *, ControlValue>;
public: public:
ControlList(Camera *camera); ControlList(ControlValidator *validator);
using iterator = ControlListMap::iterator; using iterator = ControlListMap::iterator;
using const_iterator = ControlListMap::const_iterator; using const_iterator = ControlListMap::const_iterator;
@ -160,7 +160,7 @@ private:
const ControlValue *find(const ControlId &id) const; const ControlValue *find(const ControlId &id) const;
ControlValue *find(const ControlId &id); ControlValue *find(const ControlId &id);
Camera *camera_; ControlValidator *validator_;
ControlListMap controls_; ControlListMap controls_;
}; };

View file

@ -19,9 +19,9 @@ namespace libcamera {
class Buffer; class Buffer;
class Camera; class Camera;
class CameraControlValidator;
class Stream; class Stream;
class Request class Request
{ {
public: public:
@ -36,7 +36,7 @@ public:
Request &operator=(const Request &) = delete; Request &operator=(const Request &) = delete;
~Request(); ~Request();
ControlList &controls() { return controls_; } ControlList &controls() { return *controls_; }
const std::map<Stream *, Buffer *> &buffers() const { return bufferMap_; } const std::map<Stream *, Buffer *> &buffers() const { return bufferMap_; }
int addBuffer(std::unique_ptr<Buffer> buffer); int addBuffer(std::unique_ptr<Buffer> buffer);
Buffer *findBuffer(Stream *stream) const; Buffer *findBuffer(Stream *stream) const;
@ -56,7 +56,8 @@ private:
bool completeBuffer(Buffer *buffer); bool completeBuffer(Buffer *buffer);
Camera *camera_; Camera *camera_;
ControlList controls_; CameraControlValidator *validator_;
ControlList *controls_;
std::map<Stream *, Buffer *> bufferMap_; std::map<Stream *, Buffer *> bufferMap_;
std::unordered_set<Buffer *> pending_; std::unordered_set<Buffer *> pending_;

View file

@ -10,8 +10,7 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <libcamera/camera.h> #include "control_validator.h"
#include "log.h" #include "log.h"
#include "utils.h" #include "utils.h"
@ -365,20 +364,16 @@ std::string ControlRange::toString() const
* \class ControlList * \class ControlList
* \brief Associate a list of ControlId with their values for a camera * \brief Associate a list of ControlId with their values for a camera
* *
* A ControlList wraps a map of ControlId to ControlValue and provide * A ControlList wraps a map of ControlId to ControlValue and optionally
* additional validation against the control information exposed by a Camera. * validates controls against a ControlValidator.
*
* A list is only valid for as long as the camera it refers to is valid. After
* that calling any method of the ControlList class other than its destructor
* will cause undefined behaviour.
*/ */
/** /**
* \brief Construct a ControlList with a reference to the Camera it applies on * \brief Construct a ControlList with an optional control validator
* \param[in] camera The camera * \param[in] validator The validator (may be null)
*/ */
ControlList::ControlList(Camera *camera) ControlList::ControlList(ControlValidator *validator)
: camera_(camera) : validator_(validator)
{ {
} }
@ -493,12 +488,10 @@ const ControlValue *ControlList::find(const ControlId &id) const
ControlValue *ControlList::find(const ControlId &id) ControlValue *ControlList::find(const ControlId &id)
{ {
const ControlInfoMap &controls = camera_->controls(); if (validator_ && !validator_->validate(id)) {
const auto iter = controls.find(&id);
if (iter == controls.end()) {
LOG(Controls, Error) LOG(Controls, Error)
<< "Camera " << camera_->name() << "Control " << id.name()
<< " does not support control " << id.name(); << " is not valid for " << validator_->name();
return nullptr; return nullptr;
} }

View file

@ -13,6 +13,7 @@
#include <libcamera/camera.h> #include <libcamera/camera.h>
#include <libcamera/stream.h> #include <libcamera/stream.h>
#include "camera_controls.h"
#include "log.h" #include "log.h"
/** /**
@ -55,9 +56,15 @@ LOG_DEFINE_CATEGORY(Request)
* *
*/ */
Request::Request(Camera *camera, uint64_t cookie) Request::Request(Camera *camera, uint64_t cookie)
: camera_(camera), controls_(camera), cookie_(cookie), : camera_(camera), cookie_(cookie), status_(RequestPending),
status_(RequestPending), cancelled_(false) cancelled_(false)
{ {
/**
* \todo Should the Camera expose a validator instance, to avoid
* creating a new instance for each request?
*/
validator_ = new CameraControlValidator(camera);
controls_ = new ControlList(validator_);
} }
Request::~Request() Request::~Request()
@ -66,6 +73,9 @@ Request::~Request()
Buffer *buffer = it.second; Buffer *buffer = it.second;
delete buffer; delete buffer;
} }
delete controls_;
delete validator_;
} }
/** /**

View file

@ -12,6 +12,7 @@
#include <libcamera/control_ids.h> #include <libcamera/control_ids.h>
#include <libcamera/controls.h> #include <libcamera/controls.h>
#include "camera_controls.h"
#include "test.h" #include "test.h"
using namespace std; using namespace std;
@ -40,7 +41,8 @@ protected:
int run() int run()
{ {
ControlList list(camera_.get()); CameraControlValidator validator(camera_.get());
ControlList list(&validator);
/* Test that the list is initially empty. */ /* Test that the list is initially empty. */
if (!list.empty()) { if (!list.empty()) {
@ -141,6 +143,17 @@ protected:
return TestFail; return TestFail;
} }
/*
* Attempt to set an invalid control and verify that the
* operation failed.
*/
list.set(controls::AwbEnable, true);
if (list.contains(controls::AwbEnable)) {
cout << "List shouldn't contain AwbEnable control" << endl;
return TestFail;
}
return TestPass; return TestPass;
} }