windows 上开发摄像头程序,比较容易的方式是 OpenCV ,几行代码就能显示出来,但是简单的容易搞,有点难度定制化需求的就不这么容易了。
所以说还是要从,最基础的 DirectShow 开始搞起,网上找了许久,这方面的资料不多。
准备工作:
SDK的下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=8442 下载完成,安装上就行了。
开发环境:win7 x86, vs2010, DirectShow SDK
参考程序:
C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow
先编译一下 baseclasses
C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\capture\amcap
amcap 源码,功能还挺齐全,源码也有,但是有几千行,这里面有的功能是不需要的,的确,直接把这个代码复制到,你的工程里面修改一下,的确是可以使用。
但是这样,还是不知道,其中的原理。
下面新建一个普通的 MFC 程序,配置一些编译属性,对比着 amcap 参考就行。
1,实现获取本机 Camera 列表,音频设备
1 void CSampleCapDlg::AddDevices() 2 { 3 HRESULT hr; 4 5 // enumerate all video capture devices 6 ICreateDevEnum *pCreateDevEnum=0; 7 hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 8 IID_ICreateDevEnum, (void**)&pCreateDevEnum); 9 if(hr != NOERROR) 10 { 11 return; 12 } 13 14 IEnumMoniker *pEm=0; 15 hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0); 16 if(hr != NOERROR) 17 { 18 return; 19 } 20 21 pEm->Reset(); 22 ULONG cFetched; 23 IMoniker *pM; 24 25 while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) 26 { 27 IPropertyBag *pBag=0; 28 29 hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); 30 if(SUCCEEDED(hr)) 31 { 32 VARIANT var; 33 var.vt = VT_BSTR; 34 hr = pBag->Read(L"FriendlyName", &var, NULL); 35 if(hr == NOERROR) 36 { 37 m_ComboBoxVideoDevice.AddString(var.bstrVal); 38 SysFreeString(var.bstrVal); 39 pM->AddRef(); 40 } 41 pBag->Release(); 42 } 43 44 pM->Release(); 45 } 46 pEm->Release(); 47 48 // enumerate all audio capture devices 49 ASSERT(pCreateDevEnum != NULL); 50 51 hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0); 52 pCreateDevEnum->Release(); 53 if(hr != NOERROR) 54 return; 55 pEm->Reset(); 56 57 while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) 58 { 59 IPropertyBag *pBag; 60 hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); 61 if(SUCCEEDED(hr)) 62 { 63 VARIANT var; 64 var.vt = VT_BSTR; 65 hr = pBag->Read(L"FriendlyName", &var, NULL); 66 if(hr == NOERROR) 67 { 68 m_ComboBoxAudioDevice.AddString(var.bstrVal); 69 SysFreeString(var.bstrVal); 70 pM->AddRef(); 71 } 72 pBag->Release(); 73 } 74 pM->Release(); 75 } 76 77 pEm->Release(); 78 }
2,实时预览
代码比较多,不贴了。
3,拍照
写 BMP 这里不讲,很简单一个文件头加内容。 JPG PNG 之类的,要用到第三方库。这里也不讲。
怎么获取图像帧:
1 hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER, 2 IID_IBaseFilter, (LPVOID*)&pSampleGrabberFilter); 3 hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,(LPVOID*)&m_pSampGrabber); 4 hr = m_pSampGrabber->SetCallback(&g_sampleGrabberCB,1); 5 HRESULT STDMETHODCALLTYPE SampleGrabberCallback::BufferCB(double Time, BYTE *pBuffer, long BufferLen)
创建一个 m_pSampGrabber 在重写的 BufferCB 中,自己保存数据。
原文:https://www.cnblogs.com/ningci/p/12457583.html