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