From patchwork Thu Nov 30 15:43:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaslo Ziska X-Patchwork-Id: 19257 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 C61C8BDE6B for ; Thu, 30 Nov 2023 15:54:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 85495629C2; Thu, 30 Nov 2023 16:54:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1701359673; bh=sub7EUP7Zgfkfnw+cI5Q6+nxIAuZewzIe/zvYkn6eZk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=rmnmvxSNHX9wyiNanZ7M8hc/auqAAW+MC3HPYopHyLTVOVtWtpFpR+2tUyFm3Jscx 7X3lNSocqXuTfb2S4XEAr46kWSyOak0431S8y4D5xBkdmUuwtTCBGe5AvCFx9aQSGc O4tK3g/mPqtCa0BxXy1Dczl3GOREYL3YQEcYbWN8O6yKasPty8Tcv9SIOAtKQ4w/eO oIkvyoQtkqzGIy4qr6vj8OCmIWVrJLtlI4/S1/CzNv1f2zCbApOglairNyNWC7kCIu VIrInmevsuJPgtvXU5i7y6uh1HghzckifSat6RPVL/wME//B+gCGq38ehpLNwea4gW R/wmjILcuaAyw== Received: from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de [85.215.255.22]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5EAB361DA0 for ; Thu, 30 Nov 2023 16:54:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=ziska.de header.i=@ziska.de header.b="gfIWpS1c"; dkim=permerror (0-bit key) header.d=ziska.de header.i=@ziska.de header.b="c2EcKEd6"; dkim-atps=neutral ARC-Seal: i=1; a=rsa-sha256; t=1701359670; cv=none; d=strato.com; s=strato-dkim-0002; b=kRGk4cQdDddh28Z0QVurZV9LR6iOz5wE95ZNYuAqkkYVQJCdGw9BGoPXwiUR8ShzOW zRbgdJv6xeQFmIoWuanhNWAWPGDzIDr+4xITQZz1saz0r1rheDtHoQEhRR7bbUBFnQGU INixfJZWT++GzyVSYyTw0f0Kvq3OGJkebYd4aNxxMw0D8dUiW8i62gC846DfXM/PjoqP LDDf0fCQQiM2eP2nOyfsvqROF+LygBnYpVBmd6wqqOzUepJXik7aqNMcueKIultmVDhI mGMFtwEELorUsse6YVfc//t11nJbPL1HIbtAx6Ne/L/9UVOjAzILe3BWIHIxuCB1v8zI YNhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1701359670; s=strato-dkim-0002; d=strato.com; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=Oyty/H1OP9OtthVhCEO8NVCcN5ESVTneZvxybMh1zCM=; b=JuhYXYQNxXt1jW9WOyyy0WN07gmxAKM+FPbuFaZhibWLc0kLqtRZSbt3UCKqdSdp+E 9Kn0SizapZDG4grcnm5dBYOD74xsFsUq1UJ/MASxybNTR9U0X7QzZ+FM9QETTWwIbszM BhLLPKp3QUIogmathxWPlEV3naOb1KrCeDypr4ZU7U5zANkQ2elNKBxOj0RX/YUlN4mb JjnTbTJlALTYAiw0etBJ5QrYn/Ce6OWIb6J6w3tZ8jsaN+ttYohmfYdDFDhQKp2Co60c csA7gUqTLkh6M1BgkPEK+Mp/xNigM4LGH1bXyYZIWnfcK9ajrMX+X/OqjBbP6hnFGf2G 67Ww== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1701359670; s=strato-dkim-0002; d=ziska.de; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=Oyty/H1OP9OtthVhCEO8NVCcN5ESVTneZvxybMh1zCM=; b=gfIWpS1cPG8dLWRT87o7sS9WjSJhn0UK+Zyz8gp4r2BHMnc3Q7Hu0nfhnWwQCEt0i+ sHejkB6L/PfL9aTnjAtep10CPu1Hu+wd6tNZg+tRIRu7mP55QEgkJwISXdDKBD9wNh4E D2ML4RzyxYb1jab3/wU+RL/Je2IDIz9UAQNPEEiNhc2jiQlutIgXcbxvqVZtboL9NoKi ktga+2ydr8FBqRvp6HbC1eMVT03AGljLXS+9NOxkM/jFpxE86JHgFC6/xX0rs88aOdts pfnGZUWCD8g/R5MmcOZ7abN+vq3Z/4hiWEvOJRX53fJF5zGJj4qWkfhmfVZ9VZxUM/aO Mq5w== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1701359670; s=strato-dkim-0003; d=ziska.de; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=Oyty/H1OP9OtthVhCEO8NVCcN5ESVTneZvxybMh1zCM=; b=c2EcKEd6WP55Tq2aC9kxRMiH4q53PTtoQY+mKvsaAvvJ0icfe8dJCbUiKuLHxhOTpI ZHGMA4bvOLw/BAIZWLBA== X-RZG-AUTH: ":Jm0XeU+IYfb0x77LHmrjN5Wlb7TBwusDqIM6Hizy8VdfzvKi4yoFC9cH04q6BfJa07bS3ov6I8QOM/V5x+uTrCUtBrk=" Received: from archlinux.fritz.box by smtp.strato.de (RZmta 49.9.7 AUTH) with ESMTPSA id n54b84zAUFsU0SA (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Thu, 30 Nov 2023 16:54:30 +0100 (CET) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Nov 2023 16:43:08 +0100 Message-ID: <20231130155323.13259-2-jaslo@ziska.de> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231130155323.13259-1-jaslo@ziska.de> References: <20231130155323.13259-1-jaslo@ziska.de> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/3] gstreamer: Move negotiation logic to separate function 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: Jaslo Ziska via libcamera-devel From: Jaslo Ziska Reply-To: Jaslo Ziska Cc: Jaslo Ziska Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the code which negotiates all the source pad caps into a separate function called gst_libcamera_src_negotiate. When the negotiation fails this function will return FALSE and TRUE otherwise. Use this function instead of doing the negotiation manually in gst_libcamera_src_task_enter and remove the now redundant error handling code accordingly. Signed-off-by: Jaslo Ziska Reviewed-by: Nicolas Dufresne Reviewed-by: Laurent Pinchart --- src/gstreamer/gstlibcamerasrc.cpp | 178 +++++++++++++++--------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index a6f240f5..e57ba52f 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -379,6 +379,88 @@ gst_libcamera_src_open(GstLibcameraSrc *self) return true; } +/* Must be called with stream_lock held. */ +static bool +gst_libcamera_src_negotiate(GstLibcameraSrc *self) +{ + GstLibcameraSrcState *state = self->state; + + g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps"); + + for (gsize i = 0; i < state->srcpads_.size(); i++) { + GstPad *srcpad = state->srcpads_[i]; + StreamConfiguration &stream_cfg = state->config_->at(i); + + /* 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)) + return false; + + /* Fixate caps and configure the stream. */ + caps = gst_caps_make_writable(caps); + gst_libcamera_configure_stream_from_caps(stream_cfg, caps); + gst_libcamera_get_framerate_from_caps(caps, element_caps); + } + + /* Validate the configuration. */ + if (state->config_->validate() == CameraConfiguration::Invalid) + return false; + + int ret = state->cam_->configure(state->config_.get()); + if (ret) { + GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, + ("Failed to configure camera: %s", g_strerror(-ret)), + ("Camera::configure() failed with error code %i", ret)); + return false; + } + + /* Check frame duration bounds within controls::FrameDurationLimits */ + gst_libcamera_clamp_and_set_frameduration(state->initControls_, + state->cam_->controls(), element_caps); + + /* + * Regardless if it has been modified, create clean caps and push the + * caps event. Downstream will decide if the caps are acceptable. + */ + for (gsize i = 0; i < state->srcpads_.size(); i++) { + GstPad *srcpad = state->srcpads_[i]; + const StreamConfiguration &stream_cfg = state->config_->at(i); + + g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg); + gst_libcamera_framerate_to_caps(caps, element_caps); + + if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps))) + return false; + + } + + if (self->allocator) + g_clear_object(&self->allocator); + + self->allocator = gst_libcamera_allocator_new(state->cam_, state->config_.get()); + if (!self->allocator) { + GST_ELEMENT_ERROR(self, RESOURCE, NO_SPACE_LEFT, + ("Failed to allocate memory"), + ("gst_libcamera_allocator_new() failed.")); + return false; + } + + for (gsize i = 0; i < state->srcpads_.size(); i++) { + GstPad *srcpad = state->srcpads_[i]; + const StreamConfiguration &stream_cfg = state->config_->at(i); + + GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator, + stream_cfg.stream()); + g_signal_connect_swapped(pool, "buffer-notify", + G_CALLBACK(gst_task_resume), self->task); + + gst_libcamera_pad_set_pool(srcpad, pool); + } + + return true; +} + static void gst_libcamera_src_task_run(gpointer user_data) { @@ -468,11 +550,8 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); GLibRecLocker lock(&self->stream_lock); GstLibcameraSrcState *state = self->state; - GstFlowReturn flow_ret = GST_FLOW_OK; gint ret; - g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps"); - GST_DEBUG_OBJECT(self, "Streaming thread has started"); gint stream_id_num = 0; @@ -500,62 +579,16 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, } g_assert(state->config_->size() == state->srcpads_.size()); - for (gsize i = 0; i < state->srcpads_.size(); i++) { - GstPad *srcpad = state->srcpads_[i]; - StreamConfiguration &stream_cfg = state->config_->at(i); - - /* 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; - } - - /* Fixate caps and configure the stream. */ - caps = gst_caps_make_writable(caps); - gst_libcamera_configure_stream_from_caps(stream_cfg, caps); - gst_libcamera_get_framerate_from_caps(caps, element_caps); - } - - if (flow_ret != GST_FLOW_OK) - goto done; - - /* Validate the configuration. */ - if (state->config_->validate() == CameraConfiguration::Invalid) { - flow_ret = GST_FLOW_NOT_NEGOTIATED; - goto done; - } - - ret = state->cam_->configure(state->config_.get()); - if (ret) { - GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, - ("Failed to configure camera: %s", g_strerror(-ret)), - ("Camera::configure() failed with error code %i", ret)); + if (!gst_libcamera_src_negotiate(self)) { + state->initControls_.clear(); + GST_ELEMENT_FLOW_ERROR(self, GST_FLOW_NOT_NEGOTIATED); gst_task_stop(task); - flow_ret = GST_FLOW_NOT_NEGOTIATED; - goto done; + return; } - /* Check frame duration bounds within controls::FrameDurationLimits */ - gst_libcamera_clamp_and_set_frameduration(state->initControls_, - state->cam_->controls(), element_caps); - - /* - * Regardless if it has been modified, create clean caps and push the - * caps event. Downstream will decide if the caps are acceptable. - */ - for (gsize i = 0; i < state->srcpads_.size(); i++) { - GstPad *srcpad = state->srcpads_[i]; - const StreamConfiguration &stream_cfg = state->config_->at(i); - - g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg); - gst_libcamera_framerate_to_caps(caps, element_caps); - - if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps))) { - flow_ret = GST_FLOW_NOT_NEGOTIATED; - break; - } + self->flow_combiner = gst_flow_combiner_new(); + for (GstPad *srcpad : state->srcpads_) { + gst_flow_combiner_add_pad(self->flow_combiner, srcpad); /* Send an open segment event with time format. */ GstSegment segment; @@ -563,28 +596,6 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_pad_push_event(srcpad, gst_event_new_segment(&segment)); } - self->allocator = gst_libcamera_allocator_new(state->cam_, state->config_.get()); - if (!self->allocator) { - GST_ELEMENT_ERROR(self, RESOURCE, NO_SPACE_LEFT, - ("Failed to allocate memory"), - ("gst_libcamera_allocator_new() failed.")); - gst_task_stop(task); - return; - } - - self->flow_combiner = gst_flow_combiner_new(); - for (gsize i = 0; i < state->srcpads_.size(); i++) { - GstPad *srcpad = state->srcpads_[i]; - const StreamConfiguration &stream_cfg = state->config_->at(i); - GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator, - stream_cfg.stream()); - g_signal_connect_swapped(pool, "buffer-notify", - G_CALLBACK(gst_task_resume), task); - - gst_libcamera_pad_set_pool(srcpad, pool); - 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()) { @@ -605,17 +616,6 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_task_stop(task); return; } - -done: - state->initControls_.clear(); - switch (flow_ret) { - case GST_FLOW_NOT_NEGOTIATED: - GST_ELEMENT_FLOW_ERROR(self, flow_ret); - gst_task_stop(task); - break; - default: - break; - } } static void