Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpV4l2Grabber.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 
44 #include <visp3/core/vpConfig.h>
45 
46 #ifdef VISP_HAVE_V4L2
47 
48 #include <stdio.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <sys/time.h>
52 #include <sys/ioctl.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <fcntl.h>
56 #include <stdio.h>
57 #include <sys/mman.h>
58 #include <errno.h>
59 #include <iostream>
60 
61 #include <visp3/sensor/vpV4l2Grabber.h>
62 #include <visp3/core/vpFrameGrabberException.h>
63 //#include <visp3/io/vpImageIo.h>
64 #include <visp3/core/vpImageConvert.h>
65 #include <visp3/core/vpImageTools.h>
66 
67 const unsigned int vpV4l2Grabber::DEFAULT_INPUT = 2;
68 const unsigned int vpV4l2Grabber::DEFAULT_SCALE = 2;
69 const __u32 vpV4l2Grabber::MAX_INPUTS = 16;
70 const __u32 vpV4l2Grabber::MAX_NORM = 16;
71 const __u32 vpV4l2Grabber::MAX_FORMAT = 32;
72 const unsigned int vpV4l2Grabber::MAX_CTRL = 32;
73 const unsigned int vpV4l2Grabber::MAX_BUFFERS = 32;
74 const unsigned int vpV4l2Grabber::FRAME_SIZE = 288;
75 #define vpCLEAR(x) memset (&(x), 0, sizeof (x))
76 
150  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
151  fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
152  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
153  m_input(vpV4l2Grabber::DEFAULT_INPUT),
154  m_framerate(vpV4l2Grabber::framerate_25fps),
155  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
156  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
157 {
158  setDevice("/dev/video0");
159  setNBuffers(3);
164 
165  init = false;
166 }
167 
209  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
210  fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
211  waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0), streaming(false),
212  m_input(vpV4l2Grabber::DEFAULT_INPUT),
213  m_framerate(vpV4l2Grabber::framerate_25fps),
214  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
215  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
216 {
217  setDevice("/dev/video0");
218  setNBuffers(3);
223 
224  init = false;
225 }
226 
227 
258 vpV4l2Grabber::vpV4l2Grabber(unsigned input, unsigned scale)
259  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
260  fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
261  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
262  m_input(vpV4l2Grabber::DEFAULT_INPUT),
263  m_framerate(vpV4l2Grabber::framerate_25fps),
264  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
265  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
266 {
267  setDevice("/dev/video0");
268  setNBuffers(3);
270  setInput(input);
271  setScale(scale);
272 
273  init = false;
274 }
275 
307 vpV4l2Grabber::vpV4l2Grabber(vpImage<unsigned char> &I, unsigned input, unsigned scale )
308  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
309  fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
310  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
311  m_input(vpV4l2Grabber::DEFAULT_INPUT),
312  m_framerate(vpV4l2Grabber::framerate_25fps),
313  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
314  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
315 {
316  setDevice("/dev/video0");
317  setNBuffers(3);
319  setInput(input);
320  setScale(scale);
321 
322  init = false;
323 
324  open(I);
325 }
326 
359 vpV4l2Grabber::vpV4l2Grabber(vpImage<vpRGBa> &I, unsigned input, unsigned scale )
360  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
361  fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
362  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
363  m_input(vpV4l2Grabber::DEFAULT_INPUT),
364  m_framerate(vpV4l2Grabber::framerate_25fps),
365  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
366  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
367 {
368  setDevice("/dev/video0");
369  setNBuffers(3);
371  setInput(input);
372  setScale(scale);
373 
374  init = false;
375 
376  open(I);
377 }
378 
385 {
386  close() ;
387 }
388 
392 void
393 vpV4l2Grabber::setInput(unsigned input)
394 {
395  this->m_input = input;
396 }
397 
410 void
411 vpV4l2Grabber::setScale(unsigned scale)
412 {
413  if ((scale <1) || (scale >16))
414  {
415  close();
416 
417  vpERROR_TRACE("Wrong scale %d, scale should be between 1 and 16",scale) ;
419  "Wrong scale") );
420  }
421 
422  setWidth(640/scale);
423  setHeight(480/scale);
424 }
425 
436 void
438 {
439  open();
440 
441  if( v4l2_ioctl (fd, VIDIOC_S_INPUT, &m_input) == -1 )
442  {
443  std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
444  }
445 
446  vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
447 
448  try {
449  setFormat();
450 
451  startStreaming();
452  }
453  catch(...) {
454  if (m_verbose) {
455  std::cout << "Requested pixel format [" << req_pixelformat
456  << "] not compatible with camera" << std::endl;
457  std::cout << "Try to found a compatible pixel format..." << std::endl;
458  }
459 
460  // try to fing a compatible format
461  for (int format=0; format< (int)V4L2_MAX_FORMAT; format ++) {
462  if (format == req_pixelformat) {
463  continue;
464  }
465  try {
467  setFormat();
468  startStreaming();
469  if (m_verbose)
470  std::cout << "This format [" << m_pixelformat
471  << "] is compatible with camera" << std::endl;
472 
473  break;
474  }
475  catch (...) {
476  if (m_verbose)
477  std::cout << "This format [" << m_pixelformat
478  << "] is not compatible with camera" << std::endl;
479  if (format == (int)V4L2_MAX_FORMAT) {
480  std::cout << "No pixel format compatible with the camera was found" << std::endl;
481  close();
482 
484  "No pixel format compatible with the camera was found"));
485  }
486  }
487  }
488  }
489 
490  I.resize(height, width) ;
491 
492  init = true;
493 }
494 
504 void
506 {
507  open();
508 
509  if( v4l2_ioctl (fd, VIDIOC_S_INPUT, &m_input) == -1 )
510  {
511  std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
512  }
513 
514  vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
515 
516  try {
517  setFormat();
518 
519  startStreaming();
520  }
521  catch(...) {
522  if (m_verbose) {
523  std::cout << "Requested pixel format [" << m_pixelformat
524  << "] not compatible with camera" << std::endl;
525  std::cout << "Try to found a compatible pixel format..." << std::endl;
526  }
527 
528  // try to fing a compatible format
529  for (int format=0; format< (int)V4L2_MAX_FORMAT; format ++) {
530  if (format == req_pixelformat) {
531  continue;
532  }
533  try {
535  setFormat();
536  startStreaming();
537  if (m_verbose)
538  std::cout << "This format [" << m_pixelformat
539  << "] is compatible with camera" << std::endl;
540 
541  break;
542  }
543  catch (...) {
544  if (m_verbose)
545  std::cout << "This format [" << m_pixelformat
546  << "] is not compatible with camera" << std::endl;
547 
548  }
549  }
550  }
551 
552  I.resize(height, width) ;
553 
554  init = true;
555 }
556 
567 void
569 {
570  struct timeval timestamp;
571  vpRect roi;
572 
573  acquire(I, timestamp, roi);
574 }
575 
587 void
589 {
590  struct timeval timestamp;
591 
592  acquire(I, timestamp, roi);
593 }
594 
612 void
613 vpV4l2Grabber::acquire(vpImage<unsigned char> &I, struct timeval &timestamp, const vpRect &roi)
614 {
615  if (init==false)
616  {
617  open(I);
618  }
619 
620  if (init==false)
621  {
622  close();
623 
625  "V4l2 frame grabber not initialized") );
626  }
627 
628  unsigned char *bitmap ;
629  bitmap = waiton(index_buffer, timestamp);
630 
631  if (roi == vpRect())
632  I.resize(height, width);
633  else
634  I.resize((unsigned int)roi.getHeight(), (unsigned int)roi.getWidth());
635  switch(m_pixelformat) {
636  case V4L2_GREY_FORMAT:
637  if (roi == vpRect())
638  memcpy(I.bitmap, bitmap, height * width*sizeof(unsigned char));
639  else
640  vpImageTools::crop(bitmap, width, height, roi, I);
641  break;
642  case V4L2_RGB24_FORMAT: // tested
643  if (roi == vpRect())
644  vpImageConvert::RGBToGrey((unsigned char *) bitmap, I.bitmap, width*height);
645  else {
646  vpImage<unsigned char> tmp(height, width);
647  vpImageConvert::RGBToGrey((unsigned char *) bitmap, tmp.bitmap, width*height);
648  vpImageTools::crop(tmp, roi, I);
649  }
650  break;
651  case V4L2_RGB32_FORMAT:
652  if (roi == vpRect())
653  vpImageConvert::RGBaToGrey((unsigned char *) bitmap, I.bitmap, width*height);
654  else {
655  vpImage<unsigned char> tmp(height, width);
656  vpImageConvert::RGBaToGrey((unsigned char *) bitmap, tmp.bitmap, width*height);
657  vpImageTools::crop(tmp, roi, I);
658  }
659 
660  break;
661  case V4L2_BGR24_FORMAT: // tested
662  if (roi == vpRect())
663  vpImageConvert::BGRToGrey( (unsigned char *) bitmap, I.bitmap, width, height, false);
664  else {
665  vpImage<unsigned char> tmp(height, width);
666  vpImageConvert::BGRToGrey( (unsigned char *) bitmap, tmp.bitmap, width, height, false);
667  vpImageTools::crop(tmp, roi, I);
668  }
669  break;
670  case V4L2_YUYV_FORMAT: // tested
671  if (roi == vpRect())
672  vpImageConvert::YUYVToGrey( (unsigned char *) bitmap, I.bitmap, width*height);
673  else {
674  vpImage<unsigned char> tmp(height, width);
675  vpImageConvert::YUYVToGrey( (unsigned char *) bitmap, tmp.bitmap, width*height);
676  vpImageTools::crop(tmp, roi, I);
677  }
678  break;
679  default:
680  std::cout << "V4L2 conversion not handled" << std::endl;
681  break;
682  }
683 
684  queueAll();
685 }
686 
697 void
699 {
700  struct timeval timestamp;
701  vpRect roi;
702 
703  acquire(I, timestamp, roi);
704 }
705 
717 void
719 {
720  struct timeval timestamp;
721 
722  acquire(I, timestamp, roi);
723 }
724 
742 void
743 vpV4l2Grabber::acquire(vpImage<vpRGBa> &I, struct timeval &timestamp, const vpRect &roi)
744 {
745  if (init==false)
746  {
747  open(I);
748  }
749 
750  if (init==false)
751  {
752  close();
753 
755  "V4l2 frame grabber not initialized") );
756  }
757 
758  unsigned char *bitmap ;
759  bitmap = waiton(index_buffer, timestamp);
760 
761  if (roi == vpRect())
762  I.resize(height, width);
763  else
764  I.resize((unsigned int)roi.getHeight(), (unsigned int)roi.getWidth());
765 
766  // The framegrabber acquire aRGB format. We just shift the data from 1 byte all the data and initialize the last byte
767 
768  switch(m_pixelformat) {
769  case V4L2_GREY_FORMAT:
770  if (roi == vpRect())
771  vpImageConvert::GreyToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width*height);
772  else
773  vpImageTools::crop(bitmap, width, height, roi, I);
774  break;
775  case V4L2_RGB24_FORMAT: // tested
776  if (roi == vpRect())
777  vpImageConvert::RGBToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width*height);
778  else {
779  vpImage<vpRGBa> tmp(height, width);
780  vpImageConvert::RGBToRGBa((unsigned char *) bitmap, (unsigned char *) tmp.bitmap, width*height);
781  vpImageTools::crop(tmp, roi, I);
782  }
783  break;
784  case V4L2_RGB32_FORMAT:
785  if (roi == vpRect()) {
786  // The framegrabber acquire aRGB format. We just shift the data
787  // from 1 byte all the data and initialize the last byte
788  memcpy(I.bitmap, bitmap + 1, height * width * sizeof(vpRGBa) - 1);
789  I[height-1][width-1].A = 0;
790  }
791  else {
792  for(unsigned int i=0; i<I.getHeight(); i++) {
793  memcpy(I.bitmap, bitmap + 1 + (unsigned int)(roi.getTop()*width + roi.getLeft()), I.getWidth() * sizeof(vpRGBa) - 1);
794  I[i][I.getWidth()-1].A = 0;
795  }
796  }
797  break;
798  case V4L2_BGR24_FORMAT: // tested
799  if (roi == vpRect())
800  vpImageConvert::BGRToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width, height, false);
801  else {
802  vpImage<vpRGBa> tmp(height, width);
803  vpImageConvert::BGRToRGBa((unsigned char *) bitmap, (unsigned char *) tmp.bitmap, width, height, false);
804  vpImageTools::crop(tmp, roi, I);
805  }
806  break;
807  case V4L2_YUYV_FORMAT: // tested
808  if (roi == vpRect())
809  vpImageConvert::YUYVToRGBa( (unsigned char *) bitmap, (unsigned char *) I.bitmap, width, height);
810  else {
811  vpImage<vpRGBa> tmp(height, width);
812  vpImageConvert::YUYVToRGBa((unsigned char *) bitmap, (unsigned char *) tmp.bitmap, width, height);
813  vpImageTools::crop(tmp, roi, I);
814  }
815  break;
816  default:
817  std::cout << "V4l2 conversion not handled" << std::endl;
818  break;
819  }
820 
821  queueAll();
822 }
839 bool
841 {
842  if(field == 2) return 0; //top field
843  else if (field == 3) return 1; //bottom field;
844  else {
845  close();
846 
848  "V4l2 returns a bad frame field") );
849  return false;
850  }
851 }
866 void
868 {
869  this->m_framerate = framerate;
870 
871  if (framerate == vpV4l2Grabber::framerate_25fps)
872  setFrameFormat(V4L2_IMAGE_FORMAT);
873  else
874  setFrameFormat(V4L2_FRAME_FORMAT);
875 }
876 
889 {
890  return m_framerate;
891 }
892 
893 
897 void
899 {
900  stopStreaming();
901  streaming = false;
902 
903  if (fd >= 0){
904  //vpTRACE("v4l2_close()");
905  v4l2_close (fd);
906  fd = -1;
907  }
908 
909  if (inp != NULL) { delete [] inp; inp = NULL; }
910  if (std != NULL) { delete [] std; std = NULL; }
911  if (fmt != NULL) { delete [] fmt; fmt = NULL; }
912  if (ctl != NULL) { delete [] ctl; ctl = NULL; }
913  if (buf_v4l2 != NULL) { delete [] buf_v4l2; buf_v4l2 = NULL; }
914  if (buf_me != NULL) { delete [] buf_me; buf_me = NULL; }
915 }
916 
928 void
929 vpV4l2Grabber::open()
930 {
931  /* Open Video Device */
932  struct stat st;
933 
934  if (-1 == stat (device, &st)) {
935  fprintf (stderr, "Cannot identify '%s': %d, %s\n",
936  device, errno, strerror (errno));
938  "Cannot identify video device") );
939 
940  }
941 
942  if (!S_ISCHR (st.st_mode)) {
943  fprintf (stderr, "%s is no device\n", device);
945  "No device") );
946 
947  }
948  fd = v4l2_open (device, O_RDWR | O_NONBLOCK, 0);
949  if (fd < 0) {
950  close();
951 
952  vpERROR_TRACE ("No video device \"%s\"\n", device);
954  "Can't access to video device") );
955 
956  }
957 
958  if (inp != NULL) { delete [] inp; inp = NULL; }
959  if (std != NULL) { delete [] std; std = NULL; }
960  if (fmt != NULL) { delete [] fmt; fmt = NULL; }
961  if (ctl != NULL) { delete [] ctl; ctl = NULL; }
962  if (buf_v4l2 != NULL) { delete [] buf_v4l2; buf_v4l2 = NULL; }
963  if (buf_me != NULL) { delete [] buf_me; buf_me = NULL; }
964 
965  inp = new struct v4l2_input [vpV4l2Grabber::MAX_INPUTS];
966  std = new struct v4l2_standard [vpV4l2Grabber::MAX_NORM];
967  fmt = new struct v4l2_fmtdesc [vpV4l2Grabber::MAX_FORMAT];
968  ctl = new struct v4l2_queryctrl [vpV4l2Grabber::MAX_CTRL*2];
969  buf_v4l2 = new struct v4l2_buffer [vpV4l2Grabber::MAX_BUFFERS];
970  buf_me = new struct ng_video_buf [vpV4l2Grabber::MAX_BUFFERS];
971 
972  /* Querry Video Device Capabilities */
973  if ( v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap) == -1 ) {
974  close();
975  fprintf (stderr, "%s is no V4L2 device\n", device);
977  "Is not a V4L2 device") );
978  }
979  if (m_verbose) {
980  fprintf(stdout, "v4l2 info:\n"
981  " device: %s\n"
982  " %s %d.%d.%d / %s @ %s\n",
983  device,
984  cap.driver,
985  (cap.version >> 16) & 0xff,
986  (cap.version >> 8) & 0xff,
987  cap.version & 0xff,
988  cap.card, cap.bus_info);
989  if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
990  fprintf(stdout, " Support overlay\n");
991  else
992  fprintf(stdout, " Does not support overlay\n");
993  if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
994  fprintf(stdout, " Support capture\n");
995  else
996  fprintf(stdout, " Does not support capture\n");
997  if (cap.capabilities & V4L2_CAP_TUNER)
998  fprintf(stdout, " Support tuning\n");
999  else
1000  fprintf(stdout, " Does not support tuning\n");
1001  if (cap.capabilities & V4L2_CAP_STREAMING)
1002  fprintf(stdout, " Support streaming capture.\n");
1003  else
1004  fprintf(stdout, " Does not support streaming capture\n");
1005  if(cap.capabilities & V4L2_CAP_ASYNCIO)
1006  fprintf(stdout, " Support asynchronous I/O methods\n");
1007  else
1008  fprintf(stdout, " Does not support asynchronous I/O methods\n");
1009  if(cap.capabilities & V4L2_CAP_TIMEPERFRAME)
1010  fprintf(stdout, " Support time per frame field\n");
1011  else
1012  fprintf(stdout, " Does not support time per frame field\n");
1013  // Get framerate
1014  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1015  if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
1016  fprintf(stdout, " Current acquisition framerate: %d fps\n",
1017  streamparm.parm.output.timeperframe.denominator);
1018  }
1019  }
1020 
1021  getCapabilities();
1022 }
1023 
1030 void
1031 vpV4l2Grabber::getCapabilities()
1032 {
1033  for (__u32 ninputs = 0; ninputs < MAX_INPUTS; ninputs++) {
1034  inp[ninputs].index = ninputs;
1035  if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1036  break;
1037  }
1038  for (__u32 nstds = 0; nstds < MAX_NORM; nstds++) {
1039  std[nstds].index = nstds;
1040  if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1041  break;
1042 
1043  }
1044  for (__u32 nfmts = 0; nfmts < MAX_FORMAT; nfmts++) {
1045  fmt[nfmts].index = nfmts;
1046  fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1047  if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1048  break;
1049  }
1050 
1051  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1052  if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1)
1053  {
1054  close();
1055 
1057  "Can't get video parameters") );
1058  }
1059 }
1060 
1074 void
1075 vpV4l2Grabber::setFormat()
1076 {
1077  fmt_me.width = width;
1078  fmt_me.height = height;
1079  //fmt_me.bytesperline = width; // bad (normally width * depth / 8), but works
1080  // because initialized later by an ioctl call to VIDIOC_S_FMT
1081 
1082  switch(m_pixelformat) {
1083  case V4L2_GREY_FORMAT : fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1084  if (m_verbose)
1085  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1086  break;
1087  case V4L2_RGB24_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1088  if (m_verbose)
1089  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1090  break;
1091  case V4L2_RGB32_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1092  if (m_verbose)
1093  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1094  break;
1095  case V4L2_BGR24_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1096  if (m_verbose)
1097  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1098  break;
1099  case V4L2_YUYV_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1100  if (m_verbose)
1101  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1102  break;
1103 
1104  default:
1105  close();
1106 
1108  "Bad format, probably do to a wrong scale"));
1109  }
1110 
1111  /* Get Video Format */
1112  vpCLEAR (fmt_v4l2);
1113 
1114  fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1115 
1116  if (v4l2_ioctl (fd, VIDIOC_G_FMT, &fmt_v4l2) == -1 ) {
1117  close();
1118 
1120  "Can't get video format") );
1121  }
1122  fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1123  fmt_v4l2.fmt.pix.width = fmt_me.width;
1124  fmt_v4l2.fmt.pix.height = fmt_me.height;
1125  //printf("1 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width, fmt_v4l2.fmt.pix.height);
1126 
1127 
1128  switch (m_frameformat) {
1129  case V4L2_FRAME_FORMAT: fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1130  if (m_verbose) {
1131  fprintf(stdout,"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1132  }
1133  break;
1134  case V4L2_IMAGE_FORMAT: fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1135  if (m_verbose) {
1136  fprintf(stdout,"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1137  }
1138  break;
1139  default:
1140  close();
1141 
1143  "Unrecognized frame format") );
1144  }
1145 
1146  //height and width of the captured image or frame
1147  if( m_frameformat == V4L2_FRAME_FORMAT && height > FRAME_SIZE )
1148  {
1149  height = FRAME_SIZE;
1150  }
1151  //printf("2 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width, fmt_v4l2.fmt.pix.height);
1152 
1153  if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1155  "Can't set video format") );
1156  }
1157 
1158  if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1160  "Bad pixel format") );
1161  }
1162 
1163  /* Buggy driver paranoia. */
1164  unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1165  if (fmt_v4l2.fmt.pix.bytesperline < min)
1166  fmt_v4l2.fmt.pix.bytesperline = min;
1167  min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1168  if (fmt_v4l2.fmt.pix.sizeimage < min)
1169  fmt_v4l2.fmt.pix.sizeimage = min;
1170 
1171  fmt_me.width = fmt_v4l2.fmt.pix.width;
1172  fmt_me.height = fmt_v4l2.fmt.pix.height;
1173  fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1174 
1175  if (m_verbose) {
1176  fprintf(stdout,"v4l2: new capture params (%dx%d, %c%c%c%c, %d byte, %d bytes per line)\n",
1177  fmt_me.width, fmt_me.height,
1178  fmt_v4l2.fmt.pix.pixelformat & 0xff,
1179  (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff,
1180  (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1181  (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff,
1182  fmt_v4l2.fmt.pix.sizeimage,
1183  fmt_v4l2.fmt.pix.bytesperline);
1184  }
1185 
1186 }
1195 void
1196 vpV4l2Grabber::startStreaming()
1197 {
1198  if (streaming == true) { // Acquisition in process.
1199  stopStreaming();
1200  streaming = false;
1201  }
1202 
1203  /* setup buffers */
1204  memset (&(reqbufs), 0, sizeof (reqbufs));
1205  reqbufs.count = m_nbuffers;
1206  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1207  reqbufs.memory = V4L2_MEMORY_MMAP;
1208 
1209 
1210  if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1)
1211  {
1212  if (EINVAL == errno) {
1213  fprintf (stderr, "%s does not support "
1214  "memory mapping\n", device);
1216  "Does not support memory mapping") );
1217  }
1219  "Can't require video buffers") );
1220  }
1221 
1222  for (unsigned i = 0; i < reqbufs.count; i++) {
1223  // Clear the buffer
1224  memset (&(buf_v4l2[i]), 0, sizeof (buf_v4l2[i]));
1225  buf_v4l2[i].index = i;
1226  buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1227  buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1228  buf_v4l2[i].length = 0;
1229  if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1)
1230  {
1232  "Can't query video buffers") );
1233  }
1234  memcpy(&buf_me[i].fmt, &fmt_me, sizeof(ng_video_fmt));
1235  buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1236 
1237  // if (m_verbose)
1238  // std::cout << "1: buf_v4l2[" << i << "].length: " << buf_v4l2[i].length
1239  // << " buf_v4l2[" << i << "].offset: " << buf_v4l2[i].m.offset
1240  // << std::endl;
1241 
1242 
1243  buf_me[i].data = (unsigned char *) v4l2_mmap(NULL, buf_v4l2[i].length,
1244  PROT_READ | PROT_WRITE,
1245  MAP_SHARED,
1246  fd, (off_t)buf_v4l2[i].m.offset);
1247 
1248  if(buf_me[i].data == MAP_FAILED)
1249  {
1251  "Can't map memory") );
1252  }
1253 
1254  buf_me[i].refcount = 0;
1255 
1256  // if (m_verbose)
1257  // {
1258  // std::cout << "2: buf_v4l2[" << i << "].length: " << buf_v4l2[i].length
1259  // << " buf_v4l2[" << i << "].offset: " << buf_v4l2[i].m.offset
1260  // << std::endl;
1261  // std::cout << "2: buf_me[" << i << "].size: " << buf_me[i].size << std::endl;
1262  // }
1263 
1264  if (m_verbose)
1265  printBufInfo(buf_v4l2[i]);
1266  }
1267 
1268  /* queue up all buffers */
1269  queueAll();
1270 
1271  /* Set video stream capture on */
1272  if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type)<0)
1273  {
1275  "Can't start streaming") );
1276  }
1277 
1278  streaming = true;
1279 }
1280 
1287 void
1288 vpV4l2Grabber::stopStreaming()
1289 {
1290  //nothing to do if (fd < 0) or if (streaming == false)
1291  if ((fd >= 0) && (streaming == true)) {
1292 
1293  //vpTRACE(" Stop the streaming...");
1294  /* stop capture */
1295  fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1296  if (v4l2_ioctl(fd, VIDIOC_STREAMOFF,&fmt_v4l2.type)) {
1298  "Can't stop streaming") );
1299  }
1300  /* free buffers */
1301  for (unsigned int i = 0; i < reqbufs.count; i++) {
1302  if (m_verbose)
1303  printBufInfo(buf_v4l2[i]);
1304  //vpTRACE("v4l2_munmap()");
1305 
1306  if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1308  "Can't unmap memory") );
1309  }
1310  }
1311  queue = 0;
1312  waiton_cpt = 0;
1313  streaming = false;
1314  }
1315 }
1316 
1330 unsigned char *
1331 vpV4l2Grabber::waiton(__u32 &index, struct timeval &timestamp)
1332 {
1333  struct v4l2_buffer buf;
1334  struct timeval tv;
1335  fd_set rdset;
1336 
1337  /* wait for the next frame */
1338 again:
1339 
1340  tv.tv_sec = 30;
1341  tv.tv_usec = 0;
1342  FD_ZERO(&rdset);
1343  FD_SET(static_cast<unsigned int>(fd), &rdset);
1344  switch (select(fd + 1, &rdset, NULL, NULL, &tv)) {
1345  case -1:
1346  if (EINTR == errno)
1347  goto again;
1348  index = 0;
1350  "Can't access to the frame") );
1351  return NULL;
1352  case 0:
1353  index = 0;
1355  "Can't access to the frame: timeout") );
1356  return NULL;
1357  }
1358 
1359 
1360  /* get it */
1361  memset(&buf, 0, sizeof(buf));
1362  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1363  buf.memory = V4L2_MEMORY_MMAP; // Fabien manquait
1364  if (-1 == v4l2_ioctl(fd,VIDIOC_DQBUF, &buf)) {
1365  index = 0;
1366  switch(errno)
1367  {
1368  case EAGAIN:
1370  "VIDIOC_DQBUF: EAGAIN") );
1371  break;
1372  case EINVAL:
1374  "VIDIOC_DQBUF: EINVAL") );
1375  break;
1376  case ENOMEM:
1378  "VIDIOC_DQBUF: ENOMEM") );
1379  break;
1380  default:
1382  "VIDIOC_DQBUF") );
1383  break;
1384  }
1385  return NULL;
1386  }
1387 
1388  waiton_cpt++;
1389  buf_v4l2[buf.index] = buf;
1390 
1391  index = buf.index;
1392 
1393  field = buf_v4l2[index].field;
1394 
1395  timestamp = buf_v4l2[index].timestamp;
1396 
1397  // if(m_verbose)
1398  // {
1399  // vpERROR_TRACE("field: %d\n", buf_v4l2[index].field);
1400 
1401  // vpERROR_TRACE("data adress : 0x%p\n", buf_me[buf.index].data);
1402  // }
1403  return buf_me[buf.index].data;
1404 }
1405 
1411 int
1412 vpV4l2Grabber::queueBuffer()
1413 {
1414  unsigned int frame = queue % reqbufs.count;
1415  int rc;
1416 
1417 
1418  if (0 != buf_me[frame].refcount) {
1419  if (0 != queue - waiton_cpt)
1420  return -1;
1421  fprintf(stderr,"v4l2: waiting for a free buffer..............\n");
1422  //ng_waiton_video_buf(h->buf_me+frame);
1423  std::cout << "Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1424  }
1425 
1426  // std::cout << "frame: " << frame << std::endl;
1427  rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1428  if (0 == rc)
1429  queue++;
1430  else
1431  {
1432  switch(errno)
1433  {
1434  case EAGAIN:
1436  "VIDIOC_QBUF: EAGAIN") );
1437  break;
1438  case EINVAL:
1440  "VIDIOC_QBUF: EINVAL") );
1441  break;
1442  case ENOMEM:
1444  "VIDIOC_QBUF: ENOMEM") );
1445  break;
1446  default:
1448  "VIDIOC_QBUF") );
1449  break;
1450  }
1451  }
1452  return rc;
1453 }
1454 
1460 void
1461 vpV4l2Grabber::queueAll()
1462 {
1463  for (;;) {
1464  if (queue - waiton_cpt >= reqbufs.count) {
1465  return;
1466  }
1467  if (0 != queueBuffer()) {
1468  return;
1469  }
1470  }
1471 }
1472 
1478 void
1479 vpV4l2Grabber::printBufInfo(struct v4l2_buffer buf)
1480 {
1481  char type[40];
1482 
1483  switch(buf.type) {
1484  case V4L2_BUF_TYPE_VIDEO_CAPTURE: sprintf(type, "video-cap"); break;
1485  case V4L2_BUF_TYPE_VIDEO_OVERLAY: sprintf(type, "video-over"); break;
1486  case V4L2_BUF_TYPE_VIDEO_OUTPUT: sprintf(type, "video-out"); break;
1487  case V4L2_BUF_TYPE_VBI_CAPTURE: sprintf(type, "vbi-cap"); break;
1488  case V4L2_BUF_TYPE_VBI_OUTPUT: sprintf(type, "vbi-out"); break;
1489  default: sprintf(type, "unknown"); break;
1490  }
1491 
1492  fprintf(stdout,"v4l2: buf %d: %d ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n",
1493  buf.index, buf.type, buf.m.userptr, buf.m.offset,
1494  buf.length, buf.length, buf.bytesused);
1495 
1496 }
1497 
1515 {
1516  this->acquire(I);
1517  return *this;
1518 }
1519 
1537 {
1538  this->acquire(I);
1539  return *this;
1540 }
1541 
1542 #elif !defined(VISP_BUILD_SHARED_LIBS)
1543 // Work arround to avoid warning: libvisp_sensor.a(vpV4l2Grabber.cpp.o) has no symbols
1544 void dummy_vpV4l2Grabber() {};
1545 #endif
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static const unsigned int MAX_CTRL
double getTop() const
Definition: vpRect.h:178
void acquire(vpImage< unsigned char > &I)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
void open(vpImage< unsigned char > &I)
static const __u32 MAX_FORMAT
unsigned int getWidth() const
Definition: vpImage.h:226
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
vpV4l2FramerateType getFramerate()
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
#define vpERROR_TRACE
Definition: vpDebug.h:391
void setDevice(const std::string &devname)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
vpV4l2PixelFormatType getPixelFormat()
double getHeight() const
Definition: vpRect.h:152
static const unsigned int DEFAULT_INPUT
Error that can be emited by the vpFrameGrabber class and its derivates.
Definition: vpRGBa.h:66
double getWidth() const
Definition: vpRect.h:199
virtual ~vpV4l2Grabber()
vpV4l2Grabber & operator>>(vpImage< unsigned char > &I)
static const unsigned int FRAME_SIZE
void setHeight(unsigned h)
unsigned int height
Number of rows in the image.
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static const __u32 MAX_INPUTS
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
void setWidth(unsigned w)
static const __u32 MAX_NORM
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
bool init
Set to true if the frame grabber has been initialized.
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
25 frames per second
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: vpImageTools.h:266
unsigned int getHeight() const
Definition: vpImage.h:175
Defines a rectangle in the plane.
Definition: vpRect.h:82
void setNBuffers(unsigned nbuffers)
unsigned int width
Number of columns in the image.
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int size)
double getLeft() const
Definition: vpRect.h:159
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
static const unsigned int DEFAULT_SCALE
static const unsigned int MAX_BUFFERS
void setFramerate(vpV4l2FramerateType framerate)