From patchwork Sun Aug 28 14:56:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rishikesh Donadkar X-Patchwork-Id: 17216 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 2C244C0DA4 for ; Sun, 28 Aug 2022 14:56:52 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7472761FC0; Sun, 28 Aug 2022 16:56:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661698611; bh=FN53VUar5tGP6AqTXgv+rSzxWCTgO92p7kxc0OVHA/s=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=2M+NhmGRx685vFNcXMQuIdTc65AMCvSpzU/JStbnpdgC276gLoNrAU14QF7mgPBkz Aox6Ctuj9jLLVb7TZvz7nY6p5UfSFyv4kY40Vsx46l6CcCe2CoKCjL3Ufcf/FbcZKT 8atY4pfgyWr7cS5idIZSE7K1ddBc+HvwmKHRIeTHYCoWPy7XwUlMY7YGJYxvZG7v2c Hi1l/KOqhKRhfCQ8ILvbtnDtKTMA1qFlCXiFXShtH/P3mXZpatC2VN4XTEnd9BCIOx 8ZJXrP2zbNmTEkTqn+tPthVDk1akUH6TITOZ6ToGFH73YYEsl6K2RPOAlV5QNHZ1lv S1mC6CzhQuMYg== Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 305BB61FBD for ; Sun, 28 Aug 2022 16:56:49 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Gssls2sS"; dkim-atps=neutral Received: by mail-pf1-x42e.google.com with SMTP id 76so5984072pfy.3 for ; Sun, 28 Aug 2022 07:56:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=Ysbi09SuQEm5ulPFfNHN/3SE38w9Vw1FikBdUGpOivM=; b=Gssls2sSheotNRpk5a5ai9X+C1Q87jXnzNmbmYxkMpmm0XEbh8UKkwO+/ALX+IHn0C 6nPDgGslZraNAaLubIySQcHgN6+voSGzBWpKVsEUCrK6stLuWvoYAiiZBqPTlU0w+z+s RcK/XxqqKKPIBe3yNT5DnLUwSdgrKpN7wv6VI/mPwnLU/xReM6qb5nZHoJoz+fEwvm1e QokpSHdeFUJKMcmtYuarOdJ7v1Fj6+GZ/S3W2I//RCQ/5PdhB02Hmo+npq25BOrKNPAE 1qacJA1tR2kd+2LrS4y1XeZciqhOzs9nKAFA91biZsPx58NVwp76Gsm8JSZwwziMLRXf Q5EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=Ysbi09SuQEm5ulPFfNHN/3SE38w9Vw1FikBdUGpOivM=; b=7eR/thh6N6+22jrWtLOMjH5e8Xi2zNTQpOGFZzC7cVBfnED8Mvn03vM6MqtnAOBr9L Th9Pukd0HjIDI+lfzizLO1zaouKTILlYQEsrWu72hlsAEgBdsBFb/cpT1t+xZp/qmdej oq1krwa2U1YeYUEu8L/xK5XtSfXSD1rc/T0Ag9doeoUcevfBwHKwMgG2gJYcycYX/KM2 31ctRxTGoE01Jw0ATi/096qfmLymRwLEV4NfXhEE9iXEFKtkYDiStUgZ60NWjGhE4w44 x5bRDNgP3IqsIzCzvpKjod4SFjG+ddMxHRJ8/cvsqXGfUIUwXzHJWicSUcgcXwZK1Tcu njNA== X-Gm-Message-State: ACgBeo3walv+CRbJBVzf/21rWgHK5zBTAujVmxG6OLLMoQIwvOs0wphG 9s52p8ieGde2a6Ji5GVB4KIBCLrqH08KQY9O X-Google-Smtp-Source: AA6agR67iwirdfvl61M1aZ13ON8wtThzPSZquaWcHkfm4GqVum6koHZZmGvwEU59RBgR0Ox67inI7w== X-Received: by 2002:a63:5418:0:b0:42a:d773:cbd6 with SMTP id i24-20020a635418000000b0042ad773cbd6mr10656617pgb.106.1661698607186; Sun, 28 Aug 2022 07:56:47 -0700 (PDT) Received: from localhost.localdomain ([49.36.103.8]) by smtp.googlemail.com with ESMTPSA id p63-20020a622942000000b005321340753fsm5356002pfp.103.2022.08.28.07.56.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Aug 2022 07:56:46 -0700 (PDT) To: libcamera-devel@lists.libcamera.org Date: Sun, 28 Aug 2022 20:26:30 +0530 Message-Id: <20220828145630.51618-1-rishikeshdonadkar@gmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1] gstreamer: Provide framerate support for libcamerasrc. 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: Rishikesh Donadkar via libcamera-devel From: Rishikesh Donadkar Reply-To: Rishikesh Donadkar Cc: Rishikesh Donadkar , nicolas.dufresne@collabora.com, vedantparanjape160201@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This patch aims to add framerate support to libcamerasrc in the direction gstreamer->libcamera. Add a field of the type ControlList to GstLibcameraSrcState. Get the framerate from the caps and convert it to FrameDuration. Set the FrameDurationLimits control in the initControls_ and pass the initControls_ at the time of starting camera. Signed-off-by: Umang Jain Signed-off-by: Rishikesh Donadkar --- Tested the patch with 3 different framerates with the help of the fpsdisplaysink element. https://paste.debian.net/1251951/ https://paste.debian.net/1251952/ https://paste.debian.net/1251953/ --- src/gstreamer/gstlibcamera-utils.cpp | 18 ++++++++++++++++++ src/gstreamer/gstlibcamera-utils.h | 3 +++ src/gstreamer/gstlibcamerasrc.cpp | 7 ++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index 5a21a391..7d8519da 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -8,6 +8,7 @@ #include "gstlibcamera-utils.h" +#include #include using namespace libcamera; @@ -236,6 +237,23 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg, stream_cfg.size.height = height; } +void +gst_libcamera_configure_controls_from_caps(ControlList &controls, [[maybe_unused]] GstCaps *caps) +{ + /* read framerate from caps - convert to integer and set to frame_time. */ + GstStructure *s = gst_caps_get_structure(caps, 0); + gint fps_n = -1, fps_d = -1; + if (gst_structure_has_field(s, "framerate")) + gst_structure_get_fraction(s, "framerate", &fps_n, &fps_d); + + if (fps_n < 0 || fps_d < 0) + return; + + gdouble frame_duration = static_cast(fps_d) / static_cast(fps_n) * 1000000.0; + controls.set(controls::FrameDurationLimits, + Span({ static_cast(frame_duration), static_cast(frame_duration) })); +} + #if !GST_CHECK_VERSION(1, 17, 1) gboolean gst_task_resume(GstTask *task) diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h index 164189a2..1f737e84 100644 --- a/src/gstreamer/gstlibcamera-utils.h +++ b/src/gstreamer/gstlibcamera-utils.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -18,6 +19,8 @@ GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &fo GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg); void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg, GstCaps *caps); +void gst_libcamera_configure_controls_from_caps(libcamera::ControlList &controls, GstCaps *caps); + #if !GST_CHECK_VERSION(1, 17, 1) gboolean gst_task_resume(GstTask *task); #endif diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 16d70fea..d1080271 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -131,6 +131,7 @@ struct GstLibcameraSrcState { std::queue> completedRequests_ LIBCAMERA_TSA_GUARDED_BY(lock_); + ControlList initControls_; guint group_id_; int queueRequest(); @@ -496,6 +497,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, /* Retrieve the supported caps. */ g_autoptr(GstCaps) filter = gst_libcamera_stream_formats_to_caps(stream_cfg.formats()); g_autoptr(GstCaps) caps = gst_pad_peer_query_caps(srcpad, filter); + if (gst_caps_is_empty(caps)) { flow_ret = GST_FLOW_NOT_NEGOTIATED; break; @@ -504,6 +506,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, /* Fixate caps and configure the stream. */ caps = gst_caps_make_writable(caps); gst_libcamera_configure_stream_from_caps(stream_cfg, caps); + gst_libcamera_configure_controls_from_caps(state->initControls_, caps); } if (flow_ret != GST_FLOW_OK) @@ -524,6 +527,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, const StreamConfiguration &stream_cfg = state->config_->at(i); g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg); + if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps))) { flow_ret = GST_FLOW_NOT_NEGOTIATED; break; @@ -566,7 +570,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_flow_combiner_add_pad(self->flow_combiner, srcpad); } - ret = state->cam_->start(); + ret = state->cam_->start(&state->initControls_); if (ret) { GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, ("Failed to start the camera: %s", g_strerror(-ret)), @@ -576,6 +580,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, } done: + state->initControls_.clear(); switch (flow_ret) { case GST_FLOW_NOT_NEGOTIATED: GST_ELEMENT_FLOW_ERROR(self, flow_ret);