1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Video for linux two framegrabber.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
39 /*!
40   \file vpV4l2Grabber.h
41   \brief class for the Video For Linux 2 video device framegrabbing.
42   \ingroup libdevice
43 */
44 
45 #ifndef vpV4l2Grabber_hh
46 #define vpV4l2Grabber_hh
47 
48 #include <visp3/core/vpConfig.h>
49 
50 #ifdef VISP_HAVE_V4L2
51 
52 #include <libv4l2.h> // Video For Linux Two interface
53 #include <linux/videodev2.h> // Video For Linux Two interface
54 
55 #include <visp3/core/vpFrameGrabber.h>
56 #include <visp3/core/vpImage.h>
57 #include <visp3/core/vpRGBa.h>
58 #include <visp3/core/vpRect.h>
59 
60 /*!
61   \class vpV4l2Grabber
62 
63   \ingroup group_sensor_camera
64 
65   \brief Class that is a wrapper over the Video4Linux2 (V4L2) driver.
66 
67   Thus to be enabled, this class needs the optional V4L2 3rd party.
68 Installation instruction are provided here https://visp.inria.fr/3rd_v4l2.
69 
70   Information about Video4Linux can be found on
71   http://linuxtv.org/v4lwiki/index.php/Main_Page
72 
73   This class was tested with a Pinnacle PCTV Studio/Rave board but
74   also with the following webcams (Logitech QuickCam Vision Pro 9000,
75   Logitech QuickCam Orbit AF, Logitech QuickCam IM (V-USB39), Dell latitude
76 E6400 internal webcam).
77 
78   If the grabbing fail with a webcam, it means probably that you don't
79   have the read/write permission on the /dev/video%%d device. You can
80   set the right permissions by "sudo chmod a+rw /dev/video*".
81 
82   If the grabbing fails when the camera is attached to a bttv PCI
83   card, it means potentially that you have not configured the linux
84   bttv kernel module according to your board.
85 
86   For that, depending on your linux distribution check the card id in
87   - /usr/share/doc/kernel-doc-2.4.20/video4linux/bttv/CARDLIST
88   - or
89 /usr/share/doc/kernel-doc-2.6.20/Documentation/video4linux/CARDLIST.bttv
90 
91   For example, the card id of a Pinnacle PCTV Studio/Rave board is 39.
92   Once this id is determined, you have to set the bttv driver with, by adding
93   \verbatim
94   options bttv card=39
95   \endverbatim
96   in one of theses files :
97   - /etc/modules.conf
98   - or /etc/modprobe.conf
99 
100   This first example available in tutorial-grabber-v4l2.cpp shows how to grab
101   and display images from an usb camera.
102   \include tutorial-grabber-v4l2.cpp
103 
104   This other example shows how to use this grabber with an analogic camera
105   attached to a bttv PCI card.
106   \code
107 #include <visp3/io/vpImageIo.h>
108 #include <visp3/sensor/vpV4l2Grabber.h>
109 
110 int main()
111 {
112 #if defined(VISP_HAVE_V4L2)
113   vpImage<unsigned char> I;
114   vpV4l2Grabber g;
115   g.setInput(2);    // Input 2 on the board
116   g.setFramerate(vpV4l2Grabber::framerate_25fps); //  25 fps
117   g.setWidth(768);  // Acquired images are 768 width
118   g.setHeight(576); // Acquired images are 576 height
119   g.setNBuffers(3); // 3 ring buffers to ensure real-time acquisition
120   g.open(I);        // Open the grabber
121 
122   g.acquire(I);     // Acquire a 768x576 grey image
123   vpImageIo::write(I, "image.pgm"); // Save the image on the disk
124 #endif
125 }
126   \endcode
127 
128 
129   \author Fabien Spindler (Fabien.Spindler@irisa.fr), Irisa / Inria Rennes
130 
131 
132   \sa vpFrameGrabber
133 */
134 class VISP_EXPORT vpV4l2Grabber : public vpFrameGrabber
135 {
136 public:
137   static const unsigned int DEFAULT_INPUT;
138   static const unsigned int DEFAULT_SCALE;
139   static const __u32 MAX_INPUTS;
140   static const __u32 MAX_NORM;
141   static const __u32 MAX_FORMAT;
142   static const unsigned int MAX_CTRL;
143   static const unsigned int MAX_BUFFERS;
144   static const unsigned int FRAME_SIZE;
145 
146   /*! \enum vpV4l2FramerateType
147     Frame rate type for capture.
148   */
149   typedef enum {
150     framerate_50fps, //!< 50 frames per second
151     framerate_25fps  //!< 25 frames per second
152   } vpV4l2FramerateType;
153 
154   /*! \enum vpV4l2FrameFormatType
155     Frame format type for capture.
156   */
157   typedef enum {
158     V4L2_FRAME_FORMAT, /*!< a field only */
159     V4L2_IMAGE_FORMAT  /*!< an interlaced image */
160   } vpV4l2FrameFormatType;
161 
162   /*! \enum vpV4l2PixelFormatType
163     Pixel format type for capture.
164   */
165   typedef enum {
166     V4L2_GREY_FORMAT,  /*!< 8  Greyscale */
167     V4L2_RGB24_FORMAT, /*!< 24  RGB-8-8-8 */
168     V4L2_RGB32_FORMAT, /*!< 32  RGB-8-8-8-8 */
169     V4L2_BGR24_FORMAT, /*!< 24  BGR-8-8-8 */
170     V4L2_YUYV_FORMAT,  /*!< 16  YUYV 4:2:2  */
171     V4L2_MAX_FORMAT
172   } vpV4l2PixelFormatType;
173 
174 #ifndef DOXYGEN_SHOULD_SKIP_THIS
175   struct ng_video_fmt {
176     unsigned int pixelformat; /* VIDEO_* */
177     unsigned int width;
178     unsigned int height;
179     unsigned int bytesperline; /* zero for compressed formats */
180   };
181 
182   struct ng_video_buf {
183     struct ng_video_fmt fmt;
184     size_t size;
185     unsigned char *data;
186     int refcount;
187   };
188 #endif
189 
190   // private:
191   //#ifndef DOXYGEN_SHOULD_SKIP_THIS
192   //  vpV4l2Grabber(const vpV4l2Grabber &)
193   //    : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL),
194   //    fmt(NULL), ctl(NULL),
195   //      fmt_v4l2(), fmt_me(), reqbufs(), buf_v4l2(NULL), buf_me(NULL),
196   //      queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false),
197   //      m_nbuffers(3), field(0), streaming(false),
198   //      m_input(vpV4l2Grabber::DEFAULT_INPUT),
199   //      m_framerate(vpV4l2Grabber::framerate_25fps),
200   //      m_frameformat(vpV4l2Grabber::V4L2_FRAME_FORMAT),
201   //      m_pixelformat(vpV4l2Grabber::V4L2_YUYV_FORMAT)
202   //  {
203   //    throw vpException(vpException::functionNotImplementedError,"Not
204   //    implemented!");
205   //  }
206   //  vpV4l2Grabber &operator=(const vpV4l2Grabber &){
207   //    throw vpException(vpException::functionNotImplementedError,"Not
208   //    implemented!"); return *this;
209   //  }
210   //#endif
211 
212 public:
213   vpV4l2Grabber();
214   explicit vpV4l2Grabber(bool verbose);
215   vpV4l2Grabber(unsigned input, unsigned scale = vpV4l2Grabber::DEFAULT_SCALE);
216   vpV4l2Grabber(vpImage<unsigned char> &I, unsigned input, unsigned scale = vpV4l2Grabber::DEFAULT_SCALE);
217   vpV4l2Grabber(vpImage<vpRGBa> &I, unsigned input, unsigned scale = vpV4l2Grabber::DEFAULT_SCALE);
218   virtual ~vpV4l2Grabber();
219 
220 public:
221   void open(vpImage<unsigned char> &I);
222   void open(vpImage<vpRGBa> &I);
223 
224   void acquire(vpImage<unsigned char> &I);
225   void acquire(vpImage<unsigned char> &I, const vpRect &roi);
226   void acquire(vpImage<unsigned char> &I, struct timeval &timestamp, const vpRect &roi = vpRect());
227   void acquire(vpImage<vpRGBa> &I);
228   void acquire(vpImage<vpRGBa> &I, const vpRect &roi);
229   void acquire(vpImage<vpRGBa> &I, struct timeval &timestamp, const vpRect &roi = vpRect());
230   bool getField();
231   vpV4l2FramerateType getFramerate();
232   /*!
233 
234   Get the pixel format used for capture.
235 
236   \return Camera pixel format coding.
237 
238   */
getPixelFormat()239   inline vpV4l2PixelFormatType getPixelFormat() { return (this->m_pixelformat); }
240 
241   vpV4l2Grabber &operator>>(vpImage<unsigned char> &I);
242   vpV4l2Grabber &operator>>(vpImage<vpRGBa> &I);
243 
244   /*!
245     Activates the verbose mode to print additional information on stdout.
246     \param verbose : If true activates the verbose mode.
247   */
setVerboseMode(bool verbose)248   void setVerboseMode(bool verbose) { this->m_verbose = verbose; };
249   void setFramerate(vpV4l2FramerateType framerate);
250 
251   void setInput(unsigned input = vpV4l2Grabber::DEFAULT_INPUT);
252 
253   /*!
254     Set image width to acquire.
255 
256   */
setWidth(unsigned w)257   inline void setWidth(unsigned w) { this->width = w; }
258   /*!
259     Set image height to acquire.
260 
261   */
setHeight(unsigned h)262   inline void setHeight(unsigned h) { this->height = h; }
263 
264   void setScale(unsigned scale = vpV4l2Grabber::DEFAULT_SCALE);
265 
266   /*!
267 
268   Set the number of buffers required for streaming data.
269 
270   For non real-time applications the number of buffers should be set to 1. For
271   real-time applications to reach 25 fps or 50 fps a good compromise is to set
272   the number of buffers to 3.
273 
274   \param nbuffers : Number of ring buffers.
275 
276   */
setNBuffers(unsigned nbuffers)277   inline void setNBuffers(unsigned nbuffers) { this->m_nbuffers = nbuffers; }
278 
279   /*!
280     Set the device name.
281 
282     \param devname : Device name (like /dev/video0).
283 
284   */
setDevice(const std::string & devname)285   inline void setDevice(const std::string &devname) { sprintf(device, "%s", devname.c_str()); }
286   /*!
287 
288   Set the pixel format for capture.`If the specified pixel format is
289   out of range, we set the V4L2_RGB24_FORMAT.
290 
291   \param pixelformat : Camera pixel format coding.
292 
293   */
setPixelFormat(vpV4l2PixelFormatType pixelformat)294   inline void setPixelFormat(vpV4l2PixelFormatType pixelformat)
295   {
296     this->m_pixelformat = pixelformat;
297     if (this->m_pixelformat >= V4L2_MAX_FORMAT)
298       this->m_pixelformat = V4L2_RGB24_FORMAT;
299   }
300 
301   void close();
302 
303 private:
304   void setFormat();
305   /*!
306     Set the frame format.
307 
308     \param frameformat :
309     - vpV4l2Grabber::V4L2_FRAME_FORMAT: capture alternate fields (or frames),
310     - vpV4l2Grabber::V4L2_IMAGE_FORMAT: capture interlaced images.
311   */
setFrameFormat(vpV4l2FrameFormatType frameformat)312   inline void setFrameFormat(vpV4l2FrameFormatType frameformat) { this->m_frameformat = frameformat; }
313   void open();
314   void getCapabilities();
315   void startStreaming();
316   void stopStreaming();
317   unsigned char *waiton(__u32 &index, struct timeval &timestamp);
318   int queueBuffer();
319   void queueAll();
320   void printBufInfo(struct v4l2_buffer buf);
321 
322   int fd;
323   char device[FILENAME_MAX];
324   /* device descriptions */
325   struct v4l2_capability cap;
326   struct v4l2_streamparm streamparm;
327   struct v4l2_input *inp;     //[vpV4l2Grabber::MAX_INPUTS];
328   struct v4l2_standard *std;  //[vpV4l2Grabber::MAX_NORM];
329   struct v4l2_fmtdesc *fmt;   //[vpV4l2Grabber::MAX_FORMAT];
330   struct v4l2_queryctrl *ctl; //[vpV4l2Grabber::MAX_CTRL*2];
331 
332   /* capture */
333   struct v4l2_format fmt_v4l2;
334   struct ng_video_fmt fmt_me;
335   struct v4l2_requestbuffers reqbufs;
336   struct v4l2_buffer *buf_v4l2; //[vpV4l2Grabber::MAX_BUFFERS];
337   struct ng_video_buf *buf_me;  //[vpV4l2Grabber::MAX_BUFFERS];
338   unsigned int queue;
339   unsigned int waiton_cpt;
340   __u32 index_buffer; //!< index of the buffer in use
341 
342   bool m_verbose;
343   unsigned m_nbuffers;
344   unsigned int field;
345   bool streaming;
346 
347   unsigned m_input;
348   vpV4l2FramerateType m_framerate;
349   vpV4l2FrameFormatType m_frameformat;
350   vpV4l2PixelFormatType m_pixelformat;
351 };
352 
353 #endif
354 #endif
355