前些日子在CSDN上遇到很多人问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):
- #include <windows.h>
- #include <mmsystem.h>
- #include "streams.h"
- #include <cs.h>
- #include <csmedia.h>
- #include <camera.h>
- #include <aygshell.h>
- #include "ddcam.h"
- #include "grabber.h"
- #include <windef.h>
-
- #define MAX_LOADSTRING 100
- #define WM_GRAPHNOTIFY WM_APP + 1
- #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
- #define CHK( x ) do{ if( FAILED( hr = ( x ))) { goto Cleanup; }} while( FALSE );
- #define ERR( x ) do{ hr = x; goto Cleanup; } while( FALSE );
-
- #define ARRAYSIZE(s) (sizeof(s) / sizeof(s[0]))
-
- struct _capstuff {
- TCHAR szCaptureFile[_MAX_PATH];
- WORD wCapFileSize;
- ICaptureGraphBuilder2 *pBuilder;
- IVideoWindow *pVWS, *pVWP;
- IMediaEventEx *pME;
- IAMDroppedFrames *pDF;
- IAMVideoCompression *pVC;
- IAMVideoControl *pAMVidControl;
- IAMCameraControl *pCamControl;
- IAMVideoProcAmp *pVProcAmp;
- IAMStreamConfig *pConfigP;
- IAMStreamConfig *pVSC;
- IBaseFilter *pRenderS;
- IBaseFilter *pRenderP;
- IBaseFilter *pCap;
- IGraphBuilder *pGraph;
- CSampleGrabber *pGrab;
- IFileSinkFilter *pSink;
- BOOL fStillGraphBuilt;
- BOOL fPreviewGraphBuilt;
- BOOL fStillCapturing;
- BOOL fPreviewing;
- } gcap;
-
-
- g_hInstance = NULL;
-
- HWND g_hWnd;
-
- HWND g_hWndMenu;
-
- HWND hWndMenuStill = NULL;
-
- ATOM MyRegisterClass (HINSTANCE, LPTSTR);
- BOOL InitInstance (HINSTANCE, int);
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
- LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
- HRESULT SetCapMode(IBaseFilter *pCap);
- HRESULT OpenCamera(LPCOLESTR lpFile,BOOL bCapture,BOOL bStill,BOOL bPreview);
- BOOL WriteBMPToDisk(unsigned char *pStillImageBuffer,long size);
- void UpdatePictureNumber();
- BOOL WriteBMPToTXT(unsigned char *pStillImageBuffer,long lBufferSize);
- HRESULT ActivatePreviousInstance(const TCHAR* pszClass,
- const TCHAR* pszTitle,BOOL* pfActivated);
-
- int g_PicNumber=0;
-
- HRESULT Callback( IMediaSample * pSample, REFERENCE_TIME * StartTime, REFERENCE_TIME *
- StopTime,BOOL TypeChanged )
- {
- unsigned char *pbuf;
- HRESULT hr = S_OK;
-
-
- RETAILMSG(1, (TEXT("Callback with sample %lx for time %ld"),
- pSample, long( *StartTime / 10000 ) ) );
- hr = pSample->GetPointer(&pbuf);
- LONG lSize = pSample->GetActualDataLength();
- BOOL bReturn = WriteBMPToDisk(pbuf,lSize);
- WriteBMPToTXT(pbuf,lSize);
- if(bReturn == FALSE)
- {
- return S_FALSE;
- }
- return hr;
- }
-
- BOOL StartPreview()
- {
- HRESULT hr;
- IMediaControl *pMC = NULL;
- hr = gcap.pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
- if(SUCCEEDED(hr))
- {
- hr = pMC->Run();
- if(FAILED(hr))
- {
-
- pMC->Stop();
- }
- pMC->Release();
- }
- if(FAILED(hr))
- {
- return FALSE;
- }
- return TRUE;
- }
-
-
- BOOL StopPreview() {
-
- if(!gcap.fPreviewing)
- {
- return FALSE;
- }
-
- IMediaControl *pMC = NULL;
- HRESULT hr = gcap.pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
- if(SUCCEEDED(hr))
- {
- hr = pMC->Stop();
- pMC->Release();
- }
- if(FAILED(hr))
- {
- return FALSE;
- }
- gcap.fPreviewing = FALSE;
- return TRUE;
- }
-
- BOOL CloseCamera()
- {
- SAFE_RELEASE(gcap.pCap);
- SAFE_RELEASE(gcap.pConfigP);
- SAFE_RELEASE(gcap.pVWS);
- SAFE_RELEASE(gcap.pVWP);
- SAFE_RELEASE(gcap.pGraph);
- SAFE_RELEASE(gcap.pBuilder);
- return TRUE;
- }
-
- HRESULT CaptureStillImage()
- {
- HRESULT hr;
- hr = SetCapMode(gcap.pCap);
- return hr;
- }
-
- HRESULT InitCapFilter()
- {
- HRESULT hr = S_OK;
- GUID clsid = DEVCLASS_CAMERA_GUID;
- IPersistPropertyBag *pPropertyBag = NULL;
-
- CHK( hr = CoCreateInstance(CLSID_VideoCapture, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter,(void **)&gcap.pCap) );
- DEVMGR_DEVICE_INFORMATION pdi;
- HANDLE hand = FindFirstDevice(DeviceSearchByGuid,&clsid,&pdi);
- RETAILMSG(1, (TEXT("CamTest: Find device: %x %x\r\n"),hand,pdi.szDeviceName));
- CHK( hr = gcap.pCap->QueryInterface(IID_IPersistPropertyBag,
- (void **)&pPropertyBag) );
- if (!SUCCEEDED(hr))
- {
- return hr;
- }
- VARIANT varCamName;
- IPropertyBag *propBag = NULL;
- varCamName.byref = L"CAM1:" ;
- CHK( hr = pPropertyBag->Load(propBag,NULL) );
- SAFE_RELEASE(pPropertyBag);
- Cleanup:
- if(FAILED(hr))
- {
- OutputDebugString(L"Initial Error!");
- SendMessage(g_hWnd,WM_CLOSE,0,0);
- }
- return hr;
- }
-
- HRESULT SetupVideoWindow(IVideoWindow *pVW)
- {
- HRESULT hr = S_OK;
- if (pVW)
- {
- CHK( hr = pVW->SetWindowPosition(0,0,240,268) );
- CHK( hr = pVW->put_Owner((OAHWND)g_hWnd) );
- CHK( hr = pVW->put_WindowStyle(WS_CHILD) );
- }
- Cleanup:
- if(FAILED(hr))
- {
- OutputDebugString(L"Setup window Error!");
- }
- return hr;
- }
-
- HRESULT ConnectFilters(IGraphBuilder *pGraph,IBaseFilter *pF1,
- int iPin1,IBaseFilter *pF2,int iPin2,IPin **ppPinout)
- {
- IPin *pPin1, *pPin2;
- IEnumPins *pEnum;
- unsigned long fetched;
- HRESULT hr = S_OK;
- hr = pF1->EnumPins(&pEnum);
- while (iPin1>0)
- {
- hr = pEnum->Next(1,&pPin1,&fetched);
- iPin1--;
- }
- hr = pEnum->Next(1,&pPin1,&fetched);
- hr = pF2->EnumPins(&pEnum);
- while (iPin2>0)
- {
- hr = pEnum->Next(1,&pPin2,&fetched);
- iPin2--;
- }
- hr = pEnum->Next(1,&pPin2,&fetched);
- hr = pGraph->Connect(pPin1,pPin2);
- if (ppPinout)
- {
- *ppPinout = pPin1;
- }
- if (!SUCCEEDED(hr))
- RETAILMSG(1, (TEXT("CamTest: Fail to Connect Pin! %x\r\n"),hr));
- return hr;
- }
-
- 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);
-
- hr = CoCreateInstance(CLSID_FilterGraph, NULL,
- CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&gcap.pGraph);
-
- 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);
-
-
-
-
-
-
-
-
-
-
- SetupVideoWindow(gcap.pVWP);
- gcap.pVWP->put_MessageDrain((OAHWND)g_hWnd);
- gcap.pVWP->put_Owner((OAHWND)g_hWnd);
-
- return hr;
- }
-
- HRESULT SetCapMode(IBaseFilter *pCap)
- {
- HRESULT hr;
- IPin *pPin = NULL;
- hr = gcap.pCap->FindPin(L"Still",&pPin);
- if (SUCCEEDED(hr))
- {
- hr = gcap.pCap->QueryInterface(IID_IAMVideoControl,(void **)&gcap.pAMVidControl);
- hr = gcap.pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);
- MessageBox(NULL,L"拍照成功,生成的图片保存在根目录下",L"成功",64);
- pPin->Release();
- }
- else
- {
- RETAILMSG(1, (TEXT("CamTest: Fail to Find Pin! %x\r\n"),hr));
- }
- return hr;
- }
-
- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine,int nCmdShow)
- {
- MSG msg;
- HACCEL hAccelTable;
-
- if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- RETAILMSG(1, (TEXT("CoInitialize Failed!\r\n")));
- return FALSE;
- }
-
- if (!InitInstance (hInstance, nCmdShow))
- {
- return FALSE;
- }
- hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WCETEST);
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- CoUninitialize();
- return msg.wParam;
- }
-
-
-
-
-
-
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
- HRESULT hr;
- BOOL fActivated;
- TCHAR szTitle[MAX_LOADSTRING];
-
- TCHAR szWindowClass[MAX_LOADSTRING];
-
- g_hInstance = hInstance;
-
-
- LoadString(hInstance, IDC_WCETEST, szWindowClass, MAX_LOADSTRING);
- WNDCLASS wc;
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = (WNDPROC) WndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WCETEST));
- wc.hCursor = 0;
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = 0;
- wc.lpszClassName = szWindowClass;
- RegisterClass(&wc);
- LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
- if(FAILED(ActivatePreviousInstance(szWindowClass, szTitle, &fActivated))
- ||fActivated)
- {
- return(0);
- }
- g_hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT, GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
- if (!g_hWnd)
- {
- return FALSE;
- }
- ShowWindow(g_hWnd, nCmdShow);
- UpdateWindow(g_hWnd);
- hr = InitCapFilter();
- if (SUCCEEDED(hr))
- {
- BuildGraph();
- StartPreview();
- }
- else
- {
- RETAILMSG(1,(TEXT("CamTest: Fail to create Capture filter. \r\n")));
- }
- return TRUE;
- }
-
-
-
-
- LRESULT OnCreate(HWND hwnd,CREATESTRUCT* lParam)
- {
-
- SHMENUBARINFO mbi;
- ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
- mbi.cbSize = sizeof(SHMENUBARINFO);
- mbi.hwndParent = hwnd;
- mbi.nToolBarId = IDM_MENU;
- mbi.hInstRes = g_hInstance;
- mbi.dwFlags = SHCMBF_HMENU;
- if(!SHCreateMenuBar(&mbi))
- {
-
- return(-1);
- }
- return(0);
- }
-
-
-
-
-
-
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
- LRESULT lResult = TRUE;
- switch(message)
- {
- case WM_CLOSE:
- StopPreview();
- CloseCamera();
- DestroyWindow(hWnd);
- break;
- case WM_CREATE:
- lResult = OnCreate(hWnd, (CREATESTRUCT*)lParam);
- break;
- case WM_COMMAND:
- switch (wParam)
- {
- case ID_CAPTURE:
- CaptureStillImage();
- break;
- }
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- lResult = DefWindowProc(hWnd, message, wParam, lParam);
- break;
- }
- return(lResult);
- }
- BOOL WriteBMPToTXT(unsigned char *pStillImageBuffer,long lBufferSize)
- {
- TCHAR x[256];
- const TCHAR *picture_path = TEXT("\\My Documents\\My Pictures") ;
- UpdatePictureNumber();
- wsprintf(x, TEXT("%s\\%d.txt"), picture_path, g_PicNumber++);
- HANDLE hf = CreateFile(x,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,NULL,NULL);
- if(hf == INVALID_HANDLE_VALUE)
- return FALSE;
- DWORD dwWritten=0;
- if( !WriteFile(hf,pStillImageBuffer,lBufferSize,&dwWritten,NULL) )
- {
- return FALSE;
- }
- CloseHandle(hf);
- return TRUE;
- }
- //保存为24位的图片
- BOOL WriteBMPToDisk(unsigned char *pStillImageBuffer,long lBufferSize)
- {
- TCHAR x[256];
- UpdatePictureNumber();
- wsprintf(x, TEXT("%d.bmp"), g_PicNumber++);
- HANDLE hf = CreateFile(x,GENERIC_WRITE,FILE_SHARE_READ,
- NULL,CREATE_ALWAYS,NULL,NULL);
- if(hf == INVALID_HANDLE_VALUE)
- return FALSE;
- BITMAPFILEHEADER bfh;
- memset(&bfh,0,sizeof(bfh));
- bfh.bfType=0x4D42;
- bfh.bfSize=sizeof(bfh)+lBufferSize+sizeof(BITMAPFILEHEADER);
- bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
- DWORD dwWritten=0;
- WriteFile(hf,&bfh,sizeof(bfh),&dwWritten,NULL);
- BITMAPINFOHEADER bih;
- memset(&bih,0,sizeof(bih));
- bih.biSize=sizeof(bih);
- bih.biWidth=144;
- bih.biHeight=176;
- bih.biPlanes=1;
- bih.biBitCount=24;
- if( !WriteFile(hf,&bih,sizeof(bih),&dwWritten,NULL) )
- {
- return FALSE;
- }
- if( !WriteFile(hf,pStillImageBuffer,lBufferSize,&dwWritten,NULL) )
- {
- return FALSE;
- }
- CloseHandle(hf);
- return TRUE;
- }
- void UpdatePictureNumber()
- {
- DWORD dwSize;
- HANDLE hFile;
- char *buffer;
- buffer = (char *)malloc(1024);
- hFile = CreateFile(TEXT("\\temp\\cam.cfg"), GENERIC_WRITE | GENERIC_READ,
- 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- dwSize = 0;
- if (hFile == INVALID_HANDLE_VALUE)
- {
- g_PicNumber = 1;
- hFile = CreateFile(TEXT("\\temp\\cam.cfg"), GENERIC_WRITE | GENERIC_READ,
- 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- buffer[0] = g_PicNumber & 0x00FF;
- buffer[1] = (g_PicNumber & 0xFF00) >> 8;
-
- WriteFile(hFile, buffer, 2, &dwSize, NULL);
- CloseHandle(hFile);
- } else
- {
- dwSize = 0;
- ReadFile(hFile, buffer, 2, &dwSize, NULL);
- g_PicNumber = buffer[1];
- g_PicNumber <<= 8;
- g_PicNumber |= buffer[0];
- g_PicNumber++;
- CloseHandle(hFile);
- hFile = CreateFile(TEXT("\\temp\\cam.cfg"), GENERIC_WRITE | GENERIC_READ,
- 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- buffer[0] = g_PicNumber & 0x00FF;
- buffer[1] = (g_PicNumber & 0xFF00) >> 8;
- dwSize = 0;
- WriteFile(hFile, buffer, 2, &dwSize, NULL);
- CloseHandle(hFile);
- }
- free(buffer);
- }
-
- HRESULT ActivatePreviousInstance(const TCHAR* pszClass,
- const TCHAR* pszTitle,BOOL* pfActivated)
- {
- HRESULT hr = S_OK;
- int cTries;
- HANDLE hMutex = NULL;
-
- *pfActivated = FALSE;
- cTries = 5;
- while(cTries > 0)
- {
- hMutex = CreateMutex(NULL, FALSE, pszClass);
- if(NULL == hMutex)
- {
-
- hr = E_FAIL;
- goto Exit;
- }
-
- if(GetLastError() == ERROR_ALREADY_EXISTS)
- {
- HWND hwnd;
-
- CloseHandle(hMutex);
- hMutex = NULL;
-
-
-
-
- hwnd = FindWindow(pszClass, pszTitle);
- if(NULL == hwnd)
- {
-
- Sleep(500);
- hwnd = FindWindow(pszClass, pszTitle);
- }
-
- if(NULL != hwnd)
- {
-
-
-
-
- SetForegroundWindow((HWND) (((ULONG) hwnd) | 0x01));
-
-
- *pfActivated = TRUE;
- break;
- }
-
-
-
- cTries--;
- }
- else
- {
-
-
-
-
- break;
- }
- }
- if(cTries <= 0)
- {
-
-
- hr = E_FAIL;
- goto Exit;
- }
- Exit:
- return(hr);
- }
-
- void setscreenMetrics(HWND hWnd,int width,int height)
- {
- DEVMODE lpDevMode;
- lpDevMode.dmBitsPerPel=24;
- lpDevMode.dmPelsWidth=width;
- lpDevMode.dmPelsHeight=height;
- lpDevMode.dmSize=sizeof(lpDevMode);
- lpDevMode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
- LONG result;
- result=ChangeDisplaySettingsEx(NULL,&lpDevMode,hWnd,0,NULL);
- if(result==DISP_CHANGE_SUCCESSFUL)
- {
- MessageBoxW(hWnd,_T("success!"),_T("alert"),MB_OK);
- }
- else
- {
- MessageBoxW(hWnd,_T("failure!"),_T("alert"),MB_OK);
- }
- }
主要构建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);
-
-
- hr = CoCreateInstance(CLSID_FilterGraph, NULL,
- CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&gcap.pGraph);
-
-
- 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);
-
-
-
-
-
-
-
-
-
-
-
-
-
- SetupVideoWindow(gcap.pVWP);
- gcap.pVWP->put_MessageDrain((OAHWND)g_hWnd);
- gcap.pVWP->put_Owner((OAHWND)g_hWnd);
-
- 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://bbs.rosoo.net/thread-828-1-1.html
有问题多多联系!
(czbever) |