LoGrabber.C

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: */
Generated on Sun May 8 08:05:54 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3