Advertisement
Guest User

Webcamm Dshow mingw

a guest
Feb 13th, 2013
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.29 KB | None | 0 0
  1. /*
  2.  *  Web cam capture snippet
  3.  *  Based on Ted Burke's commandline capture program
  4.  *  Check http://batchloaf.wordpress.com
  5.  *  Licensed under the GPL
  6.  */
  7.  
  8. #define STRSAFE_NO_DEPRECATE
  9. #include <dshow.h>
  10. #include "my_string.h"
  11. #include "my_vector.h"
  12. #include "link.h"
  13.  
  14. #define HEADER(pVideoInfo) (&(((VIDEOINFOHEADER *) (pVideoInfo))->bmiHeader))
  15. #define SIZE_PREHEADER 48
  16.  
  17. interface ISampleGrabberCB : public IUnknown {
  18.     virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
  19.     virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
  20. };
  21. static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };
  22. interface ISampleGrabber : public IUnknown {
  23.     virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0;
  24.     virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0;
  25.     virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0;
  26.     virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0;
  27.     virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0;
  28.     virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0;
  29.     virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0;
  30. };
  31. static const IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
  32.  
  33. #define DEFGUID(a,b,c,d, e,f,g,h,i,j,k,l) \
  34.     const IID a = { b,c,d, { e,f,g,h,i,j,k,l } };
  35.  
  36. DEFGUID(MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
  37. DEFGUID(MEDIASUBTYPE_RGB24, 0xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
  38. DEFGUID(IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
  39. DEFGUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
  40. DEFGUID(PIN_CATEGORY_CAPTURE, 0xfb6c4281, 0x0353, 0x11d1, 0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
  41. DEFGUID(IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
  42. DEFGUID(CLSID_NullRenderer,0xc1f400a4, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
  43. DEFGUID(CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
  44. DEFGUID(CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
  45. DEFGUID(IID_ICaptureGraphBuilder2, 0x93e5a4e0, 0x2d50, 0x11d2, 0xab, 0xfa, 0x00, 0xa0, 0xc9, 0xc6, 0xe3, 0x8d);
  46. DEFGUID(CLSID_CaptureGraphBuilder2, 0xBF87B6E1, 0x8C27, 0x11d0, 0xB3, 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
  47. DEFGUID(CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
  48. DEFGUID(CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01, 0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
  49. DEFGUID(IID_IBaseFilter, 0x56a86895, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
  50. DEFGUID(FORMAT_VideoInfo,0x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
  51.  
  52. // DirectShow objects
  53.  
  54. my::vector <my::string> list_devices() {
  55.     my::vector <my::string> list;
  56.     HRESULT hr;
  57.     ICreateDevEnum *pDevEnum = NULL;
  58.     IEnumMoniker *pEnum = NULL;
  59.     IMoniker *pMoniker = NULL;
  60.     IPropertyBag *pPropBag = NULL;
  61.     IGraphBuilder *pGraph = NULL;
  62.     ICaptureGraphBuilder2 *pBuilder = NULL;
  63.    
  64.     // Intialise COM
  65.     hr = CoInitializeEx__(NULL, COINIT_MULTITHREADED);
  66.     if (hr != S_OK) goto cleanup_list;
  67.  
  68.     // Create filter graph
  69.     hr = CoCreateInstance__(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
  70.     if (hr != S_OK) goto cleanup_list;
  71.    
  72.     // Create capture graph builder.
  73.     hr = CoCreateInstance__(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
  74.     if (hr != S_OK) goto cleanup_list;
  75.  
  76.     // Attach capture graph builder to graph
  77.     hr = pBuilder->SetFiltergraph(pGraph);
  78.     if (hr != S_OK) goto cleanup_list;
  79.  
  80.     // Create system device enumerator
  81.     hr = CoCreateInstance__(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
  82.     if (hr != S_OK) goto cleanup_list;
  83.  
  84.     // Video input device enumerator
  85.     hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
  86.     if (hr != S_OK) goto cleanup_list;
  87.    
  88.     while (hr == S_OK) {
  89.         hr = pEnum->Next(1, &pMoniker, NULL);
  90.         if (hr == S_OK) {
  91.             hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
  92.             VARIANT var;
  93.             VariantInit__(&var);
  94.             hr = pPropBag->Read(L"FriendlyName", &var, 0);
  95.             char utf8str[4096]; memset(utf8str,0,sizeof(utf8str));
  96.             WideCharToMultiByte(CP_UTF8, 0, var.bstrVal, -1, utf8str, sizeof(utf8str), 0, 0);
  97.             VariantClear__(&var);
  98.             list.push_back(my::string(utf8str));
  99.         }
  100.     }
  101.    
  102.     cleanup_list:
  103.     if (pBuilder != NULL) pBuilder->Release();
  104.     if (pGraph != NULL)   pGraph->Release();
  105.     if (pPropBag != NULL) pPropBag->Release();
  106.     if (pMoniker != NULL) pMoniker->Release();
  107.     if (pEnum != NULL)    pEnum->Release();
  108.     if (pDevEnum != NULL) pDevEnum->Release();
  109.     CoUninitialize__();
  110.    
  111.     return list;
  112. }
  113.  
  114. int get_snapshot(int devnum, unsigned char * buffer, int maxlen, int * width, int * height) {
  115.     HRESULT hr;
  116.     ICreateDevEnum *pDevEnum = NULL;
  117.     IEnumMoniker *pEnum = NULL;
  118.     IMoniker *pMoniker = NULL;
  119.     IPropertyBag *pPropBag = NULL;
  120.     IGraphBuilder *pGraph = NULL;
  121.     ICaptureGraphBuilder2 *pBuilder = NULL;
  122.     IBaseFilter *pCap = NULL;
  123.     IBaseFilter *pSampleGrabberFilter = NULL;
  124.     ISampleGrabber *pSampleGrabber = NULL;
  125.     IBaseFilter *pNullRenderer = NULL;
  126.     IMediaControl *pMediaControl = NULL;
  127.     char *pBuffer = NULL;
  128.     AM_MEDIA_TYPE mt;
  129.     ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
  130.     int returnv = 0;
  131.     long buffer_size = 0;
  132.     int n = 0;
  133.     VIDEOINFOHEADER *pVih = NULL;
  134.    
  135.     hr = CoInitializeEx__(NULL, COINIT_MULTITHREADED);
  136.     if (hr != S_OK) goto cleanup_snap;
  137.     hr = CoCreateInstance__(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
  138.     if (hr != S_OK) goto cleanup_snap;
  139.     hr = CoCreateInstance__(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
  140.     if (hr != S_OK) goto cleanup_snap;
  141.     hr = pBuilder->SetFiltergraph(pGraph);
  142.     if (hr != S_OK) goto cleanup_snap;
  143.     hr = CoCreateInstance__(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
  144.     if (hr != S_OK) goto cleanup_snap;
  145.     hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
  146.     if (hr != S_OK) goto cleanup_snap;
  147.    
  148.     while (hr == S_OK) {
  149.         hr = pEnum->Next(1, &pMoniker, NULL);
  150.         if (hr == S_OK) {
  151.             hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
  152.             if (n == devnum) break;
  153.             n++;
  154.         }
  155.     }
  156.     if (n != devnum) goto cleanup_snap; // Could not find the device!
  157.    
  158.     // Get video input device name
  159.     hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
  160.    
  161.     hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
  162.     if (hr != S_OK) goto cleanup_snap;
  163.     hr = pGraph->AddFilter(pCap, L"Capture Filter");
  164.     if (hr != S_OK) goto cleanup_snap;
  165.     hr = CoCreateInstance__(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSampleGrabberFilter);
  166.     if (hr != S_OK) goto cleanup_snap;
  167.     hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
  168.     if (hr != S_OK) goto cleanup_snap;
  169.     hr = pSampleGrabber->SetBufferSamples(TRUE);
  170.     if (hr != S_OK) goto cleanup_snap;
  171.    
  172.     mt.majortype = MEDIATYPE_Video;
  173.     mt.subtype = MEDIASUBTYPE_RGB24;
  174.     hr = pSampleGrabber->SetMediaType((_AMMediaType *)&mt);
  175.     if (hr != S_OK) goto cleanup_snap;
  176.     hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
  177.     if (hr != S_OK) goto cleanup_snap;
  178.     hr = CoCreateInstance__(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNullRenderer);
  179.     if (hr != S_OK) goto cleanup_snap;
  180.     hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
  181.     if (hr != S_OK) goto cleanup_snap;
  182.     hr = pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap, pSampleGrabberFilter, pNullRenderer);
  183.     if (hr != S_OK) goto cleanup_snap;
  184.     hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pMediaControl);
  185.     if (hr != S_OK) goto cleanup_snap;
  186.  
  187.     while(1) {
  188.         hr = pMediaControl->Run();
  189.        
  190.         if (hr == S_OK) break;
  191.         if (hr == S_FALSE) continue;
  192.        
  193.         goto cleanup_snap;
  194.     }
  195.    
  196.     Sleep(1000);
  197.    
  198.     while(1) {
  199.         hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, NULL);
  200.        
  201.         if (hr == S_OK && buffer_size != 0) break;
  202.        
  203.         if (hr != S_OK && hr != VFW_E_WRONG_STATE)
  204.             goto cleanup_snap;
  205.     }
  206.  
  207.     pMediaControl->Stop();
  208.     pBuffer = new char[buffer_size];
  209.     if (!pBuffer) goto cleanup_snap;
  210.     hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, (long*)pBuffer);
  211.     if (hr != S_OK) goto cleanup_snap;
  212.     hr = pSampleGrabber->GetConnectedMediaType((_AMMediaType *)&mt);
  213.     if (hr != S_OK) goto cleanup_snap;
  214.    
  215.     if ((mt.formattype == FORMAT_VideoInfo) && (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mt.pbFormat != NULL)) {
  216.         pVih = (VIDEOINFOHEADER*)mt.pbFormat;
  217.  
  218.         if (buffer_size > maxlen)
  219.             goto cleanup_snap;
  220.  
  221.         *width  = pVih->bmiHeader.biWidth;
  222.         *height = pVih->bmiHeader.biHeight;
  223.         memcpy(buffer,pBuffer,buffer_size);
  224.        
  225.         // Invert the scanlines
  226.         for (int i = 0; i < (*height)/2; i++) {
  227.             char line[*width*3];
  228.             memcpy(line,&buffer[i*(*width)*3],3*(*width));
  229.             memcpy(&buffer[i*(*width)*3],&buffer[((*height)-i-1)*(*width)*3],3*(*width));
  230.             memcpy(&buffer[((*height)-i-1)*(*width)*3],line,3*(*width));
  231.         }
  232.     }
  233.     else {
  234.         goto cleanup_snap;
  235.     }
  236.     returnv = 1;
  237.  
  238.     cleanup_snap:
  239.     // Clean up DirectShow / COM stuff
  240.     if (pBuffer != NULL) delete[] pBuffer;
  241.     if (pMediaControl != NULL) pMediaControl->Release();   
  242.     if (pNullRenderer != NULL) pNullRenderer->Release();
  243.     if (pSampleGrabber != NULL) pSampleGrabber->Release();
  244.     if (pSampleGrabberFilter != NULL)
  245.         pSampleGrabberFilter->Release();
  246.     if (pCap != NULL) pCap->Release();
  247.     if (pBuilder != NULL) pBuilder->Release();
  248.     if (pGraph != NULL) pGraph->Release();
  249.     if (pPropBag != NULL) pPropBag->Release();
  250.     if (pMoniker != NULL) pMoniker->Release();
  251.     if (pEnum != NULL) pEnum->Release();
  252.     if (pDevEnum != NULL) pDevEnum->Release();
  253.     CoUninitialize__();
  254.     if (mt.cbFormat != 0) {
  255.         CoTaskMemFree__((PVOID)mt.pbFormat);
  256.     }
  257.     if (mt.pUnk != NULL) {
  258.         mt.pUnk->Release();
  259.     }
  260.    
  261.     return returnv;
  262. }
  263.  
  264. extern "C" {
  265.     __declspec(dllexport) char* __cdecl ListWebcams ();
  266.     __declspec(dllexport) int __cdecl WebcamSnap(int devnum, unsigned char * buffer, int maxlen, int * width, int * height);
  267. }
  268.  
  269. __declspec(dllexport) char* __cdecl ListWebcams () {
  270.     my::vector <my::string> dlist = list_devices();
  271.     int mem_needed = sizeof(int);
  272.     for (unsigned int i = 0; i < dlist.size(); i++) {
  273.         mem_needed += sizeof(int) + dlist[i].size() + 1;
  274.     }
  275.     char * buffer = (char*)malloc(mem_needed);
  276.     int * ptrs = (int*)buffer;
  277.     memset(buffer,0,mem_needed);
  278.     int n = sizeof(int)*(dlist.size()+1);
  279.     for (unsigned int i = 0; i < dlist.size(); i++) {
  280.         ptrs[i] = (&buffer[n])-(&buffer[0]);
  281.         memcpy(&buffer[n],dlist[i].c_str(),dlist[i].size()+1);
  282.         n += dlist[i].size()+1;
  283.     }
  284.     return buffer;
  285. }
  286.  
  287. __declspec(dllexport) int __cdecl WebcamSnap(int devnum, unsigned char * buffer, int maxlen, int * width, int * height) {
  288.     return get_snapshot(devnum, buffer, maxlen, width, height);
  289. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement