From e97a954008859df24a82ac05003f0bbd95a781b3 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 15 Aug 2024 13:07:31 -0400 Subject: [PATCH] v4l2: Move M2M template caps probe into v4l2object This allow reusing the code that produces output and capture devices templates. This fixes the lack of Interlaced caps feature for M2M devices such as decoder, encoder or converters. Part-of: --- .../gst-plugins-good/sys/v4l2/gstv4l2.c | 87 +++++-------------- .../gst-plugins-good/sys/v4l2/gstv4l2object.c | 60 +++++++++++-- .../gst-plugins-good/sys/v4l2/gstv4l2object.h | 3 + 3 files changed, 75 insertions(+), 75 deletions(-) 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);