MFC Camera 摄像头预览 拍照

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 中,自己保存数据。

 

posted @ 2020-03-11 21:04  宁次  阅读(1298)  评论(0编辑  收藏  举报