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