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_