前些日子在优快云上遇到很多人问directshow是如何驱动摄象头的,看来很多人对于directshow的一些基本知识还不够清晰,于是我就写一篇文章介绍一下:
directshow的原理大概大家都知道,基本就是用微软封装的接口来实现硬件无关性,但是最终调用的接口都要在驱动层有对应的实现:
为了更清楚地演示directshow的数据传输过程,我必须说明的这个程序的基本流程。我采用的是vs2005 + windows mobile 6。0 professional 仿真模拟器,驱动层传出的是176*144格式的rgb565的数据,最后我将保存图片为RGB24的bmp图片。
说明:source filter从驱动层获取数据后一般分成两个pin将数据传出,一个是still pin用于传输静态数据,一帧的数据,一个是capture pin用于传出连续的视频数据,用RenderStream的方式gcap.pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, gcap.pCap, NULL, gcap.pRenderP);默认会产生Smart Tee这个filter,这个filter将接收到的数据分成两份,同样也是分成两个pin传出,本例中我只用到smartTee传出的preview这个pin,连接到Render Filter以显示图象数据.
以下是主要程序部分(DDCam.cpp):
主要构建Graph的代码:
HRESULT BuildGraph()
{
HRESULT hr;
gcap.pGrab = new CSampleGrabber(NULL,&hr,FALSE);
gcap.pGrab->AddRef();
gcap.pGrab->SetCallback(&Callback);
CMediaType mt;
mt.SetType(&MEDIATYPE_Video);
mt.SetSubtype(&MEDIASUBTYPE_RGB24);
gcap.pGrab->SetAcceptedMediaType(&mt);
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&gcap.pGraph);
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&gcap.pBuilder);
hr = gcap.pGraph->AddFilter(gcap.pCap,L"Video Capture Source");
hr = gcap.pGraph->AddFilter(gcap.pGrab,L"SampleGrabber");
gcap.pBuilder->SetFiltergraph(gcap.pGraph);
hr = CoCreateInstance(CLSID_VideoRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void **)&gcap.pRenderP);
hr = CoCreateInstance(CLSID_VideoRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void **)&gcap.pRenderS);
hr = gcap.pGraph->AddFilter(gcap.pRenderP,L"Video Render");
hr = gcap.pGraph->AddFilter(gcap.pRenderS,L"Video Render");
hr = gcap.pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, gcap.pCap, NULL, gcap.pRenderP);
hr = gcap.pRenderP->QueryInterface(IID_IVideoWindow, (void**)&gcap.pVWP);
hr = gcap.pBuilder->RenderStream(&PIN_CATEGORY_STILL,&MEDIATYPE_Video, gcap.pCap, gcap.pGrab, gcap.pRenderS);
// Query for video interfaces, which may not be relevant for audio files
//hr = gcap.pGraph->QueryInterface(IID_IMediaEventEx, (void **)&gcap.pME);
//hr = gcap.pCap->QueryInterface(IID_IAMVideoProcAmp,(void **)&gcap.pVProcAmp);
Query the output pin for IAMStreamConfig (not shown).
//hr = gcap.pBuilder->FindInterface(
// &PIN_CATEGORY_PREVIEW, // Preview pin.
// 0, // Any media type.
// gcap.pCap, // Pointer to the capture filter.
// IID_IAMStreamConfig, (void**)&gcap.pConfigP);
// Have the graph signal event via window callbacks for performance
SetupVideoWindow(gcap.pVWP);
gcap.pVWP->put_MessageDrain((OAHWND)g_hWnd);
gcap.pVWP->put_Owner((OAHWND)g_hWnd);
//hr = gcap.pME->SetNotifyWindow((OAHWND)g_hWnd, WM_GRAPHNOTIFY, 0);
return hr;
}
另外SampleGrabber这个filter是要一个transform filter,可以在 directx 的directshow sample里找到,主要代码如下(Grabber.cpp):
还有个头文件Grabber.h:
另外还可以自己编译baseclasses里的工程生成mobile下的strmbasd.lib 和 strmbase.lib,当然,windows mobile6是有自己的strmbase.lib的,只有strmbasd.lib没有而已,不过你可以通过AKU目录下的baseclasses来编译生成wm下的baseclasses工程,这样便于调试. 其中strmbasd.lib和strmbase.lib分别用于Debug和Release下的。
很简单吧
代码下载处: http://download.youkuaiyun.com/source/2185421
有问题多多联系!