出于兴趣一直以来都断断续续看过dshow的东西,可没怎么系统地总结过(学习还是要多实践,多总结啊).
dshow预览摄像头捕捉的视频比较简单基础,网上相关的资料很多,简单的思路由下面代码所示:
-
ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
-
// Initialize pBuild (not shown).
-
IBaseFilter *pCap; // Video capture filter.
-
/* Initialize pCap and add it to the filter graph (not shown). */
-
hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
-
pCap, NULL, NULL);
dshow 提供了一个 Capture Graph Builder COM 组件使得捕捉graph 图的生成更加简单。 Capture Graph Builder 提供了一 ICaptureGraphBuilder2接口 ,这个接口提供了一些方法用来构建和控制捕捉 graph。video capture filter则由系统设备枚举得到可用视频设备,并生成filter;最后智能连接graph即可.具体见代码和注释:
-
#include <dshow.h>
-
#include <stdio.h>
-
#include <atlconv.h>
-
#pragma comment(lib,"quartz.lib")
-
#pragma comment(lib, "strmiids.lib")
-
void main()
-
{
-
IGraphBuilder *pGraph = NULL;
-
IMediaControl *pControl = NULL;
-
IMediaEvent *pEvent = NULL;
-
IVideoWindow *pVideoWindow = NULL;
-
ICaptureGraphBuilder2 *pBuild = NULL;
-
// Initialize the COM library.
-
HRESULT hr = CoInitialize(NULL);
-
if (FAILED(hr)){
-
printf("ERROR - Could not initialize COM library");
-
return;
-
}
-
//创建Capture Graph Builder 对象
-
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
-
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
-
if (SUCCEEDED(hr)){
-
// 创建 graph manger 对象.
-
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
-
IID_IGraphBuilder, (void**)&pGraph);
-
if (SUCCEEDED(hr))
-
// 初始化 Capture Graph Builder.
-
pBuild->SetFiltergraph(pGraph);
-
}
-
//各个查询接口.
-
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
-
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
-
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow);
-
ICreateDevEnum *pDevEnum = NULL;
-
IEnumMoniker *pEnum = NULL;
-
//创建一个系统设备枚举对象
-
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
-
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,reinterpret_cast<void**>(&pDevEnum));
-
if (SUCCEEDED(hr))
-
//创建一个枚举器,用来枚举视频设备
-
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);
-
IMoniker *pMoniker = NULL;
-
//开始枚举设备
-
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
-
{
-
IBaseFilter *pCap = NULL;
-
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);//为设备生成 filter
-
if (SUCCEEDED(hr))
-
{
-
hr = pGraph->AddFilter(pCap, L"Capture Filter");//将filter加入到graph
-
}
-
if (SUCCEEDED(hr))
-
{
-
//PIN_CATEGORY_PREVIEW: specifying a pin category;
-
//MEDIATYPE_Video: the major media types.
-
//pCap: pointer to the starting filter for the connection
-
hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, pCap, NULL, NULL);//连接graph
-
break;
-
}
-
else{
-
pMoniker->Release();
-
continue; //尝试下一个
-
}
-
}
-
pVideoWindow->put_AutoShow(OATRUE);//graph自动显示视频窗口
-
//pVideoWindow->put_Visible(OATRUE/*OAFALSE*/);
-
if (SUCCEEDED(hr))
-
{
-
// Run the graph.
-
hr = pControl->Run();
-
if (SUCCEEDED(hr)){
-
long evCode;
-
pEvent->WaitForCompletion(INFINITE, &evCode);//一直阻塞在这边;
-
}
-
}
-
pBuild->Release();
-
pMoniker->Release();
-
pControl->Release();
-
pEvent->Release();
-
pGraph->Release();
-
CoUninitialize();
-
}
参考资料:
- 《Directshow开发指南》
- 《directshow SDK 学习笔记》