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   if (!read(fd, (void*)contents[current], width*height*3))
00139     return;
00140   if (debug)
00141     vcl_cout << "acquire_frame_synch end, current = " << current << vcl_endl;
00142 #if 0
00143   current = (current+1)%2;
00144   aio->read(contents[current], width*height*sizeof(ImageContents));
00145   aio->wait_for_completion();
00146 
00147   // Alessandro reckons the following is needed for compatibility with
00148   // >0.28 versions of the driver, but it seems to work fine without it. 
00149 
00150   struct Px_BufControl bufcontrol; 
00151   ioctl(aio->getFd(), PX_IOCINFOBUF, &bufcontrol); 
00152   ioctl(aio->getFd(), PX_IOCDONEBUF, &bufcontrol);
00153 
00154   flip_current();
00155 #endif // 0
00156 }
00157 
00158 //----------------------------------------------------------------------
00159 //: acquire_frame_asynch
00160 //
00161 // acquire a new frame asynchronously (ie start acquiring and
00162 // return immediately )
00163 //
00164 // actually the asynch bit is currently not working. So at the moment
00165 // it is actually acquiring synchronously.
00166 //
00167 // .status Under Development
00168 // .author Brendan McCane
00169 // .library oul/oufgl
00170 //----------------------------------------------------------------------
00171 
00172 void FrameGrabberV4lGrey::acquire_frame_asynch()
00173 {
00174   if (debug)
00175     vcl_cout << "acquire_frame_asynch: currently equivalent to synch\n";
00176   if (!read(fd, (void*)contents[current], width*height*3))
00177     return;
00178   if (debug)
00179     vcl_cout << "acquire_frame_asynch end\n";
00180 #if 0
00181   // first need to wait for any previous acquire to finish
00182   aio->wait_for_completion();
00183   // now start reading the next one
00184   aio->read(contents[current], width*height*sizeof(ImageContents));
00185 
00186   struct Px_BufControl bufcontrol;
00187   ioctl(aio->getFd(), PX_IOCINFOBUF, &bufcontrol);
00188   ioctl(aio->getFd(), PX_IOCDONEBUF, &bufcontrol);
00189 
00190   // move the current frame to the frame previously completed
00191   current = (current+1)%2;
00192   // now need to flip the image so that it is the right way up
00193   flip_current();
00194 #endif // 0
00195 }
00196 
00197 
00198 //----------------------------------------------------------------------
00199 //: get_current_and_acquire
00200 //
00201 // start acquiring the next frame asynchronously and return the
00202 // current frame
00203 //
00204 // .status Under Development
00205 // .author Brendan McCane
00206 // .library oul/oufgl
00207 //----------------------------------------------------------------------
00208 
00209 vil1_memory_image *FrameGrabberV4lGrey::get_current_and_acquire()
00210 {
00211   if (debug)
00212     vcl_cout << "get_current_and_acquire\n";
00213   acquire_frame_asynch();
00214   return get_current_frame();
00215   if (debug)
00216     vcl_cout << "get_current_and_acquire end\n";
00217 }
00218 
00219 //----------------------------------------------------------------------
00220 //: flip the current frame around a horizontal axis
00221 //
00222 // .status Under Development
00223 // .author Brendan McCane
00224 // .library oul/oufgl
00225 //----------------------------------------------------------------------
00226 
00227 void FrameGrabberV4lGrey::flip_current()
00228 {
00229   int limit = im[current]->height()/2;
00230   int length = im[current]->width()*sizeof(ImageContents);
00231   int width = im[current]->width();
00232   int height = im[current]->height();
00233   ImageContents *temp_mem = new ImageContents[im[current]->width()]; 
00234   for (int i=0; i<limit; i++)
00235   {
00236     vcl_memcpy(temp_mem, contents[current]+i*width, length);
00237     vcl_memcpy(contents[current]+i*width, contents[current]+(height-i-1)*width, length);
00238     vcl_memcpy(contents[current]+(height-i-1)*width, temp_mem, length);
00239   }
00240   delete[] temp_mem;
00241 }