libcamera/test/controls/control_list.cpp
Laurent Pinchart a8c40942b9 libcamera: controls: Improve the API towards applications
Rework the control-related classes to improve the API towards
applications. The goal is to enable writing code similar to

	Request *req = ...;
	ControlList &controls = req->controls();
	controls->set(controls::AwbEnable, false);
	controls->set(controls::ManualExposure, 1000);

	...

	int32_t exposure = controls->get(controls::ManualExposure);

with the get and set operations ensuring type safety for the control
values. This is achieved by creating the following classes:

- Control defines controls and is the main way to reference a control.
  It is a template class to allow methods using it to refer to the
  control type.

- ControlId is the base class of Control. It stores the control ID, name
  and type, and can be used in contexts where a control needs to be
  referenced regardless of its type (for instance in lists of controls).
  This class replaces ControlIdentifier.

- ControlValue is kept as-is.

The ControlList class now exposes two template get() and set() methods
that replace the operator[]. They ensure type safety by infering the
value type from the Control reference that they receive.

The main way to refer to a control is now through the Control class, and
optionally through its base ControlId class. The ControlId enumeration
is removed, replaced by a list of global Control instances. Numerical
control IDs are turned into macros, and are still exposed as they are
required to communicate with IPAs (especially to deserialise control
lists). They should however not be used by applications.

Auto-generation of header and source files is removed for now to keep
the change simple. It will be added back in the future in a more
elaborate form.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-10-04 19:33:08 +03:00

206 lines
4.5 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* control_list.cpp - ControlList tests
*/
#include <iostream>
#include <libcamera/camera.h>
#include <libcamera/camera_manager.h>
#include <libcamera/control_ids.h>
#include <libcamera/controls.h>
#include "test.h"
using namespace std;
using namespace libcamera;
class ControlListTest : public Test
{
protected:
int init()
{
cm_ = new CameraManager();
if (cm_->start()) {
cout << "Failed to start camera manager" << endl;
return TestFail;
}
camera_ = cm_->get("VIMC Sensor B");
if (!camera_) {
cout << "Can not find VIMC camera" << endl;
return TestSkip;
}
return TestPass;
}
int run()
{
ControlList list(camera_.get());
/* Test that the list is initially empty. */
if (!list.empty()) {
cout << "List should to be empty" << endl;
return TestFail;
}
if (list.size() != 0) {
cout << "List should contain zero items" << endl;
return TestFail;
}
if (list.contains(controls::Brightness)) {
cout << "List should not contain Brightness control" << endl;
return TestFail;
}
unsigned int count = 0;
for (auto iter = list.begin(); iter != list.end(); ++iter)
count++;
if (count != 0) {
cout << "List iteration should not produce any item" << endl;
return TestFail;
}
/*
* Set a control, and verify that the list now contains it, and
* nothing else.
*/
list.set(controls::Brightness, 255);
if (list.empty()) {
cout << "List should not be empty" << endl;
return TestFail;
}
if (list.size() != 1) {
cout << "List should contain one item" << endl;
return TestFail;
}
if (!list.contains(controls::Brightness)) {
cout << "List should contain Brightness control" << endl;
return TestFail;
}
count = 0;
for (auto iter = list.begin(); iter != list.end(); ++iter)
count++;
if (count != 1) {
cout << "List iteration should produce one item" << endl;
return TestFail;
}
if (list.get(controls::Brightness) != 255) {
cout << "Incorrest Brightness control value" << endl;
return TestFail;
}
if (list.contains(controls::Contrast)) {
cout << "List should not contain Contract control" << endl;
return TestFail;
}
/* Update the first control and set a second one. */
list.set(controls::Brightness, 64);
list.set(controls::Contrast, 128);
if (!list.contains(controls::Contrast) ||
!list.contains(controls::Contrast)) {
cout << "List should contain Contrast control" << endl;
return TestFail;
}
if (list.get(controls::Brightness) != 64 ||
list.get(controls::Contrast) != 128) {
cout << "Failed to retrieve control value" << endl;
return TestFail;
}
/*
* Update both controls and verify that the container doesn't
* grow.
*/
list.set(controls::Brightness, 10);
list.set(controls::Contrast, 20);
if (list.get(controls::Brightness) != 10 ||
list.get(controls::Contrast) != 20) {
cout << "Failed to update control value" << endl;
return TestFail;
}
if (list.size() != 2) {
cout << "List should contain two elements" << endl;
return TestFail;
}
/*
* Test list merging. Create a new list, add two controls with
* one overlapping the existing list, merge the lists and clear
* the old list. Verify that the new list is empty and that the
* new list contains the expected items and values.
*/
ControlList newList(camera_.get());
newList.set(controls::Brightness, 128);
newList.set(controls::Saturation, 255);
newList.update(list);
list.clear();
if (list.size() != 0) {
cout << "Old List should contain zero items" << endl;
return TestFail;
}
if (!list.empty()) {
cout << "Old List should be empty" << endl;
return TestFail;
}
if (newList.size() != 3) {
cout << "New list has incorrect size" << endl;
return TestFail;
}
if (!newList.contains(controls::Brightness) ||
!newList.contains(controls::Contrast) ||
!newList.contains(controls::Saturation)) {
cout << "New list contains incorrect items" << endl;
return TestFail;
}
if (newList.get(controls::Brightness) != 10 ||
newList.get(controls::Contrast) != 20 ||
newList.get(controls::Saturation) != 255) {
cout << "New list contains incorrect values" << endl;
return TestFail;
}
return TestPass;
}
void cleanup()
{
if (camera_) {
camera_->release();
camera_.reset();
}
cm_->stop();
delete cm_;
}
private:
CameraManager *cm_;
std::shared_ptr<Camera> camera_;
};
TEST_REGISTER(ControlListTest)