v4l2src: Refactor to use PreferredCapsInfo structure

Avoid passing around a bare structure for the preference, this removes
the need to copy and free that structure and simplify the code. Also
fix a type in the structure name, Prefered -> Preferred.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/870>
This commit is contained in:
Nicolas Dufresne 2021-02-10 10:48:48 -05:00
parent c0fdaffc55
commit afb412b75d

View file

@ -99,6 +99,14 @@ G_DEFINE_TYPE_WITH_CODE (GstV4l2Src, gst_v4l2src, GST_TYPE_PUSH_SRC,
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION, G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION,
gst_v4l2src_video_orientation_interface_init)); gst_v4l2src_video_orientation_interface_init));
struct PreferredCapsInfo
{
gint width;
gint height;
gint fps_n;
gint fps_d;
};
static void gst_v4l2src_finalize (GstV4l2Src * v4l2src); static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
/* element methods */ /* element methods */
@ -116,7 +124,7 @@ static gboolean gst_v4l2src_decide_allocation (GstBaseSrc * src,
GstQuery * query); GstQuery * query);
static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out); static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
static GstCaps *gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, static GstCaps *gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps,
GstStructure * pref_s); struct PreferredCapsInfo *pref);
static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc); static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc);
static void gst_v4l2src_set_property (GObject * object, guint prop_id, static void gst_v4l2src_set_property (GObject * object, guint prop_id,
@ -248,14 +256,6 @@ gst_v4l2src_get_property (GObject * object,
} }
} }
struct PreferedCapsInfo
{
gint width;
gint height;
gint fps_n;
gint fps_d;
};
static gboolean static gboolean
gst_vl42_src_fixate_fields (GQuark field_id, GValue * value, gpointer user_data) gst_vl42_src_fixate_fields (GQuark field_id, GValue * value, gpointer user_data)
{ {
@ -274,7 +274,7 @@ gst_vl42_src_fixate_fields (GQuark field_id, GValue * value, gpointer user_data)
static void static void
gst_v4l2_src_fixate_struct_with_preference (GstStructure * s, gst_v4l2_src_fixate_struct_with_preference (GstStructure * s,
struct PreferedCapsInfo *pref) struct PreferredCapsInfo *pref)
{ {
if (gst_structure_has_field (s, "width")) if (gst_structure_has_field (s, "width"))
gst_structure_fixate_field_nearest_int (s, "width", pref->width); gst_structure_fixate_field_nearest_int (s, "width", pref->width);
@ -308,7 +308,7 @@ gst_v4l2_src_parse_fixed_struct (GstStructure * s,
/* TODO Consider framerate */ /* 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 PreferedCapsInfo *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, ad = G_MAXINT;
@ -389,12 +389,9 @@ gst_v4l2src_set_format (GstV4l2Src * v4l2src, GstCaps * caps,
} }
static GstCaps * static GstCaps *
gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s) gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps,
struct PreferredCapsInfo *pref)
{ {
/* Let's prefer a good resolutiion as of today's standard. */
struct PreferedCapsInfo pref = {
3840, 2160, 120, 1
};
GstV4l2Src *v4l2src = GST_V4L2SRC (basesrc); GstV4l2Src *v4l2src = GST_V4L2SRC (basesrc);
GstV4l2Object *obj = v4l2src->v4l2object; GstV4l2Object *obj = v4l2src->v4l2object;
GList *caps_list = NULL; GList *caps_list = NULL;
@ -403,17 +400,8 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
GstV4l2Error error = GST_V4L2_ERROR_INIT; GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstCaps *fcaps = NULL; GstCaps *fcaps = NULL;
GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (basesrc, "Fixating caps %" GST_PTR_FORMAT, caps);
GST_DEBUG_OBJECT (basesrc, "Preferred size %ix%i", pref->width, pref->height);
if (pref_s) {
pref_s = gst_structure_copy (pref_s);
gst_v4l2_src_fixate_struct_with_preference (pref_s, &pref);
gst_v4l2_src_parse_fixed_struct (pref_s, &pref.width, &pref.height,
&pref.fps_n, &pref.fps_d);
gst_structure_free (pref_s);
}
GST_DEBUG_OBJECT (basesrc, "Preferred size %ix%i", pref.width, pref.height);
/* Sort the structures to get the caps that is nearest to our preferences, /* Sort the structures to get the caps that is nearest to our preferences,
* first. Use single struct caps for sorting so we preserve the features. */ * first. Use single struct caps for sorting so we preserve the features. */
@ -421,10 +409,10 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
GstCaps *tmp = gst_caps_copy_nth (caps, i); GstCaps *tmp = gst_caps_copy_nth (caps, i);
s = gst_caps_get_structure (tmp, 0); s = gst_caps_get_structure (tmp, 0);
gst_v4l2_src_fixate_struct_with_preference (s, &pref); gst_v4l2_src_fixate_struct_with_preference (s, pref);
caps_list = g_list_insert_sorted_with_data (caps_list, tmp, caps_list = g_list_insert_sorted_with_data (caps_list, tmp,
(GCompareDataFunc) gst_v4l2src_fixed_caps_compare, &pref); (GCompareDataFunc) gst_v4l2src_fixed_caps_compare, pref);
} }
gst_caps_unref (caps); gst_caps_unref (caps);
@ -499,24 +487,25 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
return fcaps; return fcaps;
} }
static GstStructure * static gboolean
gst_v4l2src_query_preferred_dv_timings (GstV4l2Src * v4l2src) gst_v4l2src_query_preferred_dv_timings (GstV4l2Src * v4l2src,
struct PreferredCapsInfo *pref)
{ {
GST_FIXME_OBJECT (v4l2src, "query dv_timings not implements"); GST_FIXME_OBJECT (v4l2src, "query dv_timings not implements");
return NULL; return NULL;
} }
static GstStructure * static gboolean
gst_v4l2src_query_preferred_size (GstV4l2Src * v4l2src) gst_v4l2src_query_preferred_size (GstV4l2Src * v4l2src,
struct PreferredCapsInfo *pref)
{ {
struct v4l2_input in = { 0, }; struct v4l2_input in = { 0, };
GstStructure *pref = NULL;
if (!gst_v4l2_get_input (v4l2src->v4l2object, &in.index)) if (!gst_v4l2_get_input (v4l2src->v4l2object, &in.index))
return NULL; return FALSE;
if (!gst_v4l2_query_input (v4l2src->v4l2object, &in)) if (!gst_v4l2_query_input (v4l2src->v4l2object, &in))
return NULL; return FALSE;
GST_INFO_OBJECT (v4l2src, "Detect input %u as `%s`", in.index, in.name); GST_INFO_OBJECT (v4l2src, "Detect input %u as `%s`", in.index, in.name);
@ -536,18 +525,21 @@ gst_v4l2src_query_preferred_size (GstV4l2Src * v4l2src)
if (in.capabilities & V4L2_IN_CAP_NATIVE_SIZE) { if (in.capabilities & V4L2_IN_CAP_NATIVE_SIZE) {
GST_FIXME_OBJECT (v4l2src, "missing support for native video size"); GST_FIXME_OBJECT (v4l2src, "missing support for native video size");
return FALSE;
} else if (in.capabilities & V4L2_IN_CAP_DV_TIMINGS) { } else if (in.capabilities & V4L2_IN_CAP_DV_TIMINGS) {
return gst_v4l2src_query_preferred_dv_timings (v4l2src); return gst_v4l2src_query_preferred_dv_timings (v4l2src, pref);
} else if (in.capabilities & V4L2_IN_CAP_STD) { } else if (in.capabilities & V4L2_IN_CAP_STD) {
GST_FIXME_OBJECT (v4l2src, "missing support for video standards"); GST_FIXME_OBJECT (v4l2src, "missing support for video standards");
return FALSE;
} }
return pref; return FALSE;
} }
static gboolean static gboolean
gst_v4l2src_negotiate (GstBaseSrc * basesrc) gst_v4l2src_negotiate (GstBaseSrc * basesrc)
{ {
GstV4l2Src *v4l2src = GST_V4L2SRC (basesrc);
GstCaps *thiscaps; GstCaps *thiscaps;
GstCaps *caps = NULL; GstCaps *caps = NULL;
GstCaps *peercaps = NULL; GstCaps *peercaps = NULL;
@ -580,20 +572,29 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
if (caps) { if (caps) {
/* now fixate */ /* now fixate */
if (!gst_caps_is_empty (caps)) { if (!gst_caps_is_empty (caps)) {
GstStructure *pref = NULL; /* Let's prefer a good resolution as of today's standard. */
struct PreferredCapsInfo pref = {
3840, 2160, 120, 1
};
gboolean have_pref;
/* For drivers that has DV timings or other default size query /* For drivers that has DV timings or other default size query
* capabilities, we will prefer that resolution. */ * capabilities, we will prefer that resolution. */
pref = gst_v4l2src_query_preferred_size (GST_V4L2SRC (basesrc)); have_pref = gst_v4l2src_query_preferred_size (v4l2src, &pref);
/* otherwise consider the first structure from peercaps to be a /* otherwise consider the first structure from peercaps to be a
* preference. This is useful for matching a reported native display, * preference. This is useful for matching a reported native display,
* or simply to avoid transformation to happen downstream. */ * or simply to avoid transformation to happen downstream. */
if (!pref && peercaps && !gst_caps_is_any (peercaps)) if (!have_pref && peercaps && !gst_caps_is_any (peercaps)) {
pref = gst_structure_copy (gst_caps_get_structure (peercaps, 0)); GstStructure *pref_s = gst_caps_get_structure (peercaps, 0);
pref_s = gst_structure_copy (pref_s);
gst_v4l2_src_fixate_struct_with_preference (pref_s, &pref);
gst_v4l2_src_parse_fixed_struct (pref_s, &pref.width, &pref.height,
&pref.fps_n, &pref.fps_d);
gst_structure_free (pref_s);
}
caps = gst_v4l2src_fixate (basesrc, caps, pref); caps = gst_v4l2src_fixate (basesrc, caps, &pref);
gst_structure_free (pref);
/* Fixating may fail as we now set the selected format */ /* Fixating may fail as we now set the selected format */
if (!caps) { if (!caps) {