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 usefull 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 
00112 
00113   //: Name of the associated file device (same as constructor)
00114   vcl_string device_file() const { return dev_name_; }
00115   //: Friendly name of the device.
00116   vcl_string card_name() const { return card_name_; }
00117   //: Number of inputs in device
00118   unsigned int n_inputs() const { return inputs_.size(); }
00119   //: Inputs been used (0 to ninputs-1)
00120   // if equal to ninputs, indicates unknown
00121   // \see ninputs
00122   unsigned int current_input() const;
00123   //: Return input number i (0 .. ninputs-1)
00124   const vidl_v4l2_input& input(int i) const { return inputs_.at(i);}
00125 
00126   //: Select input i
00127   // \return if successful
00128   bool set_input(unsigned int i);
00129 
00130   //: Select a new format.
00131   // 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.
00132   // \param fourcode A four character code defined in v4l2 (see v4l2 specification and vidl_pixel_format.h) indicating pixel encoding
00133   // \param width can be changed by drivers to the closest possible value
00134   // \param height can be changed by drivers to the closest possible value
00135   // \param fps frame rate to try (not garanteed).
00136   // \return if successful
00137   // \see format_is_set
00138   bool set_v4l2_format(unsigned int fourcode, int width, int height,double fps=0.0);
00139 
00140   //: Try several formats implemented in vidl
00141   // \param width can be changed by drivers to the closest possible value
00142   // \param height can be changed by drivers to the closest possible value
00143   // \param fps frame rate to try (not garanteed).
00144   // \return if successful
00145 
00146   bool try_formats(int width= 640, int height= 480);
00147 
00148   
00149   //: Return if the format is set.
00150   // 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.
00151   // \see set_v4l2_format
00152   bool format_is_set() const { return fmt.fmt.pix.width!=0; }
00153 
00154   //: Get pixel format of type of compression
00155   // \return the four character code which is being used by driver(see v4l2 specification and vidl_pixel_format.h) or 0 if not set
00156   // \see set_v4l2_format
00157   unsigned int  get_v4l2_format() const {
00158                return (fmt.fmt.pix.width!=0)?
00159                       fmt.fmt.pix.pixelformat:0;
00160   }
00161 
00162   //: Return Image width in pixels.
00163   // \note You can use this function to know the width selected by driver after calling set_v4l2_format
00164   // \see set_v4l2_format
00165   int get_width() const { return fmt.fmt.pix.width; }
00166   //: Return Image height in pixels.
00167   // \note You can use this function to know the height selected by driver after calling set_v4l2_format
00168   // \see set_v4l2_format
00169   int get_height() const { return fmt.fmt.pix.height; }
00170 
00171   //: Return Current frame rate.
00172   // \see set_v4l2_format
00173   double get_frame_rate() const { return frame_rate; }
00174 
00175   // ----------------- Methods associated to controls -------------------
00176 
00177   //: Reset controls to default
00178   void reset_controls() ;
00179 
00180   //: Get number of controls
00181   // \return the number of detected controls (control not disabled and not inactive).
00182   int n_controls() const { return controls_.size(); }
00183   //: Get control
00184   // The user must downcast the pointer -depending on type- to use all functionality.
00185   // \param i indicates the control to be extracted, from 0 to n_controls-1
00186   // \return pointer to control
00187   // \see n_controls
00188   vidl_v4l2_control * get_control(int i) const { return controls_[i]; }
00189   //: Get control from driver id
00190   // The user must downcast the pointer -depending on type- to use all functionality.
00191   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00192   // \return pointer to control or 0 if does not exist
00193   vidl_v4l2_control * get_control_id(int id) const
00194     { for (int i=0;i<n_controls();++i) { if (controls_[i]->id()==id) return controls_[i]; } return 0;}
00195 
00196   //: Get control from driver id
00197   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00198   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_INTEGER
00199   vidl_v4l2_control_integer * get_control_integer_id( int id) const
00200   {
00201     vidl_v4l2_control *pc= get_control_id(id);
00202     return pc ? (pc->type()==V4L2_CTRL_TYPE_INTEGER ?
00203                  dynamic_cast<vidl_v4l2_control_integer *>(pc) : 0 ) : 0;
00204   }
00205 
00206   //: Get control from driver id
00207   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00208   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_MENU
00209   vidl_v4l2_control_menu * get_control_menu_id( int id) const
00210   {
00211     vidl_v4l2_control *pc= get_control_id(id);
00212     return pc ? (pc->type()==V4L2_CTRL_TYPE_MENU ?
00213                  dynamic_cast<vidl_v4l2_control_menu *>(pc) : 0 ) : 0;
00214   }
00215 
00216   //: Get control from driver id
00217   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00218   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_BOOLEAN
00219   vidl_v4l2_control_boolean * get_control_boolean_id( int id) const
00220   {
00221     vidl_v4l2_control *pc= get_control_id(id);
00222     return pc ? (pc->type()==V4L2_CTRL_TYPE_BOOLEAN ?
00223                  dynamic_cast<vidl_v4l2_control_boolean *>(pc) : 0 ) : 0;
00224   }
00225 
00226   //: Get control from driver id
00227   // \param id is control ID from v4l2 specification. For example, V4L2_CID_BRIGHTNESS
00228   // \return pointer to control. Null if doesn't exist or is not of type V4L2_CTRL_TYPE_BUTTON
00229   vidl_v4l2_control_button * get_control_button_id( int id) const
00230   {
00231     vidl_v4l2_control *pc= get_control_id(id);
00232     return pc ? (pc->type()==V4L2_CTRL_TYPE_BUTTON ?
00233                  dynamic_cast<vidl_v4l2_control_button *>(pc) : 0 ) : 0;
00234   }
00235 
00236 
00237   // ----------------- End methods associated to controls -------------------
00238 
00239   //: Start capturing
00240   // \return if successful
00241   bool start_capturing ();
00242   //: Return if device is capturing
00243   bool is_capturing() const { return capturing; }
00244   //: Stop capturing
00245   // \return if successful
00246   bool stop_capturing();
00247   //: Read next frame
00248   // \return if successful
00249   bool read_frame();
00250 
00251 
00252   // ----------------- Methods associated to buffers -------------------
00253 
00254   //: Set numbers of buffers
00255   // \return if successful
00256   bool set_number_of_buffers(unsigned int nb);
00257   //: Get numbers of buffers
00258   unsigned int get_number_of_buffers() const { return pre_nbuffers; }
00259 
00260   //: Return the last used buffer
00261   // \pre device is capturing
00262   void * current_buffer() const {
00263     return (last_buffer==-1)?0:buffers[last_buffer].start;
00264   }
00265 
00266   //: Return length of the last used buffer
00267   // \pre device is capturing
00268   unsigned int current_buffer_length() const { // return __u32
00269     return (last_buffer==-1)?0:buffers[last_buffer].buf.length;
00270   }
00271 
00272   //: Return buffer number i
00273   // \pre device is capturing
00274   // \see get_number_of_buffers
00275   void *ibuffer(unsigned int i) const {
00276     return buffers && i < n_buffers ? buffers[i].start : 0;
00277   }
00278 
00279   // Return number in sequence associated to last frame, as indicated by driver
00280   unsigned int sequence() const { // return __u32
00281     if (last_buffer==-1) vcl_cerr << "UPS\n";
00282     return (last_buffer==-1)?0:buffers[last_buffer].buf.sequence;
00283   }
00284 
00285   // ----------------- End methods associated to buffers -------------------
00286 
00287 
00288   //: Return if driver has time associated to the captured frame
00289   // \pre device is capturing
00290   bool time_available() const {
00291     return (last_buffer==-1)?false:(buffers[last_buffer].buf.flags&V4L2_BUF_FLAG_TIMECODE);
00292   }
00293 
00294   //: Time from last frame
00295   // \see time_available
00296   v4l2_timecode time() const {
00297     return (last_buffer==-1)?v4l2_timecode():buffers[last_buffer].buf.timecode;
00298   }
00299 
00300   // --------   Next functions indicate if the device is in a bad state: not usable.
00301 
00302   //: Cast to bool is true if video device is working ok
00303   operator safe_bool () const
00304   { return (last_error.size()==0)? VCL_SAFE_BOOL_TRUE : 0; }
00305 
00306   //: Return false if video device is not working ok
00307   bool operator!() const
00308   { return (last_error.size()==0)? false : true; }
00309 
00310   //: Return last error if device is in a bad state. Empty if ok
00311   vcl_string get_error() const { return last_error; }
00312 
00313 
00314   //-------------------------------------------------------
00315   // reference counting if used through sptr
00316  public:
00317 
00318   //: Increment reference count
00319   void ref() { ref_count_++; }
00320 
00321   //: Decrement reference count
00322   void unref(){
00323     assert (ref_count_ >0);
00324     ref_count_--;
00325     if (ref_count_==0)
00326     {
00327       delete this;
00328     }
00329   }
00330 
00331   //: Number of objects referring to this data
00332   int ref_count() const { return ref_count_; }
00333 
00334  private:
00335   int ref_count_;
00336 };
00337 
00338 
00339 vcl_ostream &
00340 operator << (vcl_ostream &os, const vidl_v4l2_device & dev);
00341 
00342 
00343 #endif // vidl_v4l2_device_h_