Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpV4l2Grabber.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See httpS://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Framegrabber based on Video4Linux2 driver.
32 */
33
38
39#include <visp3/core/vpConfig.h>
40
41#ifdef VISP_HAVE_V4L2
42
43#include <errno.h>
44#include <fcntl.h>
45#include <iostream>
46#include <stdio.h>
47#include <stdlib.h>
48#include <sys/ioctl.h>
49#include <sys/mman.h>
50#include <sys/stat.h>
51#include <sys/time.h>
52#include <sys/types.h>
53#include <unistd.h>
54
55#include <visp3/core/vpDebug.h>
56#include <visp3/core/vpFrameGrabberException.h>
57#include <visp3/sensor/vpV4l2Grabber.h>
58//#include <visp3/io/vpImageIo.h>
59#include <visp3/core/vpImageConvert.h>
60#include <visp3/core/vpImageTools.h>
61
63const unsigned int vpV4l2Grabber::DEFAULT_INPUT = 2;
64const unsigned int vpV4l2Grabber::DEFAULT_SCALE = 2;
65const __u32 vpV4l2Grabber::MAX_INPUTS = 16;
66const __u32 vpV4l2Grabber::MAX_NORM = 16;
67const __u32 vpV4l2Grabber::MAX_FORMAT = 32;
68const unsigned int vpV4l2Grabber::MAX_CTRL = 32;
69const unsigned int vpV4l2Grabber::MAX_BUFFERS = 32;
70const unsigned int vpV4l2Grabber::FRAME_SIZE = 288;
71#define vpCLEAR(x) memset(&(x), 0, sizeof(x))
72
149 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
150 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
151 streaming(false), m_input(vpV4l2Grabber::DEFAULT_INPUT), m_framerate(vpV4l2Grabber::framerate_25fps),
152 m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT), m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
153{
154 setDevice("/dev/video0");
155 setNBuffers(3);
160
161 init = false;
162}
163
204 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
205 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0),
206 streaming(false), m_input(vpV4l2Grabber::DEFAULT_INPUT), m_framerate(vpV4l2Grabber::framerate_25fps),
207 m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT), m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
208{
209 setDevice("/dev/video0");
210 setNBuffers(3);
215
216 init = false;
217}
218
248vpV4l2Grabber::vpV4l2Grabber(unsigned input, unsigned scale)
249 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
250 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
251 streaming(false), m_input(vpV4l2Grabber::DEFAULT_INPUT), m_framerate(vpV4l2Grabber::framerate_25fps),
252 m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT), m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
253{
254 setDevice("/dev/video0");
255 setNBuffers(3);
257 setInput(input);
258 setScale(scale);
259
260 init = false;
261}
262
294vpV4l2Grabber::vpV4l2Grabber(vpImage<unsigned char> &I, unsigned input, unsigned scale)
295 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
296 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
297 streaming(false), m_input(vpV4l2Grabber::DEFAULT_INPUT), m_framerate(vpV4l2Grabber::framerate_25fps),
298 m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT), m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
299{
300 setDevice("/dev/video0");
301 setNBuffers(3);
303 setInput(input);
304 setScale(scale);
305
306 init = false;
307
308 open(I);
309}
310
341vpV4l2Grabber::vpV4l2Grabber(vpImage<vpRGBa> &I, unsigned input, unsigned scale)
342 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
343 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
344 streaming(false), m_input(vpV4l2Grabber::DEFAULT_INPUT), m_framerate(vpV4l2Grabber::framerate_25fps),
345 m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT), m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
346{
347 setDevice("/dev/video0");
348 setNBuffers(3);
350 setInput(input);
351 setScale(scale);
352
353 init = false;
354
355 open(I);
356}
357
364
368void vpV4l2Grabber::setInput(unsigned input) { this->m_input = input; }
369
382void vpV4l2Grabber::setScale(unsigned scale)
383{
384 if ((scale < 1) || (scale > 16)) {
385 close();
386
387 vpERROR_TRACE("Wrong scale %d, scale should be between 1 and 16", scale);
389 }
390
391 setWidth(640 / scale);
392 setHeight(480 / scale);
393}
394
406{
407 open();
408
409 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
410 std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
411 }
412
413 vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
414
415 try {
416 setFormat();
417
418 startStreaming();
419 }
420 catch (...) {
421 if (m_verbose) {
422 std::cout << "Requested pixel format [" << req_pixelformat << "] not compatible with camera" << std::endl;
423 std::cout << "Try to found a compatible pixel format..." << std::endl;
424 }
425
426 // try to fing a compatible format
427 for (int format = 0; format < static_cast<int>(V4L2_MAX_FORMAT); format++) {
428 if (format == req_pixelformat) {
429 continue;
430 }
431 try {
433 setFormat();
434 startStreaming();
435 if (m_verbose)
436 std::cout << "This format [" << m_pixelformat << "] is compatible with camera" << std::endl;
437
438 break;
439 }
440 catch (...) {
441 if (m_verbose)
442 std::cout << "This format [" << m_pixelformat << "] is not compatible with camera" << std::endl;
443 if (format == static_cast<int>(V4L2_MAX_FORMAT)) {
444 std::cout << "No pixel format compatible with the camera was found" << std::endl;
445 close();
446
448 "No pixel format compatible with the camera was found"));
449 }
450 }
451 }
452 }
453
454 I.resize(height, width);
455
456 init = true;
457}
458
469{
470 open();
471
472 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
473 std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
474 }
475
476 vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
477
478 try {
479 setFormat();
480
481 startStreaming();
482 }
483 catch (...) {
484 if (m_verbose) {
485 std::cout << "Requested pixel format [" << m_pixelformat << "] not compatible with camera" << std::endl;
486 std::cout << "Try to found a compatible pixel format..." << std::endl;
487 }
488
489 // try to fing a compatible format
490 for (int format = 0; format < static_cast<int>(V4L2_MAX_FORMAT); format++) {
491 if (format == req_pixelformat) {
492 continue;
493 }
494 try {
496 setFormat();
497 startStreaming();
498 if (m_verbose)
499 std::cout << "This format [" << m_pixelformat << "] is compatible with camera" << std::endl;
500
501 break;
502 }
503 catch (...) {
504 if (m_verbose)
505 std::cout << "This format [" << m_pixelformat << "] is not compatible with camera" << std::endl;
506 }
507 }
508 }
509
510 I.resize(height, width);
511
512 init = true;
513}
514
526{
527 struct timeval timestamp;
528 vpRect roi;
529
530 acquire(I, timestamp, roi);
531}
532
545{
546 struct timeval timestamp;
547
548 acquire(I, timestamp, roi);
549}
550
570void vpV4l2Grabber::acquire(vpImage<unsigned char> &I, struct timeval &timestamp, const vpRect &roi)
571{
572 if (init == false) {
573 open(I);
574 }
575
576 if (init == false) {
577 close();
578
579 throw(vpFrameGrabberException(vpFrameGrabberException::initializationError, "V4l2 frame grabber not initialized"));
580 }
581
582 unsigned char *bitmap;
583 bitmap = waiton(index_buffer, timestamp);
584
585 if (roi == vpRect())
586 I.resize(height, width);
587 else
588 I.resize(static_cast<unsigned int>(roi.getHeight()), static_cast<unsigned int>(roi.getWidth()));
589 switch (m_pixelformat) {
590 case V4L2_GREY_FORMAT:
591 if (roi == vpRect())
592 memcpy(I.bitmap, bitmap, height * width * sizeof(unsigned char));
593 else
594 vpImageTools::crop(bitmap, width, height, roi, I);
595 break;
596 case V4L2_RGB24_FORMAT: // tested
597 if (roi == vpRect())
598 vpImageConvert::RGBToGrey((unsigned char *)bitmap, I.bitmap, width * height);
599 else {
601 vpImageConvert::RGBToGrey((unsigned char *)bitmap, tmp.bitmap, width * height);
602 vpImageTools::crop(tmp, roi, I);
603 }
604 break;
606 if (roi == vpRect())
607 vpImageConvert::RGBaToGrey((unsigned char *)bitmap, I.bitmap, width * height);
608 else {
610 vpImageConvert::RGBaToGrey((unsigned char *)bitmap, tmp.bitmap, width * height);
611 vpImageTools::crop(tmp, roi, I);
612 }
613
614 break;
615 case V4L2_BGR24_FORMAT: // tested
616 if (roi == vpRect())
617 vpImageConvert::BGRToGrey((unsigned char *)bitmap, I.bitmap, width, height, false);
618 else {
620 vpImageConvert::BGRToGrey((unsigned char *)bitmap, tmp.bitmap, width, height, false);
621 vpImageTools::crop(tmp, roi, I);
622 }
623 break;
624 case V4L2_YUYV_FORMAT: // tested
625 if (roi == vpRect())
626 vpImageConvert::YUYVToGrey((unsigned char *)bitmap, I.bitmap, width * height);
627 else {
629 vpImageConvert::YUYVToGrey((unsigned char *)bitmap, tmp.bitmap, width * height);
630 vpImageTools::crop(tmp, roi, I);
631 }
632 break;
633 default:
634 std::cout << "V4L2 conversion not handled" << std::endl;
635 break;
636 }
637
638 queueAll();
639}
640
652{
653 struct timeval timestamp;
654 vpRect roi;
655
656 acquire(I, timestamp, roi);
657}
658
671{
672 struct timeval timestamp;
673
674 acquire(I, timestamp, roi);
675}
676
696void vpV4l2Grabber::acquire(vpImage<vpRGBa> &I, struct timeval &timestamp, const vpRect &roi)
697{
698 if (init == false) {
699 open(I);
700 }
701
702 if (init == false) {
703 close();
704
705 throw(vpFrameGrabberException(vpFrameGrabberException::initializationError, "V4l2 frame grabber not initialized"));
706 }
707
708 unsigned char *bitmap;
709 bitmap = waiton(index_buffer, timestamp);
710
711 if (roi == vpRect())
712 I.resize(height, width);
713 else
714 I.resize(static_cast<unsigned int>(roi.getHeight()), static_cast<unsigned int>(roi.getWidth()));
715
716 // The framegrabber acquire aRGB format. We just shift the data from 1 byte
717 // all the data and initialize the last byte
718
719 switch (m_pixelformat) {
720 case V4L2_GREY_FORMAT:
721 if (roi == vpRect())
722 vpImageConvert::GreyToRGBa((unsigned char *)bitmap, (unsigned char *)I.bitmap, width * height);
723 else
724 vpImageTools::crop(bitmap, width, height, roi, I);
725 break;
726 case V4L2_RGB24_FORMAT: // tested
727 if (roi == vpRect()) {
728 vpImageConvert::RGBToRGBa((unsigned char *)bitmap, (unsigned char *)I.bitmap, width * height);
729 }
730 else {
732 vpImageConvert::RGBToRGBa((unsigned char *)bitmap, (unsigned char *)tmp.bitmap, width * height);
733 vpImageTools::crop(tmp, roi, I);
734 }
735 break;
737 if (roi == vpRect()) {
738 // The framegrabber acquire aRGB format. We just shift the data
739 // from 1 byte all the data and initialize the last byte
740 memcpy(static_cast<void *>(I.bitmap), static_cast<void *>(bitmap + 1), height * width * sizeof(vpRGBa) - 1);
741 I[height - 1][width - 1].A = 0;
742 }
743 else {
744 for (unsigned int i = 0; i < I.getHeight(); i++) {
745 memcpy(static_cast<void *>(I.bitmap),
746 static_cast<void *>(bitmap + 1 + static_cast<unsigned int>(roi.getTop() * width + roi.getLeft())),
747 I.getWidth() * sizeof(vpRGBa) - 1);
748 I[i][I.getWidth() - 1].A = 0;
749 }
750 }
751 break;
752 case V4L2_BGR24_FORMAT: // tested
753 if (roi == vpRect())
754 vpImageConvert::BGRToRGBa((unsigned char *)bitmap, (unsigned char *)I.bitmap, width, height, false);
755 else {
757 vpImageConvert::BGRToRGBa((unsigned char *)bitmap, (unsigned char *)tmp.bitmap, width, height, false);
758 vpImageTools::crop(tmp, roi, I);
759 }
760 break;
761 case V4L2_YUYV_FORMAT: // tested
762 if (roi == vpRect())
763 vpImageConvert::YUYVToRGBa((unsigned char *)bitmap, (unsigned char *)I.bitmap, width, height);
764 else {
766 vpImageConvert::YUYVToRGBa((unsigned char *)bitmap, (unsigned char *)tmp.bitmap, width, height);
767 vpImageTools::crop(tmp, roi, I);
768 }
769 break;
770 default:
771 std::cout << "V4l2 conversion not handled" << std::endl;
772 break;
773 }
774
775 queueAll();
776}
777
794{
795 if (field == 2)
796 return 0; // top field
797 else if (field == 3)
798 return 1; // bottom field;
799 else {
800 close();
801
802 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "V4l2 returns a bad frame field"));
803 return false;
804 }
805}
806
821{
822 this->m_framerate = framerate;
823
824 if (framerate == vpV4l2Grabber::framerate_25fps)
825 setFrameFormat(V4L2_IMAGE_FORMAT);
826 else
827 setFrameFormat(V4L2_FRAME_FORMAT);
828}
829
838
840
845{
846 stopStreaming();
847 streaming = false;
848
849 if (fd >= 0) {
850 // vpTRACE("v4l2_close()");
851 v4l2_close(fd);
852 fd = -1;
853 }
854
855 if (inp != nullptr) {
856 delete[] inp;
857 inp = nullptr;
858 }
859 if (std != nullptr) {
860 delete[] std;
861 std = nullptr;
862 }
863 if (fmt != nullptr) {
864 delete[] fmt;
865 fmt = nullptr;
866 }
867 if (ctl != nullptr) {
868 delete[] ctl;
869 ctl = nullptr;
870 }
871 if (buf_v4l2 != nullptr) {
872 delete[] buf_v4l2;
873 buf_v4l2 = nullptr;
874 }
875 if (buf_me != nullptr) {
876 delete[] buf_me;
877 buf_me = nullptr;
878 }
879}
880
893{
894 /* Open Video Device */
895 struct stat st;
896
897 if (-1 == stat(device.c_str(), &st)) {
898 fprintf(stderr, "Cannot identify '%s': %d, %s\n", device.c_str(), errno, strerror(errno));
899 throw(vpFrameGrabberException(vpFrameGrabberException::initializationError, "Cannot identify video device"));
900 }
901
902 if (!S_ISCHR(st.st_mode)) {
903 fprintf(stderr, "%s is no device\n", device.c_str());
904 throw(vpFrameGrabberException(vpFrameGrabberException::initializationError, "No device"));
905 }
906 fd = v4l2_open(device.c_str(), O_RDWR | O_NONBLOCK, 0);
907 if (fd < 0) {
908 close();
909
910 vpERROR_TRACE("No video device \"%s\"\n", device.c_str());
911 throw(vpFrameGrabberException(vpFrameGrabberException::initializationError, "Can't access to video device"));
912 }
913
914 if (inp != nullptr) {
915 delete[] inp;
916 inp = nullptr;
917 }
918 if (std != nullptr) {
919 delete[] std;
920 std = nullptr;
921 }
922 if (fmt != nullptr) {
923 delete[] fmt;
924 fmt = nullptr;
925 }
926 if (ctl != nullptr) {
927 delete[] ctl;
928 ctl = nullptr;
929 }
930 if (buf_v4l2 != nullptr) {
931 delete[] buf_v4l2;
932 buf_v4l2 = nullptr;
933 }
934 if (buf_me != nullptr) {
935 delete[] buf_me;
936 buf_me = nullptr;
937 }
938
939 inp = new struct v4l2_input[vpV4l2Grabber::MAX_INPUTS];
940 std = new struct v4l2_standard[vpV4l2Grabber::MAX_NORM];
941 fmt = new struct v4l2_fmtdesc[vpV4l2Grabber::MAX_FORMAT];
942 ctl = new struct v4l2_queryctrl[vpV4l2Grabber::MAX_CTRL * 2];
943 buf_v4l2 = new struct v4l2_buffer[vpV4l2Grabber::MAX_BUFFERS];
944 buf_me = new struct ng_video_buf[vpV4l2Grabber::MAX_BUFFERS];
945
946 /* Querry Video Device Capabilities */
947 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
948 close();
949 fprintf(stderr, "%s is no V4L2 device\n", device.c_str());
950 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Is not a V4L2 device"));
951 }
952 if (m_verbose) {
953 fprintf(stdout,
954 "v4l2 info:\n"
955 " device: %s\n"
956 " %s %d.%d.%d / %s @ %s\n",
957 device.c_str(), cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff,
958 cap.card, cap.bus_info);
959 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
960 fprintf(stdout, " Support overlay\n");
961 else
962 fprintf(stdout, " Does not support overlay\n");
963 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
964 fprintf(stdout, " Support capture\n");
965 else
966 fprintf(stdout, " Does not support capture\n");
967 if (cap.capabilities & V4L2_CAP_TUNER)
968 fprintf(stdout, " Support tuning\n");
969 else
970 fprintf(stdout, " Does not support tuning\n");
971 if (cap.capabilities & V4L2_CAP_STREAMING)
972 fprintf(stdout, " Support streaming capture.\n");
973 else
974 fprintf(stdout, " Does not support streaming capture\n");
975 if (cap.capabilities & V4L2_CAP_ASYNCIO)
976 fprintf(stdout, " Support asynchronous I/O methods\n");
977 else
978 fprintf(stdout, " Does not support asynchronous I/O methods\n");
979 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
980 fprintf(stdout, " Support time per frame field\n");
981 else
982 fprintf(stdout, " Does not support time per frame field\n");
983 // Get framerate
984 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
985 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
986 fprintf(stdout, " Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
987 }
988 }
989
990 getCapabilities();
991}
992
999void vpV4l2Grabber::getCapabilities()
1000{
1001 for (__u32 ninputs = 0; ninputs < MAX_INPUTS; ninputs++) {
1002 inp[ninputs].index = ninputs;
1003 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1004 break;
1005 }
1006 for (__u32 nstds = 0; nstds < MAX_NORM; nstds++) {
1007 std[nstds].index = nstds;
1008 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1009 break;
1010 }
1011 for (__u32 nfmts = 0; nfmts < MAX_FORMAT; nfmts++) {
1012 fmt[nfmts].index = nfmts;
1013 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1014 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1015 break;
1016 }
1017
1018 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1020 close();
1021
1022 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't get video parameters"));
1023 }
1024}
1025
1039void vpV4l2Grabber::setFormat()
1040{
1041 fmt_me.width = width;
1042 fmt_me.height = height;
1043 // fmt_me.bytesperline = width; // bad (normally width * depth / 8), but
1044 // works
1045 // because initialized later by an ioctl call to VIDIOC_S_FMT
1046
1047 switch (m_pixelformat) {
1048 case V4L2_GREY_FORMAT:
1049 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1050 if (m_verbose)
1051 fprintf(stdout, "v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1052 break;
1053 case V4L2_RGB24_FORMAT:
1054 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1055 if (m_verbose)
1056 fprintf(stdout, "v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1057 break;
1058 case V4L2_RGB32_FORMAT:
1059 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1060 if (m_verbose)
1061 fprintf(stdout, "v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1062 break;
1063 case V4L2_BGR24_FORMAT:
1064 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1065 if (m_verbose)
1066 fprintf(stdout, "v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1067 break;
1068 case V4L2_YUYV_FORMAT:
1069 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1070 if (m_verbose)
1071 fprintf(stdout, "v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1072 break;
1073
1074 default:
1075 close();
1076
1077 throw(vpFrameGrabberException(vpFrameGrabberException::settingError, "Bad format, probably do to a wrong scale"));
1078 }
1079
1080 /* Get Video Format */
1081 vpCLEAR(fmt_v4l2);
1082
1083 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1084
1085 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1086 close();
1087
1088 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't get video format"));
1089 }
1090 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1091 fmt_v4l2.fmt.pix.width = fmt_me.width;
1092 fmt_v4l2.fmt.pix.height = fmt_me.height;
1093 // printf("1 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width,
1094 // fmt_v4l2.fmt.pix.height);
1095
1096 switch (m_frameformat) {
1097 case V4L2_FRAME_FORMAT:
1098 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1099 if (m_verbose) {
1100 fprintf(stdout, "v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1101 }
1102 break;
1103 case V4L2_IMAGE_FORMAT:
1104 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1105 if (m_verbose) {
1106 fprintf(stdout, "v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1107 }
1108 break;
1109 default:
1110 close();
1111
1112 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Unrecognized frame format"));
1113 }
1114
1115 // height and width of the captured image or frame
1116 if (m_frameformat == V4L2_FRAME_FORMAT && height > FRAME_SIZE) {
1118 }
1119 // printf("2 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width,
1120 // fmt_v4l2.fmt.pix.height);
1121
1122 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1123 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't set video format"));
1124 }
1125
1126 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1127 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Bad pixel format"));
1128 }
1129
1130 /* Buggy driver paranoia. */
1131 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1132 if (fmt_v4l2.fmt.pix.bytesperline < min)
1133 fmt_v4l2.fmt.pix.bytesperline = min;
1134 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1135 if (fmt_v4l2.fmt.pix.sizeimage < min)
1136 fmt_v4l2.fmt.pix.sizeimage = min;
1137
1138 fmt_me.width = fmt_v4l2.fmt.pix.width;
1139 fmt_me.height = fmt_v4l2.fmt.pix.height;
1140 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1141
1142 if (m_verbose) {
1143 fprintf(stdout,
1144 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1145 "per line)\n",
1146 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1147 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1148 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1149 }
1150}
1159void vpV4l2Grabber::startStreaming()
1160{
1161 if (streaming == true) { // Acquisition in process.
1162 stopStreaming();
1163 streaming = false;
1164 }
1165
1166 /* setup buffers */
1167 memset(&(reqbufs), 0, sizeof(reqbufs));
1168 reqbufs.count = m_nbuffers;
1169 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1170 reqbufs.memory = V4L2_MEMORY_MMAP;
1171
1172 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1173 if (EINVAL == errno) {
1174 fprintf(stderr,
1175 "%s does not support "
1176 "memory mapping\n",
1177 device.c_str());
1178 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Does not support memory mapping"));
1179 }
1180 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't require video buffers"));
1181 }
1182
1183 for (unsigned i = 0; i < reqbufs.count; i++) {
1184 // Clear the buffer
1185 memset(&(buf_v4l2[i]), 0, sizeof(buf_v4l2[i]));
1186 buf_v4l2[i].index = i;
1187 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1188 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1189 buf_v4l2[i].length = 0;
1190 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1191 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't query video buffers"));
1192 }
1193 memcpy(&buf_me[i].fmt, &fmt_me, sizeof(ng_video_fmt));
1194 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1195
1196 buf_me[i].data = (unsigned char *)v4l2_mmap(nullptr, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1197 (off_t)buf_v4l2[i].m.offset);
1198
1199 if (buf_me[i].data == MAP_FAILED) {
1200 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't map memory"));
1201 }
1202
1203 buf_me[i].refcount = 0;
1204
1205 if (m_verbose)
1206 printBufInfo(buf_v4l2[i]);
1207 }
1208
1209 /* queue up all buffers */
1210 queueAll();
1211
1212 /* Set video stream capture on */
1213 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1214 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't start streaming"));
1215 }
1216
1217 streaming = true;
1218}
1219
1226void vpV4l2Grabber::stopStreaming()
1227{
1228 // nothing to do if (fd < 0) or if (streaming == false)
1229 if ((fd >= 0) && (streaming == true)) {
1230
1231 // vpTRACE(" Stop the streaming...");
1232 /* stop capture */
1233 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1234 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1235 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't stop streaming"));
1236 }
1237 /* free buffers */
1238 for (unsigned int i = 0; i < reqbufs.count; i++) {
1239 if (m_verbose)
1240 printBufInfo(buf_v4l2[i]);
1241 // vpTRACE("v4l2_munmap()");
1242
1243 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1244 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't unmap memory"));
1245 }
1246 }
1247 queue = 0;
1248 waiton_cpt = 0;
1249 streaming = false;
1250 }
1251}
1252
1266unsigned char *vpV4l2Grabber::waiton(__u32 &index, struct timeval &timestamp)
1267{
1268 struct v4l2_buffer buf;
1269 struct timeval tv;
1270 fd_set rdset;
1271
1272 /* wait for the next frame */
1273again:
1274
1275 tv.tv_sec = 30;
1276 tv.tv_usec = 0;
1277 FD_ZERO(&rdset);
1278 FD_SET(static_cast<unsigned int>(fd), &rdset);
1279 switch (select(fd + 1, &rdset, nullptr, nullptr, &tv)) {
1280 case -1:
1281 if (EINTR == errno)
1282 goto again;
1283 index = 0;
1284 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't access to the frame"));
1285 return nullptr;
1286 case 0:
1287 index = 0;
1288 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "Can't access to the frame: timeout"));
1289 return nullptr;
1290 }
1291
1292 /* get it */
1293 memset(&buf, 0, sizeof(buf));
1294 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1295 buf.memory = V4L2_MEMORY_MMAP;
1296 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1297 index = 0;
1298 switch (errno) {
1299 case EAGAIN:
1300 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_DQBUF: EAGAIN"));
1301 break;
1302 case EINVAL:
1303 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_DQBUF: EINVAL"));
1304 break;
1305 case ENOMEM:
1306 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_DQBUF: ENOMEM"));
1307 break;
1308 default:
1309 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_DQBUF"));
1310 break;
1311 }
1312 return nullptr;
1313 }
1314
1315 waiton_cpt++;
1316 buf_v4l2[buf.index] = buf;
1317
1318 index = buf.index;
1319
1320 field = buf_v4l2[index].field;
1321
1322 timestamp = buf_v4l2[index].timestamp;
1323
1324 // if(m_verbose)
1325 // {
1326 // vpERROR_TRACE("field: %d\n", buf_v4l2[index].field);
1327
1328 // vpERROR_TRACE("data adress : 0x%p\n", buf_me[buf.index].data);
1329 // }
1330 return buf_me[buf.index].data;
1331}
1332
1338int vpV4l2Grabber::queueBuffer()
1339{
1340 unsigned int frame = queue % reqbufs.count;
1341 int rc;
1342
1343 if (0 != buf_me[frame].refcount) {
1344 if (0 != queue - waiton_cpt)
1345 return -1;
1346 fprintf(stderr, "v4l2: waiting for a free buffer..............\n");
1347 // ng_waiton_video_buf(h->buf_me+frame);
1348 std::cout << "Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1349 }
1350
1351 // std::cout << "frame: " << frame << std::endl;
1352 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1353 if (0 == rc)
1354 queue++;
1355 else {
1356 switch (errno) {
1357 case EAGAIN:
1358 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_QBUF: EAGAIN"));
1359 break;
1360 case EINVAL:
1361 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_QBUF: EINVAL"));
1362 break;
1363 case ENOMEM:
1364 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_QBUF: ENOMEM"));
1365 break;
1366 default:
1367 throw(vpFrameGrabberException(vpFrameGrabberException::otherError, "VIDIOC_QBUF"));
1368 break;
1369 }
1370 }
1371 return rc;
1372}
1373
1379void vpV4l2Grabber::queueAll()
1380{
1381 for (;;) {
1382 if (queue - waiton_cpt >= reqbufs.count) {
1383 return;
1384 }
1385 if (0 != queueBuffer()) {
1386 return;
1387 }
1388 }
1389}
1390
1396void vpV4l2Grabber::printBufInfo(struct v4l2_buffer buf)
1397{
1398 std::string type;
1399
1400 switch (buf.type) {
1401 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1402 type = "video-cap";
1403 break;
1404 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1405 type = "video-over";
1406 break;
1407 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1408 type = "video-out";
1409 break;
1410 case V4L2_BUF_TYPE_VBI_CAPTURE:
1411 type = "vbi-cap";
1412 break;
1413 case V4L2_BUF_TYPE_VBI_OUTPUT:
1414 type = "vbi-out";
1415 break;
1416 default:
1417 type = "unknown";
1418 break;
1419 }
1420
1421 fprintf(stdout, "v4l2: buf %d: type %d (%s) ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n", buf.index, buf.type,
1422 type.c_str(), buf.m.userptr, buf.m.offset, buf.length, buf.length, buf.bytesused);
1423}
1424
1446{
1447 this->acquire(I);
1448 return *this;
1449}
1450
1472{
1473 this->acquire(I);
1474 return *this;
1475}
1476END_VISP_NAMESPACE
1477#elif !defined(VISP_BUILD_SHARED_LIBS)
1478// Work around to avoid warning: libvisp_sensor.a(vpV4l2Grabber.cpp.o) has no symbols
1479void dummy_vpV4l2Grabber() { }
1480#endif
Error that can be emitted by the vpFrameGrabber class and its derivates.
@ settingError
Grabber settings error.
@ initializationError
Grabber initialization error.
@ otherError
Grabber returned an other error.
unsigned int height
Number of rows in the image.
bool init
Set to true if the frame grabber has been initialized.
unsigned int width
Number of columns in the image.
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void crop(const vpImage< Type > &I, double roi_top, double roi_left, unsigned int roi_height, unsigned int roi_width, vpImage< Type > &crop, unsigned int v_scale=1, unsigned int h_scale=1)
Definition of the vpImage class member functions.
Definition vpImage.h:131
Type * bitmap
points toward the bitmap
Definition vpImage.h:135
Defines a rectangle in the plane.
Definition vpRect.h:79
double getWidth() const
Definition vpRect.h:227
double getLeft() const
Definition vpRect.h:173
double getHeight() const
Definition vpRect.h:166
double getTop() const
Definition vpRect.h:192
@ framerate_25fps
25 frames per second
void setWidth(unsigned w)
static const __u32 MAX_NORM
void setFramerate(vpV4l2FramerateType framerate)
vpV4l2Grabber & operator>>(vpImage< unsigned char > &I)
static const unsigned int MAX_CTRL
static const unsigned int MAX_BUFFERS
static const __u32 MAX_INPUTS
static const unsigned int DEFAULT_INPUT
vpV4l2Grabber(const vpV4l2Grabber &)=delete
vpV4l2PixelFormatType getPixelFormat()
static const unsigned int FRAME_SIZE
static const unsigned int DEFAULT_SCALE
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
static const __u32 MAX_FORMAT
void open(vpImage< unsigned char > &I)
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setHeight(unsigned h)
virtual ~vpV4l2Grabber()
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
void setNBuffers(unsigned nbuffers)
vpV4l2FramerateType getFramerate()
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)
#define vpERROR_TRACE
Definition vpDebug.h:423