diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2.c index 2d60709447..3944a6a2b7 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2.c @@ -62,63 +62,6 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug); #define GST_CAT_DEFAULT v4l2_debug #ifdef GST_V4L2_ENABLE_PROBE -/* This is a minimalist probe, for speed, we only enumerate formats */ -static GstCaps * -gst_v4l2_probe_template_caps (const gchar * device, gint video_fd, - enum v4l2_buf_type type) -{ - gint n; - struct v4l2_fmtdesc format; - GstCaps *caps; - - GST_DEBUG ("Getting %s format enumerations", device); - caps = gst_caps_new_empty (); - - for (n = 0;; n++) { - GstStructure *template; - - memset (&format, 0, sizeof (format)); - - format.index = n; - format.type = type; - - if (ioctl (video_fd, VIDIOC_ENUM_FMT, &format) < 0) - break; /* end of enumeration */ - - GST_LOG ("index: %u", format.index); - GST_LOG ("type: %d", format.type); - GST_LOG ("flags: %08x", format.flags); - GST_LOG ("description: '%s'", format.description); - GST_LOG ("pixelformat: %" GST_FOURCC_FORMAT, - GST_FOURCC_ARGS (format.pixelformat)); - - template = gst_v4l2_object_v4l2fourcc_to_structure (format.pixelformat); - - if (template) { - GstStructure *alt_t = NULL; - - switch (format.pixelformat) { - case V4L2_PIX_FMT_RGB32: - alt_t = gst_structure_copy (template); - gst_structure_set (alt_t, "format", G_TYPE_STRING, "ARGB", NULL); - break; - case V4L2_PIX_FMT_BGR32: - alt_t = gst_structure_copy (template); - gst_structure_set (alt_t, "format", G_TYPE_STRING, "BGRA", NULL); - default: - break; - } - - gst_caps_append_structure (caps, template); - - if (alt_t) - gst_caps_append_structure (caps, alt_t); - } - } - - return gst_caps_simplify (caps); -} - static gboolean gst_v4l2_probe_and_register (GstPlugin * plugin) { @@ -126,6 +69,7 @@ gst_v4l2_probe_and_register (GstPlugin * plugin) gint video_fd = -1; struct v4l2_capability vcap; guint32 device_caps; + enum v4l2_buf_type output_type, capture_type; v4l2_element_init (plugin); @@ -140,6 +84,7 @@ gst_v4l2_probe_and_register (GstPlugin * plugin) if (video_fd >= 0) close (video_fd); + /* FIXME, missing libv4l2 support */ video_fd = open (it->device_path, O_RDWR | O_CLOEXEC); if (video_fd == -1) { @@ -150,7 +95,8 @@ gst_v4l2_probe_and_register (GstPlugin * plugin) memset (&vcap, 0, sizeof (vcap)); if (ioctl (video_fd, VIDIOC_QUERYCAP, &vcap) < 0) { - GST_DEBUG ("Failed to get device capabilities: %s", g_strerror (errno)); + GST_DEBUG ("Failed to get device '%s' capabilities: %s", + it->device_path, g_strerror (errno)); continue; } @@ -162,26 +108,33 @@ gst_v4l2_probe_and_register (GstPlugin * plugin) if (!GST_V4L2_IS_M2M (device_caps)) continue; + if (device_caps & V4L2_CAP_VIDEO_M2M_MPLANE) { + output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + } else { + output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + GST_DEBUG ("Probing '%s' located at '%s'", it->device_name ? it->device_name : (const gchar *) vcap.driver, it->device_path); /* get sink supported format (no MPLANE for codec) */ - sink_caps = gst_caps_merge (gst_v4l2_probe_template_caps (it->device_path, - video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT), - gst_v4l2_probe_template_caps (it->device_path, video_fd, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)); - + sink_caps = gst_v4l2_object_probe_template_caps (it->device_path, + video_fd, output_type); /* get src supported format */ - src_caps = gst_caps_merge (gst_v4l2_probe_template_caps (it->device_path, - video_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE), - gst_v4l2_probe_template_caps (it->device_path, video_fd, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)); + src_caps = gst_v4l2_object_probe_template_caps (it->device_path, + video_fd, capture_type); /* Skip devices without any supported formats */ if (gst_caps_is_empty (sink_caps) || gst_caps_is_empty (src_caps)) { gst_caps_unref (sink_caps); gst_caps_unref (src_caps); + + GST_DEBUG ("Skipping unsupported device '%s' located at '%s'", + it->device_name ? it->device_name : (const gchar *) vcap.driver, + it->device_path); continue; } diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c index 4d39819483..1431b98b42 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c @@ -1696,7 +1696,8 @@ add_non_colorimetry_caps (GstV4l2Object * v4l2object, GstCaps * caps) } static GstCaps * -gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags) +gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags, + const GstV4L2FormatDesc * formats, const guint len) { GstStructure *structure; GstCaps *caps, *caps_interlaced; @@ -1704,10 +1705,10 @@ gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags) caps = gst_caps_new_empty (); caps_interlaced = gst_caps_new_empty (); - for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) { - guint32 fourcc = gst_v4l2_formats[i].v4l2_format; + for (i = 0; i < len; i++) { + guint32 fourcc = formats[i].v4l2_format; - if ((gst_v4l2_formats[i].flags & flags) == 0) + if ((formats[i].flags & flags) == 0) continue; structure = gst_v4l2_object_v4l2fourcc_to_bare_struct (fourcc); @@ -1715,7 +1716,7 @@ gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags) if (structure) { GstStructure *alt_s = NULL; - if (gst_v4l2_formats[i].flags & GST_V4L2_RESOLUTION_AND_RATE) { + if (formats[i].flags & GST_V4L2_RESOLUTION_AND_RATE) { gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, @@ -1757,7 +1758,8 @@ gst_v4l2_object_get_all_caps (void) static GstCaps *caps = NULL; if (g_once_init_enter (&caps)) { - GstCaps *all_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_ALL); + GstCaps *all_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_ALL, + gst_v4l2_formats, GST_V4L2_FORMAT_COUNT); GST_MINI_OBJECT_FLAG_SET (all_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); g_once_init_leave (&caps, all_caps); } @@ -1771,7 +1773,8 @@ gst_v4l2_object_get_raw_caps (void) static GstCaps *caps = NULL; if (g_once_init_enter (&caps)) { - GstCaps *raw_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_RAW); + GstCaps *raw_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_RAW, + gst_v4l2_formats, GST_V4L2_FORMAT_COUNT); GST_MINI_OBJECT_FLAG_SET (raw_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); g_once_init_leave (&caps, raw_caps); } @@ -1785,7 +1788,8 @@ gst_v4l2_object_get_codec_caps (void) static GstCaps *caps = NULL; if (g_once_init_enter (&caps)) { - GstCaps *codec_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_CODEC); + GstCaps *codec_caps = gst_v4l2_object_get_caps_helper (GST_V4L2_CODEC, + gst_v4l2_formats, GST_V4L2_FORMAT_COUNT); GST_MINI_OBJECT_FLAG_SET (codec_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); g_once_init_leave (&caps, codec_caps); } @@ -1793,6 +1797,46 @@ gst_v4l2_object_get_codec_caps (void) return caps; } +/* This is a minimalist probe, for speed, we only enumerate formats */ +GstCaps * +gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd, + enum v4l2_buf_type type) +{ + GArray *formats = g_array_new (FALSE, TRUE, sizeof (GstV4L2FormatDesc)); + GstCaps *caps; + gint n; + + GST_DEBUG ("Getting %s format enumerations", device); + for (n = 0;; n++) { + const GstV4L2FormatDesc *desc; + struct v4l2_fmtdesc fmtdesc = { + .index = n, + .type = type, + }; + + /* FIXME, missing libv4l2 support */ + if (ioctl (video_fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) + break; /* end of enumeration */ + + GST_LOG ("index: %u", fmtdesc.index); + GST_LOG ("type: %d", fmtdesc.type); + GST_LOG ("flags: %08x", fmtdesc.flags); + GST_LOG ("description: '%s'", fmtdesc.description); + GST_LOG ("pixelformat: %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (fmtdesc.pixelformat)); + + desc = gst_v4l2_object_get_desc_from_v4l2fourcc (fmtdesc.pixelformat); + if (desc) + g_array_append_val (formats, *desc); + } + + caps = gst_v4l2_object_get_caps_helper (GST_V4L2_ALL, + (const GstV4L2FormatDesc *) formats->data, formats->len); + g_array_free (formats, TRUE); + + return caps; +} + /* collect data for the given caps * @caps: given input caps * @format: location for the v4l format diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h index 1485fbe91f..2e8d9264da 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h @@ -296,6 +296,9 @@ GstCaps* gst_v4l2_object_get_raw_caps (void); GstCaps* gst_v4l2_object_get_codec_caps (void); +GstCaps* gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd, + enum v4l2_buf_type type); + gboolean gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error); gboolean gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error); gboolean gst_v4l2_object_try_import (GstV4l2Object * v4l2object, GstBuffer * buffer);