From patchwork Sat Sep 14 22:52:52 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: 21268 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 46050C324C for ; Sat, 14 Sep 2024 22:52:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 325B0634F5; Sun, 15 Sep 2024 00:52:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=makewise.pt header.i=@makewise.pt header.b="i9swKfyJ"; dkim=pass (1024-bit key; unprotected) header.d=amazonses.com header.i=@amazonses.com header.b="UiX8nbwj"; dkim-atps=neutral Received: from a7-11.smtp-out.eu-west-1.amazonses.com (a7-11.smtp-out.eu-west-1.amazonses.com [54.240.7.11]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86960634E3 for ; Sun, 15 Sep 2024 00:52:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=4ymqmigrodjwq5luewph2eedidgwlpqq; d=makewise.pt; t=1726354372; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type:Content-Transfer-Encoding; bh=SX/Fo0JhDJZ6NzewaEd+ogo1eCyRm2le2L4DPudORlY=; b=i9swKfyJG6ykgviPQaFzlhtYjTOQEjZAqtzOfATnsaeLTgtREOdEWtZsgCHrRLik 5dDs/QjyZe9kKJVYZo5tOwoPWkTfwsTYVqU9IwoVONoQgqYiGH/5hEPD97ba3w6ckPA Y/BRWHu+aSqT0CfqNV6PQXfrP85xKvhlHA3uN6Pk3m4xER3R1yiqKV3RnARjc+9d4nE kULuKpNRaesAbvFpQYu6ciyx/m9l7mZZKYVgcisyFvUB+gsbrsLG/lGUa+M6nZ8R0Yg V8AnIpSGR1t/h5ZQb649DT0OsITvjsloZ5PMAJCuGJ6ZLqw3qQaTYSSLpjSjjd2LRAl ZHe72+2gxQ== DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=uku4taia5b5tsbglxyj6zym32efj7xqv; d=amazonses.com; t=1726354372; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type:Content-Transfer-Encoding:Feedback-ID; bh=SX/Fo0JhDJZ6NzewaEd+ogo1eCyRm2le2L4DPudORlY=; b=UiX8nbwjC1KZ1pkxY79BGLD2gLBjPKi+m8SryvzBCFczzWAbgSr3btlBfuWllYSl mQGPF5TVkJczKfX5UL7/mLYsEClhIXNrFcuI2UmwFaOfTxhU5SbbxZlkbutk80eoRHb gbC8YFGjAgnZK01k+R7hszKa9QYxI1C27RZGpt1s= From: =?utf-8?q?Cl=C3=A1udio_Paulo?= To: libcamera-devel@lists.libcamera.org Cc: =?utf-8?q?Cl=C3=A1udio_Paulo?= Subject: [PATCH v3] libcamera: pipeline: uvcvideo: Retrieve v4l2 device control information Date: Sat, 14 Sep 2024 22:52:52 +0000 Message-ID: <01020191f2bd3860-8a479d82-2724-43c0-895c-779c826ef28a-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.14-54.240.7.11 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 --- 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() - ? 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 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(); + if (v4l2Info.min().type() == ControlTypeInteger32) + def = v4l2Info.def().get(); + if (v4l2Info.min().type() == ControlTypeInteger32) + max = v4l2Info.max().get(); + + switch (cid) { + case V4L2_CID_BRIGHTNESS: { + 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: { + 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() + 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() - min) / scale); + break; + } + + case V4L2_CID_EXPOSURE_AUTO: { + int32_t 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: { + 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: { + metadata->set(controls::AfMode, + value.get() == 0 + ? controls::AfModeManual + : controls::AfModeContinuous); + break; + } + + default:; + } + } pipe()->completeBuffer(request, buffer); pipe()->completeRequest(request);