core/vidl/vidl_v4l2_device.h
Go to the documentation of this file.
00001 // This is core/vidl/vidl_v4l2_device.h
00002 #ifndef vidl_v4l2_device_h_
00003 #define vidl_v4l2_device_h_
00004 //:
00005 // \file
00006 // \brief A class for handling a video device
00007 //
00008 // \author Antonio Garrido
00009 // \verbatim
00010 //  Modifications
00011 //   15 Apr 2009 Created (A. Garrido)
00012 //\endverbatim
00013 
00014 #include "vidl_v4l2_control.h"
00015 #include <vcl_vector.h>
00016 #include <vcl_string.h>
00017 #include <vcl_cassert.h>
00018 #include <vcl_iosfwd.h>
00019 #include <vcl_iostream.h>
00020 extern "C" {
00021 //#include <asm/types.h>          /* for videodev2.h */
00022 #include <sys/time.h>
00023 #include <linux/videodev2.h>
00024 };
00025 
00026 //: A class for handle a video device input
00027 // This class is not finished.
00028 // I am thinking about adding controls, that is, a number of user-settable controls such as
00029 // brightness, saturation and so on, but different devices will have different controls available.
00030 // So, I am thinking about new classes...
00031 class vidl_v4l2_input
00032 {
00033   struct v4l2_input input_;
00034   vidl_v4l2_input (const struct v4l2_input& inp) { input_=inp; }
00035   friend class vidl_v4l2_device;
00036  public:
00037   //: Return name of input
00038   vcl_string name() const { return vcl_string((const char*) input_.name); }
00039   //: Return if the input uses a tuner (RF modulator)
00040   bool is_tuner() const { return input_.type==V4L2_INPUT_TYPE_TUNER; }
00041 };
00042 
00043 //: A class for handle a video device.
00044 // This class is designed to be vidl independent, although it is very easy to create a vidl istream from it.
00045 // It has not been fully tested, although it has been proven to capture images
00046 // from multiple webcams with a single buffer (default) and has worked properly.
00047 // Generally, the steps to be made for a capture are as follows:
00048 // -# <b>Select input</b>
00049 // -# <b>Select format</b>
00050 // -# <b>Select number of buffers</b>.
00051 // -# <b>Start capturing</b>
00052 // -# <b>Stop capturing</b>
00053 // When a device is opened, an input and format are selected by default (see vidl_v4l2_device::try_formats function).
00054 // Then if you start capturing, you will <b>probably</b> get 640x480 frames,  from input 0,
00055 // using just one buffer with an unknown format (the first one valid for the driver).
00056 // \see vidl_v4l2_devices
00057 class vidl_v4l2_device
00058 {
00059   VCL_SAFE_BOOL_DEFINE;
00060   int fd;
00061 
00062   struct buffer {
00063     void *                  start; // vidl_frame_sptr??
00064     struct v4l2_buffer buf;
00065     //size_t                  length;
00066   };
00067   unsigned int pre_nbuffers; // Number of buffers to create
00068   struct buffer * buffers;
00069   unsigned int n_buffers;
00070   int last_buffer; // last read buffer to enqueue again (-1 if none)
00071   struct v4l2_format fmt; // width=height=0 indicates not established
00072   double frame_rate;
00073 
00074   vcl_string dev_name_;
00075   vcl_string card_name_;
00076   mutable vcl_string last_error;
00077   bool capturing; // see start_capturing
00078   vcl_vector<vidl_v4l2_input> inputs_;
00079   vcl_vector<vidl_v4l2_control *> controls_;
00080   void update_controls(); // must be called after input change
00081 
00082   // Reset the device to an initial state
00083   // It was public, but it is not useful for users of device, so it is moved to private
00084   void reset();
00085 
00086   bool open(); // return true if successful
00087   bool initialize_device(); //  return true if successful
00088   bool init_mmap(int reqbuf);
00089   bool uninit_mmap ();
00090   // Close device. If other functions are called, it would be automatically re-opened.
00091   bool close();
00092 
00093   bool is_open() const { return fd!=-1; }
00094   bool is_prepared_for_capturing() const  { return buffers!=0; }
00095   bool good() const { return last_error.size()==0; }
00096 
00097   // non-valid functions
00098   vidl_v4l2_device(const vidl_v4l2_device&);
00099   vidl_v4l2_device& operator= (const vidl_v4l2_device&);
00100 
00101  public:
00102 
00103   //: Constructor
00104   // After construction, device is closed (device is not busy).
00105   // You can use device as a boolean expression to test if device is ok.
00106   // \param file device name (for example, "/dev/video")
00107   // \param file device name (for example, "/dev/video")
00108   vidl_v4l2_device(const char *file);
00109   ~vidl_v4l2_device();
00110 
00111   //: Name of the associated file device (same as constructor)
00112   vcl_string device_file() const { return dev_name_; }
00113   //: Friendly name of the device.
00114   vcl_string card_name() const { return card_name_; }
00115   //: Number of inputs in device
00116   unsigned int n_inputs() const { return inputs_.size(); }
00117   //: Inputs been used (0 to ninputs-1)
00118   // if equal to ninputs, indicates unknown
00119   // \see ninputs
00120   unsigned int current_input() const;
00121   //: Return input number i (0 .. ninputs-1)
00122   const vidl_v4l2_input& input(int i) const { return inputs_.at(i);}
00123 
00124   //: Select input i
00125   // \return if successful
00126   bool set_input(unsigned int i);
00127 
00128   //: Select a new format.
00129   // Device try automatically different formats (\see try_formats()). Then this function could be ignored if you don't mind the format. Usually, user wants a concrete pixel format or, simply, change width and height.
00130   // \param fourcode A four character code defined in v4l2 (see v4l2 specification and vidl_pixel_format.h) indicating pixel encoding
00131   // \param width can be changed by drivers to the closest possible value
00132   // \param height can be changed by drivers to the closest possible value
00133   // \param fps frame rate to try (not garanteed).
00134   // \return if successful
00135   // \see format_is_set
00136   bool set_v4l2_format(unsigned int fourcode, int width, int height,double fps=0.0);
00137 
00138   //: Try several formats implemented in vidl
00139   // \param width can be changed by drivers to the closest possible value
00140   // \param height can be changed by drivers to the closest possible value
00141   // \param fps frame rate to try (not garanteed).
00142   // \return if successful
00143 
00144   bool try_formats(int width= 640, int height= 480);
00145 
00146   //: Return if the format is set.
00147   // Normally, a format is automatically selected or user call set_v4l2_format. User can use this function to know if a format is selected before calling start_capturing.
00148   // \see set_v4l2_format
00149   bool format_is_set() const { return fmt.fmt.pix.width!=0; }
00150 
00151   //: Get pixel format of type of compression
00152   // \return the four character code which is being used by driver(see v4l2 specification and vidl_pixel_format.h) or 0 if not set
00153   // \see set_v4l2_format
00154   unsigned int  get_v4l2_format() const {
00155                return (fmt.fmt.pix.width!=0)?
00156                       fmt.fmt.pix.pixelformat:0;
00157   }
00158 
00159   //: Return Image width in pixels.
00160   // \note You can use this function to know the width selected by driver after calling set_v4l2_format
00161   // \see set_v4l2_format
00162   int get_width() const { return fmt.fmt.pix.width; }
00163   //: Return Image height in pixels.
00164   // \note You can use this function to know the height selected by driver after calling set_v4l2_format
00165   // \see set_v4l2_format
00166   int get_height() const { return fmt.fmt.pix.height; }
00167 
00168   //: Return Current frame rate.
00169   // \see set_v4l2_format
00170   double get_frame_rate() const { return frame_rate; }
00171 
00172   // ----------------- Methods associated to controls -------------------
00173 
00174   //: Reset controls to default
00175   void reset_controls() ;
00176 
00177   //: Get number of controls
00178   // \return the number of detected controls (control not disabled and not inactive).
00179   int n_controls() const { return controls_.size(); }
00180   //: Get control
00181   // The user must downcast the pointer -depending on type- to use all functionality.
00182   // \param i indicates the control to be extracted, from 0 to n_controls-1
00183   // \return pointer to control
00184   // \see n_controls
00185   vidl_v4l2_control * get_control(int i) const { return controls_[i]; }
00186   //: Get control from driver id
00187   // The user must downcast the pointer -depending on type- to use all functionality.
00188   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00189   // \return pointer to control or 0 if does not exist
00190   vidl_v4l2_control * get_control_id(int id) const
00191     { for (int i=0;i<n_controls();++i) { if (controls_[i]->id()==id) return controls_[i]; } return 0;}
00192 
00193   //: Get control from driver id
00194   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00195   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_INTEGER
00196   vidl_v4l2_control_integer * get_control_integer_id( int id) const
00197   {
00198     vidl_v4l2_control *pc= get_control_id(id);
00199     return pc ? (pc->type()==V4L2_CTRL_TYPE_INTEGER ?
00200                  dynamic_cast<vidl_v4l2_control_integer *>(pc) : 0 ) : 0;
00201   }
00202 
00203   //: Get control from driver id
00204   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00205   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_MENU
00206   vidl_v4l2_control_menu * get_control_menu_id( int id) const
00207   {
00208     vidl_v4l2_control *pc= get_control_id(id);
00209     return pc ? (pc->type()==V4L2_CTRL_TYPE_MENU ?
00210                  dynamic_cast<vidl_v4l2_control_menu *>(pc) : 0 ) : 0;
00211   }
00212 
00213   //: Get control from driver id
00214   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00215   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_BOOLEAN
00216   vidl_v4l2_control_boolean * get_control_boolean_id( int id) const
00217   {
00218     vidl_v4l2_control *pc= get_control_id(id);
00219     return pc ? (pc->type()==V4L2_CTRL_TYPE_BOOLEAN ?
00220                  dynamic_cast<vidl_v4l2_control_boolean *>(pc) : 0 ) : 0;
00221   }
00222 
00223   //: Get control from driver id
00224   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00225   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_BUTTON
00226   vidl_v4l2_control_button * get_control_button_id( int id) const
00227   {
00228     vidl_v4l2_control *pc= get_control_id(id);
00229     return pc ? (pc->type()==V4L2_CTRL_TYPE_BUTTON ?
00230                  dynamic_cast<vidl_v4l2_control_button *>(pc) : 0 ) : 0;
00231   }
00232 
00233   // ----------------- End methods associated to controls -------------------
00234 
00235   //: Start capturing
00236   // \return if successful
00237   bool start_capturing ();
00238   //: Return if device is capturing
00239   bool is_capturing() const { return capturing; }
00240   //: Stop capturing
00241   // \return if successful
00242   bool stop_capturing();
00243   //: Read next frame
00244   // \return if successful
00245   bool read_frame();
00246 
00247   // ----------------- Methods associated to buffers -------------------
00248 
00249   //: Set numbers of buffers
00250   // \return if successful
00251   bool set_number_of_buffers(unsigned int nb);
00252   //: Get numbers of buffers
00253   unsigned int get_number_of_buffers() const { return pre_nbuffers; }
00254 
00255   //: Return the last used buffer
00256   // \pre device is capturing
00257   void * current_buffer() const {
00258     return (last_buffer==-1)?0:buffers[last_buffer].start;
00259   }
00260 
00261   //: Return length of the last used buffer
00262   // \pre device is capturing
00263   unsigned int current_buffer_length() const { // return __u32
00264     return (last_buffer==-1)?0:buffers[last_buffer].buf.length;
00265   }
00266 
00267   //: Return buffer number i
00268   // \pre device is capturing
00269   // \see get_number_of_buffers
00270   void *ibuffer(unsigned int i) const {
00271     return buffers && i < n_buffers ? buffers[i].start : 0;
00272   }
00273 
00274   // Return number in sequence associated to last frame, as indicated by driver
00275   unsigned int sequence() const { // return __u32
00276     if (last_buffer==-1) vcl_cerr << "UPS\n";
00277     return (last_buffer==-1)?0:buffers[last_buffer].buf.sequence;
00278   }
00279 
00280   // ----------------- End methods associated to buffers -------------------
00281 
00282   //: Return if driver has time associated to the captured frame
00283   // \pre device is capturing
00284   bool time_available() const {
00285     return (last_buffer==-1)?false:(buffers[last_buffer].buf.flags&V4L2_BUF_FLAG_TIMECODE);
00286   }
00287 
00288   //: Time from last frame
00289   // \see time_available
00290   v4l2_timecode time() const {
00291     return (last_buffer==-1)?v4l2_timecode():buffers[last_buffer].buf.timecode;
00292   }
00293 
00294   // --------   Next functions indicate if the device is in a bad state: not usable.
00295 
00296   //: Cast to bool is true if video device is working ok
00297   operator safe_bool () const
00298   { return (last_error.size()==0)? VCL_SAFE_BOOL_TRUE : 0; }
00299 
00300   //: Return false if video device is not working ok
00301   bool operator!() const
00302   { return (last_error.size()==0)? false : true; }
00303 
00304   //: Return last error if device is in a bad state. Empty if ok
00305   vcl_string get_error() const { return last_error; }
00306 
00307   //-------------------------------------------------------
00308   // reference counting if used through sptr
00309  public:
00310 
00311   //: Increment reference count
00312   void ref() { ref_count_++; }
00313 
00314   //: Decrement reference count
00315   void unref(){
00316     assert (ref_count_ >0);
00317     ref_count_--;
00318     if (ref_count_==0)
00319     {
00320       delete this;
00321     }
00322   }
00323 
00324   //: Number of objects referring to this data
00325   int ref_count() const { return ref_count_; }
00326 
00327  private:
00328   int ref_count_;
00329 };
00330 
00331 
00332 vcl_ostream &
00333 operator << (vcl_ostream &os, const vidl_v4l2_device & dev);
00334 
00335 
00336 #endif // vidl_v4l2_device_h_