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_
1.7.5.1