Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Web cam capture snippet
- * Based on Ted Burke's commandline capture program
- * Check http://batchloaf.wordpress.com
- * Licensed under the GPL
- */
- #define STRSAFE_NO_DEPRECATE
- #include <dshow.h>
- #include "my_string.h"
- #include "my_vector.h"
- #include "link.h"
- #define HEADER(pVideoInfo) (&(((VIDEOINFOHEADER *) (pVideoInfo))->bmiHeader))
- #define SIZE_PREHEADER 48
- interface ISampleGrabberCB : public IUnknown {
- virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
- virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
- };
- static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };
- interface ISampleGrabber : public IUnknown {
- virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0;
- virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0;
- virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0;
- virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0;
- };
- static const IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
- #define DEFGUID(a,b,c,d, e,f,g,h,i,j,k,l) \
- const IID a = { b,c,d, { e,f,g,h,i,j,k,l } };
- DEFGUID(MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
- DEFGUID(MEDIASUBTYPE_RGB24, 0xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
- DEFGUID(IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
- DEFGUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
- DEFGUID(PIN_CATEGORY_CAPTURE, 0xfb6c4281, 0x0353, 0x11d1, 0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
- DEFGUID(IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
- DEFGUID(CLSID_NullRenderer,0xc1f400a4, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
- DEFGUID(CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
- DEFGUID(CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
- DEFGUID(IID_ICaptureGraphBuilder2, 0x93e5a4e0, 0x2d50, 0x11d2, 0xab, 0xfa, 0x00, 0xa0, 0xc9, 0xc6, 0xe3, 0x8d);
- DEFGUID(CLSID_CaptureGraphBuilder2, 0xBF87B6E1, 0x8C27, 0x11d0, 0xB3, 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
- DEFGUID(CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
- DEFGUID(CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01, 0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
- DEFGUID(IID_IBaseFilter, 0x56a86895, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
- DEFGUID(FORMAT_VideoInfo,0x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
- // DirectShow objects
- my::vector <my::string> list_devices() {
- my::vector <my::string> list;
- HRESULT hr;
- ICreateDevEnum *pDevEnum = NULL;
- IEnumMoniker *pEnum = NULL;
- IMoniker *pMoniker = NULL;
- IPropertyBag *pPropBag = NULL;
- IGraphBuilder *pGraph = NULL;
- ICaptureGraphBuilder2 *pBuilder = NULL;
- // Intialise COM
- hr = CoInitializeEx__(NULL, COINIT_MULTITHREADED);
- if (hr != S_OK) goto cleanup_list;
- // Create filter graph
- hr = CoCreateInstance__(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
- if (hr != S_OK) goto cleanup_list;
- // Create capture graph builder.
- hr = CoCreateInstance__(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
- if (hr != S_OK) goto cleanup_list;
- // Attach capture graph builder to graph
- hr = pBuilder->SetFiltergraph(pGraph);
- if (hr != S_OK) goto cleanup_list;
- // Create system device enumerator
- hr = CoCreateInstance__(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
- if (hr != S_OK) goto cleanup_list;
- // Video input device enumerator
- hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
- if (hr != S_OK) goto cleanup_list;
- while (hr == S_OK) {
- hr = pEnum->Next(1, &pMoniker, NULL);
- if (hr == S_OK) {
- hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
- VARIANT var;
- VariantInit__(&var);
- hr = pPropBag->Read(L"FriendlyName", &var, 0);
- char utf8str[4096]; memset(utf8str,0,sizeof(utf8str));
- WideCharToMultiByte(CP_UTF8, 0, var.bstrVal, -1, utf8str, sizeof(utf8str), 0, 0);
- VariantClear__(&var);
- list.push_back(my::string(utf8str));
- }
- }
- cleanup_list:
- if (pBuilder != NULL) pBuilder->Release();
- if (pGraph != NULL) pGraph->Release();
- if (pPropBag != NULL) pPropBag->Release();
- if (pMoniker != NULL) pMoniker->Release();
- if (pEnum != NULL) pEnum->Release();
- if (pDevEnum != NULL) pDevEnum->Release();
- CoUninitialize__();
- return list;
- }
- int get_snapshot(int devnum, unsigned char * buffer, int maxlen, int * width, int * height) {
- HRESULT hr;
- ICreateDevEnum *pDevEnum = NULL;
- IEnumMoniker *pEnum = NULL;
- IMoniker *pMoniker = NULL;
- IPropertyBag *pPropBag = NULL;
- IGraphBuilder *pGraph = NULL;
- ICaptureGraphBuilder2 *pBuilder = NULL;
- IBaseFilter *pCap = NULL;
- IBaseFilter *pSampleGrabberFilter = NULL;
- ISampleGrabber *pSampleGrabber = NULL;
- IBaseFilter *pNullRenderer = NULL;
- IMediaControl *pMediaControl = NULL;
- char *pBuffer = NULL;
- AM_MEDIA_TYPE mt;
- ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
- int returnv = 0;
- long buffer_size = 0;
- int n = 0;
- VIDEOINFOHEADER *pVih = NULL;
- hr = CoInitializeEx__(NULL, COINIT_MULTITHREADED);
- if (hr != S_OK) goto cleanup_snap;
- hr = CoCreateInstance__(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
- if (hr != S_OK) goto cleanup_snap;
- hr = CoCreateInstance__(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);
- if (hr != S_OK) goto cleanup_snap;
- hr = pBuilder->SetFiltergraph(pGraph);
- if (hr != S_OK) goto cleanup_snap;
- hr = CoCreateInstance__(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
- if (hr != S_OK) goto cleanup_snap;
- hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
- if (hr != S_OK) goto cleanup_snap;
- while (hr == S_OK) {
- hr = pEnum->Next(1, &pMoniker, NULL);
- if (hr == S_OK) {
- hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
- if (n == devnum) break;
- n++;
- }
- }
- if (n != devnum) goto cleanup_snap; // Could not find the device!
- // Get video input device name
- hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
- hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
- if (hr != S_OK) goto cleanup_snap;
- hr = pGraph->AddFilter(pCap, L"Capture Filter");
- if (hr != S_OK) goto cleanup_snap;
- hr = CoCreateInstance__(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSampleGrabberFilter);
- if (hr != S_OK) goto cleanup_snap;
- hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
- if (hr != S_OK) goto cleanup_snap;
- hr = pSampleGrabber->SetBufferSamples(TRUE);
- if (hr != S_OK) goto cleanup_snap;
- mt.majortype = MEDIATYPE_Video;
- mt.subtype = MEDIASUBTYPE_RGB24;
- hr = pSampleGrabber->SetMediaType((_AMMediaType *)&mt);
- if (hr != S_OK) goto cleanup_snap;
- hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
- if (hr != S_OK) goto cleanup_snap;
- hr = CoCreateInstance__(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNullRenderer);
- if (hr != S_OK) goto cleanup_snap;
- hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
- if (hr != S_OK) goto cleanup_snap;
- hr = pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap, pSampleGrabberFilter, pNullRenderer);
- if (hr != S_OK) goto cleanup_snap;
- hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pMediaControl);
- if (hr != S_OK) goto cleanup_snap;
- while(1) {
- hr = pMediaControl->Run();
- if (hr == S_OK) break;
- if (hr == S_FALSE) continue;
- goto cleanup_snap;
- }
- Sleep(1000);
- while(1) {
- hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, NULL);
- if (hr == S_OK && buffer_size != 0) break;
- if (hr != S_OK && hr != VFW_E_WRONG_STATE)
- goto cleanup_snap;
- }
- pMediaControl->Stop();
- pBuffer = new char[buffer_size];
- if (!pBuffer) goto cleanup_snap;
- hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, (long*)pBuffer);
- if (hr != S_OK) goto cleanup_snap;
- hr = pSampleGrabber->GetConnectedMediaType((_AMMediaType *)&mt);
- if (hr != S_OK) goto cleanup_snap;
- if ((mt.formattype == FORMAT_VideoInfo) && (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mt.pbFormat != NULL)) {
- pVih = (VIDEOINFOHEADER*)mt.pbFormat;
- if (buffer_size > maxlen)
- goto cleanup_snap;
- *width = pVih->bmiHeader.biWidth;
- *height = pVih->bmiHeader.biHeight;
- memcpy(buffer,pBuffer,buffer_size);
- // Invert the scanlines
- for (int i = 0; i < (*height)/2; i++) {
- char line[*width*3];
- memcpy(line,&buffer[i*(*width)*3],3*(*width));
- memcpy(&buffer[i*(*width)*3],&buffer[((*height)-i-1)*(*width)*3],3*(*width));
- memcpy(&buffer[((*height)-i-1)*(*width)*3],line,3*(*width));
- }
- }
- else {
- goto cleanup_snap;
- }
- returnv = 1;
- cleanup_snap:
- // Clean up DirectShow / COM stuff
- if (pBuffer != NULL) delete[] pBuffer;
- if (pMediaControl != NULL) pMediaControl->Release();
- if (pNullRenderer != NULL) pNullRenderer->Release();
- if (pSampleGrabber != NULL) pSampleGrabber->Release();
- if (pSampleGrabberFilter != NULL)
- pSampleGrabberFilter->Release();
- if (pCap != NULL) pCap->Release();
- if (pBuilder != NULL) pBuilder->Release();
- if (pGraph != NULL) pGraph->Release();
- if (pPropBag != NULL) pPropBag->Release();
- if (pMoniker != NULL) pMoniker->Release();
- if (pEnum != NULL) pEnum->Release();
- if (pDevEnum != NULL) pDevEnum->Release();
- CoUninitialize__();
- if (mt.cbFormat != 0) {
- CoTaskMemFree__((PVOID)mt.pbFormat);
- }
- if (mt.pUnk != NULL) {
- mt.pUnk->Release();
- }
- return returnv;
- }
- extern "C" {
- __declspec(dllexport) char* __cdecl ListWebcams ();
- __declspec(dllexport) int __cdecl WebcamSnap(int devnum, unsigned char * buffer, int maxlen, int * width, int * height);
- }
- __declspec(dllexport) char* __cdecl ListWebcams () {
- my::vector <my::string> dlist = list_devices();
- int mem_needed = sizeof(int);
- for (unsigned int i = 0; i < dlist.size(); i++) {
- mem_needed += sizeof(int) + dlist[i].size() + 1;
- }
- char * buffer = (char*)malloc(mem_needed);
- int * ptrs = (int*)buffer;
- memset(buffer,0,mem_needed);
- int n = sizeof(int)*(dlist.size()+1);
- for (unsigned int i = 0; i < dlist.size(); i++) {
- ptrs[i] = (&buffer[n])-(&buffer[0]);
- memcpy(&buffer[n],dlist[i].c_str(),dlist[i].size()+1);
- n += dlist[i].size()+1;
- }
- return buffer;
- }
- __declspec(dllexport) int __cdecl WebcamSnap(int devnum, unsigned char * buffer, int maxlen, int * width, int * height) {
- return get_snapshot(devnum, buffer, maxlen, width, height);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement