mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-06-10 10:09:28 +00:00
v4l2src: Consider framerate during caps selection
This simplifies the way it picks the closest caps to preference and take into consideration the framerate to avoid picking high resolution at 5fps or so. Simply calculate a "distance" of caps A and B from the preference and put closest first, sorting by framerate first. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5956>
This commit is contained in:
parent
533b28cd6a
commit
0ce3a2782c
|
@ -438,68 +438,41 @@ gst_v4l2_src_parse_fixed_struct (GstStructure * s,
|
|||
gst_structure_get_fraction (s, "framerate", fps_n, fps_d);
|
||||
}
|
||||
|
||||
/* TODO Consider framerate */
|
||||
static gint
|
||||
gst_v4l2src_fixed_caps_compare (GstCaps * caps_a, GstCaps * caps_b,
|
||||
struct PreferredCapsInfo *pref)
|
||||
{
|
||||
GstStructure *a, *b;
|
||||
gint aw = G_MAXINT, ah = G_MAXINT, ad = G_MAXINT;
|
||||
gint bw = G_MAXINT, bh = G_MAXINT, bd = G_MAXINT;
|
||||
gint ret;
|
||||
gint aw = G_MAXINT, ah = G_MAXINT;
|
||||
gint bw = G_MAXINT, bh = G_MAXINT;
|
||||
gint a_fps_n = G_MAXINT, a_fps_d = 1;
|
||||
gint b_fps_n = G_MAXINT, b_fps_d = 1;
|
||||
gint a_distance, b_distance;
|
||||
|
||||
a = gst_caps_get_structure (caps_a, 0);
|
||||
b = gst_caps_get_structure (caps_b, 0);
|
||||
|
||||
gst_v4l2_src_parse_fixed_struct (a, &aw, &ah, NULL, NULL);
|
||||
gst_v4l2_src_parse_fixed_struct (b, &bw, &bh, NULL, NULL);
|
||||
gst_v4l2_src_parse_fixed_struct (a, &aw, &ah, &a_fps_n, &a_fps_d);
|
||||
gst_v4l2_src_parse_fixed_struct (b, &bw, &bh, &b_fps_n, &b_fps_d);
|
||||
|
||||
/* When both are smaller then pref, just append to the end */
|
||||
if ((bw < pref->width || bh < pref->height)
|
||||
&& (aw < pref->width || ah < pref->height)) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
// Sort first the one with closest framerate to preference. Note that any
|
||||
// framerate lower then 1 frame per second will be considered the same. In
|
||||
// practice this should be fine considering that these framerate only exists
|
||||
// for still picture, in which case the resolution is most likely the key.
|
||||
a_distance = ABS ((a_fps_n / a_fps_d) - (pref->fps_n / pref->fps_d));
|
||||
b_distance = ABS ((b_fps_n / b_fps_d) - (pref->fps_n / pref->fps_d));
|
||||
if (a_distance != b_distance)
|
||||
return a_distance - b_distance;
|
||||
|
||||
/* If a is smaller then pref and not b, then a goes after b */
|
||||
if (aw < pref->width || ah < pref->height) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
// If same framerate, sort first the one with closest resolution to preference
|
||||
a_distance = ABS (aw * ah - pref->width * pref->height);
|
||||
b_distance = ABS (bw * bh - pref->width * pref->height);
|
||||
|
||||
/* If b is smaller then pref and not a, then a goes before b */
|
||||
if (bw < pref->width || bh < pref->height) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
gint ret = a_distance - b_distance;
|
||||
|
||||
/* Both are larger or equal to the preference, prefer the smallest */
|
||||
ad = MAX (1, aw - pref->width) * MAX (1, ah - pref->height);
|
||||
bd = MAX (1, bw - pref->width) * MAX (1, bh - pref->height);
|
||||
GST_TRACE ("Placing %" GST_PTR_FORMAT " %s %" GST_PTR_FORMAT,
|
||||
caps_a, ret > 0 ? "after" : "before", caps_b);
|
||||
|
||||
/* Adjust slightly in case width/height matched the preference */
|
||||
if (aw == pref->width)
|
||||
ad -= 1;
|
||||
|
||||
if (ah == pref->height)
|
||||
ad -= 1;
|
||||
|
||||
if (bw == pref->width)
|
||||
bd -= 1;
|
||||
|
||||
if (bh == pref->height)
|
||||
bd -= 1;
|
||||
|
||||
/* If the choices are equivalent, maintain the order */
|
||||
if (ad == bd)
|
||||
ret = 1;
|
||||
else
|
||||
ret = ad - bd;
|
||||
|
||||
done:
|
||||
GST_TRACE ("Placing %ix%i (%s) %s %ix%i (%s)", aw, ah,
|
||||
gst_structure_get_string (a, "format"), ret > 0 ? "after" : "before", bw,
|
||||
bh, gst_structure_get_string (b, "format"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue