Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpDirectShowGrabberImpl.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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  * DirectShow framegrabber implementation.
32  *
33  * Authors:
34  * Bruno Renier
35  * Anthony Saunier
36  *
37  *****************************************************************************/
38 
39 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 
41 #include <visp3/core/vpConfig.h>
42 #if ( defined(VISP_HAVE_DIRECTSHOW) )
43 
44 #include <visp3/sensor/vpDirectShowGrabberImpl.h>
45 
46 vpDirectShowDevice * vpDirectShowGrabberImpl::deviceList = NULL;
47 unsigned int vpDirectShowGrabberImpl::nbDevices ;
48 
52 void vpDirectShowGrabberImpl::HRtoStr(std::string str)
53 {
54  TCHAR szErr[MAX_ERROR_TEXT_LEN];
55  DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
56 
57  if (res == 0) str = "Unknown Error: 0x%2x";
58 
59  char msg[MAX_ERROR_TEXT_LEN];
60  sprintf(msg,"%s",szErr);
61  str = msg;
62 }
63 
64 
69 vpDirectShowGrabberImpl::vpDirectShowGrabberImpl()
70 {
71  init = false ;
72  initCo = false ;
73  //COM initialization
74  if (FAILED(hr = CoInitializeEx(NULL,COINIT_MULTITHREADED)))
75  {
76  std::string err;
77  HRtoStr(err);
80  "Can't initialize COM\n"+ err));
81  }
82  initCo = true ;
83 
84  //create the device list
85  if(deviceList == NULL) {
86  CComPtr<IEnumMoniker> pVideoInputEnum = NULL;
87 
88  if(enumerate(pVideoInputEnum)) {
89  createDeviceList(pVideoInputEnum);
90  }
91  //not used anymore, so we release it
92  pVideoInputEnum.Release();
93  }
94 }
95 
100 void vpDirectShowGrabberImpl::open()
101 {
102  //create the device list
103  if(deviceList == NULL) {
104  CComPtr<IEnumMoniker> pVideoInputEnum = NULL;
105 
106  if(enumerate(pVideoInputEnum)) {
107  createDeviceList(pVideoInputEnum);
108  }
109  //not used anymore, so we release it
110  pVideoInputEnum.Release();
111  }
112 
113  init = initDirectShow();
114  if(! init )
115  {
116  std::string err;
117  HRtoStr(err);
120  }
121 }
126 void vpDirectShowGrabberImpl::open(vpImage<unsigned char> &I)
127 {
128  open();
129 }
130 
135 void vpDirectShowGrabberImpl::open(vpImage<vpRGBa> &I)
136 {
137  open();
138 }
139 
145 bool vpDirectShowGrabberImpl::initDirectShow()
146 {
147 
148 
149  //get the first working device's filter (unused and getdevice works on it)
150  currentDevice = getFirstUnusedDevice(pCapSource);
151 
152  if(currentDevice == nbDevices)
153  return false;
154 
155  //create the filter graph
156  if(!createGraph())
157  return false;
158 
159  //we add the capture source to the filter graph
160  if(FAILED(hr = pGraph->AddFilter(pCapSource, L"Capture Filter")))
161  return false;
162 
163  //we create a sample grabber
164  if(!createSampleGrabber(pGrabberFilter))
165  return false;
166 
167  //we add the grabber to the filter graph
168  if(FAILED(hr = pGraph->AddFilter(pGrabberFilter, L"SampleGrabber")))
169  return false;
170 
171  //we connect the pins
172  if(!connectSourceToGrabber(pCapSource, pGrabberFilter))
173  return false;
174 
175 
176  //get the current connected media type (needed by the callback)
177  if(FAILED(hr = pGrabberI->GetConnectedMediaType(&(sgCB.connectedMediaType))))
178  return false;
179 
180  //Gets the various graph's interfaces
181  CComPtr<IMediaFilter> pMediaFilter;
182 
183  pGraph->QueryInterface(IID_IMediaFilter, (void **)&pMediaFilter);
184  pGraph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&pControl));
185  pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
186 
187  pMediaFilter->SetSyncSource(NULL);
188  pMediaFilter.Release();
189 
190  return true;
191 }
192 
196 vpDirectShowGrabberImpl::~vpDirectShowGrabberImpl()
197 {
198  close();
199 }
200 
206 bool vpDirectShowGrabberImpl::enumerate(CComPtr<IEnumMoniker>& ppVideoInputEnum)
207 {
208  CComPtr<ICreateDevEnum> pDevEnum = NULL;
209  bool res = false;
210 
211  //Enumerate system devices
212  hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER);
213 
214  //if it is a success
215  if (SUCCEEDED(hr))
216  {
217  //Create a video input device enumerator
218  hr = pDevEnum->CreateClassEnumerator(
219  CLSID_VideoInputDeviceCategory,
220  &ppVideoInputEnum, 0);
221 
222  if(hr == S_OK) res = true;
223  }
224 
225 
226  pDevEnum.Release();
227  return res;
228 }
229 
230 
236 bool vpDirectShowGrabberImpl::createDeviceList(CComPtr<IEnumMoniker>& ppVideoInputEnum)
237 {
238  CComPtr<IMoniker> pMoniker[10]; //const max devices
239  unsigned long nbMoniker;
240 
241  ppVideoInputEnum->Reset();
242 
243  //Enumerates the different inputs
244  ppVideoInputEnum->Next(10, reinterpret_cast<IMoniker **>(&pMoniker), &nbMoniker);
245 
246  //if no input device
247  if(nbMoniker == 0) return false;
248 
249  deviceList = new vpDirectShowDevice[nbMoniker];
250 
251  nbDevices = (unsigned int)nbMoniker;
252 
253  //we try to get the properties of each moniker, if it fails, we skip to the next one and
254  //decrement the number of valid devices
255  unsigned int i=0;
256  unsigned int j=0;
257  while(i<nbDevices)
258  {
259  if(!deviceList[i].init(pMoniker[j]))
260  {
261  //if we can't get the device properties, skip to the next device
262  j++;
263  nbDevices--;
264  }
265  else
266  {
267  i++;
268  j++;
269  }
270  }
271 
272  //if no working input device
273  if(nbDevices == 0) return false;
274 
275  //we release the monikers
276  for(unsigned int i=0 ; i<nbMoniker ;i++)
277  {
278  pMoniker[i].Release();
279  }
280 
281  return true;
282 }
283 
284 
291 bool vpDirectShowGrabberImpl::getDevice(unsigned int n, CComPtr<IBaseFilter>& ppDevice)
292 {
293  //if n is invalid, quit
294  if(n>=nbDevices)
295  return false;
296 
297  //if the device is already in use, quit
298  if(deviceList[n].getState() == true)
299  return false;
300 
301  //if we can't enumerate the devices, quit
302  CComPtr<IEnumMoniker> pVideoInputEnum = NULL;
303  if(!enumerate(pVideoInputEnum))
304  return false;
305 
306  CComPtr<IMoniker> pMoniker = NULL;
307  bool deviceFound = false;
308 
309  //Enumerates the different inputs
310  while (pVideoInputEnum->Next(1, &pMoniker, NULL) == S_OK
311  && !deviceFound)
312  {
313  //implicit conversion should work ...
314  if(deviceList[n] == vpDirectShowDevice(pMoniker))
315  {
316  //we get the filter
317  if(SUCCEEDED(pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&ppDevice)))
318  {
319  //now the device is in use
320  deviceList[n].setInUse();
321  deviceFound = true;
322  }
323  else{ break; } //we can't get the device's filter, quit
324  }
325  pMoniker.Release();
326  }
327 
328  pVideoInputEnum.Release();
329 
330  return deviceFound;
331 }
332 
338 unsigned int vpDirectShowGrabberImpl::getFirstUnusedDevice(CComPtr<IBaseFilter>& ppDevice)
339 {
340  unsigned int n=0;
341  bool found=false;
342 
343  for(n=0;n<nbDevices && !found; n++)
344  {
345  //if the device is not being used
346  if(!deviceList[n].getState())
347  {
348  if(getDevice(n,ppDevice))
349  {
350  found = true;
351  deviceList[n].setInUse();
352  return n;
353  }
354  }
355  }
356 
357  return n;
358 }
359 
364 bool vpDirectShowGrabberImpl::createGraph()
365 {
366 
367  // Create the Capture Graph Builder.
368  hr = pBuild.CoCreateInstance(CLSID_CaptureGraphBuilder2, 0, CLSCTX_INPROC_SERVER);
369 
370  if (SUCCEEDED(hr))
371  {
372  // Create the Filter Graph Manager.
373  hr = pGraph.CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER);
374 
375  if (SUCCEEDED(hr))
376  {
377  // Initialize the Capture Graph Builder.
378  pBuild->SetFiltergraph(pGraph);
379 
380  return true;
381  }
382  }
383 
384  return false;
385 }
386 
392 bool vpDirectShowGrabberImpl::createSampleGrabber(CComPtr<IBaseFilter>& ppGrabberFilter)
393 {
394  //Creates the sample grabber
395  hr = ppGrabberFilter.CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER);
396 
397  if (FAILED(hr))
398  return false;
399 
400  //gets the SampleGrabber interface in order to configure it later
401  hr = ppGrabberFilter->QueryInterface(IID_ISampleGrabber,
402  reinterpret_cast<void**>(&pGrabberI));
403 
404  if (FAILED(hr))
405  return false;
406 
407  //configure the grabber
408  AM_MEDIA_TYPE mt;
409  ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
410 
411  mt.majortype = MEDIATYPE_Video;
412 
413  //ask for a connection
414  mt.subtype = MEDIATYPE_NULL;
415 
416  if(FAILED(hr = pGrabberI->SetMediaType(&mt)))
417  return false;
418 
419  //configure the callback of the grabber
420  pGrabberI->SetCallback(&sgCB,1);
421 
422  //grab only one frame at a time
423  pGrabberI->SetOneShot(TRUE);
424 
425  //no need to bufferize the sample in the grabber
426  pGrabberI->SetBufferSamples(false);
427 
428  return true;
429 }
430 
440 bool vpDirectShowGrabberImpl::checkSourceType(CComPtr<IPin>& pCapSourcePin)
441 {
442  //retrieves the connected media type
443  AM_MEDIA_TYPE mt;
444  if(FAILED (pCapSourcePin->ConnectionMediaType(&mt)))
445  return false;
446 
447  if(mt.majortype != MEDIATYPE_Video)
448  return false;
449 
450  //Known RGB formats
451  if(mt.subtype == MEDIASUBTYPE_ARGB32 ||
452  mt.subtype == MEDIASUBTYPE_RGB32 ||
453  mt.subtype == MEDIASUBTYPE_RGB24 ||
454  mt.subtype == MEDIASUBTYPE_RGB555 ||
455  mt.subtype == MEDIASUBTYPE_RGB565 ||
456  mt.subtype == MEDIASUBTYPE_RGB8 ||
457  mt.subtype == MEDIASUBTYPE_RGB4 ||
458  mt.subtype == MEDIASUBTYPE_RGB1 )
459  {
460  //image orientation will be handled "automatically"
461  sgCB.specialMediaType = false;
462  }
463  //Known YUV formats
464  else if(mt.subtype == MEDIASUBTYPE_AYUV ||
465  mt.subtype == MEDIASUBTYPE_UYVY ||
466  mt.subtype == MEDIASUBTYPE_Y411 ||
467  mt.subtype == MEDIASUBTYPE_Y41P ||
468  mt.subtype == MEDIASUBTYPE_Y211 ||
469  mt.subtype == MEDIASUBTYPE_YUY2 ||
470  mt.subtype == MEDIASUBTYPE_YVYU ||
471  mt.subtype == MEDIASUBTYPE_YUYV ||
472  mt.subtype == MEDIASUBTYPE_IF09 ||
473  mt.subtype == MEDIASUBTYPE_IYUV ||
474  mt.subtype == MEDIASUBTYPE_YV12 ||
475  mt.subtype == MEDIASUBTYPE_YVU9 )
476  {
477  //image orientation will be handled "automatically"
478  sgCB.specialMediaType = false;
479  }
480  //FOURCC formats
481  else
482  {
483  //invertedSource boolean will decide the bitmap orientation
484  sgCB.specialMediaType = true;
485 
486  DWORD format;
487  VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
488  BITMAPINFOHEADER bmpInfo = pVih->bmiHeader;
489 
490  //get the fourcc code
491  format = ((bmpInfo.biCompression&0xFF000000)>>24) |
492  ((bmpInfo.biCompression&0x00FF0000)>>8) |
493  ((bmpInfo.biCompression&0x0000FF00)<<8) |
494  (bmpInfo.biCompression&0x000000FF)<<24;
495 
496  std::cout<<"This format is not one of the standard YUV or RGB format supported by DirectShow.\n"
497  <<"FourCC : "
498  <<(char)(bmpInfo.biCompression&0x000000FF)
499  <<(char)((bmpInfo.biCompression&0x0000FF00)>>8)
500  <<(char)((bmpInfo.biCompression&0x00FF0000)>>16)
501  <<(char)((bmpInfo.biCompression&0xFF000000)>>24)<<std::endl;
502 
503  //Y800 is top-down oriented so the image doesn't have to be flipped vertically
504  if(format == 'Y800')
505  {
506  sgCB.invertedSource = false;
507  }
508  //cyuv seems to be the only yuv bottom-up oriented format (image has to be flipped)
509  else if(format == 'cyuv')
510  {
511  sgCB.invertedSource = true;
512  }
513  //insert code for other fourcc formats here
514  //see fourcc.org to know which format is bottom-up oriented and thus needs invertedSource sets to true
515  else
516  {
517  std::cout<<"Unknown FourCC compression type, assuming top-down orientation. Image may be inverted."<<std::endl;
518  sgCB.invertedSource = false; //consider that the image is topdown oriented by default
519  }
520  }
521 
522  return true;
523 }
524 
531 bool vpDirectShowGrabberImpl::connectSourceToGrabber(CComPtr<IBaseFilter>& _pCapSource, CComPtr<IBaseFilter>& _pGrabberFilter)
532 {
533  /*
534  //get the capture source's output pin
535  CComPtr<IPin> pCapSourcePin;
536  if(FAILED(pBuild->FindPin(_pCapSource, PINDIR_OUTPUT, NULL, NULL, false, 0, &pCapSourcePin)))
537  return false;
538 
539  //get the grabber's input pin
540  CComPtr<IPin> pGrabberInputPin;
541  if(FAILED(pBuild->FindPin(_pGrabberFilter, PINDIR_INPUT, NULL, NULL, false, 0, &pGrabberInputPin)))
542  return false;
543 
544  //connect the two of them
545  if(FAILED(pGraph->Connect(pCapSourcePin, pGrabberInputPin)))
546  return false;
547 
548  //not used anymore, we can release it
549  pGrabberInputPin.Release();
550  */
551  if(FAILED(hr = pBuild->RenderStream(NULL,NULL, _pCapSource, NULL, _pGrabberFilter)))
552  return false;
553 
554  /*
555  //get the grabber's output pin
556  CComPtr<IPin> pGrabberOutputPin;
557  if(FAILED(pBuild->FindPin(_pGrabberFilter, PINDIR_OUTPUT, NULL, NULL, false, 0, &pGrabberOutputPin)))
558  return false;
559  */
560  //get the Null renderer
561  CComPtr<IBaseFilter> pNull = NULL;
562  if (FAILED(pNull.CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER)))
563  return false;
564 /*
565  //get the null renderer's input pin
566  CComPtr<IPin> pNullInputPin;
567  if(FAILED(pBuild->FindPin(pNull, PINDIR_INPUT, NULL, NULL, false, 0, &pNullInputPin)))
568  return false;
569 
570  //connect the grabber's output to the null renderer
571  if( FAILED(pGraph->AddFilter(pNull, L"NullRenderer")) ||
572  FAILED(pGraph->Connect(pGrabberOutputPin, pNullInputPin)))
573  return false;
574 */
575 
576  if( FAILED(pGraph->AddFilter(pNull, L"NullRenderer")) ||
577  FAILED(pBuild->RenderStream(NULL,NULL, _pGrabberFilter, NULL, pNull)))
578  return false;
579 
580  //get the capture source's output pin
581  CComPtr<IPin> pCapSourcePin;
582  if(FAILED(pBuild->FindPin(_pCapSource, PINDIR_OUTPUT, NULL, NULL, false, 0, &pCapSourcePin)))
583  return false;
584  //checks the media type of the capture filter
585  //and if the image needs to be inverted
586  if(!checkSourceType(pCapSourcePin))
587  return false;
588 
589  //release the remaining interfaces
590  pCapSourcePin.Release();
591  pNull.Release();
592 // pGrabberOutputPin.Release();
593 // pNullInputPin.Release();
594 
595  return true;
596 }
597 
598 
604 bool vpDirectShowGrabberImpl::removeAll()
605 {
606  CComPtr<IEnumFilters> pEnum = NULL;
607  CComPtr<IBaseFilter> pFilter;
608  ULONG cFetched;
609 
610  if (FAILED(hr = pGraph->EnumFilters(&pEnum)))
611  return false;
612 
613  while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
614  {
615  if(FAILED(hr = pGraph->RemoveFilter(pFilter))) return false;
616  pFilter.Release();
617  pEnum->Reset();
618  }
619 
620  pEnum.Release();
621  return true;
622 }
623 
624 
633 void vpDirectShowGrabberImpl::acquire(vpImage<vpRGBa> &I)
634 {
635  if (init==false)
636  {
637  close();
639  "Initialization not done") );
640  }
641 
642  //set the rgbaIm pointer on I (will be filled on the next framegrabber callback)
643  sgCB.rgbaIm = &I;
644  //there is an acquire demand (execute copy during callback)
645  sgCB.acqRGBaDemand = true;
646 
647  //Run the graph to grab a frame
648  pControl->Run();
649 
650  // Wait untill it's done
651  long ev;
652  hr = pEvent->WaitForCompletion(MAX_DELAY, &ev);
653 
654  width = I.getWidth();
655  height = I.getHeight();
656 
657  //wait for the end of the next callback (copy)
658  if( WaitForSingleObject(sgCB.copySem,MAX_DELAY) != WAIT_OBJECT_0)
660  "Can't grab the frame, callback timeout") );
661 
662 
663 }
664 
673 void vpDirectShowGrabberImpl::acquire(vpImage<unsigned char> &I)
674 {
675  if (init==false)
676  {
677  close();
679  "Initialization not done") );
680  }
681 
682  //set the grayIm pointer on I (will be filled on the next framegrabber callback)
683  sgCB.grayIm = &I;
684  //there is an acquire demand (execute copy during callback)
685  sgCB.acqGrayDemand = true;
686 
687  //Run the graph to grab a frame
688  pControl->Run();
689 
690  // Wait untill it's done
691  long ev;
692  hr = pEvent->WaitForCompletion(MAX_DELAY, &ev);
693 
694  width = I.getWidth();
695  height = I.getHeight();
696 
697  //wait for the end of the next callback (copy)
698  if( WaitForSingleObject(sgCB.copySem,MAX_DELAY) != WAIT_OBJECT_0)
700  "Can't grab the frame, callback timeout") );
701 }
702 
709 bool vpDirectShowGrabberImpl::setDevice(unsigned int id)
710 {
711  if (init==false)
712  {
713  close();
715  "Initialization not done") );
716  }
717 
718 
719  //if n is invalid, or the device is already in use, quit
720  if(id>=nbDevices || deviceList[id].getState()==true)
721  return false;
722 
723  //we stop the graph
724  pControl->Stop();
725 
726  //then we can safely remove all the filters
727  if(!removeAll()) return false;
728 
729 
730  //we release the previous source's interface
731  pCapSource.Release();
732 
733  //here reset inUse in the old DSDevice
734  deviceList[currentDevice].resetInUse();
735 
736  //we add the grabber back in the graph
737  pGraph->AddFilter(pGrabberFilter,L"SampleGrabber");
738 
739  //get the n-th device's filter
740  if(!getDevice(id, pCapSource))
741  return false;
742 
743  //we add the capture source to the filter graph
744  if(FAILED(hr = pGraph->AddFilter(pCapSource, L"Capture Filter")))
745  return false;
746 
747  //we connect the pins
748  if(!connectSourceToGrabber(pCapSource, pGrabberFilter))
749  return false;
750 
751 
752  //get the current connected media type (needed by the callback)
753  if(FAILED(hr = pGrabberI->GetConnectedMediaType(&(sgCB.connectedMediaType))))
754  {
755  return false;
756  }
757 
758  //the device is now in use
759  deviceList[id].setInUse();
760  currentDevice=id;
761 
762  return true;
763 }
764 
768 void vpDirectShowGrabberImpl::displayDevices()
769 {
770  if(deviceList == NULL)
771  {
773  "Initialization not done") );
774  }
775 
776  for(unsigned int i=0 ; i<nbDevices ; i++)
777  std::cout<<i<<" : "<< deviceList[i].getName() <<std::endl;
778 
779  std::cout<<"Current device : "<<currentDevice<<std::endl<<std::endl;
780 }
781 
782 
787 void vpDirectShowGrabberImpl::close()
788 {
789  //the current device isn't being used anymore
790  if (init) {
791  deviceList[currentDevice].resetInUse();
792  init = false ;
793  }
794  if (initCo) {
795  //uninstalls COM
796  CoUninitialize();
797  initCo = false;
798  }
799 }
803 bool vpDirectShowGrabberImpl::setImageSize(unsigned int width,unsigned int height)
804 {
805  if (init==false)
806  {
807  close();
809  "Initialization not done") );
810  }
811 
812  return setFormat(width, height,NULL);
813 
814 }
815 
819 bool vpDirectShowGrabberImpl::setFramerate(double framerate)
820 {
821  if (init==false)
822  {
823  close();
825  "Initialization not done") );
826  }
827 
828  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)sgCB.connectedMediaType.pbFormat;
829  return setFormat(pVih->bmiHeader.biWidth,pVih->bmiHeader.biHeight,framerate);
830 
831 }
835 bool vpDirectShowGrabberImpl::setFormat(unsigned int width,unsigned int height, double framerate)
836 {
837  if (init==false)
838  {
839  close();
841  "Initialization not done") );
842  }
843 
844  bool found=false;
845 
846  //gets the stream config interface
847  IAMStreamConfig *pConfig = NULL;
848 
849  if(FAILED(hr = pBuild->FindInterface(
850  &LOOK_UPSTREAM_ONLY, // Capture pin. / Preview pin
851  0, // Any media type.
852  pGrabberFilter, // Pointer to the grabber filter.
853  IID_IAMStreamConfig, (void**)&pConfig)))
854  return false;
855 
856  //gets the video control interface
857  IAMVideoControl *pVideoControl = NULL;
858 
859  if(FAILED(hr = pBuild->FindInterface(
860  &LOOK_UPSTREAM_ONLY, // Capture pin. / Preview pin
861  0, // Any media type.
862  pGrabberFilter, // Pointer to the grabber filter.
863  IID_IAMVideoControl, (void**)&pVideoControl)))
864  return false;
865 
866  //get the grabber's input pin
867  CComPtr<IPin> pCapSourcePin;
868  if(FAILED(pBuild->FindPin(pCapSource, PINDIR_OUTPUT, NULL, NULL, false, 0, &pCapSourcePin)))
869  return false;
870 
871  int iCount = 0, iSize = 0;
872  if(FAILED(hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize)))
873  return false;
874 
875  // Check the size to make sure we pass in the correct structure.
876  if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
877  {
878  // Use the video capabilities structure.
879 
880  for (int iFormat = 0; iFormat < iCount; iFormat++)
881  {
882  VIDEO_STREAM_CONFIG_CAPS scc;
883  AM_MEDIA_TYPE *pmtConfig;
884  hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
885 // VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
886 
887 // pVih->bmiHeader.biWidth;
888 // pVih->bmiHeader.biHeight;
889 // 10000000 /pVih->AvgTimePerFrame;
890 // std::cout<<"available image size : "<<pVih->bmiHeader.biWidth<<" x "<<pVih->bmiHeader.biHeight<<" at "<<10000000 /pVih->AvgTimePerFrame<<std::endl;
891 // std::cout<<"compression : "<<pVih->bmiHeader.biCompression<<std::endl;
892  if (SUCCEEDED(hr)&& found==false)
893  {
894  /* Examine the format, and possibly use it. */
895  if ((pmtConfig->majortype == sgCB.connectedMediaType.majortype) &&
896  (pmtConfig->subtype == sgCB.connectedMediaType.subtype) &&
897  (pmtConfig->formattype == sgCB.connectedMediaType.formattype) &&
898  (pmtConfig->cbFormat >= sizeof (VIDEOINFOHEADER)) &&
899  (pmtConfig->pbFormat != NULL))
900  {
901  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
902 
903  LONG lWidth = pVih->bmiHeader.biWidth;
904  LONG lHeight = pVih->bmiHeader.biHeight;
905  if(framerate != NULL)
906  {
907  if((unsigned int)lWidth == width && (unsigned int)lHeight == height)
908  {
909 
910  pVih->AvgTimePerFrame = (LONGLONG)(10000000 / framerate);
911  //set the capture media type and the grabber media type
912  if(FAILED(hr = pConfig->SetFormat(pmtConfig))||
913  FAILED(hr = pGrabberI->SetMediaType(pmtConfig)))
914  return false;
915  //Run the graph to grab a frame
916  pControl->Run();
917 
918  //get the current connected media type (needed by the callback)
919  if(FAILED(hr = pGrabberI->GetConnectedMediaType(&(sgCB.connectedMediaType))))
920  return false;
921  pVih = (VIDEOINFOHEADER*)sgCB.connectedMediaType.pbFormat;
922  LONGLONG ActualFrameDuration;
923  if(FAILED(hr = pVideoControl->GetCurrentActualFrameRate(pCapSourcePin,&ActualFrameDuration)))
924  std::cout<<"Current format (not sure): "<<width <<" x "<< height <<" at "<< 10000000/pVih->AvgTimePerFrame <<" fps"<<std::endl<<std::endl;
925  else {
926  std::cout<<"Current format : "<<width <<" x "<< height <<" at "<< 10000000/ActualFrameDuration <<" fps"<<std::endl<<std::endl;
927  pVih->AvgTimePerFrame = ActualFrameDuration;
928  }
929  found=true;
930  }
931  }
932  else
933  {
934  if((unsigned int)lWidth == width && (unsigned int)lHeight == height)
935  {
936  pVih->AvgTimePerFrame = scc.MinFrameInterval;
937  //set the capture media type and the grabber media type
938  if(FAILED(hr = pConfig->SetFormat(pmtConfig))||
939  FAILED(hr = pGrabberI->SetMediaType(pmtConfig)))
940  return false;
941  //get the current connected media type (needed by the callback)
942  if(FAILED(hr = pGrabberI->GetConnectedMediaType(&(sgCB.connectedMediaType))))
943  return false;
944  pVih = (VIDEOINFOHEADER*)sgCB.connectedMediaType.pbFormat;
945  found=true;
946  std::cout<<"Current format : "<<width <<" x "<< height <<" at "<<(10000000 /pVih->AvgTimePerFrame) <<" fps"<<std::endl<<std::endl;
947  }
948 
949  }
950  }
951  }
952  // Delete the media type when you are done.
953  MyDeleteMediaType(pmtConfig);
954  }
955  }
956  if(!found)
957  if(framerate != NULL)
958  std::cout << "The "<<width <<" x "<< height <<" at " <<framerate<<" fps source image format is not available. "<<std::endl<<std::endl;
959  else
960  std::cout << "The "<<width <<" x "<< height <<"source image size is not available. "<<std::endl<<std::endl;
961 
962  return found;
963 }
970 void vpDirectShowGrabberImpl::getFormat(unsigned int &width,unsigned int &height, double &framerate)
971 {
972  if (init==false)
973  {
974  close();
976  "Initialization not done") );
977  }
978  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)sgCB.connectedMediaType.pbFormat;
979  width = (unsigned int)pVih->bmiHeader.biWidth;
980  height = (unsigned int)pVih->bmiHeader.biHeight;
981  framerate = (double)(10000000/pVih->AvgTimePerFrame);
982 
983 }
987 bool vpDirectShowGrabberImpl::getStreamCapabilities()
988 {
989  if (init==false)
990  {
991  close();
993  "Initialization not done") );
994  }
995 
996  //gets the stream config interface
997  IAMStreamConfig *pConfig = NULL;
998 
999  if(FAILED(hr = pBuild->FindInterface(
1000  &LOOK_UPSTREAM_ONLY, // Capture pin. / Preview pin
1001  0, // Any media type.
1002  pGrabberFilter, // Pointer to the grabber filter.
1003  IID_IAMStreamConfig, (void**)&pConfig)))
1004  return false;
1005 
1006  int iCount = 0, iSize = 0;
1007  if(FAILED(hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize)))
1008  return false;
1009 
1010  // Check the size to make sure we pass in the correct structure.
1011  if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
1012  {
1013  std::cout<<"Available MediaTypes : "<<std::endl<<std::endl;
1014  // Use the video capabilities structure.
1015  for (int iFormat = 0; iFormat < iCount; iFormat++)
1016  {
1017  VIDEO_STREAM_CONFIG_CAPS scc;
1018  AM_MEDIA_TYPE *pmtConfig;
1019  hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
1020 
1021  if (SUCCEEDED(hr))
1022  {
1023  /* Examine the format, and possibly use it. */
1024  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
1025 
1026 // LONG lWidth = pVih->bmiHeader.biWidth;
1027 // LONG lHeight = pVih->bmiHeader.biHeight;
1028 // SIZE dimensions={lWidth,lHeight};
1029 // LONGLONG lAvgTimePerFrame = pVih->AvgTimePerFrame;
1030  std::cout<<"MediaType : "<<iFormat<<std::endl;
1031 
1032  if(pmtConfig->subtype==MEDIASUBTYPE_ARGB32)
1033  std::cout<<"subtype (not supported): MEDIASUBTYPE_ARGB32"<<std::endl;
1034  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB32)
1035  std::cout<<"subtype : MEDIASUBTYPE_RGB32"<<std::endl;
1036  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB24)
1037  std::cout<<"subtype : MEDIASUBTYPE_RGB24"<<std::endl;
1038  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB555)
1039  std::cout<<"subtype (not supported): MEDIASUBTYPE_RGB555"<<std::endl;
1040  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB565)
1041  std::cout<<"subtype (not supported): MEDIASUBTYPE_RGB565"<<std::endl;
1042  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB8)
1043  std::cout<<"subtype (not supported): MEDIASUBTYPE_RGB8"<<std::endl;
1044  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB4)
1045  std::cout<<"subtype (not supported): MEDIASUBTYPE_RGB4"<<std::endl;
1046  else if(pmtConfig->subtype==MEDIASUBTYPE_RGB1)
1047  std::cout<<"subtype (not supported): MEDIASUBTYPE_RGB1"<<std::endl;
1048  else if(pmtConfig->subtype==MEDIASUBTYPE_YV12)
1049  std::cout<<"subtype : MEDIASUBTYPE_YV12"<<std::endl;
1050  else if(pmtConfig->subtype==MEDIASUBTYPE_YVU9)
1051  std::cout<<"subtype : MEDIASUBTYPE_YVU9"<<std::endl;
1052  else if(pmtConfig->subtype==MEDIASUBTYPE_YUY2)
1053  std::cout<<"subtype : MEDIASUBTYPE_YUY2"<<std::endl;
1054  else if(pmtConfig->subtype==MEDIASUBTYPE_YUYV)
1055  std::cout<<"subtype : MEDIASUBTYPE_YUYV"<<std::endl;
1056  else if(pmtConfig->subtype==MEDIASUBTYPE_YVYU)
1057  std::cout<<"subtype : MEDIASUBTYPE_YVYU"<<std::endl;
1058  else if(pmtConfig->subtype==MEDIASUBTYPE_IYUV)
1059  std::cout<<"subtype : MEDIASUBTYPE_IYUV"<<std::endl;
1060  else if(pmtConfig->subtype==MEDIASUBTYPE_UYVY)
1061  std::cout<<"subtype : MEDIASUBTYPE_UYVY"<<std::endl;
1062  else if((((pVih->bmiHeader.biCompression&0xFF000000)>>24) |
1063  ((pVih->bmiHeader.biCompression&0x00FF0000)>>8) |
1064  ((pVih->bmiHeader.biCompression&0x0000FF00)<<8) |
1065  ((pVih->bmiHeader.biCompression&0x000000FF)<<24)) == 'I420')
1066  std::cout<<"subtype : I420"<<std::endl;
1067  else std::cout<<"subtype (not supported) :"
1068  <<(char)(pVih->bmiHeader.biCompression&0x000000FF)
1069  <<(char)((pVih->bmiHeader.biCompression&0x0000FF00)>>8)
1070  <<(char)((pVih->bmiHeader.biCompression&0x00FF0000)>>16)
1071  <<(char)((pVih->bmiHeader.biCompression&0xFF000000)>>24)<<std::endl;
1072 
1073  std::cout<<"image size : "<<pVih->bmiHeader.biWidth<<" x "<<pVih->bmiHeader.biHeight<<std::endl;
1074  std::cout<<"framerate range: ["<< 10000000/scc.MaxFrameInterval<<","<<10000000/scc.MinFrameInterval<<"]"<<std::endl<<std::endl;
1075 
1076 /*
1077  long frameRateNum;
1078  LONGLONG *frameRateList;
1079  if(FAILED(hr = pVideoControl->GetFrameRateList(pCapSourcePin,iFormat,dimensions, //inputs
1080  &frameRateNum, &frameRateList))) //outputs
1081  return false;
1082  for(int i=0; i<(int)frameRateNum ; i++)
1083  {
1084  std::cout<<(float)(10000000/frameRateList[i])<<" fps"<<std::endl;
1085  }
1086  std::cout<<std::endl;
1087 */
1088  }
1089  // Delete the media type when you are done.
1090  MyDeleteMediaType(pmtConfig);
1091  }
1092  }
1093  return true;
1094 }
1098 bool vpDirectShowGrabberImpl::setMediaType(int mediaTypeID)
1099 {
1100  if (init==false)
1101  {
1102  close();
1104  "Initialization not done") );
1105  }
1106 
1107  //gets the stream config interface
1108  IAMStreamConfig *pConfig = NULL;
1109 
1110  if(FAILED(hr = pBuild->FindInterface(
1111  &LOOK_UPSTREAM_ONLY, // Capture pin. / Preview pin
1112  0, // Any media type.
1113  pGrabberFilter, // Pointer to the grabber filter.
1114  IID_IAMStreamConfig, (void**)&pConfig)))
1115  return false;
1116 
1117  VIDEO_STREAM_CONFIG_CAPS scc;
1118  AM_MEDIA_TYPE *pmtConfig;
1119  hr = pConfig->GetStreamCaps(mediaTypeID, &pmtConfig, (BYTE*)&scc);
1120 
1121 
1122  if (SUCCEEDED(hr))
1123  {
1124  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
1125  pVih->AvgTimePerFrame = scc.MinFrameInterval ;
1126  //set the capture media type and the grabber media type
1127  if(FAILED(hr = pGrabberI->SetMediaType(pmtConfig))||
1128  FAILED(hr = pConfig->SetFormat(pmtConfig)))
1129  return false;
1130  //get the current connected media type (needed by the callback)
1131  if(FAILED(hr = pGrabberI->GetConnectedMediaType(&(sgCB.connectedMediaType))))
1132  return false;
1133  }
1134  // Delete the media type when you are done.
1135  MyDeleteMediaType(pmtConfig);
1136  return true;
1137 }
1138 
1139 /*
1140  Get current capture MediaType
1141  \return mediaTypeID (-1 if failed)
1142 */
1143 int vpDirectShowGrabberImpl::getMediaType()
1144 {
1145  if (init==false)
1146  {
1147  close();
1149  "Initialization not done") );
1150  }
1151 
1152  int mediaTypeID = -1;
1153  VIDEOINFOHEADER *pVihConnected = (VIDEOINFOHEADER*)sgCB.connectedMediaType.pbFormat;
1154 
1155  //gets the stream config interface
1156  IAMStreamConfig *pConfig = NULL;
1157 
1158  if(FAILED(hr = pBuild->FindInterface(
1159  &LOOK_UPSTREAM_ONLY, // Capture pin. / Preview pin
1160  0, // Any media type.
1161  pGrabberFilter, // Pointer to the grabber filter.
1162  IID_IAMStreamConfig, (void**)&pConfig)))
1163  return -1;
1164 
1165  int iCount = 0, iSize = 0;
1166  if(FAILED(hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize)))
1167  return -1;
1168 
1169  // Check the size to make sure we pass in the correct structure.
1170  if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
1171  {
1172  // Use the video capabilities structure.
1173  for (int iFormat = 0; iFormat < iCount; iFormat++)
1174  {
1175  VIDEO_STREAM_CONFIG_CAPS scc;
1176  AM_MEDIA_TYPE *pmtConfig;
1177  hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
1178 
1179  if (SUCCEEDED(hr))
1180  {
1181  /* Examine the format, and possibly use it. */
1182  if ((pmtConfig->majortype == sgCB.connectedMediaType.majortype) &&
1183  (pmtConfig->subtype == sgCB.connectedMediaType.subtype) &&
1184  (pmtConfig->formattype == sgCB.connectedMediaType.formattype) &&
1185  (pmtConfig->cbFormat >= sizeof (VIDEOINFOHEADER)) &&
1186  (pmtConfig->pbFormat != NULL))
1187  {
1188  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
1189  if(pVih->bmiHeader.biWidth == pVihConnected->bmiHeader.biWidth &&
1190  pVih->bmiHeader.biHeight == pVihConnected->bmiHeader.biHeight)
1191  mediaTypeID = iFormat ;
1192  }
1193  }
1194  // Delete the media type when you are done.
1195  MyDeleteMediaType(pmtConfig);
1196  }
1197  }
1198  return mediaTypeID;
1199 }
1200 
1201 
1205 void vpDirectShowGrabberImpl::MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
1206 {
1207  if (pmt != NULL)
1208  {
1209  MyFreeMediaType(*pmt); // See FreeMediaType for the implementation.
1210  CoTaskMemFree(pmt);
1211  }
1212 }
1213 
1214 
1218 void vpDirectShowGrabberImpl::MyFreeMediaType(AM_MEDIA_TYPE& mt)
1219 {
1220  if (mt.cbFormat != 0)
1221  {
1222  CoTaskMemFree((PVOID)mt.pbFormat);
1223  mt.cbFormat = 0;
1224  mt.pbFormat = NULL;
1225  }
1226  if (mt.pUnk != NULL)
1227  {
1228  // Unecessary because pUnk should not be used, but safest.
1229  mt.pUnk->Release();
1230  mt.pUnk = NULL;
1231  }
1232 }
1233 
1234 #elif !defined(VISP_BUILD_SHARED_LIBS)
1235 // Work arround to avoid warning: libvisp_sensor.a(vpDirectShowGrabberImpl.cpp.o) has no symbols
1236 void dummy_vpDirectShowGrabberImpl() {};
1237 #endif
1238 #endif
unsigned int getWidth() const
Definition: vpImage.h:226
Error that can be emited by the vpFrameGrabber class and its derivates.
unsigned int getHeight() const
Definition: vpImage.h:175