00001 /** 00002 \file Robots/LoBot/io/Grabber.C 00003 \brief The bastard step cousin to the IEEE1394grabber. 00004 */ 00005 00006 // //////////////////////////////////////////////////////////////////// // 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00008 // by the University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 // //////////////////////////////////////////////////////////////////// // 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 // //////////////////////////////////////////////////////////////////// // 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 // //////////////////////////////////////////////////////////////////// // 00035 // 00036 // Primary maintainer for this file: mviswana usc edu 00037 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/io/LoGrabber.C $ 00038 // $Id: LoGrabber.C 13037 2010-03-23 01:00:53Z mviswana $ 00039 // 00040 00041 //---------------------- ALTERNATIVE DEFINITION ------------------------- 00042 00043 // In case libdc1394 and other IEEE-1394 libraries are missing 00044 #ifndef HAVE_IEEE1394 00045 00046 #include "Robots/LoBot/io/LoGrabber.H" 00047 00048 namespace lobot { 00049 00050 Grabber::Grabber(int, const Dims&, float) 00051 { 00052 throw missing_libs(MISSING_LIBDC1394) ; 00053 } 00054 00055 } // end of namespace encapsulating above empty definition 00056 00057 #else 00058 00059 //------------------------------ HEADERS -------------------------------- 00060 00061 // lobot headers 00062 #include "Robots/LoBot/io/LoGrabber.H" 00063 #include "Robots/LoBot/io/LoFireWireBus.H" 00064 #include "Robots/LoBot/misc/LoExcept.H" 00065 #include "Robots/LoBot/util/LoMath.H" 00066 00067 // INVT video conversion support 00068 #include "Video/VideoFrame.H" 00069 00070 // Unix headers 00071 #include <unistd.h> 00072 00073 //----------------------------- NAMESPACE ------------------------------- 00074 00075 namespace lobot { 00076 00077 //----------------------- FORWARD DECLARATIONS -------------------------- 00078 00079 typedef std::pair<int, VideoFormat> GrabMode ; 00080 static GrabMode grab_mode_enums(const Dims& resolution) ; 00081 00082 static int frame_rate_enum(float frame_rate) ; 00083 static Dims restrict_grab_size(const Dims& resolution) ; 00084 00085 static int get_num_cameras() ; 00086 static bool init_camera(int camera_number, int grab_mode, int frame_rate, 00087 dc1394_cameracapture*) ; 00088 static int setup_capture(const raw1394handle_t&, 00089 const nodeid_t& camera, int camera_number, 00090 int mode, int frame_rate, 00091 dc1394_cameracapture*) ; 00092 static bool start_transmission(dc1394_cameracapture*) ; 00093 00094 static void release_camera(dc1394_cameracapture*, int camera_number) ; 00095 00096 //-------------------------- HELPER CLASSES ----------------------------- 00097 00098 // Camera parameters "packet" 00099 CameraParams::CameraParams(int bright, int exp, int sharp, 00100 int ub, int vr, int hu, int sat, 00101 int gam, int shut, int gn) 00102 : brightness(bright), 00103 exposure(exp), 00104 sharpness(sharp), 00105 white_balance_ub(ub), white_balance_vr(vr), 00106 hue(hu), saturation(sat), 00107 gamma(gam), 00108 shutter(shut), 00109 gain(gn) 00110 {} 00111 00112 //---------------------- GRABBER INITIALIZATION ------------------------- 00113 00114 // On initialization, sanify parameters passed in prior to 00115 // remembering/setting the appropriate internal variables. 00116 Grabber::Grabber(int camera_number, 00117 const Dims& resolution, float frame_rate, 00118 const CameraParams& params) 00119 : m_camera_number(clamp(camera_number, 0, get_num_cameras())), 00120 m_grab_size(restrict_grab_size(resolution)), 00121 m_grab_mode(grab_mode_enums(m_grab_size)), 00122 m_frame_rate(frame_rate_enum(frame_rate)) 00123 { 00124 if (! init_camera(m_camera_number, 00125 m_grab_mode.first, m_frame_rate, & m_capture)) 00126 throw camera_error(SETUP_FAILED) ; 00127 00128 setParams(params) ; 00129 if (! start_transmission(& m_capture)) { 00130 release_camera(& m_capture, m_camera_number) ; 00131 throw camera_error(START_TRANSMISSION_FAILED) ; 00132 } 00133 } 00134 00135 // Setup camera capture over DMA 00136 static bool init_camera(int camera_number, int mode, int frame_rate, 00137 dc1394_cameracapture* capture) 00138 { 00139 const FireWireBus& bus = FireWireBus::instance() ; 00140 const raw1394handle_t& handle = bus.handle() ; 00141 const nodeid_t& camera = bus[camera_number] ; 00142 00143 capture->num_dma_buffers = 8 ; 00144 capture->drop_frames = 1 ; 00145 capture->dma_device_file = NULL ; 00146 00147 int setup = setup_capture(handle, camera, camera_number, 00148 mode, frame_rate, capture) ; 00149 return setup == DC1394_SUCCESS ; 00150 } 00151 00152 // Initiate camera capture mode 00153 static bool start_transmission(dc1394_cameracapture* capture) 00154 { 00155 const raw1394handle_t& handle = FireWireBus::instance().handle() ; 00156 int start = dc1394_start_iso_transmission(handle, capture->node) ; 00157 return start == DC1394_SUCCESS ; 00158 } 00159 00160 // Set various camera parameters 00161 void Grabber::setParams(const CameraParams& params) 00162 { 00163 const FireWireBus& bus = FireWireBus::instance() ; 00164 const raw1394handle_t& handle = bus.handle() ; 00165 const nodeid_t& camera = bus[m_camera_number] ; 00166 00167 dc1394_set_brightness(handle, camera, params.brightness) ; 00168 dc1394_set_exposure(handle, camera, params.exposure) ; 00169 dc1394_set_sharpness(handle, camera, params.sharpness) ; 00170 dc1394_set_white_balance(handle, camera, 00171 params.white_balance_ub, 00172 params.white_balance_vr) ; 00173 dc1394_set_hue(handle, camera, params.hue) ; 00174 dc1394_set_saturation(handle, camera, params.saturation) ; 00175 dc1394_set_gamma(handle, camera, params.gamma) ; 00176 dc1394_set_shutter(handle, camera, params.shutter) ; 00177 dc1394_set_gain(handle, camera, params.gain) ; 00178 } 00179 00180 //-------------------------- GRABBING FRAMES ---------------------------- 00181 00182 ImageType Grabber::grab() const 00183 { 00184 while (dc1394_dma_single_capture(& m_capture) != DC1394_SUCCESS) 00185 usleep(1) ; 00186 00187 const byte* data = m_capture.dma_ring_buffer + 00188 m_capture.dma_frame_size * m_capture.dma_last_buffer ; 00189 VideoFrame V(data, m_capture.dma_frame_size, 00190 m_grab_size, m_grab_mode.second, false, false) ; 00191 ImageType I(V.toRgb()) ; 00192 00193 dc1394_dma_done_with_buffer(& m_capture) ; 00194 return I ; 00195 } 00196 00197 //--------------------------- GRABBER INFO ------------------------------ 00198 00199 float Grabber::frameRate() const 00200 { 00201 switch (m_frame_rate) 00202 { 00203 case FRAMERATE_60: 00204 return 60 ; 00205 case FRAMERATE_30: 00206 return 30 ; 00207 case FRAMERATE_15: 00208 return 15 ; 00209 case FRAMERATE_7_5: 00210 return 7.5f ; 00211 case FRAMERATE_3_75: 00212 return 3.75f ; 00213 case FRAMERATE_1_875: 00214 return 1.875f ; 00215 default: 00216 return -1 ; 00217 } 00218 } 00219 00220 //------------------------- GRABBER CLEAN-UP ---------------------------- 00221 00222 Grabber::~Grabber() 00223 { 00224 release_camera(& m_capture, m_camera_number) ; 00225 } 00226 00227 static void release_camera(dc1394_cameracapture* capture, int camera_number) 00228 { 00229 const raw1394handle_t& handle = FireWireBus::instance().handle() ; 00230 00231 dc1394_dma_unlisten(handle, capture) ; 00232 dc1394_stop_iso_transmission(handle, capture->node) ; 00233 dc1394_dma_release_camera(handle, capture) ; 00234 } 00235 00236 //----------------------- MISCELLANEOUS HELPERS ------------------------- 00237 00238 static int get_num_cameras() 00239 { 00240 return FireWireBus::instance().num_cameras() ; 00241 } 00242 00243 // This grabber will only grab frames sized 160x120 or 320x240 pixels 00244 // (because it was originally written for Unibrain Fire-i cameras and 00245 // they work at 30fps only at these resolutions). 00246 static Dims restrict_grab_size(const Dims& resolution) 00247 { 00248 if (resolution.w() > 240) // halfway between 160 and 320 00249 return Dims(320, 240) ; 00250 return Dims(160, 120) ; 00251 } 00252 00253 // Return appropriate enums for libdc1394 and INVT based on the size of 00254 // frames to be grabbed from cameras. 00255 static GrabMode grab_mode_enums(const Dims& resolution) 00256 { 00257 if (resolution.w() > 240) // halfway between 160 and 320 00258 return GrabMode(MODE_320x240_YUV422, VIDFMT_YUV422) ; 00259 return GrabMode(MODE_160x120_YUV444, VIDFMT_YUV444) ; 00260 } 00261 00262 // The following function returns the libdc1394 enum corresponding to the 00263 // specified frame rate. 00264 static int frame_rate_enum(float r) 00265 { 00266 if (r >= 45) // halfway between 30 and 60 00267 return FRAMERATE_60 ; // r in [45, inf) 00268 if (r >= 22.5f) 00269 return FRAMERATE_30 ; // r in [22.5, 45) 00270 if (r >= 11.25f) 00271 return FRAMERATE_15 ; // r in [11.25, 22.5) 00272 if (r >= 5.625) 00273 return FRAMERATE_7_5 ; // r in [5.625, 11.25) 00274 if (r >= 2.8125f) 00275 return FRAMERATE_3_75 ; // r in [2.8125, 5.625) 00276 return FRAMERATE_1_875 ; // r in (-inf, 2.8125) 00277 } 00278 00279 // Convenience routine to perform DMA capture setup. libdc1394's API 00280 // comes in two flavours depending on the version of the library. 00281 // Encapsulating this API in a separate function allows us to pass the 00282 // appropriate parameters based on the version of libdc1394 without 00283 // messing up the call site. All of this ugly #ifdef-ing can be localized 00284 // to this portion of the code while the caller remains blissfully 00285 // unaware of the low-level plumbing required to make it work. 00286 #ifdef IEEE1394NEW 00287 00288 // Extra param in new version of DMA capture setup API 00289 static int setup_capture(const raw1394handle_t& handle, 00290 const nodeid_t& camera, int camera_number, 00291 int mode, int frame_rate, 00292 dc1394_cameracapture* capture) 00293 { 00294 return dc1394_dma_setup_capture(handle, camera, camera_number, 00295 FORMAT_VGA_NONCOMPRESSED, mode, 00296 SPEED_400, frame_rate, 00297 capture->num_dma_buffers, 00298 0, // new param: do_extra_buffering 00299 capture->drop_frames, 00300 capture->dma_device_file, capture) ; 00301 } 00302 00303 #else // use old version of DMA capture setup API 00304 00305 static int setup_capture(const raw1394handle_t& handle, 00306 const nodeid_t& camera, int camera_number, 00307 int mode, int frame_rate, 00308 dc1394_cameracapture* capture) 00309 { 00310 return dc1394_dma_setup_capture(handle, camera, camera_number, 00311 FORMAT_VGA_NONCOMPRESSED, mode, 00312 SPEED_400, frame_rate, 00313 capture->num_dma_buffers, 00314 capture->drop_frames, 00315 capture->dma_device_file, capture) ; 00316 } 00317 00318 #endif // #ifdef IEEE1394NEW 00319 00320 //----------------------------------------------------------------------- 00321 00322 } // end of namespace encapsulating this file's definitions 00323 00324 #endif // #ifndef HAVE_IEEE1394 00325 00326 /* So things look consistent in everyone's emacs... */ 00327 /* Local Variables: */ 00328 /* indent-tabs-mode: nil */ 00329 /* End: */