mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-11 16:55:23 +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);
|
gst_structure_get_fraction (s, "framerate", fps_n, fps_d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Consider framerate */
|
|
||||||
static gint
|
static gint
|
||||||
gst_v4l2src_fixed_caps_compare (GstCaps * caps_a, GstCaps * caps_b,
|
gst_v4l2src_fixed_caps_compare (GstCaps * caps_a, GstCaps * caps_b,
|
||||||
struct PreferredCapsInfo *pref)
|
struct PreferredCapsInfo *pref)
|
||||||
{
|
{
|
||||||
GstStructure *a, *b;
|
GstStructure *a, *b;
|
||||||
gint aw = G_MAXINT, ah = G_MAXINT, ad = G_MAXINT;
|
gint aw = G_MAXINT, ah = G_MAXINT;
|
||||||
gint bw = G_MAXINT, bh = G_MAXINT, bd = G_MAXINT;
|
gint bw = G_MAXINT, bh = G_MAXINT;
|
||||||
gint ret;
|
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);
|
a = gst_caps_get_structure (caps_a, 0);
|
||||||
b = gst_caps_get_structure (caps_b, 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 (a, &aw, &ah, &a_fps_n, &a_fps_d);
|
||||||
gst_v4l2_src_parse_fixed_struct (b, &bw, &bh, NULL, NULL);
|
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 */
|
// Sort first the one with closest framerate to preference. Note that any
|
||||||
if ((bw < pref->width || bh < pref->height)
|
// framerate lower then 1 frame per second will be considered the same. In
|
||||||
&& (aw < pref->width || ah < pref->height)) {
|
// practice this should be fine considering that these framerate only exists
|
||||||
ret = 1;
|
// for still picture, in which case the resolution is most likely the key.
|
||||||
goto done;
|
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 same framerate, sort first the one with closest resolution to preference
|
||||||
if (aw < pref->width || ah < pref->height) {
|
a_distance = ABS (aw * ah - pref->width * pref->height);
|
||||||
ret = 1;
|
b_distance = ABS (bw * bh - pref->width * pref->height);
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If b is smaller then pref and not a, then a goes before b */
|
gint ret = a_distance - b_distance;
|
||||||
if (bw < pref->width || bh < pref->height) {
|
|
||||||
ret = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Both are larger or equal to the preference, prefer the smallest */
|
GST_TRACE ("Placing %" GST_PTR_FORMAT " %s %" GST_PTR_FORMAT,
|
||||||
ad = MAX (1, aw - pref->width) * MAX (1, ah - pref->height);
|
caps_a, ret > 0 ? "after" : "before", caps_b);
|
||||||
bd = MAX (1, bw - pref->width) * MAX (1, bh - pref->height);
|
|
||||||
|
|
||||||
/* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue