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