[libcamera-devel,9/9] libcamera: pipeline: vivid: Handle controls

Message ID 20200713132451.2944673-10-kieran.bingham@ideasonboard.com
State Awaiting Upstream
Headers show
Series
  • Introduce a new PipelineHandler
Related show

Commit Message

Kieran Bingham July 13, 2020, 1:24 p.m. UTC
When constructing the camera, we parse the available controls on the
video capture device, and map supported controls to libcamera controls,
and initialise the defaults.

The controls are handled during queueRequestDevice for each request and
applied to the device through the capture node.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 src/libcamera/pipeline/vivid/vivid.cpp | 80 +++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

Patch

diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp
index 1744d78f2f28..b8b8e3ae0287 100644
--- a/src/libcamera/pipeline/vivid/vivid.cpp
+++ b/src/libcamera/pipeline/vivid/vivid.cpp
@@ -5,7 +5,11 @@ 
  * vivid.cpp - Pipeline handler for the vivid capture device
  */
 
+#include <math.h>
+
 #include <libcamera/camera.h>
+#include <libcamera/control_ids.h>
+#include <libcamera/controls.h>
 #include <libcamera/formats.h>
 
 #include "libcamera/internal/device_enumerator.h"
@@ -239,6 +243,46 @@  void PipelineHandlerVivid::stop(Camera *camera)
 	data->video_->releaseBuffers();
 }
 
+int PipelineHandlerVivid::processControls(VividCameraData *data, Request *request)
+{
+	ControlList controls(data->video_->controls());
+
+	for (auto it : request->controls()) {
+		unsigned int id = it.first;
+		unsigned int offset;
+		uint32_t cid;
+
+		if (id == controls::Brightness) {
+			cid = V4L2_CID_BRIGHTNESS;
+			offset = 128;
+		} else if (id == controls::Contrast) {
+			cid = V4L2_CID_CONTRAST;
+			offset = 0;
+		} else if (id == controls::Saturation) {
+			cid = V4L2_CID_SATURATION;
+			offset = 0;
+		} else {
+			continue;
+		}
+
+		int32_t value = lroundf(it.second.get<float>() * 128 + offset);
+		controls.set(cid, utils::clamp(value, 0, 255));
+	}
+
+	for (const auto &ctrl : controls)
+		LOG(VIVID, Debug)
+			<< "Setting control " << utils::hex(ctrl.first)
+			<< " to " << ctrl.second.toString();
+
+	int ret = data->video_->setControls(&controls);
+	if (ret) {
+		LOG(VIVID, Error) << "Failed to set controls: " << ret;
+		return ret < 0 ? ret : -EINVAL;
+	}
+
+	return ret;
+}
+
 int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)
 {
 	VividCameraData *data = cameraData(camera);
@@ -250,7 +294,11 @@  int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)
 		return -ENOENT;
 	}
 
-	int ret = data->video_->queueBuffer(buffer);
+	int ret = processControls(data, request);
+	if (ret < 0)
+		return ret;
+
+	ret = data->video_->queueBuffer(buffer);
 	if (ret < 0)
 		return ret;
 
@@ -288,6 +336,36 @@  int VividCameraData::init()
 
 	video_->bufferReady.connect(this, &VividCameraData::bufferReady);
 
+	/* Initialise the supported controls. */
+	const ControlInfoMap &controls = video_->controls();
+	ControlInfoMap::Map ctrls;
+
+	for (const auto &ctrl : controls) {
+		const ControlId *id;
+		ControlInfo info;
+
+		switch (ctrl.first->id()) {
+		case V4L2_CID_BRIGHTNESS:
+			id = &controls::Brightness;
+			info = ControlInfo{ { -1.0f }, { 1.0f }, { 0.0f } };
+			break;
+		case V4L2_CID_CONTRAST:
+			id = &controls::Contrast;
+			info = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };
+			break;
+		case V4L2_CID_SATURATION:
+			id = &controls::Saturation;
+			info = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };
+			break;
+		default:
+			continue;
+		}
+
+		ctrls.emplace(id, info);
+	}
+
+	controlInfo_ = std::move(ctrls);
+
 	return 0;
 }