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