Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * v4l1.cpp - Implementation to access V4L cam 00004 * 00005 * Generated: Fri Mar 11 17:48:27 2005 00006 * Copyright 2005 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <core/exception.h> 00025 #include <core/exceptions/software.h> 00026 00027 #include <cams/v4l1.h> 00028 #include <fvutils/color/colorspaces.h> 00029 #include <fvutils/color/rgb.h> 00030 #include <fvutils/system/camargp.h> 00031 00032 #include <cstdio> 00033 #include <cstdlib> 00034 #include <sys/stat.h> 00035 #include <sys/ioctl.h> 00036 #include <sys/mman.h> 00037 #include <sys/time.h> /* gettimeofday() */ 00038 #include <fcntl.h> 00039 #include <unistd.h> 00040 #include <linux/types.h> 00041 #include <errno.h> 00042 #include <cstring> 00043 #include <iostream> 00044 #include <cassert> 00045 #include <sys/types.h> 00046 #include <linux/videodev.h> 00047 00048 00049 using namespace std; 00050 using namespace fawkes; 00051 00052 namespace firevision { 00053 #if 0 /* just to make Emacs auto-indent happy */ 00054 } 00055 #endif 00056 00057 /// @cond INTERNALS 00058 00059 class V4L1CameraData 00060 { 00061 public: 00062 V4L1CameraData(const char *device_name) 00063 { 00064 this->device_name = strdup(device_name); 00065 } 00066 00067 ~V4L1CameraData() 00068 { 00069 free(device_name); 00070 } 00071 00072 public: 00073 char *device_name; 00074 00075 /* V4L1 stuff */ 00076 struct video_capability capabilities; // Device Capabilities: Can overlay, Number of channels, etc 00077 struct video_buffer vbuffer; // information about buffer 00078 struct video_window window; // Window Information: Size, Depth, etc 00079 struct video_channel *channel; // Channels information: Channel[0] holds information for channel 0 and so on... 00080 struct video_picture picture; // Picture information: Palette, contrast, hue, etc 00081 struct video_tuner *tuner; // Tuner Information: if the card has tuners... 00082 struct video_audio audio; // If the card has audio 00083 struct video_mbuf captured_frame_buffer; // Information for the frame to be captured: norm, palette, etc 00084 struct video_mmap *buf_v4l; // mmap() buffer VIDIOCMCAPTURE 00085 }; 00086 00087 /// @endcond 00088 00089 /** @class V4L1Camera <cams/v4l1.h> 00090 * Video4Linux 1 camera implementation. 00091 */ 00092 00093 /** Constructor. 00094 * @param device_name device file name (e.g. /dev/video0) 00095 */ 00096 V4L1Camera::V4L1Camera(const char *device_name) 00097 { 00098 started = opened = false; 00099 __data = new V4L1CameraData(device_name); 00100 } 00101 00102 00103 /** Constructor. 00104 * Initialize camera with parameters from camera argument parser. 00105 * Supported arguments: 00106 * - device=DEV, device file, for example /dev/video0 00107 * @param cap camera argument parser 00108 */ 00109 V4L1Camera::V4L1Camera(const CameraArgumentParser *cap) 00110 { 00111 started = opened = false; 00112 if ( cap->has("device") ) { 00113 __data = new V4L1CameraData(cap->get("device").c_str()); 00114 } else { 00115 throw MissingParameterException("Missing device for V4L1Camera"); 00116 } 00117 } 00118 00119 /** Protected Constructor. 00120 * Gets called from V4LCamera, when the device has already been opened 00121 * and determined to be a V4L1 device. 00122 * @param device_name device file name (e.g. /dev/video0) 00123 * @param dev file descriptor of the opened device 00124 */ 00125 V4L1Camera::V4L1Camera(const char *device_name, int dev) 00126 { 00127 started = opened = false; 00128 __data = new V4L1CameraData(device_name); 00129 this->dev = dev; 00130 00131 // getting grabber info in capabilities struct 00132 if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) { 00133 throw Exception("V4L1Cam: Could not get capabilities"); 00134 } 00135 00136 post_open(); 00137 } 00138 00139 00140 /** Destructor. */ 00141 V4L1Camera::~V4L1Camera() 00142 { 00143 delete __data; 00144 } 00145 00146 00147 void 00148 V4L1Camera::open() 00149 { 00150 opened = false; 00151 00152 dev = ::open(__data->device_name, O_RDWR); 00153 if (dev < 0) { 00154 throw Exception("V4L1Cam: Could not open device"); 00155 } 00156 00157 // getting grabber info in capabilities struct 00158 if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) { 00159 throw Exception("V4L1Cam: Could not get capabilities"); 00160 } 00161 00162 post_open(); 00163 } 00164 00165 /** 00166 * Post-open() operations 00167 * @param dev file descriptor of the opened device 00168 */ 00169 void 00170 V4L1Camera::post_open() 00171 { 00172 // Capture window information 00173 if ( (ioctl(dev, VIDIOCGWIN, &__data->window)) == -1) { 00174 throw Exception("V4L1Cam: Could not get window information"); 00175 } 00176 00177 // Picture information 00178 if ( (ioctl(dev, VIDIOCGPICT, &__data->picture)) == -1) { 00179 throw Exception("V4L1Cam: Could not get window information"); 00180 } 00181 00182 ///Video Channel Information or Video Sources 00183 ///Allocate space for each channel 00184 __data->channel = (struct video_channel*)malloc(sizeof(struct video_channel)*(__data->capabilities.channels+1)); 00185 for(int ch = 0; ch < __data->capabilities.channels; ch++) { 00186 __data->channel[ch].norm = 0; 00187 if ( (ioctl(dev, VIDIOCSCHAN, &__data->channel[ch])) == -1) { 00188 printf("V4L1Cam: Could not get channel information for channel %i: %s", ch, strerror(errno)); 00189 } 00190 } 00191 00192 ///Trying to capture through read() 00193 if (ioctl (dev, VIDIOCGMBUF, __data->captured_frame_buffer) == -1) { 00194 capture_method = READ; 00195 frame_buffer = (unsigned char *)malloc(__data->window.width * __data->window.height * RGB_PIXEL_SIZE); 00196 } else { 00197 capture_method = MMAP; 00198 frame_buffer = (unsigned char*)mmap (0, __data->captured_frame_buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev, 0); 00199 if ((unsigned char *) -1 == (unsigned char *)frame_buffer) { 00200 throw Exception("V4L1Cam: Cannot initialize mmap region"); 00201 } 00202 } 00203 00204 __data->buf_v4l = NULL; 00205 00206 opened = true; 00207 } 00208 00209 00210 void 00211 V4L1Camera::start() 00212 { 00213 00214 started = false; 00215 if (!opened) { 00216 throw Exception("V4L1Cam: Trying to start closed cam!"); 00217 } 00218 00219 started = true; 00220 } 00221 00222 00223 void 00224 V4L1Camera::stop() 00225 { 00226 started = false; 00227 } 00228 00229 00230 void 00231 V4L1Camera::print_info() 00232 { 00233 00234 if (! opened) return; 00235 00236 cout << endl << "CAPABILITIES" << endl 00237 << "===========================================================================" << endl; 00238 00239 if(__data->capabilities.type & VID_TYPE_CAPTURE) 00240 cout << " + Can capture to memory" << endl; 00241 if(__data->capabilities.type & VID_TYPE_TUNER) 00242 cout << " + Has a tuner of some form" << endl; 00243 if(__data->capabilities.type & VID_TYPE_TELETEXT) 00244 cout << " + Has teletext capability" << endl; 00245 if(__data->capabilities.type & VID_TYPE_OVERLAY) 00246 cout << " + Can overlay its image onto the frame buffer" << endl; 00247 if(__data->capabilities.type & VID_TYPE_CHROMAKEY) 00248 cout << " + Overlay is Chromakeyed" << endl; 00249 if(__data->capabilities.type & VID_TYPE_CLIPPING) 00250 cout << " + Overlay clipping is supported" << endl; 00251 if(__data->capabilities.type & VID_TYPE_FRAMERAM) 00252 cout << " + Overlay overwrites frame buffer memory" << endl; 00253 if(__data->capabilities.type & VID_TYPE_SCALES) 00254 cout << " + The hardware supports image scaling" << endl; 00255 if(__data->capabilities.type & VID_TYPE_MONOCHROME) 00256 cout << " + Image capture is grey scale only" << endl; 00257 if(__data->capabilities.type & VID_TYPE_SUBCAPTURE) 00258 cout << " + Can subcapture" << endl; 00259 00260 cout << endl; 00261 cout << " Number of Channels ='" << __data->capabilities.channels << "'" << endl; 00262 cout << " Number of Audio Devices ='" << __data->capabilities.audios << "'" << endl; 00263 cout << " Maximum Capture Width ='" << __data->capabilities.maxwidth << "'" << endl; 00264 cout << " Maximum Capture Height ='" << __data->capabilities.maxheight << "'" << endl; 00265 cout << " Minimum Capture Width ='" << __data->capabilities.minwidth << "'" << endl; 00266 cout << " Minimum Capture Height ='" << __data->capabilities.minheight << "'" << endl; 00267 00268 00269 00270 00271 cout << endl << "CAPTURE WINDOW INFO" << endl 00272 << "===========================================================================" << endl; 00273 00274 cout << " X Coord in X window Format: " << __data->window.x << endl; 00275 cout << " Y Coord in X window Format: " << __data->window.y << endl; 00276 cout << " Width of the Image Capture: " << __data->window.width << endl; 00277 cout << " Height of the Image Capture: " << __data->window.height << endl; 00278 cout << " ChromaKey: " << __data->window.chromakey << endl; 00279 00280 00281 00282 00283 cout << endl << "DEVICE PICTURE INFO" << endl 00284 << "===========================================================================" << endl; 00285 00286 cout << " Picture Brightness: " << __data->picture.brightness << endl; 00287 cout << " Picture Hue: " << __data->picture.hue << endl; 00288 cout << " Picture Colour: " << __data->picture.colour << endl; 00289 cout << " Picture Contrast: " << __data->picture.contrast << endl; 00290 cout << " Picture Whiteness: " << __data->picture.whiteness << endl; 00291 cout << " Picture Depth: " << __data->picture.depth << endl; 00292 cout << " Picture Palette: " << __data->picture.palette << " ("; 00293 00294 if(__data->picture.palette == VIDEO_PALETTE_GREY) 00295 cout << "VIDEO_PALETTE_GRAY"; 00296 if(__data->picture.palette == VIDEO_PALETTE_HI240) 00297 cout << "VIDEO_PALETTE_HI240"; 00298 if(__data->picture.palette == VIDEO_PALETTE_RGB565) 00299 cout << "VIDEO_PALETTE_RGB565"; 00300 if(__data->picture.palette == VIDEO_PALETTE_RGB555) 00301 cout << "VIDEO_PALETTE_RGB555"; 00302 if(__data->picture.palette == VIDEO_PALETTE_RGB24) 00303 cout << "VIDEO_PALETTE_RGB24"; 00304 if(__data->picture.palette == VIDEO_PALETTE_RGB32) 00305 cout << "VIDEO_PALETTE_RGB32"; 00306 if(__data->picture.palette == VIDEO_PALETTE_YUV422) 00307 cout << "VIDEO_PALETTE_YUV422"; 00308 if(__data->picture.palette == VIDEO_PALETTE_YUYV) 00309 cout << "VIDEO_PALETTE_YUYV"; 00310 if(__data->picture.palette == VIDEO_PALETTE_UYVY) 00311 cout << "VIDEO_PALETTE_UYVY"; 00312 if(__data->picture.palette == VIDEO_PALETTE_YUV420) 00313 cout << "VIDEO_PALETTE_YUV420"; 00314 if(__data->picture.palette == VIDEO_PALETTE_YUV411) 00315 cout << "VIDEO_PALETTE_YUV411"; 00316 if(__data->picture.palette == VIDEO_PALETTE_RAW) 00317 cout << "VIDEO_PALETTE_RAW"; 00318 if(__data->picture.palette == VIDEO_PALETTE_YUV422P) 00319 cout << "VIDEO_PALETTE_YUV422P"; 00320 if(__data->picture.palette == VIDEO_PALETTE_YUV411P) 00321 cout << "VIDEO_PALETTE_YUV411P"; 00322 00323 cout << ")" << endl; 00324 00325 00326 00327 cout << endl << "VIDEO SOURCE INFO" << endl 00328 << "===========================================================================" << endl; 00329 00330 cout << " Channel Number or Video Source Number: " << __data->channel->channel << endl; 00331 cout << " Channel Name: " << __data->channel->name << endl; 00332 cout << " Number of Tuners for this source: " << __data->channel->tuners << endl; 00333 cout << " Channel Norm: " << __data->channel->norm << endl; 00334 if(__data->channel->flags & VIDEO_VC_TUNER) 00335 cout << " + This channel source has tuners" << endl; 00336 if(__data->channel->flags & VIDEO_VC_AUDIO) 00337 cout << " + This channel source has audio" << endl; 00338 if(__data->channel->type & VIDEO_TYPE_TV) 00339 cout << " + This channel source is a TV input" << endl; 00340 if(__data->channel->type & VIDEO_TYPE_CAMERA) 00341 cout << " + This channel source is a Camera input" << endl; 00342 00343 00344 00345 00346 cout << endl << "FRAME BUFFER INFO" << endl 00347 << "===========================================================================" << endl; 00348 00349 cout << " Base Physical Address: " << __data->vbuffer.base << endl; 00350 cout << " Height of Frame Buffer: " << __data->vbuffer.height << endl; 00351 cout << " Width of Frame Buffer: " << __data->vbuffer.width << endl; 00352 cout << " Depth of Frame Buffer: " << __data->vbuffer.depth << endl; 00353 cout << " Bytes Per Line: " << __data->vbuffer.bytesperline << endl; 00354 00355 00356 00357 /* Which channel!? 00358 cout << endl << "CHANNEL INFO" << endl 00359 << "===========================================================================" << endl; 00360 00361 cout << " Channel: " << ch << " - " << channel[ch].name << endl; 00362 cout << " Number of Tuners: " << channel[0].tuners << endl; 00363 cout << " Input Type: " << channel[ch].type << endl; 00364 cout << " Flags: " << endl; 00365 if(channel[0].flags & VIDEO_VC_TUNER) 00366 cout << " + This Channel Source has Tuners" << endl; 00367 if(channel[0].flags & VIDEO_VC_AUDIO) 00368 cout << " + This Channel Source has Audio" << endl; 00369 // if(channel[0].flags & VIDEO_VC_NORM) 00370 //cout << " \tThis Channel Source has Norm\n"); 00371 cout << " Norm for Channel: '" << channel[0].norm << "'" << endl; 00372 */ 00373 00374 } 00375 00376 00377 void 00378 V4L1Camera::capture() 00379 { 00380 00381 if (capture_method == READ) { 00382 int len = read(dev, frame_buffer, __data->window.width * __data->window.height * RGB_PIXEL_SIZE); 00383 if (len < 0) { 00384 throw Exception("V4L1Cam: Could not capture frame"); 00385 } 00386 } else { 00387 00388 __data->buf_v4l = (struct video_mmap*)malloc(__data->captured_frame_buffer.frames * sizeof(struct video_mmap)); 00389 00390 ///Setting up the palette, size of frame and which frame to capture 00391 __data->buf_v4l[0].format = __data->picture.palette; 00392 __data->buf_v4l[0].frame = 0; 00393 __data->buf_v4l[0].width = __data->window.width; 00394 __data->buf_v4l[0].height = __data->window.height; 00395 00396 if (ioctl (dev, VIDIOCMCAPTURE, &(__data->buf_v4l[0])) == -1) { 00397 throw Exception("V4L1Cam: Could not capture frame (VIDIOCMCAPTURE)"); 00398 } 00399 ///Waiting for the frame to finish 00400 int Frame = 0; 00401 if (ioctl (dev, VIDIOCSYNC, &Frame) == -1) { 00402 throw Exception("V4L1Cam: Could not capture frame (VIDIOCSYNC)"); 00403 } 00404 } 00405 } 00406 00407 00408 void 00409 V4L1Camera::dispose_buffer() 00410 { 00411 if (capture_method == MMAP) { 00412 if (__data->buf_v4l != NULL) { 00413 free(__data->buf_v4l); 00414 __data->buf_v4l = NULL; 00415 } 00416 munmap(frame_buffer, __data->captured_frame_buffer.size); 00417 } 00418 } 00419 00420 00421 unsigned char* 00422 V4L1Camera::buffer() 00423 { 00424 return frame_buffer; 00425 } 00426 00427 unsigned int 00428 V4L1Camera::buffer_size() 00429 { 00430 return colorspace_buffer_size(RGB, __data->window.width, __data->window.height); 00431 } 00432 00433 void 00434 V4L1Camera::close() 00435 { 00436 if (opened) { 00437 ::close(dev); 00438 } 00439 } 00440 00441 unsigned int 00442 V4L1Camera::pixel_width() 00443 { 00444 if (opened) { 00445 return __data->window.width; 00446 } else { 00447 throw Exception("V4L1Cam::pixel_width(): Camera not opened"); 00448 } 00449 } 00450 00451 unsigned int 00452 V4L1Camera::pixel_height() 00453 { 00454 if (opened) { 00455 return __data->window.height; 00456 } else { 00457 throw Exception("V4L1Cam::pixel_height(): Camera not opened"); 00458 } 00459 } 00460 00461 00462 colorspace_t 00463 V4L1Camera::colorspace() 00464 { 00465 return BGR; 00466 } 00467 00468 00469 void 00470 V4L1Camera::flush() 00471 { 00472 } 00473 00474 00475 bool 00476 V4L1Camera::ready() 00477 { 00478 return started; 00479 } 00480 00481 00482 void 00483 V4L1Camera::set_image_number(unsigned int n) 00484 { 00485 } 00486 00487 } // end namespace firevision