FPS option part 2
[fswebcam.git] / src_v4l2.c
blob92c8e9cefad81a1c567805686ac0171b2fa8f209
1 /* fswebcam - FireStorm.cx's webcam generator */
2 /*===========================================================*/
3 /* Copyright (C)2005-2009 Philip Heron <phil@firestorm.cx> */
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. */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
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 #include "log.h"
26 #ifdef HAVE_V4L2
28 typedef struct {
29 void *start;
30 size_t length;
31 } v4l2_buffer_t;
33 typedef struct {
35 int fd;
36 char map;
38 struct v4l2_capability cap;
39 struct v4l2_format fmt;
40 struct v4l2_requestbuffers req;
41 struct v4l2_buffer buf;
43 v4l2_buffer_t *buffer;
45 int pframe;
47 } src_v4l2_t;
49 typedef struct {
50 uint16_t src;
51 uint32_t v4l2;
52 } v4l2_palette_t;
54 v4l2_palette_t v4l2_palette[] = {
55 { SRC_PAL_JPEG, V4L2_PIX_FMT_JPEG },
56 { SRC_PAL_MJPEG, V4L2_PIX_FMT_MJPEG },
57 { SRC_PAL_RGB24, V4L2_PIX_FMT_RGB24 },
58 { SRC_PAL_BGR24, V4L2_PIX_FMT_BGR24 },
59 { SRC_PAL_RGB32, V4L2_PIX_FMT_RGB32 },
60 { SRC_PAL_BGR32, V4L2_PIX_FMT_BGR32 },
61 { SRC_PAL_YUYV, V4L2_PIX_FMT_YUYV },
62 { SRC_PAL_UYVY, V4L2_PIX_FMT_UYVY },
63 { SRC_PAL_YUV420P, V4L2_PIX_FMT_YUV420 },
64 { SRC_PAL_BAYER, V4L2_PIX_FMT_SBGGR8 },
65 { SRC_PAL_SGBRG8, V4L2_PIX_FMT_SGBRG8 },
66 { SRC_PAL_RGB565, V4L2_PIX_FMT_RGB565 },
67 { SRC_PAL_RGB555, V4L2_PIX_FMT_RGB555 },
68 { SRC_PAL_GREY, V4L2_PIX_FMT_GREY },
69 { 0, 0 }
72 int src_v4l2_get_capability(src_t *src)
74 src_v4l2_t *s = (src_v4l2_t *) src->state;
76 if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0)
78 ERROR("%s: Not a V4L2 device?", src->source);
79 return(-1);
82 DEBUG("%s information:", src->source);
83 DEBUG("cap.driver: \"%s\"", s->cap.driver);
84 DEBUG("cap.card: \"%s\"", s->cap.card);
85 DEBUG("cap.bus_info: \"%s\"", s->cap.bus_info);
86 DEBUG("cap.capabilities=0x%08X", s->cap.capabilities);
87 if(s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) DEBUG("- VIDEO_CAPTURE");
88 if(s->cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) DEBUG("- VIDEO_OUTPUT");
89 if(s->cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) DEBUG("- VIDEO_OVERLAY");
90 if(s->cap.capabilities & V4L2_CAP_VBI_CAPTURE) DEBUG("- VBI_CAPTURE");
91 if(s->cap.capabilities & V4L2_CAP_VBI_OUTPUT) DEBUG("- VBI_OUTPUT");
92 if(s->cap.capabilities & V4L2_CAP_RDS_CAPTURE) DEBUG("- RDS_CAPTURE");
93 if(s->cap.capabilities & V4L2_CAP_TUNER) DEBUG("- TUNER");
94 if(s->cap.capabilities & V4L2_CAP_AUDIO) DEBUG("- AUDIO");
95 if(s->cap.capabilities & V4L2_CAP_RADIO) DEBUG("- RADIO");
96 if(s->cap.capabilities & V4L2_CAP_READWRITE) DEBUG("- READWRITE");
97 if(s->cap.capabilities & V4L2_CAP_ASYNCIO) DEBUG("- ASYNCIO");
98 if(s->cap.capabilities & V4L2_CAP_STREAMING) DEBUG("- STREAMING");
99 if(s->cap.capabilities & V4L2_CAP_TIMEPERFRAME) DEBUG("- TIMEPERFRAME");
101 if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
103 ERROR("Device does not support capturing.");
104 return(-1);
107 return(0);
110 int src_v4l2_set_input(src_t *src)
112 src_v4l2_t *s = (src_v4l2_t *) src->state;
113 struct v4l2_input input;
114 int count = 0, i = -1;
116 memset(&input, 0, sizeof(input));
118 if(src->list & SRC_LIST_INPUTS)
120 HEAD("--- Avaliable inputs:");
122 input.index = count;
123 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
125 MSG("%i: %s", count, input.name);
126 input.index = ++count;
130 /* If no input was specified, use input 0. */
131 if(!src->input)
133 MSG("No input was specified, using the first.");
134 count = 1;
135 i = 0;
138 /* Check if the input is specified by name. */
139 if(i == -1)
141 input.index = count;
142 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
144 if(!strncasecmp((char *) input.name, src->input, 32))
145 i = count;
146 input.index = ++count;
150 if(i == -1)
152 char *endptr;
154 /* Is the input specified by number? */
155 i = strtol(src->input, &endptr, 10);
157 if(endptr == src->input) i = -1;
160 if(i == -1 || i >= count)
162 /* The specified input wasn't found! */
163 ERROR("Unrecognised input \"%s\"", src->input);
164 return(-1);
167 /* Set the input. */
168 input.index = i;
169 if(ioctl(s->fd, VIDIOC_ENUMINPUT, &input) == -1)
171 ERROR("Unable to query input %i.", i);
172 ERROR("VIDIOC_ENUMINPUT: %s", strerror(errno));
173 return(-1);
176 DEBUG("%s: Input %i information:", src->source, i);
177 DEBUG("name = \"%s\"", input.name);
178 DEBUG("type = %08X", input.type);
179 if(input.type & V4L2_INPUT_TYPE_TUNER) DEBUG("- TUNER");
180 if(input.type & V4L2_INPUT_TYPE_CAMERA) DEBUG("- CAMERA");
181 DEBUG("audioset = %08X", input.audioset);
182 DEBUG("tuner = %08X", input.tuner);
183 DEBUG("status = %08X", input.status);
184 if(input.status & V4L2_IN_ST_NO_POWER) DEBUG("- NO_POWER");
185 if(input.status & V4L2_IN_ST_NO_SIGNAL) DEBUG("- NO_SIGNAL");
186 if(input.status & V4L2_IN_ST_NO_COLOR) DEBUG("- NO_COLOR");
187 if(input.status & V4L2_IN_ST_NO_H_LOCK) DEBUG("- NO_H_LOCK");
188 if(input.status & V4L2_IN_ST_COLOR_KILL) DEBUG("- COLOR_KILL");
189 if(input.status & V4L2_IN_ST_NO_SYNC) DEBUG("- NO_SYNC");
190 if(input.status & V4L2_IN_ST_NO_EQU) DEBUG("- NO_EQU");
191 if(input.status & V4L2_IN_ST_NO_CARRIER) DEBUG("- NO_CARRIER");
192 if(input.status & V4L2_IN_ST_MACROVISION) DEBUG("- MACROVISION");
193 if(input.status & V4L2_IN_ST_NO_ACCESS) DEBUG("- NO_ACCESS");
194 if(input.status & V4L2_IN_ST_VTR) DEBUG("- VTR");
196 if(ioctl(s->fd, VIDIOC_S_INPUT, &i) == -1)
198 ERROR("Error selecting input %i", i);
199 ERROR("VIDIOC_S_INPUT: %s", strerror(errno));
200 return(-1);
203 /* If this input is attached to a tuner, set the frequency. */
204 if(input.type & V4L2_INPUT_TYPE_TUNER)
206 char *range;
207 struct v4l2_tuner tuner;
208 struct v4l2_frequency freq;
210 /* Query the tuners capabilities. */
212 memset(&tuner, 0, sizeof(tuner));
213 tuner.index = input.tuner;
215 if(ioctl(s->fd, VIDIOC_G_TUNER, &tuner) == -1)
217 WARN("Error querying tuner %i.", input.tuner);
218 WARN("VIDIOC_G_TUNER: %s", strerror(errno));
219 return(0);
222 if(tuner.capability & V4L2_TUNER_CAP_LOW) range = "kHz";
223 else range = "MHz";
225 DEBUG("%s: Tuner %i information:", src->source, input.tuner);
226 DEBUG("name = \"%s\"", tuner.name);
227 DEBUG("type = %08X", tuner.type);
228 if(tuner.type == V4L2_TUNER_RADIO) DEBUG("- RADIO");
229 if(tuner.type == V4L2_TUNER_ANALOG_TV) DEBUG("- ANALOG_TV");
230 DEBUG("capability = %08X", tuner.capability);
231 if(tuner.capability & V4L2_TUNER_CAP_LOW) DEBUG("- LOW");
232 if(tuner.capability & V4L2_TUNER_CAP_NORM) DEBUG("- NORM");
233 if(tuner.capability & V4L2_TUNER_CAP_STEREO) DEBUG("- STEREO");
234 if(tuner.capability & V4L2_TUNER_CAP_LANG1) DEBUG("- LANG1");
235 if(tuner.capability & V4L2_TUNER_CAP_LANG2) DEBUG("- LANG2");
236 if(tuner.capability & V4L2_TUNER_CAP_SAP) DEBUG("- SAP");
237 DEBUG("rangelow = %08X, (%.3f%s)", tuner.rangelow, (double) tuner.rangelow * 16 / 1000, range);
238 DEBUG("rangehigh = %08X, (%.3f%s)", tuner.rangehigh, (double) tuner.rangehigh * 16 / 1000, range);
239 DEBUG("signal = %08X", tuner.signal);
240 DEBUG("afc = %08X", tuner.afc);
242 /* Set the frequency. */
243 memset(&freq, 0, sizeof(freq));
244 freq.tuner = input.tuner;
245 freq.type = V4L2_TUNER_ANALOG_TV;
246 freq.frequency = (src->frequency / 1000) * 16;
248 if(ioctl(s->fd, VIDIOC_S_FREQUENCY, &freq) == -1)
250 WARN("Error setting frequency %.3f%s", src->frequency / 16.0, range);
251 WARN("VIDIOC_S_FREQUENCY: %s", strerror(errno));
252 return(0);
255 MSG("Set frequency to %.3f%s",
256 (double) src->frequency / 1000, range);
259 return(0);
262 int src_v4l2_show_control(src_t *src, struct v4l2_queryctrl *queryctrl)
264 src_v4l2_t *s = (src_v4l2_t *) src->state;
265 struct v4l2_querymenu querymenu;
266 struct v4l2_control control;
267 char *t;
268 int m;
270 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
272 memset(&querymenu, 0, sizeof(querymenu));
273 memset(&control, 0, sizeof(control));
275 if(queryctrl->type != V4L2_CTRL_TYPE_BUTTON)
277 control.id = queryctrl->id;
278 if(ioctl(s->fd, VIDIOC_G_CTRL, &control))
280 ERROR("Error reading value of control '%s'.", queryctrl->name);
281 ERROR("VIDIOC_G_CTRL: %s", strerror(errno));
285 switch(queryctrl->type)
287 case V4L2_CTRL_TYPE_INTEGER:
289 t = malloc(64); /* Ick ... TODO: re-write this. */
290 if(!t)
292 ERROR("Out of memory.");
293 return(-1);
296 if(queryctrl->maximum - queryctrl->minimum <= 10)
298 snprintf(t, 63, "%i", control.value);
300 else
302 snprintf(t, 63, "%i (%i%%)",
303 control.value,
304 SCALE(0, 100,
305 queryctrl->minimum,
306 queryctrl->maximum,
307 control.value));
310 MSG("%-25s %-15s %i - %i", queryctrl->name, t,
311 queryctrl->minimum, queryctrl->maximum);
313 free(t);
315 break;
317 case V4L2_CTRL_TYPE_BOOLEAN:
318 MSG("%-25s %-15s True | False", queryctrl->name,
319 (control.value ? "True" : "False"));
320 break;
322 case V4L2_CTRL_TYPE_MENU:
324 querymenu.id = queryctrl->id;
326 t = calloc((queryctrl->maximum - queryctrl->minimum) + 1, 34);
327 m = queryctrl->minimum;
328 for(m = queryctrl->minimum; m <= queryctrl->maximum; m++)
330 querymenu.index = m;
331 if(!ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
333 strncat(t, (char *) querymenu.name, 32);
334 if(m < queryctrl->maximum) strncat(t, " | ", 3);
338 querymenu.index = control.value;
339 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
341 free(t);
342 ERROR("Error reading value of menu item %i for control '%s'",
343 control.value, queryctrl->name);
344 ERROR("VIDIOC_QUERYMENU: %s", strerror(errno));
345 return(0);
348 MSG("%-25s %-15s %s", queryctrl->name, querymenu.name, t);
349 free(t);
351 break;
353 case V4L2_CTRL_TYPE_BUTTON:
354 MSG("%-25s %-15s %s", queryctrl->name, "-", "[Button]");
355 break;
357 default:
358 MSG("%-25s %-15s %s", queryctrl->name, "N/A", "[Unknown Control Type]");
359 break;
362 return(0);
365 int src_v4l2_set_control(src_t *src, struct v4l2_queryctrl *queryctrl)
367 src_v4l2_t *s = (src_v4l2_t *) src->state;
368 struct v4l2_control control;
369 struct v4l2_querymenu querymenu;
370 char *sv;
371 int iv;
373 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
374 if(src_get_option_by_name(src->option, (char *) queryctrl->name, &sv))
375 return(0);
377 memset(&querymenu, 0, sizeof(querymenu));
378 memset(&control, 0, sizeof(control));
380 control.id = queryctrl->id;
382 switch(queryctrl->type)
384 case V4L2_CTRL_TYPE_INTEGER:
386 /* Convert the value to an integer. */
387 iv = atoi(sv);
389 /* Is the value a precentage? */
390 if(strchr(sv, '%'))
392 /* Adjust the precentage to fit the controls range. */
393 iv = SCALE(queryctrl->minimum, queryctrl->maximum,
394 0, 100, iv);
397 MSG("Setting %s to %i (%i%%).", queryctrl->name, iv,
398 SCALE(0, 100, queryctrl->minimum, queryctrl->maximum, iv));
400 if(iv < queryctrl->minimum || iv > queryctrl->maximum)
401 WARN("Value is out of range. Setting anyway.");
403 control.value = iv;
404 ioctl(s->fd, VIDIOC_S_CTRL, &control);
405 break;
407 case V4L2_CTRL_TYPE_BOOLEAN:
409 iv = -1;
410 if(!strcasecmp(sv, "1") || !strcasecmp(sv, "true")) iv = 1;
411 if(!strcasecmp(sv, "0") || !strcasecmp(sv, "false")) iv = 0;
413 if(iv == -1)
415 WARN("Unknown boolean value '%s' for %s.",
416 sv, queryctrl->name);
417 return(-1);
420 MSG("Setting %s to %s (%i).", queryctrl->name, sv, iv);
422 control.value = iv;
423 ioctl(s->fd, VIDIOC_S_CTRL, &control);
425 break;
427 case V4L2_CTRL_TYPE_MENU:
429 /* Scan for a matching value. */
430 querymenu.id = queryctrl->id;
432 for(iv = queryctrl->minimum; iv <= queryctrl->maximum; iv++)
434 querymenu.index = iv;
436 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
438 ERROR("Error querying menu.");
439 continue;
442 if(!strncasecmp((char *) querymenu.name, sv, 32))
443 break;
446 if(iv > queryctrl->maximum)
448 MSG("Unknown value '%s' for %s.", sv, queryctrl->name);
449 return(-1);
452 MSG("Setting %s to %s (%i).",
453 queryctrl->name, querymenu.name, iv);
455 control.value = iv;
456 ioctl(s->fd, VIDIOC_S_CTRL, &control);
458 break;
460 case V4L2_CTRL_TYPE_BUTTON:
462 MSG("Triggering %s control.", queryctrl->name);
463 ioctl(s->fd, VIDIOC_S_CTRL, &control);
465 break;
467 default:
468 WARN("Not setting unknown control type %i (%s).",
469 queryctrl->name);
470 break;
473 return(0);
476 int src_v4l2_set_controls(src_t *src)
478 src_v4l2_t *s = (src_v4l2_t *) src->state;
479 struct v4l2_queryctrl queryctrl;
480 int c;
482 memset(&queryctrl, 0, sizeof(queryctrl));
484 if(src->list & SRC_LIST_CONTROLS)
486 HEAD("%-25s %-15s %s", "Available Controls", "Current Value", "Range");
487 MSG("%-25s %-15s %s", "------------------", "-------------", "-----");
489 /* Display normal controls. */
490 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
492 queryctrl.id = c;
494 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
495 src_v4l2_show_control(src, &queryctrl);
498 /* Display device-specific controls. */
499 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
501 queryctrl.id = c;
503 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
504 src_v4l2_show_control(src, &queryctrl);
508 /* Scan normal controls. */
509 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
511 queryctrl.id = c;
513 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
514 src_v4l2_set_control(src, &queryctrl);
517 /* Scan device-specific controls. */
518 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
520 queryctrl.id = c;
522 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
523 src_v4l2_set_control(src, &queryctrl);
526 return(0);
529 int src_v4l2_set_pix_format(src_t *src)
531 src_v4l2_t *s = (src_v4l2_t *) src->state;
532 struct v4l2_fmtdesc fmt;
533 int v4l2_pal;
535 /* Dump a list of formats the device supports. */
536 DEBUG("Device offers the following V4L2 pixel formats:");
538 v4l2_pal = 0;
539 memset(&fmt, 0, sizeof(fmt));
540 fmt.index = v4l2_pal;
541 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
543 while(ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
545 DEBUG("%i: %c%c%c%c (%s)", v4l2_pal,
546 fmt.pixelformat >> 0, fmt.pixelformat >> 8,
547 fmt.pixelformat >> 16, fmt.pixelformat >> 24,
548 fmt.description);
550 memset(&fmt, 0, sizeof(fmt));
551 fmt.index = ++v4l2_pal;
552 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
555 /* Step through each palette type. */
556 v4l2_pal = 0;
558 if(src->palette != -1)
560 while(v4l2_palette[v4l2_pal].v4l2)
562 if(v4l2_palette[v4l2_pal].src == src->palette) break;
563 v4l2_pal++;
566 if(!v4l2_palette[v4l2_pal].v4l2)
568 ERROR("Unable to handle palette format %s.",
569 src_palette[src->palette]);
571 return(-1);
575 while(v4l2_palette[v4l2_pal].v4l2)
577 /* Try the palette... */
578 memset(&s->fmt, 0, sizeof(s->fmt));
579 s->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
580 s->fmt.fmt.pix.width = src->width;
581 s->fmt.fmt.pix.height = src->height;
582 s->fmt.fmt.pix.pixelformat = v4l2_palette[v4l2_pal].v4l2;
583 s->fmt.fmt.pix.field = V4L2_FIELD_ANY;
585 if(ioctl(s->fd, VIDIOC_TRY_FMT, &s->fmt) != -1 &&
586 s->fmt.fmt.pix.pixelformat == v4l2_palette[v4l2_pal].v4l2)
588 src->palette = v4l2_palette[v4l2_pal].src;
590 INFO("Using palette %s", src_palette[src->palette].name);
592 if(s->fmt.fmt.pix.width != src->width ||
593 s->fmt.fmt.pix.height != src->height)
595 MSG("Adjusting resolution from %ix%i to %ix%i.",
596 src->width, src->height,
597 s->fmt.fmt.pix.width,
598 s->fmt.fmt.pix.height);
599 src->width = s->fmt.fmt.pix.width;
600 src->height = s->fmt.fmt.pix.height;
603 if(ioctl(s->fd, VIDIOC_S_FMT, &s->fmt) == -1)
605 ERROR("Error setting pixel format.");
606 ERROR("VIDIOC_S_FMT: %s", strerror(errno));
607 return(-1);
610 if(v4l2_palette[v4l2_pal].v4l2 == V4L2_PIX_FMT_MJPEG)
612 struct v4l2_jpegcompression jpegcomp;
614 memset(&jpegcomp, 0, sizeof(jpegcomp));
615 ioctl(s->fd, VIDIOC_G_JPEGCOMP, &jpegcomp);
616 jpegcomp.jpeg_markers |= V4L2_JPEG_MARKER_DHT;
617 ioctl(s->fd, VIDIOC_S_JPEGCOMP, &jpegcomp);
620 return(0);
623 if(src->palette != -1) break;
625 v4l2_pal++;
628 ERROR("Unable to find a compatible palette format.");
630 return(-1);
633 int src_v4l2_set_fps(src_t *src)
635 src_v4l2_t *s = (src_v4l2_t *) src->state;
636 struct v4l2_streamparm setfps;
638 memset(&setfps, 0, sizeof(setfps));
640 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
641 setfps.parm.capture.timeperframe.numerator = 1;
642 setfps.parm.capture.timeperframe.denominator = src->fps;
643 if(ioctl(s->fd, VIDIOC_S_PARM, setfps) == -1)
645 /* Not fatal - just warn about it */
646 WARN("Error setting frame rate:");
647 WARN("VIDIOC_S_PARM: %s", strerror(errno));
648 return(-1);
651 return(0);
654 int src_v4l2_free_mmap(src_t *src)
656 src_v4l2_t *s = (src_v4l2_t *) src->state;
657 int i;
659 for(i = 0; i < s->req.count; i++)
660 munmap(s->buffer[i].start, s->buffer[i].length);
662 return(0);
665 int src_v4l2_set_mmap(src_t *src)
667 src_v4l2_t *s = (src_v4l2_t *) src->state;
668 enum v4l2_buf_type type;
669 uint32_t b;
671 /* Does the device support streaming? */
672 if(~s->cap.capabilities & V4L2_CAP_STREAMING) return(-1);
674 memset(&s->req, 0, sizeof(s->req));
676 s->req.count = 4;
677 s->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
678 s->req.memory = V4L2_MEMORY_MMAP;
680 if(ioctl(s->fd, VIDIOC_REQBUFS, &s->req) == -1)
682 ERROR("Error requesting buffers for memory map.");
683 ERROR("VIDIOC_REQBUFS: %s", strerror(errno));
684 return(-1);
687 DEBUG("mmap information:");
688 DEBUG("frames=%d", s->req.count);
690 if(s->req.count < 2)
692 ERROR("Insufficient buffer memory.");
693 return(-1);
696 s->buffer = calloc(s->req.count, sizeof(v4l2_buffer_t));
697 if(!s->buffer)
699 ERROR("Out of memory.");
700 return(-1);
703 for(b = 0; b < s->req.count; b++)
705 struct v4l2_buffer buf;
707 memset(&buf, 0, sizeof(buf));
709 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
710 buf.memory = V4L2_MEMORY_MMAP;
711 buf.index = b;
713 if(ioctl(s->fd, VIDIOC_QUERYBUF, &buf) == -1)
715 ERROR("Error querying buffer %i", b);
716 ERROR("VIDIOC_QUERYBUF: %s", strerror(errno));
717 free(s->buffer);
718 return(-1);
721 s->buffer[b].length = buf.length;
722 s->buffer[b].start = mmap(NULL, buf.length,
723 PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
725 if(s->buffer[b].start == MAP_FAILED)
727 ERROR("Error mapping buffer %i", b);
728 ERROR("mmap: %s", strerror(errno));
729 s->req.count = b;
730 src_v4l2_free_mmap(src);
731 free(s->buffer);
732 return(-1);
735 DEBUG("%i length=%d", b, buf.length);
738 s->map = -1;
740 for(b = 0; b < s->req.count; b++)
742 memset(&s->buf, 0, sizeof(s->buf));
744 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
745 s->buf.memory = V4L2_MEMORY_MMAP;
746 s->buf.index = b;
748 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
750 ERROR("VIDIOC_QBUF: %s", strerror(errno));
751 src_v4l2_free_mmap(src);
752 free(s->buffer);
753 return(-1);
757 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
759 if(ioctl(s->fd, VIDIOC_STREAMON, &type) == -1)
761 ERROR("Error starting stream.");
762 ERROR("VIDIOC_STREAMON: %s", strerror(errno));
763 src_v4l2_free_mmap(src);
764 free(s->buffer);
765 return(-1);
768 return(0);
771 int src_v4l2_set_read(src_t *src)
773 src_v4l2_t *s = (src_v4l2_t *) src->state;
775 if(~s->cap.capabilities & V4L2_CAP_READWRITE) return(-1);
777 s->buffer = calloc(1, sizeof(v4l2_buffer_t));
778 if(!s->buffer)
780 ERROR("Out of memory.");
781 return(-1);
784 s->buffer[0].length = s->fmt.fmt.pix.sizeimage;
785 s->buffer[0].start = malloc(s->buffer[0].length);
787 if(!s->buffer[0].start)
789 ERROR("Out of memory.");
791 free(s->buffer);
792 s->buffer = NULL;
794 return(-1);
797 return(0);
800 int src_v4l2_open(src_t *src)
802 src_v4l2_t *s;
804 if(!src->source)
806 ERROR("No device name specified.");
807 return(-2);
810 /* Allocate memory for the state structure. */
811 s = calloc(sizeof(src_v4l2_t), 1);
812 if(!s)
814 ERROR("Out of memory.");
815 return(-2);
818 src->state = (void *) s;
820 /* Open the device. */
821 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
822 if(s->fd < 0)
824 ERROR("Error opening device: %s", src->source);
825 ERROR("open: %s", strerror(errno));
826 free(s);
827 return(-2);
830 MSG("%s opened.", src->source);
832 /* Get the device capabilities. */
833 if(src_v4l2_get_capability(src))
835 src_close(src);
836 return(-2);
839 /* Set the input. */
840 if(src_v4l2_set_input(src))
842 src_close(src);
843 return(-1);
846 /* Set picture options. */
847 src_v4l2_set_controls(src);
849 /* Set the pixel format. */
850 if(src_v4l2_set_pix_format(src))
852 src_close(src);
853 return(-1);
856 /* Set the frame-rate if > 0 */
857 if(src->fps) src_v4l2_set_fps(src);
859 /* Delay to let the image settle down. */
860 if(src->delay)
862 MSG("Delaying %i seconds.", src->delay);
863 usleep(src->delay * 1000 * 1000);
866 /* Try to setup mmap. */
867 if(!src->use_read && src_v4l2_set_mmap(src))
869 WARN("Unable to use mmap. Using read instead.");
870 src->use_read = -1;
873 /* If unable to use mmap or user requested read(). */
874 if(src->use_read)
876 if(src_v4l2_set_read(src))
878 ERROR("Unable to use read.");
879 src_close(src);
880 return(-1);
884 s->pframe = -1;
886 return(0);
889 int src_v4l2_close(src_t *src)
891 src_v4l2_t *s = (src_v4l2_t *) src->state;
893 if(s->buffer)
895 if(!s->map) free(s->buffer[0].start);
896 else src_v4l2_free_mmap(src);
897 free(s->buffer);
899 if(s->fd >= 0) close(s->fd);
900 free(s);
902 return(0);
905 int src_v4l2_grab(src_t *src)
907 src_v4l2_t *s = (src_v4l2_t *) src->state;
909 if(src->timeout)
911 fd_set fds;
912 struct timeval tv;
913 int r;
915 /* Is a frame ready? */
916 FD_ZERO(&fds);
917 FD_SET(s->fd, &fds);
919 tv.tv_sec = src->timeout;
920 tv.tv_usec = 0;
922 r = select(s->fd + 1, &fds, NULL, NULL, &tv);
924 if(r == -1)
926 ERROR("select: %s", strerror(errno));
927 return(-1);
930 if(!r)
932 ERROR("Timed out waiting for frame!");
933 return(-1);
937 if(s->map)
939 if(s->pframe >= 0)
941 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
943 ERROR("VIDIOC_QBUF: %s", strerror(errno));
944 return(-1);
948 memset(&s->buf, 0, sizeof(s->buf));
950 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
951 s->buf.memory = V4L2_MEMORY_MMAP;
953 if(ioctl(s->fd, VIDIOC_DQBUF, &s->buf) == -1)
955 ERROR("VIDIOC_DQBUF: %s", strerror(errno));
956 return(-1);
959 src->img = s->buffer[s->buf.index].start;
960 src->length = s->buffer[s->buf.index].length;
962 s->pframe = s->buf.index;
964 else
966 ssize_t r;
968 r = read(s->fd, s->buffer[0].start, s->buffer[0].length);
969 if(r <= 0)
971 ERROR("Unable to read a frame.");
972 ERROR("read: %s", strerror(errno));
973 return(-1);
976 src->img = s->buffer[0].start;
977 src->length = r;
980 return(0);
983 src_mod_t src_v4l2 = {
984 "v4l2", SRC_TYPE_DEVICE,
985 src_v4l2_open,
986 src_v4l2_close,
987 src_v4l2_grab
990 #else /* #ifdef HAVE_V4L2 */
992 src_mod_t src_v4l2 = {
993 "", SRC_TYPE_NONE,
994 NULL,
995 NULL,
996 NULL
999 #endif /* #ifdef HAVE_V4L2 */