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