Fawkes API  Fawkes Development Version
firewire.cpp
1 
2 /***************************************************************************
3  * firewire.cpp - Implementation to access FW cam using libdc1394
4  *
5  * Generated: Tue Feb 22 13:28:08 2005
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/exception.h>
25 #include <core/exceptions/software.h>
26 #include <utils/system/console_colors.h>
27 
28 #include <cstdlib>
29 #include <unistd.h>
30 #include <climits>
31 #include <cstring>
32 
33 #include <fvcams/firewire.h>
34 #include <fvcams/cam_exceptions.h>
35 #include <fvutils/system/camargp.h>
36 
37 #include <dc1394/utils.h>
38 
39 using namespace std;
40 using namespace fawkes;
41 
42 namespace firevision {
43 #if 0 /* just to make Emacs auto-indent happy */
44 }
45 #endif
46 
47 /** @class FirewireCamera <fvcams/firewire.h>
48  * Firewire camera.
49  * This camera implementation allows for access to IEEE1394 cameras via
50  * libdc1394.
51  * @author Tim Niemueller
52  */
53 
54 /** Constructor.
55  * @param framerate desired framerate
56  * @param mode desired mode
57  * @param speed IEEE 1394 speed
58  * @param num_buffers number of DMA buffers
59  */
60 FirewireCamera::FirewireCamera(dc1394framerate_t framerate,
61  dc1394video_mode_t mode,
62  dc1394speed_t speed,
63  int num_buffers)
64 {
65  _started = _opened = false;
66  _valid_frame_received = false;
67  _auto_focus = true; // assume auto_focus, checked in open()
68  _auto_shutter = false;
69  _auto_white_balance = false;
70  _speed = speed;
71  _num_buffers = num_buffers;
72  _mode = mode;
73  _framerate = framerate;
74  _white_balance_ub = 0xFFFFFFFF;
75  _white_balance_vr = 0xFFFFFFFF;
76  _format7_mode_enabled = false;
77  _format7_width = _format7_height = _format7_startx = _format7_starty = 0;
78  _format7_bpp = 4096;
79  _model = strdup("any");
80  _do_set_shutter = false;
81  _do_set_white_balance = false;
82  _do_set_focus = false;
83  _gain = 0;
84  _auto_gain = true;
85 
86  _dc1394 = NULL;
87  _camera = NULL;
88 
89  if ((mode == DC1394_VIDEO_MODE_640x480_YUV422) && (framerate == DC1394_FRAMERATE_30)) {
90  // cerr << "When in mode YUV422 @ 640x480 with more than 15 fps. Setting framerate to 15fps." << endl;
91  _framerate = DC1394_FRAMERATE_15;
92  }
93 }
94 
95 
96 /** Empty destructor. */
97 FirewireCamera::~FirewireCamera()
98 {
99  close();
100 
101  if ( _model != NULL ) {
102  free(_model);
103  }
104 }
105 
106 
107 /** Open the desired device.
108  * This only opens the device but does not do any initialization.
109  */
110 void
111 FirewireCamera::open_device()
112 {
113  _dc1394 = dc1394_new();
114  dc1394camera_list_t *list;
115 
116  if ( dc1394_camera_enumerate(_dc1394, &list) != DC1394_SUCCESS ) {
117  throw Exception("Could not enumerate cameras");
118  }
119 
120  if (list->num > 0) {
121  if ( strcmp(_model, "any") == 0 ) {
122  /* use the first camera found */
123  _camera = dc1394_camera_new(_dc1394, list->ids[0].guid);
124  if (! _camera) {
125  dc1394_free(_dc1394);
126  _dc1394 = NULL;
127  throw Exception("Could not create camera for first foiund camera");
128  }
129  } else {
130  _camera = NULL;
131  for (unsigned int i = 0; i < list->num; ++i) {
132  dc1394camera_t *tmpcam = dc1394_camera_new(_dc1394, list->ids[i].guid);
133  if ( strcmp(_model, tmpcam->model) == 0) {
134  // found desired camera
135  _camera = tmpcam;
136  break;
137  } else {
138  dc1394_camera_free(tmpcam);
139  }
140  }
141  if ( _camera == NULL ) {
142  throw Exception("Could not find camera with model %s", _model);
143  }
144  }
145  } else {
146  throw Exception("No cameras connected");
147  }
148 
149  _device_opened = true;
150 }
151 
152 void
153 FirewireCamera::open()
154 {
155  if (_opened) return;
156 
157  if (! _device_opened) {
158  open_device();
159  }
160 
161  dc1394error_t err;
162 
163  if ( iso_mode_enabled() ) {
164  dc1394_video_set_transmission(_camera, DC1394_OFF);
165  }
166  // These methods would cleanup the mess left behind by other processes,
167  // but as of now (libdc1394 2.0.0 rc9) this is not supported for the Juju stack
168  dc1394_iso_release_bandwidth(_camera, INT_MAX);
169  for (int channel = 0; channel < 64; ++channel) {
170  dc1394_iso_release_channel(_camera, channel);
171  }
172  // This is rude, but for now needed (Juju)...
173  //dc1394_reset_bus(_camera);
174 
175  if (_camera->bmode_capable > 0) {
176  dc1394_video_set_operation_mode(_camera, DC1394_OPERATION_MODE_1394B);
177  }
178  if ( //((err = dc1394_cleanup_iso_channels_and_bandwidth(_camera)) != DC1394_SUCCESS) ||
179  ((err = dc1394_video_set_iso_speed(_camera, _speed)) != DC1394_SUCCESS) ||
180  ((err = dc1394_video_set_mode(_camera, _mode)) != DC1394_SUCCESS) ||
181  ((err = dc1394_video_set_framerate(_camera, _framerate)) != DC1394_SUCCESS) ) {
182  throw Exception("Setting up the camera failed: %s", dc1394_error_get_string(err));
183  }
184 
185  if (_format7_mode_enabled) {
186  if (_format7_bpp == 0) {
187  uint32_t rps;
188  dc1394_format7_get_recommended_packet_size(_camera, _mode, &rps);
189  _format7_bpp = rps;
190  }
191 
192  if ( ((err = dc1394_format7_set_image_size(_camera, _mode, _format7_width, _format7_height)) != DC1394_SUCCESS) ||
193  ((err = dc1394_format7_set_image_position(_camera, _mode, _format7_startx, _format7_starty)) != DC1394_SUCCESS) ||
194  ((err = dc1394_format7_set_color_coding(_camera, _mode, _format7_coding)) != DC1394_SUCCESS) ||
195  ((err = dc1394_format7_set_packet_size(_camera, _mode, _format7_bpp)) != DC1394_SUCCESS) ) {
196  throw Exception("Could not setup Format7 parameters: %s", dc1394_error_get_string(err));
197  }
198  }
199 
200  set_auto_shutter(_auto_shutter);
201  if ( !_auto_shutter && _do_set_shutter ) {
202  set_shutter(_shutter);
203  }
204 
205  set_auto_focus(_auto_focus);
206  if ( ! _auto_focus && _do_set_focus ) {
207  set_focus(_focus);
208  }
209 
210  set_auto_white_balance(_auto_white_balance);
211  if ( ! _auto_white_balance &&
212  (_white_balance_ub != 0xFFFFFFFF) &&
213  (_white_balance_vr != 0xFFFFFFFF) &&
214  _do_set_white_balance ) {
215  set_white_balance(_white_balance_ub, _white_balance_vr);
216  }
217 
218  if ( !_auto_gain ) {
219  set_gain(_gain);
220  }
221 
222  _opened = true;
223 }
224 
225 
226 void
227 FirewireCamera::start()
228 {
229  if (_started) return;
230 
231  if (! _opened) {
232  throw Exception("FirewireCamera: Cannot start closed camera");
233  }
234 
235  dc1394error_t err;
236  if ( (err = dc1394_capture_setup(_camera, _num_buffers, DC1394_CAPTURE_FLAGS_DEFAULT )) != DC1394_SUCCESS ) {
237  dc1394_capture_stop(_camera);
238  throw Exception("FirewireCamera: Could not setup capture (%s)", dc1394_error_get_string(err));
239  }
240 
241  if ( (err = dc1394_video_set_transmission(_camera, DC1394_ON)) != DC1394_SUCCESS) {
242  // cout << cred << "Could not start video transmission" << cnormal << endl;
243  dc1394_capture_stop(_camera);
244  throw Exception("FirewireCamera: Could not start ISO transmission (%s)", dc1394_error_get_string(err));
245  }
246 
247  // Give it some time to be ready
248  usleep(500000);
249 
250  _started = true;
251 }
252 
253 
254 void
255 FirewireCamera::stop()
256 {
257  if (_camera) {
258  dc1394_video_set_transmission(_camera, DC1394_OFF);
259  dc1394_capture_stop(_camera);
260  }
261  _started = false;
262 }
263 
264 
265 /** Check if ISO mode is enabled.
266  * @return true if isochronous transfer is running, false otherwise.
267  * @exception Exception thrown if the transmission status could not be determined
268  */
269 bool
270 FirewireCamera::iso_mode_enabled()
271 {
272  dc1394switch_t status;
273  if ( dc1394_video_get_transmission(_camera, &status) != DC1394_SUCCESS) {
274  throw Exception("Could not get transmission status");
275  } else {
276  return (status == DC1394_ON);
277  }
278 }
279 
280 
281 void
282 FirewireCamera::print_info()
283 {
284  if (_opened) {
285  dc1394_camera_print_info( _camera, stdout );
286  }
287 
288  printf("Parameters:\n"
289  "valid frame received: %i\n"
290  "auto focus: %i\n"
291  "auto shutter: %i (shutter value: %u)\n"
292  "auto white balance: %i (white balance value %u/%u)\n"
293  "do set shutter: %i do set white balance: %i\n",
294  _valid_frame_received,_auto_focus,
295  _auto_shutter, _shutter,
296  _auto_white_balance, _white_balance_ub, _white_balance_vr,
297  _do_set_shutter = false, _do_set_white_balance = false
298  );
299 }
300 
301 
302 /** Get Firewire GUID of camera.
303  * @return IEEE1394 GUID
304  */
305 uint64_t
306 FirewireCamera::guid() const
307 {
308  if ( ! _opened ) {
309  throw Exception("Camera not opened");
310  }
311 
312  return _camera->guid;
313 }
314 
315 
316 /** Get camera model.
317  * @return string with the camera model name
318  */
319 const char *
320 FirewireCamera::model() const
321 {
322  if ( ! _opened ) {
323  throw Exception("Camera not opened");
324  }
325 
326  return _camera->model;
327 }
328 
329 
330 void
331 FirewireCamera::capture()
332 {
333 
334  if (! _opened) {
335  throw CaptureException("FirewireCamera(%s): cannot capture on closed camera", _model);
336  }
337  if (! _started) {
338  throw CaptureException("FirewireCamera(%s): cannot capture on stopped camera", _model);
339  }
340 
341  if (! iso_mode_enabled()) {
342  throw CaptureException("FirewireCamera(%s): isochronous transfer not active", _model);
343  }
344 
345  dc1394error_t err;
346  if (DC1394_SUCCESS != (err = dc1394_capture_dequeue(_camera, DC1394_CAPTURE_POLICY_WAIT, &_frame))) {
347  _valid_frame_received = false;
348  throw CaptureException("FireWireCamera(%s): capture failed (%s)",
349  _model, dc1394_error_get_string(err));
350  } else {
351  _valid_frame_received = (_frame != NULL);
352  }
353 }
354 
355 
356 void
357 FirewireCamera::flush()
358 {
359  capture();
360  // HACK, needed or we will get kernel NULL pointer exception *urgh*
361  usleep(100000);
362  dispose_buffer();
363 }
364 
365 
366 unsigned char*
367 FirewireCamera::buffer()
368 {
369  if ( _valid_frame_received ) {
370  return _frame->image;
371  } else {
372  return NULL;
373  }
374 }
375 
376 
377 unsigned int
378 FirewireCamera::buffer_size()
379 {
380  if ( _valid_frame_received ) {
381  return _frame->total_bytes;
382  } else {
383  return 0;
384  }
385 }
386 
387 void
388 FirewireCamera::close()
389 {
390  if ( _started ) stop();
391  if ( _opened ) {
392  if (_camera) dc1394_camera_free( _camera );
393  if (_dc1394) dc1394_free(_dc1394);
394  _camera = NULL;
395  _dc1394 = NULL;
396  _opened = false;
397  }
398 }
399 
400 
401 void
402 FirewireCamera::dispose_buffer()
403 {
404  if ( _valid_frame_received ) {
405  dc1394_capture_enqueue( _camera, _frame );
406  }
407 }
408 
409 
410 unsigned int
411 FirewireCamera::pixel_width()
412 {
413  if (_opened) {
414  if ( _valid_frame_received ) {
415  return _frame->size[0];
416  } else {
417  unsigned int width, height;
418  dc1394error_t err;
419  if ((err = dc1394_get_image_size_from_video_mode(_camera, _mode, &width, &height)) != DC1394_SUCCESS) {
420  throw Exception("FirewireCamera(%s): cannot get width (%s)", _model,
421  dc1394_error_get_string(err));
422  }
423  return width;
424  }
425  } else {
426  throw Exception("Camera not opened");
427  }
428 }
429 
430 
431 unsigned int
432 FirewireCamera::pixel_height()
433 {
434  if (_opened) {
435  if ( _valid_frame_received ) {
436  return _frame->size[1];
437  } else {
438  unsigned int width, height;
439  dc1394error_t err;
440  if ((err = dc1394_get_image_size_from_video_mode(_camera, _mode, &width, &height)) != DC1394_SUCCESS) {
441  throw Exception("FirewireCamera(%s): cannot get width (%s)", _model,
442  dc1394_error_get_string(err));
443  }
444  return height;
445  }
446  } else {
447  throw Exception("Camera not opened");
448  }
449 }
450 
451 
452 colorspace_t
453 FirewireCamera::colorspace()
454 {
455  // this needs to be changed for different modes
456  switch (_mode) {
457  case DC1394_VIDEO_MODE_320x240_YUV422:
458  case DC1394_VIDEO_MODE_640x480_YUV422:
459  case DC1394_VIDEO_MODE_800x600_YUV422:
460  case DC1394_VIDEO_MODE_1024x768_YUV422:
461  case DC1394_VIDEO_MODE_1280x960_YUV422:
462  case DC1394_VIDEO_MODE_1600x1200_YUV422:
463  return YUV422_PACKED;
464 
465  case DC1394_VIDEO_MODE_640x480_YUV411:
466  return YUV411_PACKED;
467 
468 
469  case DC1394_VIDEO_MODE_640x480_RGB8:
470  case DC1394_VIDEO_MODE_800x600_RGB8:
471  case DC1394_VIDEO_MODE_1024x768_RGB8:
472  case DC1394_VIDEO_MODE_1280x960_RGB8:
473  case DC1394_VIDEO_MODE_1600x1200_RGB8:
474  return RGB;
475 
476  case DC1394_VIDEO_MODE_640x480_MONO8:
477  case DC1394_VIDEO_MODE_800x600_MONO8:
478  case DC1394_VIDEO_MODE_1024x768_MONO8:
479  case DC1394_VIDEO_MODE_1280x960_MONO8:
480  case DC1394_VIDEO_MODE_1600x1200_MONO8:
481  return MONO8;
482 
483  case DC1394_VIDEO_MODE_640x480_MONO16:
484  case DC1394_VIDEO_MODE_800x600_MONO16:
485  case DC1394_VIDEO_MODE_1024x768_MONO16:
486  case DC1394_VIDEO_MODE_1280x960_MONO16:
487  case DC1394_VIDEO_MODE_1600x1200_MONO16:
488  return MONO16;
489 
490  case DC1394_VIDEO_MODE_FORMAT7_0:
491  case DC1394_VIDEO_MODE_FORMAT7_1:
492  case DC1394_VIDEO_MODE_FORMAT7_2:
493  case DC1394_VIDEO_MODE_FORMAT7_3:
494  case DC1394_VIDEO_MODE_FORMAT7_4:
495  case DC1394_VIDEO_MODE_FORMAT7_5:
496  case DC1394_VIDEO_MODE_FORMAT7_6:
497  case DC1394_VIDEO_MODE_FORMAT7_7:
498  switch (_format7_coding) {
499  case DC1394_COLOR_CODING_MONO8:
500  return MONO8;
501  case DC1394_COLOR_CODING_YUV411:
502  return YUV411_PACKED;
503  case DC1394_COLOR_CODING_YUV422:
504  return YUV422_PACKED;
505  case DC1394_COLOR_CODING_RGB8:
506  return RGB;
507  case DC1394_COLOR_CODING_MONO16:
508  return MONO16;
509  case DC1394_COLOR_CODING_RAW8:
510  return RAW8;
511  case DC1394_COLOR_CODING_RAW16:
512  return RAW16;
513  default:
514  return CS_UNKNOWN;
515  }
516  break;
517 
518  default:
519  return CS_UNKNOWN;
520  }
521 }
522 
523 
524 bool
525 FirewireCamera::ready()
526 {
527  return _started;
528 }
529 
530 
531 void
532 FirewireCamera::set_image_number(unsigned int n)
533 {
534 }
535 
536 
537 /* CAMERA CONTROL STUFF */
538 
539 void
540 FirewireCamera::set_auto_focus(bool enabled)
541 {
542  dc1394error_t err;
543  if ((err = dc1394_feature_set_mode(_camera, DC1394_FEATURE_FOCUS,
544  enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
545  == DC1394_SUCCESS) {
546  _auto_focus = enabled;
547  } else {
548  throw Exception("FirewireCamera(%s): Setting auto focus failed (%s)", _model,
549  dc1394_error_get_string(err));
550  }
551 }
552 
553 
554 bool
555 FirewireCamera::auto_focus()
556 {
557  return _auto_focus;
558 }
559 
560 
561 unsigned int
562 FirewireCamera::focus()
563 {
564  unsigned int focus = 0;
565  if (dc1394_feature_get_value(_camera, DC1394_FEATURE_FOCUS, &focus) == DC1394_SUCCESS) {
566  return focus;
567  } else {
568  return 0;
569  }
570 
571 }
572 
573 
574 void
575 FirewireCamera::set_focus(unsigned int focus)
576 {
577  dc1394_feature_set_value(_camera, DC1394_FEATURE_FOCUS, focus);
578 }
579 
580 
581 unsigned int
582 FirewireCamera::focus_min()
583 {
584  unsigned int min = 0;
585  unsigned int max = 0;
586  if (dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_FOCUS, &min, &max) == DC1394_SUCCESS) {
587  return min;
588  } else {
589  return 0;
590  }
591 }
592 
593 
594 unsigned int
595 FirewireCamera::focus_max()
596 {
597  unsigned int max = 0;
598  unsigned int min = 0;
599  if (dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_FOCUS, &min, &max) == DC1394_SUCCESS) {
600  return max;
601  } else {
602  return 0;
603  }
604 }
605 
606 
607 /** Set status of auto shutter.
608  * @param enabled true to enable auto shutter, false to disable.
609  */
610 void
611 FirewireCamera::set_auto_shutter(bool enabled)
612 {
613  if (dc1394_feature_set_mode(_camera, DC1394_FEATURE_SHUTTER,
614  enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL)
615  == DC1394_SUCCESS) {
616  _auto_shutter = enabled;
617  }
618 }
619 
620 
621 /** Get status of auto shutter.
622  * @return true if auto shutter is enabled, false otherwise
623  */
624 bool
625 FirewireCamera::auto_shutter()
626 {
627  return _auto_shutter;
628 }
629 
630 
631 /** Set shutter value.
632  * @param shutter shutter value
633  */
634 void
635 FirewireCamera::set_shutter(unsigned int shutter)
636 {
637  if ( dc1394_feature_set_value(_camera, DC1394_FEATURE_SHUTTER, shutter) != DC1394_SUCCESS ) {
638  throw Exception("Failed to set shutter to %d", shutter);
639  }
640 }
641 
642 
643 /** Get shutter value.
644  * @return the current shutter value
645  */
646 unsigned int
647 FirewireCamera::shutter()
648 {
649  if ( dc1394_feature_get_value(_camera, DC1394_FEATURE_SHUTTER, &_shutter) != DC1394_SUCCESS ) {
650  throw Exception("Failed to retrieve shutter value");
651  }
652 
653  return _shutter;
654 }
655 
656 
657 /** Set status of auto white balance.
658  * @param enabled true to enable auto white balance, false to disable.
659  */
660 void
661 FirewireCamera::set_auto_white_balance(bool enabled)
662 {
663  if (dc1394_feature_set_mode(_camera, DC1394_FEATURE_WHITE_BALANCE,
664  enabled ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL)
665  == DC1394_SUCCESS) {
666  _auto_white_balance = enabled;
667  }
668 }
669 
670 
671 /** Get status of auto white balance.
672  * @return true if white balance is enabled, false otherwise
673  */
674 bool
675 FirewireCamera::auto_white_balance()
676 {
677  return _auto_white_balance;
678 }
679 
680 
681 /** Get white balance values.
682  * @param ub contains U/B value upon return
683  * @param vr contains V/R value upon return
684  */
685 void
686 FirewireCamera::white_balance(unsigned int *ub, unsigned int *vr)
687 {
688  if ( dc1394_feature_whitebalance_get_value(_camera, &_white_balance_ub, &_white_balance_vr) != DC1394_SUCCESS ) {
689  throw Exception("Failed to retrieve white balance values");
690  }
691 
692  *ub = _white_balance_ub;
693  *vr = _white_balance_vr;
694 }
695 
696 
697 /** Set white balance values.
698  * @param ub U/B value
699  * @param vr V/R value
700  */
701 void
702 FirewireCamera::set_white_balance(unsigned int ub, unsigned int vr)
703 {
704  if ( dc1394_feature_whitebalance_set_value(_camera, ub, vr) != DC1394_SUCCESS ) {
705  throw Exception("Failed to set white balance to ub=%d vr=%d", ub, vr);
706  }
707 }
708 
709 /** Set the gain.
710  * @param gain the gain value
711  */
712 void
713 FirewireCamera::set_gain(unsigned int gain)
714 {
715  uint32_t min;
716  uint32_t max;
717  if ( dc1394_feature_get_boundaries(_camera, DC1394_FEATURE_GAIN, &min, &max) != DC1394_SUCCESS ) {
718  throw Exception("Failed to get boundaries for feature gain");
719  }
720  if (gain < min) {
721  gain = min;
722  }
723  if (max < gain) {
724  gain = max;
725  }
726  if ( dc1394_feature_set_mode( _camera, DC1394_FEATURE_GAIN, DC1394_FEATURE_MODE_MANUAL ) != DC1394_SUCCESS ) {
727  throw Exception("Failed to set manual mode for feature gain");
728  }
729  if ( dc1394_feature_set_value( _camera, DC1394_FEATURE_GAIN, gain ) != DC1394_SUCCESS) {
730  throw Exception("Failed to set value for feature gain");
731  }
732 }
733 
734 /** Parse focus and set value.
735  * Parses the given string for a valid focus value and sets it.
736  * @param focus string representation of value
737  */
738 void
739 FirewireCamera::parse_set_focus(const char *focus)
740 {
741  string f = focus;
742  if ( f == "auto" ) {
743  _auto_focus = true;
744  } else if ( f == "manual" ) {
745  _auto_focus = false;
746  } else {
747  char *endptr = NULL;
748  long int focus = strtol(f.c_str(), &endptr, 10);
749  if ( endptr[0] != 0 ) {
750  throw TypeMismatchException("Focus value is invalid. String to int conversion failed");
751  } else if ( focus < 0 ) {
752  throw OutOfBoundsException("'Focus value < 0", focus, 0, 0xFFFFFFFF);
753  }
754  _auto_focus = false;
755  _focus = focus;
756  _do_set_focus = true;
757  }
758 }
759 
760 
761 /** Parse white balance and set value.
762  * Parses the given string for a valid white balance value and sets it.
763  * @param white_balance string representation of value
764  */
765 void
766 FirewireCamera::parse_set_white_balance(const char *white_balance)
767 {
768  string w = white_balance;
769  if ( w == "auto" ) {
770  _auto_white_balance = true;
771  } else {
772  // try to parse U/V values
773  string::size_type commapos = w.find(",", 0);
774  if ( commapos == string::npos ) {
775  throw Exception("Illegal white balance value, neither auto and no comma found");
776  }
777  string ub = w.substr(0, commapos);
778  string vr = w.substr(commapos + 1);
779  char *endptr;
780  long int ub_i = strtol(ub.c_str(), &endptr, 10);
781  if ( endptr[0] != 0 ) {
782  throw TypeMismatchException("White balance value for U/B is invalid. "
783  "String to int conversion failed");
784  } else if ( ub_i < 0 ) {
785  throw OutOfBoundsException("White balance value for U/B < 0", ub_i, 0, 0xFFFFFFFF);
786  }
787  long int vr_i = strtol(vr.c_str(), &endptr, 10);
788  if ( endptr[0] != 0 ) {
789  throw TypeMismatchException("White balance value for V/R is invalid. "
790  "String to int conversion failed");
791  } else if ( vr_i < 0 ) {
792  throw OutOfBoundsException("White balance value for V/R < 0", vr_i, 0, 0xFFFFFFFF);
793  }
794 
795  _auto_white_balance = false;
796  _white_balance_ub = ub_i;
797  _white_balance_vr = vr_i;
798  _do_set_white_balance = true;
799  }
800 }
801 
802 
803 /** Parse shutter and set value.
804  * Parses the given string for a valid shutter value and sets it.
805  * @param shutter string representation of value
806  */
807 void
808 FirewireCamera::parse_set_shutter(const char *shutter)
809 {
810  string s = shutter;
811  if ( s == "auto" ) {
812  _auto_shutter = true;
813  } else {
814  char *endptr;
815  long int tmp = strtol(s.c_str(), &endptr, 10);
816  if ( endptr[0] != '\0' ) {
817  throw TypeMismatchException("Shutter value is invalid. "
818  "String to int conversion failed");
819  } else if ( tmp < 0 ) {
820  throw OutOfBoundsException("Shutter value < 0", tmp, 0, 0xFFFFFFFF);
821  }
822  _auto_shutter = false;
823  _shutter = tmp;
824  _do_set_shutter = true;
825  }
826 }
827 
828 /** Constructor.
829  * Initialize and take parameters from camera argument parser. The following
830  * arguments are supported:
831  * - mode=MODE where MODE is one of
832  * - 640x480_YUV422
833  * - 640x480_MONO16
834  * - FORMAT7_0
835  * - FORMAT7_1
836  * - FORMAT7_2
837  * - FORMAT7_3
838  * - FORMAT7_4
839  * - FORMAT7_5
840  * - FORMAT7_6
841  * - FORMAT7_7
842  * - coding=CODING, color coding for Format7, CODING is one of:
843  * - YUV422
844  * - MONO8
845  * - MONO16
846  * - RAW16
847  * - isospeed=SPEED, ISO speed, SPEED is one of:
848  * - 400
849  * - 800
850  * - framerate=FPS, desired rate in frames per second, FPS is one of:
851  * - 15
852  * - 30
853  * - 60
854  * - 120
855  * - nbufs=NBUFS, number of DMA buffers, integer, 0 < n <= 32
856  * - width=WIDTH, width in pixels of Format7 ROI
857  * - height=HEIGHT, height in pixels of Format7 ROI
858  * - startx=STARTX, X start of Format7 ROI
859  * - starty=STARTY, Y start of Format7 ROI
860  * - packetsize=BYTES, packet size in BYTES
861  * - white_balance=(auto|U,V), white balance value, either auto for auto white balance
862  * or U/B and V/R values for adjustment
863  * - shutter=auto, determine the shutter time automatically
864  * - focus=MODE, MODE is either auto for auto focus, manual for manual focus without
865  * actually setting (for example set from external application) or a
866  * number for the focus.
867  * @param cap camera argument parser
868  */
869 FirewireCamera::FirewireCamera(const CameraArgumentParser *cap)
870 {
871  _started = _opened = false;
872  _valid_frame_received = false;
873  _auto_focus = true; // assume auto_focus, checked in open()
874  _auto_shutter = false;
875  _auto_white_balance = false;
876  _white_balance_ub = 0xFFFFFFFF;
877  _white_balance_vr = 0xFFFFFFFF;
878  _do_set_shutter = false;
879  _do_set_white_balance = false;
880  _do_set_focus = false;
881 
882  // Defaults
883  _mode = DC1394_VIDEO_MODE_640x480_YUV422;
884  _speed = DC1394_ISO_SPEED_400;
885  _framerate = DC1394_FRAMERATE_15;
886  _camera = NULL;
887  _dc1394 = NULL;
888  _format7_mode_enabled = false;
889  _format7_width = _format7_height = _format7_startx = _format7_starty = 0;
890  _format7_bpp = 4096;
891  _model = strdup(cap->cam_id().c_str());
892  _num_buffers = 8;
893  _shutter = 0;
894  _auto_gain = true;
895  _gain = 0;
896 
897  if ( cap->has("mode") ) {
898  string m = cap->get("mode");
899  if ( m == "640x480_MONO16" ) {
900  _mode = DC1394_VIDEO_MODE_640x480_MONO16;
901  } else if ( m == "FORMAT7_0" ) {
902  _mode = DC1394_VIDEO_MODE_FORMAT7_0;
903  _format7_mode_enabled = true;
904  } else if ( m == "FORMAT7_1" ) {
905  _mode = DC1394_VIDEO_MODE_FORMAT7_1;
906  _format7_mode_enabled = true;
907  } else if ( m == "FORMAT7_2" ) {
908  _mode = DC1394_VIDEO_MODE_FORMAT7_2;
909  _format7_mode_enabled = true;
910  } else if ( m == "FORMAT7_3" ) {
911  _mode = DC1394_VIDEO_MODE_FORMAT7_3;
912  _format7_mode_enabled = true;
913  } else if ( m == "FORMAT7_4" ) {
914  _mode = DC1394_VIDEO_MODE_FORMAT7_4;
915  _format7_mode_enabled = true;
916  } else if ( m == "FORMAT7_5" ) {
917  _mode = DC1394_VIDEO_MODE_FORMAT7_5;
918  _format7_mode_enabled = true;
919  } else if ( m == "FORMAT7_6" ) {
920  _mode = DC1394_VIDEO_MODE_FORMAT7_6;
921  _format7_mode_enabled = true;
922  } else if ( m == "FORMAT7_7" ) {
923  _mode = DC1394_VIDEO_MODE_FORMAT7_7;
924  _format7_mode_enabled = true;
925  }
926  }
927  if ( cap->has("coding") ) {
928  string c = cap->get("coding");
929  if ( c == "YUV422" ) {
930  _format7_coding = DC1394_COLOR_CODING_YUV422;
931  } else if ( c == "MONO8" ) {
932  _format7_coding = DC1394_COLOR_CODING_MONO8;
933  } else if ( c == "MONO16" ) {
934  _format7_coding = DC1394_COLOR_CODING_MONO16;
935  } else if ( c == "RAW16" ) {
936  _format7_coding = DC1394_COLOR_CODING_RAW16;
937  }
938  }
939  if ( cap->has("isospeed") ) {
940  string s = cap->get("isospeed");
941  if ( s == "400" ) {
942  _speed = DC1394_ISO_SPEED_400;
943  } else if ( s == "800" ) {
944  _speed = DC1394_ISO_SPEED_800;
945  }
946  }
947  if ( cap->has("framerate") ) {
948  string f = cap->get("framerate");
949  if ( f == "1.875" ) {
950  _framerate = DC1394_FRAMERATE_1_875;
951  } else if ( f == "3.75" ) {
952  _framerate = DC1394_FRAMERATE_3_75;
953  } else if ( f == "7.5" ) {
954  _framerate = DC1394_FRAMERATE_7_5;
955  } else if ( f == "15" ) {
956  _framerate = DC1394_FRAMERATE_15;
957  } else if ( f == "30" ) {
958  _framerate = DC1394_FRAMERATE_30;
959  } else if ( f == "60" ) {
960  _framerate = DC1394_FRAMERATE_60;
961  } else if ( f == "120" ) {
962  _framerate = DC1394_FRAMERATE_120;
963  } else if ( f == "240" ) {
964  _framerate = DC1394_FRAMERATE_240;
965  }
966  }
967  if ( cap->has("focus") ) {
968  parse_set_focus(cap->get("focus").c_str());
969  }
970  if ( cap->has("nbufs") ) {
971  _num_buffers = atoi(cap->get("nbufs").c_str());
972  }
973  if ( cap->has("width") ) {
974  _format7_width = atoi(cap->get("width").c_str());
975  }
976  if ( cap->has("height") ) {
977  _format7_height = atoi(cap->get("height").c_str());
978  }
979  if ( cap->has("startx") ) {
980  _format7_startx = atoi(cap->get("startx").c_str());
981  }
982  if ( cap->has("starty") ) {
983  _format7_starty = atoi(cap->get("starty").c_str());
984  }
985  if ( cap->has("packetsize") ) {
986  string p = cap->get("packetsize");
987  if ( p == "recommended" ) {
988  _format7_bpp = 0;
989  } else {
990  _format7_bpp = atoi(p.c_str());
991  }
992  }
993  if ( cap->has("gain") ) {
994  string g = cap->get("gain");
995  if ( g != "auto" ) {
996  _gain = atoi(g.c_str());
997  _auto_gain = false;
998  }
999  }
1000  if ( cap->has("white_balance") ) {
1001  parse_set_white_balance(cap->get("white_balance").c_str());
1002  }
1003  if ( cap->has("shutter") ) {
1004  parse_set_shutter(cap->get("shutter").c_str());
1005  }
1006 }
1007 
1008 
1009 /** Print list of cameras.
1010  * Prints a list of available cameras to stdout.
1011  */
1012 void
1013 FirewireCamera::print_available_fwcams()
1014 {
1015 
1016  dc1394_t *dc1394 = dc1394_new();
1017  dc1394camera_list_t *list;
1018  dc1394error_t err;
1019  if ( (err = dc1394_camera_enumerate(dc1394, &list)) != DC1394_SUCCESS ) {
1020  throw Exception("Could not enumerate cameras: %s", dc1394_error_get_string(err));
1021  }
1022 
1023  if (list->num > 0) {
1024  for (unsigned int i = 0; i < list->num; ++i) {
1025  dc1394camera_t *tmpcam = dc1394_camera_new(dc1394, list->ids[i].guid);
1026  dc1394_camera_print_info(tmpcam, stdout);
1027  dc1394_camera_free(tmpcam);
1028  }
1029  } else {
1030  printf("Could not find any cameras\n");
1031  }
1032 }
1033 
1034 } // end namespace firevision
Fawkes library namespace.
Capturing a frame failed.
STL namespace.
Camera argument parser.
Definition: camargp.h:38
std::string cam_id() const
Get camera ID.
Definition: camargp.cpp:139
bool has(std::string s) const
Check if an parameter was given.
Definition: camargp.cpp:152
Base class for exceptions in Fawkes.
Definition: exception.h:36
Index out of bounds.
Definition: software.h:88
std::string get(std::string s) const
Get the value of the given parameter.
Definition: camargp.cpp:164