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"
27 int src_v4l2_get_capability(src_t *src)
29 src_v4l2_t *s = (src_v4l2_t *) src->state;
31 if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0)
33 /*ERROR("%s: Not a V4L2 device?", src->source);*/
36 fprintf(stderr, "cap.card: \"%s\"", s->cap.card);
37 /*DEBUG("%s information:", src->source);
38 DEBUG("cap.driver: \"%s\"", s->cap.driver);
39 DEBUG("cap.card: \"%s\"", s->cap.card);
40 DEBUG("cap.bus_info: \"%s\"", s->cap.bus_info);
41 DEBUG("cap.capabilities=0x%08X", s->cap.capabilities);*/
42 /*if(s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) DEBUG("- VIDEO_CAPTURE");
43 if(s->cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) DEBUG("- VIDEO_OUTPUT");
44 if(s->cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) DEBUG("- VIDEO_OVERLAY");
45 if(s->cap.capabilities & V4L2_CAP_VBI_CAPTURE) DEBUG("- VBI_CAPTURE");
46 if(s->cap.capabilities & V4L2_CAP_VBI_OUTPUT) DEBUG("- VBI_OUTPUT");
47 if(s->cap.capabilities & V4L2_CAP_RDS_CAPTURE) DEBUG("- RDS_CAPTURE");
48 if(s->cap.capabilities & V4L2_CAP_TUNER) DEBUG("- TUNER");
49 if(s->cap.capabilities & V4L2_CAP_AUDIO) DEBUG("- AUDIO");
50 if(s->cap.capabilities & V4L2_CAP_RADIO) DEBUG("- RADIO");
51 if(s->cap.capabilities & V4L2_CAP_READWRITE) DEBUG("- READWRITE");
52 if(s->cap.capabilities & V4L2_CAP_ASYNCIO) DEBUG("- ASYNCIO");
53 if(s->cap.capabilities & V4L2_CAP_STREAMING) DEBUG("- STREAMING");
54 if(s->cap.capabilities & V4L2_CAP_TIMEPERFRAME) DEBUG("- TIMEPERFRAME");*/
56 if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
58 /*ERROR("Device does not support capturing.");*/
65 int src_v4l2_set_input(src_t *src)
67 src_v4l2_t *s = (src_v4l2_t *) src->state;
68 struct v4l2_input input;
69 int count = 0, i = -1;
71 memset(&input, 0, sizeof(input));
73 if(src->list & SRC_LIST_INPUTS)
75 /*HEAD("--- Available inputs:");*/
78 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
80 /*MSG("%i: %s", count, input.name);*/
81 input.index = ++count;
85 /* If no input was specified, use input 0. */
88 /*MSG("No input was specified, using the first.");*/
93 /* Check if the input is specified by name. */
97 while(!ioctl(s->fd, VIDIOC_ENUMINPUT, &input))
99 if(!strncasecmp((char *) input.name, src->input, 32))
101 input.index = ++count;
109 /* Is the input specified by number? */
110 i = strtol(src->input, &endptr, 10);
112 if(endptr == src->input) i = -1;
115 if(i == -1 || i >= count)
117 /* The specified input wasn't found! */
118 /*ERROR("Unrecognised input \"%s\"", src->input);*/
124 if(ioctl(s->fd, VIDIOC_ENUMINPUT, &input) == -1)
126 /*ERROR("Unable to query input %i.", i);
127 ERROR("VIDIOC_ENUMINPUT: %s", strerror(errno));*/
131 /*DEBUG("%s: Input %i information:", src->source, i);
132 DEBUG("name = \"%s\"", input.name);
133 DEBUG("type = %08X", input.type);
134 if(input.type & V4L2_INPUT_TYPE_TUNER) DEBUG("- TUNER");
135 if(input.type & V4L2_INPUT_TYPE_CAMERA) DEBUG("- CAMERA");
136 DEBUG("audioset = %08X", input.audioset);
137 DEBUG("tuner = %08X", input.tuner);
138 DEBUG("status = %08X", input.status);
139 if(input.status & V4L2_IN_ST_NO_POWER) DEBUG("- NO_POWER");
140 if(input.status & V4L2_IN_ST_NO_SIGNAL) DEBUG("- NO_SIGNAL");
141 if(input.status & V4L2_IN_ST_NO_COLOR) DEBUG("- NO_COLOR");
142 if(input.status & V4L2_IN_ST_NO_H_LOCK) DEBUG("- NO_H_LOCK");
143 if(input.status & V4L2_IN_ST_COLOR_KILL) DEBUG("- COLOR_KILL");
144 if(input.status & V4L2_IN_ST_NO_SYNC) DEBUG("- NO_SYNC");
145 if(input.status & V4L2_IN_ST_NO_EQU) DEBUG("- NO_EQU");
146 if(input.status & V4L2_IN_ST_NO_CARRIER) DEBUG("- NO_CARRIER");
147 if(input.status & V4L2_IN_ST_MACROVISION) DEBUG("- MACROVISION");
148 if(input.status & V4L2_IN_ST_NO_ACCESS) DEBUG("- NO_ACCESS");
149 if(input.status & V4L2_IN_ST_VTR) DEBUG("- VTR");*/
151 if(ioctl(s->fd, VIDIOC_S_INPUT, &i) == -1)
153 /*ERROR("Error selecting input %i", i);
154 ERROR("VIDIOC_S_INPUT: %s", strerror(errno));*/
158 /* If this input is attached to a tuner, set the frequency. */
159 if(input.type & V4L2_INPUT_TYPE_TUNER)
162 struct v4l2_tuner tuner;
163 struct v4l2_frequency freq;
165 /* Query the tuners capabilities. */
167 memset(&tuner, 0, sizeof(tuner));
168 tuner.index = input.tuner;
170 if(ioctl(s->fd, VIDIOC_G_TUNER, &tuner) == -1)
172 /*WARN("Error querying tuner %i.", input.tuner);
173 WARN("VIDIOC_G_TUNER: %s", strerror(errno));*/
177 if(tuner.capability & V4L2_TUNER_CAP_LOW) range = "kHz";
180 /*DEBUG("%s: Tuner %i information:", src->source, input.tuner);
181 DEBUG("name = \"%s\"", tuner.name);
182 DEBUG("type = %08X", tuner.type);
183 if(tuner.type == V4L2_TUNER_RADIO) DEBUG("- RADIO");
184 if(tuner.type == V4L2_TUNER_ANALOG_TV) DEBUG("- ANALOG_TV");
185 DEBUG("capability = %08X", tuner.capability);
186 if(tuner.capability & V4L2_TUNER_CAP_LOW) DEBUG("- LOW");
187 if(tuner.capability & V4L2_TUNER_CAP_NORM) DEBUG("- NORM");
188 if(tuner.capability & V4L2_TUNER_CAP_STEREO) DEBUG("- STEREO");
189 if(tuner.capability & V4L2_TUNER_CAP_LANG1) DEBUG("- LANG1");
190 if(tuner.capability & V4L2_TUNER_CAP_LANG2) DEBUG("- LANG2");
191 if(tuner.capability & V4L2_TUNER_CAP_SAP) DEBUG("- SAP");
192 DEBUG("rangelow = %08X, (%.3f%s)", tuner.rangelow, (double) tuner.rangelow * 16 / 1000, range);
193 DEBUG("rangehigh = %08X, (%.3f%s)", tuner.rangehigh, (double) tuner.rangehigh * 16 / 1000, range);
194 DEBUG("signal = %08X", tuner.signal);
195 DEBUG("afc = %08X", tuner.afc);*/
197 /* Set the frequency. */
198 memset(&freq, 0, sizeof(freq));
199 freq.tuner = input.tuner;
200 freq.type = V4L2_TUNER_ANALOG_TV;
201 freq.frequency = (src->frequency / 1000) * 16;
203 if(ioctl(s->fd, VIDIOC_S_FREQUENCY, &freq) == -1)
205 /*WARN("Error setting frequency %.3f%s", src->frequency / 16.0, range);
206 WARN("VIDIOC_S_FREQUENCY: %s", strerror(errno));*/
210 /*MSG("Set frequency to %.3f%s",
211 (double) src->frequency / 1000, range);*/
217 int src_v4l2_show_control(src_t *src, struct v4l2_queryctrl *queryctrl)
219 src_v4l2_t *s = (src_v4l2_t *) src->state;
220 struct v4l2_querymenu querymenu;
221 struct v4l2_control control;
225 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
227 memset(&querymenu, 0, sizeof(querymenu));
228 memset(&control, 0, sizeof(control));
230 if(queryctrl->type != V4L2_CTRL_TYPE_BUTTON)
232 control.id = queryctrl->id;
233 if(ioctl(s->fd, VIDIOC_G_CTRL, &control))
235 /*ERROR("Error reading value of control '%s'.", queryctrl->name);
236 ERROR("VIDIOC_G_CTRL: %s", strerror(errno));*/
240 switch(queryctrl->type)
242 case V4L2_CTRL_TYPE_INTEGER:
244 t = malloc(64); /* Ick ... TODO: re-write this. */
247 /*ERROR("Out of memory.");*/
251 if(queryctrl->maximum - queryctrl->minimum <= 10)
253 snprintf(t, 63, "%i", control.value);
257 snprintf(t, 63, "%i (%i%%)",
265 /*MSG("%-25s %-15s %i - %i", queryctrl->name, t,
266 queryctrl->minimum, queryctrl->maximum);*/
272 case V4L2_CTRL_TYPE_BOOLEAN:
273 /*MSG("%-25s %-15s True | False", queryctrl->name,
274 (control.value ? "True" : "False"));*/
277 case V4L2_CTRL_TYPE_MENU:
279 querymenu.id = queryctrl->id;
281 t = calloc((queryctrl->maximum - queryctrl->minimum) + 1, 34);
282 m = queryctrl->minimum;
283 for(m = queryctrl->minimum; m <= queryctrl->maximum; m++)
286 if(!ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
288 strncat(t, (char *) querymenu.name, 32);
289 if(m < queryctrl->maximum) strncat(t, " | ", 3);
293 querymenu.index = control.value;
294 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
297 /*ERROR("Error reading value of menu item %i for control '%s'",
298 control.value, queryctrl->name);
299 ERROR("VIDIOC_QUERYMENU: %s", strerror(errno));*/
303 /*MSG("%-25s %-15s %s", queryctrl->name, querymenu.name, t);*/
308 case V4L2_CTRL_TYPE_BUTTON:
309 /*MSG("%-25s %-15s %s", queryctrl->name, "-", "[Button]");*/
313 /*MSG("%-25s %-15s %s", queryctrl->name, "N/A", "[Unknown Control Type]");*/
320 int src_v4l2_set_control(src_t *src, struct v4l2_queryctrl *queryctrl)
322 src_v4l2_t *s = (src_v4l2_t *) src->state;
323 struct v4l2_control control;
324 struct v4l2_querymenu querymenu;
328 if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0);
329 if(src_get_option_by_name(src->option, (char *) queryctrl->name, &sv))
332 memset(&querymenu, 0, sizeof(querymenu));
333 memset(&control, 0, sizeof(control));
335 control.id = queryctrl->id;
337 switch(queryctrl->type)
339 case V4L2_CTRL_TYPE_INTEGER:
341 /* Convert the value to an integer. */
344 /* Is the value a precentage? */
347 /* Adjust the precentage to fit the controls range. */
348 iv = SCALE(queryctrl->minimum, queryctrl->maximum,
352 /*MSG("Setting %s to %i (%i%%).", queryctrl->name, iv,
353 SCALE(0, 100, queryctrl->minimum, queryctrl->maximum, iv));*/
355 /*if(iv < queryctrl->minimum || iv > queryctrl->maximum)
356 WARN("Value is out of range. Setting anyway.");*/
359 ioctl(s->fd, VIDIOC_S_CTRL, &control);
362 case V4L2_CTRL_TYPE_BOOLEAN:
365 if(!strcasecmp(sv, "1") || !strcasecmp(sv, "true")) iv = 1;
366 if(!strcasecmp(sv, "0") || !strcasecmp(sv, "false")) iv = 0;
370 /*WARN("Unknown boolean value '%s' for %s.",
371 sv, queryctrl->name);*/
375 /*MSG("Setting %s to %s (%i).", queryctrl->name, sv, iv);*/
378 ioctl(s->fd, VIDIOC_S_CTRL, &control);
382 case V4L2_CTRL_TYPE_MENU:
384 /* Scan for a matching value. */
385 querymenu.id = queryctrl->id;
387 for(iv = queryctrl->minimum; iv <= queryctrl->maximum; iv++)
389 querymenu.index = iv;
391 if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu))
393 /*ERROR("Error querying menu.");*/
397 if(!strncasecmp((char *) querymenu.name, sv, 32))
401 if(iv > queryctrl->maximum)
403 /*MSG("Unknown value '%s' for %s.", sv, queryctrl->name);*/
407 /*MSG("Setting %s to %s (%i).",
408 queryctrl->name, querymenu.name, iv);*/
411 ioctl(s->fd, VIDIOC_S_CTRL, &control);
415 case V4L2_CTRL_TYPE_BUTTON:
417 /*MSG("Triggering %s control.", queryctrl->name);
418 ioctl(s->fd, VIDIOC_S_CTRL, &control);*/
423 /*WARN("Not setting unknown control type %i (%s).",
431 int src_v4l2_set_controls(src_t *src)
433 src_v4l2_t *s = (src_v4l2_t *) src->state;
434 struct v4l2_queryctrl queryctrl;
437 memset(&queryctrl, 0, sizeof(queryctrl));
439 if(src->list & SRC_LIST_CONTROLS)
441 /*HEAD("%-25s %-15s %s", "Available Controls", "Current Value", "Range");
442 MSG("%-25s %-15s %s", "------------------", "-------------", "-----");*/
444 /* Display normal controls. */
445 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
449 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
450 src_v4l2_show_control(src, &queryctrl);
453 /* Display device-specific controls. */
454 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
458 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
459 src_v4l2_show_control(src, &queryctrl);
463 /* Scan normal controls. */
464 for(c = V4L2_CID_BASE; c < V4L2_CID_LASTP1; c++)
468 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) continue;
469 src_v4l2_set_control(src, &queryctrl);
472 /* Scan device-specific controls. */
473 for(c = V4L2_CID_PRIVATE_BASE; ; c++)
477 if(ioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl)) break;
478 src_v4l2_set_control(src, &queryctrl);
484 int src_v4l2_set_pix_format(src_t *src)
486 src_v4l2_t *s = (src_v4l2_t *) src->state;
487 struct v4l2_fmtdesc fmt;
490 /* Dump a list of formats the device supports. */
491 /*DEBUG("Device offers the following V4L2 pixel formats:");*/
494 memset(&fmt, 0, sizeof(fmt));
495 fmt.index = v4l2_pal;
496 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
498 while(ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
500 /*DEBUG("%i: [0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
502 fmt.pixelformat >> 0, fmt.pixelformat >> 8,
503 fmt.pixelformat >> 16, fmt.pixelformat >> 24,
506 memset(&fmt, 0, sizeof(fmt));
507 fmt.index = ++v4l2_pal;
508 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
511 /* Step through each palette type. */
514 if(src->palette != -1)
516 while(v4l2_palette[v4l2_pal].v4l2)
518 if(v4l2_palette[v4l2_pal].src == src->palette) break;
522 if(!v4l2_palette[v4l2_pal].v4l2)
524 /*ERROR("Unable to handle palette format %s.",
525 src_palette[src->palette]);*/
531 while(v4l2_palette[v4l2_pal].v4l2)
533 /* Try the palette... */
534 memset(&s->fmt, 0, sizeof(s->fmt));
535 s->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
536 s->fmt.fmt.pix.width = src->width;
537 s->fmt.fmt.pix.height = src->height;
538 s->fmt.fmt.pix.pixelformat = v4l2_palette[v4l2_pal].v4l2;
539 s->fmt.fmt.pix.field = V4L2_FIELD_ANY;
541 if(ioctl(s->fd, VIDIOC_TRY_FMT, &s->fmt) != -1 &&
542 s->fmt.fmt.pix.pixelformat == v4l2_palette[v4l2_pal].v4l2)
544 src->palette = v4l2_palette[v4l2_pal].src;
546 /*INFO("Using palette %s", src_palette[src->palette].name);*/
548 if(s->fmt.fmt.pix.width != src->width ||
549 s->fmt.fmt.pix.height != src->height)
551 /*MSG("Adjusting resolution from %ix%i to %ix%i.",
552 src->width, src->height,
553 s->fmt.fmt.pix.width,
554 s->fmt.fmt.pix.height);*/
555 src->width = s->fmt.fmt.pix.width;
556 src->height = s->fmt.fmt.pix.height;
559 if(ioctl(s->fd, VIDIOC_S_FMT, &s->fmt) == -1)
561 /*ERROR("Error setting pixel format.");
562 ERROR("VIDIOC_S_FMT: %s", strerror(errno));*/
566 if(v4l2_palette[v4l2_pal].v4l2 == V4L2_PIX_FMT_MJPEG)
568 struct v4l2_jpegcompression jpegcomp;
570 memset(&jpegcomp, 0, sizeof(jpegcomp));
571 ioctl(s->fd, VIDIOC_G_JPEGCOMP, &jpegcomp);
572 jpegcomp.jpeg_markers |= V4L2_JPEG_MARKER_DHT;
573 ioctl(s->fd, VIDIOC_S_JPEGCOMP, &jpegcomp);
579 if(src->palette != -1) break;
584 /*ERROR("Unable to find a compatible palette format.");*/
589 int src_v4l2_set_fps(src_t *src)
591 src_v4l2_t *s = (src_v4l2_t *) src->state;
592 struct v4l2_streamparm setfps;
594 memset(&setfps, 0, sizeof(setfps));
596 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
597 setfps.parm.capture.timeperframe.numerator = 1;
598 setfps.parm.capture.timeperframe.denominator = src->fps;
599 if(ioctl(s->fd, VIDIOC_S_PARM, setfps) == -1)
601 /* Not fatal - just warn about it */
602 /*WARN("Error setting frame rate:");
603 WARN("VIDIOC_S_PARM: %s", strerror(errno));*/
610 int src_v4l2_free_mmap(src_t *src)
612 src_v4l2_t *s = (src_v4l2_t *) src->state;
615 for(i = 0; i < s->req.count; i++)
616 munmap(s->buffer[i].start, s->buffer[i].length);
621 int src_v4l2_set_mmap(src_t *src)
623 src_v4l2_t *s = (src_v4l2_t *) src->state;
624 enum v4l2_buf_type type;
627 /* Does the device support streaming? */
628 if(~s->cap.capabilities & V4L2_CAP_STREAMING) return(-1);
630 memset(&s->req, 0, sizeof(s->req));
633 s->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
634 s->req.memory = V4L2_MEMORY_MMAP;
636 if(ioctl(s->fd, VIDIOC_REQBUFS, &s->req) == -1)
638 /*ERROR("Error requesting buffers for memory map.");
639 ERROR("VIDIOC_REQBUFS: %s", strerror(errno));*/
643 /*DEBUG("mmap information:");
644 DEBUG("frames=%d", s->req.count);*/
648 /*ERROR("Insufficient buffer memory.");*/
652 s->buffer = calloc(s->req.count, sizeof(v4l2_buffer_t));
655 /*ERROR("Out of memory.");*/
659 for(b = 0; b < s->req.count; b++)
661 struct v4l2_buffer buf;
663 memset(&buf, 0, sizeof(buf));
665 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
666 buf.memory = V4L2_MEMORY_MMAP;
669 if(ioctl(s->fd, VIDIOC_QUERYBUF, &buf) == -1)
671 /*ERROR("Error querying buffer %i", b);
672 ERROR("VIDIOC_QUERYBUF: %s", strerror(errno));*/
677 s->buffer[b].length = buf.length;
678 s->buffer[b].start = mmap(NULL, buf.length,
679 PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
681 if(s->buffer[b].start == MAP_FAILED)
683 /*ERROR("Error mapping buffer %i", b);
684 ERROR("mmap: %s", strerror(errno));*/
686 src_v4l2_free_mmap(src);
691 /*DEBUG("%i length=%d", b, buf.length);*/
696 for(b = 0; b < s->req.count; b++)
698 memset(&s->buf, 0, sizeof(s->buf));
700 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
701 s->buf.memory = V4L2_MEMORY_MMAP;
704 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
706 /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
707 src_v4l2_free_mmap(src);
713 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
715 if(ioctl(s->fd, VIDIOC_STREAMON, &type) == -1)
717 /*ERROR("Error starting stream.");
718 ERROR("VIDIOC_STREAMON: %s", strerror(errno));*/
719 src_v4l2_free_mmap(src);
727 int src_v4l2_set_read(src_t *src)
729 src_v4l2_t *s = (src_v4l2_t *) src->state;
731 if(~s->cap.capabilities & V4L2_CAP_READWRITE) return(-1);
733 s->buffer = calloc(1, sizeof(v4l2_buffer_t));
736 /*ERROR("Out of memory.");*/
740 s->buffer[0].length = s->fmt.fmt.pix.sizeimage;
741 s->buffer[0].start = malloc(s->buffer[0].length);
743 if(!s->buffer[0].start)
745 /*ERROR("Out of memory.");*/
756 static const char *src_v4l2_query(src_t *src, uint *width, uint *height, char **pixelformatdescription)
760 /*ERROR("No device name specified.");*/
761 fprintf(stderr, "No device name specified.");
766 /* Allocate memory for the state structure. */
767 s = calloc(sizeof(src_v4l2_t), 1);
770 fprintf(stderr, "Out of memory.");
774 src->state = (void *) s;
776 /* Open the device. */
777 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
780 fprintf(stderr, "Cannot open device.");
785 if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
787 fprintf(stderr, "Cannot get capabilities.");
790 char *res = strdup((char*) s->cap.card);
791 /*strcpy(res, (char*) s->cap.card);*/
792 if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
797 struct v4l2_format format;
798 memset(&format,0,sizeof(format));
799 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
800 if (ioctl(s->fd,VIDIOC_G_FMT,&format) < 0) {
801 fprintf(stderr, "Cannot get format.");
804 *width = format.fmt.pix.width;
805 *height = format.fmt.pix.height;
807 struct v4l2_fmtdesc fmt;
808 memset(&fmt,0,sizeof(fmt));
810 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
812 struct v4l2_frmsizeenum sizes;
813 memset(&sizes,0,sizeof(sizes));
815 struct v4l2_frmivalenum rates;
816 memset(&rates,0,sizeof(rates));
818 *pixelformatdescription = strdup((char *) "result:");
820 while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
822 /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
823 //*pixelformatdescription = strdup((char*)fmt.description);
824 snprintf( value, sizeof(value), "%c%c%c%c:", fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 );
825 strcat(*pixelformatdescription, strdup((char *) value));
826 fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0, fmt.pixelformat >> 8,
827 fmt.pixelformat >> 16, fmt.pixelformat >> 24);
829 sizes.pixel_format = fmt.pixelformat;
831 // Query supported frame size
832 while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
833 struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
834 // Query supported frame rates
836 rates.pixel_format = fmt.pixelformat;
837 rates.width = image_size.width;
838 rates.height = image_size.height;
839 snprintf( value, sizeof(value), "%dx%d,", image_size.width, image_size.height );
840 strcat(*pixelformatdescription, strdup((char *) value));
841 fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
842 while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
843 snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.numerator, rates.un.discrete.denominator );
844 strcat(*pixelformatdescription, strdup((char *) value));
845 fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
848 fprintf(stderr, "\n");
853 /*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
855 fmt.pixelformat >> 0, fmt.pixelformat >> 8,
856 fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
860 *pixelformatdescription = '\0';
867 static int src_v4l2_open(src_t *src)
873 /*ERROR("No device name specified.");*/
877 /* Allocate memory for the state structure. */
878 s = calloc(sizeof(src_v4l2_t), 1);
881 /*ERROR("Out of memory.");*/
885 src->state = (void *) s;
887 /* Open the device. */
888 s->fd = open(src->source, O_RDWR | O_NONBLOCK);
891 /*ERROR("Error opening device: %s", src->source);
892 ERROR("open: %s", strerror(errno));*/
897 /*MSG("%s opened.", src->source);*/
899 /* Get the device capabilities. */
900 if(src_v4l2_get_capability(src))
907 if(src_v4l2_set_input(src))
913 /* Set picture options. */
914 src_v4l2_set_controls(src);
916 /* Set the pixel format. */
917 if(src_v4l2_set_pix_format(src))
923 /* Set the frame-rate if > 0 */
924 if(src->fps) src_v4l2_set_fps(src);
926 /* Delay to let the image settle down. */
929 /*MSG("Delaying %i seconds.", src->delay);*/
930 usleep(src->delay * 1000 * 1000);
933 /* Try to setup mmap. */
934 if(!src->use_read && src_v4l2_set_mmap(src))
936 /*WARN("Unable to use mmap. Using read instead.");*/
940 /* If unable to use mmap or user requested read(). */
943 if(src_v4l2_set_read(src))
945 /*ERROR("Unable to use read.");*/
956 static int src_v4l2_close(src_t *src)
958 src_v4l2_t *s = (src_v4l2_t *) src->state;
962 if(!s->map) free(s->buffer[0].start);
963 else src_v4l2_free_mmap(src);
966 if(s->fd >= 0) close(s->fd);
972 static int src_v4l2_grab(src_t *src)
974 src_v4l2_t *s = (src_v4l2_t *) src->state;
982 /* Is a frame ready? */
986 tv.tv_sec = src->timeout;
989 r = select(s->fd + 1, &fds, NULL, NULL, &tv);
993 /*ERROR("select: %s", strerror(errno));*/
999 /*ERROR("Timed out waiting for frame!");*/
1008 if(ioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1)
1010 /*ERROR("VIDIOC_QBUF: %s", strerror(errno));*/
1015 memset(&s->buf, 0, sizeof(s->buf));
1017 s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1018 s->buf.memory = V4L2_MEMORY_MMAP;
1020 if(ioctl(s->fd, VIDIOC_DQBUF, &s->buf) == -1)
1022 /*ERROR("VIDIOC_DQBUF: %s", strerror(errno));*/
1026 src->img = s->buffer[s->buf.index].start;
1027 src->length = s->buffer[s->buf.index].length;
1029 s->pframe = s->buf.index;
1035 r = read(s->fd, s->buffer[0].start, s->buffer[0].length);
1038 /*ERROR("Unable to read a frame.");
1039 ERROR("read: %s", strerror(errno));*/
1043 src->img = s->buffer[0].start;
1050 src_mod_t src_v4l2 = {
1051 "v4l2", SRC_TYPE_DEVICE,
1058 #else /* #ifdef HAVE_V4L2 */
1060 src_mod_t src_v4l2 = {
1068 #endif /* #ifdef HAVE_V4L2 */