From a08d7cdef5e20b88f93674a5b1053dc6edee7e18 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 13 Sep 2017 16:05:08 -0400 Subject: [PATCH] v4l2src: Ensure all caps a fixated The code relied on the list compare function to fixate the caps but if the caps only has one structure, the compare function will never get called. Capture device for which there is only one structure in the caps would then get some assertion and later fail badly. Instead, fixate before inserting into the list and split the reading and the fixation of the structures. --- sys/v4l2/gstv4l2src.c | 52 +++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index e98cb79857..9ed87849c8 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -277,46 +277,47 @@ gst_vl42_src_fixate_fields (GQuark field_id, GValue * value, gpointer user_data) static void gst_v4l2_src_fixate_struct_with_preference (GstStructure * s, - struct PreferedCapsInfo *pref, gint * width, gint * height, - gint * fps_n, gint * fps_d) + struct PreferedCapsInfo *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); - if (width) - gst_structure_get_int (s, "width", width); - } - - if (gst_structure_has_field (s, "height")) { + if (gst_structure_has_field (s, "height")) gst_structure_fixate_field_nearest_int (s, "height", pref->height); - if (height) - gst_structure_get_int (s, "height", height); - } - - if (gst_structure_has_field (s, "framerate")) { + if (gst_structure_has_field (s, "framerate")) gst_structure_fixate_field_nearest_fraction (s, "framerate", pref->fps_n, pref->fps_d); - if (fps_n && fps_d) - gst_structure_get_fraction (s, "framerate", fps_n, fps_d); - } - /* Finally, fixate everything else except the interlace-mode and colorimetry * which still need further negotiation as it wasn't probed */ gst_structure_map_in_place (s, gst_vl42_src_fixate_fields, s); } +static void +gst_v4l2_src_parse_fixed_struct (GstStructure * s, + gint * width, gint * height, gint * fps_n, gint * fps_d) +{ + if (gst_structure_has_field (s, "width") && width) + gst_structure_get_int (s, "width", width); + + if (gst_structure_has_field (s, "height") && height) + gst_structure_get_int (s, "height", height); + + if (gst_structure_has_field (s, "framerate") && fps_n && fps_d) + gst_structure_get_fraction (s, "framerate", fps_n, fps_d); +} + /* TODO Consider framerate */ static gint -gst_v4l2src_caps_fixate_and_compare (GstStructure * a, GstStructure * b, +gst_v4l2src_fixed_caps_compare (GstStructure * a, GstStructure * b, struct PreferedCapsInfo *pref) { gint aw = G_MAXINT, ah = G_MAXINT, ad = G_MAXINT; gint bw = G_MAXINT, bh = G_MAXINT, bd = G_MAXINT; - gst_v4l2_src_fixate_struct_with_preference (a, pref, &aw, &ah, NULL, NULL); - gst_v4l2_src_fixate_struct_with_preference (b, pref, &bw, &bh, NULL, NULL); + gst_v4l2_src_parse_fixed_struct (a, &aw, &ah, NULL, NULL); + gst_v4l2_src_parse_fixed_struct (b, &bw, &bh, NULL, NULL); /* When both are smaller then pref, just append to the end */ if ((bw < pref->width || bh < pref->height) @@ -380,16 +381,19 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s) * transformation to happen downstream. */ if (pref_s) { pref_s = gst_structure_copy (pref_s); - gst_v4l2_src_fixate_struct_with_preference (pref_s, &pref, &pref.width, - &pref.height, &pref.fps_n, &pref.fps_d); + 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); } /* Sort the structures to get the caps that is nearest to our preferences, * first */ - while ((s = gst_caps_steal_structure (caps, 0))) + while ((s = gst_caps_steal_structure (caps, 0))) { + gst_v4l2_src_fixate_struct_with_preference (s, &pref); caps_list = g_list_insert_sorted_with_data (caps_list, s, - (GCompareDataFunc) gst_v4l2src_caps_fixate_and_compare, &pref); + (GCompareDataFunc) gst_v4l2src_fixed_caps_compare, &pref); + } while (caps_list) { s = caps_list->data;