]> git.sesse.net Git - kdenlive/blob - src/v4l/src_v4l2.c
7d1e03f434573e4bcb3ff9ac30d785895a039aac
[kdenlive] / src / v4l / src_v4l2.c
1 /* fswebcam - FireStorm.cx's webcam generator                 */
2 /*============================================================*/
3 /* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
4 /*                                                            */
5 /* This program is distributed under the terms of the GNU     */
6 /* General Public License, version 2. You may use, modify,    */
7 /* and redistribute it under the terms of this license. A     */
8 /* copy should be included with this source.                  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 #include "videodev2.h"
23 #include "src.h"
24
25 #ifdef HAVE_V4L2
26
27 typedef struct {
28         void *start;
29         size_t length;
30 } v4l2_buffer_t;
31
32 typedef struct {
33         
34         int fd;
35         char map;
36         
37         struct v4l2_capability cap;
38         struct v4l2_format fmt;
39         struct v4l2_requestbuffers req;
40         struct v4l2_buffer buf;
41         
42         v4l2_buffer_t *buffer;
43         
44         int pframe;
45         
46 } src_v4l2_t;
47
48 static int src_v4l2_close(src_t *src);
49
50 typedef struct {
51         uint16_t src;
52         uint32_t v4l2;
53 } v4l2_palette_t;
54
55 v4l2_palette_t v4l2_palette[] = {
56         { SRC_PAL_JPEG,    V4L2_PIX_FMT_JPEG   },
57         { SRC_PAL_MJPEG,   V4L2_PIX_FMT_MJPEG  },
58         { SRC_PAL_S561,    V4L2_PIX_FMT_SPCA561 },
59         { SRC_PAL_RGB24,   V4L2_PIX_FMT_RGB24  },
60         { SRC_PAL_BGR24,   V4L2_PIX_FMT_BGR24  },
61         { SRC_PAL_RGB32,   V4L2_PIX_FMT_RGB32  },
62         { SRC_PAL_BGR32,   V4L2_PIX_FMT_BGR32  },
63         { SRC_PAL_YUYV,    V4L2_PIX_FMT_YUYV   },
64         { SRC_PAL_UYVY,    V4L2_PIX_FMT_UYVY   },
65         { SRC_PAL_YUV420P, V4L2_PIX_FMT_YUV420 },
66         { SRC_PAL_BAYER,   V4L2_PIX_FMT_SBGGR8 },
67         { SRC_PAL_SGBRG8,  V4L2_PIX_FMT_SGBRG8 },
68         { SRC_PAL_SGRBG8,  V4L2_PIX_FMT_SGRBG8 },
69         { SRC_PAL_RGB565,  V4L2_PIX_FMT_RGB565 },
70         { SRC_PAL_RGB555,  V4L2_PIX_FMT_RGB555 },
71         { SRC_PAL_Y16,     V4L2_PIX_FMT_Y16    },
72         { SRC_PAL_GREY,    V4L2_PIX_FMT_GREY   },
73         { 0, 0 }
74 };
75
76 int src_v4l2_get_capability(src_t *src)
77 {
78         src_v4l2_t *s = (src_v4l2_t *) src->state;
79         
80         if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0)
81         {
82                 /*ERROR("%s: Not a V4L2 device?", src->source);*/
83                 return(-1);
84         }
85         fprintf(stderr, "cap.card: \"%s\"", s->cap.card);
86         /*DEBUG("%s information:", src->source);
87         DEBUG("cap.driver: \"%s\"", s->cap.driver);
88         DEBUG("cap.card: \"%s\"", s->cap.card);
89         DEBUG("cap.bus_info: \"%s\"", s->cap.bus_info);
90         DEBUG("cap.capabilities=0x%08X", s->cap.capabilities);*/
91         /*if(s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) DEBUG("- VIDEO_CAPTURE");
92         if(s->cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)  DEBUG("- VIDEO_OUTPUT");
93         if(s->cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) DEBUG("- VIDEO_OVERLAY");
94         if(s->cap.capabilities & V4L2_CAP_VBI_CAPTURE)   DEBUG("- VBI_CAPTURE");
95         if(s->cap.capabilities & V4L2_CAP_VBI_OUTPUT)    DEBUG("- VBI_OUTPUT");
96         if(s->cap.capabilities & V4L2_CAP_RDS_CAPTURE)   DEBUG("- RDS_CAPTURE");
97         if(s->cap.capabilities & V4L2_CAP_TUNER)         DEBUG("- TUNER");
98         if(s->cap.capabilities & V4L2_CAP_AUDIO)         DEBUG("- AUDIO");
99         if(s->cap.capabilities & V4L2_CAP_RADIO)         DEBUG("- RADIO");
100         if(s->cap.capabilities & V4L2_CAP_READWRITE)     DEBUG("- READWRITE");
101         if(s->cap.capabilities & V4L2_CAP_ASYNCIO)       DEBUG("- ASYNCIO");
102         if(s->cap.capabilities & V4L2_CAP_STREAMING)     DEBUG("- STREAMING");
103         if(s->cap.capabilities & V4L2_CAP_TIMEPERFRAME)  DEBUG("- TIMEPERFRAME");*/
104         
105         if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
106         {
107                 /*ERROR("Device does not support capturing.");*/
108                 return(-1);
109         }
110         
111         return(0);
112 }
113
114 int src_v4l2_set_input(src_t *src)
115 {
116         src_v4l2_t *s = (src_v4l2_t *) src->state;
117         struct v4l2_input input;
118         int count = 0, i = -1;
119         
120         memset(&input, 0, sizeof(input));
121         
122         if(src->list & SRC_LIST_INPUTS)
123         {
124                 /*HEAD("--- Available inputs:");*/
125                 
126                 input.index = count;
127                 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
128                 {
129                         /*MSG("%i: %s", count, input.name);*/
130                         input.index = ++count;
131                 }
132         }
133         
134         /* If no input was specified, use input 0. */
135         if(!src->input)
136         {
137                 /*MSG("No input was specified, using the first.");*/
138                 count = 1;
139                 i = 0;
140         }
141         
142         /* Check if the input is specified by name. */
143         if(i == -1)
144         {
145                 input.index = count;
146                 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
147                 {
148                         if(!strncasecmp((char *) input.name, src->input, 32))
149                                 i = count;
150                         input.index = ++count;
151                 }
152         }
153         
154         if(i == -1)
155         {
156                 char *endptr;
157                 
158                 /* Is the input specified by number? */
159                 i = strtol(src->input, &endptr, 10);
160                 
161                 if(endptr == src->input) i = -1;
162         }
163         
164         if(i == -1 || i >= count)
165         {
166                 /* The specified input wasn't found! */
167                 /*ERROR("Unrecognised input \"%s\"", src->input);*/
168                 return(-1);
169         }
170         
171         /* Set the input. */
172         input.index = i;
173         if(ioctl(s->fd, VIDIOC_ENUMINPUT, &input) == -1)
174         {
175                 /*ERROR("Unable to query input %i.", i);
176                 ERROR("VIDIOC_ENUMINPUT: %s", strerror(errno));*/
177                 return(-1);
178         }
179         
180         /*DEBUG("%s: Input %i information:", src->source, i);
181         DEBUG("name = \"%s\"", input.name);
182         DEBUG("type = %08X", input.type);
183         if(input.type & V4L2_INPUT_TYPE_TUNER) DEBUG("- TUNER");
184         if(input.type & V4L2_INPUT_TYPE_CAMERA) DEBUG("- CAMERA");
185         DEBUG("audioset = %08X", input.audioset);
186         DEBUG("tuner = %08X", input.tuner);
187         DEBUG("status = %08X", input.status);
188         if(input.status & V4L2_IN_ST_NO_POWER) DEBUG("- NO_POWER");
189         if(input.status & V4L2_IN_ST_NO_SIGNAL) DEBUG("- NO_SIGNAL");
190         if(input.status & V4L2_IN_ST_NO_COLOR) DEBUG("- NO_COLOR");
191         if(input.status & V4L2_IN_ST_NO_H_LOCK) DEBUG("- NO_H_LOCK");
192         if(input.status & V4L2_IN_ST_COLOR_KILL) DEBUG("- COLOR_KILL");
193         if(input.status & V4L2_IN_ST_NO_SYNC) DEBUG("- NO_SYNC");
194         if(input.status & V4L2_IN_ST_NO_EQU) DEBUG("- NO_EQU");
195         if(input.status & V4L2_IN_ST_NO_CARRIER) DEBUG("- NO_CARRIER");
196         if(input.status & V4L2_IN_ST_MACROVISION) DEBUG("- MACROVISION");
197         if(input.status & V4L2_IN_ST_NO_ACCESS) DEBUG("- NO_ACCESS");
198         if(input.status & V4L2_IN_ST_VTR) DEBUG("- VTR");*/
199         
200         if(ioctl(s->fd, VIDIOC_S_INPUT, &i) == -1)
201         {
202                 /*ERROR("Error selecting input %i", i);
203                 ERROR("VIDIOC_S_INPUT: %s", strerror(errno));*/
204                 return(-1);
205         }
206         
207         /* If this input is attached to a tuner, set the frequency. */
208         if(input.type & V4L2_INPUT_TYPE_TUNER)
209         {
210                 char *range;
211                 struct v4l2_tuner tuner;
212                 struct v4l2_frequency freq;
213                 
214                 /* Query the tuners capabilities. */
215                 
216                 memset(&tuner, 0, sizeof(tuner));
217                 tuner.index = input.tuner;
218                 
219                 if(ioctl(s->fd, VIDIOC_G_TUNER, &tuner) == -1)
220                 {
221                         /*WARN("Error querying tuner %i.", input.tuner);
222                         WARN("VIDIOC_G_TUNER: %s", strerror(errno));*/
223                         return(0);
224                 }
225                 
226                 if(tuner.capability & V4L2_TUNER_CAP_LOW) range = "kHz";
227                 else range = "MHz";
228                 
229                 /*DEBUG("%s: Tuner %i information:", src->source, input.tuner);
230                 DEBUG("name = \"%s\"", tuner.name);
231                 DEBUG("type = %08X", tuner.type);
232                 if(tuner.type == V4L2_TUNER_RADIO) DEBUG("- RADIO");
233                 if(tuner.type == V4L2_TUNER_ANALOG_TV) DEBUG("- ANALOG_TV");
234                 DEBUG("capability = %08X", tuner.capability);
235                 if(tuner.capability & V4L2_TUNER_CAP_LOW) DEBUG("- LOW");
236                 if(tuner.capability & V4L2_TUNER_CAP_NORM) DEBUG("- NORM");
237                 if(tuner.capability & V4L2_TUNER_CAP_STEREO) DEBUG("- STEREO");
238                 if(tuner.capability & V4L2_TUNER_CAP_LANG1) DEBUG("- LANG1");
239                 if(tuner.capability & V4L2_TUNER_CAP_LANG2) DEBUG("- LANG2");
240                 if(tuner.capability & V4L2_TUNER_CAP_SAP) DEBUG("- SAP");
241                 DEBUG("rangelow = %08X, (%.3f%s)", tuner.rangelow, (double) tuner.rangelow * 16 / 1000, range);
242                 DEBUG("rangehigh = %08X, (%.3f%s)", tuner.rangehigh, (double) tuner.rangehigh * 16 / 1000, range);
243                 DEBUG("signal = %08X", tuner.signal);
244                 DEBUG("afc = %08X", tuner.afc);*/
245                 
246                 /* Set the frequency. */
247                 memset(&freq, 0, sizeof(freq));
248                 freq.tuner = input.tuner;
249                 freq.type = V4L2_TUNER_ANALOG_TV;
250                 freq.frequency = (src->frequency / 1000) * 16;
251                 
252                 if(ioctl(s->fd, VIDIOC_S_FREQUENCY, &freq) == -1)
253                 {
254                         /*WARN("Error setting frequency %.3f%s", src->frequency / 16.0, range);
255                         WARN("VIDIOC_S_FREQUENCY: %s", strerror(errno));*/
256                         return(0);
257                 }
258                 
259                 /*MSG("Set frequency to %.3f%s",
260                     (double) src->frequency / 1000, range);*/
261         }
262         
263         return(0);
264 }
265
266 int src_v4l2_show_control(src_t *src, struct v4l2_queryctrl *queryctrl)
267 {
268         src_v4l2_t *s = (src_v4l2_t *) src->state;
269         struct v4l2_querymenu querymenu;
270         struct v4l2_control control;
271         char *t;
272         int m;
273         
274         if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
275         
276         memset(&querymenu, 0, sizeof(querymenu));
277         memset(&control, 0, sizeof(control));
278         
279         if(queryctrl->type != V4L2_CTRL_TYPE_BUTTON)
280         {
281                 control.id = queryctrl->id;
282                 if(ioctl(s->fd, VIDIOC_G_CTRL, &control))
283                 {
284                         /*ERROR("Error reading value of control '%s'.", queryctrl->name);
285                         ERROR("VIDIOC_G_CTRL: %s", strerror(errno));*/
286                 }
287         }
288         
289         switch(queryctrl->type)
290         {
291         case V4L2_CTRL_TYPE_INTEGER:
292                 
293                 t = malloc(64); /* Ick ... TODO: re-write this. */
294                 if(!t)
295                 {
296                         /*ERROR("Out of memory.");*/
297                         return(-1);
298                 }
299                 
300                 if(queryctrl->maximum - queryctrl->minimum <= 10)
301                 {
302                         snprintf(t, 63, "%i", control.value);
303                 }
304                 else
305                 {
306                         snprintf(t, 63, "%i (%i%%)",
307                                  control.value,
308                                  SCALE(0, 100,
309                                        queryctrl->minimum,
310                                        queryctrl->maximum,
311                                        control.value));
312                 }
313                 
314                 /*MSG("%-25s %-15s %i - %i", queryctrl->name, t,
315                     queryctrl->minimum, queryctrl->maximum);*/
316                 
317                 free(t);
318                 
319                 break;
320                 
321         case V4L2_CTRL_TYPE_BOOLEAN:
322                 /*MSG("%-25s %-15s True | False", queryctrl->name,
323                     (control.value ? "True" : "False"));*/
324                 break;
325                 
326         case V4L2_CTRL_TYPE_MENU:
327                 
328                 querymenu.id = queryctrl->id;
329                 
330                 t = calloc((queryctrl->maximum - queryctrl->minimum) + 1, 34);
331                 m = queryctrl->minimum;
332                 for(m = queryctrl->minimum; m <= queryctrl->maximum; m++)
333                 {
334                         querymenu.index = m;
335                         if(!ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
336                         {
337                                 strncat(t, (char *) querymenu.name, 32);
338                                 if(m < queryctrl->maximum) strncat(t, " | ", 3);
339                         }
340                 }
341                 
342                 querymenu.index = control.value;
343                 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
344                 {
345                         free(t);
346                         /*ERROR("Error reading value of menu item %i for control '%s'",
347                               control.value, queryctrl->name);
348                         ERROR("VIDIOC_QUERYMENU: %s", strerror(errno));*/
349                         return(0);
350                 }
351                 
352                 /*MSG("%-25s %-15s %s", queryctrl->name, querymenu.name, t);*/
353                 free(t);
354                 
355                 break;
356         
357         case V4L2_CTRL_TYPE_BUTTON:
358                 /*MSG("%-25s %-15s %s", queryctrl->name, "-", "[Button]");*/
359                 break;
360                 
361         default:
362                 /*MSG("%-25s %-15s %s", queryctrl->name, "N/A", "[Unknown Control Type]");*/
363                 break;
364         }
365         
366         return(0);
367 }
368
369 int src_v4l2_set_control(src_t *src, struct v4l2_queryctrl *queryctrl)
370 {
371         src_v4l2_t *s = (src_v4l2_t *) src->state;
372         struct v4l2_control control;
373         struct v4l2_querymenu querymenu;
374         char *sv;
375         int iv;
376         
377         if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
378         if(src_get_option_by_name(src->option, (char *) queryctrl->name, &sv))
379                 return(0);
380         
381         memset(&querymenu, 0, sizeof(querymenu));
382         memset(&control, 0, sizeof(control));
383         
384         control.id = queryctrl->id;
385         
386         switch(queryctrl->type)
387         {
388         case V4L2_CTRL_TYPE_INTEGER:
389                 
390                 /* Convert the value to an integer. */
391                 iv = atoi(sv);
392                 
393                 /* Is the value a precentage? */
394                 if(strchr(sv, '%'))
395                 {
396                         /* Adjust the precentage to fit the controls range. */
397                         iv = SCALE(queryctrl->minimum, queryctrl->maximum,
398                                    0, 100, iv);
399                 }
400                 
401                 /*MSG("Setting %s to %i (%i%%).", queryctrl->name, iv,
402                     SCALE(0, 100, queryctrl->minimum, queryctrl->maximum, iv));*/
403                 
404                 /*if(iv < queryctrl->minimum || iv > queryctrl->maximum)
405                         WARN("Value is out of range. Setting anyway.");*/
406                 
407                 control.value = iv;
408                 ioctl(s->fd, VIDIOC_S_CTRL, &control);
409                 break;
410         
411         case V4L2_CTRL_TYPE_BOOLEAN:
412                 
413                 iv = -1;
414                 if(!strcasecmp(sv, "1") || !strcasecmp(sv, "true")) iv = 1;
415                 if(!strcasecmp(sv, "0") || !strcasecmp(sv, "false")) iv = 0;
416                 
417                 if(iv == -1)
418                 {
419                         /*WARN("Unknown boolean value '%s' for %s.",
420                              sv, queryctrl->name);*/
421                         return(-1);
422                 }
423                 
424                 /*MSG("Setting %s to %s (%i).", queryctrl->name, sv, iv);*/
425                 
426                 control.value = iv;
427                 ioctl(s->fd, VIDIOC_S_CTRL, &control);
428                 
429                 break;
430         
431         case V4L2_CTRL_TYPE_MENU:
432                 
433                 /* Scan for a matching value. */
434                 querymenu.id = queryctrl->id;
435                 
436                 for(iv = queryctrl->minimum; iv <= queryctrl->maximum; iv++)
437                 {
438                         querymenu.index = iv;
439                         
440                         if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
441                         {
442                                 /*ERROR("Error querying menu.");*/
443                                 continue;
444                         }
445                         
446                         if(!strncasecmp((char *) querymenu.name, sv, 32))
447                                 break;
448                 }
449                 
450                 if(iv > queryctrl->maximum)
451                 {
452                         /*MSG("Unknown value '%s' for %s.", sv, queryctrl->name);*/
453                         return(-1);
454                 }
455                 
456                 /*MSG("Setting %s to %s (%i).",
457                     queryctrl->name, querymenu.name, iv);*/
458                 
459                 control.value = iv;
460                 ioctl(s->fd, VIDIOC_S_CTRL, &control);
461                 
462                 break;
463         
464         case V4L2_CTRL_TYPE_BUTTON:
465                 
466                 /*MSG("Triggering %s control.", queryctrl->name);
467                 ioctl(s->fd, VIDIOC_S_CTRL, &control);*/
468                 
469                 break;
470         
471         default:
472                 /*WARN("Not setting unknown control type %i (%s).",
473                      queryctrl->name);*/
474                 break;
475         }
476         
477         return(0);
478 }
479
480 int src_v4l2_set_controls(src_t *src)
481 {
482         src_v4l2_t *s = (src_v4l2_t *) src->state;
483         struct v4l2_queryctrl queryctrl;
484         int c;
485         
486         memset(&queryctrl, 0, sizeof(queryctrl));
487         
488         if(src->list & SRC_LIST_CONTROLS)
489         {
490                 /*HEAD("%-25s %-15s %s", "Available Controls", "Current Value", "Range");
491                 MSG("%-25s %-15s %s",  "------------------", "-------------", "-----");*/
492                 
493                 /* Display normal controls. */
494                 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
495                 {
496                         queryctrl.id = c;
497                         
498                         if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
499                         src_v4l2_show_control(src, &queryctrl);
500                 }
501                 
502                 /* Display device-specific controls. */
503                 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
504                 {
505                         queryctrl.id = c;
506                         
507                         if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
508                         src_v4l2_show_control(src, &queryctrl);
509                 }
510         }
511         
512         /* Scan normal controls. */
513         for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
514         {
515                 queryctrl.id = c;
516                 
517                 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
518                 src_v4l2_set_control(src, &queryctrl);
519         }
520         
521         /* Scan device-specific controls. */
522         for(c = V4L2_CID_PRIVATE_BASE; ; c++)
523         {
524                 queryctrl.id = c;
525                 
526                 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
527                 src_v4l2_set_control(src, &queryctrl);
528         }
529         
530         return(0);
531 }
532
533 int src_v4l2_set_pix_format(src_t *src)
534 {
535         src_v4l2_t *s = (src_v4l2_t *) src->state;
536         struct v4l2_fmtdesc fmt;
537         int v4l2_pal;
538         
539         /* Dump a list of formats the device supports. */
540         /*DEBUG("Device offers the following V4L2 pixel formats:");*/
541         
542         v4l2_pal = 0;
543         memset(&fmt, 0, sizeof(fmt));
544         fmt.index = v4l2_pal;
545         fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
546         
547         while(ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
548         {
549                 /*DEBUG("%i: [0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
550                       fmt.pixelformat,
551                       fmt.pixelformat >> 0,  fmt.pixelformat >> 8,
552                       fmt.pixelformat >> 16, fmt.pixelformat >> 24,
553                       fmt.description);*/
554                 
555                 memset(&fmt, 0, sizeof(fmt));
556                 fmt.index = ++v4l2_pal;
557                 fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
558         }
559         
560         /* Step through each palette type. */
561         v4l2_pal = 0;
562         
563         if(src->palette != -1)
564         {
565                 while(v4l2_palette[v4l2_pal].v4l2)
566                 {
567                         if(v4l2_palette[v4l2_pal].src == src->palette) break;
568                         v4l2_pal++;
569                 }
570                 
571                 if(!v4l2_palette[v4l2_pal].v4l2)
572                 {
573                         /*ERROR("Unable to handle palette format %s.",
574                               src_palette[src->palette]);*/
575                         
576                         return(-1);
577                 }
578         }
579         
580         while(v4l2_palette[v4l2_pal].v4l2)
581         {
582                 /* Try the palette... */
583                 memset(&s->fmt, 0, sizeof(s->fmt));
584                 s->fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
585                 s->fmt.fmt.pix.width       = src->width;
586                 s->fmt.fmt.pix.height      = src->height;
587                 s->fmt.fmt.pix.pixelformat = v4l2_palette[v4l2_pal].v4l2;
588                 s->fmt.fmt.pix.field       = V4L2_FIELD_ANY;
589                 
590                 if(ioctl(s->fd, VIDIOC_TRY_FMT, &s->fmt) != -1 &&
591                    s->fmt.fmt.pix.pixelformat == v4l2_palette[v4l2_pal].v4l2)
592                 {
593                         src->palette = v4l2_palette[v4l2_pal].src;
594                         
595                         /*INFO("Using palette %s", src_palette[src->palette].name);*/
596                         
597                         if(s->fmt.fmt.pix.width != src->width ||
598                            s->fmt.fmt.pix.height != src->height)
599                         {
600                                 /*MSG("Adjusting resolution from %ix%i to %ix%i.",
601                                     src->width, src->height,
602                                     s->fmt.fmt.pix.width,
603                                     s->fmt.fmt.pix.height);*/
604                                 src->width = s->fmt.fmt.pix.width;
605                                 src->height = s->fmt.fmt.pix.height;
606                         }
607                         
608                         if(ioctl(s->fd, VIDIOC_S_FMT, &s->fmt) == -1)
609                         {
610                                 /*ERROR("Error setting pixel format.");
611                                 ERROR("VIDIOC_S_FMT: %s", strerror(errno));*/
612                                 return(-1);
613                         }
614                         
615                         if(v4l2_palette[v4l2_pal].v4l2 == V4L2_PIX_FMT_MJPEG)
616                         {
617                                 struct v4l2_jpegcompression jpegcomp;
618                                 
619                                 memset(&jpegcomp, 0, sizeof(jpegcomp));
620                                 ioctl(s->fd, VIDIOC_G_JPEGCOMP, &jpegcomp);
621                                 jpegcomp.jpeg_markers |= V4L2_JPEG_MARKER_DHT;
622                                 ioctl(s->fd, VIDIOC_S_JPEGCOMP, &jpegcomp);
623                         }
624                         
625                         return(0);
626                 }
627                 
628                 if(src->palette != -1) break;
629                 
630                 v4l2_pal++;
631         }
632         
633         /*ERROR("Unable to find a compatible palette format.");*/
634         
635         return(-1);
636 }
637
638 int src_v4l2_set_fps(src_t *src)
639 {
640         src_v4l2_t *s = (src_v4l2_t *) src->state;
641         struct v4l2_streamparm setfps;
642         
643         memset(&setfps, 0, sizeof(setfps));
644         
645         setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
646         setfps.parm.capture.timeperframe.numerator = 1;
647         setfps.parm.capture.timeperframe.denominator = src->fps;
648         if(ioctl(s->fd, VIDIOC_S_PARM, setfps) == -1)
649         {
650                 /* Not fatal - just warn about it */
651                 /*WARN("Error setting frame rate:");
652                 WARN("VIDIOC_S_PARM: %s", strerror(errno));*/
653                 return(-1);
654         }
655         
656         return(0);
657 }
658
659 int src_v4l2_free_mmap(src_t *src)
660 {
661         src_v4l2_t *s = (src_v4l2_t *) src->state;
662         int i;
663         
664         for(i = 0; i < s->req.count; i++)
665                 munmap(s->buffer[i].start, s->buffer[i].length);
666         
667         return(0);
668 }
669
670 int src_v4l2_set_mmap(src_t *src)
671 {
672         src_v4l2_t *s = (src_v4l2_t *) src->state;
673         enum v4l2_buf_type type;
674         uint32_t b;
675         
676         /* Does the device support streaming? */
677         if(~s->cap.capabilities & V4L2_CAP_STREAMING) return(-1);
678         
679         memset(&s->req, 0, sizeof(s->req));
680         
681         s->req.count  = 4;
682         s->req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
683         s->req.memory = V4L2_MEMORY_MMAP;
684         
685         if(ioctl(s->fd, VIDIOC_REQBUFS, &s->req) == -1)
686         {
687                 /*ERROR("Error requesting buffers for memory map.");
688                 ERROR("VIDIOC_REQBUFS: %s", strerror(errno));*/
689                 return(-1);
690         }
691         
692         /*DEBUG("mmap information:");
693         DEBUG("frames=%d", s->req.count);*/
694         
695         if(s->req.count < 2)
696         {
697                 /*ERROR("Insufficient buffer memory.");*/
698                 return(-1);
699         }
700         
701         s->buffer = calloc(s->req.count, sizeof(v4l2_buffer_t));
702         if(!s->buffer)
703         {
704                 /*ERROR("Out of memory.");*/
705                 return(-1);
706         }
707         
708         for(b = 0; b < s->req.count; b++)
709         {
710                 struct v4l2_buffer buf;
711                 
712                 memset(&buf, 0, sizeof(buf));
713                 
714                 buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
715                 buf.memory = V4L2_MEMORY_MMAP;
716                 buf.index  = b;
717                 
718                 if(ioctl(s->fd, VIDIOC_QUERYBUF, &buf) == -1)
719                 {
720                         /*ERROR("Error querying buffer %i", b);
721                         ERROR("VIDIOC_QUERYBUF: %s", strerror(errno));*/
722                         free(s->buffer);
723                         return(-1);
724                 }
725                 
726                 s->buffer[b].length = buf.length;
727                 s->buffer[b].start = mmap(NULL, buf.length,
728                    PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
729                 
730                 if(s->buffer[b].start == MAP_FAILED)
731                 {
732                         /*ERROR("Error mapping buffer %i", b);
733                         ERROR("mmap: %s", strerror(errno));*/
734                         s->req.count = b;
735                         src_v4l2_free_mmap(src);
736                         free(s->buffer);
737                         return(-1);
738                 }
739                 
740                 /*DEBUG("%i length=%d", b, buf.length);*/
741         }
742         
743         s->map = -1;
744         
745         for(b = 0; b < s->req.count; b++)
746         {
747                 memset(&s->buf, 0, sizeof(s->buf));
748                 
749                 s->buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
750                 s->buf.memory = V4L2_MEMORY_MMAP;
751                 s->buf.index  = b;
752                 
753                 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
754                 {
755                         /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
756                         src_v4l2_free_mmap(src);
757                         free(s->buffer);
758                         return(-1);
759                 }
760         }
761         
762         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
763         
764         if(ioctl(s->fd, VIDIOC_STREAMON, &type) == -1)
765         {
766                 /*ERROR("Error starting stream.");
767                 ERROR("VIDIOC_STREAMON: %s", strerror(errno));*/
768                 src_v4l2_free_mmap(src);
769                 free(s->buffer);
770                 return(-1);
771         }
772         
773         return(0);
774 }
775
776 int src_v4l2_set_read(src_t *src)
777 {
778         src_v4l2_t *s = (src_v4l2_t *) src->state;
779         
780         if(~s->cap.capabilities & V4L2_CAP_READWRITE) return(-1);
781         
782         s->buffer = calloc(1, sizeof(v4l2_buffer_t));
783         if(!s->buffer)
784         {
785                 /*ERROR("Out of memory.");*/
786                 return(-1);
787         }
788         
789         s->buffer[0].length = s->fmt.fmt.pix.sizeimage;
790         s->buffer[0].start  = malloc(s->buffer[0].length);
791         
792         if(!s->buffer[0].start)
793         {
794                 /*ERROR("Out of memory.");*/
795                 
796                 free(s->buffer);
797                 s->buffer = NULL;
798                 
799                 return(-1);
800         }
801         
802         return(0);
803 }
804
805 static const char *src_v4l2_query(src_t *src, uint *width, uint *height, char **pixelformatdescription)
806 {
807         if(!src->source)
808         {
809                 /*ERROR("No device name specified.");*/
810                 fprintf(stderr, "No device name specified.");
811                 return NULL;
812         }
813         src_v4l2_t *s;  
814
815         /* Allocate memory for the state structure. */
816         s = calloc(sizeof(src_v4l2_t), 1);
817         if(!s)
818         {
819                 fprintf(stderr, "Out of memory.");
820                 return NULL;
821         }
822         
823         src->state = (void *) s;
824
825         /* Open the device. */
826         s->fd = open(src->source, O_RDWR | O_NONBLOCK);
827         if(s->fd < 0)
828         {
829                 fprintf(stderr, "Cannot open device.");
830                 free(s);
831                 return NULL;
832         }
833
834         if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
835             src_v4l2_close(src);
836             fprintf(stderr, "Cannot get capabilities.");
837             return NULL;
838         }
839         char *res = strdup((char*) s->cap.card);
840         /*strcpy(res, (char*) s->cap.card);*/
841         if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
842             *width = 0;
843             *height = 0;
844         }
845         else {
846             struct v4l2_format format;
847             memset(&format,0,sizeof(format));
848             format.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
849             if (ioctl(s->fd,VIDIOC_G_FMT,&format) < 0) {
850                 fprintf(stderr, "Cannot get format.");
851             }
852             else {
853                 *width = format.fmt.pix.width;
854                 *height = format.fmt.pix.height;
855             }
856             struct v4l2_fmtdesc fmt;
857             memset(&fmt,0,sizeof(fmt));
858             fmt.index = 0;
859             fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
860             if (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
861             {
862                 /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
863                 *pixelformatdescription = strdup((char*)fmt.description);
864                 fprintf(stderr, "format: %s", fmt.description);
865             }
866             else {
867                 *pixelformatdescription = '\0';
868             }
869         }
870         src_v4l2_close(src);
871         return res;
872 }
873
874 static int src_v4l2_open(src_t *src)
875 {
876         src_v4l2_t *s;
877         
878         if(!src->source)
879         {
880                 /*ERROR("No device name specified.");*/
881                 return(-2);
882         }
883         
884         /* Allocate memory for the state structure. */
885         s = calloc(sizeof(src_v4l2_t), 1);
886         if(!s)
887         {
888                 /*ERROR("Out of memory.");*/
889                 return(-2);
890         }
891         
892         src->state = (void *) s;
893         
894         /* Open the device. */
895         s->fd = open(src->source, O_RDWR | O_NONBLOCK);
896         if(s->fd < 0)
897         {
898                 /*ERROR("Error opening device: %s", src->source);
899                 ERROR("open: %s", strerror(errno));*/
900                 free(s);
901                 return(-2);
902         }
903         
904         /*MSG("%s opened.", src->source);*/
905         
906         /* Get the device capabilities. */
907         if(src_v4l2_get_capability(src))
908         {
909                 src_v4l2_close(src);
910                 return(-2);
911         }
912         
913         /* Set the input. */
914         if(src_v4l2_set_input(src))
915         {
916                 src_v4l2_close(src);
917                 return(-1);
918         }
919         
920         /* Set picture options. */
921         src_v4l2_set_controls(src);
922         
923         /* Set the pixel format. */
924         if(src_v4l2_set_pix_format(src))
925         {
926                 src_v4l2_close(src);
927                 return(-1);
928         }
929         
930         /* Set the frame-rate if > 0 */
931         if(src->fps) src_v4l2_set_fps(src);
932         
933         /* Delay to let the image settle down. */
934         if(src->delay)
935         {
936                 /*MSG("Delaying %i seconds.", src->delay);*/
937                 usleep(src->delay * 1000 * 1000);
938         }
939         
940         /* Try to setup mmap. */
941         if(!src->use_read && src_v4l2_set_mmap(src))
942         {
943                 /*WARN("Unable to use mmap. Using read instead.");*/
944                 src->use_read = -1;
945         }
946         
947         /* If unable to use mmap or user requested read(). */
948         if(src->use_read)
949         {
950                 if(src_v4l2_set_read(src))
951                 {
952                         /*ERROR("Unable to use read.");*/
953                         src_v4l2_close(src);
954                         return(-1);
955                 }
956         }
957         
958         s->pframe = -1;
959         
960         return(0);
961 }
962
963 static int src_v4l2_close(src_t *src)
964 {
965         src_v4l2_t *s = (src_v4l2_t *) src->state;
966         
967         if(s->buffer)
968         {
969                 if(!s->map) free(s->buffer[0].start);
970                 else src_v4l2_free_mmap(src);
971                 free(s->buffer);
972         }
973         if(s->fd >= 0) close(s->fd);
974         free(s);
975         
976         return(0);
977 }
978
979 static int src_v4l2_grab(src_t *src)
980 {
981         src_v4l2_t *s = (src_v4l2_t *) src->state;
982         
983         if(src->timeout)
984         {
985                 fd_set fds;
986                 struct timeval tv;
987                 int r;
988                 
989                 /* Is a frame ready? */
990                 FD_ZERO(&fds);
991                 FD_SET(s->fd, &fds);
992                 
993                 tv.tv_sec = src->timeout;
994                 tv.tv_usec = 0;
995                 
996                 r = select(s->fd + 1, &fds, NULL, NULL, &tv);
997                 
998                 if(r == -1)
999                 {
1000                         /*ERROR("select: %s", strerror(errno));*/
1001                         return(-1);
1002                 }
1003                 
1004                 if(!r)
1005                 {
1006                         /*ERROR("Timed out waiting for frame!");*/
1007                         return(-1);
1008                 }
1009         }
1010         
1011         if(s->map)
1012         {
1013                 if(s->pframe >= 0)
1014                 {
1015                         if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
1016                         {
1017                                 /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
1018                                 return(-1);
1019                         }
1020                 }
1021                 
1022                 memset(&s->buf, 0, sizeof(s->buf));
1023                 
1024                 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1025                 s->buf.memory = V4L2_MEMORY_MMAP;
1026                 
1027                 if(ioctl(s->fd, VIDIOC_DQBUF, &s->buf) == -1)
1028                 {
1029                         /*ERROR("VIDIOC_DQBUF: %s", strerror(errno));*/
1030                         return(-1);
1031                 }
1032                 
1033                 src->img    = s->buffer[s->buf.index].start;
1034                 src->length = s->buffer[s->buf.index].length;
1035                 
1036                 s->pframe = s->buf.index;
1037         }
1038         else
1039         {
1040                 ssize_t r;
1041                 
1042                 r = read(s->fd, s->buffer[0].start, s->buffer[0].length);
1043                 if(r <= 0)
1044                 {
1045                         /*ERROR("Unable to read a frame.");
1046                         ERROR("read: %s", strerror(errno));*/
1047                         return(-1);
1048                 }
1049                 
1050                 src->img = s->buffer[0].start;
1051                 src->length = r;
1052         }
1053         
1054         return(0);
1055 }
1056
1057 src_mod_t src_v4l2 = {
1058         "v4l2", SRC_TYPE_DEVICE,
1059         src_v4l2_open,
1060         src_v4l2_close,
1061         src_v4l2_grab,
1062         src_v4l2_query
1063 };
1064
1065 #else /* #ifdef HAVE_V4L2 */
1066
1067 src_mod_t src_v4l2 = {
1068         "", SRC_TYPE_NONE,
1069         NULL,
1070         NULL,
1071         NULL,
1072         NULL
1073 };
1074
1075 #endif /* #ifdef HAVE_V4L2 */
1076