V4Lgrabber.C

Go to the documentation of this file.
00001 /*!@file Devices/V4Lgrabber.C Interface with a video4linux frame grabber */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/V4Lgrabber.C $
00035 // $Id: V4Lgrabber.C 10794 2009-02-08 06:21:09Z itti $
00036 //
00037 
00038 #ifdef HAVE_LINUX_VIDEODEV_H
00039 
00040 #include "Devices/V4Lgrabber.H"
00041 
00042 #include "Component/OptionManager.H" // for option alias requests
00043 #include "Devices/DeviceOpts.H"
00044 #include "Image/ColorOps.H"
00045 #include "Raster/GenericFrame.H"
00046 #include "Util/Assert.H"
00047 #include "Util/log.H"
00048 #include "Video/VideoFrame.H"
00049 
00050 #include <cerrno>
00051 #include <fcntl.h>
00052 #include <sys/ioctl.h>
00053 #include <sys/mman.h>
00054 #include <sys/stat.h>
00055 #include <unistd.h>
00056 
00057 //! for id-logging; see log.H:
00058 #define MYLOGID itsFd
00059 
00060 namespace
00061 {
00062   //! A V4L palette entry
00063   struct V4LPalette
00064   {
00065     int pal;             //!< palette
00066     int depth;           //!< depth
00067     const char* name;    //!< name of palette e.g. "rgb24"
00068     VideoFormat vidformat; //!< Frame grabber mode
00069   };
00070 
00071   //! array of all known palettes
00072   //! high preference modes have lower indices
00073   struct V4LPalette palettes[12] =
00074     {
00075       { VIDEO_PALETTE_RGB24,         24, "bgr24", VIDFMT_RGB24 },
00076       { VIDEO_PALETTE_RGB24 | 0x80,  24, "rgb24", VIDFMT_RGB24 },
00077       { VIDEO_PALETTE_RGB32,         32, "bgr32", VIDFMT_RGB32 },
00078       { VIDEO_PALETTE_RGB32 | 0x80,  32, "rgb32", VIDFMT_RGB32 },
00079       { VIDEO_PALETTE_YUYV,          24, "yuyv 16bpp", VIDFMT_YUYV  },
00080       { VIDEO_PALETTE_YUV422,        24, "yuv422 16bpp", VIDFMT_YUV422 },
00081       { VIDEO_PALETTE_RGB565,        16, "rgb565", VIDFMT_RGB565 },
00082       { VIDEO_PALETTE_RGB555,        15, "rgb555", VIDFMT_RGB555 },
00083       { VIDEO_PALETTE_YUV420,        24, "yuv420 12bpp", VIDFMT_YUV420 },
00084       { VIDEO_PALETTE_YUV420P,       24, "yuv420 planar 12bpp", VIDFMT_YUV420P },
00085       { VIDEO_PALETTE_GREY,          8, "grayscale 8bpp", VIDFMT_GREY },
00086       { -1,                          -1, 0, VideoFormat(-1) }
00087     };
00088 
00089   int ioctl_nointr(int d, int req, void* mem)
00090   {
00091     int result = 0;
00092     do { result = ioctl(d, req, mem); }
00093     while ((result < 0) && (errno == EINTR));
00094     return result;
00095   }
00096 }
00097 
00098 // ######################################################################
00099 V4Lgrabber::V4Lgrabber(OptionManager& mgr, const std::string& descrName,
00100                        const std::string& tagName,
00101                        const ParamFlag flags) :
00102   FrameIstream(mgr, descrName, tagName),
00103   // NOTE that contrary to the common case, we may give (by default
00104   // value of 'flags') USE_MY_VAL here when we construct the
00105   // OModelParam objects; that means that we push our values into the
00106   // ModelManager as the new default values, rather than having our
00107   // param take its value from the ModelManager's default
00108   itsDevName(&OPT_FrameGrabberDevice, this, "/dev/video0", flags), // V4l device
00109   itsChannel(&OPT_FrameGrabberChannel, this, 1, flags),  // composite input
00110   itsDims(&OPT_FrameGrabberDims, this, Dims(320, 240), flags),
00111   itsGrabMode(&OPT_FrameGrabberMode, this, VIDFMT_RGB24, flags), // 24-bit rgb grabbing
00112   itsByteSwap(&OPT_FrameGrabberByteSwap, this, true, flags), // use byte-swapping
00113   itsBrightness(&OPT_FrameGrabberBrightness, this, 32768, flags | ALLOW_ONLINE_CHANGES),
00114   itsHue(&OPT_FrameGrabberHue, this, 32768, flags | ALLOW_ONLINE_CHANGES),
00115   itsColour(&OPT_FrameGrabberColour, this, 32768, flags | ALLOW_ONLINE_CHANGES),
00116   itsContrast(&OPT_FrameGrabberContrast, this, 32768, flags | ALLOW_ONLINE_CHANGES),
00117   itsWhiteness(&OPT_FrameGrabberWhiteness, this, 32768, flags | ALLOW_ONLINE_CHANGES),
00118   itsStreamingMode(&OPT_FrameGrabberStreaming, this),
00119   itsFd(-1),
00120   itsMmapBuf(NULL),
00121   itsReadBuf(),
00122   itsTotalBufSize(0),
00123   itsNumBufFrames(0),
00124   itsCurrentFrame(0),
00125   itsGrabbing(NULL),
00126   itsFrameTime(SimTime::ZERO()),
00127   itsListener(),
00128   itsStreamStarted(false)
00129 {
00130   // request a bunch of camera aliases which work with V4L:
00131   mgr.requestOptionAlias(&OPT_ALIAScamBttv);
00132 }
00133 
00134 // ######################################################################
00135 void V4Lgrabber::start1()
00136 {
00137   itsFd = open(itsDevName.getVal().c_str(), O_RDWR | O_NONBLOCK);
00138   if (itsFd == -1) PLFATAL("Cannot open V4L device %s",
00139                            itsDevName.getVal().c_str());
00140 
00141   // get frame grabber capabilities:
00142   struct video_capability vc;
00143   if (ioctl_nointr(itsFd, VIDIOCGCAP, &vc) < 0)
00144     IDPLFATAL("Cannot get V4L device capabilities");
00145   IDLINFO("FrameGrabber board name is: %s", vc.name);
00146   IDLINFO("maxwidth = %d, maxheight = %d", vc.maxwidth, vc.maxheight);
00147   if (itsDims.getVal().w() > vc.maxwidth ||
00148       itsDims.getVal().h() > vc.maxheight)
00149     IDLFATAL("Requested grab size %dx%d too large",
00150              itsDims.getVal().w(), itsDims.getVal().h());
00151 
00152   // select input channel & norm:
00153   struct video_channel vch;
00154   vch.channel = itsChannel.getVal();
00155   if (ioctl_nointr(itsFd, VIDIOCGCHAN, &vch) < 0)
00156     IDPLERROR("Cannot get V4L device channel information");
00157   vch.norm = VIDEO_MODE_NTSC;   // set NTSC norm
00158   vch.type = VIDEO_TYPE_CAMERA; // camera input
00159   IDLINFO("Channel %d is '%s' [norm %d]",
00160            vch.channel, vch.name, vch.norm);
00161   if (ioctl_nointr(itsFd, VIDIOCSCHAN, &vch) < 0)
00162     IDPLERROR("Cannot set V4L device channel information");
00163 
00164   switch (vch.norm)
00165     {
00166     case VIDEO_MODE_PAL:
00167       itsFrameTime = SimTime::HERTZ(25.0);
00168       break;
00169 
00170     case VIDEO_MODE_NTSC:
00171       itsFrameTime = SimTime::HERTZ(29.97);
00172       break;
00173 
00174     case VIDEO_MODE_SECAM:
00175       itsFrameTime = SimTime::HERTZ(25.0);
00176       break;
00177 
00178     default:
00179       itsFrameTime = SimTime::ZERO();
00180       break;
00181     }
00182 
00183   // get specs of video buffer:
00184   struct video_mbuf vmb;
00185   if (ioctl_nointr(itsFd, VIDIOCGMBUF, &vmb) < 0)
00186     IDPLFATAL("Cannot get V4L device buffer");
00187 
00188   IDLINFO("video Mbuf: 0x%x bytes, %d frames", vmb.size, vmb.frames);
00189   for (int i = 0; i < vmb.frames; ++i)
00190     IDLINFO("buffer offset[%d] = %d", i, vmb.offsets[i]);
00191 
00192   // get the picture properties
00193   struct video_picture vp;
00194   if (ioctl_nointr(itsFd, VIDIOCGPICT, &vp) != 0)
00195     IDPLFATAL("ioctl(VIDIOCSPICT) get picture properties failed");
00196 
00197   // get ready for capture, for all frames in buffer:
00198   switch (itsGrabMode.getVal()) {
00199   case VIDFMT_GREY: itsVmmInfo.format = VIDEO_PALETTE_GREY; break;
00200   case VIDFMT_RAW: itsVmmInfo.format = VIDEO_PALETTE_RAW; break;
00201   case VIDFMT_RGB555: itsVmmInfo.format = VIDEO_PALETTE_RGB555; break;
00202   case VIDFMT_RGB565: itsVmmInfo.format = VIDEO_PALETTE_RGB565; break;
00203   case VIDFMT_RGB24: itsVmmInfo.format = VIDEO_PALETTE_RGB24; break;
00204   case VIDFMT_RGB32: itsVmmInfo.format = VIDEO_PALETTE_RGB32; break;
00205   case VIDFMT_YUYV: itsVmmInfo.format = VIDEO_PALETTE_YUYV; break;
00206   case VIDFMT_UYVY: itsVmmInfo.format = VIDEO_PALETTE_UYVY; break;
00207   case VIDFMT_YUV422: itsVmmInfo.format = VIDEO_PALETTE_YUV422; break;
00208   case VIDFMT_YUV411: itsVmmInfo.format = VIDEO_PALETTE_YUV411; break;
00209   case VIDFMT_YUV420: itsVmmInfo.format = VIDEO_PALETTE_YUV420; break;
00210   case VIDFMT_YUV422P: itsVmmInfo.format = VIDEO_PALETTE_YUV422P; break;
00211   case VIDFMT_YUV411P: itsVmmInfo.format = VIDEO_PALETTE_YUV411P; break;
00212   case VIDFMT_YUV420P: itsVmmInfo.format = VIDEO_PALETTE_YUV420P; break;
00213   case VIDFMT_YUV410P: itsVmmInfo.format = VIDEO_PALETTE_YUV410P; break;
00214   case VIDFMT_AUTO:
00215     // Auto selection of grab mode:
00216     struct V4LPalette* pal;
00217     LINFO("Probing for supported palettes:");
00218 
00219 #define CHECK_PALETTE(p)                        \
00220         {                                       \
00221           vp.palette = p;                       \
00222           vp.depth = 32;                        \
00223           ioctl_nointr(itsFd, VIDIOCSPICT, &vp);\
00224           ioctl_nointr(itsFd, VIDIOCGPICT, &vp);\
00225           if (vp.palette == p)                  \
00226             LINFO("  %-22s supported", #p);     \
00227           else                                  \
00228             LINFO("  %-22s NOT supported", #p); \
00229         }
00230 
00231     CHECK_PALETTE(VIDEO_PALETTE_GREY);
00232     CHECK_PALETTE(VIDEO_PALETTE_HI240);
00233     CHECK_PALETTE(VIDEO_PALETTE_RGB565);
00234     CHECK_PALETTE(VIDEO_PALETTE_RGB24);
00235     CHECK_PALETTE(VIDEO_PALETTE_RGB32);
00236     CHECK_PALETTE(VIDEO_PALETTE_RGB555);
00237     CHECK_PALETTE(VIDEO_PALETTE_YUV422);
00238     CHECK_PALETTE(VIDEO_PALETTE_YUYV);
00239     CHECK_PALETTE(VIDEO_PALETTE_UYVY);
00240     CHECK_PALETTE(VIDEO_PALETTE_YUV420);
00241     CHECK_PALETTE(VIDEO_PALETTE_YUV411);
00242     CHECK_PALETTE(VIDEO_PALETTE_RAW);
00243     CHECK_PALETTE(VIDEO_PALETTE_YUV422P);
00244     CHECK_PALETTE(VIDEO_PALETTE_YUV411P);
00245     CHECK_PALETTE(VIDEO_PALETTE_YUV420P);
00246     CHECK_PALETTE(VIDEO_PALETTE_YUV410P);
00247 
00248 #undef CHECK_PALETTE
00249 
00250     // Brutal, loop through all available modes
00251     for (pal = &palettes[0]; pal->pal >= 0; ++pal)
00252       {
00253         vp.palette = pal->pal;
00254         vp.depth = pal->depth;
00255         ioctl_nointr(itsFd, VIDIOCSPICT, &vp);
00256         ioctl_nointr(itsFd, VIDIOCGPICT, &vp);
00257         if (vp.palette == pal->pal)
00258           {
00259             LINFO("  Using palette \"%s\" with depth %u",
00260                   pal->name, vp.depth);
00261             // hack
00262             itsGrabMode.setVal(pal->vidformat);
00263             itsVmmInfo.format = vp.palette;
00264             break;
00265           }
00266         else
00267           LINFO("  Palette \"%s\" not supported", pal->name);
00268       }
00269 
00270     if (pal->pal < 0)
00271       IDLFATAL("Auto palette selection failed - try setting manually.");
00272     break;
00273   default:
00274     LFATAL("Unsupported grab mode");
00275   }
00276 
00277   // get ready to grab frames, starting with buffer/frame 0:
00278   itsNumBufFrames = vmb.frames;
00279   itsTotalBufSize = vmb.size;
00280   itsCurrentFrame = 0;
00281   itsGrabbing = new bool[itsNumBufFrames];
00282   for (int i = 0; i < itsNumBufFrames; ++i) itsGrabbing[i] = false;
00283   itsVmmInfo.width = itsDims.getVal().w();
00284   itsVmmInfo.height = itsDims.getVal().h();
00285   itsVmmInfo.frame = 0;
00286 
00287   // decide on mmap'ed or read() access:
00288   if (ioctl_nointr(itsFd, VIDIOCGMBUF, &vmb) != -1)
00289     {
00290       IDLINFO("Using mmap'ed image capture");
00291       // setup mmap'ed access to the video buffer:
00292       itsMmapBuf =
00293         static_cast<byte*>(mmap((void*)0, vmb.size,
00294                                 PROT_READ|PROT_WRITE,
00295                                 MAP_SHARED, itsFd, 0));
00296 
00297       if (itsMmapBuf == MAP_FAILED)
00298         IDPLFATAL("mmap failed");
00299 
00300       itsReadBuf = Image<byte>();
00301     }
00302   else
00303     {
00304       IDLINFO("Using read() image capture");
00305       itsMmapBuf = NULL;
00306 
00307       itsReadBuf = Image<byte>(getFrameSize(itsGrabMode.getVal(),
00308                                             itsDims.getVal()),
00309                                1, NO_INIT);
00310     }
00311 
00312   // set picture properties
00313   vp.brightness = itsBrightness.getVal();
00314   vp.hue = itsHue.getVal();
00315   vp.colour = itsColour.getVal();
00316   vp.contrast = itsContrast.getVal();
00317   vp.whiteness = itsWhiteness.getVal();
00318   vp.palette = itsVmmInfo.format;
00319   LINFO("bright=%u hue=%u color=%u contrast=%u white=%u depth=%u palette=%u",
00320         vp.brightness, vp.hue, vp.colour, vp.contrast,
00321         vp.whiteness, vp.depth, vp.palette);
00322   if (ioctl_nointr(itsFd, VIDIOCSPICT, &vp) != 0)
00323     IDPLERROR("ioctl(VIDIOCSPICT) set picture properties failed");
00324 }
00325 
00326 // ######################################################################
00327 void V4Lgrabber::stop2()
00328 {
00329   if (itsMmapBuf) { munmap(itsMmapBuf, itsTotalBufSize); itsMmapBuf = NULL; }
00330   if (itsFd >= 0) { close(itsFd); itsFd = -1; }
00331   if (itsGrabbing) { delete [] itsGrabbing; itsGrabbing = NULL; }
00332   itsReadBuf = Image<byte>();
00333   itsStreamStarted = false;
00334 }
00335 
00336 // ######################################################################
00337 V4Lgrabber::~V4Lgrabber()
00338 {  }
00339 
00340 // ######################################################################
00341 void V4Lgrabber::setListener(rutz::shared_ptr<FrameListener> listener)
00342 {
00343   itsListener = listener;
00344 }
00345 
00346 // ######################################################################
00347 void V4Lgrabber::startStream()
00348 {
00349   // reset itsStreamStarted so that we wait for any pending frames to
00350   // be grabbed, then start fresh grabbing requests:
00351   itsStreamStarted = false;
00352 
00353   this->restartStream();
00354 }
00355 
00356 // ######################################################################
00357 SimTime V4Lgrabber::getNaturalFrameTime() const
00358 {
00359   return itsFrameTime;
00360 }
00361 
00362 // ######################################################################
00363 GenericFrameSpec V4Lgrabber::peekFrameSpec()
00364 {
00365   GenericFrameSpec result;
00366 
00367   result.nativeType = GenericFrame::VIDEO;
00368   result.videoFormat = itsGrabMode.getVal();
00369   result.videoByteSwap = itsByteSwap.getVal();
00370   result.dims = itsDims.getVal();
00371   result.floatFlags = 0;
00372 
00373   return result;
00374 }
00375 
00376 // ######################################################################
00377 GenericFrame V4Lgrabber::readFrame()
00378 {
00379   const GenericFrame frame =
00380     itsStreamingMode.getVal()
00381     ? GenericFrame(this->grabRaw())
00382     : GenericFrame(this->grabSingleRaw());
00383 
00384   if (itsListener.get() != 0)
00385     itsListener->onRawFrame(frame);
00386 
00387   return frame;
00388 }
00389 
00390 // ######################################################################
00391 VideoFrame V4Lgrabber::grabRaw()
00392 {
00393   byte* result = 0;
00394   if (itsMmapBuf) // mmap interface
00395     {
00396       this->restartStream();
00397 
00398       result = itsMmapBuf + itsCurrentFrame * (itsTotalBufSize / itsNumBufFrames);
00399 
00400       // are we already grabbing buffer 'itsCurrentFrame'? otherwise,
00401       // start the grab now:
00402       if (itsGrabbing[itsCurrentFrame] == false)
00403         {
00404           itsVmmInfo.frame = itsCurrentFrame;
00405           itsGrabbing[itsCurrentFrame] = true;
00406           if (ioctl_nointr(itsFd, VIDIOCMCAPTURE, &itsVmmInfo) < 0)
00407             IDPLFATAL("VIDIOCMCAPTURE (frame %d)", itsCurrentFrame);
00408         }
00409 
00410       // wait until buffer 'itsCurrentFrame' has been fully captured:
00411       if (ioctl_nointr(itsFd, VIDIOCSYNC, &itsCurrentFrame) < 0)
00412         IDPLFATAL("VIDIOCSYNC (frame %d)", itsCurrentFrame);
00413       itsGrabbing[itsCurrentFrame] = false;
00414 
00415       // get ready for capture of that frame again (for later):
00416       itsVmmInfo.frame = itsCurrentFrame;
00417       itsGrabbing[itsCurrentFrame] = true;
00418       if (ioctl_nointr(itsFd, VIDIOCMCAPTURE, &itsVmmInfo) < 0)
00419         IDPLFATAL("VIDIOCMCAPTURE (frame %d)", itsCurrentFrame);
00420     }
00421   else // read() interface
00422     {
00423       ASSERT(itsReadBuf.initialized());
00424       const ssize_t nbytes =
00425         read(itsFd, itsReadBuf.getArrayPtr(), itsReadBuf.getSize());
00426       if (nbytes < 0)
00427         IDPLFATAL("read() failed");
00428       PLDEBUG("got %zd bytes", nbytes);
00429       result = itsReadBuf.getArrayPtr();
00430     }
00431 
00432   // switch to another frame:
00433   ++itsCurrentFrame;
00434   if (itsCurrentFrame >= itsNumBufFrames) itsCurrentFrame = 0;
00435 
00436   // return pointer to last-grabbed frame. You have a bit of time to
00437   // get a hold of the data but beware that an order to capture that
00438   // buffer has already been issued, so as soon as the grabber gets to
00439   // it, it will overwrite this buffer with a new frame:
00440   ASSERT(result != 0);
00441   VideoFrame frame(result, (itsTotalBufSize / itsNumBufFrames),
00442                    itsDims.getVal(),
00443                    itsGrabMode.getVal(), itsByteSwap.getVal(),
00444                    /* strictLength = */ false);
00445 
00446   return frame;
00447 }
00448 
00449 // ######################################################################
00450 void V4Lgrabber::paramChanged(ModelParamBase* const param,
00451                                    const bool valueChanged,
00452                                    ParamClient::ChangeStatus* status)
00453 {
00454 
00455   FrameIstream::paramChanged(param, valueChanged, status);
00456 
00457   // set picture properties
00458   if (valueChanged)
00459   {
00460     //FIXME
00461     /*struct video_picture vp;
00462     vp.brightness = itsBrightness.getVal();
00463     vp.hue = itsHue.getVal();
00464     vp.colour = itsColour.getVal();
00465     vp.contrast = itsContrast.getVal();
00466     vp.whiteness = itsWhiteness.getVal();
00467     vp.palette = itsVmmInfo.format;
00468     LINFO("bright=%u hue=%u color=%u contrast=%u white=%u depth=%u palette=%u",
00469         vp.brightness, vp.hue, vp.colour, vp.contrast,
00470         vp.whiteness, vp.depth, vp.palette);
00471     if (ioctl_nointr(itsFd, VIDIOCSPICT, &vp) != 0)
00472     {
00473       LERROR("ioctl(VIDIOCSPICT) set picture properties failed");
00474       *status = ParamClient::CHANGE_REJECTED;
00475     }*/
00476   }
00477 
00478 
00479 
00480 }
00481 
00482 
00483 // ######################################################################
00484 VideoFrame V4Lgrabber::grabSingleRaw()
00485 {
00486   byte* result = 0;
00487   if (itsMmapBuf) // mmap interface
00488     {
00489       itsCurrentFrame = 0;
00490       result = itsMmapBuf;
00491 
00492       // are we already grabbing buffer 'itsCurrentFrame'? otherwise,
00493       // start the grab now:
00494       if (itsGrabbing[itsCurrentFrame] == false)
00495         {
00496           itsVmmInfo.frame = itsCurrentFrame;
00497           itsGrabbing[itsCurrentFrame] = true;
00498           if (ioctl_nointr(itsFd, VIDIOCMCAPTURE, &itsVmmInfo) < 0)
00499             IDPLFATAL("VIDIOCMCAPTURE (frame %d)", itsCurrentFrame);
00500         }
00501 
00502       // wait until grab is complete:
00503       if (ioctl_nointr(itsFd, VIDIOCSYNC, &itsCurrentFrame) < 0)
00504         IDPLFATAL("VIDIOCSYNC (frame %d)", itsCurrentFrame);
00505       itsGrabbing[itsCurrentFrame] = false;
00506     }
00507   else // read() interface
00508     {
00509       ASSERT(itsReadBuf.initialized());
00510       const ssize_t nbytes =
00511         read(itsFd, itsReadBuf.getArrayPtr(), itsReadBuf.getSize());
00512       if (nbytes < 0)
00513         IDPLFATAL("read() failed (frame %d)", itsCurrentFrame);
00514       PLDEBUG("got %zd bytes", nbytes);
00515       result = itsReadBuf.getArrayPtr();
00516     }
00517 
00518   // return grabbed & converted frame:
00519   VideoFrame frame(result, (itsTotalBufSize / itsNumBufFrames),
00520                    itsDims.getVal(),
00521                    itsGrabMode.getVal(), itsByteSwap.getVal(),
00522                    /* strictLength = */ false);
00523 
00524   return frame;
00525 }
00526 
00527 // ######################################################################
00528 void V4Lgrabber::restartStream()
00529 {
00530   if (itsStreamingMode.getVal()
00531       && itsMmapBuf
00532       && !itsStreamStarted)
00533     {
00534       for (int i = 0; i < itsNumBufFrames; ++i)
00535         {
00536           // are we already grabbing buffer i?  if so, wait for grab
00537           // to finished if we've requested resync (if we don't do
00538           // this, then the first few frames after a restart will be
00539           // wrong -- they'll come too quickly and they'll be too old,
00540           // since the v4l driver doesn't grab new frames into buffers
00541           // until the old frames have been retrieved):
00542           if (itsGrabbing[i] == true)
00543             {
00544               if (ioctl_nointr(itsFd, VIDIOCSYNC, &i) < 0)
00545                 IDPLFATAL("VIDIOCSYNC (frame %d)", i);
00546               LINFO("flushed buffer %d", i);
00547               itsGrabbing[i] = false;
00548             }
00549         }
00550 
00551       for (int i = 0; i < itsNumBufFrames; ++i)
00552         {
00553           // now start a fresh grab for buffer i:
00554           itsVmmInfo.frame = i; itsGrabbing[i] = true;
00555           if (ioctl_nointr(itsFd, VIDIOCMCAPTURE, &itsVmmInfo) < 0)
00556             IDPLFATAL("VIDIOCMCAPTURE (frame %d)", i);
00557         }
00558 
00559       itsCurrentFrame = 0;
00560 
00561       itsStreamStarted = true;
00562     }
00563 }
00564 
00565 #endif // HAVE_LINUX_VIDEODEV_H
00566 
00567 // ######################################################################
00568 /* So things look consistent in everyone's emacs... */
00569 /* Local Variables: */
00570 /* indent-tabs-mode: nil */
00571 /* End: */
Generated on Sun May 8 08:04:45 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3