ViSP  2.10.0
vpV4l2Grabber.cpp
1 /****************************************************************************
2  *
3  * $Id: vpV4l2Grabber.cpp 5126 2015-01-05 22:07:11Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Framegrabber based on Video4Linux2 driver.
36  *
37  * Authors:
38  * Fabien Spindler
39  *
40  *****************************************************************************/
41 
48 #include <visp/vpConfig.h>
49 
50 #ifdef VISP_HAVE_V4L2
51 
52 #include <stdio.h>
53 #include <unistd.h>
54 #include <stdlib.h>
55 #include <sys/time.h>
56 #include <sys/ioctl.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <fcntl.h>
60 #include <stdio.h>
61 #include <sys/mman.h>
62 #include <errno.h>
63 #include <iostream>
64 
65 #include <visp/vpV4l2Grabber.h>
66 #include <visp/vpFrameGrabberException.h>
67 #include <visp/vpImageIo.h>
68 
69 const unsigned int vpV4l2Grabber::DEFAULT_INPUT = 2;
70 const unsigned int vpV4l2Grabber::DEFAULT_SCALE = 2;
71 const __u32 vpV4l2Grabber::MAX_INPUTS = 16;
72 const __u32 vpV4l2Grabber::MAX_NORM = 16;
73 const __u32 vpV4l2Grabber::MAX_FORMAT = 32;
74 const unsigned int vpV4l2Grabber::MAX_CTRL = 32;
75 const unsigned int vpV4l2Grabber::MAX_BUFFERS = 32;
76 const unsigned int vpV4l2Grabber::FRAME_SIZE = 288;
77 #define vpCLEAR(x) memset (&(x), 0, sizeof (x))
78 
118  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
119  fps(0), fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
120  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
121  m_input(vpV4l2Grabber::DEFAULT_INPUT),
122  m_framerate(vpV4l2Grabber::framerate_25fps),
123  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
124  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
125 {
126  setDevice("/dev/video0");
127  setNBuffers(3);
132 
133  init = false;
134 }
135 
177  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
178  fps(0), fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
179  waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0), streaming(false),
180  m_input(vpV4l2Grabber::DEFAULT_INPUT),
181  m_framerate(vpV4l2Grabber::framerate_25fps),
182  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
183  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
184 {
185  setDevice("/dev/video0");
186  setNBuffers(3);
191 
192  init = false;
193 }
194 
195 
226 vpV4l2Grabber::vpV4l2Grabber(unsigned input, unsigned scale)
227  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
228  fps(0), fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
229  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
230  m_input(vpV4l2Grabber::DEFAULT_INPUT),
231  m_framerate(vpV4l2Grabber::framerate_25fps),
232  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
233  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
234 {
235  setDevice("/dev/video0");
236  setNBuffers(3);
238  setInput(input);
239  setScale(scale);
240 
241  init = false;
242 }
243 
275 vpV4l2Grabber::vpV4l2Grabber(vpImage<unsigned char> &I, unsigned input, unsigned scale )
276  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
277  fps(0), fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
278  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
279  m_input(vpV4l2Grabber::DEFAULT_INPUT),
280  m_framerate(vpV4l2Grabber::framerate_25fps),
281  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
282  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
283 {
284  setDevice("/dev/video0");
285  setNBuffers(3);
287  setInput(input);
288  setScale(scale);
289 
290  init = false;
291 
292  open(I);
293 }
294 
327 vpV4l2Grabber::vpV4l2Grabber(vpImage<vpRGBa> &I, unsigned input, unsigned scale )
328  : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL),
329  fps(0), fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL), queue(0),
330  waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0), streaming(false),
331  m_input(vpV4l2Grabber::DEFAULT_INPUT),
332  m_framerate(vpV4l2Grabber::framerate_25fps),
333  m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
334  m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
335 {
336  setDevice("/dev/video0");
337  setNBuffers(3);
339  setInput(input);
340  setScale(scale);
341 
342  init = false;
343 
344  open(I);
345 }
346 
353 {
354  close() ;
355 }
356 
360 void
361 vpV4l2Grabber::setInput(unsigned input)
362 {
363  this->m_input = input;
364 }
365 
378 void
379 vpV4l2Grabber::setScale(unsigned scale)
380 {
381  if ((scale <1) || (scale >16))
382  {
383  close();
384 
385  vpERROR_TRACE("Wrong scale %d, scale should be between 1 and 16",scale) ;
387  "Wrong scale") );
388  }
389 
390  setWidth(640/scale);
391  setHeight(480/scale);
392 }
393 
404 void
406 {
407  open();
408 
409  if( v4l2_ioctl (fd, VIDIOC_S_INPUT, &m_input) == -1 )
410  {
411  std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
412  }
413 
414  vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
415 
416  try {
417  setFormat();
418 
419  startStreaming();
420  }
421  catch(...) {
422  if (m_verbose) {
423  std::cout << "Requested pixel format [" << req_pixelformat
424  << "] not compatible with camera" << std::endl;
425  std::cout << "Try to found a compatible pixel format..." << std::endl;
426  }
427 
428  // try to fing a compatible format
429  for (int format=0; format< (int)V4L2_MAX_FORMAT; format ++) {
430  if (format == req_pixelformat) {
431  continue;
432  }
433  try {
435  setFormat();
436  startStreaming();
437  if (m_verbose)
438  std::cout << "This format [" << m_pixelformat
439  << "] is compatible with camera" << std::endl;
440 
441  break;
442  }
443  catch (...) {
444  if (m_verbose)
445  std::cout << "This format [" << m_pixelformat
446  << "] is not compatible with camera" << std::endl;
447  if (format == (int)V4L2_MAX_FORMAT) {
448  std::cout << "No pixel format compatible with the camera was found" << std::endl;
449  close();
450 
452  "No pixel format compatible with the camera was found"));
453  }
454  }
455  }
456  }
457 
458  I.resize(height, width) ;
459 
460  init = true;
461 }
462 
472 void
474 {
475  open();
476 
477  if( v4l2_ioctl (fd, VIDIOC_S_INPUT, &m_input) == -1 )
478  {
479  std::cout << "Warning: cannot set input channel to " << m_input << std::endl;
480  }
481 
482  vpV4l2PixelFormatType req_pixelformat = getPixelFormat();
483 
484  try {
485  setFormat();
486 
487  startStreaming();
488  }
489  catch(...) {
490  if (m_verbose) {
491  std::cout << "Requested pixel format [" << m_pixelformat
492  << "] not compatible with camera" << std::endl;
493  std::cout << "Try to found a compatible pixel format..." << std::endl;
494  }
495 
496  // try to fing a compatible format
497  for (int format=0; format< (int)V4L2_MAX_FORMAT; format ++) {
498  if (format == req_pixelformat) {
499  continue;
500  }
501  try {
503  setFormat();
504  startStreaming();
505  if (m_verbose)
506  std::cout << "This format [" << m_pixelformat
507  << "] is compatible with camera" << std::endl;
508 
509  break;
510  }
511  catch (...) {
512  if (m_verbose)
513  std::cout << "This format [" << m_pixelformat
514  << "] is not compatible with camera" << std::endl;
515 
516  }
517  }
518  }
519 
520  I.resize(height, width) ;
521 
522  init = true;
523 }
524 
525 
526 
537 void
539 {
540  struct timeval timestamp;
541 
542  acquire(I, timestamp);
543 }
544 
558 void
559 vpV4l2Grabber::acquire(vpImage<unsigned char> &I, struct timeval &timestamp)
560 {
561  if (init==false)
562  {
563  open(I);
564  }
565 
566  if (init==false)
567  {
568  close();
569 
571  "V4l2 frame grabber not initialized") );
572  }
573 
574  unsigned char *bitmap ;
575  bitmap = waiton(index_buffer, timestamp);
576 
577  if ((I.getWidth() != width)||(I.getHeight() != height))
578  I.resize(height, width) ;
579 
580  switch(m_pixelformat) {
581  case V4L2_GREY_FORMAT:
582  memcpy(I.bitmap, bitmap, height * width*sizeof(unsigned char));
583  break;
584  case V4L2_RGB24_FORMAT:
585  vpImageConvert::RGBToGrey((unsigned char *) bitmap, I.bitmap, width*height);
586 
587  break;
588  case V4L2_RGB32_FORMAT:
589  vpImageConvert::RGBaToGrey((unsigned char *) bitmap, I.bitmap, width*height);
590 
591  break;
592  case V4L2_BGR24_FORMAT:
593  vpImageConvert::BGRToGrey( (unsigned char *) bitmap, I.bitmap, width, height, false);
594 
595  break;
596  case V4L2_YUYV_FORMAT:
597  vpImageConvert::YUYVToGrey( (unsigned char *) bitmap, I.bitmap, width*height);
598 
599  break;
600  default:
601  std::cout << "V4L2 conversion not handled" << std::endl;
602  break;
603  }
604 
605  queueAll();
606 }
607 
618 void
620 {
621  struct timeval timestamp;
622 
623  acquire(I, timestamp);
624 }
625 
639 void
640 vpV4l2Grabber::acquire(vpImage<vpRGBa> &I, struct timeval &timestamp)
641 {
642  if (init==false)
643  {
644  open(I);
645  }
646 
647  if (init==false)
648  {
649  close();
650 
652  "V4l2 frame grabber not initialized") );
653  }
654 
655  unsigned char *bitmap ;
656  bitmap = waiton(index_buffer, timestamp);
657 
658  if ((I.getWidth() != width)||(I.getHeight() != height))
659  I.resize(height, width) ;
660 
661  // The framegrabber acquire aRGB format. We just shift the data from 1 byte all the data and initialize the last byte
662 
663  switch(m_pixelformat) {
664  case V4L2_GREY_FORMAT:
665  vpImageConvert::GreyToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width*height);
666  break;
667  case V4L2_RGB24_FORMAT:
668  vpImageConvert::RGBToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width*height);
669 
670  break;
671  case V4L2_RGB32_FORMAT:
672  // The framegrabber acquire aRGB format. We just shift the data
673  // from 1 byte all the data and initialize the last byte
674  memcpy(I.bitmap, bitmap + 1, height * width * sizeof(vpRGBa) - 1);
675  I[height-1][width-1].A = 0;
676  break;
677  case V4L2_BGR24_FORMAT:
678  vpImageConvert::BGRToRGBa((unsigned char *) bitmap, (unsigned char *) I.bitmap, width, height, false);
679  break;
680  case V4L2_YUYV_FORMAT:
681  vpImageConvert::YUYVToRGBa( (unsigned char *) bitmap, (unsigned char *) I.bitmap, width, height);
682  break;
683  default:
684  std::cout << "V4l2 conversion not handled" << std::endl;
685  break;
686  }
687 
688  queueAll();
689 }
706 bool
708 {
709  if(field == 2) return 0; //top field
710  else if (field == 3) return 1; //bottom field;
711  else {
712  close();
713 
715  "V4l2 returns a bad frame field") );
716  return false;
717  }
718 }
733 void
735 {
736  this->m_framerate = framerate;
737 
738  if (framerate == vpV4l2Grabber::framerate_25fps)
739  setFrameFormat(V4L2_IMAGE_FORMAT);
740  else
741  setFrameFormat(V4L2_FRAME_FORMAT);
742 }
743 
756 {
757  return m_framerate;
758 }
759 
760 
764 void
766 {
767  stopStreaming();
768  streaming = false;
769 
770  if (fd >= 0){
771  //vpTRACE("v4l2_close()");
772  v4l2_close (fd);
773  fd = -1;
774  }
775 
776  if (inp != NULL) { delete [] inp; inp = NULL; }
777  if (std != NULL) { delete [] std; std = NULL; }
778  if (fmt != NULL) { delete [] fmt; fmt = NULL; }
779  if (ctl != NULL) { delete [] ctl; ctl = NULL; }
780  if (buf_v4l2 != NULL) { delete [] buf_v4l2; buf_v4l2 = NULL; }
781  if (buf_me != NULL) { delete [] buf_me; buf_me = NULL; }
782 }
783 
795 void
796 vpV4l2Grabber::open()
797 {
798  /* Open Video Device */
799  struct stat st;
800 
801  if (-1 == stat (device, &st)) {
802  fprintf (stderr, "Cannot identify '%s': %d, %s\n",
803  device, errno, strerror (errno));
805  "Cannot identify video device") );
806 
807  }
808 
809  if (!S_ISCHR (st.st_mode)) {
810  fprintf (stderr, "%s is no device\n", device);
812  "No device") );
813 
814  }
815  fd = v4l2_open (device, O_RDWR | O_NONBLOCK, 0);
816  if (fd < 0) {
817  close();
818 
819  vpERROR_TRACE ("No video device \"%s\"\n", device);
821  "Can't access to video device") );
822 
823  }
824 
825  if (inp != NULL) { delete [] inp; inp = NULL; }
826  if (std != NULL) { delete [] std; std = NULL; }
827  if (fmt != NULL) { delete [] fmt; fmt = NULL; }
828  if (ctl != NULL) { delete [] ctl; ctl = NULL; }
829  if (buf_v4l2 != NULL) { delete [] buf_v4l2; buf_v4l2 = NULL; }
830  if (buf_me != NULL) { delete [] buf_me; buf_me = NULL; }
831 
832  inp = new struct v4l2_input [vpV4l2Grabber::MAX_INPUTS];
833  std = new struct v4l2_standard [vpV4l2Grabber::MAX_NORM];
834  fmt = new struct v4l2_fmtdesc [vpV4l2Grabber::MAX_FORMAT];
835  ctl = new struct v4l2_queryctrl [vpV4l2Grabber::MAX_CTRL*2];
836  buf_v4l2 = new struct v4l2_buffer [vpV4l2Grabber::MAX_BUFFERS];
837  buf_me = new struct ng_video_buf [vpV4l2Grabber::MAX_BUFFERS];
838 
839  /* Querry Video Device Capabilities */
840  if ( v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap) == -1 ) {
841  close();
842  fprintf (stderr, "%s is no V4L2 device\n", device);
844  "Is not a V4L2 device") );
845  }
846  if (m_verbose) {
847  fprintf(stdout, "v4l2 info:\n"
848  " device: %s\n"
849  " %s %d.%d.%d / %s @ %s\n",
850  device,
851  cap.driver,
852  (cap.version >> 16) & 0xff,
853  (cap.version >> 8) & 0xff,
854  cap.version & 0xff,
855  cap.card, cap.bus_info);
856  if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
857  fprintf(stdout, " Support overlay\n");
858  else
859  fprintf(stdout, " Does not support overlay\n");
860  if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
861  fprintf(stdout, " Support capture\n");
862  else
863  fprintf(stdout, " Does not support capture\n");
864  if (cap.capabilities & V4L2_CAP_TUNER)
865  fprintf(stdout, " Support tuning\n");
866  else
867  fprintf(stdout, " Does not support tuning\n");
868  if (cap.capabilities & V4L2_CAP_STREAMING)
869  fprintf(stdout, " Support streaming capture.\n");
870  else
871  fprintf(stdout, " Does not support streaming capture\n");
872  if(cap.capabilities & V4L2_CAP_ASYNCIO)
873  fprintf(stdout, " Support asynchronous I/O methods\n");
874  else
875  fprintf(stdout, " Does not support asynchronous I/O methods\n");
876  if(cap.capabilities & V4L2_CAP_TIMEPERFRAME)
877  fprintf(stdout, " Support time per frame field\n");
878  else
879  fprintf(stdout, " Does not support time per frame field\n");
880  // Get framerate
881  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
882  if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
883  fprintf(stdout, " Current acquisition framerate: %d fps\n",
884  streamparm.parm.output.timeperframe.denominator);
885  }
886  }
887 
888  getCapabilities();
889 }
890 
897 void
898 vpV4l2Grabber::getCapabilities()
899 {
900  for (__u32 ninputs = 0; ninputs < MAX_INPUTS; ninputs++) {
901  inp[ninputs].index = ninputs;
902  if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
903  break;
904  }
905  for (__u32 nstds = 0; nstds < MAX_NORM; nstds++) {
906  std[nstds].index = nstds;
907  if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
908  break;
909 
910  }
911  for (__u32 nfmts = 0; nfmts < MAX_FORMAT; nfmts++) {
912  fmt[nfmts].index = nfmts;
913  fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
914  if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
915  break;
916  }
917 
918  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
919  if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1)
920  {
921  close();
922 
924  "Can't get video parameters") );
925  }
926 }
927 
941 void
942 vpV4l2Grabber::setFormat()
943 {
944  fmt_me.width = width;
945  fmt_me.height = height;
946  //fmt_me.bytesperline = width; // bad (normally width * depth / 8), but works
947  // because initialized later by an ioctl call to VIDIOC_S_FMT
948 
949  switch(m_pixelformat) {
950  case V4L2_GREY_FORMAT : fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
951  if (m_verbose)
952  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
953  break;
954  case V4L2_RGB24_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
955  if (m_verbose)
956  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
957  break;
958  case V4L2_RGB32_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
959  if (m_verbose)
960  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
961  break;
962  case V4L2_BGR24_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
963  if (m_verbose)
964  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
965  break;
966  case V4L2_YUYV_FORMAT: fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
967  if (m_verbose)
968  fprintf(stdout,"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
969  break;
970 
971  default:
972  close();
973 
975  "Bad format, probably do to a wrong scale"));
976  }
977 
978  /* Get Video Format */
979  vpCLEAR (fmt_v4l2);
980 
981  fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
982 
983  if (v4l2_ioctl (fd, VIDIOC_G_FMT, &fmt_v4l2) == -1 ) {
984  close();
985 
987  "Can't get video format") );
988  }
989  fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
990  fmt_v4l2.fmt.pix.width = fmt_me.width;
991  fmt_v4l2.fmt.pix.height = fmt_me.height;
992  //printf("1 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width, fmt_v4l2.fmt.pix.height);
993 
994 
995  switch (m_frameformat) {
996  case V4L2_FRAME_FORMAT: fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
997  if (m_verbose) {
998  fprintf(stdout,"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
999  }
1000  break;
1001  case V4L2_IMAGE_FORMAT: fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1002  if (m_verbose) {
1003  fprintf(stdout,"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1004  }
1005  break;
1006  default:
1007  close();
1008 
1010  "Unrecognized frame format") );
1011  }
1012 
1013  //height and width of the captured image or frame
1014  if( m_frameformat == V4L2_FRAME_FORMAT && height > FRAME_SIZE )
1015  {
1016  height = FRAME_SIZE;
1017  }
1018  //printf("2 - w: %d h: %d\n", fmt_v4l2.fmt.pix.width, fmt_v4l2.fmt.pix.height);
1019 
1020  if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1022  "Can't set video format") );
1023  }
1024 
1025  if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1027  "Bad pixel format") );
1028  }
1029 
1030  /* Buggy driver paranoia. */
1031  unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1032  if (fmt_v4l2.fmt.pix.bytesperline < min)
1033  fmt_v4l2.fmt.pix.bytesperline = min;
1034  min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1035  if (fmt_v4l2.fmt.pix.sizeimage < min)
1036  fmt_v4l2.fmt.pix.sizeimage = min;
1037 
1038  fmt_me.width = fmt_v4l2.fmt.pix.width;
1039  fmt_me.height = fmt_v4l2.fmt.pix.height;
1040  fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1041 
1042  if (m_verbose) {
1043  fprintf(stdout,"v4l2: new capture params (%dx%d, %c%c%c%c, %d byte, %d bytes per line)\n",
1044  fmt_me.width, fmt_me.height,
1045  fmt_v4l2.fmt.pix.pixelformat & 0xff,
1046  (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff,
1047  (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1048  (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff,
1049  fmt_v4l2.fmt.pix.sizeimage,
1050  fmt_v4l2.fmt.pix.bytesperline);
1051  }
1052 
1053 }
1062 void
1063 vpV4l2Grabber::startStreaming()
1064 {
1065  if (streaming == true) { // Acquisition in process.
1066  stopStreaming();
1067  streaming = false;
1068  }
1069 
1070  /* setup buffers */
1071  memset (&(reqbufs), 0, sizeof (reqbufs));
1072  reqbufs.count = m_nbuffers;
1073  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1074  reqbufs.memory = V4L2_MEMORY_MMAP;
1075 
1076 
1077  if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1)
1078  {
1079  if (EINVAL == errno) {
1080  fprintf (stderr, "%s does not support "
1081  "memory mapping\n", device);
1083  "Does not support memory mapping") );
1084  }
1086  "Can't require video buffers") );
1087  }
1088 
1089  for (unsigned i = 0; i < reqbufs.count; i++) {
1090  // Clear the buffer
1091  memset (&(buf_v4l2[i]), 0, sizeof (buf_v4l2[i]));
1092  buf_v4l2[i].index = i;
1093  buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1094  buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1095  buf_v4l2[i].length = 0;
1096  if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1)
1097  {
1099  "Can't query video buffers") );
1100  }
1101  memcpy(&buf_me[i].fmt, &fmt_me, sizeof(ng_video_fmt));
1102  buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1103 
1104  // if (m_verbose)
1105  // std::cout << "1: buf_v4l2[" << i << "].length: " << buf_v4l2[i].length
1106  // << " buf_v4l2[" << i << "].offset: " << buf_v4l2[i].m.offset
1107  // << std::endl;
1108 
1109 
1110  buf_me[i].data = (unsigned char *) v4l2_mmap(NULL, buf_v4l2[i].length,
1111  PROT_READ | PROT_WRITE,
1112  MAP_SHARED,
1113  fd, (off_t)buf_v4l2[i].m.offset);
1114 
1115  if(buf_me[i].data == MAP_FAILED)
1116  {
1118  "Can't map memory") );
1119  }
1120 
1121  buf_me[i].refcount = 0;
1122 
1123 // if (m_verbose)
1124 // {
1125 // std::cout << "2: buf_v4l2[" << i << "].length: " << buf_v4l2[i].length
1126 // << " buf_v4l2[" << i << "].offset: " << buf_v4l2[i].m.offset
1127 // << std::endl;
1128 // std::cout << "2: buf_me[" << i << "].size: " << buf_me[i].size << std::endl;
1129 // }
1130 
1131  if (m_verbose)
1132  printBufInfo(buf_v4l2[i]);
1133  }
1134 
1135  /* queue up all buffers */
1136  queueAll();
1137 
1138  /* Set video stream capture on */
1139  if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type)<0)
1140  {
1142  "Can't start streaming") );
1143  }
1144 
1145  streaming = true;
1146 }
1147 
1154 void
1155 vpV4l2Grabber::stopStreaming()
1156 {
1157  unsigned int i;
1158 
1159  //nothing to do if (fd < 0) or if (streaming == false)
1160  if ((fd >= 0) && (streaming == true)) {
1161 
1162  //vpTRACE(" Stop the streaming...");
1163  /* stop capture */
1164  fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1165  if (v4l2_ioctl(fd, VIDIOC_STREAMOFF,&fmt_v4l2.type)) {
1167  "Can't stop streaming") );
1168  }
1169  /* free buffers */
1170  for (i = 0; i < reqbufs.count; i++) {
1171  if (m_verbose)
1172  printBufInfo(buf_v4l2[i]);
1173  //vpTRACE("v4l2_munmap()");
1174 
1175  if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1177  "Can't unmap memory") );
1178  }
1179  }
1180  queue = 0;
1181  waiton_cpt = 0;
1182  streaming = false;
1183  }
1184 }
1185 
1199 unsigned char *
1200 vpV4l2Grabber::waiton(__u32 &index, struct timeval &timestamp)
1201 {
1202  struct v4l2_buffer buf;
1203  struct timeval tv;
1204  fd_set rdset;
1205 
1206  /* wait for the next frame */
1207  again:
1208 
1209  tv.tv_sec = 30;
1210  tv.tv_usec = 0;
1211  FD_ZERO(&rdset);
1212  FD_SET(static_cast<unsigned int>(fd), &rdset);
1213  switch (select(fd + 1, &rdset, NULL, NULL, &tv)) {
1214  case -1:
1215  if (EINTR == errno)
1216  goto again;
1217  index = 0;
1219  "Can't access to the frame") );
1220  return NULL;
1221  case 0:
1222  index = 0;
1224  "Can't access to the frame: timeout") );
1225  return NULL;
1226  }
1227 
1228 
1229  /* get it */
1230  memset(&buf, 0, sizeof(buf));
1231  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1232  buf.memory = V4L2_MEMORY_MMAP; // Fabien manquait
1233  if (-1 == v4l2_ioctl(fd,VIDIOC_DQBUF, &buf)) {
1234  index = 0;
1235  switch(errno)
1236  {
1237  case EAGAIN:
1239  "VIDIOC_DQBUF: EAGAIN") );
1240  break;
1241  case EINVAL:
1243  "VIDIOC_DQBUF: EINVAL") );
1244  break;
1245  case ENOMEM:
1247  "VIDIOC_DQBUF: ENOMEM") );
1248  break;
1249  default:
1251  "VIDIOC_DQBUF") );
1252  break;
1253  }
1254  return NULL;
1255  }
1256 
1257  waiton_cpt++;
1258  buf_v4l2[buf.index] = buf;
1259 
1260  index = buf.index;
1261 
1262  field = buf_v4l2[index].field;
1263 
1264  timestamp = buf_v4l2[index].timestamp;
1265 
1266  // if(m_verbose)
1267  // {
1268  // vpERROR_TRACE("field: %d\n", buf_v4l2[index].field);
1269 
1270  // vpERROR_TRACE("data adress : 0x%p\n", buf_me[buf.index].data);
1271  // }
1272  return buf_me[buf.index].data;
1273 }
1274 
1280 int
1281 vpV4l2Grabber::queueBuffer()
1282 {
1283  unsigned int frame = queue % reqbufs.count;
1284  int rc;
1285 
1286 
1287  if (0 != buf_me[frame].refcount) {
1288  if (0 != queue - waiton_cpt)
1289  return -1;
1290  fprintf(stderr,"v4l2: waiting for a free buffer..............\n");
1291  //ng_waiton_video_buf(h->buf_me+frame);
1292  std::cout << "Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1293  }
1294 
1295  // std::cout << "frame: " << frame << std::endl;
1296  rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1297  if (0 == rc)
1298  queue++;
1299  else
1300  {
1301  switch(errno)
1302  {
1303  case EAGAIN:
1305  "VIDIOC_QBUF: EAGAIN") );
1306  break;
1307  case EINVAL:
1309  "VIDIOC_QBUF: EINVAL") );
1310  break;
1311  case ENOMEM:
1313  "VIDIOC_QBUF: ENOMEM") );
1314  break;
1315  default:
1317  "VIDIOC_QBUF") );
1318  break;
1319  }
1320  }
1321  return rc;
1322 }
1323 
1329 void
1330 vpV4l2Grabber::queueAll()
1331 {
1332  for (;;) {
1333  if (queue - waiton_cpt >= reqbufs.count) {
1334  return;
1335  }
1336  if (0 != queueBuffer()) {
1337  return;
1338  }
1339  }
1340 }
1341 
1347 void
1348 vpV4l2Grabber::printBufInfo(struct v4l2_buffer buf)
1349 {
1350  char type[40];
1351 
1352  switch(buf.type) {
1353  case V4L2_BUF_TYPE_VIDEO_CAPTURE: sprintf(type, "video-cap"); break;
1354  case V4L2_BUF_TYPE_VIDEO_OVERLAY: sprintf(type, "video-over"); break;
1355  case V4L2_BUF_TYPE_VIDEO_OUTPUT: sprintf(type, "video-out"); break;
1356  case V4L2_BUF_TYPE_VBI_CAPTURE: sprintf(type, "vbi-cap"); break;
1357  case V4L2_BUF_TYPE_VBI_OUTPUT: sprintf(type, "vbi-out"); break;
1358  default: sprintf(type, "unknown"); break;
1359  }
1360 
1361  fprintf(stdout,"v4l2: buf %d: %d ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n",
1362  buf.index, buf.type, buf.m.userptr, buf.m.offset,
1363  buf.length, buf.length, buf.bytesused);
1364 
1365 }
1366 #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
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:161
#define vpERROR_TRACE
Definition: vpDebug.h:395
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:120
void setDevice(const std::string &devname)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int size)
vpV4l2PixelFormatType getPixelFormat()
static const unsigned int DEFAULT_INPUT
Error that can be emited by the vpFrameGrabber class and its derivates.
Class that defines a RGB 32 bits structure.
Definition: vpRGBa.h:68
virtual ~vpV4l2Grabber()
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)
set the size of the image without initializing it.
Definition: vpImage.h:536
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 for the Video4Linux2 video device.
25 frames per second
unsigned int getHeight() const
Definition: vpImage.h:152
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)
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
static const unsigned int DEFAULT_SCALE
static const unsigned int MAX_BUFFERS
void setFramerate(vpV4l2FramerateType framerate)