Fawkes API  Fawkes Development Version
firewire.cpp
00001  
00002 /***************************************************************************
00003  *  firewire.cpp - Implementation to access FW cam using libdc1394
00004  *
00005  *  Generated: Tue Feb 22 13:28:08 2005
00006  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <core/exception.h>
00025 #include <core/exceptions/software.h>
00026 #include <utils/system/console_colors.h>
00027 
00028 #include <cstdlib>
00029 #include <unistd.h>
00030 #include <climits>
00031 #include <cstring>
00032 
00033 #include <cams/firewire.h>
00034 #include <cams/cam_exceptions.h>
00035 #include <fvutils/system/camargp.h>
00036 
00037 #include <dc1394/utils.h>
00038 
00039 using namespace std;
00040 using namespace fawkes;
00041 
00042 namespace firevision {
00043 #if 0 /* just to make Emacs auto-indent happy */
00044 }
00045 #endif
00046 
00047 /** @class FirewireCamera <cams/firewire.h>
00048  * Firewire camera.
00049  * This camera implementation allows for access to IEEE1394 cameras via
00050  * libdc1394.
00051  * @author Tim Niemueller
00052  */
00053 
00054 /** Constructor.
00055  * @param framerate desired framerate
00056  * @param mode desired mode
00057  * @param speed IEEE 1394 speed
00058  * @param num_buffers number of DMA buffers
00059  */
00060 FirewireCamera::FirewireCamera(dc1394framerate_t framerate,
00061                                dc1394video_mode_t mode,
00062                                dc1394speed_t speed,
00063                                int num_buffers)
00064 {
00065   _started = _opened = false;
00066   _valid_frame_received = false;
00067   _auto_focus = true; // assume auto_focus, checked in open()
00068   _auto_shutter = false;
00069   _auto_white_balance = false;
00070   _speed = speed;
00071   _num_buffers = num_buffers;
00072   _mode = mode;
00073   _framerate = framerate;
00074   _white_balance_ub = 0xFFFFFFFF;
00075   _white_balance_vr = 0xFFFFFFFF;
00076   _format7_mode_enabled = false;
00077   _format7_width = _format7_height = _format7_startx = _format7_starty = 0;
00078   _format7_bpp = 4096;
00079   _model = strdup("any");
00080   _do_set_shutter = false;
00081   _do_set_white_balance = false;
00082   _do_set_focus = false;
00083   _gain = 0;
00084   _auto_gain = true;
00085 
00086   _dc1394 = NULL;
00087   _camera = NULL;
00088 
00089   if ((mode == DC1394_VIDEO_MODE_640x480_YUV422) && (framerate == DC1394_FRAMERATE_30)) {
00090     // cerr  << "When in mode YUV422 @ 640x480 with more than 15 fps. Setting framerate to 15fps." << endl;
00091     _framerate = DC1394_FRAMERATE_15;
00092   }
00093 }
00094 
00095 
00096 /** Empty destructor. */
00097 FirewireCamera::~FirewireCamera()
00098 {
00099   close();
00100   
00101   if ( _model != NULL ) {
00102     free(_model);
00103   }
00104 }
00105 
00106 
00107 void
00108 FirewireCamera::open()
00109 {
00110   if (_opened) return;
00111 
00112   _dc1394 = dc1394_new();
00113   dc1394camera_list_t *list;
00114   dc1394error_t        err;
00115 
00116   if ( dc1394_camera_enumerate(_dc1394, &list) != DC1394_SUCCESS ) {
00117     throw Exception("Could not enumerate cameras");
00118   }
00119 
00120   if (list->num > 0) {
00121     if ( strcmp(_model, "any") == 0 ) {
00122       /* use the first camera found */
00123       _camera = dc1394_camera_new(_dc1394, list->ids[0].guid);
00124       if (! _camera) {
00125         dc1394_free(_dc1394);
00126         _dc1394 = NULL;
00127         throw Exception("Could not create camera for first foiund camera");
00128       }
00129     } else {
00130       _camera = NULL;
00131       for (unsigned int i = 0; i < list->num; ++i) {
00132         dc1394camera_t *tmpcam = dc1394_camera_new(_dc1394, list->ids[i].guid);
00133         if ( strcmp(_model, tmpcam->model) == 0) {
00134           // found desired camera
00135           _camera = tmpcam;
00136           break;
00137         } else {
00138           dc1394_camera_free(tmpcam);
00139         }
00140       }
00141       if ( _camera == NULL ) {
00142         throw Exception("Could not find camera with model %s", _model);
00143       }
00144     }
00145 
00146     if ( iso_mode_enabled() ) {
00147       dc1394_video_set_transmission(_camera, DC1394_OFF);
00148     }
00149     // These methods would cleanup the mess left behind by other processes,
00150     // but as of now (libdc1394 2.0.0 rc9) this is not supported for the Juju stack
00151     dc1394_iso_release_bandwidth(_camera, INT_MAX);
00152     for (int channel = 0; channel < 64; ++channel) {
00153       dc1394_iso_release_channel(_camera, channel);
00154     }
00155     // This is rude, but for now needed (Juju)...
00156     //dc1394_reset_bus(_camera);
00157 
00158     if (_camera->bmode_capable > 0) {
00159       dc1394_video_set_operation_mode(_camera, DC1394_OPERATION_MODE_1394B);
00160     }
00161     if ( //((err = dc1394_cleanup_iso_channels_and_bandwidth(_camera)) != DC1394_SUCCESS) ||
00162          ((err = dc1394_video_set_iso_speed(_camera, _speed)) != DC1394_SUCCESS) ||
00163          ((err = dc1394_video_set_mode(_camera, _mode)) != DC1394_SUCCESS) ||
00164          ((err = dc1394_video_set_framerate(_camera, _framerate)) != DC1394_SUCCESS) ) {
00165       throw Exception("Setting up the camera failed: %s", dc1394_error_get_string(err));
00166     }
00167 
00168     if (_format7_mode_enabled) {
00169       if (_format7_bpp == 0) {
00170         uint32_t rps;
00171         dc1394_format7_get_recommended_packet_size(_camera, _mode, &rps);
00172         _format7_bpp = rps;
00173       }
00174 
00175       if ( ((err = dc1394_format7_set_image_size(_camera, _mode, _format7_width, _format7_height)) != DC1394_SUCCESS) ||
00176            ((err = dc1394_format7_set_image_position(_camera, _mode, _format7_startx, _format7_starty)) != DC1394_SUCCESS) ||
00177            ((err = dc1394_format7_set_color_coding(_camera, _mode, _format7_coding)) != DC1394_SUCCESS) ||
00178            ((err = dc1394_format7_set_packet_size(_camera, _mode, _format7_bpp)) != DC1394_SUCCESS) ) {
00179         throw Exception("Could not setup Format7 parameters: %s", dc1394_error_get_string(err));
00180       }
00181     }
00182 
00183     set_auto_shutter(_auto_shutter);
00184     if ( !_auto_shutter && _do_set_shutter ) {
00185       set_shutter(_shutter);
00186     }
00187 
00188     set_auto_focus(_auto_focus);
00189     if ( ! _auto_focus && _do_set_focus ) {
00190       set_focus(_focus);
00191     }
00192 
00193     set_auto_white_balance(_auto_white_balance);
00194     if ( ! _auto_white_balance &&
00195          (_white_balance_ub != 0xFFFFFFFF) &&
00196          (_white_balance_vr != 0xFFFFFFFF) &&
00197          _do_set_white_balance ) {
00198       set_white_balance(_white_balance_ub, _white_balance_vr);
00199     }
00200     
00201     if ( !_auto_gain ) {
00202       set_gain(_gain);
00203     }
00204 
00205   } else {
00206     throw Exception("No cameras connected");
00207   }
00208 
00209   _opened = true;
00210 }
00211 
00212 
00213 void
00214 FirewireCamera::start()
00215 {
00216   if (_started) return;
00217 
00218   if (! _opened) {
00219     throw Exception("FirewireCamera: Cannot start closed camera");
00220   }
00221 
00222   dc1394error_t err;
00223   if ( (err = dc1394_capture_setup(_camera, _num_buffers, DC1394_CAPTURE_FLAGS_DEFAULT )) != DC1394_SUCCESS ) {
00224     dc1394_capture_stop(_camera);
00225     throw Exception("FirewireCamera: Could not setup capture (%s)", dc1394_error_get_string(err));
00226   }
00227 
00228   if ( (err = dc1394_video_set_transmission(_camera, DC1394_ON)) != DC1394_SUCCESS) {
00229     // cout  << cred << "Could not start video transmission" << cnormal << endl;
00230     dc1394_capture_stop(_camera);
00231     throw Exception("FirewireCamera: Could not start ISO transmission (%s)", dc1394_error_get_string(err));
00232   }
00233                                 
00234   // Give it some time to be ready
00235   usleep(500000);
00236 
00237   _started = true;
00238 }
00239 
00240 
00241 void
00242 FirewireCamera::stop()
00243 {
00244   dc1394_video_set_transmission(_camera, DC1394_OFF);
00245   dc1394_capture_stop(_camera);
00246   _started = false;
00247 }
00248 
00249 
00250 /** Check if ISO mode is enabled.
00251  * @return true if isochronous transfer is running, false otherwise.
00252  * @exception Exception thrown if the transmission status could not be determined
00253  */
00254 bool
00255 FirewireCamera::iso_mode_enabled()
00256 {
00257   dc1394switch_t status;
00258   if ( dc1394_video_get_transmission(_camera, &status) != DC1394_SUCCESS) {
00259     throw Exception("Could not get transmission status");
00260   } else {
00261     return (status == DC1394_ON);
00262   }
00263 }
00264 
00265 
00266 void
00267 FirewireCamera::print_info()
00268 {
00269   if (_opened) {
00270     dc1394_camera_print_info( _camera, stdout );
00271   }
00272 
00273   printf("Parameters:\n"
00274          "valid frame received: %i\n"
00275          "auto focus: %i\n"
00276          "auto shutter: %i  (shutter value: %u)\n"
00277          "auto white balance: %i  (white balance value %u/%u)\n"
00278          "do set shutter: %i   do set white balance: %i\n",
00279          _valid_frame_received,_auto_focus,
00280          _auto_shutter, _shutter,
00281          _auto_white_balance, _white_balance_ub, _white_balance_vr,
00282          _do_set_shutter = false, _do_set_white_balance = false
00283          );
00284 }
00285 
00286 
00287 /** Get Firewire GUID of camera.
00288  * @return IEEE1394 GUID
00289  */
00290 uint64_t
00291 FirewireCamera::guid() const
00292 {
00293   if ( ! _opened ) {
00294     throw Exception("Camera not opened");
00295   }
00296 
00297   return _camera->guid;
00298 }
00299 
00300 
00301 /** Get camera model.
00302  * @return string with the camera model name
00303  */
00304 const char *
00305 FirewireCamera::model() const
00306 {
00307   if ( ! _opened ) {
00308     throw Exception("Camera not opened");
00309   }
00310 
00311   return _camera->model;
00312 }
00313 
00314 
00315 void
00316 FirewireCamera::capture()
00317 {
00318 
00319   if (! _opened) {
00320     throw CaptureException("FirewireCamera(%s): cannot capture on closed camera", _model);
00321   }
00322   if (! _started) {
00323     throw CaptureException("FirewireCamera(%s): cannot capture on stopped camera", _model);
00324   }
00325 
00326   if (! iso_mode_enabled()) {
00327     throw CaptureException("FirewireCamera(%s): isochronous transfer not active", _model);
00328   }
00329 
00330   dc1394error_t err;
00331   if (DC1394_SUCCESS != (err = dc1394_capture_dequeue(_camera, DC1394_CAPTURE_POLICY_WAIT, &_frame))) {
00332     _valid_frame_received = false;
00333     throw CaptureException("FireWireCamera(%s): capture failed (%s)",
00334                            _model, dc1394_error_get_string(err));
00335   } else {
00336     _valid_frame_received = (_frame != NULL);
00337   }
00338 }
00339 
00340 
00341 void
00342 FirewireCamera::flush()
00343 {
00344   capture();
00345   // HACK, needed or we will get kernel NULL pointer exception *urgh*
00346   usleep(100000);
00347   dispose_buffer();
00348 }
00349 
00350 
00351 unsigned char*
00352 FirewireCamera::buffer()
00353 {
00354   if ( _valid_frame_received ) {
00355     return _frame->image;
00356   } else {
00357     return NULL;
00358   }
00359 }
00360 
00361 
00362 unsigned int
00363 FirewireCamera::buffer_size()
00364 {
00365   if ( _valid_frame_received ) {
00366     return _frame->total_bytes;
00367   } else {
00368     return 0;
00369   }
00370 }
00371 
00372 void
00373 FirewireCamera::close()
00374 {
00375   if ( _started ) stop();
00376   if ( _opened ) {
00377     dc1394_camera_free( _camera );
00378     dc1394_free(_dc1394);
00379     _camera = NULL;
00380     _dc1394 = NULL;
00381     _opened = false;
00382   }
00383 }
00384 
00385 
00386 void
00387 FirewireCamera::dispose_buffer()
00388 {
00389   if ( _valid_frame_received ) {
00390     dc1394_capture_enqueue( _camera, _frame );
00391   }
00392 }
00393 
00394 
00395 unsigned int
00396 FirewireCamera::pixel_width()
00397 {
00398   if (_opened) {
00399     if ( _valid_frame_received ) {
00400       return _frame->size[0];
00401     } else {
00402       unsigned int width, height;
00403       dc1394error_t err;
00404       if ((err = dc1394_get_image_size_from_video_mode(_camera, _mode, &width, &height)) != DC1394_SUCCESS) {
00405         throw Exception("FirewireCamera(%s): cannot get width (%s)", _model,
00406                         dc1394_error_get_string(err));
00407       }
00408       return width;
00409     }
00410   } else {
00411     throw Exception("Camera not opened");
00412   }
00413 }
00414 
00415 
00416 unsigned int
00417 FirewireCamera::pixel_height()
00418 {
00419   if (_opened) {
00420     if ( _valid_frame_received ) {
00421       return _frame->size[1];
00422     } else {
00423       unsigned int width, height;
00424       dc1394error_t err;
00425       if ((err = dc1394_get_image_size_from_video_mode(_camera, _mode, &width, &height)) != DC1394_SUCCESS) {
00426         throw Exception("FirewireCamera(%s): cannot get width (%s)", _model,
00427                         dc1394_error_get_string(err));
00428       }
00429       return height;
00430     }
00431   } else {
00432     throw Exception("Camera not opened");
00433   }
00434 }
00435 
00436 
00437 colorspace_t
00438 FirewireCamera::colorspace()
00439 {
00440   // this needs to be changed for different modes
00441   switch (_mode) {
00442   case DC1394_VIDEO_MODE_320x240_YUV422:
00443   case DC1394_VIDEO_MODE_640x480_YUV422:
00444   case DC1394_VIDEO_MODE_800x600_YUV422:
00445   case DC1394_VIDEO_MODE_1024x768_YUV422:
00446   case DC1394_VIDEO_MODE_1280x960_YUV422:
00447   case DC1394_VIDEO_MODE_1600x1200_YUV422:
00448     return YUV422_PACKED;
00449 
00450   case DC1394_VIDEO_MODE_640x480_YUV411:
00451     return YUV411_PACKED;
00452 
00453 
00454   case DC1394_VIDEO_MODE_640x480_RGB8:
00455   case DC1394_VIDEO_MODE_800x600_RGB8:
00456   case DC1394_VIDEO_MODE_1024x768_RGB8:
00457   case DC1394_VIDEO_MODE_1280x960_RGB8:
00458   case DC1394_VIDEO_MODE_1600x1200_RGB8:
00459     return RGB;
00460 
00461   case DC1394_VIDEO_MODE_640x480_MONO8:
00462   case DC1394_VIDEO_MODE_800x600_MONO8:
00463   case DC1394_VIDEO_MODE_1024x768_MONO8:
00464   case DC1394_VIDEO_MODE_1280x960_MONO8:
00465   case DC1394_VIDEO_MODE_1600x1200_MONO8:
00466     return MONO8;
00467 
00468   case DC1394_VIDEO_MODE_640x480_MONO16:
00469   case DC1394_VIDEO_MODE_800x600_MONO16:
00470   case DC1394_VIDEO_MODE_1024x768_MONO16:
00471   case DC1394_VIDEO_MODE_1280x960_MONO16:
00472   case DC1394_VIDEO_MODE_1600x1200_MONO16:
00473     return MONO16;
00474 
00475   case DC1394_VIDEO_MODE_FORMAT7_0:
00476   case DC1394_VIDEO_MODE_FORMAT7_1:
00477   case DC1394_VIDEO_MODE_FORMAT7_2:
00478   case DC1394_VIDEO_MODE_FORMAT7_3:
00479   case DC1394_VIDEO_MODE_FORMAT7_4:
00480   case DC1394_VIDEO_MODE_FORMAT7_5:
00481   case DC1394_VIDEO_MODE_FORMAT7_6:
00482   case DC1394_VIDEO_MODE_FORMAT7_7:
00483     switch (_format7_coding) {
00484     case DC1394_COLOR_CODING_MONO8:
00485       return MONO8;
00486     case DC1394_COLOR_CODING_YUV411:
00487       return YUV411_PACKED;
00488     case DC1394_COLOR_CODING_YUV422:
00489       return YUV422_PACKED;
00490     case DC1394_COLOR_CODING_RGB8:
00491       return RGB;
00492     case DC1394_COLOR_CODING_MONO16:
00493       return MONO16;
00494     case DC1394_COLOR_CODING_RAW8:
00495       return RAW8;
00496     case DC1394_COLOR_CODING_RAW16:
00497       return RAW16;
00498     default:
00499       return CS_UNKNOWN;
00500     }
00501     break;
00502 
00503   default:
00504     return CS_UNKNOWN;
00505   }
00506 }
00507 
00508 
00509 bool
00510 FirewireCamera::ready()
00511 {
00512   return _started;
00513 }
00514 
00515 
00516 void
00517 FirewireCamera::set_image_number(unsigned int n)
00518 {
00519 }
00520 
00521 
00522 /* CAMERA CONTROL STUFF */
00523 
00524 void
00525 FirewireCamera::set_auto_focus(bool enabled)
00526 {
00527   dc1394error_t err;
00528   if ((err = dc1394_feature_set_mode(_camera, DC1394_FEATURE_FOCUS,
00529                                      enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
00530       == DC1394_SUCCESS) {
00531     _auto_focus = enabled;
00532   } else {
00533     throw Exception("FirewireCamera(%s): Setting auto focus failed (%s)", _model,
00534                     dc1394_error_get_string(err));
00535   }
00536 }
00537 
00538 
00539 bool
00540 FirewireCamera::auto_focus()
00541 {
00542   return _auto_focus;
00543 }
00544 
00545 
00546 unsigned int
00547 FirewireCamera::focus()
00548 {
00549   unsigned int focus = 0;
00550   if (dc1394_feature_get_value(_camera, DC1394_FEATURE_FOCUS, &focus) == DC1394_SUCCESS) {
00551     return focus;
00552   } else {
00553     return 0;
00554   }
00555   
00556 }
00557 
00558 
00559 void
00560 FirewireCamera::set_focus(unsigned int focus)
00561 {
00562   dc1394_feature_set_value(_camera, DC1394_FEATURE_FOCUS, focus);
00563 }
00564 
00565 
00566 unsigned int
00567 FirewireCamera::focus_min()
00568 {
00569   unsigned int min = 0;
00570   unsigned int max = 0;
00571   if (dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_FOCUS, &min, &max) == DC1394_SUCCESS) {
00572     return min;
00573   } else {
00574     return 0;
00575   }
00576 }
00577 
00578 
00579 unsigned int
00580 FirewireCamera::focus_max()
00581 {
00582   unsigned int max = 0;
00583   unsigned int min = 0;
00584   if (dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_FOCUS, &min, &max) == DC1394_SUCCESS) {
00585     return max;
00586   } else {
00587     return 0;
00588   }
00589 }
00590 
00591 
00592 /** Set status of auto shutter.
00593  * @param enabled true to enable auto shutter, false to disable.
00594  */
00595 void
00596 FirewireCamera::set_auto_shutter(bool enabled)
00597 {
00598   if (dc1394_feature_set_mode(_camera, DC1394_FEATURE_SHUTTER,
00599                               enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL)
00600       == DC1394_SUCCESS) {
00601     _auto_shutter = enabled;
00602   }
00603 }
00604 
00605 
00606 /** Get status of auto shutter.
00607  * @return true if auto shutter is enabled, false otherwise
00608  */
00609 bool
00610 FirewireCamera::auto_shutter()
00611 {
00612   return _auto_shutter;
00613 }
00614 
00615 
00616 /** Set shutter value.
00617  * @param shutter shutter value
00618  */
00619 void
00620 FirewireCamera::set_shutter(unsigned int shutter)
00621 {
00622   if ( dc1394_feature_set_value(_camera, DC1394_FEATURE_SHUTTER, shutter) != DC1394_SUCCESS ) {
00623     throw Exception("Failed to set shutter to %d", shutter);
00624   }
00625 }
00626 
00627 
00628 /** Get shutter value.
00629  * @return the current shutter value
00630  */
00631 unsigned int
00632 FirewireCamera::shutter()
00633 {
00634   if ( dc1394_feature_get_value(_camera, DC1394_FEATURE_SHUTTER, &_shutter) != DC1394_SUCCESS ) {
00635     throw Exception("Failed to retrieve shutter value");
00636   }
00637   
00638   return _shutter;
00639 }
00640 
00641 
00642 /** Set status of auto white balance.
00643  * @param enabled true to enable auto white balance, false to disable.
00644  */
00645 void
00646 FirewireCamera::set_auto_white_balance(bool enabled)
00647 {
00648   if (dc1394_feature_set_mode(_camera, DC1394_FEATURE_WHITE_BALANCE,
00649                               enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL)
00650       == DC1394_SUCCESS) {
00651     _auto_white_balance = enabled;
00652   }
00653 }
00654 
00655 
00656 /** Get status of auto white balance.
00657  * @return true if white balance is enabled, false otherwise
00658  */
00659 bool
00660 FirewireCamera::auto_white_balance()
00661 {
00662   return _auto_white_balance;
00663 }
00664 
00665 
00666 /** Get white balance values.
00667  * @param ub contains U/B value upon return
00668  * @param vr contains V/R value upon return
00669  */
00670 void
00671 FirewireCamera::white_balance(unsigned int *ub, unsigned int *vr)
00672 {
00673   if ( dc1394_feature_whitebalance_get_value(_camera, &_white_balance_ub, &_white_balance_vr) != DC1394_SUCCESS ) {
00674     throw Exception("Failed to retrieve white balance values");
00675   }
00676 
00677   *ub = _white_balance_ub;
00678   *vr = _white_balance_vr;
00679 }
00680 
00681 
00682 /** Set white balance values.
00683  * @param ub U/B value
00684  * @param vr V/R value
00685  */
00686 void
00687 FirewireCamera::set_white_balance(unsigned int ub, unsigned int vr)
00688 {
00689   if ( dc1394_feature_whitebalance_set_value(_camera, ub, vr) != DC1394_SUCCESS ) {
00690     throw Exception("Failed to set white balance to ub=%d vr=%d", ub, vr);
00691   }
00692 }
00693 
00694 /** Set the gain.
00695  * @param gain the gain value
00696  */
00697 void
00698 FirewireCamera::set_gain(unsigned int gain)
00699 {
00700   uint32_t min;
00701   uint32_t max;
00702   if ( dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_GAIN, &min, &max) != DC1394_SUCCESS ) {
00703     throw Exception("Failed to get boundaries for feature gain");
00704   }
00705   if (gain < min) {
00706     gain = min;
00707   }
00708   if (max < gain) {
00709     gain = max;
00710   }
00711   if ( dc1394_feature_set_mode( _camera, DC1394_FEATURE_GAIN, DC1394_FEATURE_MODE_MANUAL ) != DC1394_SUCCESS ) {
00712     throw Exception("Failed to set manual mode for feature gain");
00713   }
00714   if ( dc1394_feature_set_value( _camera, DC1394_FEATURE_GAIN, gain ) != DC1394_SUCCESS) {
00715     throw Exception("Failed to set value for feature gain");
00716   }
00717 }
00718 
00719 /** Parse focus and set value.
00720  * Parses the given string for a valid focus value and sets it.
00721  * @param focus string representation of value
00722  */
00723 void
00724 FirewireCamera::parse_set_focus(const char *focus)
00725 {
00726   string f = focus;
00727   if ( f == "auto" ) {
00728     _auto_focus = true;
00729   } else if ( f == "manual" ) {
00730     _auto_focus = false;
00731   } else {
00732     char *endptr = NULL;
00733     long int focus = strtol(f.c_str(), &endptr, 10);
00734     if ( endptr[0] != 0 ) {
00735       throw TypeMismatchException("Focus value is invalid. String to int conversion failed");
00736     } else if ( focus < 0 ) {
00737       throw OutOfBoundsException("'Focus value < 0", focus, 0, 0xFFFFFFFF);
00738     }
00739     _auto_focus = false;
00740     _focus = focus;
00741     _do_set_focus = true;
00742   }
00743 }
00744 
00745 
00746 /** Parse white balance and set value.
00747  * Parses the given string for a valid white balance value and sets it.
00748  * @param white_balance string representation of value
00749  */
00750 void
00751 FirewireCamera::parse_set_white_balance(const char *white_balance)
00752 {
00753   string w = white_balance;
00754   if ( w == "auto" ) {
00755     _auto_white_balance = true;
00756   } else {
00757     // try to parse U/V values
00758     string::size_type commapos = w.find(",", 0);
00759     if ( commapos == string::npos ) {
00760       throw Exception("Illegal white balance value, neither auto and no comma found");
00761     }
00762     string ub = w.substr(0, commapos);
00763     string vr = w.substr(commapos + 1);
00764     char *endptr;
00765     long int ub_i = strtol(ub.c_str(), &endptr, 10);
00766     if ( endptr[0] != 0 ) {
00767       throw TypeMismatchException("White balance value for U/B is invalid. "
00768                                   "String to int conversion failed");
00769     } else if ( ub_i < 0 ) {
00770       throw OutOfBoundsException("White balance value for U/B < 0", ub_i, 0, 0xFFFFFFFF);
00771     }
00772     long int vr_i = strtol(vr.c_str(), &endptr, 10);
00773     if ( endptr[0] != 0 ) {
00774       throw TypeMismatchException("White balance value for V/R is invalid. "
00775                                   "String to int conversion failed");
00776     } else if ( vr_i < 0 ) {
00777       throw OutOfBoundsException("White balance value for V/R < 0", vr_i, 0, 0xFFFFFFFF);
00778     }
00779 
00780     _auto_white_balance = false;
00781     _white_balance_ub = ub_i;
00782     _white_balance_vr = vr_i;
00783     _do_set_white_balance = true;
00784   }
00785 }
00786 
00787 
00788 /** Parse shutter and set value.
00789  * Parses the given string for a valid shutter value and sets it.
00790  * @param shutter string representation of value
00791  */
00792 void
00793 FirewireCamera::parse_set_shutter(const char *shutter)
00794 {
00795   string s = shutter;
00796   if ( s == "auto" ) {
00797     _auto_shutter = true;
00798   } else {
00799     char *endptr;
00800     long int tmp = strtol(s.c_str(), &endptr, 10);
00801     if ( endptr[0] != '\0' ) {
00802       throw TypeMismatchException("Shutter value is invalid. "
00803                                   "String to int conversion failed");
00804     } else if ( tmp < 0 ) {
00805       throw OutOfBoundsException("Shutter value < 0", tmp, 0, 0xFFFFFFFF);
00806     }
00807     _auto_shutter = false;
00808     _shutter = tmp;
00809     _do_set_shutter = true;
00810   }
00811 }
00812 
00813 /** Constructor.
00814  * Initialize and take parameters from camera argument parser. The following
00815  * arguments are supported:
00816  * - mode=MODE where MODE is one of
00817  *   - 640x480_YUV422
00818  *   - 640x480_MONO16
00819  *   - FORMAT7_0
00820  *   - FORMAT7_1
00821  *   - FORMAT7_2
00822  *   - FORMAT7_3
00823  *   - FORMAT7_4
00824  *   - FORMAT7_5
00825  *   - FORMAT7_6
00826  *   - FORMAT7_7
00827  * - coding=CODING, color coding for Format7, CODING is one of:
00828  *   - YUV422
00829  *   - MONO8
00830  *   - MONO16
00831  *   - RAW16
00832  * - isospeed=SPEED, ISO speed, SPEED is one of:
00833  *   - 400
00834  *   - 800
00835  * - framerate=FPS, desired rate in frames per second, FPS is one of:
00836  *   - 15
00837  *   - 30
00838  *   - 60
00839  *   - 120
00840  * - nbufs=NBUFS, number of DMA buffers, integer, 0 < n <= 32
00841  * - width=WIDTH, width in pixels of Format7 ROI
00842  * - height=HEIGHT, height in pixels of Format7 ROI
00843  * - startx=STARTX, X start of Format7 ROI
00844  * - starty=STARTY, Y start of Format7 ROI
00845  * - packetsize=BYTES, packet size in BYTES
00846  * - white_balance=(auto|U,V), white balance value, either auto for auto white balance
00847  *                             or U/B and V/R values for adjustment
00848  * - shutter=auto, determine the shutter time automatically
00849  * - focus=MODE, MODE is either auto for auto focus, manual for manual focus without
00850  *               actually setting (for example set from external application) or a
00851  *               number for the focus.
00852  * @param cap camera argument parser
00853  */
00854 FirewireCamera::FirewireCamera(const CameraArgumentParser *cap)
00855 {
00856   _started = _opened = false;
00857   _valid_frame_received = false;
00858   _auto_focus = true; // assume auto_focus, checked in open()
00859   _auto_shutter = false;
00860   _auto_white_balance = false;
00861   _white_balance_ub = 0xFFFFFFFF;
00862   _white_balance_vr = 0xFFFFFFFF;
00863   _do_set_shutter = false;
00864   _do_set_white_balance = false;
00865   _do_set_focus = false;
00866 
00867   // Defaults
00868   _mode = DC1394_VIDEO_MODE_640x480_YUV422;
00869   _speed = DC1394_ISO_SPEED_400;
00870   _framerate = DC1394_FRAMERATE_15;
00871   _camera = NULL;
00872   _dc1394 = NULL;
00873   _format7_mode_enabled = false;
00874   _format7_width = _format7_height = _format7_startx = _format7_starty = 0;
00875   _format7_bpp = 4096;
00876   _model = strdup(cap->cam_id().c_str());
00877   _num_buffers = 8;
00878   _shutter = 0;
00879   _auto_gain = true;
00880   _gain = 0;
00881 
00882   if ( cap->has("mode") ) {
00883     string m = cap->get("mode");
00884     if ( m == "640x480_MONO16" ) {
00885       _mode = DC1394_VIDEO_MODE_640x480_MONO16;
00886     } else if ( m == "FORMAT7_0" ) {
00887       _mode = DC1394_VIDEO_MODE_FORMAT7_0;
00888       _format7_mode_enabled = true;
00889     } else if ( m == "FORMAT7_1" ) {
00890       _mode = DC1394_VIDEO_MODE_FORMAT7_1;
00891       _format7_mode_enabled = true;
00892     } else if ( m == "FORMAT7_2" ) {
00893       _mode = DC1394_VIDEO_MODE_FORMAT7_2;
00894       _format7_mode_enabled = true;
00895     } else if ( m == "FORMAT7_3" ) {
00896       _mode = DC1394_VIDEO_MODE_FORMAT7_3;
00897       _format7_mode_enabled = true;
00898     } else if ( m == "FORMAT7_4" ) {
00899       _mode = DC1394_VIDEO_MODE_FORMAT7_4;
00900       _format7_mode_enabled = true;
00901     } else if ( m == "FORMAT7_5" ) {
00902       _mode = DC1394_VIDEO_MODE_FORMAT7_5;
00903       _format7_mode_enabled = true;
00904     } else if ( m == "FORMAT7_6" ) {
00905       _mode = DC1394_VIDEO_MODE_FORMAT7_6;
00906       _format7_mode_enabled = true;
00907     } else if ( m == "FORMAT7_7" ) {
00908       _mode = DC1394_VIDEO_MODE_FORMAT7_7;
00909       _format7_mode_enabled = true;
00910     }
00911   }
00912   if ( cap->has("coding") ) {
00913     string c = cap->get("coding");
00914     if ( c == "YUV422" ) {
00915       _format7_coding = DC1394_COLOR_CODING_YUV422;
00916     } else if ( c == "MONO8" ) {
00917       _format7_coding = DC1394_COLOR_CODING_MONO8;
00918     } else if ( c == "MONO16" ) {
00919       _format7_coding = DC1394_COLOR_CODING_MONO16;
00920     } else if ( c == "RAW16" ) {
00921       _format7_coding = DC1394_COLOR_CODING_RAW16;
00922     }
00923   }
00924   if ( cap->has("isospeed") ) {
00925     string s = cap->get("isospeed");
00926     if ( s == "400" ) {
00927       _speed = DC1394_ISO_SPEED_400;
00928     } else if ( s == "800" ) {
00929       _speed = DC1394_ISO_SPEED_800;
00930     }
00931   }
00932   if ( cap->has("framerate") ) {
00933     string f = cap->get("framerate");
00934     if ( f == "1.875" ) {
00935       _framerate = DC1394_FRAMERATE_1_875;
00936     } else if ( f == "3.75" ) {
00937       _framerate = DC1394_FRAMERATE_3_75;
00938     } else if ( f == "7.5" ) {
00939       _framerate = DC1394_FRAMERATE_7_5;
00940     } else if ( f == "15" ) {
00941       _framerate = DC1394_FRAMERATE_15;
00942     } else if ( f == "30" ) {
00943       _framerate = DC1394_FRAMERATE_30;
00944     } else if ( f == "60" ) {
00945       _framerate = DC1394_FRAMERATE_60;
00946     } else if ( f == "120" ) {
00947       _framerate = DC1394_FRAMERATE_120;
00948     } else if ( f == "240" ) {
00949       _framerate = DC1394_FRAMERATE_240;
00950     }
00951   }
00952   if ( cap->has("focus") ) {
00953     parse_set_focus(cap->get("focus").c_str());
00954   }
00955   if ( cap->has("nbufs") ) {
00956     _num_buffers = atoi(cap->get("nbufs").c_str());
00957   }
00958   if ( cap->has("width") ) {
00959     _format7_width = atoi(cap->get("width").c_str());
00960   }
00961   if ( cap->has("height") ) {
00962     _format7_height = atoi(cap->get("height").c_str());
00963   }
00964   if ( cap->has("startx") ) {
00965     _format7_startx = atoi(cap->get("startx").c_str());
00966   }
00967   if ( cap->has("starty") ) {
00968     _format7_starty = atoi(cap->get("starty").c_str());
00969   }
00970   if ( cap->has("packetsize") ) {
00971     string p = cap->get("packetsize");
00972     if ( p == "recommended" ) {
00973       _format7_bpp = 0;
00974     } else {
00975       _format7_bpp = atoi(p.c_str());
00976     }
00977   }
00978   if ( cap->has("gain") ) {
00979     string g = cap->get("gain");
00980     if ( g != "auto" ) {
00981       _gain = atoi(g.c_str());
00982       _auto_gain = false;
00983     }
00984   }
00985   if ( cap->has("white_balance") ) {
00986     parse_set_white_balance(cap->get("white_balance").c_str());
00987   }
00988   if ( cap->has("shutter") ) {
00989     parse_set_shutter(cap->get("shutter").c_str());
00990   }
00991 }
00992 
00993 
00994 /** Print list of cameras.
00995  * Prints a list of available cameras to stdout.
00996  */
00997 void
00998 FirewireCamera::print_available_fwcams()
00999 {
01000 
01001   dc1394_t *dc1394 = dc1394_new();
01002   dc1394camera_list_t *list;
01003   dc1394error_t        err;
01004   if ( (err = dc1394_camera_enumerate(dc1394, &list)) != DC1394_SUCCESS ) {
01005     throw Exception("Could not enumerate cameras: %s", dc1394_error_get_string(err));
01006   }
01007 
01008   if (list->num > 0) {
01009     for (unsigned int i = 0; i < list->num; ++i) {
01010       dc1394camera_t *tmpcam = dc1394_camera_new(dc1394, list->ids[i].guid);
01011       dc1394_camera_print_info(tmpcam, stdout);
01012       dc1394_camera_free(tmpcam);
01013     }
01014   } else {
01015     printf("Could not find any cameras\n");
01016   }
01017 }
01018 
01019 } // end namespace firevision