From patchwork Fri Jun 16 10:03:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cedric Nugteren X-Patchwork-Id: 18747 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 94C96BD78E for ; Fri, 16 Jun 2023 10:03:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D640D628AE; Fri, 16 Jun 2023 12:03:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1686909813; bh=ZXlN82+xYshFIMijo0bH+u3sSX6f13ZPPAhE7IFs1PY=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=2h8lqbNcmEUDSuN8viym0HjDMPAXDyptj3X7hb30xK4tTBD4tFJDTSi15DxhEwN9O 0EKJkCTuJEpmeYaKVa4tNqZasRZzT6e47RYT9hCSJ/yfUY7u96M/5MwsffKx5CF28b dpq9Q/kuRxAyBEhaXAf5Wg8LDY+mRNUIadCoOR+Is4uqX5N8axQmkV9qZaxAuX+Fq9 B1UQP3QIkS80hSYZTwJXuXspVj3d7eYA7iSorZEOGxI7P/tQFowDsV/jWmA9YQ6O47 xSSpxNXJto0aVTqEUt/oWZrIvuvvDiW8Puev81idgU+NZvmYhNavbe7ASLmUPKsAUu vZ56QYpDgjZmg== Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3AD09628AD for ; Fri, 16 Jun 2023 12:03:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=plumerai.com header.i=@plumerai.com header.b="iFLdaLES"; dkim-atps=neutral Received: by mail-ed1-x536.google.com with SMTP id 4fb4d7f45d1cf-51a2fa4a45eso662159a12.0 for ; Fri, 16 Jun 2023 03:03:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plumerai.com; s=google; t=1686909811; x=1689501811; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=E59dRrYZlRucjxD1I+BCKdQ7O6+MoGo4uHa8CGEVIq8=; b=iFLdaLESLxzBnkF2dmb5d+0ANeHJMG8KN8ty2labxHGMmmURTb4LwB9KGHK2tdxh9G qNyAPNEYc92Rhb0Ulv+uAt5+mibeKR2ajJaa0OxkTNNWcaQGfw/KxjdvlOilngEOHl3P eMjcrn4bEsde5G/D/OqdGkl08gQOjr/VSMF5g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686909811; x=1689501811; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=E59dRrYZlRucjxD1I+BCKdQ7O6+MoGo4uHa8CGEVIq8=; b=AzHhaapZyXDZlWmTW/FBa8aFUJ8uV3YIzOo9u0Ed0Ba1cNzYJd8dohVBRBTJZptQ3k N6HX0ZeKWbPvxSQl4uRCffhObv5+Pqoroxch71CeNqsCbmb6SQrSZrquU/xVVh+dXrV+ XjwU1+43h0AfnfNVNqqbHBJjF9J/GBvxPfMWKHerK0UPNdiAVRd5qjgLu1ljBomavlCi Ti8zGav8bm7iLCqOvn4e1pwsbBkWRA+RJy+RKGdeHXMh9HddgfA4qE2JYznuxSf36ptB H9LxyfV7c8Ig7mqEV8/SoSmKE3rra5bP5r5DkoLMmKGqEhkcjuyvzQtYOCQa59v4A0KO Wm9A== X-Gm-Message-State: AC+VfDxLftB750584JgSVSTGpas46dbQ4zCU0nseLzvurE3/OK29HMy6 ZH6C8UJpSD9mrvnz+qUVMRCzvgAhekEfLjdxkv8= X-Google-Smtp-Source: ACHHUZ4yxoWsQKLmow8IQ6po+UfiEn8mQshZZI5F5vVsjzEaLU/b1YgpYu6xP+JwekUnN1a3rx/vzg== X-Received: by 2002:a05:6402:111a:b0:514:a110:6bed with SMTP id u26-20020a056402111a00b00514a1106bedmr942599edv.27.1686909811625; Fri, 16 Jun 2023 03:03:31 -0700 (PDT) Received: from kaylee.. (92-68-83-157.biz.kpn.net. [92.68.83.157]) by smtp.gmail.com with ESMTPSA id r23-20020a056402035700b0051a2c4b1743sm1479974edw.21.2023.06.16.03.03.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jun 2023 03:03:31 -0700 (PDT) X-Google-Original-From: Cedric Nugteren To: libcamera-devel@lists.libcamera.org Date: Fri, 16 Jun 2023 12:03:27 +0200 Message-Id: <20230616100327.86707-1-web@cedricnugteren.nl> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4] gstreamer: Add enable_auto_focus option to the GStreamer plugin 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: , X-Patchwork-Original-From: Cedric Nugteren via libcamera-devel From: Cedric Nugteren Reply-To: Cedric Nugteren Cc: Cedric Nugteren Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Cameras such as the PiCam 3 support auto-focus, but the GStreamer plugin for libcamera does not enable auto-focus. With this patch auto-focus can be enabled for cameras that support it. By default it is disabled, which means default behaviour remains unchanged. For cameras that do not support auto-focus, an error message shows up if auto-focus is enabled. This was tested on cameras that do not support auto-focus (e.g. PiCam2) and was tested on a camera that does support auto-focus (PiCam3). The test involved setting the focus to AfModeContinous and observing it. However, by not setting "auto-focus-mode" or using AfModeManual as the "auto-focus-mode" both resulting in auto-focus being disabled. Bug: https://bugs.libcamera.org/show_bug.cgi?id=188 Signed-off-by: Cedric Nugteren Reviewed-by: Maarten Lankhorst Tested-by: Umang Jain --- Changes since v1: - Now re-using the GParamSpec variables instead of re-creating. - Use bool instead of gboolean for enable_auto_focus. - Remove changes from the reconfigure_element functions. Changes since v2: - Fix a typo in the commit message (remove 'it'). - Fix the link to the actual bug. - Apply the style suggestions of utils/checkstyle.py. - Start the commit message with 'gstreamer:'. - Change the boolean to a 3-option AfMode enum and change variable names and strings accordingly. Changes since v3: - Removed a period at the end of the bug link. - Split the long sentence in the commit message in three parts. - Remove unnecessary use of "libcamera::". - Use controls::AfModeEnum enum instead of int. - Add a newline before 'g_param_spec_enum'. --- src/gstreamer/gstlibcameraprovider.cpp | 14 ++++++++++++ src/gstreamer/gstlibcamerasrc.cpp | 31 +++++++++++++++++++++++++- src/gstreamer/gstlibcamerasrc.h | 31 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/gstreamer/gstlibcameraprovider.cpp b/src/gstreamer/gstlibcameraprovider.cpp index 6eb0a0eb..d9216046 100644 --- a/src/gstreamer/gstlibcameraprovider.cpp +++ b/src/gstreamer/gstlibcameraprovider.cpp @@ -31,6 +31,7 @@ GST_DEBUG_CATEGORY_STATIC(provider_debug); enum { PROP_DEVICE_NAME = 1, + PROP_AUTO_FOCUS_MODE = 2, }; #define GST_TYPE_LIBCAMERA_DEVICE gst_libcamera_device_get_type() @@ -40,6 +41,7 @@ G_DECLARE_FINAL_TYPE(GstLibcameraDevice, gst_libcamera_device, struct _GstLibcameraDevice { GstDevice parent; gchar *name; + controls::AfModeEnum auto_focus_mode = controls::AfModeManual; }; G_DEFINE_TYPE(GstLibcameraDevice, gst_libcamera_device, GST_TYPE_DEVICE) @@ -56,6 +58,7 @@ gst_libcamera_device_create_element(GstDevice *device, const gchar *name) g_assert(source); g_object_set(source, "camera-name", GST_LIBCAMERA_DEVICE(device)->name, nullptr); + g_object_set(source, "auto-focus-mode", GST_LIBCAMERA_DEVICE(device)->auto_focus_mode, nullptr); return source; } @@ -82,6 +85,9 @@ gst_libcamera_device_set_property(GObject *object, guint prop_id, case PROP_DEVICE_NAME: device->name = g_value_dup_string(value); break; + case PROP_AUTO_FOCUS_MODE: + device->auto_focus_mode = static_cast(g_value_get_enum(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -121,6 +127,14 @@ gst_libcamera_device_class_init(GstLibcameraDeviceClass *klass) (GParamFlags)(G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_DEVICE_NAME, pspec); + pspec = g_param_spec_enum("auto-focus-mode", + "Set auto-focus mode", + "Available options: AfModeManual, " + "AfModeAuto or AfModeContinuous.", + gst_libcamera_auto_focus_get_type(), + static_cast(controls::AfModeManual), + G_PARAM_WRITABLE); + g_object_class_install_property(object_class, PROP_AUTO_FOCUS_MODE, pspec); } static GstDevice * diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index a10cbd4f..47d8ff43 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -146,6 +146,7 @@ struct _GstLibcameraSrc { GstTask *task; gchar *camera_name; + controls::AfModeEnum auto_focus_mode = controls::AfModeManual; GstLibcameraSrcState *state; GstLibcameraAllocator *allocator; @@ -154,7 +155,8 @@ struct _GstLibcameraSrc { enum { PROP_0, - PROP_CAMERA_NAME + PROP_CAMERA_NAME, + PROP_AUTO_FOCUS_MODE, }; G_DEFINE_TYPE_WITH_CODE(GstLibcameraSrc, gst_libcamera_src, GST_TYPE_ELEMENT, @@ -577,6 +579,18 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_flow_combiner_add_pad(self->flow_combiner, srcpad); } + if (self->auto_focus_mode != controls::AfModeManual) { + const ControlInfoMap &infoMap = state->cam_->controls(); + if (infoMap.find(&controls::AfMode) != infoMap.end()) { + state->initControls_.set(controls::AfMode, self->auto_focus_mode); + } else { + GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, + ("Failed to enable auto focus"), + ("AfMode not supported by this camera, " + "please retry with 'auto-focus-mode=AfModeManual'")); + } + } + ret = state->cam_->start(&state->initControls_); if (ret) { GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, @@ -659,6 +673,9 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id, g_free(self->camera_name); self->camera_name = g_value_dup_string(value); break; + case PROP_AUTO_FOCUS_MODE: + self->auto_focus_mode = static_cast(g_value_get_enum(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -676,6 +693,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value, case PROP_CAMERA_NAME: g_value_set_string(value, self->camera_name); break; + case PROP_AUTO_FOCUS_MODE: + g_value_set_enum(value, static_cast(self->auto_focus_mode)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -844,4 +864,13 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass) | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec); + + spec = g_param_spec_enum("auto-focus-mode", + "Set auto-focus mode", + "Available options: AfModeManual, " + "AfModeAuto or AfModeContinuous.", + gst_libcamera_auto_focus_get_type(), + static_cast(controls::AfModeManual), + G_PARAM_WRITABLE); + g_object_class_install_property(object_class, PROP_AUTO_FOCUS_MODE, spec); } diff --git a/src/gstreamer/gstlibcamerasrc.h b/src/gstreamer/gstlibcamerasrc.h index fdea2f10..0a88ba02 100644 --- a/src/gstreamer/gstlibcamerasrc.h +++ b/src/gstreamer/gstlibcamerasrc.h @@ -8,6 +8,8 @@ #pragma once +#include + #include G_BEGIN_DECLS @@ -17,3 +19,32 @@ G_DECLARE_FINAL_TYPE(GstLibcameraSrc, gst_libcamera_src, GST_LIBCAMERA, SRC, GstElement) G_END_DECLS + +inline GType +gst_libcamera_auto_focus_get_type() +{ + static GType type = 0; + static const GEnumValue values[] = { + { + static_cast(libcamera::controls::AfModeManual), + "AfModeManual", + "manual-focus", + }, + { + static_cast(libcamera::controls::AfModeAuto), + "AfModeAuto", + "automatic-auto-focus", + }, + { + static_cast(libcamera::controls::AfModeContinuous), + "AfModeContinuous", + "continuous-auto-focus", + }, + { 0, NULL, NULL } + }; + + if (!type) + type = g_enum_register_static("GstLibcameraAutoFocus", values); + + return type; +}