00001 /*!@file Devices/V4Lgrabber.H Definition and access functions for video4linux 00002 grabber */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/V4Lgrabber.H $ 00036 // $Id: V4Lgrabber.H 10794 2009-02-08 06:21:09Z itti $ 00037 // 00038 00039 #ifndef V4LGRABBER_H_DEFINED 00040 #define V4LGRABBER_H_DEFINED 00041 00042 #ifdef HAVE_LINUX_VIDEODEV_H 00043 00044 // We need this in order for <linux/videodev.h> to be parsed 00045 // successfully (we could avoid this if we didn't have -ansi on the 00046 // command-line; not sure in fact why we have -ansi there in the first 00047 // place) 00048 #undef __STRICT_ANSI__ 00049 00050 #include "Component/ModelParam.H" 00051 #include "Image/Image.H" 00052 #include "Image/Pixels.H" 00053 #include "Transport/FrameIstream.H" 00054 #include "Util/SimTime.H" 00055 #include "Util/Types.H" 00056 #include "Video/VideoFormat.H" 00057 00058 #include <linux/videodev.h> 00059 00060 class VideoFrame; 00061 00062 //! Definition and access functions for video4linux frame grabber 00063 /*! This class provides a trivial interface to Video4Linux frame 00064 grabbers. All the low-level setup is done during construction. The 00065 user only needs to call readRGB() or readFrame() to capture an 00066 image. Shared memory and DMA directly from the grabber hardware into 00067 our memory is used if supported by the grabber and driver. This 00068 should work with any framegrabber that is supported by 00069 Video4Linux. We use Bt878-based boards. 00070 00071 After each grab, the next grab is initiated, and will be ready 33ms 00072 later (or one frame later if not NTSC). If you call readFrame() again 00073 before 33ms have elapsed, it will block until the next frame is 00074 available. If you call it too late, you will have missed the latest 00075 frame, and readFrame() will block until the next frame is acquired. 00076 00077 So a good strategy is to use readFrame() to not only grab but also 00078 to synchronize your code with the video rate (30 frames/s if NTSC). 00079 Typically, then, you would have a main loop that first grabs and 00080 then does various processing that is guaranteed to take less than 00081 33ms. You do not need to insert any pause after that processing to 00082 obtain a stable framerate; just finish your main loop, and the next 00083 call to readFrame() (at the next iteration) will block until exactly 00084 one frame has passed since it was last called. See how this is done, 00085 for example, in pvisionTCP-master.C or test-grab.C */ 00086 00087 class V4Lgrabber : public FrameIstream 00088 { 00089 public: 00090 //! Constructor 00091 V4Lgrabber(OptionManager& mgr, 00092 const std::string& descrName = "V4L Frame Grabber Driver", 00093 const std::string& tagName = "V4LFrameGrabber", 00094 const ParamFlag flags = USE_MY_VAL); 00095 00096 //! Destructor 00097 virtual ~V4Lgrabber(); 00098 00099 /// Install a FrameListener 00100 /** We call the listener's onRawFrame() inside each readFrame(). */ 00101 virtual void setListener(rutz::shared_ptr<FrameListener> listener); 00102 00103 //! Get a streaming grab started 00104 /*! This will instruct the grabber to grab all of its possible 00105 buffers, one after the other. Typically you should call this just 00106 before you start reading frames. If the option 00107 --framegrabber-streaming=false is set, then this call is a (safe) 00108 no-op. */ 00109 virtual void startStream(); 00110 00111 //! Return the specifications of the next frame to be returned 00112 virtual GenericFrameSpec peekFrameSpec(); 00113 00114 //! Get the inter-frame time that matches our video mode 00115 virtual SimTime getNaturalFrameTime() const; 00116 00117 //! Get the next frame from the frame-grabber 00118 /*! Returns grabbed frame. This call will block until a frame is 00119 ready and has been grabbed. 00120 00121 Beware that the integrity of the GenericFrame object may not 00122 last "very long"; basically, try to be finished using the 00123 GenericFrame object before you attempt to grab the next frame in 00124 the stream. If you need it for longer than that, then you should 00125 use GenericFrame::deepCopyOf() to make a copy of the frame that 00126 can be safely held indefinitely. */ 00127 virtual GenericFrame readFrame(); 00128 00129 protected: 00130 //! Grab a raw VideoFrame 00131 /*! Don't call this directly; use readFrame() instead. */ 00132 VideoFrame grabRaw(); 00133 00134 //! Grab a single VideoFrame 00135 /*! Don't call this directly; use readFrame() instead. 00136 00137 This function will work better with single-shot grabs (as 00138 opposed to video) and USB cameras. */ 00139 VideoFrame grabSingleRaw(); 00140 00141 //! get started 00142 virtual void start1(); 00143 00144 //! get stopped 00145 virtual void stop2(); 00146 00147 private: 00148 //! Set the camera parameters on the fly 00149 virtual void paramChanged(ModelParamBase* const param, 00150 const bool valueChanged, 00151 ParamClient::ChangeStatus* status); 00152 00153 //! Auxiliary helper for startStream() 00154 void restartStream(); 00155 00156 //! device name of the /dev/ entry for the grabber device 00157 OModelParam<std::string> itsDevName; 00158 00159 //! input channel to use 00160 OModelParam<int> itsChannel; 00161 00162 //! width of grabbed frames 00163 OModelParam<Dims> itsDims; 00164 00165 //! grab mode that the hardware should use 00166 /*! Grabbed frames will internally be converted to Image< 00167 PixRGB<byte> > whatever that mode is, but playing with it may 00168 influence image quality, maximum achievable framerate, and amounts 00169 of CPU doing those conversions to RGB. */ 00170 OModelParam<VideoFormat> itsGrabMode; 00171 00172 //! determines whether byte swapping is done during conversion to RGB 00173 OModelParam<bool> itsByteSwap; 00174 00175 //! brightness - highly dependent on your driver 00176 OModelParam<int> itsBrightness; 00177 00178 //! hue - highly dependent on your driver 00179 OModelParam<int> itsHue; 00180 00181 //! color - highly dependent on your driver 00182 OModelParam<int> itsColour; 00183 00184 //! contrast - highly dependent on your driver 00185 OModelParam<int> itsContrast; 00186 00187 //! whiteness - highly dependent on your driver 00188 OModelParam<int> itsWhiteness; 00189 00190 //! whether to operate in streaming or single-frame mode 00191 OModelParam<bool> itsStreamingMode; 00192 00193 int itsFd; //!< file descriptor for video device 00194 byte* itsMmapBuf; //!< mmap'ed buffer with the video frames 00195 Image<byte> itsReadBuf; //!< raw buffer for use with read() interface 00196 int itsTotalBufSize; //!< size of the mmap'ed buffer 00197 int itsNumBufFrames; //!< total number of frames in buf 00198 int itsCurrentFrame; //!< current frame 00199 bool* itsGrabbing; //!< which buffers have we told the hardware to grab? 00200 00201 struct video_mmap itsVmmInfo; 00202 00203 SimTime itsFrameTime; //!< inter-frame time for our video mode 00204 00205 rutz::shared_ptr<FrameListener> itsListener; 00206 00207 bool itsStreamStarted; //!< whether startStream() has been called 00208 }; 00209 00210 #endif // HAVE_LINUX_VIDEODEV_H 00211 00212 #endif 00213 00214 // ###################################################################### 00215 /* So things look consistent in everyone's emacs... */ 00216 /* Local Variables: */ 00217 /* indent-tabs-mode: nil */ 00218 /* End: */