v4l2: Don't require parser for VP8
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2object.c
1 /* GStreamer
2  *
3  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4  *               2006 Edgard Lima <edgard.lima@indt.org.br>
5  *
6  * gstv4l2object.c: base class for V4L2 elements
7  *
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,
18  * USA.
19  */
20
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
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <string.h>
34
35 #ifdef HAVE_GUDEV
36 #include <gudev/gudev.h>
37 #endif
38
39 #include "v4l2_calls.h"
40 #include "gstv4l2tuner.h"
41 #ifdef HAVE_XVIDEO
42 #include "gstv4l2videooverlay.h"
43 #endif
44 #include "gstv4l2colorbalance.h"
45
46 #include "gst/gst-i18n-plugin.h"
47
48 #include <gst/video/video.h>
49
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
56 #endif
57
58 #ifndef V4L2_PIX_FMT_NV12M
59 #define V4L2_PIX_FMT_NV12M GST_MAKE_FOURCC ('N', 'M', '1', '2')
60 #endif
61 #ifndef V4L2_PIX_FMT_NV12MT
62 #define V4L2_PIX_FMT_NV12MT GST_MAKE_FOURCC ('T', 'M', '1', '2')
63 #endif
64 #ifndef V4L2_PIX_FMT_NV21M
65 #define V4L2_PIX_FMT_NV21M GST_MAKE_FOURCC ('N', 'M', '2', '1')
66 #endif
67 #ifndef V4L2_PIX_FMT_MPEG1
68 #define V4L2_PIX_FMT_MPEG1 GST_MAKE_FOURCC ('M', 'P', 'G', '1')
69 #endif
70 #ifndef V4L2_PIX_FMT_MPEG2
71 #define V4L2_PIX_FMT_MPEG2 GST_MAKE_FOURCC ('M', 'P', 'G', '2')
72 #endif
73 #ifndef V4L2_PIX_FMT_MPEG4
74 #define V4L2_PIX_FMT_MPEG4 GST_MAKE_FOURCC ('M', 'P', 'G', '4')
75 #endif
76
77 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
78 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
79 #define GST_CAT_DEFAULT v4l2_debug
80
81 #define DEFAULT_PROP_DEVICE_NAME        NULL
82 #define DEFAULT_PROP_DEVICE_FD          -1
83 #define DEFAULT_PROP_FLAGS              0
84 #define DEFAULT_PROP_TV_NORM            0
85 #define DEFAULT_PROP_CHANNEL            NULL
86 #define DEFAULT_PROP_FREQUENCY          0
87 #define DEFAULT_PROP_IO_MODE            GST_V4L2_IO_AUTO
88
89 #define ENCODED_BUFFER_SIZE             (1 * 1024 * 1024)
90
91 enum
92 {
93   PROP_0,
94   V4L2_STD_OBJECT_PROPS,
95 };
96
97 static GSList *gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object);
98
99 #if 0
100 G_LOCK_DEFINE_STATIC (probe_lock);
101
102 const GList *
103 gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
104 {
105   GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
106   static GList *list = NULL;
107
108   G_LOCK (probe_lock);
109
110   if (!list) {
111     list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
112   }
113
114   G_UNLOCK (probe_lock);
115
116   return list;
117 }
118
119 static gboolean init = FALSE;
120 static GList *devices = NULL;
121
122 #ifdef HAVE_GUDEV
123 static gboolean
124 gst_v4l2_class_probe_devices_with_udev (GstElementClass * klass, gboolean check,
125     GList ** klass_devices)
126 {
127   GUdevClient *client = NULL;
128   GList *item;
129
130   if (!check) {
131     while (devices) {
132       gchar *device = devices->data;
133       devices = g_list_remove (devices, device);
134       g_free (device);
135     }
136
137     GST_INFO ("Enumerating video4linux devices from udev");
138     client = g_udev_client_new (NULL);
139     if (!client) {
140       GST_WARNING ("Failed to initialize gudev client");
141       goto finish;
142     }
143
144     item = g_udev_client_query_by_subsystem (client, "video4linux");
145     while (item) {
146       GUdevDevice *device = item->data;
147       gchar *devnode = g_strdup (g_udev_device_get_device_file (device));
148       gint api = g_udev_device_get_property_as_int (device, "ID_V4L_VERSION");
149       GST_INFO ("Found new device: %s, API: %d", devnode, api);
150       /* Append v4l2 devices only. If api is 0 probably v4l_id has
151          been stripped out of the current udev installation, append
152          anyway */
153       if (api == 0) {
154         GST_WARNING
155             ("Couldn't retrieve ID_V4L_VERSION, silly udev installation?");
156       }
157       if ((api == 2 || api == 0)) {
158         devices = g_list_append (devices, devnode);
159       } else {
160         g_free (devnode);
161       }
162       g_object_unref (device);
163       item = item->next;
164     }
165     g_list_free (item);
166     init = TRUE;
167   }
168
169 finish:
170   if (client) {
171     g_object_unref (client);
172   }
173
174   *klass_devices = devices;
175
176   return init;
177 }
178 #endif /* HAVE_GUDEV */
179
180 static gboolean
181 gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
182     GList ** klass_devices)
183 {
184   if (!check) {
185     const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
186     gint base, n, fd;
187
188     while (devices) {
189       gchar *device = devices->data;
190       devices = g_list_remove (devices, device);
191       g_free (device);
192     }
193
194     /*
195      * detect /dev entries
196      */
197     for (n = 0; n < 64; n++) {
198       for (base = 0; dev_base[base] != NULL; base++) {
199         struct stat s;
200         gchar *device = g_strdup_printf ("%s%d",
201             dev_base[base],
202             n);
203
204         /*
205          * does the /dev/ entry exist at all?
206          */
207         if (stat (device, &s) == 0) {
208           /*
209            * yes: is a device attached?
210            */
211           if (S_ISCHR (s.st_mode)) {
212
213             if ((fd = open (device, O_RDWR | O_NONBLOCK)) > 0 || errno == EBUSY) {
214               if (fd > 0)
215                 close (fd);
216
217               devices = g_list_append (devices, device);
218               break;
219             }
220           }
221         }
222         g_free (device);
223       }
224     }
225     init = TRUE;
226   }
227
228   *klass_devices = devices;
229
230   return init;
231 }
232
233 void
234 gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
235     guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
236 {
237   GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
238
239   switch (prop_id) {
240     case PROP_DEVICE:
241 #ifdef HAVE_GUDEV
242       if (!gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices))
243         gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
244 #else /* !HAVE_GUDEV */
245       gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
246 #endif /* HAVE_GUDEV */
247       break;
248     default:
249       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
250       break;
251   }
252 }
253
254 gboolean
255 gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
256     guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
257 {
258   GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
259   gboolean ret = FALSE;
260
261   switch (prop_id) {
262     case PROP_DEVICE:
263 #ifdef HAVE_GUDEV
264       ret =
265           !gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices);
266 #else /* !HAVE_GUDEV */
267       ret = !gst_v4l2_class_probe_devices (klass, TRUE, klass_devices);
268 #endif /* HAVE_GUDEV */
269       break;
270     default:
271       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
272       break;
273   }
274   return ret;
275 }
276
277 static GValueArray *
278 gst_v4l2_class_list_devices (GstElementClass * klass, GList ** klass_devices)
279 {
280   GValueArray *array;
281   GValue value = { 0 };
282   GList *item;
283
284   if (!*klass_devices)
285     return NULL;
286
287   array = g_value_array_new (g_list_length (*klass_devices));
288   item = *klass_devices;
289   g_value_init (&value, G_TYPE_STRING);
290   while (item) {
291     gchar *device = item->data;
292
293     g_value_set_string (&value, device);
294     g_value_array_append (array, &value);
295
296     item = item->next;
297   }
298   g_value_unset (&value);
299
300   return array;
301 }
302
303 GValueArray *
304 gst_v4l2_probe_get_values (GstPropertyProbe * probe,
305     guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
306 {
307   GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
308   GValueArray *array = NULL;
309
310   switch (prop_id) {
311     case PROP_DEVICE:
312       array = gst_v4l2_class_list_devices (klass, klass_devices);
313       break;
314     default:
315       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
316       break;
317   }
318
319   return array;
320 }
321 #endif
322
323 #define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
324 static GType
325 gst_v4l2_device_get_type (void)
326 {
327   static GType v4l2_device_type = 0;
328
329   if (v4l2_device_type == 0) {
330     static const GFlagsValue values[] = {
331       {V4L2_CAP_VIDEO_CAPTURE, "Device supports video capture", "capture"},
332       {V4L2_CAP_VIDEO_OUTPUT, "Device supports video playback", "output"},
333       {V4L2_CAP_VIDEO_OVERLAY, "Device supports video overlay", "overlay"},
334
335       {V4L2_CAP_VBI_CAPTURE, "Device supports the VBI capture", "vbi-capture"},
336       {V4L2_CAP_VBI_OUTPUT, "Device supports the VBI output", "vbi-output"},
337
338       {V4L2_CAP_TUNER, "Device has a tuner or modulator", "tuner"},
339       {V4L2_CAP_AUDIO, "Device has audio inputs or outputs", "audio"},
340
341       {0, NULL, NULL}
342     };
343
344     v4l2_device_type =
345         g_flags_register_static ("GstV4l2DeviceTypeFlags", values);
346   }
347
348   return v4l2_device_type;
349 }
350
351 #define GST_TYPE_V4L2_TV_NORM (gst_v4l2_tv_norm_get_type ())
352 static GType
353 gst_v4l2_tv_norm_get_type (void)
354 {
355   static GType v4l2_tv_norm = 0;
356
357   if (!v4l2_tv_norm) {
358     static const GEnumValue tv_norms[] = {
359       {0, "none", "none"},
360
361       {V4L2_STD_NTSC, "NTSC", "NTSC"},
362       {V4L2_STD_NTSC_M, "NTSC-M", "NTSC-M"},
363       {V4L2_STD_NTSC_M_JP, "NTSC-M-JP", "NTSC-M-JP"},
364       {V4L2_STD_NTSC_M_KR, "NTSC-M-KR", "NTSC-M-KR"},
365       {V4L2_STD_NTSC_443, "NTSC-443", "NTSC-443"},
366
367       {V4L2_STD_PAL, "PAL", "PAL"},
368       {V4L2_STD_PAL_BG, "PAL-BG", "PAL-BG"},
369       {V4L2_STD_PAL_B, "PAL-B", "PAL-B"},
370       {V4L2_STD_PAL_B1, "PAL-B1", "PAL-B1"},
371       {V4L2_STD_PAL_G, "PAL-G", "PAL-G"},
372       {V4L2_STD_PAL_H, "PAL-H", "PAL-H"},
373       {V4L2_STD_PAL_I, "PAL-I", "PAL-I"},
374       {V4L2_STD_PAL_DK, "PAL-DK", "PAL-DK"},
375       {V4L2_STD_PAL_D, "PAL-D", "PAL-D"},
376       {V4L2_STD_PAL_D1, "PAL-D1", "PAL-D1"},
377       {V4L2_STD_PAL_K, "PAL-K", "PAL-K"},
378       {V4L2_STD_PAL_M, "PAL-M", "PAL-M"},
379       {V4L2_STD_PAL_N, "PAL-N", "PAL-N"},
380       {V4L2_STD_PAL_Nc, "PAL-Nc", "PAL-Nc"},
381       {V4L2_STD_PAL_60, "PAL-60", "PAL-60"},
382
383       {V4L2_STD_SECAM, "SECAM", "SECAM"},
384       {V4L2_STD_SECAM_B, "SECAM-B", "SECAM-B"},
385       {V4L2_STD_SECAM_G, "SECAM-G", "SECAM-G"},
386       {V4L2_STD_SECAM_H, "SECAM-H", "SECAM-H"},
387       {V4L2_STD_SECAM_DK, "SECAM-DK", "SECAM-DK"},
388       {V4L2_STD_SECAM_D, "SECAM-D", "SECAM-D"},
389       {V4L2_STD_SECAM_K, "SECAM-K", "SECAM-K"},
390       {V4L2_STD_SECAM_K1, "SECAM-K1", "SECAM-K1"},
391       {V4L2_STD_SECAM_L, "SECAM-L", "SECAM-L"},
392       {V4L2_STD_SECAM_LC, "SECAM-Lc", "SECAM-Lc"},
393
394       {0, NULL, NULL}
395     };
396
397     v4l2_tv_norm = g_enum_register_static ("V4L2_TV_norms", tv_norms);
398   }
399
400   return v4l2_tv_norm;
401 }
402
403 GType
404 gst_v4l2_io_mode_get_type (void)
405 {
406   static GType v4l2_io_mode = 0;
407
408   if (!v4l2_io_mode) {
409     static const GEnumValue io_modes[] = {
410       {GST_V4L2_IO_AUTO, "GST_V4L2_IO_AUTO", "auto"},
411       {GST_V4L2_IO_RW, "GST_V4L2_IO_RW", "rw"},
412       {GST_V4L2_IO_MMAP, "GST_V4L2_IO_MMAP", "mmap"},
413       {GST_V4L2_IO_USERPTR, "GST_V4L2_IO_USERPTR", "userptr"},
414       {GST_V4L2_IO_DMABUF, "GST_V4L2_IO_DMABUF", "dmabuf"},
415
416       {0, NULL, NULL}
417     };
418     v4l2_io_mode = g_enum_register_static ("GstV4l2IOMode", io_modes);
419   }
420   return v4l2_io_mode;
421 }
422
423 void
424 gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
425     const char *default_device)
426 {
427   g_object_class_install_property (gobject_class, PROP_DEVICE,
428       g_param_spec_string ("device", "Device", "Device location",
429           default_device, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
430   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
431       g_param_spec_string ("device-name", "Device name",
432           "Name of the device", DEFAULT_PROP_DEVICE_NAME,
433           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
434   g_object_class_install_property (gobject_class, PROP_DEVICE_FD,
435       g_param_spec_int ("device-fd", "File descriptor",
436           "File descriptor of the device", -1, G_MAXINT, DEFAULT_PROP_DEVICE_FD,
437           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
438   g_object_class_install_property (gobject_class, PROP_FLAGS,
439       g_param_spec_flags ("flags", "Flags", "Device type flags",
440           GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS,
441           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
442
443   /**
444    * GstV4l2Src:brightness:
445    *
446    * Picture brightness, or more precisely, the black level
447    */
448   g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
449       g_param_spec_int ("brightness", "Brightness",
450           "Picture brightness, or more precisely, the black level", G_MININT,
451           G_MAXINT, 0,
452           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
453   /**
454    * GstV4l2Src:contrast:
455    *
456    * Picture contrast or luma gain
457    */
458   g_object_class_install_property (gobject_class, PROP_CONTRAST,
459       g_param_spec_int ("contrast", "Contrast",
460           "Picture contrast or luma gain", G_MININT,
461           G_MAXINT, 0,
462           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
463   /**
464    * GstV4l2Src:saturation:
465    *
466    * Picture color saturation or chroma gain
467    */
468   g_object_class_install_property (gobject_class, PROP_SATURATION,
469       g_param_spec_int ("saturation", "Saturation",
470           "Picture color saturation or chroma gain", G_MININT,
471           G_MAXINT, 0,
472           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
473   /**
474    * GstV4l2Src:hue:
475    *
476    * Hue or color balance
477    */
478   g_object_class_install_property (gobject_class, PROP_HUE,
479       g_param_spec_int ("hue", "Hue",
480           "Hue or color balance", G_MININT,
481           G_MAXINT, 0,
482           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
483
484   /**
485    * GstV4l2Src:norm:
486    *
487    * TV norm
488    */
489   g_object_class_install_property (gobject_class, PROP_TV_NORM,
490       g_param_spec_enum ("norm", "TV norm",
491           "video standard",
492           GST_TYPE_V4L2_TV_NORM, DEFAULT_PROP_TV_NORM,
493           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
494
495   /**
496    * GstV4l2Src:io-mode:
497    *
498    * IO Mode
499    */
500   g_object_class_install_property (gobject_class, PROP_IO_MODE,
501       g_param_spec_enum ("io-mode", "IO mode",
502           "I/O mode",
503           GST_TYPE_V4L2_IO_MODE, DEFAULT_PROP_IO_MODE,
504           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
505
506   /**
507    * GstV4l2Src:extra-controls:
508    *
509    * Additional v4l2 controls for the device. The controls are identified
510    * by the control name (lowercase with '_' for any non-alphanumeric
511    * characters).
512    *
513    * Since: 1.2
514    */
515   g_object_class_install_property (gobject_class, PROP_EXTRA_CONTROLS,
516       g_param_spec_boxed ("extra-controls", "Extra Controls",
517           "Extra v4l2 controls (CIDs) for the device",
518           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
519
520   /**
521    * GstV4l2Src:pixel-aspect-ratio:
522    *
523    * The pixel aspect ratio of the device. This overwrites the pixel aspect
524    * ratio queried from the device.
525    *
526    * Since: 1.2
527    */
528   g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
529       g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
530           "Overwrite the pixel aspect ratio of the device", "1/1",
531           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
532
533   /**
534    * GstV4l2Src:force-aspect-ratio:
535    *
536    * When enabled, the pixel aspect ratio queried from the device or set
537    * with the pixel-aspect-ratio property will be enforced.
538    *
539    * Since: 1.2
540    */
541   g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
542       g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
543           "When enabled, the pixel aspect ratio will be enforced", TRUE,
544           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
545
546 }
547
548 GstV4l2Object *
549 gst_v4l2_object_new (GstElement * element,
550     enum v4l2_buf_type type,
551     const char *default_device,
552     GstV4l2GetInOutFunction get_in_out_func,
553     GstV4l2SetInOutFunction set_in_out_func,
554     GstV4l2UpdateFpsFunction update_fps_func)
555 {
556   GstV4l2Object *v4l2object;
557
558   /*
559    * some default values
560    */
561   v4l2object = g_new0 (GstV4l2Object, 1);
562
563   v4l2object->type = type;
564   v4l2object->formats = NULL;
565
566   v4l2object->element = element;
567   v4l2object->get_in_out_func = get_in_out_func;
568   v4l2object->set_in_out_func = set_in_out_func;
569   v4l2object->update_fps_func = update_fps_func;
570
571   v4l2object->video_fd = -1;
572   v4l2object->poll = gst_poll_new (TRUE);
573   v4l2object->active = FALSE;
574   v4l2object->videodev = g_strdup (default_device);
575
576   v4l2object->norms = NULL;
577   v4l2object->channels = NULL;
578   v4l2object->colors = NULL;
579
580   v4l2object->xwindow_id = 0;
581
582   v4l2object->keep_aspect = TRUE;
583
584   v4l2object->n_v4l2_planes = 0;
585
586   /*
587    * this boolean only applies in v4l2-MPLANE mode.
588    * TRUE: means it prefers to use several v4l2 (non contiguous)
589    * planes. For example if the device supports NV12 and NV12M
590    * both in MPLANE mode, then it will prefer NV12M
591    * FALSE: means it prefers to use one v4l2 plane (which contains
592    * all gst planes as if it was working in non-v4l2-MPLANE mode.
593    * For example if the device supports NV12 and NV12M
594    * both in MPLANE mode, then it will prefer NV12
595    *
596    * this boolean is also used to manage the case where the
597    * device only supports the mode MPLANE and at the same time it
598    * does not support both NV12 and NV12M. So in this case we first
599    * try to use the prefered config, and at least try the other case
600    * if it fails. For example in MPLANE mode if it has NV12 and not
601    * NV21M then even if you set prefered_non_contiguous to TRUE it will
602    * try NV21 as well.
603    */
604   v4l2object->prefered_non_contiguous = TRUE;
605
606   v4l2object->no_initial_format = FALSE;
607
608   return v4l2object;
609 }
610
611 static gboolean gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object);
612
613
614 void
615 gst_v4l2_object_destroy (GstV4l2Object * v4l2object)
616 {
617   g_return_if_fail (v4l2object != NULL);
618
619   if (v4l2object->videodev)
620     g_free (v4l2object->videodev);
621
622   if (v4l2object->poll)
623     gst_poll_free (v4l2object->poll);
624
625   if (v4l2object->channel)
626     g_free (v4l2object->channel);
627
628   if (v4l2object->formats) {
629     gst_v4l2_object_clear_format_list (v4l2object);
630   }
631
632   if (v4l2object->probed_caps) {
633     gst_caps_unref (v4l2object->probed_caps);
634   }
635
636   g_free (v4l2object);
637 }
638
639
640 static gboolean
641 gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object)
642 {
643   g_slist_foreach (v4l2object->formats, (GFunc) g_free, NULL);
644   g_slist_free (v4l2object->formats);
645   v4l2object->formats = NULL;
646
647   return TRUE;
648 }
649
650 static gint
651 gst_v4l2_object_prop_to_cid (guint prop_id)
652 {
653   gint cid = -1;
654
655   switch (prop_id) {
656     case PROP_BRIGHTNESS:
657       cid = V4L2_CID_BRIGHTNESS;
658       break;
659     case PROP_CONTRAST:
660       cid = V4L2_CID_CONTRAST;
661       break;
662     case PROP_SATURATION:
663       cid = V4L2_CID_SATURATION;
664       break;
665     case PROP_HUE:
666       cid = V4L2_CID_HUE;
667       break;
668     default:
669       GST_WARNING ("unmapped property id: %d", prop_id);
670   }
671   return cid;
672 }
673
674
675 gboolean
676 gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
677     guint prop_id, const GValue * value, GParamSpec * pspec)
678 {
679   switch (prop_id) {
680     case PROP_DEVICE:
681       g_free (v4l2object->videodev);
682       v4l2object->videodev = g_value_dup_string (value);
683       break;
684     case PROP_BRIGHTNESS:
685     case PROP_CONTRAST:
686     case PROP_SATURATION:
687     case PROP_HUE:
688     {
689       gint cid = gst_v4l2_object_prop_to_cid (prop_id);
690
691       if (cid != -1) {
692         if (GST_V4L2_IS_OPEN (v4l2object)) {
693           gst_v4l2_set_attribute (v4l2object, cid, g_value_get_int (value));
694         }
695       }
696       return TRUE;
697     }
698       break;
699     case PROP_TV_NORM:
700       v4l2object->tv_norm = g_value_get_enum (value);
701       break;
702 #if 0
703     case PROP_CHANNEL:
704       if (GST_V4L2_IS_OPEN (v4l2object)) {
705         GstTuner *tuner = GST_TUNER (v4l2object->element);
706         GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
707             (gchar *) g_value_get_string (value));
708
709         if (channel) {
710           /* like gst_tuner_set_channel (tuner, channel)
711              without g_object_notify */
712           gst_v4l2_tuner_set_channel (v4l2object, channel);
713         }
714       } else {
715         g_free (v4l2object->channel);
716         v4l2object->channel = g_value_dup_string (value);
717       }
718       break;
719     case PROP_FREQUENCY:
720       if (GST_V4L2_IS_OPEN (v4l2object)) {
721         GstTuner *tuner = GST_TUNER (v4l2object->element);
722         GstTunerChannel *channel = gst_tuner_get_channel (tuner);
723
724         if (channel &&
725             GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
726           /* like
727              gst_tuner_set_frequency (tuner, channel, g_value_get_ulong (value))
728              without g_object_notify */
729           gst_v4l2_tuner_set_frequency (v4l2object, channel,
730               g_value_get_ulong (value));
731         }
732       } else {
733         v4l2object->frequency = g_value_get_ulong (value);
734       }
735       break;
736 #endif
737     case PROP_IO_MODE:
738       v4l2object->req_mode = g_value_get_enum (value);
739       break;
740     case PROP_EXTRA_CONTROLS:{
741       const GstStructure *s = gst_value_get_structure (value);
742
743       if (v4l2object->extra_controls)
744         gst_structure_free (v4l2object->extra_controls);
745
746       v4l2object->extra_controls = s ? gst_structure_copy (s) : NULL;
747       if (GST_V4L2_IS_OPEN (v4l2object))
748         gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
749       break;
750     }
751     case PROP_PIXEL_ASPECT_RATIO:
752       g_free (v4l2object->par);
753       v4l2object->par = g_new0 (GValue, 1);
754       g_value_init (v4l2object->par, GST_TYPE_FRACTION);
755       if (!g_value_transform (value, v4l2object->par)) {
756         g_warning ("Could not transform string to aspect ratio");
757         gst_value_set_fraction (v4l2object->par, 1, 1);
758       }
759       GST_DEBUG_OBJECT (v4l2object->element, "set PAR to %d/%d",
760           gst_value_get_fraction_numerator (v4l2object->par),
761           gst_value_get_fraction_denominator (v4l2object->par));
762       break;
763     case PROP_FORCE_ASPECT_RATIO:
764       v4l2object->keep_aspect = g_value_get_boolean (value);
765       break;
766     default:
767       return FALSE;
768       break;
769   }
770   return TRUE;
771 }
772
773
774 gboolean
775 gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
776     guint prop_id, GValue * value, GParamSpec * pspec)
777 {
778   switch (prop_id) {
779     case PROP_DEVICE:
780       g_value_set_string (value, v4l2object->videodev);
781       break;
782     case PROP_DEVICE_NAME:
783     {
784       const guchar *new = NULL;
785
786       if (GST_V4L2_IS_OPEN (v4l2object)) {
787         new = v4l2object->vcap.card;
788       } else if (gst_v4l2_open (v4l2object)) {
789         new = v4l2object->vcap.card;
790         gst_v4l2_close (v4l2object);
791       }
792       g_value_set_string (value, (gchar *) new);
793       break;
794     }
795     case PROP_DEVICE_FD:
796     {
797       if (GST_V4L2_IS_OPEN (v4l2object))
798         g_value_set_int (value, v4l2object->video_fd);
799       else
800         g_value_set_int (value, DEFAULT_PROP_DEVICE_FD);
801       break;
802     }
803     case PROP_FLAGS:
804     {
805       guint flags = 0;
806
807       if (GST_V4L2_IS_OPEN (v4l2object)) {
808         flags |= v4l2object->vcap.capabilities &
809             (V4L2_CAP_VIDEO_CAPTURE |
810             V4L2_CAP_VIDEO_OUTPUT |
811             V4L2_CAP_VIDEO_OVERLAY |
812             V4L2_CAP_VBI_CAPTURE |
813             V4L2_CAP_VBI_OUTPUT | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
814
815         if (v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
816           flags |= V4L2_CAP_VIDEO_CAPTURE;
817
818         if (v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
819           flags |= V4L2_CAP_VIDEO_OUTPUT;
820       }
821       g_value_set_flags (value, flags);
822       break;
823     }
824     case PROP_BRIGHTNESS:
825     case PROP_CONTRAST:
826     case PROP_SATURATION:
827     case PROP_HUE:
828     {
829       gint cid = gst_v4l2_object_prop_to_cid (prop_id);
830
831       if (cid != -1) {
832         if (GST_V4L2_IS_OPEN (v4l2object)) {
833           gint v;
834           if (gst_v4l2_get_attribute (v4l2object, cid, &v)) {
835             g_value_set_int (value, v);
836           }
837         }
838       }
839       return TRUE;
840     }
841       break;
842     case PROP_TV_NORM:
843       g_value_set_enum (value, v4l2object->tv_norm);
844       break;
845     case PROP_IO_MODE:
846       g_value_set_enum (value, v4l2object->req_mode);
847       break;
848     case PROP_EXTRA_CONTROLS:
849       gst_value_set_structure (value, v4l2object->extra_controls);
850       break;
851     case PROP_PIXEL_ASPECT_RATIO:
852       if (v4l2object->par)
853         g_value_transform (v4l2object->par, value);
854       break;
855     case PROP_FORCE_ASPECT_RATIO:
856       g_value_set_boolean (value, v4l2object->keep_aspect);
857       break;
858     default:
859       return FALSE;
860       break;
861   }
862   return TRUE;
863 }
864
865 static void
866 gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
867 {
868   GstTunerNorm *norm = NULL;
869   GstTunerChannel *channel = NULL;
870   GstTuner *tuner;
871
872   if (!GST_IS_TUNER (v4l2object->element))
873     return;
874
875   tuner = GST_TUNER (v4l2object->element);
876
877   if (v4l2object->tv_norm)
878     norm = gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
879   GST_DEBUG_OBJECT (v4l2object->element, "tv_norm=0x%" G_GINT64_MODIFIER "x, "
880       "norm=%p", (guint64) v4l2object->tv_norm, norm);
881   if (norm) {
882     gst_tuner_set_norm (tuner, norm);
883   } else {
884     norm =
885         GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2object->element)));
886     if (norm) {
887       v4l2object->tv_norm =
888           gst_v4l2_tuner_get_std_id_by_norm (v4l2object, norm);
889       gst_tuner_norm_changed (tuner, norm);
890     }
891   }
892
893   if (v4l2object->channel)
894     channel = gst_tuner_find_channel_by_name (tuner, v4l2object->channel);
895   if (channel) {
896     gst_tuner_set_channel (tuner, channel);
897   } else {
898     channel =
899         GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER
900             (v4l2object->element)));
901     if (channel) {
902       g_free (v4l2object->channel);
903       v4l2object->channel = g_strdup (channel->label);
904       gst_tuner_channel_changed (tuner, channel);
905     }
906   }
907
908   if (channel
909       && GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
910     if (v4l2object->frequency != 0) {
911       gst_tuner_set_frequency (tuner, channel, v4l2object->frequency);
912     } else {
913       v4l2object->frequency = gst_tuner_get_frequency (tuner, channel);
914       if (v4l2object->frequency == 0) {
915         /* guess */
916         gst_tuner_set_frequency (tuner, channel, 1000);
917       } else {
918       }
919     }
920   }
921 }
922
923 gboolean
924 gst_v4l2_object_open (GstV4l2Object * v4l2object)
925 {
926   if (gst_v4l2_open (v4l2object))
927     gst_v4l2_set_defaults (v4l2object);
928   else
929     return FALSE;
930
931 #ifdef HAVE_XVIDEO
932   gst_v4l2_video_overlay_start (v4l2object);
933 #endif
934
935   return TRUE;
936 }
937
938 gboolean
939 gst_v4l2_object_open_shared (GstV4l2Object * v4l2object, GstV4l2Object * other)
940 {
941   gboolean ret;
942
943   ret = gst_v4l2_dup (v4l2object, other);
944
945 #ifdef HAVE_XVIDEO
946   gst_v4l2_video_overlay_start (v4l2object);
947 #endif
948
949   return ret;
950 }
951
952 gboolean
953 gst_v4l2_object_close (GstV4l2Object * v4l2object)
954 {
955 #ifdef HAVE_XVIDEO
956   gst_v4l2_video_overlay_stop (v4l2object);
957 #endif
958
959   if (!gst_v4l2_close (v4l2object))
960     return FALSE;
961
962   gst_caps_replace (&v4l2object->probed_caps, NULL);
963
964   if (v4l2object->formats) {
965     gst_v4l2_object_clear_format_list (v4l2object);
966   }
967
968   return TRUE;
969 }
970
971
972 /*
973  * common format / caps utilities:
974  */
975 typedef enum
976 {
977   GST_V4L2_RAW = 1 << 0,
978   GST_V4L2_CODEC = 1 << 1,
979   GST_V4L2_TRANSPORT = 1 << 2,
980   GST_V4L2_ALL = 0xffff
981 } GstV4L2FormatFlags;
982
983 typedef struct
984 {
985   guint32 format;
986   gboolean dimensions;
987   GstV4L2FormatFlags flags;
988 } GstV4L2FormatDesc;
989
990 static const GstV4L2FormatDesc gst_v4l2_formats[] = {
991   /* from Linux 2.6.15 videodev2.h */
992   {V4L2_PIX_FMT_RGB332, TRUE, GST_V4L2_RAW},
993   {V4L2_PIX_FMT_RGB555, TRUE, GST_V4L2_RAW},
994   {V4L2_PIX_FMT_RGB565, TRUE, GST_V4L2_RAW},
995   {V4L2_PIX_FMT_RGB555X, TRUE, GST_V4L2_RAW},
996   {V4L2_PIX_FMT_RGB565X, TRUE, GST_V4L2_RAW},
997   {V4L2_PIX_FMT_BGR24, TRUE, GST_V4L2_RAW},
998   {V4L2_PIX_FMT_RGB24, TRUE, GST_V4L2_RAW},
999   {V4L2_PIX_FMT_BGR32, TRUE, GST_V4L2_RAW},
1000   {V4L2_PIX_FMT_RGB32, TRUE, GST_V4L2_RAW},
1001   {V4L2_PIX_FMT_GREY, TRUE, GST_V4L2_RAW},
1002   {V4L2_PIX_FMT_YVU410, TRUE, GST_V4L2_RAW},
1003   {V4L2_PIX_FMT_YVU420, TRUE, GST_V4L2_RAW},
1004   {V4L2_PIX_FMT_YUYV, TRUE, GST_V4L2_RAW},
1005   {V4L2_PIX_FMT_UYVY, TRUE, GST_V4L2_RAW},
1006   {V4L2_PIX_FMT_YUV422P, TRUE, GST_V4L2_RAW},
1007   {V4L2_PIX_FMT_YUV411P, TRUE, GST_V4L2_RAW},
1008   {V4L2_PIX_FMT_Y41P, TRUE, GST_V4L2_RAW},
1009
1010   /* two planes -- one Y, one Cr + Cb interleaved  */
1011   {V4L2_PIX_FMT_NV12, TRUE, GST_V4L2_RAW},
1012   {V4L2_PIX_FMT_NV12M, TRUE, GST_V4L2_RAW},
1013   {V4L2_PIX_FMT_NV12MT, TRUE, GST_V4L2_RAW},
1014   {V4L2_PIX_FMT_NV21, TRUE, GST_V4L2_RAW},
1015   {V4L2_PIX_FMT_NV21M, TRUE, GST_V4L2_RAW},
1016
1017   /*  The following formats are not defined in the V4L2 specification */
1018   {V4L2_PIX_FMT_YUV410, TRUE, GST_V4L2_RAW},
1019   {V4L2_PIX_FMT_YUV420, TRUE, GST_V4L2_RAW},
1020   {V4L2_PIX_FMT_YYUV, TRUE, GST_V4L2_RAW},
1021   {V4L2_PIX_FMT_HI240, TRUE, GST_V4L2_RAW},
1022
1023   /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
1024 #ifdef V4L2_PIX_FMT_SBGGR8
1025   {V4L2_PIX_FMT_SBGGR8, TRUE, GST_V4L2_CODEC},
1026 #endif
1027
1028   /* compressed formats */
1029   {V4L2_PIX_FMT_MJPEG, FALSE, GST_V4L2_CODEC},
1030   {V4L2_PIX_FMT_JPEG, FALSE, GST_V4L2_CODEC},
1031 #ifdef V4L2_PIX_FMT_PJPG
1032   {V4L2_PIX_FMT_PJPG, FALSE, GST_V4L2_CODEC},
1033 #endif
1034   {V4L2_PIX_FMT_DV, FALSE, GST_V4L2_TRANSPORT},
1035   {V4L2_PIX_FMT_MPEG, FALSE, GST_V4L2_TRANSPORT},
1036   {V4L2_PIX_FMT_MPEG1, FALSE, GST_V4L2_CODEC},
1037   {V4L2_PIX_FMT_MPEG2, FALSE, GST_V4L2_CODEC},
1038   {V4L2_PIX_FMT_MPEG4, FALSE, GST_V4L2_CODEC},
1039
1040 #ifdef V4L2_PIX_FMT_H263
1041   {V4L2_PIX_FMT_H263, FALSE, GST_V4L2_CODEC},
1042 #endif
1043 #ifdef V4L2_PIX_FMT_H264
1044   {V4L2_PIX_FMT_H264, FALSE, GST_V4L2_CODEC},
1045 #endif
1046 #ifdef V4L2_PIX_FMT_VP8
1047   {V4L2_PIX_FMT_VP8, FALSE, GST_V4L2_CODEC},
1048 #endif
1049
1050   /*  Vendor-specific formats   */
1051   {V4L2_PIX_FMT_WNVA, TRUE, GST_V4L2_CODEC},
1052
1053 #ifdef V4L2_PIX_FMT_SN9C10X
1054   {V4L2_PIX_FMT_SN9C10X, TRUE, GST_V4L2_CODEC},
1055 #endif
1056 #ifdef V4L2_PIX_FMT_PWC1
1057   {V4L2_PIX_FMT_PWC1, TRUE, GST_V4L2_CODEC},
1058 #endif
1059 #ifdef V4L2_PIX_FMT_PWC2
1060   {V4L2_PIX_FMT_PWC2, TRUE, GST_V4L2_CODEC},
1061 #endif
1062 #ifdef V4L2_PIX_FMT_YVYU
1063   {V4L2_PIX_FMT_YVYU, TRUE, GST_V4L2_RAW},
1064 #endif
1065 };
1066
1067 #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
1068
1069
1070 static struct v4l2_fmtdesc *
1071 gst_v4l2_object_get_format_from_fourcc (GstV4l2Object * v4l2object,
1072     guint32 fourcc)
1073 {
1074   struct v4l2_fmtdesc *fmt;
1075   GSList *walk;
1076
1077   if (fourcc == 0)
1078     return NULL;
1079
1080   walk = gst_v4l2_object_get_format_list (v4l2object);
1081   while (walk) {
1082     fmt = (struct v4l2_fmtdesc *) walk->data;
1083     if (fmt->pixelformat == fourcc)
1084       return fmt;
1085     /* special case for jpeg */
1086     if (fmt->pixelformat == V4L2_PIX_FMT_MJPEG ||
1087         fmt->pixelformat == V4L2_PIX_FMT_JPEG
1088 #ifdef V4L2_PIX_FMT_PJPG
1089         || fmt->pixelformat == V4L2_PIX_FMT_PJPG
1090 #endif
1091         ) {
1092       if (fourcc == V4L2_PIX_FMT_JPEG || fourcc == V4L2_PIX_FMT_MJPEG
1093 #ifdef V4L2_PIX_FMT_PJPG
1094           || fourcc == V4L2_PIX_FMT_PJPG
1095 #endif
1096           ) {
1097         return fmt;
1098       }
1099     }
1100     walk = g_slist_next (walk);
1101   }
1102
1103   return NULL;
1104 }
1105
1106
1107
1108 /* complete made up ranking, the values themselves are meaningless */
1109 /* These ranks MUST be X such that X<<15 fits on a signed int - see
1110    the comment at the end of gst_v4l2_object_format_get_rank. */
1111 #define YUV_BASE_RANK     1000
1112 #define JPEG_BASE_RANK     500
1113 #define DV_BASE_RANK       200
1114 #define RGB_BASE_RANK      100
1115 #define YUV_ODD_BASE_RANK   50
1116 #define RGB_ODD_BASE_RANK   25
1117 #define BAYER_BASE_RANK     15
1118 #define S910_BASE_RANK      10
1119 #define GREY_BASE_RANK       5
1120 #define PWC_BASE_RANK        1
1121
1122 /* This flag is already used by libv4l2 although
1123  * it was added to the Linux kernel in 2.6.32
1124  */
1125 #ifndef V4L2_FMT_FLAG_EMULATED
1126 #define V4L2_FMT_FLAG_EMULATED 0x0002
1127 #endif
1128
1129 static gint
1130 gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
1131 {
1132   guint32 fourcc = fmt->pixelformat;
1133   gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1134   gint rank = 0;
1135
1136   switch (fourcc) {
1137     case V4L2_PIX_FMT_MJPEG:
1138 #ifdef V4L2_PIX_FMT_PJPG
1139     case V4L2_PIX_FMT_PJPG:
1140       rank = JPEG_BASE_RANK;
1141       break;
1142 #endif
1143     case V4L2_PIX_FMT_JPEG:
1144       rank = JPEG_BASE_RANK + 1;
1145       break;
1146     case V4L2_PIX_FMT_MPEG:    /* MPEG          */
1147       rank = JPEG_BASE_RANK + 2;
1148       break;
1149
1150     case V4L2_PIX_FMT_RGB332:
1151     case V4L2_PIX_FMT_RGB555:
1152     case V4L2_PIX_FMT_RGB555X:
1153     case V4L2_PIX_FMT_RGB565:
1154     case V4L2_PIX_FMT_RGB565X:
1155       rank = RGB_ODD_BASE_RANK;
1156       break;
1157
1158     case V4L2_PIX_FMT_RGB24:
1159     case V4L2_PIX_FMT_BGR24:
1160       rank = RGB_BASE_RANK - 1;
1161       break;
1162
1163     case V4L2_PIX_FMT_RGB32:
1164     case V4L2_PIX_FMT_BGR32:
1165       rank = RGB_BASE_RANK;
1166       break;
1167
1168     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
1169       rank = GREY_BASE_RANK;
1170       break;
1171
1172     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
1173     case V4L2_PIX_FMT_NV12M:   /* Same as NV12      */
1174     case V4L2_PIX_FMT_NV12MT:  /* NV12 64x32 tile   */
1175     case V4L2_PIX_FMT_NV21:    /* 12  Y/CrCb 4:2:0  */
1176     case V4L2_PIX_FMT_NV21M:   /* Same as NV21      */
1177     case V4L2_PIX_FMT_YYUV:    /* 16  YUV 4:2:2     */
1178     case V4L2_PIX_FMT_HI240:   /*  8  8-bit color   */
1179       rank = YUV_ODD_BASE_RANK;
1180       break;
1181
1182     case V4L2_PIX_FMT_YVU410:  /* YVU9,  9 bits per pixel */
1183       rank = YUV_BASE_RANK + 3;
1184       break;
1185     case V4L2_PIX_FMT_YUV410:  /* YUV9,  9 bits per pixel */
1186       rank = YUV_BASE_RANK + 2;
1187       break;
1188     case V4L2_PIX_FMT_YUV420:  /* I420, 12 bits per pixel */
1189       rank = YUV_BASE_RANK + 7;
1190       break;
1191     case V4L2_PIX_FMT_YUYV:    /* YUY2, 16 bits per pixel */
1192       rank = YUV_BASE_RANK + 10;
1193       break;
1194     case V4L2_PIX_FMT_YVU420:  /* YV12, 12 bits per pixel */
1195       rank = YUV_BASE_RANK + 6;
1196       break;
1197     case V4L2_PIX_FMT_UYVY:    /* UYVY, 16 bits per pixel */
1198       rank = YUV_BASE_RANK + 9;
1199       break;
1200     case V4L2_PIX_FMT_Y41P:    /* Y41P, 12 bits per pixel */
1201       rank = YUV_BASE_RANK + 5;
1202       break;
1203     case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1204       rank = YUV_BASE_RANK + 4;
1205       break;
1206     case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1207       rank = YUV_BASE_RANK + 8;
1208       break;
1209
1210     case V4L2_PIX_FMT_DV:
1211       rank = DV_BASE_RANK;
1212       break;
1213
1214     case V4L2_PIX_FMT_WNVA:    /* Winnov hw compres */
1215       rank = 0;
1216       break;
1217
1218 #ifdef V4L2_PIX_FMT_SBGGR8
1219     case V4L2_PIX_FMT_SBGGR8:
1220       rank = BAYER_BASE_RANK;
1221       break;
1222 #endif
1223
1224 #ifdef V4L2_PIX_FMT_SN9C10X
1225     case V4L2_PIX_FMT_SN9C10X:
1226       rank = S910_BASE_RANK;
1227       break;
1228 #endif
1229
1230 #ifdef V4L2_PIX_FMT_PWC1
1231     case V4L2_PIX_FMT_PWC1:
1232       rank = PWC_BASE_RANK;
1233       break;
1234 #endif
1235 #ifdef V4L2_PIX_FMT_PWC2
1236     case V4L2_PIX_FMT_PWC2:
1237       rank = PWC_BASE_RANK;
1238       break;
1239 #endif
1240
1241     default:
1242       rank = 0;
1243       break;
1244   }
1245
1246   /* All ranks are below 1<<15 so a shift by 15
1247    * will a) make all non-emulated formats larger
1248    * than emulated and b) will not overflow
1249    */
1250   if (!emulated)
1251     rank <<= 15;
1252
1253   return rank;
1254 }
1255
1256
1257
1258 static gint
1259 format_cmp_func (gconstpointer a, gconstpointer b)
1260 {
1261   const struct v4l2_fmtdesc *fa = a;
1262   const struct v4l2_fmtdesc *fb = b;
1263
1264   if (fa->pixelformat == fb->pixelformat)
1265     return 0;
1266
1267   return gst_v4l2_object_format_get_rank (fb) -
1268       gst_v4l2_object_format_get_rank (fa);
1269 }
1270
1271 /******************************************************
1272  * gst_v4l2_object_fill_format_list():
1273  *   create list of supported capture formats
1274  * return value: TRUE on success, FALSE on error
1275  ******************************************************/
1276 static gboolean
1277 gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object,
1278     enum v4l2_buf_type type)
1279 {
1280   gint n;
1281   struct v4l2_fmtdesc *format;
1282
1283   GST_DEBUG_OBJECT (v4l2object->element, "getting src format enumerations");
1284
1285   /* format enumeration */
1286   for (n = 0;; n++) {
1287     format = g_new0 (struct v4l2_fmtdesc, 1);
1288
1289     format->index = n;
1290     format->type = type;
1291
1292     if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1293       if (errno == EINVAL) {
1294         g_free (format);
1295         break;                  /* end of enumeration */
1296       } else {
1297         goto failed;
1298       }
1299     }
1300
1301     GST_LOG_OBJECT (v4l2object->element, "index:       %u", format->index);
1302     GST_LOG_OBJECT (v4l2object->element, "type:        %d", format->type);
1303     GST_LOG_OBJECT (v4l2object->element, "flags:       %08x", format->flags);
1304     GST_LOG_OBJECT (v4l2object->element, "description: '%s'",
1305         format->description);
1306     GST_LOG_OBJECT (v4l2object->element, "pixelformat: %" GST_FOURCC_FORMAT,
1307         GST_FOURCC_ARGS (format->pixelformat));
1308
1309     /* sort formats according to our preference;  we do this, because caps
1310      * are probed in the order the formats are in the list, and the order of
1311      * formats in the final probed caps matters for things like fixation */
1312     v4l2object->formats = g_slist_insert_sorted (v4l2object->formats, format,
1313         (GCompareFunc) format_cmp_func);
1314   }
1315
1316 #ifndef GST_DISABLE_GST_DEBUG
1317   {
1318     GSList *l;
1319
1320     GST_INFO_OBJECT (v4l2object->element, "got %d format(s):", n);
1321     for (l = v4l2object->formats; l != NULL; l = l->next) {
1322       format = l->data;
1323
1324       GST_INFO_OBJECT (v4l2object->element,
1325           "  %" GST_FOURCC_FORMAT "%s", GST_FOURCC_ARGS (format->pixelformat),
1326           ((format->flags & V4L2_FMT_FLAG_EMULATED)) ? " (emulated)" : "");
1327     }
1328   }
1329 #endif
1330
1331   return TRUE;
1332
1333   /* ERRORS */
1334 failed:
1335   {
1336     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
1337         (_("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)));
1338     g_free (format);
1339     return FALSE;
1340   }
1341 }
1342
1343 /*
1344   * Get the list of supported capture formats, a list of
1345   * <code>struct v4l2_fmtdesc</code>.
1346   */
1347 static GSList *
1348 gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object)
1349 {
1350   if (!v4l2object->formats) {
1351
1352     /* check usual way */
1353     gst_v4l2_object_fill_format_list (v4l2object, v4l2object->type);
1354
1355     /* if our driver supports multi-planar
1356      * and if formats are still empty then we can workaround driver bug
1357      * by also looking up formats as if our device was not supporting
1358      * multiplanar */
1359     if (!v4l2object->formats) {
1360       switch (v4l2object->type) {
1361         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1362           gst_v4l2_object_fill_format_list (v4l2object,
1363               V4L2_BUF_TYPE_VIDEO_CAPTURE);
1364           break;
1365
1366         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1367           gst_v4l2_object_fill_format_list (v4l2object,
1368               V4L2_BUF_TYPE_VIDEO_OUTPUT);
1369           break;
1370
1371         default:
1372           break;
1373       }
1374     }
1375   }
1376   return v4l2object->formats;
1377 }
1378
1379 static GstVideoFormat
1380 gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
1381 {
1382   GstVideoFormat format;
1383
1384   switch (fourcc) {
1385     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
1386       format = GST_VIDEO_FORMAT_GRAY8;
1387       break;
1388     case V4L2_PIX_FMT_RGB555:
1389       format = GST_VIDEO_FORMAT_RGB15;
1390       break;
1391     case V4L2_PIX_FMT_RGB565:
1392       format = GST_VIDEO_FORMAT_RGB16;
1393       break;
1394     case V4L2_PIX_FMT_RGB24:
1395       format = GST_VIDEO_FORMAT_RGB;
1396       break;
1397     case V4L2_PIX_FMT_BGR24:
1398       format = GST_VIDEO_FORMAT_BGR;
1399       break;
1400     case V4L2_PIX_FMT_RGB32:
1401       format = GST_VIDEO_FORMAT_RGBx;
1402       break;
1403     case V4L2_PIX_FMT_BGR32:
1404       format = GST_VIDEO_FORMAT_BGRx;
1405       break;
1406     case V4L2_PIX_FMT_NV12:
1407     case V4L2_PIX_FMT_NV12M:
1408       format = GST_VIDEO_FORMAT_NV12;
1409       break;
1410     case V4L2_PIX_FMT_NV12MT:
1411       format = GST_VIDEO_FORMAT_NV12_64Z32;
1412       break;
1413     case V4L2_PIX_FMT_NV21:
1414     case V4L2_PIX_FMT_NV21M:
1415       format = GST_VIDEO_FORMAT_NV21;
1416       break;
1417     case V4L2_PIX_FMT_YVU410:
1418       format = GST_VIDEO_FORMAT_YVU9;
1419       break;
1420     case V4L2_PIX_FMT_YUV410:
1421       format = GST_VIDEO_FORMAT_YUV9;
1422       break;
1423     case V4L2_PIX_FMT_YUV420:
1424       format = GST_VIDEO_FORMAT_I420;
1425       break;
1426     case V4L2_PIX_FMT_YUYV:
1427       format = GST_VIDEO_FORMAT_YUY2;
1428       break;
1429     case V4L2_PIX_FMT_YVU420:
1430       format = GST_VIDEO_FORMAT_YV12;
1431       break;
1432     case V4L2_PIX_FMT_UYVY:
1433       format = GST_VIDEO_FORMAT_UYVY;
1434       break;
1435 #if 0
1436     case V4L2_PIX_FMT_Y41P:
1437       format = GST_VIDEO_FORMAT_Y41P;
1438       break;
1439 #endif
1440     case V4L2_PIX_FMT_YUV411P:
1441       format = GST_VIDEO_FORMAT_Y41B;
1442       break;
1443     case V4L2_PIX_FMT_YUV422P:
1444       format = GST_VIDEO_FORMAT_Y42B;
1445       break;
1446 #ifdef V4L2_PIX_FMT_YVYU
1447     case V4L2_PIX_FMT_YVYU:
1448       format = GST_VIDEO_FORMAT_YVYU;
1449       break;
1450 #endif
1451     default:
1452       format = GST_VIDEO_FORMAT_UNKNOWN;
1453       g_assert_not_reached ();
1454       break;
1455   }
1456
1457   return format;
1458 }
1459
1460 GstStructure *
1461 gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
1462 {
1463   GstStructure *structure = NULL;
1464
1465   switch (fourcc) {
1466     case V4L2_PIX_FMT_MJPEG:   /* Motion-JPEG */
1467 #ifdef V4L2_PIX_FMT_PJPG
1468     case V4L2_PIX_FMT_PJPG:    /* Progressive-JPEG */
1469 #endif
1470     case V4L2_PIX_FMT_JPEG:    /* JFIF JPEG */
1471       structure = gst_structure_new_empty ("image/jpeg");
1472       break;
1473     case V4L2_PIX_FMT_YYUV:    /* 16  YUV 4:2:2     */
1474     case V4L2_PIX_FMT_HI240:   /*  8  8-bit color   */
1475       /* FIXME: get correct fourccs here */
1476       break;
1477     case V4L2_PIX_FMT_MPEG1:
1478       structure = gst_structure_new ("video/mpeg",
1479           "mpegversion", G_TYPE_INT, 2, NULL);
1480       break;
1481     case V4L2_PIX_FMT_MPEG2:
1482       structure = gst_structure_new ("video/mpeg",
1483           "mpegversion", G_TYPE_INT, 2, NULL);
1484       break;
1485     case V4L2_PIX_FMT_MPEG4:
1486       structure = gst_structure_new ("video/mpeg",
1487           "mpegversion", G_TYPE_INT, 4, "systemstream",
1488           G_TYPE_BOOLEAN, FALSE, NULL);
1489       break;
1490 #ifdef V4L2_PIX_FMT_H263
1491     case V4L2_PIX_FMT_H263:
1492       structure = gst_structure_new ("video/x-h263",
1493           "variant", G_TYPE_STRING, "itu", NULL);
1494       break;
1495 #endif
1496 #ifdef V4L2_PIX_FMT_H264
1497     case V4L2_PIX_FMT_H264:    /* H.264 */
1498       structure = gst_structure_new ("video/x-h264",
1499           "stream-format", G_TYPE_STRING, "byte-stream", "alignment",
1500           G_TYPE_STRING, "au", NULL);
1501       break;
1502 #endif
1503 #ifdef V4L2_PIX_FMT_VP8
1504     case V4L2_PIX_FMT_VP8:
1505       structure = gst_structure_new_empty ("video/x-vp8");
1506       break;
1507 #endif
1508     case V4L2_PIX_FMT_RGB332:
1509     case V4L2_PIX_FMT_RGB555X:
1510     case V4L2_PIX_FMT_RGB565X:
1511       /* FIXME: get correct fourccs here */
1512       break;
1513     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
1514     case V4L2_PIX_FMT_RGB555:
1515     case V4L2_PIX_FMT_RGB565:
1516     case V4L2_PIX_FMT_RGB24:
1517     case V4L2_PIX_FMT_BGR24:
1518     case V4L2_PIX_FMT_RGB32:
1519     case V4L2_PIX_FMT_BGR32:
1520     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
1521     case V4L2_PIX_FMT_NV12M:
1522     case V4L2_PIX_FMT_NV12MT:
1523     case V4L2_PIX_FMT_NV21:    /* 12  Y/CrCb 4:2:0  */
1524     case V4L2_PIX_FMT_NV21M:
1525     case V4L2_PIX_FMT_YVU410:
1526     case V4L2_PIX_FMT_YUV410:
1527     case V4L2_PIX_FMT_YUV420:  /* I420/IYUV */
1528     case V4L2_PIX_FMT_YUYV:
1529     case V4L2_PIX_FMT_YVU420:
1530     case V4L2_PIX_FMT_UYVY:
1531 #if 0
1532     case V4L2_PIX_FMT_Y41P:
1533 #endif
1534     case V4L2_PIX_FMT_YUV422P:
1535 #ifdef V4L2_PIX_FMT_YVYU
1536     case V4L2_PIX_FMT_YVYU:
1537 #endif
1538     case V4L2_PIX_FMT_YUV411P:{
1539       GstVideoFormat format;
1540       format = gst_v4l2_object_v4l2fourcc_to_video_format (fourcc);
1541       if (format != GST_VIDEO_FORMAT_UNKNOWN)
1542         structure = gst_structure_new ("video/x-raw",
1543             "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
1544       break;
1545     }
1546     case V4L2_PIX_FMT_DV:
1547       structure =
1548           gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE,
1549           NULL);
1550       break;
1551     case V4L2_PIX_FMT_MPEG:    /* MPEG          */
1552       structure = gst_structure_new_empty ("video/mpegts");
1553       break;
1554     case V4L2_PIX_FMT_WNVA:    /* Winnov hw compres */
1555       break;
1556 #ifdef V4L2_PIX_FMT_SBGGR8
1557     case V4L2_PIX_FMT_SBGGR8:
1558       structure = gst_structure_new_empty ("video/x-bayer");
1559       break;
1560 #endif
1561 #ifdef V4L2_PIX_FMT_SN9C10X
1562     case V4L2_PIX_FMT_SN9C10X:
1563       structure = gst_structure_new_empty ("video/x-sonix");
1564       break;
1565 #endif
1566 #ifdef V4L2_PIX_FMT_PWC1
1567     case V4L2_PIX_FMT_PWC1:
1568       structure = gst_structure_new_empty ("video/x-pwc1");
1569       break;
1570 #endif
1571 #ifdef V4L2_PIX_FMT_PWC2
1572     case V4L2_PIX_FMT_PWC2:
1573       structure = gst_structure_new_empty ("video/x-pwc2");
1574       break;
1575 #endif
1576     default:
1577       GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
1578           fourcc, GST_FOURCC_ARGS (fourcc));
1579       break;
1580   }
1581
1582   return structure;
1583 }
1584
1585
1586 static GstCaps *
1587 gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags)
1588 {
1589   GstStructure *structure;
1590   GstCaps *caps;
1591   guint i;
1592
1593   caps = gst_caps_new_empty ();
1594   for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
1595
1596     if ((gst_v4l2_formats[i].flags & flags) == 0)
1597       continue;
1598
1599     structure =
1600         gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i].format);
1601     if (structure) {
1602       if (gst_v4l2_formats[i].dimensions) {
1603         gst_structure_set (structure,
1604             "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
1605             "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
1606             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL);
1607       }
1608       gst_caps_append_structure (caps, structure);
1609     }
1610   }
1611
1612   return gst_caps_simplify (caps);
1613 }
1614
1615 GstCaps *
1616 gst_v4l2_object_get_all_caps (void)
1617 {
1618   static GstCaps *caps = NULL;
1619
1620   if (caps == NULL)
1621     caps = gst_v4l2_object_get_caps_helper (GST_V4L2_ALL);
1622
1623   return gst_caps_ref (caps);
1624 }
1625
1626 GstCaps *
1627 gst_v4l2_object_get_raw_caps (void)
1628 {
1629   static GstCaps *caps = NULL;
1630
1631   if (caps == NULL)
1632     caps = gst_v4l2_object_get_caps_helper (GST_V4L2_RAW);
1633
1634   return gst_caps_ref (caps);
1635 }
1636
1637 GstCaps *
1638 gst_v4l2_object_get_codec_caps (void)
1639 {
1640   static GstCaps *caps = NULL;
1641
1642   if (caps == NULL)
1643     caps = gst_v4l2_object_get_caps_helper (GST_V4L2_CODEC);
1644
1645   return gst_caps_ref (caps);
1646 }
1647
1648 /* gst_v4l2_object_choose_fourcc:
1649  * @obj a #GstV4l2Object
1650  * @fourcc_splane The format type in single plane representation
1651  * @fourcc_mplane The format type in multi-plane representation
1652  * @fourcc Set to the first format to try
1653  * @fourcc_alt The alternative format to use, or zero if mplane is not
1654  * supported. Note that if alternate is used, the prefered_non_contiguous
1655  * setting need to be inversed.
1656  *
1657  * Certain format can be stored into multi-planar buffer type with two
1658  * representation. As an example, NV12, which has two planes, can be stored
1659  * into 1 plane of multi-planar buffer sturcture, or two. This function will
1660  * choose the right format to use base on the object settings.
1661  */
1662 static void
1663 gst_v4l2_object_choose_fourcc (GstV4l2Object * obj, guint32 fourcc_splane,
1664     guint32 fourcc_mplane, guint32 * fourcc, guint32 * fourcc_alt)
1665 {
1666   if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
1667     if (obj->prefered_non_contiguous) {
1668       *fourcc = fourcc_mplane;
1669       *fourcc_alt = fourcc_splane;
1670     } else {
1671       *fourcc = fourcc_splane;
1672       *fourcc_alt = fourcc_mplane;
1673     }
1674   } else {
1675     *fourcc = fourcc_splane;
1676     *fourcc_alt = 0;
1677   }
1678 }
1679
1680 /* collect data for the given caps
1681  * @caps: given input caps
1682  * @format: location for the v4l format
1683  * @w/@h: location for width and height
1684  * @fps_n/@fps_d: location for framerate
1685  * @size: location for expected size of the frame or 0 if unknown
1686  */
1687 static gboolean
1688 gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
1689     struct v4l2_fmtdesc **format, GstVideoInfo * info)
1690 {
1691   GstStructure *structure;
1692   guint32 fourcc, fourcc_alt = 0;
1693   const gchar *mimetype;
1694   struct v4l2_fmtdesc *fmt;
1695
1696   /* default unknown values */
1697   fourcc = 0;
1698
1699   structure = gst_caps_get_structure (caps, 0);
1700
1701   mimetype = gst_structure_get_name (structure);
1702
1703   if (!gst_video_info_from_caps (info, caps))
1704     goto invalid_format;
1705
1706   if (g_str_equal (mimetype, "video/x-raw")) {
1707     switch (GST_VIDEO_INFO_FORMAT (info)) {
1708       case GST_VIDEO_FORMAT_I420:
1709         fourcc = V4L2_PIX_FMT_YUV420;
1710         break;
1711       case GST_VIDEO_FORMAT_YUY2:
1712         fourcc = V4L2_PIX_FMT_YUYV;
1713         break;
1714 #if 0
1715       case GST_VIDEO_FORMAT_Y41P:
1716         fourcc = V4L2_PIX_FMT_Y41P;
1717         break;
1718 #endif
1719       case GST_VIDEO_FORMAT_UYVY:
1720         fourcc = V4L2_PIX_FMT_UYVY;
1721         break;
1722       case GST_VIDEO_FORMAT_YV12:
1723         fourcc = V4L2_PIX_FMT_YVU420;
1724         break;
1725       case GST_VIDEO_FORMAT_Y41B:
1726         fourcc = V4L2_PIX_FMT_YUV411P;
1727         break;
1728       case GST_VIDEO_FORMAT_Y42B:
1729         fourcc = V4L2_PIX_FMT_YUV422P;
1730         break;
1731       case GST_VIDEO_FORMAT_NV12:
1732         gst_v4l2_object_choose_fourcc (v4l2object, V4L2_PIX_FMT_NV12,
1733             V4L2_PIX_FMT_NV12M, &fourcc, &fourcc_alt);
1734         break;
1735       case GST_VIDEO_FORMAT_NV12_64Z32:
1736         fourcc = V4L2_PIX_FMT_NV12MT;
1737         break;
1738       case GST_VIDEO_FORMAT_NV21:
1739         gst_v4l2_object_choose_fourcc (v4l2object, V4L2_PIX_FMT_NV21,
1740             V4L2_PIX_FMT_NV21M, &fourcc, &fourcc_alt);
1741         break;
1742 #ifdef V4L2_PIX_FMT_YVYU
1743       case GST_VIDEO_FORMAT_YVYU:
1744         fourcc = V4L2_PIX_FMT_YVYU;
1745         break;
1746 #endif
1747       case GST_VIDEO_FORMAT_RGB15:
1748         fourcc = V4L2_PIX_FMT_RGB555;
1749         break;
1750       case GST_VIDEO_FORMAT_RGB16:
1751         fourcc = V4L2_PIX_FMT_RGB565;
1752         break;
1753       case GST_VIDEO_FORMAT_RGB:
1754         fourcc = V4L2_PIX_FMT_RGB24;
1755         break;
1756       case GST_VIDEO_FORMAT_BGR:
1757         fourcc = V4L2_PIX_FMT_BGR24;
1758         break;
1759       case GST_VIDEO_FORMAT_RGBx:
1760       case GST_VIDEO_FORMAT_RGBA:
1761         fourcc = V4L2_PIX_FMT_RGB32;
1762         break;
1763       case GST_VIDEO_FORMAT_BGRx:
1764       case GST_VIDEO_FORMAT_BGRA:
1765         fourcc = V4L2_PIX_FMT_BGR32;
1766         break;
1767       case GST_VIDEO_FORMAT_GRAY8:
1768         fourcc = V4L2_PIX_FMT_GREY;
1769       default:
1770         break;
1771     }
1772   } else {
1773     if (g_str_equal (mimetype, "video/mpegts")) {
1774       fourcc = V4L2_PIX_FMT_MPEG;
1775     } else if (g_str_equal (mimetype, "video/x-dv")) {
1776       fourcc = V4L2_PIX_FMT_DV;
1777     } else if (g_str_equal (mimetype, "image/jpeg")) {
1778       fourcc = V4L2_PIX_FMT_JPEG;
1779     } else if (g_str_equal (mimetype, "video/mpeg")) {
1780       gint version;
1781       if (gst_structure_get_int (structure, "mpegversion", &version)) {
1782         switch (version) {
1783           case 1:
1784             fourcc = V4L2_PIX_FMT_MPEG1;
1785             break;
1786           case 2:
1787             fourcc = V4L2_PIX_FMT_MPEG2;
1788             break;
1789           case 4:
1790             fourcc = V4L2_PIX_FMT_MPEG4;
1791             break;
1792           default:
1793             break;
1794         }
1795       }
1796 #ifdef V4L2_PIX_FMT_H263
1797     } else if (g_str_equal (mimetype, "video/x-h263")) {
1798       fourcc = V4L2_PIX_FMT_H263;
1799 #endif
1800 #ifdef V4L2_PIX_FMT_H264
1801     } else if (g_str_equal (mimetype, "video/x-h264")) {
1802       fourcc = V4L2_PIX_FMT_H264;
1803 #endif
1804 #ifdef V4L2_PIX_FMT_VP8
1805     } else if (g_str_equal (mimetype, "video/x-vp8")) {
1806       fourcc = V4L2_PIX_FMT_VP8;
1807 #endif
1808 #ifdef V4L2_PIX_FMT_SBGGR8
1809     } else if (g_str_equal (mimetype, "video/x-bayer")) {
1810       fourcc = V4L2_PIX_FMT_SBGGR8;
1811 #endif
1812 #ifdef V4L2_PIX_FMT_SN9C10X
1813     } else if (g_str_equal (mimetype, "video/x-sonix")) {
1814       fourcc = V4L2_PIX_FMT_SN9C10X;
1815 #endif
1816 #ifdef V4L2_PIX_FMT_PWC1
1817     } else if (g_str_equal (mimetype, "video/x-pwc1")) {
1818       fourcc = V4L2_PIX_FMT_PWC1;
1819 #endif
1820 #ifdef V4L2_PIX_FMT_PWC2
1821     } else if (g_str_equal (mimetype, "video/x-pwc2")) {
1822       fourcc = V4L2_PIX_FMT_PWC2;
1823     }
1824 #endif
1825   }
1826
1827   if (fourcc == 0)
1828     goto unhandled_format;
1829
1830   fmt = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc);
1831
1832   if (fmt == NULL && fourcc_alt != 0) {
1833     GST_DEBUG_OBJECT (v4l2object, "No support for %" GST_FOURCC_FORMAT
1834         " trying %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc),
1835         GST_FOURCC_ARGS (fourcc_alt));
1836     v4l2object->prefered_non_contiguous = !v4l2object->prefered_non_contiguous;
1837     fmt = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc_alt);
1838   }
1839
1840   if (fmt == NULL)
1841     goto unsupported_format;
1842
1843   *format = fmt;
1844
1845   return TRUE;
1846
1847   /* ERRORS */
1848 invalid_format:
1849   {
1850     GST_DEBUG_OBJECT (v4l2object, "invalid format");
1851     return FALSE;
1852   }
1853 unhandled_format:
1854   {
1855     GST_DEBUG_OBJECT (v4l2object, "unhandled format");
1856     return FALSE;
1857   }
1858 unsupported_format:
1859   {
1860     GST_DEBUG_OBJECT (v4l2object, "unsupported format");
1861     return FALSE;
1862   }
1863 }
1864
1865 static gboolean
1866 gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
1867     guint32 pixelformat, gint * width, gint * height, gboolean * interlaced);
1868
1869 static void
1870 gst_v4l2_object_add_aspect_ratio (GstV4l2Object * v4l2object, GstStructure * s)
1871 {
1872   struct v4l2_cropcap cropcap;
1873   int num = 1, den = 1;
1874
1875   if (!v4l2object->keep_aspect)
1876     return;
1877
1878   if (v4l2object->par) {
1879     num = gst_value_get_fraction_numerator (v4l2object->par);
1880     den = gst_value_get_fraction_denominator (v4l2object->par);
1881     goto done;
1882   }
1883
1884   memset (&cropcap, 0, sizeof (cropcap));
1885
1886   cropcap.type = v4l2object->type;
1887   if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0)
1888     goto cropcap_failed;
1889
1890   num = cropcap.pixelaspect.numerator;
1891   den = cropcap.pixelaspect.denominator;
1892
1893 done:
1894   gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, num, den,
1895       NULL);
1896   return;
1897
1898 cropcap_failed:
1899   if (errno != ENOTTY)
1900     GST_WARNING_OBJECT (v4l2object->element,
1901         "Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s",
1902         g_strerror (errno));
1903   goto done;
1904 }
1905
1906
1907 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1908 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1909 static GstStructure *
1910 gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
1911     guint32 pixelformat,
1912     guint32 width, guint32 height, const GstStructure * template)
1913 {
1914   gint fd = v4l2object->video_fd;
1915   struct v4l2_frmivalenum ival;
1916   guint32 num, denom;
1917   GstStructure *s;
1918   GValue rates = { 0, };
1919   gboolean interlaced;
1920   gint int_width = width;
1921   gint int_height = height;
1922
1923   if (v4l2object->never_interlaced) {
1924     interlaced = FALSE;
1925   } else {
1926     /* Interlaced detection using VIDIOC_TRY/S_FMT */
1927     if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat,
1928             &int_width, &int_height, &interlaced))
1929       return NULL;
1930   }
1931
1932   memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1933   ival.index = 0;
1934   ival.pixel_format = pixelformat;
1935   ival.width = width;
1936   ival.height = height;
1937
1938   GST_LOG_OBJECT (v4l2object->element,
1939       "get frame interval for %ux%u, %" GST_FOURCC_FORMAT, width, height,
1940       GST_FOURCC_ARGS (pixelformat));
1941
1942   /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1943    * fraction to get framerate */
1944   if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1945     goto enum_frameintervals_failed;
1946
1947   if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1948     GValue rate = { 0, };
1949
1950     g_value_init (&rates, GST_TYPE_LIST);
1951     g_value_init (&rate, GST_TYPE_FRACTION);
1952
1953     do {
1954       num = ival.discrete.numerator;
1955       denom = ival.discrete.denominator;
1956
1957       if (num > G_MAXINT || denom > G_MAXINT) {
1958         /* let us hope we don't get here... */
1959         num >>= 1;
1960         denom >>= 1;
1961       }
1962
1963       GST_LOG_OBJECT (v4l2object->element, "adding discrete framerate: %d/%d",
1964           denom, num);
1965
1966       /* swap to get the framerate */
1967       gst_value_set_fraction (&rate, denom, num);
1968       gst_value_list_append_value (&rates, &rate);
1969
1970       ival.index++;
1971     } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1972   } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1973     GValue min = { 0, };
1974     GValue step = { 0, };
1975     GValue max = { 0, };
1976     gboolean added = FALSE;
1977     guint32 minnum, mindenom;
1978     guint32 maxnum, maxdenom;
1979
1980     g_value_init (&rates, GST_TYPE_LIST);
1981
1982     g_value_init (&min, GST_TYPE_FRACTION);
1983     g_value_init (&step, GST_TYPE_FRACTION);
1984     g_value_init (&max, GST_TYPE_FRACTION);
1985
1986     /* get the min */
1987     minnum = ival.stepwise.min.numerator;
1988     mindenom = ival.stepwise.min.denominator;
1989     if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1990       minnum >>= 1;
1991       mindenom >>= 1;
1992     }
1993     GST_LOG_OBJECT (v4l2object->element, "stepwise min frame interval: %d/%d",
1994         minnum, mindenom);
1995     gst_value_set_fraction (&min, minnum, mindenom);
1996
1997     /* get the max */
1998     maxnum = ival.stepwise.max.numerator;
1999     maxdenom = ival.stepwise.max.denominator;
2000     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
2001       maxnum >>= 1;
2002       maxdenom >>= 1;
2003     }
2004
2005     GST_LOG_OBJECT (v4l2object->element, "stepwise max frame interval: %d/%d",
2006         maxnum, maxdenom);
2007     gst_value_set_fraction (&max, maxnum, maxdenom);
2008
2009     /* get the step */
2010     num = ival.stepwise.step.numerator;
2011     denom = ival.stepwise.step.denominator;
2012     if (num > G_MAXINT || denom > G_MAXINT) {
2013       num >>= 1;
2014       denom >>= 1;
2015     }
2016
2017     if (num == 0 || denom == 0) {
2018       /* in this case we have a wrong fraction or no step, set the step to max
2019        * so that we only add the min value in the loop below */
2020       num = maxnum;
2021       denom = maxdenom;
2022     }
2023
2024     /* since we only have gst_value_fraction_subtract and not add, negate the
2025      * numerator */
2026     GST_LOG_OBJECT (v4l2object->element, "stepwise step frame interval: %d/%d",
2027         num, denom);
2028     gst_value_set_fraction (&step, -num, denom);
2029
2030     while (gst_value_compare (&min, &max) != GST_VALUE_GREATER_THAN) {
2031       GValue rate = { 0, };
2032
2033       num = gst_value_get_fraction_numerator (&min);
2034       denom = gst_value_get_fraction_denominator (&min);
2035       GST_LOG_OBJECT (v4l2object->element, "adding stepwise framerate: %d/%d",
2036           denom, num);
2037
2038       /* invert to get the framerate */
2039       g_value_init (&rate, GST_TYPE_FRACTION);
2040       gst_value_set_fraction (&rate, denom, num);
2041       gst_value_list_append_value (&rates, &rate);
2042       added = TRUE;
2043
2044       /* we're actually adding because step was negated above. This is because
2045        * there is no _add function... */
2046       if (!gst_value_fraction_subtract (&min, &min, &step)) {
2047         GST_WARNING_OBJECT (v4l2object->element, "could not step fraction!");
2048         break;
2049       }
2050     }
2051     if (!added) {
2052       /* no range was added, leave the default range from the template */
2053       GST_WARNING_OBJECT (v4l2object->element,
2054           "no range added, leaving default");
2055       g_value_unset (&rates);
2056     }
2057   } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
2058     guint32 maxnum, maxdenom;
2059
2060     g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
2061
2062     num = ival.stepwise.min.numerator;
2063     denom = ival.stepwise.min.denominator;
2064     if (num > G_MAXINT || denom > G_MAXINT) {
2065       num >>= 1;
2066       denom >>= 1;
2067     }
2068
2069     maxnum = ival.stepwise.max.numerator;
2070     maxdenom = ival.stepwise.max.denominator;
2071     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
2072       maxnum >>= 1;
2073       maxdenom >>= 1;
2074     }
2075
2076     GST_LOG_OBJECT (v4l2object->element,
2077         "continuous frame interval %d/%d to %d/%d", maxdenom, maxnum, denom,
2078         num);
2079
2080     gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
2081   } else {
2082     goto unknown_type;
2083   }
2084
2085 return_data:
2086   s = gst_structure_copy (template);
2087   gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
2088       "height", G_TYPE_INT, (gint) height, NULL);
2089   gst_v4l2_object_add_aspect_ratio (v4l2object, s);
2090   if (g_str_equal (gst_structure_get_name (s), "video/x-raw"))
2091     gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
2092         (interlaced ? "mixed" : "progressive"), NULL);
2093
2094   if (G_IS_VALUE (&rates)) {
2095     /* only change the framerate on the template when we have a valid probed new
2096      * value */
2097     gst_structure_set_value (s, "framerate", &rates);
2098     g_value_unset (&rates);
2099   } else if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2100       v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2101     gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1,
2102         NULL);
2103   }
2104   return s;
2105
2106   /* ERRORS */
2107 enum_frameintervals_failed:
2108   {
2109     GST_DEBUG_OBJECT (v4l2object->element,
2110         "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
2111         GST_FOURCC_ARGS (pixelformat), width, height);
2112     goto return_data;
2113   }
2114 unknown_type:
2115   {
2116     /* I don't see how this is actually an error, we ignore the format then */
2117     GST_WARNING_OBJECT (v4l2object->element,
2118         "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
2119         GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
2120     return NULL;
2121   }
2122 }
2123 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
2124
2125 #ifdef VIDIOC_ENUM_FRAMESIZES
2126 static gint
2127 sort_by_frame_size (GstStructure * s1, GstStructure * s2)
2128 {
2129   int w1, h1, w2, h2;
2130
2131   gst_structure_get_int (s1, "width", &w1);
2132   gst_structure_get_int (s1, "height", &h1);
2133   gst_structure_get_int (s2, "width", &w2);
2134   gst_structure_get_int (s2, "height", &h2);
2135
2136   /* I think it's safe to assume that this won't overflow for a while */
2137   return ((w2 * h2) - (w1 * h1));
2138 }
2139 #endif
2140
2141 static void
2142 gst_v4l2_object_update_and_append (GstV4l2Object * v4l2object,
2143     guint32 format, GstCaps * caps, GstStructure * s)
2144 {
2145   /* FIXME remove when VP8 parser is ready, bug #722760 */
2146   if (format == V4L2_PIX_FMT_VP8)
2147     goto done;
2148
2149   /* Encoded stream on output buffer need to be parsed */
2150   if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
2151       v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2152     gint i = 0;
2153
2154     for (; i < GST_V4L2_FORMAT_COUNT; i++) {
2155       if (format == gst_v4l2_formats[i].format &&
2156           gst_v4l2_formats[i].flags == GST_V4L2_CODEC) {
2157         gst_structure_set (s, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
2158         break;
2159       }
2160     }
2161   }
2162
2163 done:
2164   gst_caps_append_structure (caps, s);
2165 }
2166
2167 static GstCaps *
2168 gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
2169     guint32 pixelformat, const GstStructure * template)
2170 {
2171   GstCaps *ret = gst_caps_new_empty ();
2172   GstStructure *tmp;
2173
2174 #ifdef VIDIOC_ENUM_FRAMESIZES
2175   gint fd = v4l2object->video_fd;
2176   struct v4l2_frmsizeenum size;
2177   GList *results = NULL;
2178   guint32 w, h;
2179
2180   if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G')) {
2181     gst_caps_append_structure (ret, gst_structure_copy (template));
2182     return ret;
2183   }
2184
2185   memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
2186   size.index = 0;
2187   size.pixel_format = pixelformat;
2188
2189   GST_DEBUG_OBJECT (v4l2object->element,
2190       "Enumerating frame sizes for %" GST_FOURCC_FORMAT,
2191       GST_FOURCC_ARGS (pixelformat));
2192
2193   if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
2194     goto enum_framesizes_failed;
2195
2196   if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
2197     do {
2198       GST_LOG_OBJECT (v4l2object->element, "got discrete frame size %dx%d",
2199           size.discrete.width, size.discrete.height);
2200
2201       w = MIN (size.discrete.width, G_MAXINT);
2202       h = MIN (size.discrete.height, G_MAXINT);
2203
2204       if (w && h) {
2205         tmp =
2206             gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
2207             pixelformat, w, h, template);
2208
2209         if (tmp)
2210           results = g_list_prepend (results, tmp);
2211       }
2212
2213       size.index++;
2214     } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
2215     GST_DEBUG_OBJECT (v4l2object->element,
2216         "done iterating discrete frame sizes");
2217   } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2218     GST_DEBUG_OBJECT (v4l2object->element, "we have stepwise frame sizes:");
2219     GST_DEBUG_OBJECT (v4l2object->element, "min width:   %d",
2220         size.stepwise.min_width);
2221     GST_DEBUG_OBJECT (v4l2object->element, "min height:  %d",
2222         size.stepwise.min_height);
2223     GST_DEBUG_OBJECT (v4l2object->element, "max width:   %d",
2224         size.stepwise.max_width);
2225     GST_DEBUG_OBJECT (v4l2object->element, "min height:  %d",
2226         size.stepwise.max_height);
2227     GST_DEBUG_OBJECT (v4l2object->element, "step width:  %d",
2228         size.stepwise.step_width);
2229     GST_DEBUG_OBJECT (v4l2object->element, "step height: %d",
2230         size.stepwise.step_height);
2231
2232     for (w = size.stepwise.min_width, h = size.stepwise.min_height;
2233         w <= size.stepwise.max_width && h <= size.stepwise.max_height;
2234         w += size.stepwise.step_width, h += size.stepwise.step_height) {
2235       if (w == 0 || h == 0)
2236         continue;
2237
2238       tmp =
2239           gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
2240           pixelformat, w, h, template);
2241
2242       if (tmp)
2243         results = g_list_prepend (results, tmp);
2244     }
2245     GST_DEBUG_OBJECT (v4l2object->element,
2246         "done iterating stepwise frame sizes");
2247   } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2248     guint32 maxw, maxh;
2249
2250     GST_DEBUG_OBJECT (v4l2object->element, "we have continuous frame sizes:");
2251     GST_DEBUG_OBJECT (v4l2object->element, "min width:   %d",
2252         size.stepwise.min_width);
2253     GST_DEBUG_OBJECT (v4l2object->element, "min height:  %d",
2254         size.stepwise.min_height);
2255     GST_DEBUG_OBJECT (v4l2object->element, "max width:   %d",
2256         size.stepwise.max_width);
2257     GST_DEBUG_OBJECT (v4l2object->element, "min height:  %d",
2258         size.stepwise.max_height);
2259
2260     w = MAX (size.stepwise.min_width, 1);
2261     h = MAX (size.stepwise.min_height, 1);
2262     maxw = MIN (size.stepwise.max_width, G_MAXINT);
2263     maxh = MIN (size.stepwise.max_height, G_MAXINT);
2264
2265     tmp =
2266         gst_v4l2_object_probe_caps_for_format_and_size (v4l2object, pixelformat,
2267         w, h, template);
2268     if (tmp) {
2269       gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, (gint) w,
2270           (gint) maxw, "height", GST_TYPE_INT_RANGE, (gint) h, (gint) maxh,
2271           NULL);
2272
2273       /* no point using the results list here, since there's only one struct */
2274       gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
2275     }
2276   } else {
2277     goto unknown_type;
2278   }
2279
2280   /* we use an intermediary list to store and then sort the results of the
2281    * probing because we can't make any assumptions about the order in which
2282    * the driver will give us the sizes, but we want the final caps to contain
2283    * the results starting with the highest resolution and having the lowest
2284    * resolution last, since order in caps matters for things like fixation. */
2285   results = g_list_sort (results, (GCompareFunc) sort_by_frame_size);
2286   while (results != NULL) {
2287     gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret,
2288         results->data);
2289     results = g_list_delete_link (results, results);
2290   }
2291
2292   if (gst_caps_is_empty (ret))
2293     goto enum_framesizes_no_results;
2294
2295   return ret;
2296
2297   /* ERRORS */
2298 enum_framesizes_failed:
2299   {
2300     /* I don't see how this is actually an error */
2301     GST_DEBUG_OBJECT (v4l2object->element,
2302         "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2303         " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2304     goto default_frame_sizes;
2305   }
2306 enum_framesizes_no_results:
2307   {
2308     /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2309      * question doesn't actually support it yet */
2310     GST_DEBUG_OBJECT (v4l2object->element,
2311         "No results for pixelformat %" GST_FOURCC_FORMAT
2312         " enumerating frame sizes, trying fallback",
2313         GST_FOURCC_ARGS (pixelformat));
2314     goto default_frame_sizes;
2315   }
2316 unknown_type:
2317   {
2318     GST_WARNING_OBJECT (v4l2object->element,
2319         "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2320         ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2321     goto default_frame_sizes;
2322   }
2323 default_frame_sizes:
2324 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2325   {
2326     gint min_w, max_w, min_h, max_h, fix_num = 0, fix_denom = 0;
2327     gboolean interlaced;
2328
2329     /* This code is for Linux < 2.6.19 */
2330     min_w = min_h = 1;
2331     max_w = max_h = GST_V4L2_MAX_SIZE;
2332     if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w,
2333             &min_h, &interlaced)) {
2334       GST_WARNING_OBJECT (v4l2object->element,
2335           "Could not probe minimum capture size for pixelformat %"
2336           GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2337     }
2338     if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w,
2339             &max_h, &interlaced)) {
2340       GST_WARNING_OBJECT (v4l2object->element,
2341           "Could not probe maximum capture size for pixelformat %"
2342           GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2343     }
2344
2345     /* Since we can't get framerate directly, try to use the current norm */
2346     if (v4l2object->tv_norm && v4l2object->norms) {
2347       GList *norms;
2348       GstTunerNorm *norm = NULL;
2349       GstTunerNorm *current =
2350           gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
2351
2352       for (norms = v4l2object->norms; norms != NULL; norms = norms->next) {
2353         norm = (GstTunerNorm *) norms->data;
2354         if (!strcmp (norm->label, current->label))
2355           break;
2356       }
2357       /* If it's possible, set framerate to that (discrete) value */
2358       if (norm) {
2359         fix_num = gst_value_get_fraction_numerator (&norm->framerate);
2360         fix_denom = gst_value_get_fraction_denominator (&norm->framerate);
2361       }
2362     }
2363
2364     tmp = gst_structure_copy (template);
2365     if (fix_num) {
2366       gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION, fix_num,
2367           fix_denom, NULL);
2368     } else if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2369         v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2370       /* if norm can't be used, copy the template framerate */
2371       gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
2372           100, 1, NULL);
2373     }
2374
2375     if (min_w == max_w)
2376       gst_structure_set (tmp, "width", G_TYPE_INT, max_w, NULL);
2377     else
2378       gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, min_w, max_w, NULL);
2379
2380     if (min_h == max_h)
2381       gst_structure_set (tmp, "height", G_TYPE_INT, max_h, NULL);
2382     else
2383       gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2384
2385     if (g_str_equal (gst_structure_get_name (tmp), "video/x-raw"))
2386       gst_structure_set (tmp, "interlace-mode", G_TYPE_STRING,
2387           (interlaced ? "mixed" : "progressive"), NULL);
2388     gst_v4l2_object_add_aspect_ratio (v4l2object, tmp);
2389
2390     gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
2391     return ret;
2392   }
2393 }
2394
2395 static gboolean
2396 gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
2397     guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
2398 {
2399   struct v4l2_format fmt, prevfmt;
2400   int fd;
2401   int r;
2402   int prevfmt_valid = FALSE;
2403   gboolean ret = FALSE;
2404
2405   g_return_val_if_fail (width != NULL, FALSE);
2406   g_return_val_if_fail (height != NULL, FALSE);
2407
2408   GST_LOG_OBJECT (v4l2object->element,
2409       "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2410       *width, *height, GST_FOURCC_ARGS (pixelformat));
2411
2412   fd = v4l2object->video_fd;
2413
2414   memset (&fmt, 0, sizeof (struct v4l2_format));
2415   memset (&prevfmt, 0, sizeof (struct v4l2_format));
2416
2417   /* Some drivers are buggy and will modify the currently set format
2418      when processing VIDIOC_TRY_FMT, so we remember what is set at the
2419      minute, and will reset it when done. */
2420   if (!v4l2object->no_initial_format) {
2421     prevfmt.type = v4l2object->type;
2422     prevfmt_valid = (v4l2_ioctl (fd, VIDIOC_G_FMT, &prevfmt) >= 0);
2423   }
2424
2425   /* get size delimiters */
2426   memset (&fmt, 0, sizeof (fmt));
2427   fmt.type = v4l2object->type;
2428   fmt.fmt.pix.width = *width;
2429   fmt.fmt.pix.height = *height;
2430   fmt.fmt.pix.pixelformat = pixelformat;
2431   fmt.fmt.pix.field = V4L2_FIELD_NONE;
2432
2433   r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2434   if (r < 0 && errno == EINVAL) {
2435     /* try again with interlaced video */
2436     fmt.fmt.pix.width = *width;
2437     fmt.fmt.pix.height = *height;
2438     fmt.fmt.pix.pixelformat = pixelformat;
2439     fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2440     r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2441   }
2442
2443   if (r < 0) {
2444     /* The driver might not implement TRY_FMT, in which case we will try
2445        S_FMT to probe */
2446     if (errno != ENOTTY)
2447       goto error;
2448
2449     /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2450        be, because we're still probing */
2451     if (GST_V4L2_IS_ACTIVE (v4l2object))
2452       goto error;
2453
2454     GST_LOG_OBJECT (v4l2object->element,
2455         "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2456
2457     fmt.fmt.pix.width = *width;
2458     fmt.fmt.pix.height = *height;
2459
2460     r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
2461     if (r < 0 && errno == EINVAL) {
2462       /* try again with progressive video */
2463       fmt.fmt.pix.width = *width;
2464       fmt.fmt.pix.height = *height;
2465       fmt.fmt.pix.pixelformat = pixelformat;
2466       fmt.fmt.pix.field = V4L2_FIELD_NONE;
2467       r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
2468     }
2469
2470     if (r < 0)
2471       goto error;
2472   }
2473
2474   GST_LOG_OBJECT (v4l2object->element,
2475       "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2476
2477   *width = fmt.fmt.pix.width;
2478   *height = fmt.fmt.pix.height;
2479
2480   switch (fmt.fmt.pix.field) {
2481     case V4L2_FIELD_ANY:
2482     case V4L2_FIELD_NONE:
2483       *interlaced = FALSE;
2484       break;
2485     case V4L2_FIELD_INTERLACED:
2486     case V4L2_FIELD_INTERLACED_TB:
2487     case V4L2_FIELD_INTERLACED_BT:
2488       *interlaced = TRUE;
2489       break;
2490     default:
2491       GST_WARNING_OBJECT (v4l2object->element,
2492           "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
2493           GST_FOURCC_ARGS (pixelformat), *width, *height);
2494       goto error;
2495   }
2496
2497   ret = TRUE;
2498
2499 error:
2500   if (!ret) {
2501     GST_WARNING_OBJECT (v4l2object->element,
2502         "Unable to try format: %s", g_strerror (errno));
2503   }
2504   if (prevfmt_valid)
2505     if (v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt) < 0) {
2506       GST_WARNING_OBJECT (v4l2object->element,
2507           "Unable to restore format after trying format: %s",
2508           g_strerror (errno));
2509     }
2510
2511   return ret;
2512 }
2513
2514 static gboolean
2515 gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
2516 {
2517   GstV4l2IOMode mode;
2518
2519   GST_DEBUG_OBJECT (v4l2object->element, "initializing the capture system");
2520
2521   GST_V4L2_CHECK_OPEN (v4l2object);
2522   GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
2523
2524   /* find transport */
2525   mode = v4l2object->req_mode;
2526
2527   if (v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
2528     if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
2529       mode = GST_V4L2_IO_RW;
2530   } else if (v4l2object->req_mode == GST_V4L2_IO_RW)
2531     goto method_not_supported;
2532
2533   if (v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
2534     if (v4l2object->req_mode == GST_V4L2_IO_AUTO)
2535       mode = GST_V4L2_IO_MMAP;
2536   } else if (v4l2object->req_mode == GST_V4L2_IO_MMAP)
2537     goto method_not_supported;
2538
2539   /* if still no transport selected, error out */
2540   if (mode == GST_V4L2_IO_AUTO)
2541     goto no_supported_capture_method;
2542
2543   GST_INFO_OBJECT (v4l2object->element, "accessing buffers via mode %d", mode);
2544   v4l2object->mode = mode;
2545
2546   /* Map the buffers */
2547   GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool");
2548
2549   if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object, caps)))
2550     goto buffer_pool_new_failed;
2551
2552   GST_V4L2_SET_ACTIVE (v4l2object);
2553
2554   return TRUE;
2555
2556   /* ERRORS */
2557 buffer_pool_new_failed:
2558   {
2559     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2560         (_("Could not map buffers from device '%s'"),
2561             v4l2object->videodev),
2562         ("Failed to create buffer pool: %s", g_strerror (errno)));
2563     return FALSE;
2564   }
2565 method_not_supported:
2566   {
2567     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2568         (_("The driver of device '%s' does not support the IO method %d"),
2569             v4l2object->videodev, mode), (NULL));
2570     return FALSE;
2571   }
2572 no_supported_capture_method:
2573   {
2574     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
2575         (_("The driver of device '%s' does not support any known IO "
2576                 "method."), v4l2object->videodev), (NULL));
2577     return FALSE;
2578   }
2579 }
2580
2581 static void
2582 gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
2583     struct v4l2_fmtdesc *fmtdesc, struct v4l2_format *format,
2584     GstVideoInfo * info)
2585 {
2586   const GstVideoFormatInfo *finfo = info->finfo;
2587   gint i;
2588
2589   if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) {
2590     /* figure out the frame layout */
2591     v4l2object->n_v4l2_planes = MAX (1, format->fmt.pix_mp.num_planes);
2592     v4l2object->sizeimage = 0;
2593     for (i = 0; i < format->fmt.pix_mp.num_planes; i++) {
2594       v4l2object->bytesperline[i] =
2595           format->fmt.pix_mp.plane_fmt[i].bytesperline;
2596       v4l2object->sizeimage += format->fmt.pix_mp.plane_fmt[i].sizeimage;
2597     }
2598   } else {
2599     /* only one plane in non-MPLANE mode */
2600     v4l2object->n_v4l2_planes = 1;
2601
2602     /* figure out the frame layout */
2603     for (i = 0; i < finfo->n_planes; i++) {
2604       guint stride = format->fmt.pix.bytesperline;
2605
2606       switch (finfo->format) {
2607         case GST_VIDEO_FORMAT_NV12:
2608         case GST_VIDEO_FORMAT_NV21:
2609         case GST_VIDEO_FORMAT_NV16:
2610         case GST_VIDEO_FORMAT_NV24:
2611           v4l2object->bytesperline[i] = (i == 0 ? 1 : 2) *
2612               GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, stride);
2613           break;
2614         default:
2615           v4l2object->bytesperline[i] =
2616               GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, stride);
2617           break;
2618       }
2619
2620       GST_DEBUG_OBJECT (v4l2object->element,
2621           "Extrapolated stride for plane %d from %d to %d", i, stride,
2622           v4l2object->bytesperline[i]);
2623     }
2624
2625     v4l2object->sizeimage = format->fmt.pix.sizeimage;
2626   }
2627
2628   GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %u",
2629       v4l2object->sizeimage);
2630
2631   v4l2object->info = *info;
2632   v4l2object->fmtdesc = fmtdesc;
2633
2634   /* if we have a framerate pre-calculate duration */
2635   if (info->fps_n > 0 && info->fps_d > 0) {
2636     v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND, info->fps_d,
2637         info->fps_n);
2638   } else {
2639     v4l2object->duration = GST_CLOCK_TIME_NONE;
2640   }
2641 }
2642
2643 gboolean
2644 gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
2645 {
2646   gint fd = v4l2object->video_fd;
2647   struct v4l2_format format;
2648   struct v4l2_streamparm streamparm;
2649   enum v4l2_field field;
2650   guint32 pixelformat;
2651   struct v4l2_fmtdesc *fmtdesc;
2652   GstVideoInfo info;
2653   gint width, height, fps_n, fps_d;
2654   gint i = 0;
2655
2656   GST_V4L2_CHECK_OPEN (v4l2object);
2657   GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
2658
2659   if (!gst_v4l2_object_get_caps_info (v4l2object, caps, &fmtdesc, &info))
2660     goto invalid_caps;
2661
2662   pixelformat = fmtdesc->pixelformat;
2663   width = GST_VIDEO_INFO_WIDTH (&info);
2664   height = GST_VIDEO_INFO_HEIGHT (&info);
2665   fps_n = GST_VIDEO_INFO_FPS_N (&info);
2666   fps_d = GST_VIDEO_INFO_FPS_D (&info);
2667
2668   /* get bytesperline for each plane */
2669   for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++)
2670     v4l2object->bytesperline[i] = GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
2671
2672   if (GST_VIDEO_INFO_IS_INTERLACED (&info)) {
2673     GST_DEBUG_OBJECT (v4l2object->element, "interlaced video");
2674     /* ideally we would differentiate between types of interlaced video
2675      * but there is not sufficient information in the caps..
2676      */
2677     field = V4L2_FIELD_INTERLACED;
2678   } else {
2679     GST_DEBUG_OBJECT (v4l2object->element, "progressive video");
2680     field = V4L2_FIELD_NONE;
2681   }
2682
2683   GST_DEBUG_OBJECT (v4l2object->element, "Desired format %dx%d, format "
2684       "%" GST_FOURCC_FORMAT " stride: %d", width, height,
2685       GST_FOURCC_ARGS (pixelformat), v4l2object->bytesperline[0]);
2686
2687   /* MPEG-TS source cameras don't get their format set for some reason.
2688    * It looks wrong and we weren't able to track down the reason for that code
2689    * so it is disabled until someone who has an mpeg-ts camera complains...
2690    */
2691 #if 0
2692   /* Only unconditionally accept mpegts for sources */
2693   if ((v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
2694       (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G')))
2695     goto done;
2696 #endif
2697
2698   memset (&format, 0x00, sizeof (struct v4l2_format));
2699   format.type = v4l2object->type;
2700
2701   if (!v4l2object->no_initial_format) {
2702     if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
2703       goto get_fmt_failed;
2704   }
2705
2706   if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) {
2707     GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2708         "%" GST_FOURCC_FORMAT " colorspace %d, nb planes %d",
2709         format.fmt.pix_mp.width, format.fmt.pix_mp.height,
2710         GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
2711         format.fmt.pix_mp.colorspace, format.fmt.pix_mp.num_planes);
2712
2713     if (format.type != v4l2object->type ||
2714         format.fmt.pix_mp.width != width ||
2715         format.fmt.pix_mp.height != height ||
2716         format.fmt.pix_mp.pixelformat != pixelformat ||
2717         format.fmt.pix_mp.field != field) {
2718       /* even in v4l2 multiplanar mode we can work in contiguous mode
2719        * if the device supports it */
2720       gint n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info);
2721
2722       /* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
2723        * or if contiguous is prefered */
2724       if (!n_v4l_planes || !v4l2object->prefered_non_contiguous)
2725         n_v4l_planes = 1;
2726
2727       /* something different, set the format */
2728       GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
2729           "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
2730
2731       format.type = v4l2object->type;
2732       format.fmt.pix_mp.pixelformat = pixelformat;
2733       format.fmt.pix_mp.width = width;
2734       format.fmt.pix_mp.height = height;
2735       format.fmt.pix_mp.field = field;
2736       format.fmt.pix_mp.num_planes = n_v4l_planes;
2737       /* try to ask our prefered stride but it's not a failure
2738        * if not accepted */
2739       for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
2740         format.fmt.pix_mp.plane_fmt[i].bytesperline =
2741             v4l2object->bytesperline[i];
2742
2743       if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED) {
2744         format.fmt.pix_mp.plane_fmt[0].sizeimage = ENCODED_BUFFER_SIZE;
2745       }
2746
2747       if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
2748         goto set_fmt_failed;
2749
2750       GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2751           "%" GST_FOURCC_FORMAT ", nb planes %d", format.fmt.pix.width,
2752           format.fmt.pix_mp.height,
2753           GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
2754           format.fmt.pix_mp.num_planes);
2755
2756 #ifndef GST_DISABLE_GST_DEBUG
2757       for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
2758         GST_DEBUG_OBJECT (v4l2object->element, "  stride %d",
2759             format.fmt.pix_mp.plane_fmt[i].bytesperline);
2760 #endif
2761
2762       if (format.fmt.pix_mp.pixelformat != pixelformat)
2763         goto invalid_pixelformat;
2764
2765       /* we set the dimensions just in case but don't validate them afterwards
2766        * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
2767        * in ASF mode for example. */
2768       if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
2769         if (format.fmt.pix_mp.width != width
2770             || format.fmt.pix_mp.height != height)
2771           goto invalid_dimensions;
2772       }
2773
2774       if (format.fmt.pix_mp.num_planes != n_v4l_planes)
2775         goto invalid_planes;
2776     }
2777
2778     /* figure out the frame layout */
2779     v4l2object->n_v4l2_planes = format.fmt.pix_mp.num_planes;
2780     v4l2object->sizeimage = 0;
2781     for (i = 0; i < format.fmt.pix_mp.num_planes; i++) {
2782       v4l2object->bytesperline[i] = format.fmt.pix_mp.plane_fmt[i].bytesperline;
2783       v4l2object->sizeimage += format.fmt.pix_mp.plane_fmt[i].sizeimage;
2784     }
2785   } else {
2786     GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2787         "%" GST_FOURCC_FORMAT " bytesperline %d, colorspace %d",
2788         format.fmt.pix.width, format.fmt.pix.height,
2789         GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
2790         format.fmt.pix.bytesperline, format.fmt.pix.colorspace);
2791
2792     if (format.type != v4l2object->type ||
2793         format.fmt.pix.width != width ||
2794         format.fmt.pix.height != height ||
2795         format.fmt.pix.pixelformat != pixelformat ||
2796         format.fmt.pix.field != field) {
2797       /* something different, set the format */
2798       GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
2799           "%" GST_FOURCC_FORMAT " bytesperline %d", width, height,
2800           GST_FOURCC_ARGS (pixelformat), v4l2object->bytesperline[0]);
2801
2802       format.type = v4l2object->type;
2803       format.fmt.pix.width = width;
2804       format.fmt.pix.height = height;
2805       format.fmt.pix.pixelformat = pixelformat;
2806       format.fmt.pix.field = field;
2807       /* try to ask our prefered stride */
2808       format.fmt.pix.bytesperline = v4l2object->bytesperline[0];
2809
2810       if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED) {
2811         format.fmt.pix.sizeimage = ENCODED_BUFFER_SIZE;
2812       }
2813
2814       if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
2815         goto set_fmt_failed;
2816
2817       GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
2818           "%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
2819           format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
2820           format.fmt.pix.bytesperline);
2821
2822       /* we set the dimensions just in case but don't validate them afterwards
2823        * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
2824        * in ASF mode for example. */
2825       if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
2826         if (format.fmt.pix.width != width || format.fmt.pix.height != height)
2827           goto invalid_dimensions;
2828       }
2829
2830       if (format.fmt.pix.pixelformat != pixelformat)
2831         goto invalid_pixelformat;
2832     }
2833   }
2834
2835   /* Is there a reason we require the caller to always specify a framerate? */
2836   GST_DEBUG_OBJECT (v4l2object->element, "Desired framerate: %u/%u", fps_n,
2837       fps_d);
2838
2839   memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
2840   streamparm.type = v4l2object->type;
2841
2842   if (v4l2_ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
2843     goto get_parm_failed;
2844
2845   GST_VIDEO_INFO_FPS_N (&info) =
2846       streamparm.parm.capture.timeperframe.denominator;
2847   GST_VIDEO_INFO_FPS_D (&info) = streamparm.parm.capture.timeperframe.numerator;
2848
2849   if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
2850       || v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2851     GST_DEBUG_OBJECT (v4l2object->element, "Got framerate: %u/%u",
2852         streamparm.parm.capture.timeperframe.denominator,
2853         streamparm.parm.capture.timeperframe.numerator);
2854
2855     /* We used to skip frame rate setup if the camera was already setup
2856      * with the requested frame rate. This breaks some cameras though,
2857      * causing them to not output data (several models of Thinkpad cameras
2858      * have this problem at least).
2859      * So, don't skip. */
2860     GST_LOG_OBJECT (v4l2object->element, "Setting framerate to %u/%u", fps_n,
2861         fps_d);
2862     /* We want to change the frame rate, so check whether we can. Some cheap USB
2863      * cameras don't have the capability */
2864     if ((streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
2865       GST_DEBUG_OBJECT (v4l2object->element,
2866           "Not setting framerate (not supported)");
2867       goto done;
2868     }
2869
2870     /* Note: V4L2 wants the frame interval, we have the frame rate */
2871     streamparm.parm.capture.timeperframe.numerator = fps_d;
2872     streamparm.parm.capture.timeperframe.denominator = fps_n;
2873
2874     /* some cheap USB cam's won't accept any change */
2875     if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
2876       goto set_parm_failed;
2877
2878     /* get new values */
2879     fps_d = streamparm.parm.capture.timeperframe.numerator;
2880     fps_n = streamparm.parm.capture.timeperframe.denominator;
2881
2882     GST_INFO_OBJECT (v4l2object->element, "Set framerate to %u/%u", fps_n,
2883         fps_d);
2884
2885     GST_VIDEO_INFO_FPS_N (&info) = fps_n;
2886     GST_VIDEO_INFO_FPS_D (&info) = fps_d;
2887   }
2888
2889 done:
2890   gst_v4l2_object_save_format (v4l2object, fmtdesc, &format, &info);
2891
2892   /* now configure ther pools */
2893   if (!gst_v4l2_object_setup_pool (v4l2object, caps))
2894     goto pool_failed;
2895
2896   return TRUE;
2897
2898   /* ERRORS */
2899 invalid_caps:
2900   {
2901     GST_DEBUG_OBJECT (v4l2object->element, "can't parse caps %" GST_PTR_FORMAT,
2902         caps);
2903     return FALSE;
2904   }
2905 get_fmt_failed:
2906   {
2907     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2908         (_("Device '%s' does not support video capture"),
2909             v4l2object->videodev),
2910         ("Call to G_FMT failed: (%s)", g_strerror (errno)));
2911     return FALSE;
2912   }
2913 set_fmt_failed:
2914   {
2915     if (errno == EBUSY) {
2916       GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, BUSY,
2917           (_("Device '%s' is busy"), v4l2object->videodev),
2918           ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
2919               GST_FOURCC_ARGS (pixelformat), width, height,
2920               g_strerror (errno)));
2921     } else {
2922       GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2923           (_("Device '%s' cannot capture at %dx%d"),
2924               v4l2object->videodev, width, height),
2925           ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
2926               GST_FOURCC_ARGS (pixelformat), width, height,
2927               g_strerror (errno)));
2928     }
2929     return FALSE;
2930   }
2931 invalid_dimensions:
2932   {
2933     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2934         (_("Device '%s' cannot capture at %dx%d"),
2935             v4l2object->videodev, width, height),
2936         ("Tried to capture at %dx%d, but device returned size %dx%d",
2937             width, height, format.fmt.pix.width, format.fmt.pix.height));
2938     return FALSE;
2939   }
2940 invalid_pixelformat:
2941   {
2942     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2943         (_("Device '%s' cannot capture in the specified format"),
2944             v4l2object->videodev),
2945         ("Tried to capture in %" GST_FOURCC_FORMAT
2946             ", but device returned format" " %" GST_FOURCC_FORMAT,
2947             GST_FOURCC_ARGS (pixelformat),
2948             GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
2949     return FALSE;
2950   }
2951 invalid_planes:
2952   {
2953     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2954         (_("Device '%s' does support non-contiguous planes"),
2955             v4l2object->videodev),
2956         ("Device wants %d planes", format.fmt.pix_mp.num_planes));
2957     return FALSE;
2958   }
2959 get_parm_failed:
2960   {
2961     /* it's possible that this call is not supported */
2962     if (errno != EINVAL && errno != ENOTTY) {
2963       GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
2964           (_("Could not get parameters on device '%s'"),
2965               v4l2object->videodev), GST_ERROR_SYSTEM);
2966     }
2967     goto done;
2968   }
2969 set_parm_failed:
2970   {
2971     GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
2972         (_("Video device did not accept new frame rate setting.")),
2973         GST_ERROR_SYSTEM);
2974     goto done;
2975   }
2976 pool_failed:
2977   {
2978     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
2979         (_("Video device could not create buffer pool.")), GST_ERROR_SYSTEM);
2980     return FALSE;
2981   }
2982 }
2983
2984 /**
2985  * gst_v4l2_object_setup_format:
2986  * @v4l2object the object
2987  * @info a GstVideoInfo to be filled
2988  * @align a GstVideoAlignment to be filled
2989  *
2990  * Setup the format base on the currently configured format. This is useful in
2991  * decoder or encoder elements where the output format is dictated by the
2992  * input.
2993  *
2994  * Returns: %TRUE on success, %FALSE on failure.
2995  */
2996 gboolean
2997 gst_v4l2_object_setup_format (GstV4l2Object * v4l2object,
2998     GstVideoInfo * info, GstVideoAlignment * align)
2999 {
3000   struct v4l2_fmtdesc *fmtdesc;
3001   struct v4l2_format fmt;
3002   struct v4l2_crop crop;
3003   GstVideoFormat format;
3004   guint width, height;
3005
3006   gst_video_info_init (info);
3007   gst_video_alignment_reset (align);
3008
3009   memset (&fmt, 0x00, sizeof (struct v4l2_format));
3010   fmt.type = v4l2object->type;
3011   if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0)
3012     goto get_fmt_failed;
3013
3014   fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object,
3015       fmt.fmt.pix.pixelformat);
3016   if (fmtdesc == NULL)
3017     goto unsupported_format;
3018
3019   /* No need to care about mplane, the four first params are the same */
3020   format = gst_v4l2_object_v4l2fourcc_to_video_format (fmt.fmt.pix.pixelformat);
3021
3022   /* FIXME do more work in the whole function if
3023    * format is GST_VIDEO_FORMAT_ENCODED
3024    * Also gst_v4l2_object_v4l2fourcc_to_video_format should be improved
3025    * because for now it never returns GST_VIDEO_FORMAT_ENCODED
3026    */
3027
3028   /* fails if we do no translate the fmt.pix.pixelformat to GstVideoFormat */
3029   if (format == GST_VIDEO_FORMAT_UNKNOWN)
3030     goto unsupported_format;
3031
3032   if (fmt.fmt.pix.width == 0 || fmt.fmt.pix.height == 0)
3033     goto invalid_dimensions;
3034
3035   width = fmt.fmt.pix.width;
3036   height = fmt.fmt.pix.height;
3037
3038   memset (&crop, 0, sizeof (struct v4l2_crop));
3039   crop.type = v4l2object->type;
3040   if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0) {
3041     align->padding_left = crop.c.left;
3042     align->padding_top = crop.c.top;
3043     align->padding_right = width - crop.c.width - crop.c.left;
3044     align->padding_bottom = height - crop.c.height - crop.c.top;
3045     width = crop.c.width;
3046     height = crop.c.height;
3047   }
3048
3049   gst_video_info_set_format (info, format, width, height);
3050
3051   switch (fmt.fmt.pix.field) {
3052     case V4L2_FIELD_ANY:
3053     case V4L2_FIELD_NONE:
3054       info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
3055       break;
3056     case V4L2_FIELD_INTERLACED:
3057     case V4L2_FIELD_INTERLACED_TB:
3058     case V4L2_FIELD_INTERLACED_BT:
3059       info->interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
3060       break;
3061     default:
3062       goto unsupported_field;
3063   }
3064
3065   gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info);
3066
3067   /* Shall we setup the pool ? */
3068
3069   return TRUE;
3070
3071 get_fmt_failed:
3072   {
3073     GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
3074         (_("Video device did not provide output format.")), GST_ERROR_SYSTEM);
3075     return FALSE;
3076   }
3077 invalid_dimensions:
3078   {
3079     GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
3080         (_("Video device returned invalid dimensions.")),
3081         ("Expected non 0 dimensions, got %dx%d", fmt.fmt.pix.width,
3082             fmt.fmt.pix.height));
3083     return FALSE;
3084   }
3085 unsupported_field:
3086   {
3087     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
3088         (_("Video devices uses an unsupported interlacing method.")),
3089         ("V4L2 field type %d not supported", fmt.fmt.pix.field));
3090     return FALSE;
3091   }
3092 unsupported_format:
3093   {
3094     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
3095         (_("Video devices uses an unsupported pixel format.")),
3096         ("V4L2 format %" GST_FOURCC_FORMAT " not supported",
3097             GST_FOURCC_ARGS (fmt.fmt.pix.pixelformat)));
3098     return FALSE;
3099   }
3100 }
3101
3102 gboolean
3103 gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
3104 {
3105   GstStructure *s;
3106   GstCaps *oldcaps;
3107
3108   if (!v4l2object->pool)
3109     return FALSE;
3110
3111   s = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (v4l2object->pool));
3112   gst_buffer_pool_config_get_params (s, &oldcaps, NULL, NULL, NULL);
3113
3114   return oldcaps && gst_caps_is_equal (caps, oldcaps);
3115 }
3116
3117 gboolean
3118 gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
3119 {
3120   GST_LOG_OBJECT (v4l2object->element, "flush poll");
3121   gst_poll_set_flushing (v4l2object->poll, TRUE);
3122
3123   return TRUE;
3124 }
3125
3126 gboolean
3127 gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object)
3128 {
3129   GST_LOG_OBJECT (v4l2object->element, "flush stop poll");
3130   gst_poll_set_flushing (v4l2object->poll, FALSE);
3131
3132   return TRUE;
3133 }
3134
3135 gboolean
3136 gst_v4l2_object_stop (GstV4l2Object * v4l2object)
3137 {
3138   GST_DEBUG_OBJECT (v4l2object->element, "stopping");
3139
3140   if (!GST_V4L2_IS_OPEN (v4l2object))
3141     goto done;
3142   if (!GST_V4L2_IS_ACTIVE (v4l2object))
3143     goto done;
3144
3145   if (v4l2object->pool) {
3146     GST_DEBUG_OBJECT (v4l2object->element, "deactivating pool");
3147     gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (v4l2object->pool), FALSE);
3148     gst_object_unref (v4l2object->pool);
3149     v4l2object->pool = NULL;
3150   }
3151
3152   GST_V4L2_SET_INACTIVE (v4l2object);
3153
3154 done:
3155   return TRUE;
3156 }
3157
3158 gboolean
3159 gst_v4l2_object_copy (GstV4l2Object * v4l2object, GstBuffer * dest,
3160     GstBuffer * src)
3161 {
3162   const GstVideoFormatInfo *finfo = v4l2object->info.finfo;
3163
3164   if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
3165           finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
3166     GstVideoFrame src_frame, dest_frame;
3167
3168     GST_DEBUG_OBJECT (v4l2object->element, "copy video frame");
3169
3170     /* we have raw video, use videoframe copy to get strides right */
3171     if (!gst_video_frame_map (&src_frame, &v4l2object->info, src, GST_MAP_READ))
3172       goto invalid_buffer;
3173
3174     if (!gst_video_frame_map (&dest_frame, &v4l2object->info, dest,
3175             GST_MAP_WRITE)) {
3176       gst_video_frame_unmap (&src_frame);
3177       goto invalid_buffer;
3178     }
3179
3180     gst_video_frame_copy (&dest_frame, &src_frame);
3181
3182     gst_video_frame_unmap (&src_frame);
3183     gst_video_frame_unmap (&dest_frame);
3184   } else {
3185     GstMapInfo map;
3186
3187     GST_DEBUG_OBJECT (v4l2object->element, "copy raw bytes");
3188     gst_buffer_map (src, &map, GST_MAP_READ);
3189     gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
3190     gst_buffer_unmap (src, &map);
3191     gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
3192   }
3193   GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2object->element,
3194       "slow copy into buffer %p", dest);
3195
3196   return TRUE;
3197
3198   /* ERRORS */
3199 invalid_buffer:
3200   {
3201     /* No Window available to put our image into */
3202     GST_WARNING_OBJECT (v4l2object->element, "could not map image");
3203     return FALSE;
3204   }
3205 }
3206
3207 GstCaps *
3208 gst_v4l2_object_get_caps (GstV4l2Object * v4l2object, GstCaps * filter)
3209 {
3210   GstCaps *ret;
3211   GSList *walk;
3212   GSList *formats;
3213
3214   if (v4l2object->probed_caps == NULL) {
3215     formats = gst_v4l2_object_get_format_list (v4l2object);
3216
3217     ret = gst_caps_new_empty ();
3218
3219     for (walk = formats; walk; walk = walk->next) {
3220       struct v4l2_fmtdesc *format;
3221       GstStructure *template;
3222
3223       format = (struct v4l2_fmtdesc *) walk->data;
3224
3225       template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat);
3226
3227       if (template) {
3228         GstCaps *tmp;
3229
3230         tmp = gst_v4l2_object_probe_caps_for_format (v4l2object,
3231             format->pixelformat, template);
3232         if (tmp)
3233           gst_caps_append (ret, tmp);
3234
3235         gst_structure_free (template);
3236       } else {
3237         GST_DEBUG_OBJECT (v4l2object->element, "unknown format %u",
3238             format->pixelformat);
3239       }
3240     }
3241     v4l2object->probed_caps = ret;
3242   }
3243
3244   if (filter) {
3245     ret = gst_caps_intersect_full (filter, v4l2object->probed_caps,
3246         GST_CAPS_INTERSECT_FIRST);
3247   } else {
3248     ret = gst_caps_ref (v4l2object->probed_caps);
3249   }
3250
3251   GST_INFO_OBJECT (v4l2object->element, "probed caps: %" GST_PTR_FORMAT, ret);
3252   LOG_CAPS (v4l2object->element, ret);
3253
3254   return ret;
3255 }
3256
3257 gboolean
3258 gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
3259 {
3260   GstBufferPool *pool;
3261   guint size, min, max;
3262   gboolean update;
3263   struct v4l2_control ctl = { 0, };
3264
3265   GST_DEBUG_OBJECT (obj->element, "decide allocation");
3266
3267   g_return_val_if_fail (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
3268       obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, FALSE);
3269
3270   if (obj->pool == NULL) {
3271     GstCaps *caps;
3272     gst_query_parse_allocation (query, &caps, NULL);
3273
3274     if (!gst_v4l2_object_setup_pool (obj, caps))
3275       goto pool_failed;
3276   }
3277
3278   if (gst_query_get_n_allocation_pools (query) > 0) {
3279     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
3280     update = TRUE;
3281   } else {
3282     pool = NULL;
3283     min = max = 0;
3284     size = 0;
3285     update = FALSE;
3286   }
3287
3288   GST_DEBUG_OBJECT (obj->element, "allocation: size:%u min:%u max:%u pool:%"
3289       GST_PTR_FORMAT, size, min, max, pool);
3290
3291   if (min != 0) {
3292     /* if there is a min-buffers suggestion, use it. We add 1 because we need 1
3293      * buffer extra to capture while the other two buffers are downstream */
3294     min += 1;
3295   } else {
3296     min = 2;
3297   }
3298
3299   /* Certain driver may expose a minimum through controls */
3300   ctl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
3301   if (v4l2_ioctl (obj->video_fd, VIDIOC_G_CTRL, &ctl) >= 0) {
3302     GST_DEBUG_OBJECT (obj->element, "driver require a minimum of %d buffers",
3303         ctl.value);
3304     obj->min_buffers_for_capture = ctl.value;
3305     min += ctl.value;
3306   }
3307
3308   /* Request a bigger max, if one was suggested but it's too small */
3309   if (max != 0 && max < min)
3310     max = min;
3311
3312   /* select a pool */
3313   switch (obj->mode) {
3314     case GST_V4L2_IO_RW:
3315       if (pool == NULL) {
3316         /* no downstream pool, use our own then */
3317         GST_DEBUG_OBJECT (obj->element,
3318             "read/write mode: no downstream pool, using our own");
3319         pool = GST_BUFFER_POOL_CAST (obj->pool);
3320         size = obj->sizeimage;
3321       } else {
3322         /* in READ/WRITE mode, prefer a downstream pool because our own pool
3323          * doesn't help much, we have to write to it as well */
3324         GST_DEBUG_OBJECT (obj->element,
3325             "read/write mode: using downstream pool");
3326         /* use the bigest size, when we use our own pool we can't really do any
3327          * other size than what the hardware gives us but for downstream pools
3328          * we can try */
3329         size = MAX (size, obj->sizeimage);
3330       }
3331       break;
3332     case GST_V4L2_IO_MMAP:
3333     case GST_V4L2_IO_USERPTR:
3334     case GST_V4L2_IO_DMABUF:
3335       /* in streaming mode, prefer our own pool */
3336       if (pool)
3337         gst_object_unref (pool);
3338       pool = GST_BUFFER_POOL_CAST (obj->pool);
3339       size = obj->sizeimage;
3340       max = 0;
3341       GST_DEBUG_OBJECT (obj->element,
3342           "streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
3343       break;
3344     case GST_V4L2_IO_AUTO:
3345     default:
3346       GST_WARNING_OBJECT (obj->element, "unhandled mode");
3347       break;
3348   }
3349
3350   if (pool) {
3351     GstStructure *config;
3352     GstCaps *caps;
3353
3354     config = gst_buffer_pool_get_config (pool);
3355     gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
3356     gst_buffer_pool_config_set_params (config, caps, size, min, max);
3357
3358     /* if downstream supports video metadata, add this to the pool config */
3359     if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
3360       GST_DEBUG_OBJECT (pool, "activate Video Meta");
3361       gst_buffer_pool_config_add_option (config,
3362           GST_BUFFER_POOL_OPTION_VIDEO_META);
3363     }
3364
3365     gst_buffer_pool_set_config (pool, config);
3366   }
3367
3368   if (update)
3369     gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
3370   else
3371     gst_query_add_allocation_pool (query, pool, size, min, max);
3372
3373   return TRUE;
3374
3375 pool_failed:
3376   {
3377     GST_ELEMENT_ERROR (obj->element, RESOURCE, SETTINGS,
3378         (_("Video device could not create buffer pool.")), GST_ERROR_SYSTEM);
3379     return FALSE;
3380   }
3381 }