Fawkes API  Fawkes Development Version
v4l1.cpp
1 
2 /***************************************************************************
3  * v4l1.cpp - Implementation to access V4L cam
4  *
5  * Generated: Fri Mar 11 17:48:27 2005
6  * Copyright 2005 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/exception.h>
25 #include <core/exceptions/software.h>
26 
27 #include <fvcams/v4l1.h>
28 #include <fvutils/color/colorspaces.h>
29 #include <fvutils/color/rgb.h>
30 #include <fvutils/system/camargp.h>
31 
32 #include <cstdio>
33 #include <cstdlib>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <sys/mman.h>
37 #include <sys/time.h> /* gettimeofday() */
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <linux/types.h>
41 #include <errno.h>
42 #include <cstring>
43 #include <iostream>
44 #include <cassert>
45 #include <sys/types.h>
46 #include <linux/videodev.h>
47 
48 
49 using namespace std;
50 using namespace fawkes;
51 
52 namespace firevision {
53 #if 0 /* just to make Emacs auto-indent happy */
54 }
55 #endif
56 
57 /// @cond INTERNALS
58 
59 class V4L1CameraData
60 {
61  public:
62  V4L1CameraData(const char *device_name)
63  {
64  this->device_name = strdup(device_name);
65  }
66 
67  ~V4L1CameraData()
68  {
69  free(device_name);
70  }
71 
72  public:
73  char *device_name;
74 
75  /* V4L1 stuff */
76  struct video_capability capabilities; // Device Capabilities: Can overlay, Number of channels, etc
77  struct video_buffer vbuffer; // information about buffer
78  struct video_window window; // Window Information: Size, Depth, etc
79  struct video_channel *channel; // Channels information: Channel[0] holds information for channel 0 and so on...
80  struct video_picture picture; // Picture information: Palette, contrast, hue, etc
81  struct video_tuner *tuner; // Tuner Information: if the card has tuners...
82  struct video_audio audio; // If the card has audio
83  struct video_mbuf captured_frame_buffer; // Information for the frame to be captured: norm, palette, etc
84  struct video_mmap *buf_v4l; // mmap() buffer VIDIOCMCAPTURE
85 };
86 
87 /// @endcond
88 
89 /** @class V4L1Camera <fvcams/v4l1.h>
90  * Video4Linux 1 camera implementation.
91  */
92 
93 /** Constructor.
94  * @param device_name device file name (e.g. /dev/video0)
95  */
96 V4L1Camera::V4L1Camera(const char *device_name)
97 {
98  started = opened = false;
99  __data = new V4L1CameraData(device_name);
100 }
101 
102 
103 /** Constructor.
104  * Initialize camera with parameters from camera argument parser.
105  * Supported arguments:
106  * - device=DEV, device file, for example /dev/video0
107  * @param cap camera argument parser
108  */
109 V4L1Camera::V4L1Camera(const CameraArgumentParser *cap)
110 {
111  started = opened = false;
112  if ( cap->has("device") ) {
113  __data = new V4L1CameraData(cap->get("device").c_str());
114  } else {
115  throw MissingParameterException("Missing device for V4L1Camera");
116  }
117 }
118 
119 /** Protected Constructor.
120  * Gets called from V4LCamera, when the device has already been opened
121  * and determined to be a V4L1 device.
122  * @param device_name device file name (e.g. /dev/video0)
123  * @param dev file descriptor of the opened device
124  */
125 V4L1Camera::V4L1Camera(const char *device_name, int dev)
126 {
127  started = opened = false;
128  __data = new V4L1CameraData(device_name);
129  this->dev = dev;
130 
131  // getting grabber info in capabilities struct
132  if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) {
133  throw Exception("V4L1Cam: Could not get capabilities");
134  }
135 
136  post_open();
137 }
138 
139 
140 /** Destructor. */
141 V4L1Camera::~V4L1Camera()
142 {
143  delete __data;
144 }
145 
146 
147 void
148 V4L1Camera::open()
149 {
150  opened = false;
151 
152  dev = ::open(__data->device_name, O_RDWR);
153  if (dev < 0) {
154  throw Exception("V4L1Cam: Could not open device");
155  }
156 
157  // getting grabber info in capabilities struct
158  if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) {
159  throw Exception("V4L1Cam: Could not get capabilities");
160  }
161 
162  post_open();
163 }
164 
165 /**
166  * Post-open() operations
167  * @param dev file descriptor of the opened device
168  */
169 void
170 V4L1Camera::post_open()
171 {
172  // Capture window information
173  if ( (ioctl(dev, VIDIOCGWIN, &__data->window)) == -1) {
174  throw Exception("V4L1Cam: Could not get window information");
175  }
176 
177  // Picture information
178  if ( (ioctl(dev, VIDIOCGPICT, &__data->picture)) == -1) {
179  throw Exception("V4L1Cam: Could not get window information");
180  }
181 
182  ///Video Channel Information or Video Sources
183  ///Allocate space for each channel
184  __data->channel = (struct video_channel*)malloc(sizeof(struct video_channel)*(__data->capabilities.channels+1));
185  for(int ch = 0; ch < __data->capabilities.channels; ch++) {
186  __data->channel[ch].norm = 0;
187  if ( (ioctl(dev, VIDIOCSCHAN, &__data->channel[ch])) == -1) {
188  printf("V4L1Cam: Could not get channel information for channel %i: %s", ch, strerror(errno));
189  }
190  }
191 
192  ///Trying to capture through read()
193  if (ioctl (dev, VIDIOCGMBUF, __data->captured_frame_buffer) == -1) {
194  capture_method = READ;
195  frame_buffer = (unsigned char *)malloc(__data->window.width * __data->window.height * RGB_PIXEL_SIZE);
196  } else {
197  capture_method = MMAP;
198  frame_buffer = (unsigned char*)mmap (0, __data->captured_frame_buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev, 0);
199  if ((unsigned char *) -1 == (unsigned char *)frame_buffer) {
200  throw Exception("V4L1Cam: Cannot initialize mmap region");
201  }
202  }
203 
204  __data->buf_v4l = NULL;
205 
206  opened = true;
207 }
208 
209 
210 void
211 V4L1Camera::start()
212 {
213 
214  started = false;
215  if (!opened) {
216  throw Exception("V4L1Cam: Trying to start closed cam!");
217  }
218 
219  started = true;
220 }
221 
222 
223 void
224 V4L1Camera::stop()
225 {
226  started = false;
227 }
228 
229 
230 void
231 V4L1Camera::print_info()
232 {
233 
234  if (! opened) return;
235 
236  cout << endl << "CAPABILITIES" << endl
237  << "===========================================================================" << endl;
238 
239  if(__data->capabilities.type & VID_TYPE_CAPTURE)
240  cout << " + Can capture to memory" << endl;
241  if(__data->capabilities.type & VID_TYPE_TUNER)
242  cout << " + Has a tuner of some form" << endl;
243  if(__data->capabilities.type & VID_TYPE_TELETEXT)
244  cout << " + Has teletext capability" << endl;
245  if(__data->capabilities.type & VID_TYPE_OVERLAY)
246  cout << " + Can overlay its image onto the frame buffer" << endl;
247  if(__data->capabilities.type & VID_TYPE_CHROMAKEY)
248  cout << " + Overlay is Chromakeyed" << endl;
249  if(__data->capabilities.type & VID_TYPE_CLIPPING)
250  cout << " + Overlay clipping is supported" << endl;
251  if(__data->capabilities.type & VID_TYPE_FRAMERAM)
252  cout << " + Overlay overwrites frame buffer memory" << endl;
253  if(__data->capabilities.type & VID_TYPE_SCALES)
254  cout << " + The hardware supports image scaling" << endl;
255  if(__data->capabilities.type & VID_TYPE_MONOCHROME)
256  cout << " + Image capture is grey scale only" << endl;
257  if(__data->capabilities.type & VID_TYPE_SUBCAPTURE)
258  cout << " + Can subcapture" << endl;
259 
260  cout << endl;
261  cout << " Number of Channels ='" << __data->capabilities.channels << "'" << endl;
262  cout << " Number of Audio Devices ='" << __data->capabilities.audios << "'" << endl;
263  cout << " Maximum Capture Width ='" << __data->capabilities.maxwidth << "'" << endl;
264  cout << " Maximum Capture Height ='" << __data->capabilities.maxheight << "'" << endl;
265  cout << " Minimum Capture Width ='" << __data->capabilities.minwidth << "'" << endl;
266  cout << " Minimum Capture Height ='" << __data->capabilities.minheight << "'" << endl;
267 
268 
269 
270 
271  cout << endl << "CAPTURE WINDOW INFO" << endl
272  << "===========================================================================" << endl;
273 
274  cout << " X Coord in X window Format: " << __data->window.x << endl;
275  cout << " Y Coord in X window Format: " << __data->window.y << endl;
276  cout << " Width of the Image Capture: " << __data->window.width << endl;
277  cout << " Height of the Image Capture: " << __data->window.height << endl;
278  cout << " ChromaKey: " << __data->window.chromakey << endl;
279 
280 
281 
282 
283  cout << endl << "DEVICE PICTURE INFO" << endl
284  << "===========================================================================" << endl;
285 
286  cout << " Picture Brightness: " << __data->picture.brightness << endl;
287  cout << " Picture Hue: " << __data->picture.hue << endl;
288  cout << " Picture Colour: " << __data->picture.colour << endl;
289  cout << " Picture Contrast: " << __data->picture.contrast << endl;
290  cout << " Picture Whiteness: " << __data->picture.whiteness << endl;
291  cout << " Picture Depth: " << __data->picture.depth << endl;
292  cout << " Picture Palette: " << __data->picture.palette << " (";
293 
294  if(__data->picture.palette == VIDEO_PALETTE_GREY)
295  cout << "VIDEO_PALETTE_GRAY";
296  if(__data->picture.palette == VIDEO_PALETTE_HI240)
297  cout << "VIDEO_PALETTE_HI240";
298  if(__data->picture.palette == VIDEO_PALETTE_RGB565)
299  cout << "VIDEO_PALETTE_RGB565";
300  if(__data->picture.palette == VIDEO_PALETTE_RGB555)
301  cout << "VIDEO_PALETTE_RGB555";
302  if(__data->picture.palette == VIDEO_PALETTE_RGB24)
303  cout << "VIDEO_PALETTE_RGB24";
304  if(__data->picture.palette == VIDEO_PALETTE_RGB32)
305  cout << "VIDEO_PALETTE_RGB32";
306  if(__data->picture.palette == VIDEO_PALETTE_YUV422)
307  cout << "VIDEO_PALETTE_YUV422";
308  if(__data->picture.palette == VIDEO_PALETTE_YUYV)
309  cout << "VIDEO_PALETTE_YUYV";
310  if(__data->picture.palette == VIDEO_PALETTE_UYVY)
311  cout << "VIDEO_PALETTE_UYVY";
312  if(__data->picture.palette == VIDEO_PALETTE_YUV420)
313  cout << "VIDEO_PALETTE_YUV420";
314  if(__data->picture.palette == VIDEO_PALETTE_YUV411)
315  cout << "VIDEO_PALETTE_YUV411";
316  if(__data->picture.palette == VIDEO_PALETTE_RAW)
317  cout << "VIDEO_PALETTE_RAW";
318  if(__data->picture.palette == VIDEO_PALETTE_YUV422P)
319  cout << "VIDEO_PALETTE_YUV422P";
320  if(__data->picture.palette == VIDEO_PALETTE_YUV411P)
321  cout << "VIDEO_PALETTE_YUV411P";
322 
323  cout << ")" << endl;
324 
325 
326 
327  cout << endl << "VIDEO SOURCE INFO" << endl
328  << "===========================================================================" << endl;
329 
330  cout << " Channel Number or Video Source Number: " << __data->channel->channel << endl;
331  cout << " Channel Name: " << __data->channel->name << endl;
332  cout << " Number of Tuners for this source: " << __data->channel->tuners << endl;
333  cout << " Channel Norm: " << __data->channel->norm << endl;
334  if(__data->channel->flags & VIDEO_VC_TUNER)
335  cout << " + This channel source has tuners" << endl;
336  if(__data->channel->flags & VIDEO_VC_AUDIO)
337  cout << " + This channel source has audio" << endl;
338  if(__data->channel->type & VIDEO_TYPE_TV)
339  cout << " + This channel source is a TV input" << endl;
340  if(__data->channel->type & VIDEO_TYPE_CAMERA)
341  cout << " + This channel source is a Camera input" << endl;
342 
343 
344 
345 
346  cout << endl << "FRAME BUFFER INFO" << endl
347  << "===========================================================================" << endl;
348 
349  cout << " Base Physical Address: " << __data->vbuffer.base << endl;
350  cout << " Height of Frame Buffer: " << __data->vbuffer.height << endl;
351  cout << " Width of Frame Buffer: " << __data->vbuffer.width << endl;
352  cout << " Depth of Frame Buffer: " << __data->vbuffer.depth << endl;
353  cout << " Bytes Per Line: " << __data->vbuffer.bytesperline << endl;
354 
355 
356 
357  /* Which channel!?
358  cout << endl << "CHANNEL INFO" << endl
359  << "===========================================================================" << endl;
360 
361  cout << " Channel: " << ch << " - " << channel[ch].name << endl;
362  cout << " Number of Tuners: " << channel[0].tuners << endl;
363  cout << " Input Type: " << channel[ch].type << endl;
364  cout << " Flags: " << endl;
365  if(channel[0].flags & VIDEO_VC_TUNER)
366  cout << " + This Channel Source has Tuners" << endl;
367  if(channel[0].flags & VIDEO_VC_AUDIO)
368  cout << " + This Channel Source has Audio" << endl;
369  // if(channel[0].flags & VIDEO_VC_NORM)
370  //cout << " \tThis Channel Source has Norm\n");
371  cout << " Norm for Channel: '" << channel[0].norm << "'" << endl;
372  */
373 
374 }
375 
376 
377 void
378 V4L1Camera::capture()
379 {
380 
381  if (capture_method == READ) {
382  int len = read(dev, frame_buffer, __data->window.width * __data->window.height * RGB_PIXEL_SIZE);
383  if (len < 0) {
384  throw Exception("V4L1Cam: Could not capture frame");
385  }
386  } else {
387 
388  __data->buf_v4l = (struct video_mmap*)malloc(__data->captured_frame_buffer.frames * sizeof(struct video_mmap));
389 
390  ///Setting up the palette, size of frame and which frame to capture
391  __data->buf_v4l[0].format = __data->picture.palette;
392  __data->buf_v4l[0].frame = 0;
393  __data->buf_v4l[0].width = __data->window.width;
394  __data->buf_v4l[0].height = __data->window.height;
395 
396  if (ioctl (dev, VIDIOCMCAPTURE, &(__data->buf_v4l[0])) == -1) {
397  throw Exception("V4L1Cam: Could not capture frame (VIDIOCMCAPTURE)");
398  }
399  ///Waiting for the frame to finish
400  int Frame = 0;
401  if (ioctl (dev, VIDIOCSYNC, &Frame) == -1) {
402  throw Exception("V4L1Cam: Could not capture frame (VIDIOCSYNC)");
403  }
404  }
405 }
406 
407 
408 void
409 V4L1Camera::dispose_buffer()
410 {
411  if (capture_method == MMAP) {
412  if (__data->buf_v4l != NULL) {
413  free(__data->buf_v4l);
414  __data->buf_v4l = NULL;
415  }
416  munmap(frame_buffer, __data->captured_frame_buffer.size);
417  }
418 }
419 
420 
421 unsigned char*
422 V4L1Camera::buffer()
423 {
424  return frame_buffer;
425 }
426 
427 unsigned int
428 V4L1Camera::buffer_size()
429 {
430  return colorspace_buffer_size(RGB, __data->window.width, __data->window.height);
431 }
432 
433 void
434 V4L1Camera::close()
435 {
436  if (opened) {
437  ::close(dev);
438  }
439 }
440 
441 unsigned int
442 V4L1Camera::pixel_width()
443 {
444  if (opened) {
445  return __data->window.width;
446  } else {
447  throw Exception("V4L1Cam::pixel_width(): Camera not opened");
448  }
449 }
450 
451 unsigned int
452 V4L1Camera::pixel_height()
453 {
454  if (opened) {
455  return __data->window.height;
456  } else {
457  throw Exception("V4L1Cam::pixel_height(): Camera not opened");
458  }
459 }
460 
461 
462 colorspace_t
463 V4L1Camera::colorspace()
464 {
465  return BGR;
466 }
467 
468 
469 void
470 V4L1Camera::flush()
471 {
472 }
473 
474 
475 bool
476 V4L1Camera::ready()
477 {
478  return started;
479 }
480 
481 
482 void
483 V4L1Camera::set_image_number(unsigned int n)
484 {
485 }
486 
487 } // end namespace firevision
Fawkes library namespace.
STL namespace.
Camera argument parser.
Definition: camargp.h:38
bool has(std::string s) const
Check if an parameter was given.
Definition: camargp.cpp:152
Base class for exceptions in Fawkes.
Definition: exception.h:36
std::string get(std::string s) const
Get the value of the given parameter.
Definition: camargp.cpp:164
Expected parameter is missing.
Definition: software.h:76