v4l1.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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>
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
00054 }
00055 #endif
00056
00057
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
00076 struct video_capability capabilities;
00077 struct video_buffer vbuffer;
00078 struct video_window window;
00079 struct video_channel *channel;
00080 struct video_picture picture;
00081 struct video_tuner *tuner;
00082 struct video_audio audio;
00083 struct video_mbuf captured_frame_buffer;
00084 struct video_mmap *buf_v4l;
00085 };
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 V4L1Camera::V4L1Camera(const char *device_name)
00097 {
00098 started = opened = false;
00099 __data = new V4L1CameraData(device_name);
00100 }
00101
00102
00103
00104
00105
00106
00107
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
00120
00121
00122
00123
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
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
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
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
00167
00168
00169 void
00170 V4L1Camera::post_open()
00171 {
00172
00173 if ( (ioctl(dev, VIDIOCGWIN, &__data->window)) == -1) {
00174 throw Exception("V4L1Cam: Could not get window information");
00175 }
00176
00177
00178 if ( (ioctl(dev, VIDIOCGPICT, &__data->picture)) == -1) {
00179 throw Exception("V4L1Cam: Could not get window information");
00180 }
00181
00182
00183
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
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
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
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
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
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 }