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
00053
00054 class V4L1CameraData
00055 {
00056 public:
00057 V4L1CameraData(const char *device_name)
00058 {
00059 this->device_name = strdup(device_name);
00060 }
00061
00062 ~V4L1CameraData()
00063 {
00064 free(device_name);
00065 }
00066
00067 public:
00068 char *device_name;
00069
00070
00071 struct video_capability capabilities;
00072 struct video_buffer vbuffer;
00073 struct video_window window;
00074 struct video_channel *channel;
00075 struct video_picture picture;
00076 struct video_tuner *tuner;
00077 struct video_audio audio;
00078 struct video_mbuf captured_frame_buffer;
00079 struct video_mmap *buf_v4l;
00080 };
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 V4L1Camera::V4L1Camera(const char *device_name)
00092 {
00093 started = opened = false;
00094 __data = new V4L1CameraData(device_name);
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 V4L1Camera::V4L1Camera(const CameraArgumentParser *cap)
00105 {
00106 started = opened = false;
00107 if ( cap->has("device") ) {
00108 __data = new V4L1CameraData(cap->get("device").c_str());
00109 } else {
00110 throw MissingParameterException("Missing device for V4L1Camera");
00111 }
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 V4L1Camera::V4L1Camera(const char *device_name, int dev)
00121 {
00122 started = opened = false;
00123 __data = new V4L1CameraData(device_name);
00124 this->dev = dev;
00125
00126
00127 if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) {
00128 throw Exception("V4L1Cam: Could not get capabilities");
00129 }
00130
00131 post_open();
00132 }
00133
00134
00135
00136 V4L1Camera::~V4L1Camera()
00137 {
00138 delete __data;
00139 }
00140
00141
00142 void
00143 V4L1Camera::open()
00144 {
00145 opened = false;
00146
00147 dev = ::open(__data->device_name, O_RDWR);
00148 if (dev < 0) {
00149 throw Exception("V4L1Cam: Could not open device");
00150 }
00151
00152
00153 if ( (ioctl(dev, VIDIOCGCAP, &(__data->capabilities))) == -1 ) {
00154 throw Exception("V4L1Cam: Could not get capabilities");
00155 }
00156
00157 post_open();
00158 }
00159
00160
00161
00162
00163
00164 void
00165 V4L1Camera::post_open()
00166 {
00167
00168 if ( (ioctl(dev, VIDIOCGWIN, &__data->window)) == -1) {
00169 throw Exception("V4L1Cam: Could not get window information");
00170 }
00171
00172
00173 if ( (ioctl(dev, VIDIOCGPICT, &__data->picture)) == -1) {
00174 throw Exception("V4L1Cam: Could not get window information");
00175 }
00176
00177
00178
00179 __data->channel = (struct video_channel*)malloc(sizeof(struct video_channel)*(__data->capabilities.channels+1));
00180 for(int ch = 0; ch < __data->capabilities.channels; ch++) {
00181 __data->channel[ch].norm = 0;
00182 if ( (ioctl(dev, VIDIOCSCHAN, &__data->channel[ch])) == -1) {
00183 printf("V4L1Cam: Could not get channel information for channel %i: %s", ch, strerror(errno));
00184 }
00185 }
00186
00187
00188 if (ioctl (dev, VIDIOCGMBUF, __data->captured_frame_buffer) == -1) {
00189 capture_method = READ;
00190 frame_buffer = (unsigned char *)malloc(__data->window.width * __data->window.height * RGB_PIXEL_SIZE);
00191 } else {
00192 capture_method = MMAP;
00193 frame_buffer = (unsigned char*)mmap (0, __data->captured_frame_buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev, 0);
00194 if ((unsigned char *) -1 == (unsigned char *)frame_buffer) {
00195 throw Exception("V4L1Cam: Cannot initialize mmap region");
00196 }
00197 }
00198
00199 __data->buf_v4l = NULL;
00200
00201 opened = true;
00202 }
00203
00204
00205 void
00206 V4L1Camera::start()
00207 {
00208
00209 started = false;
00210 if (!opened) {
00211 throw Exception("V4L1Cam: Trying to start closed cam!");
00212 }
00213
00214 started = true;
00215 }
00216
00217
00218 void
00219 V4L1Camera::stop()
00220 {
00221 started = false;
00222 }
00223
00224
00225 void
00226 V4L1Camera::print_info()
00227 {
00228
00229 if (! opened) return;
00230
00231 cout << endl << "CAPABILITIES" << endl
00232 << "===========================================================================" << endl;
00233
00234 if(__data->capabilities.type & VID_TYPE_CAPTURE)
00235 cout << " + Can capture to memory" << endl;
00236 if(__data->capabilities.type & VID_TYPE_TUNER)
00237 cout << " + Has a tuner of some form" << endl;
00238 if(__data->capabilities.type & VID_TYPE_TELETEXT)
00239 cout << " + Has teletext capability" << endl;
00240 if(__data->capabilities.type & VID_TYPE_OVERLAY)
00241 cout << " + Can overlay its image onto the frame buffer" << endl;
00242 if(__data->capabilities.type & VID_TYPE_CHROMAKEY)
00243 cout << " + Overlay is Chromakeyed" << endl;
00244 if(__data->capabilities.type & VID_TYPE_CLIPPING)
00245 cout << " + Overlay clipping is supported" << endl;
00246 if(__data->capabilities.type & VID_TYPE_FRAMERAM)
00247 cout << " + Overlay overwrites frame buffer memory" << endl;
00248 if(__data->capabilities.type & VID_TYPE_SCALES)
00249 cout << " + The hardware supports image scaling" << endl;
00250 if(__data->capabilities.type & VID_TYPE_MONOCHROME)
00251 cout << " + Image capture is grey scale only" << endl;
00252 if(__data->capabilities.type & VID_TYPE_SUBCAPTURE)
00253 cout << " + Can subcapture" << endl;
00254
00255 cout << endl;
00256 cout << " Number of Channels ='" << __data->capabilities.channels << "'" << endl;
00257 cout << " Number of Audio Devices ='" << __data->capabilities.audios << "'" << endl;
00258 cout << " Maximum Capture Width ='" << __data->capabilities.maxwidth << "'" << endl;
00259 cout << " Maximum Capture Height ='" << __data->capabilities.maxheight << "'" << endl;
00260 cout << " Minimum Capture Width ='" << __data->capabilities.minwidth << "'" << endl;
00261 cout << " Minimum Capture Height ='" << __data->capabilities.minheight << "'" << endl;
00262
00263
00264
00265
00266 cout << endl << "CAPTURE WINDOW INFO" << endl
00267 << "===========================================================================" << endl;
00268
00269 cout << " X Coord in X window Format: " << __data->window.x << endl;
00270 cout << " Y Coord in X window Format: " << __data->window.y << endl;
00271 cout << " Width of the Image Capture: " << __data->window.width << endl;
00272 cout << " Height of the Image Capture: " << __data->window.height << endl;
00273 cout << " ChromaKey: " << __data->window.chromakey << endl;
00274
00275
00276
00277
00278 cout << endl << "DEVICE PICTURE INFO" << endl
00279 << "===========================================================================" << endl;
00280
00281 cout << " Picture Brightness: " << __data->picture.brightness << endl;
00282 cout << " Picture Hue: " << __data->picture.hue << endl;
00283 cout << " Picture Colour: " << __data->picture.colour << endl;
00284 cout << " Picture Contrast: " << __data->picture.contrast << endl;
00285 cout << " Picture Whiteness: " << __data->picture.whiteness << endl;
00286 cout << " Picture Depth: " << __data->picture.depth << endl;
00287 cout << " Picture Palette: " << __data->picture.palette << " (";
00288
00289 if(__data->picture.palette == VIDEO_PALETTE_GREY)
00290 cout << "VIDEO_PALETTE_GRAY";
00291 if(__data->picture.palette == VIDEO_PALETTE_HI240)
00292 cout << "VIDEO_PALETTE_HI240";
00293 if(__data->picture.palette == VIDEO_PALETTE_RGB565)
00294 cout << "VIDEO_PALETTE_RGB565";
00295 if(__data->picture.palette == VIDEO_PALETTE_RGB555)
00296 cout << "VIDEO_PALETTE_RGB555";
00297 if(__data->picture.palette == VIDEO_PALETTE_RGB24)
00298 cout << "VIDEO_PALETTE_RGB24";
00299 if(__data->picture.palette == VIDEO_PALETTE_RGB32)
00300 cout << "VIDEO_PALETTE_RGB32";
00301 if(__data->picture.palette == VIDEO_PALETTE_YUV422)
00302 cout << "VIDEO_PALETTE_YUV422";
00303 if(__data->picture.palette == VIDEO_PALETTE_YUYV)
00304 cout << "VIDEO_PALETTE_YUYV";
00305 if(__data->picture.palette == VIDEO_PALETTE_UYVY)
00306 cout << "VIDEO_PALETTE_UYVY";
00307 if(__data->picture.palette == VIDEO_PALETTE_YUV420)
00308 cout << "VIDEO_PALETTE_YUV420";
00309 if(__data->picture.palette == VIDEO_PALETTE_YUV411)
00310 cout << "VIDEO_PALETTE_YUV411";
00311 if(__data->picture.palette == VIDEO_PALETTE_RAW)
00312 cout << "VIDEO_PALETTE_RAW";
00313 if(__data->picture.palette == VIDEO_PALETTE_YUV422P)
00314 cout << "VIDEO_PALETTE_YUV422P";
00315 if(__data->picture.palette == VIDEO_PALETTE_YUV411P)
00316 cout << "VIDEO_PALETTE_YUV411P";
00317
00318 cout << ")" << endl;
00319
00320
00321
00322 cout << endl << "VIDEO SOURCE INFO" << endl
00323 << "===========================================================================" << endl;
00324
00325 cout << " Channel Number or Video Source Number: " << __data->channel->channel << endl;
00326 cout << " Channel Name: " << __data->channel->name << endl;
00327 cout << " Number of Tuners for this source: " << __data->channel->tuners << endl;
00328 cout << " Channel Norm: " << __data->channel->norm << endl;
00329 if(__data->channel->flags & VIDEO_VC_TUNER)
00330 cout << " + This channel source has tuners" << endl;
00331 if(__data->channel->flags & VIDEO_VC_AUDIO)
00332 cout << " + This channel source has audio" << endl;
00333 if(__data->channel->type & VIDEO_TYPE_TV)
00334 cout << " + This channel source is a TV input" << endl;
00335 if(__data->channel->type & VIDEO_TYPE_CAMERA)
00336 cout << " + This channel source is a Camera input" << endl;
00337
00338
00339
00340
00341 cout << endl << "FRAME BUFFER INFO" << endl
00342 << "===========================================================================" << endl;
00343
00344 cout << " Base Physical Address: " << __data->vbuffer.base << endl;
00345 cout << " Height of Frame Buffer: " << __data->vbuffer.height << endl;
00346 cout << " Width of Frame Buffer: " << __data->vbuffer.width << endl;
00347 cout << " Depth of Frame Buffer: " << __data->vbuffer.depth << endl;
00348 cout << " Bytes Per Line: " << __data->vbuffer.bytesperline << endl;
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 }
00370
00371
00372 void
00373 V4L1Camera::capture()
00374 {
00375
00376 if (capture_method == READ) {
00377 int len = read(dev, frame_buffer, __data->window.width * __data->window.height * RGB_PIXEL_SIZE);
00378 if (len < 0) {
00379 throw Exception("V4L1Cam: Could not capture frame");
00380 }
00381 } else {
00382
00383 __data->buf_v4l = (struct video_mmap*)malloc(__data->captured_frame_buffer.frames * sizeof(struct video_mmap));
00384
00385
00386 __data->buf_v4l[0].format = __data->picture.palette;
00387 __data->buf_v4l[0].frame = 0;
00388 __data->buf_v4l[0].width = __data->window.width;
00389 __data->buf_v4l[0].height = __data->window.height;
00390
00391 if (ioctl (dev, VIDIOCMCAPTURE, &(__data->buf_v4l[0])) == -1) {
00392 throw Exception("V4L1Cam: Could not capture frame (VIDIOCMCAPTURE)");
00393 }
00394
00395 int Frame = 0;
00396 if (ioctl (dev, VIDIOCSYNC, &Frame) == -1) {
00397 throw Exception("V4L1Cam: Could not capture frame (VIDIOCSYNC)");
00398 }
00399 }
00400 }
00401
00402
00403 void
00404 V4L1Camera::dispose_buffer()
00405 {
00406 if (capture_method == MMAP) {
00407 if (__data->buf_v4l != NULL) {
00408 free(__data->buf_v4l);
00409 __data->buf_v4l = NULL;
00410 }
00411 munmap(frame_buffer, __data->captured_frame_buffer.size);
00412 }
00413 }
00414
00415
00416 unsigned char*
00417 V4L1Camera::buffer()
00418 {
00419 return frame_buffer;
00420 }
00421
00422 unsigned int
00423 V4L1Camera::buffer_size()
00424 {
00425 return colorspace_buffer_size(RGB, __data->window.width, __data->window.height);
00426 }
00427
00428 void
00429 V4L1Camera::close()
00430 {
00431 if (opened) {
00432 ::close(dev);
00433 }
00434 }
00435
00436 unsigned int
00437 V4L1Camera::pixel_width()
00438 {
00439 if (opened) {
00440 return __data->window.width;
00441 } else {
00442 throw Exception("V4L1Cam::pixel_width(): Camera not opened");
00443 }
00444 }
00445
00446 unsigned int
00447 V4L1Camera::pixel_height()
00448 {
00449 if (opened) {
00450 return __data->window.height;
00451 } else {
00452 throw Exception("V4L1Cam::pixel_height(): Camera not opened");
00453 }
00454 }
00455
00456
00457 colorspace_t
00458 V4L1Camera::colorspace()
00459 {
00460 return BGR;
00461 }
00462
00463
00464 void
00465 V4L1Camera::flush()
00466 {
00467 }
00468
00469
00470 bool
00471 V4L1Camera::ready()
00472 {
00473 return started;
00474 }
00475
00476
00477 void
00478 V4L1Camera::set_image_number(unsigned int n)
00479 {
00480 }