1 /* fswebcam - FireStorm.cx's webcam generator */
2 /*============================================================*/
3 /* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
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. */
20 #include <sys/ioctl.h>
22 #include "videodev2.h"
37 struct v4l2_capability cap;
38 struct v4l2_format fmt;
39 struct v4l2_requestbuffers req;
40 struct v4l2_buffer buf;
42 v4l2_buffer_t *buffer;
48 static int src_v4l2_close(src_t *src);
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 },
76 int src_v4l2_get_capability(src_t *src)
78 src_v4l2_t *s = (src_v4l2_t *) src->state;
80 if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0)
82 /*ERROR("%s: Not a V4L2 device?", src->source);*/
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");*/
105 if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
107 /*ERROR("Device does not support capturing.");*/
114 int src_v4l2_set_input(src_t *src)
116 src_v4l2_t *s = (src_v4l2_t *) src->state;
117 struct v4l2_input input;
118 int count = 0, i = -1;
120 memset(&input, 0, sizeof(input));
122 if(src->list & SRC_LIST_INPUTS)
124 /*HEAD("--- Available inputs:");*/
127 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
129 /*MSG("%i: %s", count, input.name);*/
130 input.index = ++count;
134 /* If no input was specified, use input 0. */
137 /*MSG("No input was specified, using the first.");*/
142 /* Check if the input is specified by name. */
146 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
148 if(!strncasecmp((char *) input.name, src->input, 32))
150 input.index = ++count;
158 /* Is the input specified by number? */
159 i = strtol(src->input, &endptr, 10);
161 if(endptr == src->input) i = -1;
164 if(i == -1 || i >= count)
166 /* The specified input wasn't found! */
167 /*ERROR("Unrecognised input \"%s\"", src->input);*/
173 if(ioctl(s->fd, VIDIOC_ENUMINPUT, &input) == -1)
175 /*ERROR("Unable to query input %i.", i);
176 ERROR("VIDIOC_ENUMINPUT: %s", strerror(errno));*/
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");*/
200 if(ioctl(s->fd, VIDIOC_S_INPUT, &i) == -1)
202 /*ERROR("Error selecting input %i", i);
203 ERROR("VIDIOC_S_INPUT: %s", strerror(errno));*/
207 /* If this input is attached to a tuner, set the frequency. */
208 if(input.type & V4L2_INPUT_TYPE_TUNER)
211 struct v4l2_tuner tuner;
212 struct v4l2_frequency freq;
214 /* Query the tuners capabilities. */
216 memset(&tuner, 0, sizeof(tuner));
217 tuner.index = input.tuner;
219 if(ioctl(s->fd, VIDIOC_G_TUNER, &tuner) == -1)
221 /*WARN("Error querying tuner %i.", input.tuner);
222 WARN("VIDIOC_G_TUNER: %s", strerror(errno));*/
226 if(tuner.capability & V4L2_TUNER_CAP_LOW) range = "kHz";
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);*/
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;
252 if(ioctl(s->fd, VIDIOC_S_FREQUENCY, &freq) == -1)
254 /*WARN("Error setting frequency %.3f%s", src->frequency / 16.0, range);
255 WARN("VIDIOC_S_FREQUENCY: %s", strerror(errno));*/
259 /*MSG("Set frequency to %.3f%s",
260 (double) src->frequency / 1000, range);*/
266 int src_v4l2_show_control(src_t *src, struct v4l2_queryctrl *queryctrl)
268 src_v4l2_t *s = (src_v4l2_t *) src->state;
269 struct v4l2_querymenu querymenu;
270 struct v4l2_control control;
274 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
276 memset(&querymenu, 0, sizeof(querymenu));
277 memset(&control, 0, sizeof(control));
279 if(queryctrl->type != V4L2_CTRL_TYPE_BUTTON)
281 control.id = queryctrl->id;
282 if(ioctl(s->fd, VIDIOC_G_CTRL, &control))
284 /*ERROR("Error reading value of control '%s'.", queryctrl->name);
285 ERROR("VIDIOC_G_CTRL: %s", strerror(errno));*/
289 switch(queryctrl->type)
291 case V4L2_CTRL_TYPE_INTEGER:
293 t = malloc(64); /* Ick ... TODO: re-write this. */
296 /*ERROR("Out of memory.");*/
300 if(queryctrl->maximum - queryctrl->minimum <= 10)
302 snprintf(t, 63, "%i", control.value);
306 snprintf(t, 63, "%i (%i%%)",
314 /*MSG("%-25s %-15s %i - %i", queryctrl->name, t,
315 queryctrl->minimum, queryctrl->maximum);*/
321 case V4L2_CTRL_TYPE_BOOLEAN:
322 /*MSG("%-25s %-15s True | False", queryctrl->name,
323 (control.value ? "True" : "False"));*/
326 case V4L2_CTRL_TYPE_MENU:
328 querymenu.id = queryctrl->id;
330 t = calloc((queryctrl->maximum - queryctrl->minimum) + 1, 34);
331 m = queryctrl->minimum;
332 for(m = queryctrl->minimum; m <= queryctrl->maximum; m++)
335 if(!ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
337 strncat(t, (char *) querymenu.name, 32);
338 if(m < queryctrl->maximum) strncat(t, " | ", 3);
342 querymenu.index = control.value;
343 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
346 /*ERROR("Error reading value of menu item %i for control '%s'",
347 control.value, queryctrl->name);
348 ERROR("VIDIOC_QUERYMENU: %s", strerror(errno));*/
352 /*MSG("%-25s %-15s %s", queryctrl->name, querymenu.name, t);*/
357 case V4L2_CTRL_TYPE_BUTTON:
358 /*MSG("%-25s %-15s %s", queryctrl->name, "-", "[Button]");*/
362 /*MSG("%-25s %-15s %s", queryctrl->name, "N/A", "[Unknown Control Type]");*/
369 int src_v4l2_set_control(src_t *src, struct v4l2_queryctrl *queryctrl)
371 src_v4l2_t *s = (src_v4l2_t *) src->state;
372 struct v4l2_control control;
373 struct v4l2_querymenu querymenu;
377 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
378 if(src_get_option_by_name(src->option, (char *) queryctrl->name, &sv))
381 memset(&querymenu, 0, sizeof(querymenu));
382 memset(&control, 0, sizeof(control));
384 control.id = queryctrl->id;
386 switch(queryctrl->type)
388 case V4L2_CTRL_TYPE_INTEGER:
390 /* Convert the value to an integer. */
393 /* Is the value a precentage? */
396 /* Adjust the precentage to fit the controls range. */
397 iv = SCALE(queryctrl->minimum, queryctrl->maximum,
401 /*MSG("Setting %s to %i (%i%%).", queryctrl->name, iv,
402 SCALE(0, 100, queryctrl->minimum, queryctrl->maximum, iv));*/
404 /*if(iv < queryctrl->minimum || iv > queryctrl->maximum)
405 WARN("Value is out of range. Setting anyway.");*/
408 ioctl(s->fd, VIDIOC_S_CTRL, &control);
411 case V4L2_CTRL_TYPE_BOOLEAN:
414 if(!strcasecmp(sv, "1") || !strcasecmp(sv, "true")) iv = 1;
415 if(!strcasecmp(sv, "0") || !strcasecmp(sv, "false")) iv = 0;
419 /*WARN("Unknown boolean value '%s' for %s.",
420 sv, queryctrl->name);*/
424 /*MSG("Setting %s to %s (%i).", queryctrl->name, sv, iv);*/
427 ioctl(s->fd, VIDIOC_S_CTRL, &control);
431 case V4L2_CTRL_TYPE_MENU:
433 /* Scan for a matching value. */
434 querymenu.id = queryctrl->id;
436 for(iv = queryctrl->minimum; iv <= queryctrl->maximum; iv++)
438 querymenu.index = iv;
440 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
442 /*ERROR("Error querying menu.");*/
446 if(!strncasecmp((char *) querymenu.name, sv, 32))
450 if(iv > queryctrl->maximum)
452 /*MSG("Unknown value '%s' for %s.", sv, queryctrl->name);*/
456 /*MSG("Setting %s to %s (%i).",
457 queryctrl->name, querymenu.name, iv);*/
460 ioctl(s->fd, VIDIOC_S_CTRL, &control);
464 case V4L2_CTRL_TYPE_BUTTON:
466 /*MSG("Triggering %s control.", queryctrl->name);
467 ioctl(s->fd, VIDIOC_S_CTRL, &control);*/
472 /*WARN("Not setting unknown control type %i (%s).",
480 int src_v4l2_set_controls(src_t *src)
482 src_v4l2_t *s = (src_v4l2_t *) src->state;
483 struct v4l2_queryctrl queryctrl;
486 memset(&queryctrl, 0, sizeof(queryctrl));
488 if(src->list & SRC_LIST_CONTROLS)
490 /*HEAD("%-25s %-15s %s", "Available Controls", "Current Value", "Range");
491 MSG("%-25s %-15s %s", "------------------", "-------------", "-----");*/
493 /* Display normal controls. */
494 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
498 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
499 src_v4l2_show_control(src, &queryctrl);
502 /* Display device-specific controls. */
503 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
507 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
508 src_v4l2_show_control(src, &queryctrl);
512 /* Scan normal controls. */
513 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
517 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
518 src_v4l2_set_control(src, &queryctrl);
521 /* Scan device-specific controls. */
522 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
526 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
527 src_v4l2_set_control(src, &queryctrl);
533 int src_v4l2_set_pix_format(src_t *src)
535 src_v4l2_t *s = (src_v4l2_t *) src->state;
536 struct v4l2_fmtdesc fmt;
539 /* Dump a list of formats the device supports. */
540 /*DEBUG("Device offers the following V4L2 pixel formats:");*/
543 memset(&fmt, 0, sizeof(fmt));
544 fmt.index = v4l2_pal;
545 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
547 while(ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
549 /*DEBUG("%i: [0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
551 fmt.pixelformat >> 0, fmt.pixelformat >> 8,
552 fmt.pixelformat >> 16, fmt.pixelformat >> 24,
555 memset(&fmt, 0, sizeof(fmt));
556 fmt.index = ++v4l2_pal;
557 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
560 /* Step through each palette type. */
563 if(src->palette != -1)
565 while(v4l2_palette[v4l2_pal].v4l2)
567 if(v4l2_palette[v4l2_pal].src == src->palette) break;
571 if(!v4l2_palette[v4l2_pal].v4l2)
573 /*ERROR("Unable to handle palette format %s.",
574 src_palette[src->palette]);*/
580 while(v4l2_palette[v4l2_pal].v4l2)
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;
590 if(ioctl(s->fd, VIDIOC_TRY_FMT, &s->fmt) != -1 &&
591 s->fmt.fmt.pix.pixelformat == v4l2_palette[v4l2_pal].v4l2)
593 src->palette = v4l2_palette[v4l2_pal].src;
595 /*INFO("Using palette %s", src_palette[src->palette].name);*/
597 if(s->fmt.fmt.pix.width != src->width ||
598 s->fmt.fmt.pix.height != src->height)
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;
608 if(ioctl(s->fd, VIDIOC_S_FMT, &s->fmt) == -1)
610 /*ERROR("Error setting pixel format.");
611 ERROR("VIDIOC_S_FMT: %s", strerror(errno));*/
615 if(v4l2_palette[v4l2_pal].v4l2 == V4L2_PIX_FMT_MJPEG)
617 struct v4l2_jpegcompression jpegcomp;
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);
628 if(src->palette != -1) break;
633 /*ERROR("Unable to find a compatible palette format.");*/
638 int src_v4l2_set_fps(src_t *src)
640 src_v4l2_t *s = (src_v4l2_t *) src->state;
641 struct v4l2_streamparm setfps;
643 memset(&setfps, 0, sizeof(setfps));
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)
650 /* Not fatal - just warn about it */
651 /*WARN("Error setting frame rate:");
652 WARN("VIDIOC_S_PARM: %s", strerror(errno));*/
659 int src_v4l2_free_mmap(src_t *src)
661 src_v4l2_t *s = (src_v4l2_t *) src->state;
664 for(i = 0; i < s->req.count; i++)
665 munmap(s->buffer[i].start, s->buffer[i].length);
670 int src_v4l2_set_mmap(src_t *src)
672 src_v4l2_t *s = (src_v4l2_t *) src->state;
673 enum v4l2_buf_type type;
676 /* Does the device support streaming? */
677 if(~s->cap.capabilities & V4L2_CAP_STREAMING) return(-1);
679 memset(&s->req, 0, sizeof(s->req));
682 s->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
683 s->req.memory = V4L2_MEMORY_MMAP;
685 if(ioctl(s->fd, VIDIOC_REQBUFS, &s->req) == -1)
687 /*ERROR("Error requesting buffers for memory map.");
688 ERROR("VIDIOC_REQBUFS: %s", strerror(errno));*/
692 /*DEBUG("mmap information:");
693 DEBUG("frames=%d", s->req.count);*/
697 /*ERROR("Insufficient buffer memory.");*/
701 s->buffer = calloc(s->req.count, sizeof(v4l2_buffer_t));
704 /*ERROR("Out of memory.");*/
708 for(b = 0; b < s->req.count; b++)
710 struct v4l2_buffer buf;
712 memset(&buf, 0, sizeof(buf));
714 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
715 buf.memory = V4L2_MEMORY_MMAP;
718 if(ioctl(s->fd, VIDIOC_QUERYBUF, &buf) == -1)
720 /*ERROR("Error querying buffer %i", b);
721 ERROR("VIDIOC_QUERYBUF: %s", strerror(errno));*/
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);
730 if(s->buffer[b].start == MAP_FAILED)
732 /*ERROR("Error mapping buffer %i", b);
733 ERROR("mmap: %s", strerror(errno));*/
735 src_v4l2_free_mmap(src);
740 /*DEBUG("%i length=%d", b, buf.length);*/
745 for(b = 0; b < s->req.count; b++)
747 memset(&s->buf, 0, sizeof(s->buf));
749 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
750 s->buf.memory = V4L2_MEMORY_MMAP;
753 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
755 /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
756 src_v4l2_free_mmap(src);
762 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
764 if(ioctl(s->fd, VIDIOC_STREAMON, &type) == -1)
766 /*ERROR("Error starting stream.");
767 ERROR("VIDIOC_STREAMON: %s", strerror(errno));*/
768 src_v4l2_free_mmap(src);
776 int src_v4l2_set_read(src_t *src)
778 src_v4l2_t *s = (src_v4l2_t *) src->state;
780 if(~s->cap.capabilities & V4L2_CAP_READWRITE) return(-1);
782 s->buffer = calloc(1, sizeof(v4l2_buffer_t));
785 /*ERROR("Out of memory.");*/
789 s->buffer[0].length = s->fmt.fmt.pix.sizeimage;
790 s->buffer[0].start = malloc(s->buffer[0].length);
792 if(!s->buffer[0].start)
794 /*ERROR("Out of memory.");*/
805 static const char *src_v4l2_query(src_t *src, uint *width, uint *height, char **pixelformatdescription)
809 /*ERROR("No device name specified.");*/
810 fprintf(stderr, "No device name specified.");
815 /* Allocate memory for the state structure. */
816 s = calloc(sizeof(src_v4l2_t), 1);
819 fprintf(stderr, "Out of memory.");
823 src->state = (void *) s;
825 /* Open the device. */
826 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
829 fprintf(stderr, "Cannot open device.");
834 if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
836 fprintf(stderr, "Cannot get capabilities.");
839 char *res = strdup((char*) s->cap.card);
840 /*strcpy(res, (char*) s->cap.card);*/
841 if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
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.");
853 *width = format.fmt.pix.width;
854 *height = format.fmt.pix.height;
856 struct v4l2_fmtdesc fmt;
857 memset(&fmt,0,sizeof(fmt));
859 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
860 if (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
862 /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
863 *pixelformatdescription = strdup((char*)fmt.description);
864 fprintf(stderr, "format: %s", fmt.description);
867 *pixelformatdescription = '\0';
874 static int src_v4l2_open(src_t *src)
880 /*ERROR("No device name specified.");*/
884 /* Allocate memory for the state structure. */
885 s = calloc(sizeof(src_v4l2_t), 1);
888 /*ERROR("Out of memory.");*/
892 src->state = (void *) s;
894 /* Open the device. */
895 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
898 /*ERROR("Error opening device: %s", src->source);
899 ERROR("open: %s", strerror(errno));*/
904 /*MSG("%s opened.", src->source);*/
906 /* Get the device capabilities. */
907 if(src_v4l2_get_capability(src))
914 if(src_v4l2_set_input(src))
920 /* Set picture options. */
921 src_v4l2_set_controls(src);
923 /* Set the pixel format. */
924 if(src_v4l2_set_pix_format(src))
930 /* Set the frame-rate if > 0 */
931 if(src->fps) src_v4l2_set_fps(src);
933 /* Delay to let the image settle down. */
936 /*MSG("Delaying %i seconds.", src->delay);*/
937 usleep(src->delay * 1000 * 1000);
940 /* Try to setup mmap. */
941 if(!src->use_read && src_v4l2_set_mmap(src))
943 /*WARN("Unable to use mmap. Using read instead.");*/
947 /* If unable to use mmap or user requested read(). */
950 if(src_v4l2_set_read(src))
952 /*ERROR("Unable to use read.");*/
963 static int src_v4l2_close(src_t *src)
965 src_v4l2_t *s = (src_v4l2_t *) src->state;
969 if(!s->map) free(s->buffer[0].start);
970 else src_v4l2_free_mmap(src);
973 if(s->fd >= 0) close(s->fd);
979 static int src_v4l2_grab(src_t *src)
981 src_v4l2_t *s = (src_v4l2_t *) src->state;
989 /* Is a frame ready? */
993 tv.tv_sec = src->timeout;
996 r = select(s->fd + 1, &fds, NULL, NULL, &tv);
1000 /*ERROR("select: %s", strerror(errno));*/
1006 /*ERROR("Timed out waiting for frame!");*/
1015 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
1017 /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
1022 memset(&s->buf, 0, sizeof(s->buf));
1024 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1025 s->buf.memory = V4L2_MEMORY_MMAP;
1027 if(ioctl(s->fd, VIDIOC_DQBUF, &s->buf) == -1)
1029 /*ERROR("VIDIOC_DQBUF: %s", strerror(errno));*/
1033 src->img = s->buffer[s->buf.index].start;
1034 src->length = s->buffer[s->buf.index].length;
1036 s->pframe = s->buf.index;
1042 r = read(s->fd, s->buffer[0].start, s->buffer[0].length);
1045 /*ERROR("Unable to read a frame.");
1046 ERROR("read: %s", strerror(errno));*/
1050 src->img = s->buffer[0].start;
1057 src_mod_t src_v4l2 = {
1058 "v4l2", SRC_TYPE_DEVICE,
1065 #else /* #ifdef HAVE_V4L2 */
1067 src_mod_t src_v4l2 = {
1075 #endif /* #ifdef HAVE_V4L2 */