contrib/oul/oufgl/frame_grabber_v4l.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 //
00004 // Copyright (c) 2002 Brendan McCane
00005 // University of Otago, Dunedin, New Zealand
00006 // Reproduction rights limited as described in the COPYRIGHT file.
00007 //----------------------------------------------------------------------
00008 
00009 //----------------------------------------------------------------------
00010 //: constructor
00011 //
00012 // @param int width: the width of the image (default 384)
00013 // @param int height: the height of the image (default 288)
00014 // @param char *devname: the name of the device (default /dev/video0
00015 //
00016 // @status Under Development
00017 // @author Brendan McCane
00018 // @library oul/oufgl
00019 //----------------------------------------------------------------------
00020 
00021 #include "frame_grabber_v4l.h"
00022 #include <vcl_cstring.h> // for memcpy()
00023 #include <vcl_cstdlib.h> // for exit()
00024 #include <vcl_cstdio.h>
00025 
00026 FrameGrabberV4lGrey::FrameGrabberV4lGrey(int width_, int height_, 
00027                                          bool debug_, char *devname)
00028   : current(0), width(width_), height(height_), debug(debug_)
00029 {
00030   if (debug)
00031     vcl_cout << "V4lGrey constructor, current = " << current << vcl_endl;
00032   // now setup the input stream
00033   fd = open(devname, O_RDWR);
00034   if (fd<0)
00035   {
00036     vcl_cerr << "Error: couldn't open device " << devname << vcl_endl;
00037     vcl_perror("Couldn't open device");
00038     vcl_exit(-1);
00039   }
00040   // check the video capability stuff
00041   struct video_capability vcap;
00042   ioctl(fd, VIDIOCGCAP, &vcap);
00043   if (debug)
00044   {
00045     vcl_cout << "camera name = " << vcap.name << vcl_endl
00046              << "max image size = " << vcap.maxwidth << ' '
00047              << vcap.maxheight << vcl_endl;
00048   }
00049 
00050   // now set the default parameters for the camera set the format to
00051   // YUV420P - easy to extract greyscale that way. What we really
00052   // need here is to poll through all possible palettes and choose
00053   // the most appropriate for grey scale, then convert as needed -
00054   // but what a pain. Actually it appears that the phillips web cam
00055   // driver only supports YUV420P, so to do colour capturing we need
00056   // to convert to RGB.
00057   struct video_picture vp;
00058   ioctl(fd, VIDIOCGPICT, &vp);
00059   if (debug)
00060     vcl_cout << "vp.pallette = " << vp.palette << vcl_endl;
00061   vp.palette = VIDEO_PALETTE_YUV420P;
00062   if (ioctl(fd, VIDIOCSPICT, &vp)>=0)
00063     vcl_cout << "Successfully set palette to YUV420P\n";
00064   else
00065   {
00066     vcl_cerr << "Error setting pallette\n"
00067              << "Capture may not work\n";
00068   }
00069 
00070   struct video_window vw;
00071   ioctl(fd, VIDIOCGWIN, &vw);
00072   vw.x = vw.y = 0;
00073   vw.width = width;
00074   vw.height = height;
00075   if (debug)
00076     vcl_cout << "trying to set to window = " << vw.x << ' ' << vw.y
00077              << ' ' << vw.width << ' ' << vw.height << vcl_endl;
00078 #if 0
00079   // set the fps to 30 fps
00080   vw.flags &= ~PWC_FPS_FRMASK;
00081   vw.flags |= (30 << PWC_FPS_SHIFT);
00082 #endif // 0
00083   // try setting the image size
00084   ioctl(fd, VIDIOCSWIN, &vw);
00085   // now read the actual size back
00086   ioctl(fd, VIDIOCGWIN, &vw);
00087   if (debug)
00088     vcl_cout << "actually setting window to = " << vw.x << ' ' << vw.y
00089              << ' ' << vw.width << ' ' << vw.height << vcl_endl;
00090   // set the size to the actual size
00091   width = vw.width;
00092   height = vw.height;
00093 
00094   // allocate the buffers for the image
00095   contents[0] = new ImageContents[width*height*3];
00096   contents[1] = new ImageContents[width*height*3];
00097   im[0] = new ImageGrey(contents[0], width, height);
00098   im[1] = new ImageGrey(contents[1], width, height);
00099 
00100   // aio = new AsyncIO(fd);
00101   if (debug)
00102     vcl_cout << "V4lGrey constructor end, current = " << current << vcl_endl;
00103 }
00104 
00105 //----------------------------------------------------------------------
00106 //: destructor
00107 //
00108 // .status Under Development
00109 // .author Brendan McCane
00110 // .library oul/oufgl
00111 //----------------------------------------------------------------------
00112 
00113 FrameGrabberV4lGrey::~FrameGrabberV4lGrey()
00114 {
00115   delete im[0];
00116   delete im[1];
00117   delete contents[0];
00118   delete contents[1];
00119 //delete aio;
00120   close(fd);
00121 }
00122 
00123 //----------------------------------------------------------------------
00124 //: acquire_frame_synch
00125 //
00126 // acquire a new frame synchronously (ie don't return until completed)
00127 // You probably shouldn't mix asynch and synchronous calls as this
00128 // tends to screw up the notion of the current frame.
00129 //
00130 // .status Under Development
00131 // .author Brendan McCane
00132 // .library oul/oufgl
00133 //----------------------------------------------------------------------
00134 void FrameGrabberV4lGrey::acquire_frame_synch()
00135 {
00136   if (debug)
00137     vcl_cout << "acquire_frame_synch, current = " << current << vcl_endl;
00138   read(fd, (void*)contents[current], width*height*3);
00139   if (debug)
00140     vcl_cout << "acquire_frame_synch end, current = " << current << vcl_endl;
00141 #if 0
00142   current = (current+1)%2;
00143   aio->read(contents[current], width*height*sizeof(ImageContents));
00144   aio->wait_for_completion();
00145 
00146   // Alessandro reckons the following is needed for compatibility with
00147   // >0.28 versions of the driver, but it seems to work fine without it. 
00148 
00149   struct Px_BufControl bufcontrol; 
00150   ioctl(aio->getFd(), PX_IOCINFOBUF, &bufcontrol); 
00151   ioctl(aio->getFd(), PX_IOCDONEBUF, &bufcontrol);
00152 
00153   flip_current();
00154 #endif // 0
00155 }
00156 
00157 //----------------------------------------------------------------------
00158 //: acquire_frame_asynch
00159 //
00160 // acquire a new frame asynchronously (ie start acquiring and
00161 // return immediately )
00162 //
00163 // actually the asynch bit is currently not working. So at the moment
00164 // it is actually acquiring synchronously.
00165 //
00166 // .status Under Development
00167 // .author Brendan McCane
00168 // .library oul/oufgl
00169 //----------------------------------------------------------------------
00170 
00171 void FrameGrabberV4lGrey::acquire_frame_asynch()
00172 {
00173   if (debug)
00174     vcl_cout << "acquire_frame_asynch: currently equivalent to synch\n";
00175   read(fd, (void*)contents[current], width*height*3);
00176   if (debug)
00177     vcl_cout << "acquire_frame_asynch end\n";
00178 #if 0
00179   // first need to wait for any previous acquire to finish
00180   aio->wait_for_completion();
00181   // now start reading the next one
00182   aio->read(contents[current], width*height*sizeof(ImageContents));
00183 
00184   struct Px_BufControl bufcontrol;
00185   ioctl(aio->getFd(), PX_IOCINFOBUF, &bufcontrol);
00186   ioctl(aio->getFd(), PX_IOCDONEBUF, &bufcontrol);
00187 
00188   // move the current frame to the frame previously completed
00189   current = (current+1)%2;
00190   // now need to flip the image so that it is the right way up
00191   flip_current();
00192 #endif // 0
00193 }
00194 
00195 
00196 //----------------------------------------------------------------------
00197 //: get_current_and_acquire
00198 //
00199 // start acquiring the next frame asynchronously and return the
00200 // current frame
00201 //
00202 // .status Under Development
00203 // .author Brendan McCane
00204 // .library oul/oufgl
00205 //----------------------------------------------------------------------
00206 
00207 vil1_memory_image *FrameGrabberV4lGrey::get_current_and_acquire()
00208 {
00209   if (debug)
00210     vcl_cout << "get_current_and_acquire\n";
00211   acquire_frame_asynch();
00212   return get_current_frame();
00213   if (debug)
00214     vcl_cout << "get_current_and_acquire end\n";
00215 }
00216 
00217 //----------------------------------------------------------------------
00218 //: flip the current frame around a horizontal axis
00219 //
00220 // .status Under Development
00221 // .author Brendan McCane
00222 // .library oul/oufgl
00223 //----------------------------------------------------------------------
00224 
00225 void FrameGrabberV4lGrey::flip_current()
00226 {
00227   int limit = im[current]->height()/2;
00228   int length = im[current]->width()*sizeof(ImageContents);
00229   int width = im[current]->width();
00230   int height = im[current]->height();
00231   ImageContents *temp_mem = new ImageContents[im[current]->width()]; 
00232   for (int i=0; i<limit; i++)
00233   {
00234     vcl_memcpy(temp_mem, contents[current]+i*width, length);
00235     vcl_memcpy(contents[current]+i*width, contents[current]+(height-i-1)*width, length);
00236     vcl_memcpy(contents[current]+(height-i-1)*width, temp_mem, length);
00237   }
00238   delete[] temp_mem;
00239 }