source: BAORadio/libindi/v1/libs/webcam/v4l2_base.cpp@ 689

Last change on this file since 689 was 490, checked in by campagne, 15 years ago

import libindi (JEC)

File size: 31.1 KB
Line 
1/*
2 Copyright (C) 2005 by Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 Based on V4L 2 Example
5 http://v4l2spec.bytesex.org/spec-single/v4l2.html#CAPTURE-EXAMPLE
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21*/
22
23#include <iostream>
24
25#include <sys/ioctl.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <assert.h>
29#include <fcntl.h>
30#include <unistd.h>
31#include <stdio.h>
32#include <errno.h>
33#include <sys/mman.h>
34#include <string.h>
35#include <asm/types.h> /* for videodev2.h */
36
37#include "ccvt.h"
38#include "v4l2_base.h"
39#include "eventloop.h"
40#include "indidevapi.h"
41
42#define ERRMSGSIZ 1024
43
44#define CLEAR(x) memset (&(x), 0, sizeof (x))
45
46using namespace std;
47
48V4L2_Base::V4L2_Base()
49{
50 frameRate=10;
51 selectCallBackID = -1;
52 dropFrame = false;
53
54 xmax = xmin = 160;
55 ymax = ymin = 120;
56
57 io = IO_METHOD_MMAP;
58 fd = -1;
59 buffers = NULL;
60 n_buffers = 0;
61
62 YBuf = NULL;
63 UBuf = NULL;
64 VBuf = NULL;
65 colorBuffer = NULL;
66 rgb24_buffer = NULL;
67 callback = NULL;
68
69}
70
71V4L2_Base::~V4L2_Base()
72{
73
74 delete (YBuf);
75 delete (UBuf);
76 delete (VBuf);
77 delete (colorBuffer);
78 delete (rgb24_buffer);
79
80}
81
82int V4L2_Base::xioctl(int fd, int request, void *arg)
83{
84 int r;
85
86 do r = ioctl (fd, request, arg);
87 while (-1 == r && EINTR == errno);
88
89 return r;
90}
91
92int V4L2_Base::errno_exit(const char *s, char *errmsg)
93{
94 fprintf (stderr, "%s error %d, %s\n",
95 s, errno, strerror (errno));
96
97 snprintf(errmsg, ERRMSGSIZ, "%s error %d, %s\n", s, errno, strerror (errno));
98
99 return -1;
100}
101
102int V4L2_Base::connectCam(const char * devpath, char *errmsg , int pixelFormat , int width , int height )
103{
104 frameRate=10;
105 selectCallBackID = -1;
106 dropFrame = false;
107
108 if (open_device (devpath, errmsg) < 0)
109 return -1;
110
111 if (init_device(errmsg, pixelFormat, width, height) < 0)
112 return -1;
113
114 cerr << "V4L 2 - All successful, returning\n";
115 return fd;
116}
117
118void V4L2_Base::disconnectCam()
119{
120 char errmsg[ERRMSGSIZ];
121 delete YBuf;
122 delete UBuf;
123 delete VBuf;
124 YBuf = UBuf = VBuf = NULL;
125
126 if (selectCallBackID != -1)
127 rmCallback(selectCallBackID);
128
129 stop_capturing (errmsg);
130
131 uninit_device (errmsg);
132
133 close_device ();
134
135 fprintf(stderr, "Disconnect cam\n");
136}
137
138int V4L2_Base::read_frame(char *errmsg)
139{
140 struct v4l2_buffer buf;
141 unsigned int i;
142 //cerr << "in read Frame" << endl;
143
144 switch (io) {
145 case IO_METHOD_READ:
146 if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
147 switch (errno) {
148 case EAGAIN:
149 return 0;
150
151 case EIO:
152 /* Could ignore EIO, see spec. */
153
154 /* fall through */
155
156 default:
157 return errno_exit ("read", errmsg);
158 }
159 }
160
161 //process_image (buffers[0].start);
162
163 break;
164
165 case IO_METHOD_MMAP:
166 CLEAR (buf);
167
168 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
169 buf.memory = V4L2_MEMORY_MMAP;
170
171 if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
172 switch (errno) {
173 case EAGAIN:
174 return 0;
175
176 case EIO:
177 /* Could ignore EIO, see spec. */
178
179 /* fall through */
180
181 default:
182 return errno_exit ("VIDIOC_DQBUF", errmsg);
183 }
184 }
185
186 assert (buf.index < n_buffers);
187
188 switch (fmt.fmt.pix.pixelformat)
189 {
190 case V4L2_PIX_FMT_YUV420:
191 memcpy(YBuf,((unsigned char *) buffers[buf.index].start), fmt.fmt.pix.width * fmt.fmt.pix.height);
192 memcpy(UBuf,((unsigned char *) buffers[buf.index].start) + fmt.fmt.pix.width * fmt.fmt.pix.height, (fmt.fmt.pix.width/2) * (fmt.fmt.pix.height/2));
193 memcpy(VBuf,((unsigned char *) buffers[buf.index].start) + fmt.fmt.pix.width * fmt.fmt.pix.height + (fmt.fmt.pix.width/2) * (fmt.fmt.pix.height/2), (fmt.fmt.pix.width/2) * (fmt.fmt.pix.width/2));
194 break;
195
196 case V4L2_PIX_FMT_YUYV:
197 ccvt_yuyv_420p( fmt.fmt.pix.width , fmt.fmt.pix.height, buffers[buf.index].start, YBuf, UBuf, VBuf);
198 break;
199
200 case V4L2_PIX_FMT_RGB24:
201 RGB2YUV(fmt.fmt.pix.width, fmt.fmt.pix.height, buffers[buf.index].start, YBuf, UBuf, VBuf, 0);
202 break;
203
204 case V4L2_PIX_FMT_SBGGR8:
205 bayer2rgb24(rgb24_buffer, ((unsigned char *) buffers[buf.index].start), fmt.fmt.pix.width, fmt.fmt.pix.height);
206 break;
207 }
208
209 /*if (dropFrame)
210 {
211 dropFrame = false;
212 return 0;
213 } */
214
215 /* Call provided callback function if any */
216 if (callback)
217 (*callback)(uptr);
218
219 if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
220 return errno_exit ("VIDIOC_QBUF", errmsg);
221
222 break;
223
224 case IO_METHOD_USERPTR:
225 CLEAR (buf);
226
227 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
228 buf.memory = V4L2_MEMORY_USERPTR;
229
230 if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
231 switch (errno) {
232 case EAGAIN:
233 return 0;
234
235 case EIO:
236 /* Could ignore EIO, see spec. */
237
238 /* fall through */
239
240 default:
241 errno_exit ("VIDIOC_DQBUF", errmsg);
242 }
243 }
244
245 for (i = 0; i < n_buffers; ++i)
246 if (buf.m.userptr == (unsigned long) buffers[i].start
247 && buf.length == buffers[i].length)
248 break;
249
250 assert (i < n_buffers);
251
252 //process_image ((void *) buf.m.userptr);
253
254 if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
255 errno_exit ("VIDIOC_QBUF", errmsg);
256
257 break;
258 }
259
260 return 0;
261}
262
263int V4L2_Base::stop_capturing(char *errmsg)
264{
265 enum v4l2_buf_type type;
266
267 switch (io) {
268 case IO_METHOD_READ:
269 /* Nothing to do. */
270 break;
271
272 case IO_METHOD_MMAP:
273 case IO_METHOD_USERPTR:
274 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
275
276 IERmCallback(selectCallBackID);
277 selectCallBackID = -1;
278
279 // N.B. I used this as a hack to solve a problem with capturing a frame
280 // long time ago. I recently tried taking this hack off, and it worked fine!
281 //dropFrame = true;
282
283 if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
284 return errno_exit ("VIDIOC_STREAMOFF", errmsg);
285
286
287
288 break;
289 }
290
291 return 0;
292}
293
294int V4L2_Base::start_capturing(char * errmsg)
295{
296 unsigned int i;
297 enum v4l2_buf_type type;
298
299 switch (io) {
300 case IO_METHOD_READ:
301 /* Nothing to do. */
302 break;
303
304 case IO_METHOD_MMAP:
305 for (i = 0; i < n_buffers; ++i) {
306 struct v4l2_buffer buf;
307
308 CLEAR (buf);
309
310 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
311 buf.memory = V4L2_MEMORY_MMAP;
312 buf.index = i;
313
314 if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
315 return errno_exit ("VIDIOC_QBUF", errmsg);
316
317 }
318
319 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
320
321 if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
322 return errno_exit ("VIDIOC_STREAMON", errmsg);
323
324
325
326 selectCallBackID = IEAddCallback(fd, newFrame, this);
327
328 break;
329
330 case IO_METHOD_USERPTR:
331 for (i = 0; i < n_buffers; ++i) {
332 struct v4l2_buffer buf;
333
334 CLEAR (buf);
335
336 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
337 buf.memory = V4L2_MEMORY_USERPTR;
338 buf.m.userptr = (unsigned long) buffers[i].start;
339 buf.length = buffers[i].length;
340
341 if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
342 return errno_exit ("VIDIOC_QBUF", errmsg);
343 }
344
345
346 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
347
348 if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
349 return errno_exit ("VIDIOC_STREAMON", errmsg);
350
351 break;
352 }
353
354 return 0;
355
356}
357
358void V4L2_Base::newFrame(int /*fd*/, void *p)
359{
360 char errmsg[ERRMSGSIZ];
361
362 ( (V4L2_Base *) (p))->read_frame(errmsg);
363
364}
365
366int V4L2_Base::uninit_device(char *errmsg)
367{
368
369 switch (io) {
370 case IO_METHOD_READ:
371 free (buffers[0].start);
372 break;
373
374 case IO_METHOD_MMAP:
375 for (unsigned int i = 0; i < n_buffers; ++i)
376 if (-1 == munmap (buffers[i].start, buffers[i].length))
377 return errno_exit ("munmap", errmsg);
378 break;
379
380 case IO_METHOD_USERPTR:
381 for (unsigned int i = 0; i < n_buffers; ++i)
382 free (buffers[i].start);
383 break;
384 }
385
386 free (buffers);
387
388 return 0;
389}
390
391void V4L2_Base::init_read(unsigned int buffer_size)
392{
393 buffers = (buffer *) calloc (1, sizeof (*buffers));
394
395 if (!buffers) {
396 fprintf (stderr, "Out of memory\n");
397 exit (EXIT_FAILURE);
398 }
399
400 buffers[0].length = buffer_size;
401 buffers[0].start = malloc (buffer_size);
402
403 if (!buffers[0].start) {
404 fprintf (stderr, "Out of memory\n");
405 exit (EXIT_FAILURE);
406 }
407}
408
409int V4L2_Base::init_mmap(char *errmsg)
410{
411 struct v4l2_requestbuffers req;
412
413 CLEAR (req);
414
415 req.count = 4;
416 //req.count = 1;
417 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
418 req.memory = V4L2_MEMORY_MMAP;
419
420 if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
421 if (EINVAL == errno) {
422 fprintf (stderr, "%s does not support "
423 "memory mapping\n", dev_name);
424 snprintf(errmsg, ERRMSGSIZ, "%s does not support "
425 "memory mapping\n", dev_name);
426 return -1;
427 } else {
428 return errno_exit ("VIDIOC_REQBUFS", errmsg);
429 }
430 }
431
432 if (req.count < 2) {
433 fprintf (stderr, "Insufficient buffer memory on %s\n",
434 dev_name);
435 snprintf(errmsg, ERRMSGSIZ, "Insufficient buffer memory on %s\n",
436 dev_name);
437 return -1;
438 }
439
440 buffers = (buffer *) calloc (req.count, sizeof (*buffers));
441
442 if (!buffers)
443 {
444 fprintf (stderr, "buffers. Out of memory\n");
445 strncpy(errmsg, "buffers. Out of memory\n", ERRMSGSIZ);
446 return -1;
447 }
448
449 for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
450 {
451 struct v4l2_buffer buf;
452
453 CLEAR (buf);
454
455 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
456 buf.memory = V4L2_MEMORY_MMAP;
457 buf.index = n_buffers;
458
459 if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
460 return errno_exit ("VIDIOC_QUERYBUF", errmsg);
461
462 buffers[n_buffers].length = buf.length;
463 buffers[n_buffers].start =
464 mmap (NULL /* start anywhere */,
465 buf.length,
466 PROT_READ | PROT_WRITE /* required */,
467 MAP_SHARED /* recommended */,
468 fd, buf.m.offset);
469
470 if (MAP_FAILED == buffers[n_buffers].start)
471 return errno_exit ("mmap", errmsg);
472 }
473
474 return 0;
475}
476
477void V4L2_Base::init_userp(unsigned int buffer_size)
478{
479 struct v4l2_requestbuffers req;
480 char errmsg[ERRMSGSIZ];
481
482 CLEAR (req);
483
484 req.count = 4;
485 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
486 req.memory = V4L2_MEMORY_USERPTR;
487
488 if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
489 if (EINVAL == errno) {
490 fprintf (stderr, "%s does not support "
491 "user pointer i/o\n", dev_name);
492 exit (EXIT_FAILURE);
493 } else {
494 errno_exit ("VIDIOC_REQBUFS", errmsg);
495 }
496 }
497
498 buffers = (buffer *) calloc (4, sizeof (*buffers));
499
500 if (!buffers) {
501 fprintf (stderr, "Out of memory\n");
502 exit (EXIT_FAILURE);
503 }
504
505 for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
506 buffers[n_buffers].length = buffer_size;
507 buffers[n_buffers].start = malloc (buffer_size);
508
509 if (!buffers[n_buffers].start) {
510 fprintf (stderr, "Out of memory\n");
511 exit (EXIT_FAILURE);
512 }
513 }
514}
515
516int V4L2_Base::init_device(char *errmsg, int pixelFormat , int width, int height)
517{
518 unsigned int min;
519
520 if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap))
521 {
522 if (EINVAL == errno) {
523 fprintf (stderr, "%s is no V4L2 device\n",
524 dev_name);
525 snprintf(errmsg, ERRMSGSIZ, "%s is no V4L2 device\n", dev_name);
526 return -1;
527 } else {
528 return errno_exit ("VIDIOC_QUERYCAP", errmsg);
529 }
530 }
531
532 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
533 {
534 fprintf (stderr, "%s is no video capture device\n",
535 dev_name);
536 snprintf(errmsg, ERRMSGSIZ, "%s is no video capture device\n", dev_name);
537 return -1;
538 }
539
540 switch (io)
541 {
542 case IO_METHOD_READ:
543 if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
544 fprintf (stderr, "%s does not support read i/o\n",
545 dev_name);
546 snprintf(errmsg, ERRMSGSIZ, "%s does not support read i/o\n",
547 dev_name);
548 return -1;
549 }
550
551 break;
552
553 case IO_METHOD_MMAP:
554 case IO_METHOD_USERPTR:
555 if (!(cap.capabilities & V4L2_CAP_STREAMING))
556 {
557 fprintf (stderr, "%s does not support streaming i/o\n",
558 dev_name);
559 snprintf(errmsg, ERRMSGSIZ, "%s does not support streaming i/o\n",
560 dev_name);
561 return -1;
562 }
563
564 break;
565 }
566
567 /* Select video input, video standard and tune here. */
568
569 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
570
571 if (-1 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
572 /* Errors ignored. */
573 }
574
575 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
576 crop.c = cropcap.defrect; /* reset to default */
577
578 if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
579 switch (errno) {
580 case EINVAL:
581 /* Cropping not supported. */
582 break;
583 default:
584 /* Errors ignored. */
585 break;
586 }
587 }
588
589 CLEAR (fmt);
590
591 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
592
593 if (-1 == xioctl (fd, VIDIOC_G_FMT, &fmt))
594 return errno_exit ("VIDIOC_G_FMT", errmsg);
595
596 fmt.fmt.pix.width = (width == -1) ? fmt.fmt.pix.width : width;
597 fmt.fmt.pix.height = (height == -1) ? fmt.fmt.pix.height : height;
598 fmt.fmt.pix.pixelformat = (pixelFormat == -1) ? fmt.fmt.pix.pixelformat : pixelFormat;
599 //fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
600
601 if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
602 return errno_exit ("VIDIOC_S_FMT", errmsg);
603
604 /* Note VIDIOC_S_FMT may change width and height. */
605
606 /* Buggy driver paranoia. */
607 min = fmt.fmt.pix.width * 2;
608 if (fmt.fmt.pix.bytesperline < min)
609 fmt.fmt.pix.bytesperline = min;
610 min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
611 if (fmt.fmt.pix.sizeimage < min)
612 fmt.fmt.pix.sizeimage = min;
613
614 /* Let's get the actual size */
615 CLEAR(fmt);
616
617 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
618
619 if (-1 == xioctl (fd, VIDIOC_G_FMT, &fmt))
620 return errno_exit ("VIDIOC_G_FMT", errmsg);
621
622 cerr << "width: " << fmt.fmt.pix.width << " - height: " << fmt.fmt.pix.height << endl;
623
624 switch (pixelFormat)
625 {
626 case V4L2_PIX_FMT_YUV420:
627 cerr << "pixel format: V4L2_PIX_FMT_YUV420" << endl;
628 break;
629
630 case V4L2_PIX_FMT_YUYV:
631 cerr << "pixel format: V4L2_PIX_FMT_YUYV" << endl;
632 break;
633
634 case V4L2_PIX_FMT_RGB24:
635 cerr << "pixel format: V4L2_PIX_FMT_RGB24" << endl;
636 break;
637
638 case V4L2_PIX_FMT_SBGGR8:
639 cerr << "pixel format: V4L2_PIX_FMT_SBGGR8" << endl;
640 break;
641
642 }
643
644 findMinMax();
645
646 allocBuffers();
647
648 switch (io)
649 {
650 case IO_METHOD_READ:
651 init_read (fmt.fmt.pix.sizeimage);
652 break;
653
654 case IO_METHOD_MMAP:
655 return init_mmap(errmsg);
656 break;
657
658 case IO_METHOD_USERPTR:
659 init_userp (fmt.fmt.pix.sizeimage);
660 break;
661 }
662
663 return 0;
664}
665
666void V4L2_Base::close_device(void)
667{
668 char errmsg[ERRMSGSIZ];
669
670 if (-1 == close (fd))
671 errno_exit ("close", errmsg);
672
673 fd = -1;
674}
675
676int V4L2_Base::open_device(const char *devpath, char *errmsg)
677{
678 struct stat st;
679
680 strncpy(dev_name, devpath, 64);
681
682 if (-1 == stat (dev_name, &st)) {
683 fprintf (stderr, "Cannot identify '%s': %d, %s\n",
684 dev_name, errno, strerror (errno));
685 snprintf(errmsg, ERRMSGSIZ, "Cannot identify '%s': %d, %s\n",
686 dev_name, errno, strerror (errno));
687 return -1;
688 }
689
690 if (!S_ISCHR (st.st_mode))
691 {
692 fprintf (stderr, "%s is no device\n", dev_name);
693 snprintf(errmsg, ERRMSGSIZ, "%s is no device\n", dev_name);
694 return -1;
695 }
696
697 fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
698
699 if (-1 == fd)
700 {
701 fprintf (stderr, "Cannot open '%s': %d, %s\n",
702 dev_name, errno, strerror (errno));
703 snprintf(errmsg, ERRMSGSIZ, "Cannot open '%s': %d, %s\n",
704 dev_name, errno, strerror (errno));
705 return -1;
706 }
707
708 return 0;
709}
710
711
712
713int V4L2_Base::getWidth()
714{
715 return fmt.fmt.pix.width;
716}
717
718int V4L2_Base::getHeight()
719{
720 return fmt.fmt.pix.height;
721}
722
723void V4L2_Base::setFPS(int fps)
724{
725 frameRate = 15;//fps;
726}
727
728int V4L2_Base::getFPS()
729{
730 return 15;
731}
732
733char * V4L2_Base::getDeviceName()
734{
735 return ((char *) cap.card);
736}
737
738void V4L2_Base::allocBuffers()
739{
740 delete (YBuf); YBuf = NULL;
741 delete (UBuf); UBuf = NULL;
742 delete (VBuf); VBuf = NULL;
743 delete (colorBuffer); colorBuffer = NULL;
744 delete (rgb24_buffer); rgb24_buffer = NULL;
745
746 YBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
747 UBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
748 VBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
749 colorBuffer = new unsigned char[fmt.fmt.pix.width * fmt.fmt.pix.height * 4];
750
751 if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
752 rgb24_buffer = new unsigned char[fmt.fmt.pix.width * fmt.fmt.pix.height * 3];
753}
754
755void V4L2_Base::getMaxMinSize(int & x_max, int & y_max, int & x_min, int & y_min)
756{
757 x_max = xmax; y_max = ymax; x_min = xmin; y_min = ymin;
758}
759
760int V4L2_Base::setSize(int x, int y)
761{
762 char errmsg[ERRMSGSIZ];
763 int oldW, oldH;
764
765 oldW = fmt.fmt.pix.width;
766 oldH = fmt.fmt.pix.height;
767
768 fmt.fmt.pix.width = x;
769 fmt.fmt.pix.height = y;
770
771 if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
772 {
773 fmt.fmt.pix.width = oldW;
774 fmt.fmt.pix.height = oldH;
775 return errno_exit ("VIDIOC_S_FMT", errmsg);
776 }
777
778 /* PWC bug? It seems that setting the "wrong" width and height will mess something in the driver.
779 Only 160x120, 320x280, and 640x480 are accepted. If I try to set it for example to 300x200, it wii
780 get set to 320x280, which is fine, but then the video information is messed up for some reason. */
781 xioctl (fd, VIDIOC_S_FMT, &fmt);
782
783
784 allocBuffers();
785
786 return 0;
787}
788
789void V4L2_Base::setContrast(int val)
790{
791 /*picture_.contrast=val;
792 updatePictureSettings();*/
793}
794
795int V4L2_Base::getContrast()
796{
797 return 255;//picture_.contrast;
798}
799
800void V4L2_Base::setBrightness(int val)
801{
802 /*picture_.brightness=val;
803 updatePictureSettings();*/
804}
805
806int V4L2_Base::getBrightness()
807{
808 return 255;//picture_.brightness;
809}
810
811void V4L2_Base::setColor(int val)
812{
813 /*picture_.colour=val;
814 updatePictureSettings();*/
815}
816
817int V4L2_Base::getColor()
818{
819 return 255; //picture_.colour;
820}
821
822void V4L2_Base::setHue(int val)
823{
824 /*picture_.hue=val;
825 updatePictureSettings();*/
826}
827
828int V4L2_Base::getHue()
829{
830 return 255;//picture_.hue;
831}
832
833void V4L2_Base::setWhiteness(int val)
834{
835 /*picture_.whiteness=val;
836 updatePictureSettings();*/
837}
838
839int V4L2_Base::getWhiteness()
840{
841 return 255;//picture_.whiteness;
842}
843
844void V4L2_Base::setPictureSettings()
845{
846 /*if (ioctl(device_, VIDIOCSPICT, &picture_) ) {
847 cerr << "updatePictureSettings" << endl;
848 }
849 ioctl(device_, VIDIOCGPICT, &picture_);*/
850}
851
852void V4L2_Base::getPictureSettings()
853{
854 /*if (ioctl(device_, VIDIOCGPICT, &picture_) )
855 {
856 cerr << "refreshPictureSettings" << endl;
857 }*/
858}
859
860unsigned char * V4L2_Base::getY()
861{
862 if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
863 RGB2YUV(fmt.fmt.pix.width, fmt.fmt.pix.height, rgb24_buffer, YBuf, UBuf, VBuf, 0);
864
865 return YBuf;
866}
867
868unsigned char * V4L2_Base::getU()
869{
870 return UBuf;
871}
872
873unsigned char * V4L2_Base::getV()
874{
875 return VBuf;
876}
877
878unsigned char * V4L2_Base::getColorBuffer()
879{
880 //cerr << "in get color buffer " << endl;
881
882 switch (fmt.fmt.pix.pixelformat)
883 {
884 case V4L2_PIX_FMT_YUV420:
885 ccvt_420p_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
886 buffers[0].start, (void*)colorBuffer);
887 break;
888
889 case V4L2_PIX_FMT_YUYV:
890 ccvt_yuyv_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
891 buffers[0].start, (void*)colorBuffer);
892 break;
893
894 case V4L2_PIX_FMT_RGB24:
895 ccvt_rgb24_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
896 buffers[0].start, (void*)colorBuffer);
897 break;
898
899 case V4L2_PIX_FMT_SBGGR8:
900 ccvt_rgb24_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
901 rgb24_buffer, (void*)colorBuffer);
902 break;
903
904 default:
905 break;
906 }
907
908 return colorBuffer;
909}
910
911void V4L2_Base::registerCallback(WPF *fp, void *ud)
912{
913 callback = fp;
914 uptr = ud;
915}
916
917void V4L2_Base::findMinMax()
918{
919 char errmsg[ERRMSGSIZ];
920 struct v4l2_format tryfmt;
921 CLEAR(tryfmt);
922
923 xmin = xmax = fmt.fmt.pix.width;
924 ymin = ymax = fmt.fmt.pix.height;
925
926 tryfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
927 tryfmt.fmt.pix.width = 10;
928 tryfmt.fmt.pix.height = 10;
929 tryfmt.fmt.pix.pixelformat = fmt.fmt.pix.pixelformat;
930 tryfmt.fmt.pix.field = fmt.fmt.pix.field;
931
932 if (-1 == xioctl (fd, VIDIOC_TRY_FMT, &tryfmt))
933 {
934 errno_exit ("VIDIOC_TRY_FMT 1", errmsg);
935 return;
936 }
937
938 xmin = tryfmt.fmt.pix.width;
939 ymin = tryfmt.fmt.pix.height;
940
941 tryfmt.fmt.pix.width = 1600;
942 tryfmt.fmt.pix.height = 1200;
943
944 if (-1 == xioctl (fd, VIDIOC_TRY_FMT, &tryfmt))
945 {
946 errno_exit ("VIDIOC_TRY_FMT 2", errmsg);
947 return;
948 }
949
950 xmax = tryfmt.fmt.pix.width;
951 ymax = tryfmt.fmt.pix.height;
952
953 cerr << "Min X: " << xmin << " - Max X: " << xmax << " - Min Y: " << ymin << " - Max Y: " << ymax << endl;
954}
955
956void V4L2_Base::enumerate_ctrl (void)
957{
958 char errmsg[ERRMSGSIZ];
959 CLEAR(queryctrl);
960
961 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
962 {
963 if (0 == xioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
964 {
965 cerr << "Control " << queryctrl.name << endl;
966
967 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
968 continue;
969
970 cerr << "Control " << queryctrl.name << endl;
971
972 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
973 enumerate_menu ();
974 } else
975 {
976 if (errno == EINVAL)
977 continue;
978
979 errno_exit("VIDIOC_QUERYCTRL", errmsg);
980 return;
981 }
982 }
983
984 for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
985 {
986 if (0 == xioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
987 {
988 cerr << "Private Control " << queryctrl.name << endl;
989
990 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
991 continue;
992
993 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
994 enumerate_menu ();
995 } else {
996 if (errno == EINVAL)
997 break;
998
999 errno_exit ("VIDIOC_QUERYCTRL", errmsg);
1000 return;
1001 }
1002
1003 }
1004
1005}
1006
1007void V4L2_Base::enumerate_menu (void)
1008{
1009 char errmsg[ERRMSGSIZ];
1010 cerr << " Menu items:" << endl;
1011
1012 CLEAR(querymenu);
1013 querymenu.id = queryctrl.id;
1014
1015 for (querymenu.index = queryctrl.minimum; querymenu.index <= queryctrl.maximum; querymenu.index++)
1016 {
1017 if (0 == xioctl (fd, VIDIOC_QUERYMENU, &querymenu))
1018 {
1019 cerr << " " << querymenu.name << endl;
1020 } else
1021 {
1022 errno_exit("VIDIOC_QUERYMENU", errmsg);
1023 return;
1024 }
1025 }
1026}
1027
1028int V4L2_Base::query_ctrl(unsigned int ctrl_id, double & ctrl_min, double & ctrl_max, double & ctrl_step, double & ctrl_value, char *errmsg)
1029{
1030
1031 struct v4l2_control control;
1032
1033 CLEAR(queryctrl);
1034
1035 queryctrl.id = ctrl_id;
1036
1037 if (-1 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
1038 {
1039 if (errno != EINVAL)
1040 return errno_exit ("VIDIOC_QUERYCTRL", errmsg);
1041
1042 else
1043 {
1044 cerr << "#" << ctrl_id << " is not supported" << endl;
1045 snprintf(errmsg, ERRMSGSIZ, "# %d is not supported", ctrl_id);
1046 return -1;
1047 }
1048 } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
1049 {
1050 cerr << "#" << ctrl_id << " is disabled" << endl;
1051 snprintf(errmsg, ERRMSGSIZ, "# %d is disabled", ctrl_id);
1052 return -1;
1053 }
1054
1055 ctrl_min = queryctrl.minimum;
1056 ctrl_max = queryctrl.maximum;
1057 ctrl_step = queryctrl.step;
1058 ctrl_value = queryctrl.default_value;
1059
1060 /* Get current value */
1061 CLEAR(control);
1062 control.id = ctrl_id;
1063
1064 if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
1065 ctrl_value = control.value;
1066
1067 cerr << queryctrl.name << " -- min: " << ctrl_min << " max: " << ctrl_max << " step: " << ctrl_step << " value: " << ctrl_value << endl;
1068
1069 return 0;
1070
1071}
1072
1073int V4L2_Base::queryINTControls(INumberVectorProperty *nvp)
1074{
1075 struct v4l2_control control;
1076 char errmsg[ERRMSGSIZ];
1077 CLEAR(queryctrl);
1078 INumber *numbers = NULL;
1079 unsigned int *num_ctrls = NULL;
1080 int nnum=0;
1081
1082 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
1083 {
1084 if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
1085 {
1086 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
1087 {
1088 cerr << queryctrl.name << " is disabled." << endl;
1089 continue;
1090 }
1091
1092 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
1093 {
1094 numbers = (numbers == NULL) ? (INumber *) malloc (sizeof(INumber)) :
1095 (INumber *) realloc (numbers, (nnum+1) * sizeof (INumber));
1096
1097 num_ctrls = (num_ctrls == NULL) ? (unsigned int *) malloc (sizeof (unsigned int)) :
1098 (unsigned int *) realloc (num_ctrls, (nnum+1) * sizeof (unsigned int));
1099
1100 strncpy(numbers[nnum].name, ((char *) queryctrl.name) , MAXINDINAME);
1101 strncpy(numbers[nnum].label, ((char *) queryctrl.name), MAXINDILABEL);
1102 strncpy(numbers[nnum].format, "%0.f", MAXINDIFORMAT);
1103 numbers[nnum].min = queryctrl.minimum;
1104 numbers[nnum].max = queryctrl.maximum;
1105 numbers[nnum].step = queryctrl.step;
1106 numbers[nnum].value = queryctrl.default_value;
1107
1108 /* Get current value if possible */
1109 CLEAR(control);
1110 control.id = queryctrl.id;
1111 if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
1112 numbers[nnum].value = control.value;
1113
1114 /* Store ID info in INumber. This is the first time ever I make use of aux0!! */
1115 num_ctrls[nnum] = queryctrl.id;
1116
1117 cerr << queryctrl.name << " -- min: " << queryctrl.minimum << " max: " << queryctrl.maximum << " step: " << queryctrl.step << " value: " << numbers[nnum].value << endl;
1118
1119 nnum++;
1120
1121 }
1122 } else if (errno != EINVAL) {
1123 if(numbers) free(numbers);
1124 return errno_exit ("VIDIOC_QUERYCTRL", errmsg);
1125 }
1126
1127 }
1128
1129 for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
1130 {
1131 if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
1132 {
1133 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
1134 {
1135 cerr << queryctrl.name << " is disabled." << endl;
1136 continue;
1137 }
1138
1139 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
1140 {
1141 numbers = (numbers == NULL) ? (INumber *) malloc (sizeof(INumber)) :
1142 (INumber *) realloc (numbers, (nnum+1) * sizeof (INumber));
1143
1144 num_ctrls = (num_ctrls == NULL) ? (unsigned int *) malloc (sizeof (unsigned int)) :
1145 (unsigned int *) realloc (num_ctrls, (nnum+1) * sizeof (unsigned int));
1146
1147 strncpy(numbers[nnum].name, ((char *) queryctrl.name) , MAXINDINAME);
1148 strncpy(numbers[nnum].label, ((char *) queryctrl.name), MAXINDILABEL);
1149 strncpy(numbers[nnum].format, "%0.f", MAXINDIFORMAT);
1150 numbers[nnum].min = queryctrl.minimum;
1151 numbers[nnum].max = queryctrl.maximum;
1152 numbers[nnum].step = queryctrl.step;
1153 numbers[nnum].value = queryctrl.default_value;
1154
1155 /* Get current value if possible */
1156 CLEAR(control);
1157 control.id = queryctrl.id;
1158 if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
1159 numbers[nnum].value = control.value;
1160
1161 /* Store ID info in INumber. This is the first time ever I make use of aux0!! */
1162 num_ctrls[nnum] = queryctrl.id;
1163
1164 nnum++;
1165
1166 }
1167 }
1168 else break;
1169 }
1170
1171 /* Store numbers in aux0 */
1172 for (int i=0; i < nnum; i++)
1173 numbers[i].aux0 = &num_ctrls[i];
1174
1175 nvp->np = numbers;
1176 nvp->nnp = nnum;
1177
1178 return nnum;
1179
1180}
1181
1182int V4L2_Base::setINTControl(unsigned int ctrl_id, double new_value, char *errmsg)
1183{
1184 struct v4l2_control control;
1185
1186 CLEAR(control);
1187
1188 //cerr << "The id is " << ctrl_id << " new value is " << new_value << endl;
1189
1190 control.id = ctrl_id;
1191 control.value = (int) new_value;
1192
1193 if (-1 == xioctl(fd, VIDIOC_S_CTRL, &control))
1194 return errno_exit ("VIDIOC_S_CTRL", errmsg);
1195
1196 return 0;
1197}
1198
Note: See TracBrowser for help on using the repository browser.