summaryrefslogtreecommitdiff
path: root/src/gstreamer/gstlibcamera-utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gstreamer/gstlibcamera-utils.cpp')
-rw-r--r--src/gstreamer/gstlibcamera-utils.cpp51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
index f7e0e1c8..0af91c1a 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);