From patchwork Thu Aug 26 14:16:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Dufresne X-Patchwork-Id: 13514 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 D150DBD87C for ; Thu, 26 Aug 2021 14:16:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0475168915; Thu, 26 Aug 2021 16:16:14 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E45B66888F for ; Thu, 26 Aug 2021 16:16:12 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nicolas) with ESMTPSA id E36C11F443FF From: Nicolas Dufresne To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Aug 2021 10:16:02 -0400 Message-Id: <20210826141602.1243989-1-nicolas@ndufresne.ca> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2] gstreamer: Fix usage of default size for fixation 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: , Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Nicolas Dufresne Pipeline managers sets a default value to StreamConfiguration::size. The original fixation code was attempting to use it, but as it was truncating the caps to its first structure it would never actually find a best match. In this patch, instead of truncating, we weight various matches using the product of the width and height delta. We also split delta from ranges apart and prefer fixed size over them as ranges are not reliable. This patch also removes the related todo, as it seems that libcamera core won't go further then providing this default value and won't be sorting the format and size lists. Signed-off-by: Nicolas Dufresne Tested-by: Kieran Bingham Reviewed-by: Kieran Bingham --- src/gstreamer/gstlibcamera-utils.cpp | 51 +++++++++++++++++++++++++--- src/gstreamer/gstlibcamerasrc.cpp | 4 --- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index 61370d5f..723c4fa3 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -136,14 +136,57 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg, GstCaps *caps) { GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat); + guint i; + gint best_fixed = -1, best_in_range = -1; + GstStructure *s; + + /* + * These are delta weight computed from: + * ABS(width - stream_cfg.size.width) * ABS(height - stream_cfg.size.height) + */ + guint best_fixed_delta = G_MAXUINT; + guint best_in_range_delta = G_MAXUINT; /* First fixate the caps using default configuration value. */ g_assert(gst_caps_is_writable(caps)); - caps = gst_caps_truncate(caps); - GstStructure *s = gst_caps_get_structure(caps, 0); - gst_structure_fixate_field_nearest_int(s, "width", stream_cfg.size.width); - gst_structure_fixate_field_nearest_int(s, "height", stream_cfg.size.height); + /* Lookup the structure for a close match to the stream_cfg.size */ + for (i = 0; i < gst_caps_get_size(caps); i++) { + s = gst_caps_get_structure(caps, i); + gint width, height; + guint delta; + + if (gst_structure_has_field_typed(s, "width", G_TYPE_INT) && + gst_structure_has_field_typed(s, "height", G_TYPE_INT)) { + gst_structure_get_int(s, "width", &width); + gst_structure_get_int(s, "height", &height); + + delta = ABS(width - (gint)stream_cfg.size.width) * ABS(height - (gint)stream_cfg.size.height); + + if (delta < best_fixed_delta) { + best_fixed_delta = delta; + best_fixed = i; + } + } else { + gst_structure_fixate_field_nearest_int(s, "width", stream_cfg.size.width); + gst_structure_fixate_field_nearest_int(s, "height", stream_cfg.size.height); + gst_structure_get_int(s, "width", &width); + gst_structure_get_int(s, "height", &height); + + delta = ABS(width - (gint)stream_cfg.size.width) * ABS(height - (gint)stream_cfg.size.height); + + if (delta < best_in_range_delta) { + best_in_range_delta = delta; + best_in_range = i; + } + } + } + + /* Prefer reliable fixed value over ranges */ + if (best_fixed >= 0) + s = gst_caps_get_structure(caps, best_fixed); + else + s = gst_caps_get_structure(caps, best_in_range); if (gst_structure_has_name(s, "video/x-raw")) { const gchar *format = gst_video_format_to_string(gst_format); diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index b243aeb3..4c7b36ae 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -25,10 +25,6 @@ * - Add timestamp support * - Use unique names to select the camera devices * - Add GstVideoMeta support (strides and offsets) - * - * \todo libcamera UVC drivers picks the lowest possible resolution first, this - * should be fixed so that we get a decent resolution and framerate for the - * role by default. */ #include "gstlibcamerasrc.h"