diff options
Diffstat (limited to 'src/gstreamer/gstlibcamera-utils.cpp')
-rw-r--r-- | src/gstreamer/gstlibcamera-utils.cpp | 51 |
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); |