From patchwork Fri Sep 13 23:30:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Cl=C3=A1udio_Paulo?= X-Patchwork-Id: 21266 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 0F216C3257 for ; Fri, 13 Sep 2024 23:30:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4E731634F8; Sat, 14 Sep 2024 01:30:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=makewise.pt header.i=@makewise.pt header.b="XwlOaDDJ"; dkim=pass (1024-bit key; unprotected) header.d=amazonses.com header.i=@amazonses.com header.b="SZNSTnXX"; dkim-atps=neutral Received: from a7-20.smtp-out.eu-west-1.amazonses.com (a7-20.smtp-out.eu-west-1.amazonses.com [54.240.7.20]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BD1DA634F2 for ; Sat, 14 Sep 2024 01:30:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=4ymqmigrodjwq5luewph2eedidgwlpqq; d=makewise.pt; t=1726270215; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type:Content-Transfer-Encoding; bh=UfEh2Pg+TDvCbm+LM6xaT3IDhT3RDuq2+YrMHiJvq6M=; b=XwlOaDDJoZHhR48ONi98ZH180kz/NRKwl3bxTbEO5m8CSLlijRC89yxdIeWbTQ6K JCxyY1FtwmYVOWvpSvgEXjKlQ0V+eQEu+jA+EdV0TguDPWLRNHO3ikOWOhdU7mUWQWh 1q/OBNzFSVhQmPiGlqE0WUl+8/oZkWGHl4FHXSwZd98dv/4+LQV69oBxzkMy52KmYPq UTwWm2Byppl0maTAnavqQSBPVxoBHE03rt5hbG0D/U/gPF/bv4RqB2fO7JU61mxihmW Erw6QXDMXjAqAjOs3Gbu6Y6QWfHN87KVTnvbgdmVbdXmCeIFZw3g28UeHhguMqqrEoQ hTN+3zdFAA== DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=uku4taia5b5tsbglxyj6zym32efj7xqv; d=amazonses.com; t=1726270215; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type:Content-Transfer-Encoding:Feedback-ID; bh=UfEh2Pg+TDvCbm+LM6xaT3IDhT3RDuq2+YrMHiJvq6M=; b=SZNSTnXXn8eWfV/n/jXAKCXuY0JVwsKkK5hcvPb2ck1p/vAiUCRA/XAgJ3Vksd7w oIWrdm+8wtQizMq5/G2Uok17Nu7ZZvp7Saj/qfQAVIgPNLv/S03tgBeRlFE3fubrTIv Y3INYf3TkemiEOkEMk1SLs+JFw0t/BE6HJ5P051M= From: =?utf-8?q?Cl=C3=A1udio_Paulo?= To: libcamera-devel@lists.libcamera.org Cc: =?utf-8?q?Cl=C3=A1udio_Paulo?= Subject: [PATCH v2] libcamera: pipeline: uvcvideo: Retrieve v4l2 device control information Date: Fri, 13 Sep 2024 23:30:14 +0000 Message-ID: <01020191edb91301-2a501bd0-5f12-4ba1-aa97-e1d610670d26-000000@eu-west-1.amazonses.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Feedback-ID: ::1.eu-west-1.z8xjvhxVxUk+kM5mx7i/KMS/a2avhcAXFe/noI67NVQ=:AmazonSES X-SES-Outgoing: 2024.09.13-54.240.7.20 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Populate frame metadata by using V4L2Device::getControls() to get the values for all supported controls on each frame. Signed-off-by: Cláudio Paulo --- Actually mapping the control values to libcamera ranges now. include/linux/v4l2-controls.h | 4 + src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 115 ++++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/include/linux/v4l2-controls.h b/include/linux/v4l2-controls.h index 882a8180..1ac85507 100644 --- a/include/linux/v4l2-controls.h +++ b/include/linux/v4l2-controls.h @@ -994,6 +994,10 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) #define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) #define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) +enum v4l2_focus_auto_type { + V4L2_FOCUS_MANUAL = 0, + V4L2_FOCUS_AUTO = 1 +}; #define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) #define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 6b32fa18..ad6468b5 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() - ? 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,117 @@ 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 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) { + switch (cid) { + case V4L2_CID_BRIGHTNESS: { + ControlInfo v4l2Info = video_->controls().at(cid); + int32_t min = v4l2Info.min().get(); + int32_t def = v4l2Info.def().get(); + int32_t max = v4l2Info.max().get(); + + float scale = std::max(max - def, def - min); + int ivalue = (value.get() - def) / scale; + metadata->set(controls::Brightness, ivalue); + break; + } + + case V4L2_CID_GAIN: + case V4L2_CID_CONTRAST: { + ControlInfo v4l2Info = video_->controls().at(cid); + int32_t min = v4l2Info.min().get(); + int32_t def = v4l2Info.def().get(); + int32_t max = v4l2Info.max().get(); + + 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; + } + + if (cid == V4L2_CID_GAIN) + metadata->set(controls::AnalogueGain, m * value.get() + p); + else if (cid == V4L2_CID_CONTRAST) + metadata->set(controls::Contrast, m * value.get() + p); + break; + } + + case V4L2_CID_SATURATION: { + ControlInfo v4l2Info = video_->controls().at(cid); + int32_t min = v4l2Info.min().get(); + int32_t def = v4l2Info.def().get(); + + float scale = def - min; + metadata->set(controls::Saturation, (value.get() - min) / scale); + break; + } + + case V4L2_CID_EXPOSURE_AUTO: { + int ivalue = value.get(); + 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() * 100); + break; + + case V4L2_CID_FOCUS_ABSOLUTE: { + ControlInfo v4l2Info = video_->controls().at(cid); + int32_t min = v4l2Info.min().get(); + int32_t max = v4l2Info.max().get(); + + float focusedAt50Cm = 0.15f * (max - min); + float scale = 2.0f / focusedAt50Cm; + + metadata->set(controls::LensPosition, (value.get() - min) * scale); + break; + } + + case V4L2_CID_FOCUS_AUTO: { + int ivalue = value.get(); + if (ivalue == V4L2_FOCUS_MANUAL) + metadata->set(controls::AfMode, controls::AfModeManual); + else if (ivalue == V4L2_FOCUS_AUTO) + metadata->set(controls::AfMode, controls::AfModeAuto); + break; + } + + default:; + } + } pipe()->completeBuffer(request, buffer); pipe()->completeRequest(request);