00001 /*!@file Devices/V4L2grabber.H Definition and access functions for 00002 video4linux v2 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/V4L2grabber.H $ 00036 // $Id: V4L2grabber.H 14046 2010-09-25 05:58:24Z itti $ 00037 // 00038 00039 #ifndef V4L2GRABBER_H_DEFINED 00040 #define V4L2GRABBER_H_DEFINED 00041 00042 #ifdef HAVE_LINUX_VIDEODEV2_H 00043 00044 #include <linux/videodev2.h> 00045 00046 #include "Component/ModelParam.H" 00047 #include "Image/Image.H" 00048 #include "Image/Pixels.H" 00049 #include "Transport/FrameIstream.H" 00050 #include "Util/SimTime.H" 00051 #include "Util/Types.H" 00052 #include "Video/VideoFormat.H" 00053 00054 class VideoFrame; 00055 00056 //! Definition and access functions for video4linux2 frame grabber 00057 /*! This class provides a trivial interface to Video4Linux2 frame 00058 grabbers. All the low-level setup is done during construction. The 00059 user only needs to call readRGB() or readFrame() to capture an 00060 image. Shared memory and DMA directly from the grabber hardware into 00061 our memory is used if supported by the grabber and driver. This 00062 should work with any framegrabber that is supported by 00063 Video4Linux. We use Bt878-based boards. 00064 00065 After each grab, the next grab is initiated, and will be ready 33ms 00066 later (or one frame later if not NTSC). If you call readFrame() again 00067 before 33ms have elapsed, it will block until the next frame is 00068 available. If you call it too late, you will have missed the latest 00069 frame, and readFrame() will block until the next frame is acquired. 00070 00071 So a good strategy is to use readFrame() to not only grab but also 00072 to synchronize your code with the video rate (30 frames/s if NTSC). 00073 Typically, then, you would have a main loop that first grabs and 00074 then does various processing that is guaranteed to take less than 00075 33ms. You do not need to insert any pause after that processing to 00076 obtain a stable framerate; just finish your main loop, and the next 00077 call to readFrame() (at the next iteration) will block until exactly 00078 one frame has passed since it was last called. See how this is done, 00079 for example, in pvisionTCP-master.C or test-grab.C */ 00080 00081 class V4L2grabber : public FrameIstream 00082 { 00083 public: 00084 //! Constructor 00085 V4L2grabber(OptionManager& mgr, 00086 const std::string& descrName = "V4L Frame Grabber Driver", 00087 const std::string& tagName = "V4LFrameGrabber", 00088 const ParamFlag flags = USE_MY_VAL); 00089 00090 //! Destructor 00091 virtual ~V4L2grabber(); 00092 00093 /// Install a FrameListener 00094 /** We call the listener's onRawFrame() inside each readFrame(). */ 00095 virtual void setListener(rutz::shared_ptr<FrameListener> listener); 00096 00097 //! Get a streaming grab started 00098 /*! This will instruct the grabber to grab all of its possible 00099 buffers, one after the other. Typically you should call this just 00100 before you start reading frames. If the option 00101 --framegrabber-streaming=false is set, then this call is a (safe) 00102 no-op. */ 00103 virtual void startStream(); 00104 00105 //! Return the specifications of the next frame to be returned 00106 virtual GenericFrameSpec peekFrameSpec(); 00107 00108 //! Get the inter-frame time that matches our video mode 00109 virtual SimTime getNaturalFrameTime() const; 00110 00111 //! Get the next frame from the frame-grabber 00112 /*! Returns grabbed frame. This call will block until a frame is 00113 ready and has been grabbed. 00114 00115 Beware that the integrity of the GenericFrame object may not 00116 last "very long"; basically, try to be finished using the 00117 GenericFrame object before you attempt to grab the next frame in 00118 the stream. If you need it for longer than that, then you should 00119 use GenericFrame::deepCopyOf() to make a copy of the frame that 00120 can be safely held indefinitely. */ 00121 virtual GenericFrame readFrame(); 00122 00123 00124 00125 protected: 00126 //! Grab a raw VideoFrame 00127 /*! Don't call this directly; use readFrame() instead. */ 00128 VideoFrame grabRaw(); 00129 00130 //! Grab a single VideoFrame 00131 /*! Don't call this directly; use readFrame() instead. 00132 00133 This function will work better with single-shot grabs (as 00134 opposed to video) and USB cameras. */ 00135 VideoFrame grabSingleRaw(); 00136 00137 //! get started 00138 virtual void start1(); 00139 00140 //! get stopped 00141 virtual void stop2(); 00142 00143 00144 private: 00145 //! Set the camera parameters on the fly 00146 virtual void paramChanged(ModelParamBase* const param, 00147 const bool valueChanged, 00148 ParamClient::ChangeStatus* status); 00149 00150 //! Auxiliary helper for startStream() 00151 void restartStream(); 00152 00153 //! device name of the /dev/ entry for the grabber device 00154 OModelParam<std::string> itsDevName; 00155 00156 //! input channel to use 00157 OModelParam<int> itsChannel; 00158 00159 //! width of grabbed frames 00160 OModelParam<Dims> itsDims; 00161 00162 //! grab mode that the hardware should use 00163 /*! Grabbed frames will internally be converted to Image< 00164 PixRGB<byte> > whatever that mode is, but playing with it may 00165 influence image quality, maximum achievable framerate, and amounts 00166 of CPU doing those conversions to RGB. */ 00167 OModelParam<VideoFormat> itsGrabMode; 00168 00169 //! determines whether byte swapping is done during conversion to RGB 00170 OModelParam<bool> itsByteSwap; 00171 00172 //! whether to operate in streaming or single-frame mode 00173 OModelParam<bool> itsStreamingMode; 00174 00175 //! number of frame buffers kept internally 00176 OModelParam<int> itsNbuf; 00177 00178 int itsFd; //!< file descriptor for video device 00179 byte** itsMmapBuf; //!< mmap'ed buffer with the video frames 00180 int *itsMmapBufSize; //!< size in bytes of each mmap'ed buffer 00181 Image<byte> itsReadBuf; //!< raw buffer for use with read() interface 00182 int itsCurrentFrame; //!< current frame 00183 bool* itsGrabbing; //!< which bufs have we told the hardware to grab? 00184 00185 SimTime itsFrameTime; //!< inter-frame time for our video mode 00186 00187 rutz::shared_ptr<FrameListener> itsListener; 00188 00189 bool itsStreamStarted; //!< whether startStream() has been called 00190 00191 // management of V4L2 controls: 00192 class V4L2grabberControlBase { 00193 public: 00194 V4L2grabberControlBase(const int id, const v4l2_ctrl_type typ) : cid(id), ctype(typ) { } 00195 virtual ~V4L2grabberControlBase() { } 00196 00197 uint cid; // use V4L2_CTRL_ID2CLASS(id) to get the control class 00198 v4l2_ctrl_type ctype; 00199 }; 00200 00201 template <class T> class V4L2grabberControl : public V4L2grabberControlBase { 00202 public: 00203 V4L2grabberControl(const ModelOptionDef *opt, ParamClient *client, const T& initval, 00204 const ParamFlag flags, const int id, const v4l2_ctrl_type typ) : 00205 V4L2grabberControlBase(id, typ), param(opt, client, initval, flags | ALLOW_ONLINE_CHANGES) { } 00206 00207 virtual ~V4L2grabberControl() { } 00208 00209 OModelParam<T> param; 00210 }; 00211 00212 std::vector<rutz::shared_ptr<V4L2grabberControlBase> > itsControls; 00213 00214 bool itsCanMMap; // the device has mmap capability 00215 bool itsCanRW; // the device has RW capability 00216 00217 00218 void openDevice(); 00219 void closeDevice(); 00220 void addControl(const struct v4l2_queryctrl & crtl); 00221 00222 ParamFlag itsOptionFlags; 00223 }; 00224 00225 #endif // HAVE_LINUX_VIDEODEV2_H 00226 00227 #endif 00228 00229 // ###################################################################### 00230 /* So things look consistent in everyone's emacs... */ 00231 /* Local Variables: */ 00232 /* indent-tabs-mode: nil */ 00233 /* End: */