3 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
6 * gstv4l2object.c: base class for V4L2 elements
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Library General Public License as published
10 * by the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. This library is distributed in the hope
12 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
13 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
21 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
22 * with newer GLib versions (>= 2.31.0) */
23 #define GLIB_DISABLE_DEPRECATION_WARNINGS
36 #include <gudev/gudev.h>
39 #include "v4l2_calls.h"
40 #include "gstv4l2tuner.h"
42 #include "gstv4l2videooverlay.h"
44 #include "gstv4l2colorbalance.h"
46 #include "gst/gst-i18n-plugin.h"
48 #include <gst/video/video.h>
50 /* videodev2.h is not versioned and we can't easily check for the presence
51 * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
52 * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
53 #ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
54 #define V4L2_FIELD_INTERLACED_TB 8
55 #define V4L2_FIELD_INTERLACED_BT 9
58 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
59 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
60 #define GST_CAT_DEFAULT v4l2_debug
62 #define DEFAULT_PROP_DEVICE_NAME NULL
63 #define DEFAULT_PROP_DEVICE_FD -1
64 #define DEFAULT_PROP_FLAGS 0
65 #define DEFAULT_PROP_TV_NORM 0
66 #define DEFAULT_PROP_CHANNEL NULL
67 #define DEFAULT_PROP_FREQUENCY 0
68 #define DEFAULT_PROP_IO_MODE GST_V4L2_IO_AUTO
73 V4L2_STD_OBJECT_PROPS,
76 static GSList *gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object);
79 G_LOCK_DEFINE_STATIC (probe_lock);
82 gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
84 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
85 static GList *list = NULL;
90 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
93 G_UNLOCK (probe_lock);
98 static gboolean init = FALSE;
99 static GList *devices = NULL;
103 gst_v4l2_class_probe_devices_with_udev (GstElementClass * klass, gboolean check,
104 GList ** klass_devices)
106 GUdevClient *client = NULL;
111 gchar *device = devices->data;
112 devices = g_list_remove (devices, device);
116 GST_INFO ("Enumerating video4linux devices from udev");
117 client = g_udev_client_new (NULL);
119 GST_WARNING ("Failed to initialize gudev client");
123 item = g_udev_client_query_by_subsystem (client, "video4linux");
125 GUdevDevice *device = item->data;
126 gchar *devnode = g_strdup (g_udev_device_get_device_file (device));
127 gint api = g_udev_device_get_property_as_int (device, "ID_V4L_VERSION");
128 GST_INFO ("Found new device: %s, API: %d", devnode, api);
129 /* Append v4l2 devices only. If api is 0 probably v4l_id has
130 been stripped out of the current udev installation, append
134 ("Couldn't retrieve ID_V4L_VERSION, silly udev installation?");
136 if ((api == 2 || api == 0)) {
137 devices = g_list_append (devices, devnode);
141 g_object_unref (device);
150 g_object_unref (client);
153 *klass_devices = devices;
157 #endif /* HAVE_GUDEV */
160 gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
161 GList ** klass_devices)
164 const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
168 gchar *device = devices->data;
169 devices = g_list_remove (devices, device);
174 * detect /dev entries
176 for (n = 0; n < 64; n++) {
177 for (base = 0; dev_base[base] != NULL; base++) {
179 gchar *device = g_strdup_printf ("%s%d",
184 * does the /dev/ entry exist at all?
186 if (stat (device, &s) == 0) {
188 * yes: is a device attached?
190 if (S_ISCHR (s.st_mode)) {
192 if ((fd = open (device, O_RDWR | O_NONBLOCK)) > 0 || errno == EBUSY) {
196 devices = g_list_append (devices, device);
207 *klass_devices = devices;
213 gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
214 guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
216 GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
221 if (!gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices))
222 gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
223 #else /* !HAVE_GUDEV */
224 gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
225 #endif /* HAVE_GUDEV */
228 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
234 gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
235 guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
237 GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
238 gboolean ret = FALSE;
244 !gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices);
245 #else /* !HAVE_GUDEV */
246 ret = !gst_v4l2_class_probe_devices (klass, TRUE, klass_devices);
247 #endif /* HAVE_GUDEV */
250 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
257 gst_v4l2_class_list_devices (GstElementClass * klass, GList ** klass_devices)
260 GValue value = { 0 };
266 array = g_value_array_new (g_list_length (*klass_devices));
267 item = *klass_devices;
268 g_value_init (&value, G_TYPE_STRING);
270 gchar *device = item->data;
272 g_value_set_string (&value, device);
273 g_value_array_append (array, &value);
277 g_value_unset (&value);
283 gst_v4l2_probe_get_values (GstPropertyProbe * probe,
284 guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
286 GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
287 GValueArray *array = NULL;
291 array = gst_v4l2_class_list_devices (klass, klass_devices);
294 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
302 #define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
304 gst_v4l2_device_get_type (void)
306 static GType v4l2_device_type = 0;
308 if (v4l2_device_type == 0) {
309 static const GFlagsValue values[] = {
310 {V4L2_CAP_VIDEO_CAPTURE, "Device supports video capture", "capture"},
311 {V4L2_CAP_VIDEO_OUTPUT, "Device supports video playback", "output"},
312 {V4L2_CAP_VIDEO_OVERLAY, "Device supports video overlay", "overlay"},
314 {V4L2_CAP_VBI_CAPTURE, "Device supports the VBI capture", "vbi-capture"},
315 {V4L2_CAP_VBI_OUTPUT, "Device supports the VBI output", "vbi-output"},
317 {V4L2_CAP_TUNER, "Device has a tuner or modulator", "tuner"},
318 {V4L2_CAP_AUDIO, "Device has audio inputs or outputs", "audio"},
324 g_flags_register_static ("GstV4l2DeviceTypeFlags", values);
327 return v4l2_device_type;
330 #define GST_TYPE_V4L2_TV_NORM (gst_v4l2_tv_norm_get_type ())
332 gst_v4l2_tv_norm_get_type (void)
334 static GType v4l2_tv_norm = 0;
337 static const GEnumValue tv_norms[] = {
340 {V4L2_STD_NTSC, "NTSC", "NTSC"},
341 {V4L2_STD_NTSC_M, "NTSC-M", "NTSC-M"},
342 {V4L2_STD_NTSC_M_JP, "NTSC-M-JP", "NTSC-M-JP"},
343 {V4L2_STD_NTSC_M_KR, "NTSC-M-KR", "NTSC-M-KR"},
344 {V4L2_STD_NTSC_443, "NTSC-443", "NTSC-443"},
346 {V4L2_STD_PAL, "PAL", "PAL"},
347 {V4L2_STD_PAL_BG, "PAL-BG", "PAL-BG"},
348 {V4L2_STD_PAL_B, "PAL-B", "PAL-B"},
349 {V4L2_STD_PAL_B1, "PAL-B1", "PAL-B1"},
350 {V4L2_STD_PAL_G, "PAL-G", "PAL-G"},
351 {V4L2_STD_PAL_H, "PAL-H", "PAL-H"},
352 {V4L2_STD_PAL_I, "PAL-I", "PAL-I"},
353 {V4L2_STD_PAL_DK, "PAL-DK", "PAL-DK"},
354 {V4L2_STD_PAL_D, "PAL-D", "PAL-D"},
355 {V4L2_STD_PAL_D1, "PAL-D1", "PAL-D1"},
356 {V4L2_STD_PAL_K, "PAL-K", "PAL-K"},
357 {V4L2_STD_PAL_M, "PAL-M", "PAL-M"},
358 {V4L2_STD_PAL_N, "PAL-N", "PAL-N"},
359 {V4L2_STD_PAL_Nc, "PAL-Nc", "PAL-Nc"},
360 {V4L2_STD_PAL_60, "PAL-60", "PAL-60"},
362 {V4L2_STD_SECAM, "SECAM", "SECAM"},
363 {V4L2_STD_SECAM_B, "SECAM-B", "SECAM-B"},
364 {V4L2_STD_SECAM_G, "SECAM-G", "SECAM-G"},
365 {V4L2_STD_SECAM_H, "SECAM-H", "SECAM-H"},
366 {V4L2_STD_SECAM_DK, "SECAM-DK", "SECAM-DK"},
367 {V4L2_STD_SECAM_D, "SECAM-D", "SECAM-D"},
368 {V4L2_STD_SECAM_K, "SECAM-K", "SECAM-K"},
369 {V4L2_STD_SECAM_K1, "SECAM-K1", "SECAM-K1"},
370 {V4L2_STD_SECAM_L, "SECAM-L", "SECAM-L"},
371 {V4L2_STD_SECAM_LC, "SECAM-Lc", "SECAM-Lc"},
376 v4l2_tv_norm = g_enum_register_static ("V4L2_TV_norms", tv_norms);
382 #define GST_TYPE_V4L2_IO_MODE (gst_v4l2_io_mode_get_type ())
384 gst_v4l2_io_mode_get_type (void)
386 static GType v4l2_io_mode = 0;
389 static const GEnumValue io_modes[] = {
390 {GST_V4L2_IO_AUTO, "GST_V4L2_IO_AUTO", "auto"},
391 {GST_V4L2_IO_RW, "GST_V4L2_IO_RW", "rw"},
392 {GST_V4L2_IO_MMAP, "GST_V4L2_IO_MMAP", "mmap"},
393 {GST_V4L2_IO_USERPTR, "GST_V4L2_IO_USERPTR", "userptr"},
394 {GST_V4L2_IO_DMABUF, "GST_V4L2_IO_DMABUF", "dmabuf"},
398 v4l2_io_mode = g_enum_register_static ("GstV4l2IOMode", io_modes);
404 gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
405 const char *default_device)
407 g_object_class_install_property (gobject_class, PROP_DEVICE,
408 g_param_spec_string ("device", "Device", "Device location",
409 default_device, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
410 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
411 g_param_spec_string ("device-name", "Device name",
412 "Name of the device", DEFAULT_PROP_DEVICE_NAME,
413 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
414 g_object_class_install_property (gobject_class, PROP_DEVICE_FD,
415 g_param_spec_int ("device-fd", "File descriptor",
416 "File descriptor of the device", -1, G_MAXINT, DEFAULT_PROP_DEVICE_FD,
417 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
418 g_object_class_install_property (gobject_class, PROP_FLAGS,
419 g_param_spec_flags ("flags", "Flags", "Device type flags",
420 GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS,
421 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
424 * GstV4l2Src:brightness
426 * Picture brightness, or more precisely, the black level
430 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
431 g_param_spec_int ("brightness", "Brightness",
432 "Picture brightness, or more precisely, the black level", G_MININT,
434 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
436 * GstV4l2Src:contrast
438 * Picture contrast or luma gain
442 g_object_class_install_property (gobject_class, PROP_CONTRAST,
443 g_param_spec_int ("contrast", "Contrast",
444 "Picture contrast or luma gain", G_MININT,
446 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
448 * GstV4l2Src:saturation
450 * Picture color saturation or chroma gain
454 g_object_class_install_property (gobject_class, PROP_SATURATION,
455 g_param_spec_int ("saturation", "Saturation",
456 "Picture color saturation or chroma gain", G_MININT,
458 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
462 * Hue or color balance
466 g_object_class_install_property (gobject_class, PROP_HUE,
467 g_param_spec_int ("hue", "Hue",
468 "Hue or color balance", G_MININT,
470 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
479 g_object_class_install_property (gobject_class, PROP_TV_NORM,
480 g_param_spec_enum ("norm", "TV norm",
482 GST_TYPE_V4L2_TV_NORM, DEFAULT_PROP_TV_NORM,
483 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
490 g_object_class_install_property (gobject_class, PROP_IO_MODE,
491 g_param_spec_enum ("io-mode", "IO mode",
493 GST_TYPE_V4L2_IO_MODE, DEFAULT_PROP_IO_MODE,
494 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
497 * GstV4l2Src:extra-controls
499 * Additional v4l2 controls for the device. The controls are identified
500 * by the control name (lowercase with '_' for any non-alphanumeric
505 g_object_class_install_property (gobject_class, PROP_EXTRA_CONTROLS,
506 g_param_spec_boxed ("extra-controls", "Extra Controls",
507 "Extra v4l2 controls (CIDs) for the device",
508 GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
511 * GstV4l2Src:pixel-aspect-ratio
513 * The pixel aspect ratio of the device. This overwrites the pixel aspect
514 * ratio queried from the device.
518 g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
519 g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
520 "Overwrite the pixel aspect ratio of the device", "1/1",
521 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
524 * GstV4l2Src:force-aspect-ratio
526 * When enabled, the pixel aspect ratio queried from the device or set
527 * with the pixel-aspect-ratio property will be enforced.
531 g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
532 g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
533 "When enabled, the pixel aspect ratio will be enforced", TRUE,
534 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
539 gst_v4l2_object_new (GstElement * element,
540 enum v4l2_buf_type type,
541 const char *default_device,
542 GstV4l2GetInOutFunction get_in_out_func,
543 GstV4l2SetInOutFunction set_in_out_func,
544 GstV4l2UpdateFpsFunction update_fps_func)
546 GstV4l2Object *v4l2object;
549 * some default values
551 v4l2object = g_new0 (GstV4l2Object, 1);
553 v4l2object->type = type;
554 v4l2object->formats = NULL;
556 v4l2object->element = element;
557 v4l2object->get_in_out_func = get_in_out_func;
558 v4l2object->set_in_out_func = set_in_out_func;
559 v4l2object->update_fps_func = update_fps_func;
561 v4l2object->video_fd = -1;
562 v4l2object->poll = gst_poll_new (TRUE);
563 v4l2object->active = FALSE;
564 v4l2object->videodev = g_strdup (default_device);
566 v4l2object->norms = NULL;
567 v4l2object->channels = NULL;
568 v4l2object->colors = NULL;
570 v4l2object->xwindow_id = 0;
572 v4l2object->keep_aspect = TRUE;
577 static gboolean gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object);
581 gst_v4l2_object_destroy (GstV4l2Object * v4l2object)
583 g_return_if_fail (v4l2object != NULL);
585 if (v4l2object->videodev)
586 g_free (v4l2object->videodev);
588 if (v4l2object->poll)
589 gst_poll_free (v4l2object->poll);
591 if (v4l2object->channel)
592 g_free (v4l2object->channel);
594 if (v4l2object->formats) {
595 gst_v4l2_object_clear_format_list (v4l2object);
598 if (v4l2object->probed_caps) {
599 gst_caps_unref (v4l2object->probed_caps);
607 gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object)
609 g_slist_foreach (v4l2object->formats, (GFunc) g_free, NULL);
610 g_slist_free (v4l2object->formats);
611 v4l2object->formats = NULL;
617 gst_v4l2_object_prop_to_cid (guint prop_id)
622 case PROP_BRIGHTNESS:
623 cid = V4L2_CID_BRIGHTNESS;
626 cid = V4L2_CID_CONTRAST;
628 case PROP_SATURATION:
629 cid = V4L2_CID_SATURATION;
635 GST_WARNING ("unmapped property id: %d", prop_id);
642 gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
643 guint prop_id, const GValue * value, GParamSpec * pspec)
647 g_free (v4l2object->videodev);
648 v4l2object->videodev = g_value_dup_string (value);
650 case PROP_BRIGHTNESS:
652 case PROP_SATURATION:
655 gint cid = gst_v4l2_object_prop_to_cid (prop_id);
658 if (GST_V4L2_IS_OPEN (v4l2object)) {
659 gst_v4l2_set_attribute (v4l2object, cid, g_value_get_int (value));
666 v4l2object->tv_norm = g_value_get_enum (value);
670 if (GST_V4L2_IS_OPEN (v4l2object)) {
671 GstTuner *tuner = GST_TUNER (v4l2object->element);
672 GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
673 (gchar *) g_value_get_string (value));
676 /* like gst_tuner_set_channel (tuner, channel)
677 without g_object_notify */
678 gst_v4l2_tuner_set_channel (v4l2object, channel);
681 g_free (v4l2object->channel);
682 v4l2object->channel = g_value_dup_string (value);
686 if (GST_V4L2_IS_OPEN (v4l2object)) {
687 GstTuner *tuner = GST_TUNER (v4l2object->element);
688 GstTunerChannel *channel = gst_tuner_get_channel (tuner);
691 GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
693 gst_tuner_set_frequency (tuner, channel, g_value_get_ulong (value))
694 without g_object_notify */
695 gst_v4l2_tuner_set_frequency (v4l2object, channel,
696 g_value_get_ulong (value));
699 v4l2object->frequency = g_value_get_ulong (value);
704 v4l2object->req_mode = g_value_get_enum (value);
706 case PROP_EXTRA_CONTROLS:{
707 const GstStructure *s = gst_value_get_structure (value);
709 if (v4l2object->extra_controls)
710 gst_structure_free (v4l2object->extra_controls);
712 v4l2object->extra_controls = s ? gst_structure_copy (s) : NULL;
713 if (GST_V4L2_IS_OPEN (v4l2object))
714 gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
717 case PROP_PIXEL_ASPECT_RATIO:
718 g_free (v4l2object->par);
719 v4l2object->par = g_new0 (GValue, 1);
720 g_value_init (v4l2object->par, GST_TYPE_FRACTION);
721 if (!g_value_transform (value, v4l2object->par)) {
722 g_warning ("Could not transform string to aspect ratio");
723 gst_value_set_fraction (v4l2object->par, 1, 1);
725 GST_DEBUG_OBJECT (v4l2object->element, "set PAR to %d/%d",
726 gst_value_get_fraction_numerator (v4l2object->par),
727 gst_value_get_fraction_denominator (v4l2object->par));
729 case PROP_FORCE_ASPECT_RATIO:
730 v4l2object->keep_aspect = g_value_get_boolean (value);
741 gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
742 guint prop_id, GValue * value, GParamSpec * pspec)
746 g_value_set_string (value, v4l2object->videodev);
748 case PROP_DEVICE_NAME:
750 const guchar *new = NULL;
752 if (GST_V4L2_IS_OPEN (v4l2object)) {
753 new = v4l2object->vcap.card;
754 } else if (gst_v4l2_open (v4l2object)) {
755 new = v4l2object->vcap.card;
756 gst_v4l2_close (v4l2object);
758 g_value_set_string (value, (gchar *) new);
763 if (GST_V4L2_IS_OPEN (v4l2object))
764 g_value_set_int (value, v4l2object->video_fd);
766 g_value_set_int (value, DEFAULT_PROP_DEVICE_FD);
773 if (GST_V4L2_IS_OPEN (v4l2object)) {
774 flags |= v4l2object->vcap.capabilities &
775 (V4L2_CAP_VIDEO_CAPTURE |
776 V4L2_CAP_VIDEO_OUTPUT |
777 V4L2_CAP_VIDEO_OVERLAY |
778 V4L2_CAP_VBI_CAPTURE |
779 V4L2_CAP_VBI_OUTPUT | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
781 g_value_set_flags (value, flags);
784 case PROP_BRIGHTNESS:
786 case PROP_SATURATION:
789 gint cid = gst_v4l2_object_prop_to_cid (prop_id);
792 if (GST_V4L2_IS_OPEN (v4l2object)) {
794 if (gst_v4l2_get_attribute (v4l2object, cid, &v)) {
795 g_value_set_int (value, v);
803 g_value_set_enum (value, v4l2object->tv_norm);
806 g_value_set_enum (value, v4l2object->req_mode);
808 case PROP_EXTRA_CONTROLS:
809 gst_value_set_structure (value, v4l2object->extra_controls);
811 case PROP_PIXEL_ASPECT_RATIO:
813 g_value_transform (v4l2object->par, value);
815 case PROP_FORCE_ASPECT_RATIO:
816 g_value_set_boolean (value, v4l2object->keep_aspect);
826 gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
828 GstTunerNorm *norm = NULL;
829 GstTunerChannel *channel = NULL;
832 if (!GST_IS_TUNER (v4l2object->element))
835 tuner = GST_TUNER (v4l2object->element);
837 if (v4l2object->tv_norm)
838 norm = gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
839 GST_DEBUG_OBJECT (v4l2object->element, "tv_norm=0x%" G_GINT64_MODIFIER "x, "
840 "norm=%p", (guint64) v4l2object->tv_norm, norm);
842 gst_tuner_set_norm (tuner, norm);
845 GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2object->element)));
847 v4l2object->tv_norm =
848 gst_v4l2_tuner_get_std_id_by_norm (v4l2object, norm);
849 gst_tuner_norm_changed (tuner, norm);
853 if (v4l2object->channel)
854 channel = gst_tuner_find_channel_by_name (tuner, v4l2object->channel);
856 gst_tuner_set_channel (tuner, channel);
859 GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER
860 (v4l2object->element)));
862 g_free (v4l2object->channel);
863 v4l2object->channel = g_strdup (channel->label);
864 gst_tuner_channel_changed (tuner, channel);
869 && GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
870 if (v4l2object->frequency != 0) {
871 gst_tuner_set_frequency (tuner, channel, v4l2object->frequency);
873 v4l2object->frequency = gst_tuner_get_frequency (tuner, channel);
874 if (v4l2object->frequency == 0) {
876 gst_tuner_set_frequency (tuner, channel, 1000);
884 gst_v4l2_object_open (GstV4l2Object * v4l2object)
886 if (gst_v4l2_open (v4l2object))
887 gst_v4l2_set_defaults (v4l2object);
892 gst_v4l2_video_overlay_start (v4l2object);
899 gst_v4l2_object_close (GstV4l2Object * v4l2object)
902 gst_v4l2_video_overlay_stop (v4l2object);
905 if (!gst_v4l2_close (v4l2object))
908 if (v4l2object->formats) {
909 gst_v4l2_object_clear_format_list (v4l2object);
917 * common format / caps utilities:
925 static const GstV4L2FormatDesc gst_v4l2_formats[] = {
926 /* from Linux 2.6.15 videodev2.h */
927 {V4L2_PIX_FMT_RGB332, TRUE},
928 {V4L2_PIX_FMT_RGB555, TRUE},
929 {V4L2_PIX_FMT_RGB565, TRUE},
930 {V4L2_PIX_FMT_RGB555X, TRUE},
931 {V4L2_PIX_FMT_RGB565X, TRUE},
932 {V4L2_PIX_FMT_BGR24, TRUE},
933 {V4L2_PIX_FMT_RGB24, TRUE},
934 {V4L2_PIX_FMT_BGR32, TRUE},
935 {V4L2_PIX_FMT_RGB32, TRUE},
936 {V4L2_PIX_FMT_GREY, TRUE},
937 {V4L2_PIX_FMT_YVU410, TRUE},
938 {V4L2_PIX_FMT_YVU420, TRUE},
939 {V4L2_PIX_FMT_YUYV, TRUE},
940 {V4L2_PIX_FMT_UYVY, TRUE},
941 {V4L2_PIX_FMT_YUV422P, TRUE},
942 {V4L2_PIX_FMT_YUV411P, TRUE},
943 {V4L2_PIX_FMT_Y41P, TRUE},
945 /* two planes -- one Y, one Cr + Cb interleaved */
946 {V4L2_PIX_FMT_NV12, TRUE},
947 {V4L2_PIX_FMT_NV21, TRUE},
949 /* The following formats are not defined in the V4L2 specification */
950 {V4L2_PIX_FMT_YUV410, TRUE},
951 {V4L2_PIX_FMT_YUV420, TRUE},
952 {V4L2_PIX_FMT_YYUV, TRUE},
953 {V4L2_PIX_FMT_HI240, TRUE},
955 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
956 #ifdef V4L2_PIX_FMT_SBGGR8
957 {V4L2_PIX_FMT_SBGGR8, TRUE},
960 /* compressed formats */
961 {V4L2_PIX_FMT_MJPEG, TRUE},
962 {V4L2_PIX_FMT_JPEG, TRUE},
963 #ifdef V4L2_PIX_FMT_PJPG
964 {V4L2_PIX_FMT_PJPG, TRUE},
966 {V4L2_PIX_FMT_DV, TRUE},
967 {V4L2_PIX_FMT_MPEG, FALSE},
968 #ifdef V4L2_PIX_FMT_MPEG4
969 {V4L2_PIX_FMT_MPEG4, TRUE},
972 #ifdef V4L2_PIX_FMT_H263
973 {V4L2_PIX_FMT_H263, TRUE},
975 #ifdef V4L2_PIX_FMT_H264
976 {V4L2_PIX_FMT_H264, TRUE},
979 /* Vendor-specific formats */
980 {V4L2_PIX_FMT_WNVA, TRUE},
982 #ifdef V4L2_PIX_FMT_SN9C10X
983 {V4L2_PIX_FMT_SN9C10X, TRUE},
985 #ifdef V4L2_PIX_FMT_PWC1
986 {V4L2_PIX_FMT_PWC1, TRUE},
988 #ifdef V4L2_PIX_FMT_PWC2
989 {V4L2_PIX_FMT_PWC2, TRUE},
991 #ifdef V4L2_PIX_FMT_YVYU
992 {V4L2_PIX_FMT_YVYU, TRUE},
996 #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
999 static struct v4l2_fmtdesc *
1000 gst_v4l2_object_get_format_from_fourcc (GstV4l2Object * v4l2object,
1003 struct v4l2_fmtdesc *fmt;
1009 walk = gst_v4l2_object_get_format_list (v4l2object);
1011 fmt = (struct v4l2_fmtdesc *) walk->data;
1012 if (fmt->pixelformat == fourcc)
1014 /* special case for jpeg */
1015 if (fmt->pixelformat == V4L2_PIX_FMT_MJPEG ||
1016 fmt->pixelformat == V4L2_PIX_FMT_JPEG
1017 #ifdef V4L2_PIX_FMT_PJPG
1018 || fmt->pixelformat == V4L2_PIX_FMT_PJPG
1021 if (fourcc == V4L2_PIX_FMT_JPEG || fourcc == V4L2_PIX_FMT_MJPEG
1022 #ifdef V4L2_PIX_FMT_PJPG
1023 || fourcc == V4L2_PIX_FMT_PJPG
1029 walk = g_slist_next (walk);
1037 /* complete made up ranking, the values themselves are meaningless */
1038 /* These ranks MUST be X such that X<<15 fits on a signed int - see
1039 the comment at the end of gst_v4l2_object_format_get_rank. */
1040 #define YUV_BASE_RANK 1000
1041 #define JPEG_BASE_RANK 500
1042 #define DV_BASE_RANK 200
1043 #define RGB_BASE_RANK 100
1044 #define YUV_ODD_BASE_RANK 50
1045 #define RGB_ODD_BASE_RANK 25
1046 #define BAYER_BASE_RANK 15
1047 #define S910_BASE_RANK 10
1048 #define GREY_BASE_RANK 5
1049 #define PWC_BASE_RANK 1
1051 /* This flag is already used by libv4l2 although
1052 * it was added to the Linux kernel in 2.6.32
1054 #ifndef V4L2_FMT_FLAG_EMULATED
1055 #define V4L2_FMT_FLAG_EMULATED 0x0002
1059 gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
1061 guint32 fourcc = fmt->pixelformat;
1062 gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1066 case V4L2_PIX_FMT_MJPEG:
1067 #ifdef V4L2_PIX_FMT_PJPG
1068 case V4L2_PIX_FMT_PJPG:
1069 rank = JPEG_BASE_RANK;
1072 case V4L2_PIX_FMT_JPEG:
1073 rank = JPEG_BASE_RANK + 1;
1075 case V4L2_PIX_FMT_MPEG: /* MPEG */
1076 rank = JPEG_BASE_RANK + 2;
1079 case V4L2_PIX_FMT_RGB332:
1080 case V4L2_PIX_FMT_RGB555:
1081 case V4L2_PIX_FMT_RGB555X:
1082 case V4L2_PIX_FMT_RGB565:
1083 case V4L2_PIX_FMT_RGB565X:
1084 rank = RGB_ODD_BASE_RANK;
1087 case V4L2_PIX_FMT_RGB24:
1088 case V4L2_PIX_FMT_BGR24:
1089 rank = RGB_BASE_RANK - 1;
1092 case V4L2_PIX_FMT_RGB32:
1093 case V4L2_PIX_FMT_BGR32:
1094 rank = RGB_BASE_RANK;
1097 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1098 rank = GREY_BASE_RANK;
1101 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
1102 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
1103 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
1104 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
1105 rank = YUV_ODD_BASE_RANK;
1108 case V4L2_PIX_FMT_YVU410: /* YVU9, 9 bits per pixel */
1109 rank = YUV_BASE_RANK + 3;
1111 case V4L2_PIX_FMT_YUV410: /* YUV9, 9 bits per pixel */
1112 rank = YUV_BASE_RANK + 2;
1114 case V4L2_PIX_FMT_YUV420: /* I420, 12 bits per pixel */
1115 rank = YUV_BASE_RANK + 7;
1117 case V4L2_PIX_FMT_YUYV: /* YUY2, 16 bits per pixel */
1118 rank = YUV_BASE_RANK + 10;
1120 case V4L2_PIX_FMT_YVU420: /* YV12, 12 bits per pixel */
1121 rank = YUV_BASE_RANK + 6;
1123 case V4L2_PIX_FMT_UYVY: /* UYVY, 16 bits per pixel */
1124 rank = YUV_BASE_RANK + 9;
1126 case V4L2_PIX_FMT_Y41P: /* Y41P, 12 bits per pixel */
1127 rank = YUV_BASE_RANK + 5;
1129 case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1130 rank = YUV_BASE_RANK + 4;
1132 case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1133 rank = YUV_BASE_RANK + 8;
1136 case V4L2_PIX_FMT_DV:
1137 rank = DV_BASE_RANK;
1140 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
1144 #ifdef V4L2_PIX_FMT_SBGGR8
1145 case V4L2_PIX_FMT_SBGGR8:
1146 rank = BAYER_BASE_RANK;
1150 #ifdef V4L2_PIX_FMT_SN9C10X
1151 case V4L2_PIX_FMT_SN9C10X:
1152 rank = S910_BASE_RANK;
1156 #ifdef V4L2_PIX_FMT_PWC1
1157 case V4L2_PIX_FMT_PWC1:
1158 rank = PWC_BASE_RANK;
1161 #ifdef V4L2_PIX_FMT_PWC2
1162 case V4L2_PIX_FMT_PWC2:
1163 rank = PWC_BASE_RANK;
1172 /* All ranks are below 1<<15 so a shift by 15
1173 * will a) make all non-emulated formats larger
1174 * than emulated and b) will not overflow
1185 format_cmp_func (gconstpointer a, gconstpointer b)
1187 const struct v4l2_fmtdesc *fa = a;
1188 const struct v4l2_fmtdesc *fb = b;
1190 if (fa->pixelformat == fb->pixelformat)
1193 return gst_v4l2_object_format_get_rank (fb) -
1194 gst_v4l2_object_format_get_rank (fa);
1197 /******************************************************
1198 * gst_v4l2_object_fill_format_list():
1199 * create list of supported capture formats
1200 * return value: TRUE on success, FALSE on error
1201 ******************************************************/
1203 gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object)
1206 struct v4l2_fmtdesc *format;
1208 GST_DEBUG_OBJECT (v4l2object->element, "getting src format enumerations");
1210 /* format enumeration */
1212 format = g_new0 (struct v4l2_fmtdesc, 1);
1215 format->type = v4l2object->type;
1217 if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1218 if (errno == EINVAL) {
1220 break; /* end of enumeration */
1226 GST_LOG_OBJECT (v4l2object->element, "index: %u", format->index);
1227 GST_LOG_OBJECT (v4l2object->element, "type: %d", format->type);
1228 GST_LOG_OBJECT (v4l2object->element, "flags: %08x", format->flags);
1229 GST_LOG_OBJECT (v4l2object->element, "description: '%s'",
1230 format->description);
1231 GST_LOG_OBJECT (v4l2object->element, "pixelformat: %" GST_FOURCC_FORMAT,
1232 GST_FOURCC_ARGS (format->pixelformat));
1234 /* sort formats according to our preference; we do this, because caps
1235 * are probed in the order the formats are in the list, and the order of
1236 * formats in the final probed caps matters for things like fixation */
1237 v4l2object->formats = g_slist_insert_sorted (v4l2object->formats, format,
1238 (GCompareFunc) format_cmp_func);
1241 #ifndef GST_DISABLE_GST_DEBUG
1245 GST_INFO_OBJECT (v4l2object->element, "got %d format(s):", n);
1246 for (l = v4l2object->formats; l != NULL; l = l->next) {
1249 GST_INFO_OBJECT (v4l2object->element,
1250 " %" GST_FOURCC_FORMAT "%s", GST_FOURCC_ARGS (format->pixelformat),
1251 ((format->flags & V4L2_FMT_FLAG_EMULATED)) ? " (emulated)" : "");
1261 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
1262 (_("Failed to enumerate possible video formats device '%s' can work with"), v4l2object->videodev), ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)", n, v4l2object->videodev, errno, g_strerror (errno)));
1269 * Get the list of supported capture formats, a list of
1270 * <code>struct v4l2_fmtdesc</code>.
1273 gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object)
1275 if (!v4l2object->formats)
1276 gst_v4l2_object_fill_format_list (v4l2object);
1277 return v4l2object->formats;
1282 gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
1284 GstStructure *structure = NULL;
1287 case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */
1288 #ifdef V4L2_PIX_FMT_PJPG
1289 case V4L2_PIX_FMT_PJPG: /* Progressive-JPEG */
1291 case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */
1292 structure = gst_structure_new_empty ("image/jpeg");
1294 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
1295 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
1296 /* FIXME: get correct fourccs here */
1298 #ifdef V4L2_PIX_FMT_MPEG4
1299 case V4L2_PIX_FMT_MPEG4:
1300 structure = gst_structure_new ("video/mpeg",
1301 "mpegversion", G_TYPE_INT, 4, "systemstream",
1302 G_TYPE_BOOLEAN, FALSE, NULL);
1305 #ifdef V4L2_PIX_FMT_H263
1306 case V4L2_PIX_FMT_H263:
1307 structure = gst_structure_new ("video/x-h263",
1308 "variant", G_TYPE_STRING, "itu", NULL);
1311 #ifdef V4L2_PIX_FMT_H264
1312 case V4L2_PIX_FMT_H264: /* H.264 */
1313 structure = gst_structure_new_empty ("video/x-h264");
1316 case V4L2_PIX_FMT_RGB332:
1317 case V4L2_PIX_FMT_RGB555X:
1318 case V4L2_PIX_FMT_RGB565X:
1319 /* FIXME: get correct fourccs here */
1321 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1322 case V4L2_PIX_FMT_RGB555:
1323 case V4L2_PIX_FMT_RGB565:
1324 case V4L2_PIX_FMT_RGB24:
1325 case V4L2_PIX_FMT_BGR24:
1326 case V4L2_PIX_FMT_RGB32:
1327 case V4L2_PIX_FMT_BGR32:
1328 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
1329 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
1330 case V4L2_PIX_FMT_YVU410:
1331 case V4L2_PIX_FMT_YUV410:
1332 case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
1333 case V4L2_PIX_FMT_YUYV:
1334 case V4L2_PIX_FMT_YVU420:
1335 case V4L2_PIX_FMT_UYVY:
1337 case V4L2_PIX_FMT_Y41P:
1339 case V4L2_PIX_FMT_YUV422P:
1340 #ifdef V4L2_PIX_FMT_YVYU
1341 case V4L2_PIX_FMT_YVYU:
1343 case V4L2_PIX_FMT_YUV411P:{
1344 GstVideoFormat format;
1347 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1348 format = GST_VIDEO_FORMAT_GRAY8;
1350 case V4L2_PIX_FMT_RGB555:
1351 format = GST_VIDEO_FORMAT_RGB15;
1353 case V4L2_PIX_FMT_RGB565:
1354 format = GST_VIDEO_FORMAT_RGB16;
1356 case V4L2_PIX_FMT_RGB24:
1357 format = GST_VIDEO_FORMAT_RGB;
1359 case V4L2_PIX_FMT_BGR24:
1360 format = GST_VIDEO_FORMAT_BGR;
1362 case V4L2_PIX_FMT_RGB32:
1363 format = GST_VIDEO_FORMAT_RGBx;
1365 case V4L2_PIX_FMT_BGR32:
1366 format = GST_VIDEO_FORMAT_BGRx;
1368 case V4L2_PIX_FMT_NV12:
1369 format = GST_VIDEO_FORMAT_NV12;
1371 case V4L2_PIX_FMT_NV21:
1372 format = GST_VIDEO_FORMAT_NV21;
1374 case V4L2_PIX_FMT_YVU410:
1375 format = GST_VIDEO_FORMAT_YVU9;
1377 case V4L2_PIX_FMT_YUV410:
1378 format = GST_VIDEO_FORMAT_YUV9;
1380 case V4L2_PIX_FMT_YUV420:
1381 format = GST_VIDEO_FORMAT_I420;
1383 case V4L2_PIX_FMT_YUYV:
1384 format = GST_VIDEO_FORMAT_YUY2;
1386 case V4L2_PIX_FMT_YVU420:
1387 format = GST_VIDEO_FORMAT_YV12;
1389 case V4L2_PIX_FMT_UYVY:
1390 format = GST_VIDEO_FORMAT_UYVY;
1393 case V4L2_PIX_FMT_Y41P:
1394 format = GST_VIDEO_FORMAT_Y41P;
1397 case V4L2_PIX_FMT_YUV411P:
1398 format = GST_VIDEO_FORMAT_Y41B;
1400 case V4L2_PIX_FMT_YUV422P:
1401 format = GST_VIDEO_FORMAT_Y42B;
1403 #ifdef V4L2_PIX_FMT_YVYU
1404 case V4L2_PIX_FMT_YVYU:
1405 format = GST_VIDEO_FORMAT_YVYU;
1409 format = GST_VIDEO_FORMAT_UNKNOWN;
1410 g_assert_not_reached ();
1413 structure = gst_structure_new ("video/x-raw",
1414 "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
1417 case V4L2_PIX_FMT_DV:
1419 gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE,
1422 case V4L2_PIX_FMT_MPEG: /* MPEG */
1423 structure = gst_structure_new_empty ("video/mpegts");
1425 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
1427 #ifdef V4L2_PIX_FMT_SBGGR8
1428 case V4L2_PIX_FMT_SBGGR8:
1429 structure = gst_structure_new_empty ("video/x-bayer");
1432 #ifdef V4L2_PIX_FMT_SN9C10X
1433 case V4L2_PIX_FMT_SN9C10X:
1434 structure = gst_structure_new_empty ("video/x-sonix");
1437 #ifdef V4L2_PIX_FMT_PWC1
1438 case V4L2_PIX_FMT_PWC1:
1439 structure = gst_structure_new_empty ("video/x-pwc1");
1442 #ifdef V4L2_PIX_FMT_PWC2
1443 case V4L2_PIX_FMT_PWC2:
1444 structure = gst_structure_new_empty ("video/x-pwc2");
1448 GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
1449 fourcc, GST_FOURCC_ARGS (fourcc));
1459 gst_v4l2_object_get_all_caps (void)
1461 static GstCaps *caps = NULL;
1464 GstStructure *structure;
1468 caps = gst_caps_new_empty ();
1469 for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
1471 gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i].format);
1473 if (gst_v4l2_formats[i].dimensions) {
1474 gst_structure_set (structure,
1475 "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
1476 "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
1477 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL);
1479 gst_caps_append_structure (caps, structure);
1484 return gst_caps_ref (caps);
1488 /* collect data for the given caps
1489 * @caps: given input caps
1490 * @format: location for the v4l format
1491 * @w/@h: location for width and height
1492 * @fps_n/@fps_d: location for framerate
1493 * @size: location for expected size of the frame or 0 if unknown
1496 gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
1497 struct v4l2_fmtdesc **format, GstVideoInfo * info)
1499 GstStructure *structure;
1501 const gchar *mimetype;
1502 struct v4l2_fmtdesc *fmt;
1504 /* default unknown values */
1507 structure = gst_caps_get_structure (caps, 0);
1509 mimetype = gst_structure_get_name (structure);
1511 if (!gst_video_info_from_caps (info, caps))
1512 goto invalid_format;
1514 if (g_str_equal (mimetype, "video/x-raw")) {
1515 switch (GST_VIDEO_INFO_FORMAT (info)) {
1516 case GST_VIDEO_FORMAT_I420:
1517 fourcc = V4L2_PIX_FMT_YUV420;
1519 case GST_VIDEO_FORMAT_YUY2:
1520 fourcc = V4L2_PIX_FMT_YUYV;
1523 case GST_VIDEO_FORMAT_Y41P:
1524 fourcc = V4L2_PIX_FMT_Y41P;
1527 case GST_VIDEO_FORMAT_UYVY:
1528 fourcc = V4L2_PIX_FMT_UYVY;
1530 case GST_VIDEO_FORMAT_YV12:
1531 fourcc = V4L2_PIX_FMT_YVU420;
1533 case GST_VIDEO_FORMAT_Y41B:
1534 fourcc = V4L2_PIX_FMT_YUV411P;
1536 case GST_VIDEO_FORMAT_Y42B:
1537 fourcc = V4L2_PIX_FMT_YUV422P;
1539 case GST_VIDEO_FORMAT_NV12:
1540 fourcc = V4L2_PIX_FMT_NV12;
1542 case GST_VIDEO_FORMAT_NV21:
1543 fourcc = V4L2_PIX_FMT_NV21;
1545 #ifdef V4L2_PIX_FMT_YVYU
1546 case GST_VIDEO_FORMAT_YVYU:
1547 fourcc = V4L2_PIX_FMT_YVYU;
1550 case GST_VIDEO_FORMAT_RGB15:
1551 fourcc = V4L2_PIX_FMT_RGB555;
1553 case GST_VIDEO_FORMAT_RGB16:
1554 fourcc = V4L2_PIX_FMT_RGB565;
1556 case GST_VIDEO_FORMAT_RGB:
1557 fourcc = V4L2_PIX_FMT_RGB24;
1559 case GST_VIDEO_FORMAT_BGR:
1560 fourcc = V4L2_PIX_FMT_BGR24;
1562 case GST_VIDEO_FORMAT_RGBx:
1563 case GST_VIDEO_FORMAT_RGBA:
1564 fourcc = V4L2_PIX_FMT_RGB32;
1566 case GST_VIDEO_FORMAT_BGRx:
1567 case GST_VIDEO_FORMAT_BGRA:
1568 fourcc = V4L2_PIX_FMT_BGR32;
1570 case GST_VIDEO_FORMAT_GRAY8:
1571 fourcc = V4L2_PIX_FMT_GREY;
1576 if (g_str_equal (mimetype, "video/mpegts")) {
1577 fourcc = V4L2_PIX_FMT_MPEG;
1578 } else if (g_str_equal (mimetype, "video/x-dv")) {
1579 fourcc = V4L2_PIX_FMT_DV;
1580 } else if (g_str_equal (mimetype, "image/jpeg")) {
1581 fourcc = V4L2_PIX_FMT_JPEG;
1582 #ifdef V4L2_PIX_FMT_MPEG4
1583 } else if (g_str_equal (mimetype, "video/mpeg")) {
1584 fourcc = V4L2_PIX_FMT_MPEG4;
1586 #ifdef V4L2_PIX_FMT_H263
1587 } else if (g_str_equal (mimetype, "video/x-h263")) {
1588 fourcc = V4L2_PIX_FMT_H263;
1590 #ifdef V4L2_PIX_FMT_H264
1591 } else if (g_str_equal (mimetype, "video/x-h264")) {
1592 fourcc = V4L2_PIX_FMT_H264;
1594 #ifdef V4L2_PIX_FMT_SBGGR8
1595 } else if (g_str_equal (mimetype, "video/x-bayer")) {
1596 fourcc = V4L2_PIX_FMT_SBGGR8;
1598 #ifdef V4L2_PIX_FMT_SN9C10X
1599 } else if (g_str_equal (mimetype, "video/x-sonix")) {
1600 fourcc = V4L2_PIX_FMT_SN9C10X;
1602 #ifdef V4L2_PIX_FMT_PWC1
1603 } else if (g_str_equal (mimetype, "video/x-pwc1")) {
1604 fourcc = V4L2_PIX_FMT_PWC1;
1606 #ifdef V4L2_PIX_FMT_PWC2
1607 } else if (g_str_equal (mimetype, "video/x-pwc2")) {
1608 fourcc = V4L2_PIX_FMT_PWC2;
1614 goto unhandled_format;
1616 fmt = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc);
1618 goto unsupported_format;
1627 GST_DEBUG_OBJECT (v4l2object, "invalid format");
1632 GST_DEBUG_OBJECT (v4l2object, "unhandled format");
1637 GST_DEBUG_OBJECT (v4l2object, "unsupported format");
1644 gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
1645 guint32 pixelformat, gint * width, gint * height, gboolean * interlaced);
1648 gst_v4l2_object_add_aspect_ratio (GstV4l2Object * v4l2object, GstStructure * s)
1650 struct v4l2_cropcap cropcap;
1651 int num = 1, den = 1;
1653 if (!v4l2object->keep_aspect)
1656 if (v4l2object->par) {
1657 num = gst_value_get_fraction_numerator (v4l2object->par);
1658 den = gst_value_get_fraction_denominator (v4l2object->par);
1662 memset (&cropcap, 0, sizeof (cropcap));
1664 cropcap.type = v4l2object->type;
1665 if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0)
1666 goto cropcap_failed;
1668 num = cropcap.pixelaspect.numerator;
1669 den = cropcap.pixelaspect.denominator;
1672 gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, num, den,
1677 if (errno != ENOTTY)
1678 GST_WARNING_OBJECT (v4l2object->element,
1679 "Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s",
1680 g_strerror (errno));
1685 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1686 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1687 static GstStructure *
1688 gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
1689 guint32 pixelformat,
1690 guint32 width, guint32 height, const GstStructure * template)
1692 gint fd = v4l2object->video_fd;
1693 struct v4l2_frmivalenum ival;
1696 GValue rates = { 0, };
1697 gboolean interlaced;
1698 gint int_width = width;
1699 gint int_height = height;
1701 if (!strcmp ((char *) v4l2object->vcap.driver, "uvcvideo")) {
1703 * UVC devices are never interlaced, and doing VIDIOC_TRY_FMT on them
1704 * causes expensive and slow USB IO, so don't probe them for interlaced
1708 /* Interlaced detection using VIDIOC_TRY/S_FMT */
1709 if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat,
1710 &int_width, &int_height, &interlaced))
1714 memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1716 ival.pixel_format = pixelformat;
1718 ival.height = height;
1720 GST_LOG_OBJECT (v4l2object->element,
1721 "get frame interval for %ux%u, %" GST_FOURCC_FORMAT, width, height,
1722 GST_FOURCC_ARGS (pixelformat));
1724 /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1725 * fraction to get framerate */
1726 if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1727 goto enum_frameintervals_failed;
1729 if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1730 GValue rate = { 0, };
1732 g_value_init (&rates, GST_TYPE_LIST);
1733 g_value_init (&rate, GST_TYPE_FRACTION);
1736 num = ival.discrete.numerator;
1737 denom = ival.discrete.denominator;
1739 if (num > G_MAXINT || denom > G_MAXINT) {
1740 /* let us hope we don't get here... */
1745 GST_LOG_OBJECT (v4l2object->element, "adding discrete framerate: %d/%d",
1748 /* swap to get the framerate */
1749 gst_value_set_fraction (&rate, denom, num);
1750 gst_value_list_append_value (&rates, &rate);
1753 } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1754 } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1755 GValue min = { 0, };
1756 GValue step = { 0, };
1757 GValue max = { 0, };
1758 gboolean added = FALSE;
1759 guint32 minnum, mindenom;
1760 guint32 maxnum, maxdenom;
1762 g_value_init (&rates, GST_TYPE_LIST);
1764 g_value_init (&min, GST_TYPE_FRACTION);
1765 g_value_init (&step, GST_TYPE_FRACTION);
1766 g_value_init (&max, GST_TYPE_FRACTION);
1769 minnum = ival.stepwise.min.numerator;
1770 mindenom = ival.stepwise.min.denominator;
1771 if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1775 GST_LOG_OBJECT (v4l2object->element, "stepwise min frame interval: %d/%d",
1777 gst_value_set_fraction (&min, minnum, mindenom);
1780 maxnum = ival.stepwise.max.numerator;
1781 maxdenom = ival.stepwise.max.denominator;
1782 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1787 GST_LOG_OBJECT (v4l2object->element, "stepwise max frame interval: %d/%d",
1789 gst_value_set_fraction (&max, maxnum, maxdenom);
1792 num = ival.stepwise.step.numerator;
1793 denom = ival.stepwise.step.denominator;
1794 if (num > G_MAXINT || denom > G_MAXINT) {
1799 if (num == 0 || denom == 0) {
1800 /* in this case we have a wrong fraction or no step, set the step to max
1801 * so that we only add the min value in the loop below */
1806 /* since we only have gst_value_fraction_subtract and not add, negate the
1808 GST_LOG_OBJECT (v4l2object->element, "stepwise step frame interval: %d/%d",
1810 gst_value_set_fraction (&step, -num, denom);
1812 while (gst_value_compare (&min, &max) != GST_VALUE_GREATER_THAN) {
1813 GValue rate = { 0, };
1815 num = gst_value_get_fraction_numerator (&min);
1816 denom = gst_value_get_fraction_denominator (&min);
1817 GST_LOG_OBJECT (v4l2object->element, "adding stepwise framerate: %d/%d",
1820 /* invert to get the framerate */
1821 g_value_init (&rate, GST_TYPE_FRACTION);
1822 gst_value_set_fraction (&rate, denom, num);
1823 gst_value_list_append_value (&rates, &rate);
1826 /* we're actually adding because step was negated above. This is because
1827 * there is no _add function... */
1828 if (!gst_value_fraction_subtract (&min, &min, &step)) {
1829 GST_WARNING_OBJECT (v4l2object->element, "could not step fraction!");
1834 /* no range was added, leave the default range from the template */
1835 GST_WARNING_OBJECT (v4l2object->element,
1836 "no range added, leaving default");
1837 g_value_unset (&rates);
1839 } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1840 guint32 maxnum, maxdenom;
1842 g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1844 num = ival.stepwise.min.numerator;
1845 denom = ival.stepwise.min.denominator;
1846 if (num > G_MAXINT || denom > G_MAXINT) {
1851 maxnum = ival.stepwise.max.numerator;
1852 maxdenom = ival.stepwise.max.denominator;
1853 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1858 GST_LOG_OBJECT (v4l2object->element,
1859 "continuous frame interval %d/%d to %d/%d", maxdenom, maxnum, denom,
1862 gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1868 s = gst_structure_copy (template);
1869 gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
1870 "height", G_TYPE_INT, (gint) height, NULL);
1871 gst_v4l2_object_add_aspect_ratio (v4l2object, s);
1872 if (g_str_equal (gst_structure_get_name (s), "video/x-raw"))
1873 gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
1874 (interlaced ? "mixed" : "progressive"), NULL);
1876 if (G_IS_VALUE (&rates)) {
1877 /* only change the framerate on the template when we have a valid probed new
1879 gst_structure_set_value (s, "framerate", &rates);
1880 g_value_unset (&rates);
1882 gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1,
1888 enum_frameintervals_failed:
1890 GST_DEBUG_OBJECT (v4l2object->element,
1891 "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1892 GST_FOURCC_ARGS (pixelformat), width, height);
1897 /* I don't see how this is actually an error, we ignore the format then */
1898 GST_WARNING_OBJECT (v4l2object->element,
1899 "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
1900 GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
1904 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1906 #ifdef VIDIOC_ENUM_FRAMESIZES
1908 sort_by_frame_size (GstStructure * s1, GstStructure * s2)
1912 gst_structure_get_int (s1, "width", &w1);
1913 gst_structure_get_int (s1, "height", &h1);
1914 gst_structure_get_int (s2, "width", &w2);
1915 gst_structure_get_int (s2, "height", &h2);
1917 /* I think it's safe to assume that this won't overflow for a while */
1918 return ((w2 * h2) - (w1 * h1));
1923 gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
1924 guint32 pixelformat, const GstStructure * template)
1926 GstCaps *ret = gst_caps_new_empty ();
1929 #ifdef VIDIOC_ENUM_FRAMESIZES
1930 gint fd = v4l2object->video_fd;
1931 struct v4l2_frmsizeenum size;
1932 GList *results = NULL;
1935 if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
1936 return gst_caps_new_empty_simple ("video/mpegts");
1938 memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
1940 size.pixel_format = pixelformat;
1942 GST_DEBUG_OBJECT (v4l2object->element, "Enumerating frame sizes");
1944 if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
1945 goto enum_framesizes_failed;
1947 if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1949 GST_LOG_OBJECT (v4l2object->element, "got discrete frame size %dx%d",
1950 size.discrete.width, size.discrete.height);
1952 w = MIN (size.discrete.width, G_MAXINT);
1953 h = MIN (size.discrete.height, G_MAXINT);
1957 gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
1958 pixelformat, w, h, template);
1961 results = g_list_prepend (results, tmp);
1965 } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
1966 GST_DEBUG_OBJECT (v4l2object->element,
1967 "done iterating discrete frame sizes");
1968 } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1969 GST_DEBUG_OBJECT (v4l2object->element, "we have stepwise frame sizes:");
1970 GST_DEBUG_OBJECT (v4l2object->element, "min width: %d",
1971 size.stepwise.min_width);
1972 GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
1973 size.stepwise.min_height);
1974 GST_DEBUG_OBJECT (v4l2object->element, "max width: %d",
1975 size.stepwise.max_width);
1976 GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
1977 size.stepwise.max_height);
1978 GST_DEBUG_OBJECT (v4l2object->element, "step width: %d",
1979 size.stepwise.step_width);
1980 GST_DEBUG_OBJECT (v4l2object->element, "step height: %d",
1981 size.stepwise.step_height);
1983 for (w = size.stepwise.min_width, h = size.stepwise.min_height;
1984 w <= size.stepwise.max_width && h <= size.stepwise.max_height;
1985 w += size.stepwise.step_width, h += size.stepwise.step_height) {
1986 if (w == 0 || h == 0)
1990 gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
1991 pixelformat, w, h, template);
1994 results = g_list_prepend (results, tmp);
1996 GST_DEBUG_OBJECT (v4l2object->element,
1997 "done iterating stepwise frame sizes");
1998 } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2001 GST_DEBUG_OBJECT (v4l2object->element, "we have continuous frame sizes:");
2002 GST_DEBUG_OBJECT (v4l2object->element, "min width: %d",
2003 size.stepwise.min_width);
2004 GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
2005 size.stepwise.min_height);
2006 GST_DEBUG_OBJECT (v4l2object->element, "max width: %d",
2007 size.stepwise.max_width);
2008 GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
2009 size.stepwise.max_height);
2011 w = MAX (size.stepwise.min_width, 1);
2012 h = MAX (size.stepwise.min_height, 1);
2013 maxw = MIN (size.stepwise.max_width, G_MAXINT);
2014 maxh = MIN (size.stepwise.max_height, G_MAXINT);
2017 gst_v4l2_object_probe_caps_for_format_and_size (v4l2object, pixelformat,
2020 gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, (gint) w,
2021 (gint) maxw, "height", GST_TYPE_INT_RANGE, (gint) h, (gint) maxh,
2024 /* no point using the results list here, since there's only one struct */
2025 gst_caps_append_structure (ret, tmp);
2031 /* we use an intermediary list to store and then sort the results of the
2032 * probing because we can't make any assumptions about the order in which
2033 * the driver will give us the sizes, but we want the final caps to contain
2034 * the results starting with the highest resolution and having the lowest
2035 * resolution last, since order in caps matters for things like fixation. */
2036 results = g_list_sort (results, (GCompareFunc) sort_by_frame_size);
2037 while (results != NULL) {
2038 gst_caps_append_structure (ret, GST_STRUCTURE (results->data));
2039 results = g_list_delete_link (results, results);
2042 if (gst_caps_is_empty (ret))
2043 goto enum_framesizes_no_results;
2048 enum_framesizes_failed:
2050 /* I don't see how this is actually an error */
2051 GST_DEBUG_OBJECT (v4l2object->element,
2052 "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2053 " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2054 goto default_frame_sizes;
2056 enum_framesizes_no_results:
2058 /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2059 * question doesn't actually support it yet */
2060 GST_DEBUG_OBJECT (v4l2object->element,
2061 "No results for pixelformat %" GST_FOURCC_FORMAT
2062 " enumerating frame sizes, trying fallback",
2063 GST_FOURCC_ARGS (pixelformat));
2064 goto default_frame_sizes;
2068 GST_WARNING_OBJECT (v4l2object->element,
2069 "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2070 ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2071 goto default_frame_sizes;
2073 default_frame_sizes:
2074 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2076 gint min_w, max_w, min_h, max_h, fix_num = 0, fix_denom = 0;
2077 gboolean interlaced;
2079 /* This code is for Linux < 2.6.19 */
2081 max_w = max_h = GST_V4L2_MAX_SIZE;
2082 if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w,
2083 &min_h, &interlaced)) {
2084 GST_WARNING_OBJECT (v4l2object->element,
2085 "Could not probe minimum capture size for pixelformat %"
2086 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2088 if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w,
2089 &max_h, &interlaced)) {
2090 GST_WARNING_OBJECT (v4l2object->element,
2091 "Could not probe maximum capture size for pixelformat %"
2092 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2095 /* Since we can't get framerate directly, try to use the current norm */
2096 if (v4l2object->tv_norm && v4l2object->norms) {
2098 GstTunerNorm *norm = NULL;
2099 GstTunerNorm *current =
2100 gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
2102 for (norms = v4l2object->norms; norms != NULL; norms = norms->next) {
2103 norm = (GstTunerNorm *) norms->data;
2104 if (!strcmp (norm->label, current->label))
2107 /* If it's possible, set framerate to that (discrete) value */
2109 fix_num = gst_value_get_fraction_numerator (&norm->framerate);
2110 fix_denom = gst_value_get_fraction_denominator (&norm->framerate);
2114 tmp = gst_structure_copy (template);
2116 gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION, fix_num,
2119 /* if norm can't be used, copy the template framerate */
2120 gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
2125 gst_structure_set (tmp, "width", G_TYPE_INT, max_w, NULL);
2127 gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, min_w, max_w, NULL);
2130 gst_structure_set (tmp, "height", G_TYPE_INT, max_h, NULL);
2132 gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2134 if (g_str_equal (gst_structure_get_name (tmp), "video/x-raw"))
2135 gst_structure_set (tmp, "interlace-mode", G_TYPE_STRING,
2136 (interlaced ? "mixed" : "progressive"), NULL);
2137 gst_v4l2_object_add_aspect_ratio (v4l2object, tmp);
2139 gst_caps_append_structure (ret, tmp);
2146 gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
2147 guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
2149 struct v4l2_format fmt, prevfmt;
2154 g_return_val_if_fail (width != NULL, FALSE);
2155 g_return_val_if_fail (height != NULL, FALSE);
2157 GST_LOG_OBJECT (v4l2object->element,
2158 "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2159 *width, *height, GST_FOURCC_ARGS (pixelformat));
2161 fd = v4l2object->video_fd;
2163 /* Some drivers are buggy and will modify the currently set format
2164 when processing VIDIOC_TRY_FMT, so we remember what is set at the
2165 minute, and will reset it when done. */
2166 prevfmt.type = v4l2object->type;
2167 prevfmt_valid = (v4l2_ioctl (fd, VIDIOC_G_FMT, &prevfmt) >= 0);
2169 /* get size delimiters */
2170 memset (&fmt, 0, sizeof (fmt));
2171 fmt.type = v4l2object->type;
2172 fmt.fmt.pix.width = *width;
2173 fmt.fmt.pix.height = *height;
2174 fmt.fmt.pix.pixelformat = pixelformat;
2175 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2177 r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2178 if (r < 0 && errno == EINVAL) {
2179 /* try again with interlaced video */
2180 fmt.fmt.pix.width = *width;
2181 fmt.fmt.pix.height = *height;
2182 fmt.fmt.pix.pixelformat = pixelformat;
2183 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2184 r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2188 /* The driver might not implement TRY_FMT, in which case we will try
2190 if (errno != ENOTTY)
2193 /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2194 be, because we're still probing */
2195 if (GST_V4L2_IS_ACTIVE (v4l2object))
2198 GST_LOG_OBJECT (v4l2object->element,
2199 "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2201 fmt.fmt.pix.width = *width;
2202 fmt.fmt.pix.height = *height;
2204 r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
2205 if (r < 0 && errno == EINVAL) {
2206 /* try again with progressive video */
2207 fmt.fmt.pix.width = *width;
2208 fmt.fmt.pix.height = *height;
2209 fmt.fmt.pix.pixelformat = pixelformat;
2210 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2211 r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
2218 GST_LOG_OBJECT (v4l2object->element,
2219 "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2221 *width = fmt.fmt.pix.width;
2222 *height = fmt.fmt.pix.height;
2224 switch (fmt.fmt.pix.field) {
2225 case V4L2_FIELD_ANY:
2226 case V4L2_FIELD_NONE:
2227 *interlaced = FALSE;
2229 case V4L2_FIELD_INTERLACED:
2230 case V4L2_FIELD_INTERLACED_TB:
2231 case V4L2_FIELD_INTERLACED_BT:
2235 GST_WARNING_OBJECT (v4l2object->element,
2236 "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
2237 GST_FOURCC_ARGS (pixelformat), *width, *height);
2242 v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
2247 v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
2252 gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
2256 GST_DEBUG_OBJECT (v4l2object->element, "initializing the capture system");
2258 GST_V4L2_CHECK_OPEN (v4l2object);
2259 GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
2261 /* find transport */
2262 mode = v4l2object->req_mode;
2264 if (v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
2265 if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
2266 mode = GST_V4L2_IO_RW;
2267 } else if (v4l2object->req_mode == GST_V4L2_IO_RW)
2268 goto method_not_supported;
2270 if (v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
2271 if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
2272 mode = GST_V4L2_IO_MMAP;
2273 } else if (v4l2object->req_mode == GST_V4L2_IO_MMAP)
2274 goto method_not_supported;
2276 /* if still no transport selected, error out */
2277 if (mode == GST_V4L2_IO_AUTO)
2278 goto no_supported_capture_method;
2280 GST_INFO_OBJECT (v4l2object->element, "accessing buffers via mode %d", mode);
2281 v4l2object->mode = mode;
2283 /* Map the buffers */
2284 GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool");
2286 if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object, caps)))
2287 goto buffer_pool_new_failed;
2289 GST_V4L2_SET_ACTIVE (v4l2object);
2294 buffer_pool_new_failed:
2296 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2297 (_("Could not map buffers from device '%s'"),
2298 v4l2object->videodev),
2299 ("Failed to create buffer pool: %s", g_strerror (errno)));
2302 method_not_supported:
2304 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2305 (_("The driver of device '%s' does not support the IO method %d"),
2306 v4l2object->videodev, mode), (NULL));
2309 no_supported_capture_method:
2311 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2312 (_("The driver of device '%s' does not support any known IO "
2313 "method."), v4l2object->videodev), (NULL));
2319 gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
2321 gint fd = v4l2object->video_fd;
2322 struct v4l2_format format;
2323 struct v4l2_streamparm streamparm;
2324 enum v4l2_field field;
2325 guint32 pixelformat;
2326 struct v4l2_fmtdesc *fmtdesc;
2328 gint width, height, fps_n, fps_d, stride;
2330 if (!gst_v4l2_object_get_caps_info (v4l2object, caps, &fmtdesc, &info))
2333 pixelformat = fmtdesc->pixelformat;
2334 width = GST_VIDEO_INFO_WIDTH (&info);
2335 height = GST_VIDEO_INFO_HEIGHT (&info);
2336 fps_n = GST_VIDEO_INFO_FPS_N (&info);
2337 fps_d = GST_VIDEO_INFO_FPS_D (&info);
2338 stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
2340 if (GST_VIDEO_INFO_IS_INTERLACED (&info)) {
2341 GST_DEBUG_OBJECT (v4l2object->element, "interlaced video");
2342 /* ideally we would differentiate between types of interlaced video
2343 * but there is not sufficient information in the caps..
2345 field = V4L2_FIELD_INTERLACED;
2347 GST_DEBUG_OBJECT (v4l2object->element, "progressive video");
2348 field = V4L2_FIELD_NONE;
2351 GST_DEBUG_OBJECT (v4l2object->element, "Desired format %dx%d, format "
2352 "%" GST_FOURCC_FORMAT " stride: %d", width, height,
2353 GST_FOURCC_ARGS (pixelformat), stride);
2355 GST_V4L2_CHECK_OPEN (v4l2object);
2356 GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
2358 /* MPEG-TS source cameras don't get their format set for some reason.
2359 * It looks wrong and we weren't able to track down the reason for that code
2360 * so it is disabled until someone who has an mpeg-ts camera complains...
2363 /* Only unconditionally accept mpegts for sources */
2364 if ((v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
2365 (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G')))
2369 memset (&format, 0x00, sizeof (struct v4l2_format));
2370 format.type = v4l2object->type;
2372 if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
2373 goto get_fmt_failed;
2375 GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2376 "%" GST_FOURCC_FORMAT " bytesperline %d, colorspace %d",
2377 format.fmt.pix.width, format.fmt.pix.height,
2378 GST_FOURCC_ARGS (format.fmt.pix.pixelformat), format.fmt.pix.bytesperline,
2379 format.fmt.pix.colorspace);
2381 if (format.type != v4l2object->type ||
2382 format.fmt.pix.width != width ||
2383 format.fmt.pix.height != height ||
2384 format.fmt.pix.pixelformat != pixelformat ||
2385 format.fmt.pix.field != field || format.fmt.pix.bytesperline != stride) {
2386 /* something different, set the format */
2387 GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
2388 "%" GST_FOURCC_FORMAT " bytesperline %d", width, height,
2389 GST_FOURCC_ARGS (pixelformat), stride);
2391 format.type = v4l2object->type;
2392 format.fmt.pix.width = width;
2393 format.fmt.pix.height = height;
2394 format.fmt.pix.pixelformat = pixelformat;
2395 format.fmt.pix.field = field;
2396 /* try to ask our prefered stride */
2397 format.fmt.pix.bytesperline = stride;
2399 if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
2400 goto set_fmt_failed;
2402 GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2403 "%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
2404 format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
2405 format.fmt.pix.bytesperline);
2407 if (format.fmt.pix.width != width || format.fmt.pix.height != height)
2408 goto invalid_dimensions;
2410 if (format.fmt.pix.pixelformat != pixelformat)
2411 goto invalid_pixelformat;
2414 /* figure out the frame layout */
2415 v4l2object->bytesperline = format.fmt.pix.bytesperline;
2416 v4l2object->sizeimage = format.fmt.pix.sizeimage;
2418 GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %u",
2419 v4l2object->sizeimage);
2421 /* Is there a reason we require the caller to always specify a framerate? */
2422 GST_DEBUG_OBJECT (v4l2object->element, "Desired framerate: %u/%u", fps_n,
2425 memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
2426 streamparm.type = v4l2object->type;
2428 if (v4l2_ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
2429 goto get_parm_failed;
2431 GST_VIDEO_INFO_FPS_N (&info) =
2432 streamparm.parm.capture.timeperframe.denominator;
2433 GST_VIDEO_INFO_FPS_D (&info) = streamparm.parm.capture.timeperframe.numerator;
2435 if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2436 GST_DEBUG_OBJECT (v4l2object->element, "Got framerate: %u/%u",
2437 streamparm.parm.capture.timeperframe.denominator,
2438 streamparm.parm.capture.timeperframe.numerator);
2440 /* We used to skip frame rate setup if the camera was already setup
2441 * with the requested frame rate. This breaks some cameras though,
2442 * causing them to not output data (several models of Thinkpad cameras
2443 * have this problem at least).
2444 * So, don't skip. */
2445 GST_LOG_OBJECT (v4l2object->element, "Setting framerate to %u/%u", fps_n,
2447 /* We want to change the frame rate, so check whether we can. Some cheap USB
2448 * cameras don't have the capability */
2449 if ((streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
2450 GST_DEBUG_OBJECT (v4l2object->element,
2451 "Not setting framerate (not supported)");
2455 /* Note: V4L2 wants the frame interval, we have the frame rate */
2456 streamparm.parm.capture.timeperframe.numerator = fps_d;
2457 streamparm.parm.capture.timeperframe.denominator = fps_n;
2459 /* some cheap USB cam's won't accept any change */
2460 if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
2461 goto set_parm_failed;
2463 /* get new values */
2464 fps_d = streamparm.parm.capture.timeperframe.numerator;
2465 fps_n = streamparm.parm.capture.timeperframe.denominator;
2467 GST_INFO_OBJECT (v4l2object->element, "Set framerate to %u/%u", fps_n,
2470 GST_VIDEO_INFO_FPS_N (&info) = fps_n;
2471 GST_VIDEO_INFO_FPS_D (&info) = fps_d;
2475 /* if we have a framerate pre-calculate duration */
2476 if (fps_n > 0 && fps_d > 0) {
2477 v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
2479 v4l2object->duration = GST_CLOCK_TIME_NONE;
2481 v4l2object->info = info;
2482 v4l2object->fmtdesc = fmtdesc;
2484 /* now configure ther pools */
2485 if (!gst_v4l2_object_setup_pool (v4l2object, caps))
2493 GST_DEBUG_OBJECT (v4l2object->element, "can't parse caps %" GST_PTR_FORMAT,
2499 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2500 (_("Device '%s' does not support video capture"),
2501 v4l2object->videodev),
2502 ("Call to G_FMT failed: (%s)", g_strerror (errno)));
2507 if (errno == EBUSY) {
2508 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, BUSY,
2509 (_("Device '%s' is busy"), v4l2object->videodev),
2510 ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
2511 GST_FOURCC_ARGS (pixelformat), width, height,
2512 g_strerror (errno)));
2514 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2515 (_("Device '%s' cannot capture at %dx%d"),
2516 v4l2object->videodev, width, height),
2517 ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
2518 GST_FOURCC_ARGS (pixelformat), width, height,
2519 g_strerror (errno)));
2525 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2526 (_("Device '%s' cannot capture at %dx%d"),
2527 v4l2object->videodev, width, height),
2528 ("Tried to capture at %dx%d, but device returned size %dx%d",
2529 width, height, format.fmt.pix.width, format.fmt.pix.height));
2532 invalid_pixelformat:
2534 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2535 (_("Device '%s' cannot capture in the specified format"),
2536 v4l2object->videodev),
2537 ("Tried to capture in %" GST_FOURCC_FORMAT
2538 ", but device returned format" " %" GST_FOURCC_FORMAT,
2539 GST_FOURCC_ARGS (pixelformat),
2540 GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
2545 /* it's possible that this call is not supported */
2546 if (errno != EINVAL && errno != ENOTTY) {
2547 GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
2548 (_("Could not get parameters on device '%s'"),
2549 v4l2object->videodev), GST_ERROR_SYSTEM);
2555 GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
2556 (_("Video device did not accept new frame rate setting.")),
2562 GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2563 (_("Video device could not create buffer pool.")), GST_ERROR_SYSTEM);
2569 gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
2574 if (!v4l2object->pool)
2577 s = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (v4l2object->pool));
2578 gst_buffer_pool_config_get_params (s, &oldcaps, NULL, NULL, NULL);
2580 return oldcaps && gst_caps_is_equal (caps, oldcaps);
2584 gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
2586 GST_LOG_OBJECT (v4l2object->element, "flush poll");
2587 gst_poll_set_flushing (v4l2object->poll, TRUE);
2593 gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object)
2595 GST_LOG_OBJECT (v4l2object->element, "flush stop poll");
2596 gst_poll_set_flushing (v4l2object->poll, FALSE);
2602 gst_v4l2_object_stop (GstV4l2Object * v4l2object)
2604 GST_DEBUG_OBJECT (v4l2object->element, "stopping");
2606 if (!GST_V4L2_IS_OPEN (v4l2object))
2608 if (!GST_V4L2_IS_ACTIVE (v4l2object))
2611 if (v4l2object->pool) {
2612 GST_DEBUG_OBJECT (v4l2object->element, "deactivating pool");
2613 gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (v4l2object->pool), FALSE);
2614 gst_object_unref (v4l2object->pool);
2615 v4l2object->pool = NULL;
2618 GST_V4L2_SET_INACTIVE (v4l2object);
2625 gst_v4l2_object_copy (GstV4l2Object * v4l2object, GstBuffer * dest,
2628 const GstVideoFormatInfo *finfo = v4l2object->info.finfo;
2630 if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
2631 finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
2632 GstVideoFrame src_frame, dest_frame;
2634 GST_DEBUG_OBJECT (v4l2object->element, "copy video frame");
2636 /* we have raw video, use videoframe copy to get strides right */
2637 if (!gst_video_frame_map (&src_frame, &v4l2object->info, src, GST_MAP_READ))
2638 goto invalid_buffer;
2640 if (!gst_video_frame_map (&dest_frame, &v4l2object->info, dest,
2642 gst_video_frame_unmap (&src_frame);
2643 goto invalid_buffer;
2646 gst_video_frame_copy (&dest_frame, &src_frame);
2648 gst_video_frame_unmap (&src_frame);
2649 gst_video_frame_unmap (&dest_frame);
2653 GST_DEBUG_OBJECT (v4l2object->element, "copy raw bytes");
2654 gst_buffer_map (src, &map, GST_MAP_READ);
2655 gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
2656 gst_buffer_unmap (src, &map);
2657 gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
2659 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2object->element,
2660 "slow copy into buffer %p", dest);
2667 /* No Window available to put our image into */
2668 GST_WARNING_OBJECT (v4l2object->element, "could not map image");
2674 gst_v4l2_object_get_caps (GstV4l2Object * v4l2object, GstCaps * filter)
2680 if (v4l2object->probed_caps == NULL) {
2681 formats = gst_v4l2_object_get_format_list (v4l2object);
2683 ret = gst_caps_new_empty ();
2685 for (walk = formats; walk; walk = walk->next) {
2686 struct v4l2_fmtdesc *format;
2687 GstStructure *template;
2689 format = (struct v4l2_fmtdesc *) walk->data;
2691 template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat);
2696 tmp = gst_v4l2_object_probe_caps_for_format (v4l2object,
2697 format->pixelformat, template);
2699 gst_caps_append (ret, tmp);
2701 gst_structure_free (template);
2703 GST_DEBUG_OBJECT (v4l2object->element, "unknown format %u",
2704 format->pixelformat);
2707 v4l2object->probed_caps = ret;
2711 ret = gst_caps_intersect_full (filter, v4l2object->probed_caps,
2712 GST_CAPS_INTERSECT_FIRST);
2714 ret = gst_caps_ref (v4l2object->probed_caps);
2717 GST_INFO_OBJECT (v4l2object->element, "probed caps: %p", ret);
2718 LOG_CAPS (v4l2object->element, ret);