FPS option part 2
[fswebcam.git] / src_v4l1.c
blobbe24a9bc86bb19e78f5daa713da20036a46aea46
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 "videodev.h"
23 #include "videodev_mjpeg.h"
24 #include "src.h"
25 #include "log.h"
27 #ifdef HAVE_V4L1
29 typedef struct {
31 int fd;
32 void *map;
34 struct video_mbuf vm;
35 struct video_mmap mm;
36 int frame;
37 int pframe;
39 struct mjpeg_requestbuffers mjpeg_breq;
40 struct mjpeg_sync mjpeg_bsync;
42 uint32_t buffer_length;
43 uint8_t *buffer;
45 uint16_t palette;
47 } src_v4l_t;
49 typedef struct {
50 uint16_t src;
51 uint16_t v4l;
52 uint16_t depth;
53 } v4l_palette_t;
55 v4l_palette_t v4l_palette[] = {
56 { SRC_PAL_JPEG, VIDEO_PALETTE_RGB24, 24 },
57 { SRC_PAL_MJPEG, VIDEO_PALETTE_RGB24, 24 },
58 { SRC_PAL_YUYV, VIDEO_PALETTE_YUYV, 16 },
59 { SRC_PAL_UYVY, VIDEO_PALETTE_UYVY, 16 },
60 { SRC_PAL_YUV420P, VIDEO_PALETTE_YUV420P, 12 },
61 { SRC_PAL_BGR24, VIDEO_PALETTE_RGB24, 24 }, /* RGB24/32 in V4L1 */
62 { SRC_PAL_BGR32, VIDEO_PALETTE_RGB32, 32 }, /* are actually BGR */
63 { SRC_PAL_RGB565, VIDEO_PALETTE_RGB565, 16 },
64 { SRC_PAL_RGB555, VIDEO_PALETTE_RGB555, 16 },
65 { SRC_PAL_GREY, VIDEO_PALETTE_GREY, 8 },
66 { 0, 0, 0 }
69 int src_v4l_get_capability(src_t *src, int fd, struct video_capability *vd)
71 if(ioctl(fd, VIDIOCGCAP, vd) < 0)
73 ERROR("%s: Not a V4L device?", src->source);
74 ERROR("VIDIOCGCAP: %s", strerror(errno));
75 return(-1);
78 /* Dump information about the capture card. */
79 DEBUG("%s information:", src->source);
80 DEBUG("vd.name: \"%s\"", vd->name);
81 DEBUG("vd.type=0x%08x", vd->type);
82 if(vd->type & VID_TYPE_CAPTURE) DEBUG("- CAPTURE");
83 if(vd->type & VID_TYPE_TUNER) DEBUG("- TUNER");
84 if(vd->type & VID_TYPE_TELETEXT) DEBUG("- TELETEXT");
85 if(vd->type & VID_TYPE_OVERLAY) DEBUG("- OVERLAY");
86 if(vd->type & VID_TYPE_CHROMAKEY) DEBUG("- CHROMAKEY");
87 if(vd->type & VID_TYPE_CLIPPING) DEBUG("- CLIPPING");
88 if(vd->type & VID_TYPE_FRAMERAM) DEBUG("- FRAMERAM");
89 if(vd->type & VID_TYPE_SCALES) DEBUG("- SCALES");
90 if(vd->type & VID_TYPE_MONOCHROME) DEBUG("- MONOCHROME");
91 if(vd->type & VID_TYPE_SUBCAPTURE) DEBUG("- SUBCAPTURE");
92 if(vd->type & VID_TYPE_MJPEG_ENCODER) DEBUG("- MJPEG_ENCODER");
93 DEBUG("vd.maxwidth=%d", vd->maxwidth);
94 DEBUG("vd.maxheight=%d", vd->maxheight);
95 DEBUG("vd.minwidth=%d", vd->minwidth);
96 DEBUG("vd.minheight=%d", vd->minheight);
98 /* Make sure we can capture from this device. */
99 if(!vd->type & VID_TYPE_CAPTURE)
101 ERROR("%s: Device does not support capturing.", src->source);
102 return(-1);
105 /* Make sure we can capture at the requested resolution. */
106 if(vd->minwidth && vd->minwidth > src->width)
108 WARN("Requested width too small. Adjusting %i -> %i.",
109 src->width, vd->minwidth);
110 src->width = vd->minwidth;
113 if(vd->maxwidth && vd->maxwidth < src->width)
115 WARN("Requested width too large. Adjusting %i -> %i.",
116 src->width, vd->maxwidth);
117 src->width = vd->maxwidth;
120 if(vd->minheight && vd->minheight > src->height)
122 WARN("Requested height too small. Adjusting %i -> %i.",
123 src->height, vd->minheight);
124 src->height = vd->minheight;
127 if(vd->maxheight && vd->maxheight < src->height)
129 WARN("Requested height too large. Adjusting %i -> %i.",
130 src->height, vd->maxheight);
131 src->height = vd->maxheight;
134 return(0);
137 int src_v4l_set_input(src_t *src, int fd,
138 struct video_capability *vd,
139 struct video_channel *vc)
141 int count = 0, i = -1;
143 if(vd->channels == 0)
145 MSG("No inputs available.");
146 return(-1);
149 if(src->list & SRC_LIST_INPUTS)
151 HEAD("--- Available inputs:");
153 count = 0;
154 vc->channel = count;
155 while(!ioctl(fd, VIDIOCGCHAN, vc))
157 MSG("%i: %s", count, (char *) vc->name);
158 vc->channel = ++count;
162 /* If no input was specified, use input 0. */
163 if(!src->input)
165 MSG("No input was specified, using the first.");
166 count = 1;
167 i = 0;
169 else
171 /* Check if the input is specified by name. */
172 count = 0;
173 vc->channel = count;
174 while(!ioctl(fd, VIDIOCGCHAN, vc))
176 if(!strncasecmp((char *) vc->name, src->input, 32))
177 i = count;
178 vc->channel = ++count;
181 if(i == -1)
183 char *endptr;
185 /* Is the input specified by number? */
186 i = strtol(src->input, &endptr, 10);
188 if(endptr == src->input) i = -1;
192 if(i == -1 || i >= count)
194 /* The specified input wasn't found! */
195 ERROR("Unrecognised input \"%s\"", src->input);
196 return(-1);
199 /* Get data about the input channel. */
200 vc->channel = i;
201 if(ioctl(fd, VIDIOCGCHAN, vc) < 0)
203 ERROR("Error getting information for input \"%s\".",src->input);
204 ERROR("VIDIOCGCHAN: %s", strerror(errno));
205 return(-1);
208 if(src->input) DEBUG("Input %i (%s) information:", i, src->input);
209 else DEBUG("Input %i information:", i, src->input);
210 DEBUG("vc.channel=%d", vc->channel);
211 DEBUG("vc.name=\"%s\"", vc->name);
212 DEBUG("vc.tuners=%d",vc->tuners);
213 DEBUG("vc.flags=0x%08x", vc->flags);
214 if(vc->flags & VIDEO_VC_TUNER) DEBUG("- TUNER");
215 if(vc->flags & VIDEO_VC_AUDIO) DEBUG("- AUDIO");
216 DEBUG("vc.type=0x%08x", vc->type);
217 if(vc->type & VIDEO_TYPE_TV) DEBUG("- TV");
218 if(vc->type & VIDEO_TYPE_CAMERA) DEBUG("- CAMERA");
219 DEBUG("vc.norm=%d", vc->norm);
221 MSG("Setting input to %i.", i);
223 /* Set the source. */
224 if(ioctl(fd, VIDIOCSCHAN, vc) < 0)
226 ERROR("Error while setting input to %i.", i);
227 ERROR("VIDIOCSCHAN: %s", strerror(errno));
228 return(-1);
231 return(0);
234 int src_v4l_set_tuner(src_t *src, int fd,
235 struct video_channel *vc,
236 struct video_tuner *vt)
238 char *range;
240 if(vc->tuners == 0)
242 MSG("No tuners available.");
243 return(-1);
246 /* Check the requested tuner exists. */
247 if(src->tuner >= vc->tuners)
249 ERROR("Requested tuner %i and only %i tuner(s) found.",
250 src->tuner, vc->tuners - 1);
251 return(-1);
254 /* Get data about the tuner. */
255 vt->tuner = src->tuner;
256 if(ioctl(fd, VIDIOCGTUNER, vt) < 0)
258 ERROR("Error getting information on tuner %i (input %i).",
259 src->tuner, src->input);
260 ERROR("VIDIOCGCHAN: %s", strerror(errno));
261 return(-1);
264 if(vt->flags & VIDEO_TUNER_LOW) range = "KHz";
265 else range = "MHz";
267 DEBUG("Tuner %i information:", src->tuner);
268 DEBUG("vt.tuner=%d", vt->tuner);
269 DEBUG("vt.name=\"%s\"", vt->name);
270 DEBUG("vt.rangelow=%u (%.3f%s)", (unsigned int) vt->rangelow,
271 (float) vt->rangelow / 16, range);
272 DEBUG("vt.rangehigh=%u (%.3f%s)", (unsigned int) vt->rangehigh,
273 (float) vt->rangehigh / 16, range);
274 DEBUG("vt.flags=0x%08x", vt->flags);
275 if(vt->flags & VIDEO_TUNER_PAL) DEBUG("- PAL");
276 if(vt->flags & VIDEO_TUNER_NTSC) DEBUG("- NTSC");
277 if(vt->flags & VIDEO_TUNER_SECAM) DEBUG("- SECAM");
278 if(vt->flags & VIDEO_TUNER_LOW) DEBUG("- LOW");
279 if(vt->flags & VIDEO_TUNER_NORM) DEBUG("- NORM");
280 if(vt->flags & VIDEO_TUNER_STEREO_ON) DEBUG("- STEREO_ON");
281 if(vt->flags & VIDEO_TUNER_RDS_ON) DEBUG("- RDS_ON");
282 if(vt->flags & VIDEO_TUNER_MBS_ON) DEBUG("- MBS_ON");
283 DEBUG("vt.mode=0x%08x", vt->mode);
284 if(vt->mode & VIDEO_MODE_PAL) DEBUG("- PAL");
285 if(vt->mode & VIDEO_MODE_NTSC) DEBUG("- NTSC");
286 if(vt->mode & VIDEO_MODE_SECAM) DEBUG("- SECAM");
287 if(vt->mode & VIDEO_MODE_AUTO) DEBUG("- AUTO");
288 DEBUG("vt.signal=%d", vt->signal);
290 MSG("Setting tuner to %i.", src->tuner);
292 if(ioctl(fd, VIDIOCSTUNER, vt) < 0)
294 ERROR("Error setting tuner %i (input %i).",
295 src->tuner, src->input);
296 ERROR("VIDIOCSTUNER: %s", strerror(errno));
297 return(-1);
300 return(0);
303 int src_v4l_set_frequency(src_t *src, int fd, struct video_tuner *vt)
305 char *range;
306 unsigned long freq;
307 float ff;
309 if(vt->flags & VIDEO_TUNER_LOW) range = "KHz";
310 else range = "MHz";
312 /* Get the current frequency. */
313 ff = 0;
314 ioctl(fd, VIDIOCGFREQ, &freq);
315 if(freq) ff = freq / 16;
316 DEBUG("Current frequency is %.3f%s", ff, range);
318 /* Don't set the frequency if it's 0. */
319 if(src->frequency == 0) return(0);
321 /* Calculate the frequency. */
322 freq = (src->frequency / 1000) * 16;
324 /* Ensure frequency is within range of the tuner. */
325 if(freq < vt->rangelow)
327 WARN("Frequency is below tuners minimum. Using %.3f%s.",
328 (float) vt->rangelow / 16, range);
330 freq = vt->rangelow;
333 if(freq > vt->rangehigh)
335 WARN("Frequency is above tuners maximum. Using %.3f%s.",
336 (float) vt->rangehigh / 16, range);
338 freq = vt->rangehigh;
341 /* Set the frequency. */
342 MSG("Setting frequency to %.3f%s.", (float) freq / 16, range);
344 if(ioctl(fd, VIDIOCSFREQ, &freq) == -1)
346 ERROR("Error setting frequency.");
347 ERROR("VIDIOCSFREQ: %s", strerror(errno));
348 return(-1);
351 return(0);
354 int src_v4l_set_picture(src_t *src, int fd, struct video_capability *vd)
356 src_v4l_t *s = (src_v4l_t *) src->state;
357 struct video_picture vp;
358 int v4l_pal;
359 char *value;
361 memset(&vp, 0, sizeof(vp));
363 if(ioctl(fd, VIDIOCGPICT, &vp) < 0)
365 ERROR("Error getting picture information.");
366 ERROR("VIDIOCGPICT: %s", strerror(errno));
367 return(-1);
370 if(src->list & SRC_LIST_CONTROLS)
372 int i;
374 HEAD("--- Available controls:");
376 for(i = 0; i < 5; i++)
378 char *name = NULL;
379 int value;
380 char t[64];
382 switch(i)
384 case 0:
385 name = "brightness";
386 value = vp.brightness;
387 break;
388 case 1:
389 name = "hue";
390 value = vp.hue;
391 break;
392 case 2:
393 name = "colour";
394 value = vp.colour;
395 break;
396 case 3:
397 name = "contrast";
398 value = vp.contrast;
399 break;
400 case 4:
401 name = "whiteness";
402 value = vp.whiteness;
403 break;
406 snprintf(t, 63, "%i (%i%%)",
407 SCALE(-100, 100, 0x0000, 0xFFFF, vp.brightness),
408 SCALE(0, 100, 0x0000, 0xFFFF, vp.brightness));
410 MSG("%-25s %-15s 100 - -100", name, t);
414 if(!src_get_option_by_name(src->option, "brightness", &value))
415 vp.brightness = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value));
417 if(!src_get_option_by_name(src->option, "hue", &value))
418 vp.hue = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value));
420 if(!src_get_option_by_name(src->option, "colour", &value))
421 vp.colour = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value));
423 if(!src_get_option_by_name(src->option, "contrast", &value))
424 vp.contrast = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value));
426 if(!src_get_option_by_name(src->option, "whiteness", &value))
427 vp.whiteness = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value));
429 /* MJPEG devices are a special case... */
430 if(vd->type & VID_TYPE_MJPEG_ENCODER)
432 WARN("Device is MJPEG only. Forcing JPEG palette.");
433 src->palette = SRC_PAL_JPEG;
436 if(src->palette == SRC_PAL_JPEG && !(vd->type & VID_TYPE_MJPEG_ENCODER))
438 ERROR("MJPEG palette requsted for a non-MJPEG device.");
439 return(-1);
442 if(src->palette == SRC_PAL_JPEG)
444 struct mjpeg_params mparm;
446 memset(&mparm, 0, sizeof(mparm));
448 if(ioctl(s->fd, MJPIOC_G_PARAMS, &mparm))
450 ERROR("Error querying video parameters.");
451 ERROR("MJPIOC_G_PARAMS: %s", strerror(errno));
452 return(-1);
455 DEBUG("%s: Video parameters...", src->source);
456 DEBUG("major_version = %i", mparm.major_version);
457 DEBUG("minor_version = %i", mparm.minor_version);
458 DEBUG("input = %i", mparm.input);
459 DEBUG("norm = %i", mparm.norm);
460 DEBUG("decimation = %i", mparm.decimation);
461 DEBUG("HorDcm = %i", mparm.HorDcm);
462 DEBUG("VerDcm = %i", mparm.VerDcm);
463 DEBUG("TmpDcm = %i", mparm.TmpDcm);
464 DEBUG("field_per_buff = %i", mparm.field_per_buff);
465 DEBUG("img_x = %i", mparm.img_x);
466 DEBUG("img_y = %i", mparm.img_y);
467 DEBUG("img_width = %i", mparm.img_width);
468 DEBUG("img_height = %i", mparm.img_height);
469 DEBUG("quality = %i", mparm.quality);
470 DEBUG("odd_even = %i", mparm.odd_even);
471 DEBUG("APPn = %i", mparm.APPn);
472 DEBUG("APP_len = %i", mparm.APP_len);
473 DEBUG("APP_data = \"%s\"", mparm.APP_data);
474 DEBUG("COM_len = %i", mparm.COM_len);
475 DEBUG("COM_data = \"%s\"", mparm.COM_data);
476 DEBUG("jpeg_markers = %i", mparm.jpeg_markers);
477 if(mparm.jpeg_markers & JPEG_MARKER_DHT) DEBUG("- DHT");
478 if(mparm.jpeg_markers & JPEG_MARKER_DQT) DEBUG("- DQT");
479 if(mparm.jpeg_markers & JPEG_MARKER_DRI) DEBUG("- DRI");
480 if(mparm.jpeg_markers & JPEG_MARKER_COM) DEBUG("- COM");
481 if(mparm.jpeg_markers & JPEG_MARKER_APP) DEBUG("- APP");
482 DEBUG("VFIFO_FB = %i", mparm.VFIFO_FB);
484 /* Set the usual parameters. */
485 mparm.input = 0;
486 mparm.norm = VIDEO_MODE_PAL;
487 /* TODO: Allow user to select PAL/SECAM/NTSC */
489 mparm.decimation = 0;
490 mparm.quality = 80;
492 mparm.HorDcm = 1;
493 mparm.VerDcm = 1;
494 mparm.TmpDcm = 1;
495 mparm.field_per_buff = 2;
497 /* Ask the driver to include the DHT with each frame. */
498 mparm.jpeg_markers |= JPEG_MARKER_DHT;
500 if(ioctl(s->fd, MJPIOC_S_PARAMS, &mparm))
502 ERROR("Error setting video parameters.");
503 ERROR("MJPIOC_S_PARAMS: %s", strerror(errno));
504 return(-1);
507 src->width = mparm.img_width / mparm.HorDcm;
508 src->height = mparm.img_height / mparm.VerDcm * mparm.field_per_buff;
510 return(0);
513 v4l_pal = 2; /* Skip the JPEG palette. */
515 if(src->palette != -1)
517 v4l_pal = 0;
519 while(v4l_palette[v4l_pal].depth)
521 if(v4l_palette[v4l_pal].src == src->palette) break;
522 v4l_pal++;
525 if(!v4l_palette[v4l_pal].depth)
527 ERROR("Unable to handle palette format %s.",
528 src_palette[src->palette]);
530 return(-1);
534 while(v4l_palette[v4l_pal].depth)
536 vp.palette = v4l_palette[v4l_pal].v4l;
537 vp.depth = v4l_palette[v4l_pal].depth;
539 if(!ioctl(fd, VIDIOCSPICT, &vp))
541 s->palette = v4l_pal;
542 src->palette = v4l_palette[v4l_pal].src;
544 MSG("Using palette %s.",src_palette[src->palette].name);
546 return(0);
549 if(src->palette != -1) break;
551 WARN("The device does not support palette %s.",
552 src_palette[v4l_palette[v4l_pal].src].name);
554 v4l_pal++;
557 ERROR("Unable to find a compatible palette.");
559 return(-1);
562 int src_v4l_free_mmap(src_t *src)
564 src_v4l_t *s = (src_v4l_t *) src->state;
566 if(src->palette == SRC_PAL_JPEG)
567 munmap(s->map, s->mjpeg_breq.count * s->mjpeg_breq.size);
568 else
569 munmap(s->map, s->vm.size);
571 return(0);
574 int src_v4l_set_mmap(src_t *src, int fd)
576 src_v4l_t *s = (src_v4l_t *) src->state;
577 uint32_t frame;
579 if(src->palette == SRC_PAL_JPEG)
581 s->mjpeg_breq.count = 32;
582 s->mjpeg_breq.size = 256 * 1024;
584 if(ioctl(s->fd, MJPIOC_REQBUFS, &s->mjpeg_breq))
586 ERROR("Error requesting video buffers.");
587 ERROR("MJPIOC_REQBUFS: %s", strerror(errno));
590 DEBUG("Got %ld buffers of size %ld KB",
591 s->mjpeg_breq.count, s->mjpeg_breq.size / 1024);
593 s->map = mmap(0, s->mjpeg_breq.count * s->mjpeg_breq.size,
594 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
596 if(s->map == MAP_FAILED)
598 WARN("Error mmap'ing buffers.");
599 WARN("mmap: %s", strerror(errno));
600 return(-1);
603 return(0);
606 /* Find out how many buffers are available. */
607 if(ioctl(fd, VIDIOCGMBUF, &s->vm) < 0)
609 WARN("Error while querying buffers.");
610 WARN("VIDEOCGMBUF: %s", strerror(errno));
611 return(-1);
614 DEBUG("mmap information:");
615 DEBUG("size=%d", s->vm.size);
616 DEBUG("frames=%d", s->vm.frames);
618 /* mmap all available buffers. */
619 s->map = mmap(0, s->vm.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
620 if(s->map == MAP_FAILED)
622 WARN("Error mmap'ing all available buffers.");
623 WARN("mmap: %s", strerror(errno));
624 return(-1);
627 /* Setup capture options. */
628 s->mm.format = v4l_palette[s->palette].v4l;
629 s->mm.width = src->width;
630 s->mm.height = src->height;
632 /* Request the maximum number of frames the device can handle. */
633 for(frame = 0; frame < s->vm.frames; frame++)
635 s->mm.frame = frame;
636 if(ioctl(fd, VIDIOCMCAPTURE, &s->mm) < 0)
638 WARN("Error while requesting buffer %i to capture an image.", frame);
639 WARN("VIDIOCMCAPTURE: %s", strerror(errno));
640 src_v4l_free_mmap(src);
641 return(-1);
645 return(0);
648 int src_v4l_set_read(src_t *src)
650 src_v4l_t *s = (src_v4l_t *) src->state;
651 struct video_window vwin;
653 memset(&vwin, 0, sizeof(vwin));
654 vwin.width = src->width;
655 vwin.height = src->height;
656 if(ioctl(s->fd, VIDIOCSWIN, &vwin) == -1)
658 ERROR("Error setting %ix%i resolution.",
659 src->width, src->height);
662 /* Ugly!, but should always be large enough. */
663 s->buffer_length = src->width * src->height * 4;
664 s->buffer = malloc(s->buffer_length);
665 if(!s->buffer)
667 ERROR("Out of memory.");
668 src_close(src);
669 return(-1);
672 return(0);
675 int src_v4l_queue_buffers(src_t *src)
677 src_v4l_t *s = (src_v4l_t *) src->state;
678 int n;
680 /* Queue all buffers. */
681 for(n = 0; n < s->mjpeg_breq.count; n++)
683 if(ioctl(s->fd, MJPIOC_QBUF_CAPT, &n))
685 ERROR("Error queing buffer %i.", n);
686 ERROR("MJPIOC_QBUF_CAPT: %s", strerror(errno));
687 return(-1);
691 return(0);
694 int src_v4l_open(src_t *src)
696 src_v4l_t *s;
697 struct video_capability vd;
698 struct video_channel vc;
699 struct video_tuner vt;
701 if(!src->source)
703 ERROR("No device name specified.");
704 return(-2);
707 /* Allocate memory for state structure. */
708 s = (src_v4l_t *) calloc(sizeof(src_v4l_t), 1);
709 if(!s)
711 ERROR("Out of memory.");
712 return(-2);
715 src->state = (void *) s;
717 memset(&vd, 0, sizeof(vd));
718 memset(&vc, 0, sizeof(vc));
719 memset(&vt, 0, sizeof(vt));
721 /* Open the device. */
722 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
723 if(s->fd < 0)
725 ERROR("Error opening device: %s", src->source);
726 ERROR("open: %s", strerror(errno));
727 free(s);
728 return(-2);
731 MSG("%s opened.", src->source);
733 /* Get the device capabilities. */
734 if(src_v4l_get_capability(src, s->fd, &vd))
736 src_close(src);
737 return(-2);
740 /* Set the input. */
741 if(src_v4l_set_input(src, s->fd, &vd, &vc))
743 src_close(src);
744 return(-1);
747 if(vc.flags & VIDEO_VC_TUNER)
749 /* Set the tuner. */
750 if(src_v4l_set_tuner(src, s->fd, &vc, &vt))
752 src_close(src);
753 return(-1);
756 /* Set the frequency. */
757 if(src_v4l_set_frequency(src, s->fd, &vt))
759 src_close(src);
760 return(-1);
764 /* Set the picture options. */
765 if(src_v4l_set_picture(src, s->fd, &vd))
767 src_close(src);
768 return(-1);
771 /* Delay to let the image settle down. */
772 if(src->delay)
774 MSG("Delaying %i seconds.", src->delay);
775 usleep(src->delay * 1000 * 1000);
778 /* Setup the mmap. */
779 if(!src->use_read && src_v4l_set_mmap(src, s->fd))
781 WARN("Unable to use mmap. Using read instead.");
782 src->use_read = -1;
785 if(src->use_read && src_v4l_set_read(src))
787 src_close(src);
788 return(-1);
791 /* If this is an MJPEG device, queue the buffers. */
792 if(src->palette == SRC_PAL_JPEG && src_v4l_queue_buffers(src))
794 src_close(src);
795 return(-1);
798 s->frame = 0;
799 s->pframe = -1;
801 return(0);
804 int src_v4l_close(src_t *src)
806 src_v4l_t *s = (src_v4l_t *) src->state;
808 if(s->fd >= 0)
810 if(s->map) src_v4l_free_mmap(src);
811 close(s->fd);
812 MSG("%s closed.", src->source);
815 if(s->buffer) free(s->buffer);
816 free(s);
818 return(0);
821 int src_v4l_grab_mjpeg(src_t *src)
823 src_v4l_t *s = (src_v4l_t *) src->state;
825 /* Finished with the previous frame? */
826 if(s->pframe >= 0)
828 if(ioctl(s->fd, MJPIOC_QBUF_CAPT, &s->mjpeg_bsync.frame))
830 ERROR("Error queing buffer.");
831 ERROR("MJPIOC_QBUF_CAPT: %s", strerror(errno));
832 return(-1);
836 if(ioctl(s->fd, MJPIOC_SYNC, &s->mjpeg_bsync))
838 ERROR("Error sync'ing buffer.");
839 ERROR("MJPIOC_SYNC: %s", strerror(errno));
840 return(-1);
843 /* Deal with it! */
844 src->img = s->map + s->mjpeg_bsync.frame * s->mjpeg_breq.size;
845 src->length = s->mjpeg_bsync.length;
847 s->pframe++;
849 return(0);
852 int src_v4l_grab(src_t *src)
854 src_v4l_t *s = (src_v4l_t *) src->state;
856 /* MJPEG devices are handled differently. */
857 if(src->palette == SRC_PAL_JPEG) return(src_v4l_grab_mjpeg(src));
859 /* Wait for a frame. */
860 if(src->timeout)
862 fd_set fds;
863 struct timeval tv;
864 int r;
866 /* Is a frame ready? */
867 FD_ZERO(&fds);
868 FD_SET(s->fd, &fds);
870 tv.tv_sec = src->timeout;
871 tv.tv_usec = 0;
873 r = select(s->fd + 1, &fds, NULL, NULL, &tv);
875 if(r == -1)
877 ERROR("select: %s", strerror(errno));
878 return(-1);
881 if(!r)
883 ERROR("Timed out waiting for frame!");
884 return(-1);
888 /* If using mmap... */
889 if(s->map)
891 /* Finished with the previous frame? */
892 if(s->pframe >= 0)
894 s->mm.frame = s->pframe;
895 if(ioctl(s->fd, VIDIOCMCAPTURE, &s->mm) < 0)
897 ERROR("Error while requesting buffer %i to capture an image.", s->pframe);
898 ERROR("VIDEOCMCAPTURE: %s", strerror(errno));
899 return(-1);
903 /* Wait for the frame to be captured. */
904 if(ioctl(s->fd, VIDIOCSYNC, &s->frame) < 0)
906 WARN("Error synchronising with buffer %i.", s->frame);
907 WARN("VIDIOCSYNC: %s", strerror(errno));
908 return(-1);
911 /* Get the pointer to the current frame. */
912 src->img = s->map + s->vm.offsets[s->frame];
914 /* How big is the frame? */
915 if(s->frame == s->vm.frames - 1)
916 src->length = s->vm.size - s->vm.offsets[s->frame];
917 else
918 src->length = s->vm.offsets[s->frame + 1] -
919 s->vm.offsets[s->frame];
921 s->pframe = s->frame;
922 if(++s->frame == s->vm.frames) s->frame = 0;
924 else
926 ssize_t r = read(s->fd, s->buffer, s->buffer_length);
928 if(r <= 0)
930 WARN("Didn't read a frame.");
931 WARN("read: %s", strerror(errno));
932 return(-1);
935 src->img = s->buffer;
936 src->length = r;
939 return(0);
942 src_mod_t src_v4l1 = {
943 "v4l1", SRC_TYPE_DEVICE,
944 src_v4l_open,
945 src_v4l_close,
946 src_v4l_grab,
949 #else /* #ifdef HAVE_V4L1 */
951 src_mod_t src_v4l1 = {
952 "", SRC_TYPE_NONE,
953 NULL,
954 NULL,
955 NULL
958 #endif /* #ifdef HAVE_V4L1 */