#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)
{
gint video_fd = -1;
struct v4l2_capability vcap;
guint32 device_caps;
+ enum v4l2_buf_type output_type, capture_type;
v4l2_element_init (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) {
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;
}
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;
}
}
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;
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);
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,
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);
}
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);
}
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);
}
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