mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-30 02:58:24 +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/5777>
This commit is contained in:
parent
81169fca8e
commit
b80f4a1fa4
1 changed files with 21 additions and 48 deletions
|
@ -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