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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7540>
This commit is contained in:
Nicolas Dufresne 2024-08-15 13:07:31 -04:00 committed by GStreamer Marge Bot
parent 7fb16f0b11
commit e97a954008
3 changed files with 75 additions and 75 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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);