首页 > 代码库 > Directshow_驱动摄像头预览视频

Directshow_驱动摄像头预览视频

  出于兴趣一直以来都断断续续看过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();	
}

参考资料:

  1. 《Directshow开发指南》
  2. 《directshow SDK 学习笔记》

Directshow_驱动摄像头预览视频