Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

Video4LinuxSource.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00008  *
00009  * Source code for Real Time Image Library (libRTImage)
00010  *
00011  * Leeds Vision Group give permission for this code to be copied, modified 
00012  * and distributed within the University of Leeds subject to the following 
00013  * conditions:-
00014  *
00015  * - The code is not to be used for commercial gain.
00016  * - The code and use thereof will be attributed to the author where
00017  *   appropriate (inluding demonstrations which rely on it's use).
00018  * - All modified, distributions of the source files will retain this header.
00019  *
00020  ****************************************************************************/
00021  
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 
00027 #include <sys/stat.h>
00028 #include <sys/ioctl.h>
00029 #include <sys/mman.h>
00030 
00031 #include "ccvt/conv.h"
00032 #include "pwc-ioctl.h"
00033 
00034 #include "Video4LinuxSource.h"
00035 
00036 #include <string.h>
00037 
00038 Video4LinuxSource::Video4LinuxSource(char* device, bool sup_memory_map)
00045 {
00046         video_capability cap;
00047         video_picture    grab_pic ; 
00048 
00049         capture = sup_memory_map ;
00050 
00051         get_capability(cap);
00052 
00053         if(capture){ 
00054         // Use memory mapping
00055 
00056             if ((fd = open("/dev/video0",O_RDWR)) == -1 ) {
00057                     exit(1);
00058             }
00059 
00060             if (ioctl(fd,VIDIOCGCAP,&cap) == -1) {
00061                     fprintf(stderr,"wrong device\n");
00062                     exit(1);
00063             }
00064             memset (&grab_pic, 0, sizeof(struct video_picture));
00065             if (ioctl (fd, VIDIOCGPICT, &grab_pic) == -1) {
00066                     fprintf (stderr, "no pict");
00067                     exit(1);
00068             }
00069 
00070             get_size(width,height);
00071 
00072             vmmap.frame  = 0 ;
00073             vmmap.width  = width ;
00074             vmmap.height = height ;
00075             vmmap.format = VIDEO_PALETTE_RGB24;
00076             size = vmmap.width * vmmap.height *  (24/8) ; 
00077 
00078             buff = (unsigned char *)mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,
00079                                          fd,0);
00080         
00081             convert_rgb  = conv_bgr24_rgb96;
00082             convert_grey  = conv_rgb24_grey;
00083        }
00084        else{
00085        // Do not use memory mapping
00086 
00087             // open the device
00088             fd = open(device, O_RDWR);
00089             if (fd == -1)
00090                 throw "error opening device";
00091         
00092             // retrieve the size of the Images to be acquired from the device
00093             get_size(width,height);
00094             size = width * height;
00095         
00096             buffsize = int(size * 1.5 + 0.5);
00097             buff     = new (unsigned char)[buffsize];
00098 
00099             // get and set palette to set the conversion routines correctly
00100             get_palette(palette);
00101             set_palette(palette);
00102         
00103         }       
00104 
00105         // default palette type for this ImageSource is colour 
00106         type = Image::COLOUR;
00107 }
00108 
00109 
00110 Video4LinuxSource::~Video4LinuxSource()
00115 {
00116         // unmap the memory map if capturing was supported
00117         if (capture)
00118                 munmap(buff, buffsize);
00119 
00120         // XXX should buff be deleted if mmap created it?       
00121         delete [] buff; 
00122         
00123         close(fd);
00124 }
00125 
00126 
00127 void Video4LinuxSource::set_size(unsigned int w, unsigned int h)
00140 {
00141         video_window  win;
00142 
00143         // first get the existing video_window values.
00144         get_captureWindows(win);
00145         
00146         win.width  = w;
00147         win.height = h;
00148         
00149         set_captureWindows(win);
00150         get_captureWindows(win);
00151 
00152 
00153         if(capture){
00154         // Re set up memory map
00155             width = w; height = h;
00156 
00157             vmmap.width  = width ;
00158             vmmap.height = height ;
00159             vmmap.format = VIDEO_PALETTE_RGB24;
00160             size = vmmap.width * vmmap.height *  (24/8) ;
00161 //            ioctl(fd,VIDIOCGMBUF,mbuf) ;
00162             ioctl(fd,VIDIOCGMBUF,&mbuf) ;
00163 
00164 //            buff = (unsigned char *)mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,
00165             buff = (unsigned char *)mmap(0,mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,
00166                                          fd,0);
00167 
00168         }
00169         else if(width !=win.width || height != win.height){
00170             width = w; height = h;
00171 
00172             delete [] buff;
00173         
00174             size     = win.width * win.height;
00175             buffsize = int(size * 1.5 + 0.5);
00176             buff     = new (unsigned char)[buffsize];
00177             cerr << "size: " << size << endl;   
00178             cerr << "buffsize: " << buffsize << endl;   
00179         }
00180 }
00181 
00182 
00183 void Video4LinuxSource::set_framerate(unsigned int fps)
00195 {
00196         video_window  win;
00197         
00198         // first get the existing video_window values.
00199         get_captureWindows(win);
00200         
00201         win.flags &= ~PWC_FPS_FRMASK;
00202         win.flags |= (fps << PWC_FPS_SHIFT);
00203         
00204         set_captureWindows(win);
00205 }
00206 
00207 
00208 void Video4LinuxSource::set_palette(int pal)
00220 {
00221         video_picture pic;
00222         
00223         // get existing video_picture properties
00224         get_imageProperties(pic);
00225         
00226         pic.palette = pal;
00227 
00228 pic.depth = 24 ;
00229         
00230         set_imageProperties(pic);
00231         get_imageProperties(pic);
00232 
00233 cerr << "Setting pallette " << pal << " " << pic.palette << " " << pic.depth << endl ; 
00234 
00235         // select conversion routines for new palette
00236         switch (pic.palette) {
00237         case VIDEO_PALETTE_RGB32:
00238                 convert_rgb  = conv_rgb32_rgb96;
00239                 convert_grey = conv_rgb32_grey;
00240                 break;
00241         case VIDEO_PALETTE_YUV420P:
00242         default:
00243                 convert_rgb  = conv_420p_rgb96;
00244                 convert_grey = conv_420p_grey;
00245                 break;
00246         };
00247 }
00248 
00249 
00250 void Video4LinuxSource::set_channel(int channel)
00257 {
00258         set_videoSource(channel);
00259 }
00260 
00261 
00262 void Video4LinuxSource::get_size(unsigned int& w, unsigned int& h)
00263 {
00264     if(capture){
00265         w = width ;
00266         h = height ;
00267     }
00268     else{
00269         video_window  win;
00270         get_captureWindows(win);
00271         
00272         w = win.width;
00273         h = win.height;
00274     }
00275 }
00276 
00277 
00278 void Video4LinuxSource::get_framerate(unsigned int& fps)
00279 {
00280         video_window  win;
00281         get_captureWindows(win);
00282         fps = (win.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
00283 }
00284 
00285 
00286 void Video4LinuxSource::get_palette(int& pal)
00287 {
00288         video_picture pic;
00289         get_imageProperties(pic);
00290         pal =  pic.palette;
00291 }
00292 
00293 
00294 ImageSource& Video4LinuxSource::operator >> (ImageRGB& img)
00295 {
00296         unsigned char* src = buff;
00297 
00298         if (capture) {
00299 
00300                 ioctl(fd,VIDIOCMCAPTURE,&vmmap)  ;
00301                 src += mbuf.offsets[currentBuffer];
00302 
00303                 if(!currentBuffer) currentBuffer++ ;
00304                 else              currentBuffer=0 ; 
00305 
00306                 vmmap.frame = currentBuffer ;
00307         } 
00308         else{
00309                 read(fd, src, buffsize);
00310         }
00311 
00312         convert_rgb(width, height, src, (int *)img.data);
00313 
00314         if(capture){
00315         // Free buffer to be used next
00316                 ioctl(fd,VIDIOCSYNC,&currentBuffer) ;
00317         }
00318 
00319         return *this;
00320 }
00321 
00322 
00323 ImageSource& Video4LinuxSource::operator >> (ImageGrey& img)
00324 {
00325         unsigned char* src = buff;
00326 
00327         if (capture) {
00328                 ioctl(fd,VIDIOCMCAPTURE,&vmmap)  ;
00329                 src += mbuf.offsets[currentBuffer];
00330 
00331                 if(!currentBuffer) currentBuffer++ ;
00332                 else              currentBuffer=0 ;
00333 
00334                 vmmap.frame = currentBuffer ;
00335         } else
00336                 read(fd, src, buffsize);
00337         
00338         convert_grey(width, height, src, img.brightness);
00339 
00340         if(capture){
00341         // Free buffer to be used next
00342                 ioctl(fd,VIDIOCSYNC,&currentBuffer) ;
00343         }
00344 
00345         
00346         return *this;
00347 }
00348 
00349 
00350 ImageSource& Video4LinuxSource::operator >> (Image& img)
00351 {
00352         unsigned char* src = buff;
00353         
00354         if (capture) {
00355                 ioctl(fd,VIDIOCMCAPTURE,&vmmap)  ;
00356                 src += mbuf.offsets[currentBuffer];
00357 
00358                 if(!currentBuffer) currentBuffer++ ;
00359                 else              currentBuffer=0 ;
00360 
00361                 vmmap.frame = currentBuffer ;
00362 
00363         } else
00364                 read(fd, src, buffsize);
00365         
00366         if (type == Image::COLOUR)
00367                 convert_rgb(width, height, src, img.data[0]);
00368         else {
00369                 convert_grey(width, height, src, img.brightness);
00370         }
00371 
00372         if(capture){
00373         // Free buffer to be used next
00374                 ioctl(fd,VIDIOCSYNC,&currentBuffer) ;
00375         }
00376 
00377         
00378         return *this;
00379 }
00380 
00381 /* set ioctl methods */
00382 
00383 int Video4LinuxSource::set_frameBuffer(video_buffer& fbuf)
00385 { return ioctl(fd, VIDIOCSFBUF, &fbuf); }
00386 
00387 int Video4LinuxSource::set_captureWindows(video_window& win)
00389 { return ioctl(fd, VIDIOCSWIN, &win); }
00390 
00391 int Video4LinuxSource::set_videoSource(int chan)
00393 { return ioctl(fd, VIDIOCSCHAN, chan); }
00394 
00395 int Video4LinuxSource::set_imageProperties(video_picture& pic)
00397 { return ioctl(fd, VIDIOCSPICT, &pic); }
00398 
00399 int Video4LinuxSource::set_tuning(video_tuner& tuner)
00401 { return ioctl(fd, VIDIOCSTUNER, &tuner); }
00402 
00403 
00404 /* get ioctl methods */
00405 
00406 int Video4LinuxSource::get_capability(video_capability& cap)
00408 { return ioctl(fd, VIDIOCGCAP, &cap); }
00409 
00410 int Video4LinuxSource::get_frameBuffer(video_buffer& fbuf)
00412 { return ioctl(fd, VIDIOCGFBUF, &fbuf); }
00413 
00414 int Video4LinuxSource::get_captureWindows(video_window& win)
00416 { return ioctl(fd, VIDIOCGWIN, &win); }
00417 
00418 int Video4LinuxSource::get_videoSource(video_channel& chan)
00420 { return ioctl(fd, VIDIOCGCHAN, &chan); }
00421 
00422 int Video4LinuxSource::get_imageProperties(video_picture& pic)
00424 { return ioctl(fd, VIDIOCGPICT, &pic); }
00425 
00426 int Video4LinuxSource::get_tuning(video_tuner& tuner)
00428 { return ioctl(fd, VIDIOCGTUNER, &tuner); }
00429 
00430 int Video4LinuxSource::get_memoryBuffer(video_mbuf& mbuf)
00432 { return ioctl(fd, VIDIOCGMBUF, &mbuf); }
00433 
00434 
00435 /* print methods for ioctl structs */
00436 
00437 void Video4LinuxSource::print_capability(video_capability& cap)
00438 {
00439         cerr << "name: " << cap.name << endl;
00440         
00441         cerr << " [ can capture to memory:\t\t\t| " 
00442              << ((cap.type & VID_TYPE_CAPTURE)?    "X" : " ") << " ]" << endl;
00443         cerr << " [ has a tuner of some form:\t\t\t| " 
00444              << ((cap.type & VID_TYPE_TUNER)?      "X" : " ") << " ]" << endl;
00445         cerr << " [ has teletext capability:\t\t\t| " 
00446              << ((cap.type & VID_TYPE_TELETEXT)?   "X" : " ") << " ]" << endl;
00447         cerr << " [ can overlay images onto frame buffer:\t| " 
00448              << ((cap.type & VID_TYPE_OVERLAY)?    "X" : " ") << " ]" << endl;
00449         cerr << " [ overlay is chromakeyed:\t\t\t| " 
00450              << ((cap.type & VID_TYPE_CHROMAKEY)?  "X" : " ") << " ]" << endl;
00451         cerr << " [ overlay clipping is supported:\t\t| " 
00452              << ((cap.type & VID_TYPE_CLIPPING)?   "X" : " ") << " ]" << endl;
00453         cerr << " [ overlay overwrites frame buffer memory:\t| " 
00454              << ((cap.type & VID_TYPE_FRAMERAM)?   "X" : " ") << " ]" << endl;
00455         cerr << " [ hardware supports image scaling:\t\t| " 
00456              << ((cap.type & VID_TYPE_SCALES)?     "X" : " ") << " ]" << endl;
00457         cerr << " [ image capture is greyscale only:\t\t| " 
00458              << ((cap.type & VID_TYPE_MONOCHROME)? "X" : " ") << " ]" << endl;
00459         cerr << " [ capture can be of only part of the image:\t| " 
00460              << ((cap.type & VID_TYPE_SUBCAPTURE)? "X" : " ") << " ]" << endl;
00461 
00462         cerr << "channels: "  << cap.channels  << endl;
00463         cerr << "audios: "    << cap.channels  << endl;
00464         cerr << "maxwidth: "  << cap.maxwidth  << endl;
00465         cerr << "maxheight: " << cap.maxheight << endl;
00466         cerr << "minwidth: "  << cap.minwidth  << endl;
00467         cerr << "minheight: " << cap.minheight << endl;
00468 }
00469 
00470 
00471 void Video4LinuxSource::print_captureWindows(video_window& win)
00472 {
00473         cerr << "x co-ord: "  << win.x         << endl;
00474         cerr << "y co-ord: "  << win.y         << endl;
00475         cerr << "width: "     << win.width     << endl;
00476         cerr << "height: "    << win.height    << endl;
00477         cerr << "chromakey: " << win.chromakey << endl;
00478         __u32 mask = 0x1 << sizeof(mask)*8 - 1;
00479         cerr << "flags: ";
00480                 for (unsigned int b = 0; b < sizeof(mask)*8; b++, mask >>= 1)
00481                         cerr << (win.flags & mask ? "1" : "0");
00482         cerr << endl;
00483 }
00484 
00485 
00486 void Video4LinuxSource::print_videoSource(video_channel& chan)
00487 {
00488         cerr << "number: " << chan.channel << endl;
00489         cerr << "name: "   << chan.name    << endl;
00490         cerr << "tuners: " << chan.tuners  << endl;
00491         cerr << "flags: "  << endl;
00492         cerr << " [ channel has tuners:\t\t\t| " 
00493              << ((chan.flags & VIDEO_VC_TUNER)? "X" : " ") << " ]" << endl;
00494         cerr << " [ channel has audio:\t\t\t| " 
00495              << ((chan.flags & VIDEO_VC_AUDIO)? "X" : " ") << " ]" << endl;
00496 // XXX not in header
00497 //      cerr << " [ channel has norm setting:\t\t| " 
00498 //           << ((chan.flags & VIDEO_VC_NORM)? "X" : " ") << " ]" << endl;
00499         cerr << "type: "   << endl;
00500         cerr << " [ input is a tv input:\t\t\t| " 
00501              << ((chan.flags & VIDEO_TYPE_TV)? "X" : " ") << " ]" << endl;
00502         cerr << " [ input is a camera:\t\t\t| " 
00503              << ((chan.flags & VIDEO_TYPE_CAMERA)? "X" : " ") << " ]" << endl;
00504         cerr << "norm: "   << chan.norm << endl;
00505 }
00506 
00507 
00508 void Video4LinuxSource::print_memoryBuffer(video_mbuf& mbuf)
00509 {
00510         cerr << "size: "   << mbuf.size       << endl;
00511         cerr << "frames: " << mbuf.frames     << endl;
00512         cerr << "offset: " << mbuf.offsets[1] << endl;
00513 }
00514 

Generated at Fri Aug 13 17:29:21 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001