ViSP  3.0.0
grabDirectShowMulti.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Acquire images using DirectShow (under Windows only) and display it
32  * using GTK or GDI.
33  *
34  * Authors:
35  * Bruno Renier
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
40 
41 #include <visp3/core/vpConfig.h>
42 #include <visp3/core/vpDebug.h>
43 
51 #include <vector>
52 
53 #include <iostream>
54 #include <sstream>
55 
56 
57 #if defined (VISP_HAVE_DIRECTSHOW)
58 #if (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
59 
60 #include <visp3/sensor/vpDirectShowGrabber.h>
61 #include <visp3/core/vpImage.h>
62 #include <visp3/io/vpImageIo.h>
63 #include <visp3/gui/vpDisplayGTK.h>
64 #include <visp3/gui/vpDisplayGDI.h>
65 #include <visp3/io/vpParseArgv.h>
66 #include <visp3/core/vpTime.h>
67 
68 
69 // List of allowed command line options
70 //#define GETOPTARGS "dhn:o:"
71 #define GETOPTARGS "c:df:hmn:io:st:?"
72 
73 #define GRAB_COLOR
74 
86 void usage(const char *name, const char *badparam, unsigned int camera, unsigned int &nframes,
87  std::string &opath)
88 {
89  if (badparam)
90  fprintf(stderr, "\nERREUR: Bad parameter [%s]\n", badparam);
91 
92  fprintf(stdout, "\n\
93 Acquire images using DirectShow (under Windows only) and display\n\
94 it using GTK or the windows GDI if GTK is not available.\n\
95 For a given camera, mediatype (or video mode) as well as framerate\n\
96 can be set.\n\
97 If more than one camera is connected, this example allows also to \n\
98 acquire images from all the cameras.\n\
99 \n\
100 SYNOPSIS\n\
101 %s [-t <mediatype>] [-f <framerate>] \n\
102  [-c <camera id>] [-m] [-n <frames>] [-i] [-s] [-d] \n\
103  [-o <filename>] [-h]\n\
104  \n\
105 OPTIONS Default\n\
106  -t [%%u] \n\
107  MediaType (or video mode) to set for the active \n\
108  camera. Use -s option so see which are the supported \n\
109  Mediatypes. You can select the active camera \n\
110  using -c option.\n\
111 \n\
112  -f [%%d] \n\
113  Framerate to set for the active camera.\n\
114  You can select the active camera using -c option.\n",
115  name);
116 
117  fprintf(stdout, "\n\
118  -c [%%u] %u\n\
119  Active camera identifier.\n\
120  Zero is for the first camera found on the bus.\n\
121 \n\
122  -m \n\
123  Flag to active multi camera acquisition. \n\
124  You need at least two cameras connected on the bus.\n\
125 \n\
126  -n [%%u] %u\n\
127  Number of frames to acquire.\n\
128 \n\
129  -i \n\
130  Flag to print camera information.\n\
131 \n\
132  -s \n\
133  Print camera settings capabilities such as MediaType \n\
134  and sizes available and exit.\n\
135 \n\
136  -d \n\
137  Flag to turn off image display.\n\
138 \n\
139  -o [%%s] \n\
140  Filename for image saving. \n\
141  Example: -o %s\n\
142  The first %%d is for the camera id, %%04d\n\
143  is for the image numbering.\n\
144 \n\
145  -h \n\
146  Print the help.\n\
147 \n",
148  camera, nframes, opath.c_str());
149 
150  exit(0);
151 }
152 
178 void read_options(int argc, const char **argv, bool &multi, unsigned int &camera,
179  unsigned int &nframes, bool &verbose_info,
180  bool &verbose_settings,
181  bool &mediatype_is_set,
182  unsigned int &mediatypeID,
183  bool &framerate_is_set,
184  double &framerate,
185  bool &display, bool &save, std::string &opath)
186 {
187  const char *optarg;
188  int c;
189  /*
190  * Lecture des options.
191  */
192 
193  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS,&optarg)) > 1) {
194  switch (c) {
195  case 'c':
196  camera = atoi(optarg); break;
197  case 'd':
198  display = false; break;
199  case 'f':
200  framerate_is_set = true;
201  framerate = atoi(optarg); break;
202  case 'i':
203  verbose_info = true; break;
204  case 'm':
205  multi = true; break;
206  case 'n':
207  nframes = atoi(optarg); break;
208  case 'o':
209  save = true;
210  opath = optarg; break;
211  case 's':
212  verbose_settings = true; break;
213  case 't':
214  mediatype_is_set = true;
215  mediatypeID = atoi(optarg); break;
216  default:
217  usage(argv[0], NULL, camera, nframes, opath);
218  break;
219  }
220  }
221 
222  if ((c == 1) || (c == -1)) {
223  // standalone param or error
224  usage(argv[0], NULL, camera, nframes, opath);
225  std::cerr << "ERROR: " << std::endl;
226  std::cerr << " Bad argument " << optarg << std::endl << std::endl;
227  }
228 }
229 
230 
239 int
240 main(int argc, const char ** argv)
241 {
242  try {
243  unsigned int camera = 0;
244  bool multi = false;
245  bool verbose_info = false;
246  bool verbose_settings = false;
247  bool display = true;
248  unsigned int nframes = 50;
249  bool mediatype_is_set = false;
250  unsigned int mediatypeID;
251  bool framerate_is_set = false;
252  double framerate;
253  bool save = false;
254 
255 #ifdef GRAB_COLOR
256  vpImage<vpRGBa> *I;
257  std::string opath = "C:/temp/I%d-%04d.ppm";
258 #else
260  std::string opath = "C:/temp/I%d-%04d.pgm";
261 #endif
262 #if defined VISP_HAVE_GDI
263  vpDisplayGDI *d;
264 #elif defined VISP_HAVE_GTK
265  vpDisplayGTK *d;
266 #endif
267  read_options(argc, argv, multi, camera, nframes,
268  verbose_info, verbose_settings,
269  mediatype_is_set, mediatypeID,
270  framerate_is_set, framerate,
271  display, save, opath);
272 
273  // Number of cameras connected on the bus
275  g = new vpDirectShowGrabber();
276  unsigned int ncameras = g->getDeviceNumber();
277  // Check the consistancy of the options
278  if (multi) {
279  // ckeck if two cameras are connected
280  if (ncameras < 2) {
281  std::cout << "You have only " << ncameras << " camera connected on the bus." << std::endl;
282  std::cout << "It is not possible to active multi-camera acquisition." << std::endl;
283  std::cout << "Disable -m command line option, or connect an other " << std::endl;
284  std::cout << "cameras on the bus." << std::endl;
285  g->close();
286  return(0);
287  }
288  }
289  if (camera >= ncameras) {
290  std::cout << "You have only " << ncameras;
291  std::cout << " camera connected on the bus." << std::endl;
292  std::cout << "It is not possible to select camera " << camera << std::endl;
293  std::cout << "Check your -c <camera> command line option." << std::endl;
294  g->close();
295  return(0);
296  }
297  if (multi) {
298  camera = 0; // to over write a bad option usage
299  //reinitialize the grabbers with the right number of devices (one grabber per device)
300  delete g;
301  g = new vpDirectShowGrabber[ncameras];
302  for(unsigned int i=0; i<ncameras ; i++)
303  {
304  g[i].open();
305  }
306 
307  }
308  else {
309  ncameras = 1; // acquisition from only one camera
310  delete g;
311  g = new vpDirectShowGrabber[1];
312  g[0].open();
313  g[0].setDevice(camera);
314 
315  }
316 
317  // allocate an image and display for each camera to consider
318 #ifdef GRAB_COLOR
319  I = new vpImage<vpRGBa> [ncameras];
320 #else
321  I = new vpImage<unsigned char> [ncameras];
322 #endif
323  if (display)
324 
325 #ifdef VISP_HAVE_GDI
326  d = new vpDisplayGDI [ncameras];
327 #else
328  d = new vpDisplayGTK [ncameras];
329 #endif
330  // If required modify camera settings
331 
332  if (mediatype_is_set) {
333  g[0].setMediaType(mediatypeID);
334  }
335  else {
336  // get The actual video mode
337  mediatypeID = g[0].getMediaType();
338  }
339  if (framerate_is_set) {
340  for(unsigned int i=0; i<ncameras ; i++)
341  {
342  unsigned int c;
343  if (multi) c = i;
344  else c = camera;
345  std::cout<<"camera " << c <<std::endl;
346  if (!g[i].setFramerate(framerate))
347  std::cout << "Set Framerate failed !!" <<std::endl<< std::endl;
348  }
349  }
350 
351 
352  unsigned int width;
353  unsigned int height;
354  // Display information for each camera
355  if (verbose_info || verbose_settings) {
356 
357  std::cout << "----------------------------------------------------------" << std::endl;
358  std::cout << "---- Device List : " << std::endl;
359  std::cout << "----------------------------------------------------------" << std::endl;
360  g[0].displayDevices();
361  for (unsigned i=0; i < ncameras; i ++) {
362  unsigned int c;
363  if (multi) c = i;
364  else c = camera;
365 
366  if (verbose_info){
367  g[i].getFormat(width, height, framerate);
368  std::cout << "----------------------------------------------------------"
369  << std::endl
370  << "---- MediaType and framerate currently used by device " << std::endl
371  << "---- (or camera) " << c << std::endl
372  << "---- Current MediaType : " << g[i].getMediaType() << std::endl
373  << "---- Current format : " << width <<" x "<< height <<" at "<< framerate << " fps" << std::endl
374  << "----------------------------------------------------------" << std::endl;
375  }
376  if (verbose_settings) {
377  std::cout << "----------------------------------------------------------"
378  << std::endl
379  << "---- MediaTypes supported by device (or camera) "
380  << c << std::endl
381  << "---- One of the MediaType below can be set using " << std::endl
382  << "---- option -t <mediatype>."
383  << std::endl
384  << "----------------------------------------------------------"
385  << std::endl;
386  g[i].getStreamCapabilities();
387  }
388 
389  }
390  return 0;
391  }
392 
393 
394  // Do a first acquisition to initialise the display
395  for (unsigned int i=0; i < ncameras; i ++) {
396  // Acquire the first image
397  g[i].acquire(I[i]);
398  unsigned int c;
399  if (multi) c = i;
400  else c = camera;
401 
402  std::cout << "Image size for camera " << c << " : width: "
403  << I[i].getWidth() << " height: " << I[i].getHeight() << std::endl;
404 
405  if (display) {
406  // Initialise the display
407  char title[100];
408  sprintf(title, "Images captured by camera %u", c );
409  d[i].init(I[i], 100+i*50, 100+i*50, title) ;
410  }
411  }
412 
413  // Main loop for single or multi-camera acquisition and display
414  std::cout << "Capture in process..." << std::endl;
415 
416  double tbegin=0, tend=0, tloop=0, ttotal=0;
417 
418  ttotal = 0;
419  tbegin = vpTime::measureTimeMs();
420  for (unsigned i = 0; i < nframes; i++) {
421  for (unsigned c = 0; c < ncameras; c++) {
422  // Acquire an image
423  g[c].acquire(I[c]);
424  if (display) {
425  // Display the last image acquired
426  vpDisplay::display(I[c]);
427  vpDisplay::flush(I[c]);
428  }
429  if (save) {
430  char buf[FILENAME_MAX];
431  sprintf(buf, opath.c_str(), c, i);
432  std::string filename(buf);
433  std::cout << "Write: " << filename << std::endl;
434  vpImageIo::write(I[c], filename);
435  }
436  }
437  tend = vpTime::measureTimeMs();
438  tloop = tend - tbegin;
439  tbegin = tend;
440  std::cout << "loop time: " << tloop << " ms" << std::endl;
441  ttotal += tloop;
442  }
443 
444  std::cout << "Mean loop time: " << ttotal / nframes << " ms" << std::endl;
445  std::cout << "Mean frequency: " << 1000./(ttotal / nframes) << " fps" << std::endl;
446 
447  // Release the framegrabber
448  delete [] g;
449 
450  // Free memory
451  delete [] I;
452  if (display)
453  delete [] d;
454 
455  return 0;
456  }
457  catch(vpException e) {
458  std::cout << "Catch an exception: " << e << std::endl;
459  return 1;
460  }
461 }
462 #else // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
463 
464 int
465 main()
466 {
467  vpTRACE("GDI or GTK is not available...") ;
468 }
469 #endif // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
470 #else // defined (VISP_HAVE_DIRECTSHOW)
471 int
472 main()
473 {
474  vpTRACE("DirectShow is not available...") ;
475 }
476 #endif // defined (VISP_HAVE_DIRECTSHOW)
477 
static void write(const vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:472
void getFormat(unsigned int &width, unsigned int &height, double &framerate)
unsigned int getWidth() const
Definition: vpImage.h:161
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
bool setMediaType(int mediaTypeID)
error that can be emited by ViSP classes.
Definition: vpException.h:73
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
class for windows direct show devices
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2233
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:76
bool setDevice(unsigned int id)
#define vpTRACE
Definition: vpDebug.h:414
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
void acquire(vpImage< unsigned char > &I)
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:141
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:93
unsigned int getDeviceNumber()
unsigned int getHeight() const
Definition: vpImage.h:152