[PATCH v3] libcamera: pipeline: uvcvideo: Retrieve v4l2 device control information
Cláudio Paulo
claudio.paulo at makewise.pt
Sun Sep 15 00:52:52 CEST 2024
Populate frame metadata by using V4L2Device::getControls() to get
the values for all supported controls on each frame.
Signed-off-by: Cláudio Paulo <claudio.paulo at makewise.pt>
---
Fixed similar issues reported on a distinct patch.
src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 112 ++++++++++++++++++-
1 file changed, 108 insertions(+), 4 deletions(-)
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index 6b32fa18..6313e9e0 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -333,8 +333,8 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
case V4L2_CID_EXPOSURE_AUTO: {
int32_t ivalue = value.get<bool>()
- ? V4L2_EXPOSURE_APERTURE_PRIORITY
- : V4L2_EXPOSURE_MANUAL;
+ ? V4L2_EXPOSURE_APERTURE_PRIORITY
+ : V4L2_EXPOSURE_MANUAL;
controls->set(V4L2_CID_EXPOSURE_AUTO, ivalue);
break;
}
@@ -750,10 +750,114 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,
void UVCCameraData::bufferReady(FrameBuffer *buffer)
{
Request *request = buffer->request();
+ ControlList *metadata = &request->metadata();
/* \todo Use the UVC metadata to calculate a more precise timestamp */
- request->metadata().set(controls::SensorTimestamp,
- buffer->metadata().timestamp);
+ metadata->set(controls::SensorTimestamp, buffer->metadata().timestamp);
+
+ /* Retrieve control as reported by the device. */
+ std::vector<uint32_t> ids;
+ for (const auto &[controlId, _] : video_->controls()) {
+ switch (uint32_t cid = controlId->id()) {
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_CONTRAST:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_EXPOSURE_AUTO:
+ case V4L2_CID_EXPOSURE_ABSOLUTE:
+ case V4L2_CID_GAIN:
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ case V4L2_CID_FOCUS_AUTO:
+ ids.push_back(cid);
+ break;
+ default:;
+ }
+ }
+
+ /*
+ * See UVCCameraData::addControl() for explanations of the different
+ * value mappings.
+ */
+ ControlList deviceControls = video_->getControls(ids);
+ for (const auto &[cid, value] : deviceControls) {
+ ControlInfo v4l2Info = video_->controls().at(cid);
+
+ int32_t min = -1, def = -1, max = -1;
+ if (v4l2Info.min().type() == ControlTypeInteger32)
+ min = v4l2Info.min().get<int32_t>();
+ if (v4l2Info.min().type() == ControlTypeInteger32)
+ def = v4l2Info.def().get<int32_t>();
+ if (v4l2Info.min().type() == ControlTypeInteger32)
+ max = v4l2Info.max().get<int32_t>();
+
+ switch (cid) {
+ case V4L2_CID_BRIGHTNESS: {
+ float scale = std::max(max - def, def - min);
+
+ int ivalue = (value.get<int32_t>() - def) / scale;
+ metadata->set(controls::Brightness, ivalue);
+ break;
+ }
+
+ case V4L2_CID_GAIN:
+ case V4L2_CID_CONTRAST: {
+ float m = (4.0f - 1.0f) / (max - def);
+ float p = 1.0f - m * def;
+
+ if (m * min + p < 0.5f) {
+ m = (1.0f - 0.5f) / (def - min);
+ p = 1.0f - m * def;
+ }
+
+ float fvalue = m * value.get<int32_t>() + p;
+ if (cid == V4L2_CID_GAIN)
+ metadata->set(controls::AnalogueGain, fvalue);
+ else if (cid == V4L2_CID_CONTRAST)
+ metadata->set(controls::Contrast, fvalue);
+ break;
+ }
+
+ case V4L2_CID_SATURATION: {
+ float scale = def - min;
+
+ metadata->set(controls::Saturation,
+ (value.get<int32_t>() - min) / scale);
+ break;
+ }
+
+ case V4L2_CID_EXPOSURE_AUTO: {
+ int32_t ivalue = value.get<int32_t>();
+ if (ivalue == V4L2_EXPOSURE_APERTURE_PRIORITY)
+ metadata->set(controls::AeEnable, true);
+ else if (ivalue == V4L2_EXPOSURE_MANUAL)
+ metadata->set(controls::AeEnable, false);
+ break;
+ }
+
+ case V4L2_CID_EXPOSURE_ABSOLUTE:
+ metadata->set(controls::ExposureTime,
+ value.get<int32_t>() * 100);
+ break;
+
+ case V4L2_CID_FOCUS_ABSOLUTE: {
+ float focusedAt50Cm = 0.15f * (max - min);
+ float scale = 2.0f / focusedAt50Cm;
+
+ metadata->set(controls::LensPosition,
+ (value.get<int32_t>() - min) * scale);
+ break;
+ }
+
+ case V4L2_CID_FOCUS_AUTO: {
+ metadata->set(controls::AfMode,
+ value.get<int32_t>() == 0
+ ? controls::AfModeManual
+ : controls::AfModeContinuous);
+ break;
+ }
+
+ default:;
+ }
+ }
pipe()->completeBuffer(request, buffer);
pipe()->completeRequest(request);
--
2.34.1
More information about the libcamera-devel
mailing list