From patchwork Wed Nov 22 13:43:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaslo Ziska X-Patchwork-Id: 19224 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 85CEDC3220 for ; Wed, 22 Nov 2023 13:55:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3C1F5629BC; Wed, 22 Nov 2023 14:55:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700661321; bh=oWgg1wo9IWt/LYBkpHt4MOBNEMDRQsTaL5IYb22BJOI=; 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=U3ybrzVxD3bz5HpNgE/kYpxLJ1Ka7BUxixa2cFA2JoCI+h+lEGebmnhVuODC0Od/s 5DOaB5mU2O7ARpbiPh08DWrmdcZn9FxvXqgE0rjW9AzEbAlAY/Al3fXrcy8NPTYjey SBRYuPGJTQlUoo2BBsaKHtDFm7sFCgB46stj2TLjoTi515xTkPp9XYzmtkqeaPAOn/ 0ok/VukpGBfsjd5nAlMdmmnXTpoVTpcJOViPvkchZDu0F+gJ5EJbBRbkWlne4T54d+ BjVlIe+hLxMdFJSAq4PRZAe9lA/Bua4kwunkRZCqnEuu/f3Lbza91zjbGIgr1bwUR+ z6DHnspPfdIfg== Received: from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de [81.169.146.221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4827A61DAD for ; Wed, 22 Nov 2023 14:55:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=ziska.de header.i=@ziska.de header.b="Yf1/24Nq"; dkim=permerror (0-bit key) header.d=ziska.de header.i=@ziska.de header.b="+f051/ws"; dkim-atps=neutral ARC-Seal: i=1; a=rsa-sha256; t=1700661319; cv=none; d=strato.com; s=strato-dkim-0002; b=beJUcUvboQ0Jnz3ZHkuu2AEIuHmCscvSgOiXPNWORvn2otEFDPvQ3W9r1TNeFwl/YK X68q8eJBMiGpAIgKjbhZRSAaIMEi/4zSBzjWNr5QMCQI6eo8YekOIHo89Bcqqt5YRjEa RmkWGxmSjJJ5cr+MgQHUtUCsX9NhXRoN5f0nEusFWsQin+Z9MT28GFmTKLXrICAsQ6Ek R4bxE1HZCcXR05QaZDU1T3LKTKa40dhxcSBOXZfS9Ki0PAQgD+fRlHuxoKJqoqR0dsXc OFIucUbsYAms8LRRIbCGrHoeMKwlDe8wcMPuh1tppB5+R9ZaFjMz6Ips2oQiQr/x5VRo KLAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1700661319; 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=fS0xtz0syGlJKn1HAlsQzRye2dlfXH4niWK15M5Wh0w=; b=t1nrEcFDZhqi5ar1Yf25JpzLxJ3a5J3A1L2wbgT9cDCthnoxLsbai6FFv5hNsP+C4i umzHcaU6M8XgWpqeuH8gNT0TtFVIDyEhIMKBFd8WoIJM6+bpC8JigS+t3AMIaiFLQ7QZ XQ7rsAUfz3WcX+NGP93i9ozAZ681DyJIFekQp+YNjWu2zcczWmPpD9T2br4oiw/4/qqq pWD6JWRX4Mu1DvtH+PGGcgK6TtvD/BO+zTGocUyCk9+V8E0wwHMyMtIRPp+mntsARWE6 tPl+kRGmSwFBetR3UyvH36wAUpNxysFDNhUB/0xQQKpsmRZvEPNNPqfsAep92Jht3Ope 6W0Q== 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=1700661319; 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=fS0xtz0syGlJKn1HAlsQzRye2dlfXH4niWK15M5Wh0w=; b=Yf1/24NqRQgbf8fwCqPTCeCOk35qgILMBHXsGDxadplWyxidRbP88cwuCYkbAuDc56 J45bwOO0V8EdJG0MkhrqgK2AMsXQdV+Oz84Dv/kO2ZrCwH7/lFSIGl4iKQ8hk1Jyv4JU JtLLQYl0yZ983ObPG80TYAHW2vjnlnSQ1l3xBpLAA6/BYcW63fpvmUZHynGSb4hWmguI YxlDNAog0/XA239WkqiyKwQGM5CA+5g+aCtJs9PNpqOgYm50MLnFx+WmcF0sC/Sv8EYB lBeCkuKPnv/m0bvql51gfP6Qgi+TzsqdM9hAqz4N9pdfyNNyhPM8XFOlKf+1aY2bKESG 2RfQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1700661319; 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=fS0xtz0syGlJKn1HAlsQzRye2dlfXH4niWK15M5Wh0w=; b=+f051/ws0gMdFdTqD3ATo6yUn1HY+qZFoci7MShMYqH/6eDZpYdweNswH+oacNR52p tuv9fUYDcfjJxRNLT3CQ== X-RZG-AUTH: ":Jm0XeU+IYfb0x77LHmrjN5Wlb7TBwusDqIM6Hizy8VdfzvKi4yoFC9cG0Yq6UfJaraj+i8jcRUV7OSd6ZI2VJZzV+od9" Received: from archlinux.fritz.box by smtp.strato.de (RZmta 49.9.1 AUTH) with ESMTPSA id j3f4eezAMDtJnQ1 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Wed, 22 Nov 2023 14:55:19 +0100 (CET) To: libcamera-devel@lists.libcamera.org Date: Wed, 22 Nov 2023 14:43:54 +0100 Message-ID: <20231122135406.14921-2-jaslo@ziska.de> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231122135406.14921-1-jaslo@ziska.de> References: <20231122135406.14921-1-jaslo@ziska.de> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] 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 --- src/gstreamer/gstlibcamerasrc.cpp | 176 +++++++++++++++--------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 767017db..e7a49fef 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -379,6 +379,87 @@ gst_libcamera_src_open(GstLibcameraSrc *self) return true; } +static gboolean +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 +549,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,89 +578,22 @@ 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; gst_segment_init(&segment, GST_FORMAT_TIME); 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) { @@ -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