zdirectshow的原理大概大家都知道,基本就是用微软封装的接口来实现硬件无关性,但是最终调用的接口都要在驱动层有对应的实现:

为了更清楚地演示directshow的数据传输过程,我必须说明的这个程序的基本流程。我采用的是vs2005 + windows mobile 6。0 professional 仿真模拟器,驱动层传出的是176*144格式的rgb565的数据,最后我将保存图片为RGB24的bmppdf图片。

说明: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):

view plaincopy to clipboardprint?
  1. #include <windows.h>
  2. #include <mmsystem.h>
  3. #include "streams.h"
  4. #include <cs.h>
  5. #include <csmedia.h>
  6. #include <camera.h>
  7. #include <aygshell.h>
  8. #include "ddcam.h"
  9. #include "grabber.h"
  10. #include <windef.h>
  11. #define MAX_LOADSTRING 100
  12. #define WM_GRAPHNOTIFY  WM_APP + 1
  13. #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
  14. #define CHK( x ) do{ if( FAILED( hr = ( x ))) { goto Cleanup; }} while( FALSE );
  15. #define ERR( x ) do{ hr = x; goto Cleanup; } while( FALSE );
  16. #define ARRAYSIZE(s) (sizeof(s) / sizeof(s[0]))
  17. struct _capstuff
  18. {
  19. TCHAR szCaptureFile[_MAX_PATH];
  20. WORD wCapFileSize;
  21. ICaptureGraphBuilder2 *pBuilder;
  22. IVideoWindow *pVWS, *pVWP;
  23. IMediaEventEx *pME;
  24. IAMDroppedFrames *pDF;
  25. IAMVideoCompression *pVC;
  26. IAMVideoControl *pAMVidControl;
  27. IAMCameraControl *pCamControl;
  28. IAMVideoProcAmp  *pVProcAmp;
  29. IAMStreamConfig  *pConfigP; //Preview config
  30. IAMStreamConfig *pVSC;      // for video cap
  31. IBaseFilter *pRenderS;      //Still render
  32. IBaseFilter *pRenderP;      //Preview render
  33. IBaseFilter *pCap;
  34. IGraphBuilder *pGraph;
  35. CSampleGrabber *pGrab;
  36. IFileSinkFilter *pSink;
  37. BOOL fStillGraphBuilt;
  38. BOOL fPreviewGraphBuilt;
  39. BOOL fStillCapturing;
  40. BOOL fPreviewing;
  41. } gcap;
  42. // Global Variables:
  43. HINSTANCE           g_hInstance = NULL;         // The current instance
  44. HWND                g_hWnd;         //The window instance
  45. HWND                g_hWndMenu;             //Menu handle
  46. HWND                hWndMenuStill = NULL;
  47. // Forward declarations of functions included in this code module:
  48. ATOM                MyRegisterClass (HINSTANCE, LPTSTR);
  49. BOOL                InitInstance    (HINSTANCE, int);
  50. LRESULT CALLBACK    WndProc         (HWND, UINT, WPARAM, LPARAM);
  51. LRESULT CALLBACK    About           (HWND, UINT, WPARAM, LPARAM);
  52. HRESULT SetCapMode(IBaseFilter *pCap);
  53. HRESULT OpenCamera(LPCOLESTR lpFile,BOOL bCapture,BOOL bStill,BOOL bPreview);
  54. BOOL WriteBMPToDisk(unsigned char *pStillImageBuffer,long size);
  55. void UpdatePictureNumber();
  56. BOOL WriteBMPToTXT(unsigned char *pStillImageBuffer,long lBufferSize);
  57. HRESULT ActivatePreviousInstance(const TCHAR* pszClass,const TCHAR* pszTitle,BOOL* pfActivated);
  58. int g_PicNumber=0;
  59. HRESULT Callback( IMediaSample * pSample, REFERENCE_TIME * StartTime, REFERENCE_TIME *
  60. StopTime,BOOL TypeChanged )
  61. {
  62. unsigned char *pbuf;
  63. HRESULT  hr = S_OK;
  64. // NOTE: We cannot do anything with this sample until we call GetConnectedMediaType
  65. // on the filter to find out what format these samples are.
  66. RETAILMSG(1, (TEXT("Callback with sample %lx for time %ld"), pSample, long( *StartTime / 10000 )  ) );
  67. hr = pSample->GetPointer(&pbuf);
  68. LONG lSize = pSample->GetActualDataLength();
  69. BOOL bReturn = WriteBMPToDisk(pbuf,lSize);
  70. WriteBMPToTXT(pbuf,lSize);
  71. if(bReturn == FALSE)
  72. {
  73. return S_FALSE;
  74. }
  75. return hr ;
  76. }
  77. BOOL StartPreview()
  78. {
  79. HRESULT hr;
  80. IMediaControl *pMC = NULL;
  81. hr = gcap.pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
  82. if(SUCCEEDED(hr))
  83. {
  84. hr = pMC->Run();
  85. if(FAILED(hr))
  86. {
  87. // stop parts that ran
  88. pMC->Stop();
  89. }
  90. pMC->Release();
  91. }
  92. if(FAILED(hr))
  93. {
  94. return FALSE;
  95. }
  96. return TRUE;
  97. }
  98. // stop the preview graph
  99. //
  100. BOOL StopPreview()
  101. {
  102. // way ahead of you
  103. if(!gcap.fPreviewing)
  104. {
  105. return FALSE;
  106. }
  107. // stop the graph
  108. IMediaControl *pMC = NULL;
  109. HRESULT hr = gcap.pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
  110. if(SUCCEEDED(hr))
  111. {
  112. hr = pMC->Stop();
  113. pMC->Release();
  114. }
  115. if(FAILED(hr))
  116. {
  117. return FALSE;
  118. }
  119. gcap.fPreviewing = FALSE;
  120. return TRUE;
  121. }
  122. BOOL CloseCamera()
  123. {
  124. SAFE_RELEASE(gcap.pCap);
  125. SAFE_RELEASE(gcap.pConfigP);
  126. SAFE_RELEASE(gcap.pVWS);
  127. SAFE_RELEASE(gcap.pVWP);
  128. SAFE_RELEASE(gcap.pGraph);
  129. SAFE_RELEASE(gcap.pBuilder);
  130. return TRUE;
  131. }
  132. HRESULT CaptureStillImage()
  133. {
  134. HRESULT hr;
  135. hr = SetCapMode(gcap.pCap); //Run still pin
  136. return hr;
  137. }
  138. HRESULT InitCapFilter()
  139. {
  140. HRESULT hr = S_OK;
  141. GUID clsid = DEVCLASS_CAMERA_GUID;
  142. IPersistPropertyBag *pPropertyBag = NULL;
  143. // Create Capture Filter
  144. CHK( hr = CoCreateInstance(CLSID_VideoCapture, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter,
  145. (void **)&gcap.pCap) );
  146. DEVMGR_DEVICE_INFORMATION pdi;
  147. HANDLE hand = FindFirstDevice(DeviceSearchByGuid,&clsid,&pdi);
  148. RETAILMSG(1, (TEXT("CamTest: Find device: %x %x/r/n"),hand,pdi.szDeviceName));
  149. CHK( hr = gcap.pCap->QueryInterface(IID_IPersistPropertyBag, (void **)&pPropertyBag) );
  150. if (!SUCCEEDED(hr))
  151. {
  152. return hr;
  153. }
  154. VARIANT varCamName;
  155. IPropertyBag *propBag = NULL;
  156. varCamName.byref =  L"CAM1:" ;
  157. CHK( hr = pPropertyBag->Load(propBag,NULL) );
  158. SAFE_RELEASE(pPropertyBag);
  159. Cleanup:
  160. if(FAILED(hr))
  161. {
  162. OutputDebugString(L"Initial Error!");
  163. SendMessage(g_hWnd,WM_CLOSE,0,0);
  164. }
  165. return hr;
  166. }
  167. HRESULT SetupVideoWindow(IVideoWindow *pVW)
  168. {
  169. HRESULT hr = S_OK;
  170. if (pVW)
  171. {
  172. CHK( hr = pVW->SetWindowPosition(0,0,240,268) );
  173. CHK( hr = pVW->put_Owner((OAHWND)g_hWnd) );
  174. CHK( hr = pVW->put_WindowStyle(WS_CHILD) );
  175. }
  176. Cleanup:
  177. if(FAILED(hr))
  178. {
  179. OutputDebugString(L"Setup window Error!");
  180. }
  181. return hr;
  182. }
  183. HRESULT ConnectFilters(IGraphBuilder *pGraph,IBaseFilter *pF1, int iPin1,IBaseFilter *pF2,int iPin2,IPin **ppPinout)
  184. {
  185. IPin *pPin1, *pPin2;
  186. IEnumPins    *pEnum;
  187. unsigned long fetched;
  188. HRESULT hr = S_OK;
  189. hr = pF1->EnumPins(&pEnum);
  190. while (iPin1>0)
  191. {
  192. hr = pEnum->Next(1,&pPin1,&fetched); //Skip Capture  pin
  193. iPin1--;
  194. }
  195. hr = pEnum->Next(1,&pPin1,&fetched);
  196. hr = pF2->EnumPins(&pEnum);
  197. while (iPin2>0)
  198. {
  199. hr = pEnum->Next(1,&pPin2,&fetched); //Skip Capture  pin
  200. iPin2--;
  201. }
  202. hr = pEnum->Next(1,&pPin2,&fetched);
  203. hr = pGraph->Connect(pPin1,pPin2);
  204. if (ppPinout)
  205. {
  206. *ppPinout = pPin1;
  207. }
  208. if (!SUCCEEDED(hr))
  209. RETAILMSG(1, (TEXT("CamTest: Fail to Connect Pin! %x/r/n"),hr));
  210. return hr;
  211. }
  212. HRESULT BuildGraph()
  213. {
  214. HRESULT hr;
  215. gcap.pGrab = new CSampleGrabber(NULL,&hr,FALSE);
  216. gcap.pGrab->AddRef();
  217. gcap.pGrab->SetCallback(&Callback);
  218. CMediaType mt;
  219. mt.SetType(&MEDIATYPE_Video);
  220. mt.SetSubtype(&MEDIASUBTYPE_RGB24);
  221. gcap.pGrab->SetAcceptedMediaType(&mt);
  222. // Create the Filter Graph Manager.
  223. hr =  CoCreateInstance(CLSID_FilterGraph, NULL,
  224. CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&gcap.pGraph);
  225. // Create the Capture Graph Builder.
  226. hr = CoCreateInstance(CLSID_CaptureGraphBuilder, NULL,
  227. CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
  228. (void **)&gcap.pBuilder);
  229. hr = gcap.pGraph->AddFilter(gcap.pCap,L"Video Capture Source");
  230. hr = gcap.pGraph->AddFilter(gcap.pGrab,L"SampleGrabber");
  231. gcap.pBuilder->SetFiltergraph(gcap.pGraph);
  232. hr = CoCreateInstance(CLSID_VideoRenderer, NULL,
  233. CLSCTX_INPROC_SERVER, IID_IBaseFilter,
  234. (void **)&gcap.pRenderP);
  235. hr = CoCreateInstance(CLSID_VideoRenderer, NULL,
  236. CLSCTX_INPROC_SERVER, IID_IBaseFilter,
  237. (void **)&gcap.pRenderS);
  238. hr = gcap.pGraph->AddFilter(gcap.pRenderP,L"Video Render");
  239. hr = gcap.pGraph->AddFilter(gcap.pRenderS,L"Video Render");
  240. hr = gcap.pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, gcap.pCap, NULL, gcap.pRenderP);
  241. hr = gcap.pRenderP->QueryInterface(IID_IVideoWindow, (void**)&gcap.pVWP);
  242. hr = gcap.pBuilder->RenderStream(&PIN_CATEGORY_STILL,&MEDIATYPE_Video, gcap.pCap, gcap.pGrab, gcap.pRenderS);
  243. // Query for video interfaces, which may not be relevant for audio files
  244. //hr = gcap.pGraph->QueryInterface(IID_IMediaEventEx, (void **)&gcap.pME);
  245. //hr = gcap.pCap->QueryInterface(IID_IAMVideoProcAmp,(void **)&gcap.pVProcAmp);
  246. Query the output pin for IAMStreamConfig (not shown).
  247. //hr = gcap.pBuilder->FindInterface(
  248. //  &PIN_CATEGORY_PREVIEW, // Preview pin.
  249. //  0,    // Any media type.
  250. //  gcap.pCap, // Pointer to the capture filter.
  251. //  IID_IAMStreamConfig, (void**)&gcap.pConfigP);
  252. // Have the graph signal event via window callbacks for performance
  253. SetupVideoWindow(gcap.pVWP);
  254. gcap.pVWP->put_MessageDrain((OAHWND)g_hWnd);
  255. gcap.pVWP->put_Owner((OAHWND)g_hWnd);
  256. //hr = gcap.pME->SetNotifyWindow((OAHWND)g_hWnd, WM_GRAPHNOTIFY, 0);
  257. return hr;
  258. }
  259. HRESULT SetCapMode(IBaseFilter *pCap)
  260. {
  261. HRESULT hr;
  262. IPin *pPin = NULL;
  263. hr = gcap.pCap->FindPin(L"Still",&pPin);
  264. if (SUCCEEDED(hr))
  265. {
  266. hr = gcap.pCap->QueryInterface(IID_IAMVideoControl,(void **)&gcap.pAMVidControl);
  267. hr = gcap.pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);
  268. MessageBox(NULL,L"拍照成功,生成的图片保存在根目录下",L"成功",64);
  269. pPin->Release();
  270. }
  271. else
  272. {
  273. RETAILMSG(1, (TEXT("CamTest: Fail to Find Pin! %x/r/n"),hr));
  274. }
  275. return hr;
  276. }
  277. int WINAPI WinMain( HINSTANCE hInstance,
  278. HINSTANCE hPrevInstance,
  279. LPTSTR    lpCmdLine,
  280. int       nCmdShow)
  281. {
  282. MSG msg;
  283. HACCEL hAccelTable;
  284. //Init COM
  285. // Get COM interfaces
  286. if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
  287. {
  288. RETAILMSG(1, (TEXT("CoInitialize Failed!/r/n")));
  289. return FALSE;
  290. }
  291. // Perform application initialization:
  292. if (!InitInstance (hInstance, nCmdShow))
  293. {
  294. return FALSE;
  295. }
  296. hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WCETEST);
  297. // Main message loop:
  298. while (GetMessage(&msg, NULL, 0, 0))
  299. {
  300. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  301. {
  302. TranslateMessage(&msg);
  303. DispatchMessage(&msg);
  304. }
  305. }
  306. // Finished with COM
  307. CoUninitialize();
  308. return msg.wParam;
  309. }
  310. //
  311. //  FUNCTION: InitInstance(HANDLE, int)
  312. //
  313. //  PURPOSE: Saves instance handle and creates main window
  314. //
  315. //  COMMENTS:
  316. //
  317. //    In this function, we save the instance handle in a global variable and
  318. //    create and display the main program window.
  319. //
  320. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  321. {
  322. HRESULT hr;
  323. BOOL fActivated;
  324. TCHAR   szTitle[MAX_LOADSTRING];            // The title bar text
  325. TCHAR   szWindowClass[MAX_LOADSTRING];      // The window class name
  326. g_hInstance = hInstance;        // Store instance handle in our global variable
  327. // Initialize global strings
  328. LoadString(hInstance, IDC_WCETEST, szWindowClass, MAX_LOADSTRING);
  329. WNDCLASS    wc;
  330. wc.style            = CS_HREDRAW | CS_VREDRAW;
  331. wc.lpfnWndProc      = (WNDPROC) WndProc;
  332. wc.cbClsExtra       = 0;
  333. wc.cbWndExtra       = 0;
  334. wc.hInstance        = hInstance;
  335. wc.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WCETEST));
  336. wc.hCursor          = 0;
  337. wc.hbrBackground    = (HBRUSH) GetStockObject(WHITE_BRUSH);
  338. wc.lpszMenuName     = 0;
  339. wc.lpszClassName    = szWindowClass;
  340. RegisterClass(&wc);
  341. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  342. if(FAILED(ActivatePreviousInstance(szWindowClass, szTitle, &fActivated)) ||
  343. fActivated)
  344. {
  345. return(0);
  346. }
  347. g_hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
  348. CW_USEDEFAULT, CW_USEDEFAULT, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
  349. if (!g_hWnd)
  350. {
  351. return FALSE;
  352. }
  353. ShowWindow(g_hWnd, nCmdShow);
  354. UpdateWindow(g_hWnd);
  355. hr = InitCapFilter();
  356. if (SUCCEEDED(hr))
  357. {
  358. BuildGraph();
  359. StartPreview();
  360. }
  361. else
  362. {
  363. RETAILMSG(1,(TEXT("CamTest: Fail to create Capture filter. /r/n")));
  364. }
  365. return TRUE;
  366. }
  367. /**************************************************************************************
  368. OnCreate
  369. **************************************************************************************/
  370. LRESULT OnCreate(
  371. HWND hwnd,
  372. CREATESTRUCT* lParam
  373. )
  374. {
  375. // create the menu bar
  376. SHMENUBARINFO mbi;
  377. ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
  378. mbi.cbSize = sizeof(SHMENUBARINFO);
  379. mbi.hwndParent = hwnd;
  380. mbi.nToolBarId = IDM_MENU;
  381. mbi.hInstRes = g_hInstance;
  382. mbi.dwFlags = SHCMBF_HMENU;
  383. if(!SHCreateMenuBar(&mbi))
  384. {
  385. // Couldn't create the menu bar.  Fail creation of the window.
  386. return(-1);
  387. }
  388. return(0); // continue creation of the window
  389. }
  390. //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
  391. //
  392. //  PURPOSE:  Processes messages for the main window.
  393. //
  394. //  WM_COMMAND  - process the application menu
  395. //  WM_PAINT    - Paint the main window
  396. //  WM_DESTROY  - post a quit message and return
  397. //
  398. //
  399. /**************************************************************************************
  400. WndProc
  401. **************************************************************************************/
  402. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  403. {
  404. LRESULT lResult = TRUE;
  405. switch(message)
  406. {
  407. case WM_CLOSE:
  408. StopPreview();
  409. CloseCamera();
  410. DestroyWindow(hWnd);
  411. break;
  412. case WM_CREATE:
  413. lResult = OnCreate(hWnd, (CREATESTRUCT*)lParam);
  414. break;
  415. case WM_COMMAND:
  416. switch (wParam)
  417. {
  418. case ID_CAPTURE:
  419. CaptureStillImage();
  420. break;
  421. }
  422. break;
  423. case WM_DESTROY:
  424. PostQuitMessage(0);
  425. break;
  426. default:
  427. lResult = DefWindowProc(hWnd, message, wParam, lParam);
  428. break;
  429. }
  430. return(lResult);
  431. }
  432. BOOL WriteBMPToTXT(unsigned char *pStillImageBuffer,long lBufferSize)
  433. {
  434. TCHAR x[256];
  435. const TCHAR *picture_path = TEXT("//My Documents//My Pictures") ;
  436. UpdatePictureNumber();
  437. wsprintf(x, TEXT("%s//%d.txt"), picture_path, g_PicNumber++);
  438. HANDLE hf = CreateFile(x,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,NULL,NULL);
  439. if(hf == INVALID_HANDLE_VALUE)
  440. return FALSE;
  441. DWORD dwWritten=0;
  442. if( !WriteFile(hf,pStillImageBuffer,lBufferSize,&dwWritten,NULL) )
  443. {
  444. return FALSE;
  445. }
  446. CloseHandle(hf);
  447. return TRUE;
  448. }
  449. BOOL WriteBMPToDisk(unsigned char *pStillImageBuffer,long lBufferSize)//保存为24位的图片
  450. {
  451. TCHAR x[256];
  452. UpdatePictureNumber();
  453. wsprintf(x, TEXT("%d.bmp"), g_PicNumber++);
  454. HANDLE hf = CreateFile(x,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,NULL,NULL);
  455. if(hf == INVALID_HANDLE_VALUE)
  456. return FALSE;
  457. BITMAPFILEHEADER bfh;
  458. memset(&bfh,0,sizeof(bfh));
  459. bfh.bfType=0x4D42/*((WORD) ('M' << 8) | 'B')*/;
  460. bfh.bfSize=sizeof(bfh)+lBufferSize+sizeof(BITMAPFILEHEADER);
  461. bfh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
  462. DWORD dwWritten=0;
  463. WriteFile(hf,&bfh,sizeof(bfh),&dwWritten,NULL);
  464. BITMAPINFOHEADER bih;
  465. memset(&bih,0,sizeof(bih));
  466. bih.biSize=sizeof(bih);
  467. bih.biWidth=144;
  468. bih.biHeight=176;
  469. bih.biPlanes=1;
  470. bih.biBitCount=24;
  471. if( !WriteFile(hf,&bih,sizeof(bih),&dwWritten,NULL) )
  472. {
  473. return FALSE;
  474. }
  475. if( !WriteFile(hf,pStillImageBuffer,lBufferSize,&dwWritten,NULL) )
  476. {
  477. return FALSE;
  478. }
  479. CloseHandle(hf);
  480. return TRUE;
  481. }
  482. //
  483. Look for cam.cfg
  484. If it doesn't exist, create it, and set picture number to 1.
  485. If it exists, read the value stored inside, increment the number, and write it back.
  486. void UpdatePictureNumber()
  487. {
  488. DWORD dwSize;
  489. HANDLE hFile;
  490. char *buffer;
  491. buffer = (char *)malloc(1024);
  492. hFile = CreateFile(TEXT("//temp//cam.cfg"), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  493. dwSize = 0;
  494. if (hFile == INVALID_HANDLE_VALUE)
  495. {
  496. // File did not exist, so we are going to create it, and initialize the counter.
  497. g_PicNumber = 1;
  498. hFile = CreateFile(TEXT("//temp//cam.cfg"), GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  499. buffer[0] = g_PicNumber & 0x00FF;
  500. buffer[1] = (g_PicNumber & 0xFF00) >> 8;
  501. WriteFile(hFile, buffer, 2, &dwSize, NULL);
  502. CloseHandle(hFile);
  503. } else
  504. {
  505. dwSize = 0;
  506. ReadFile(hFile, buffer, 2, &dwSize, NULL);
  507. g_PicNumber = buffer[1];
  508. g_PicNumber <<= 8;
  509. g_PicNumber |= buffer[0];
  510. g_PicNumber++;
  511. CloseHandle(hFile);
  512. hFile = CreateFile(TEXT("//temp//cam.cfg"), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  513. buffer[0] = g_PicNumber & 0x00FF;
  514. buffer[1] = (g_PicNumber & 0xFF00) >> 8;
  515. dwSize = 0;
  516. WriteFile(hFile, buffer, 2, &dwSize, NULL);
  517. CloseHandle(hFile);
  518. }
  519. free(buffer);
  520. }
  521. /****************************************************************************
  522. ActivatePreviousInstance
  523. ****************************************************************************/
  524. HRESULT ActivatePreviousInstance(
  525. const TCHAR* pszClass,
  526. const TCHAR* pszTitle,
  527. BOOL* pfActivated
  528. )
  529. {
  530. HRESULT hr = S_OK;
  531. int cTries;
  532. HANDLE hMutex = NULL;
  533. *pfActivated = FALSE;
  534. cTries = 5;
  535. while(cTries > 0)
  536. {
  537. hMutex = CreateMutex(NULL, FALSE, pszClass); // NOTE: We don't want to own the object.
  538. if(NULL == hMutex)
  539. {
  540. // Something bad happened, fail.
  541. hr = E_FAIL;
  542. goto Exit;
  543. }
  544. if(GetLastError() == ERROR_ALREADY_EXISTS)
  545. {
  546. HWND hwnd;
  547. CloseHandle(hMutex);
  548. hMutex = NULL;
  549. // There is already an instance of this app
  550. // running.  Try to bring it to the foreground.
  551. hwnd = FindWindow(pszClass, pszTitle);
  552. if(NULL == hwnd)
  553. {
  554. // It's possible that the other window is in the process of being created...
  555. Sleep(500);
  556. hwnd = FindWindow(pszClass, pszTitle);
  557. }
  558. if(NULL != hwnd)
  559. {
  560. // Set the previous instance as the foreground window
  561. // The "| 0x01" in the code below activates
  562. // the correct owned window of the
  563. // previous instance's main window.
  564. SetForegroundWindow((HWND) (((ULONG) hwnd) | 0x01));
  565. // We are done.
  566. *pfActivated = TRUE;
  567. break;
  568. }
  569. // It's possible that the instance we found isn't coming up,
  570. // but rather is going down.  Try again.
  571. cTries--;
  572. }
  573. else
  574. {
  575. // We were the first one to create the mutex
  576. // so that makes us the main instance.  'leak'
  577. // the mutex in this function so it gets cleaned
  578. // up by the OS when this instance exits.
  579. break;
  580. }
  581. }
  582. if(cTries <= 0)
  583. {
  584. // Someone else owns the mutex but we cannot find
  585. // their main window to activate.
  586. hr = E_FAIL;
  587. goto Exit;
  588. }
  589. Exit:
  590. return(hr);
  591. }
  592. void setscreenMetrics(HWND hWnd,int width,int height)
  593. {
  594. DEVMODE lpDevMode;
  595. lpDevMode.dmBitsPerPel=24;
  596. lpDevMode.dmPelsWidth=width;
  597. lpDevMode.dmPelsHeight=height;
  598. lpDevMode.dmSize=sizeof(lpDevMode);
  599. lpDevMode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
  600. LONG result;
  601. result=ChangeDisplaySettingsEx(NULL,&lpDevMode,hWnd,0,NULL);
  602. if(result==DISP_CHANGE_SUCCESSFUL)
  603. {
  604. MessageBoxW(hWnd,_T("success!"),_T("alert"),MB_OK);
  605. }
  606. else
  607. {
  608. MessageBoxW(hWnd,_T("failure!"),_T("alert"),MB_OK);
  609. }
  610. }

#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; //Preview config IAMStreamConfig *pVSC; // for video cap IBaseFilter *pRenderS; //Still render IBaseFilter *pRenderP; //Preview render IBaseFilter *pCap; IGraphBuilder *pGraph; CSampleGrabber *pGrab; IFileSinkFilter *pSink; BOOL fStillGraphBuilt; BOOL fPreviewGraphBuilt; BOOL fStillCapturing; BOOL fPreviewing; } gcap; // Global Variables: HINSTANCE g_hInstance = NULL; // The current instance HWND g_hWnd; //The window instance HWND g_hWndMenu; //Menu handle HWND hWndMenuStill = NULL; // Forward declarations of functions included in this code module: 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; // NOTE: We cannot do anything with this sample until we call GetConnectedMediaType // on the filter to find out what format these samples are. 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)) { // stop parts that ran pMC->Stop(); } pMC->Release(); } if(FAILED(hr)) { return FALSE; } return TRUE; } // stop the preview graph // BOOL StopPreview() { // way ahead of you if(!gcap.fPreviewing) { return FALSE; } // stop the graph 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); //Run still pin return hr; } HRESULT InitCapFilter() { HRESULT hr = S_OK; GUID clsid = DEVCLASS_CAMERA_GUID; IPersistPropertyBag *pPropertyBag = NULL; // Create Capture Filter 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); //Skip Capture pin iPin1--; } hr = pEnum->Next(1,&pPin1,&fetched); hr = pF2->EnumPins(&pEnum); while (iPin2>0) { hr = pEnum->Next(1,&pPin2,&fetched); //Skip Capture pin 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); // 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; } 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; //Init COM // Get COM interfaces if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) { RETAILMSG(1, (TEXT("CoInitialize Failed!/r/n"))); return FALSE; } // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WCETEST); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // Finished with COM CoUninitialize(); return msg.wParam; } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HRESULT hr; BOOL fActivated; TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name g_hInstance = hInstance; // Store instance handle in our global variable // Initialize global strings 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; } /************************************************************************************** OnCreate **************************************************************************************/ LRESULT OnCreate( HWND hwnd, CREATESTRUCT* lParam ) { // create the menu bar 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)) { // Couldn't create the menu bar. Fail creation of the window. return(-1); } return(0); // continue creation of the window } // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // /************************************************************************************** WndProc **************************************************************************************/ 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; } BOOL WriteBMPToDisk(unsigned char *pStillImageBuffer,long lBufferSize)//保存为24位的图片 { 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/*((WORD) ('M' << 8) | 'B')*/; 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; } // Look for cam.cfg If it doesn't exist, create it, and set picture number to 1. If it exists, read the value stored inside, increment the number, and write it back. 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) { // File did not exist, so we are going to create it, and initialize the counter. 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); } /**************************************************************************** ActivatePreviousInstance ****************************************************************************/ 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); // NOTE: We don't want to own the object. if(NULL == hMutex) { // Something bad happened, fail. hr = E_FAIL; goto Exit; } if(GetLastError() == ERROR_ALREADY_EXISTS) { HWND hwnd; CloseHandle(hMutex); hMutex = NULL; // There is already an instance of this app // running. Try to bring it to the foreground. hwnd = FindWindow(pszClass, pszTitle); if(NULL == hwnd) { // It's possible that the other window is in the process of being created... Sleep(500); hwnd = FindWindow(pszClass, pszTitle); } if(NULL != hwnd) { // Set the previous instance as the foreground window // The "| 0x01" in the code below activates // the correct owned window of the // previous instance's main window. SetForegroundWindow((HWND) (((ULONG) hwnd) | 0x01)); // We are done. *pfActivated = TRUE; break; } // It's possible that the instance we found isn't coming up, // but rather is going down. Try again. cTries--; } else { // We were the first one to create the mutex // so that makes us the main instance. 'leak' // the mutex in this function so it gets cleaned // up by the OS when this instance exits. break; } } if(cTries <= 0) { // Someone else owns the mutex but we cannot find // their main window to activate. 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);

// 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):

view plaincopy to clipboardprint?
  1. //------------------------------------------------------------------------------
  2. // File: Grabber.cpp
  3. //
  4. // Desc: DirectShow sample code - Implementation file for the SampleGrabber
  5. //       example filter
  6. //
  7. // Copyright (c) Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9. #include <streams.h>     // Active Movie (includes windows.h)
  10. #include <initguid.h>    // declares DEFINE_GUID to declare an EXTERN_C const.
  11. #include "grabber.h"
  12. //#pragma warning(disable: 4800)
  13. const AMOVIESETUP_PIN psudSampleGrabberPins[] =
  14. { { L"Input"            // strName
  15. , FALSE               // bRendered
  16. , FALSE               // bOutput
  17. , FALSE               // bZero
  18. , FALSE               // bMany
  19. , &CLSID_NULL         // clsConnectsToFilter
  20. , L""                 // strConnectsToPin
  21. , 0                   // nTypes
  22. , NULL                // lpTypes
  23. }
  24. , { L"Output"           // strName
  25. , FALSE               // bRendered
  26. , TRUE                // bOutput
  27. , FALSE               // bZero
  28. , FALSE               // bMany
  29. , &CLSID_NULL         // clsConnectsToFilter
  30. , L""                 // strConnectsToPin
  31. , 0                   // nTypes
  32. , NULL                // lpTypes
  33. }
  34. };
  35. const AMOVIESETUP_FILTER sudSampleGrabber =
  36. { &CLSID_GrabberSample            // clsID
  37. , L"SampleGrabber Example"        // strName
  38. , MERIT_DO_NOT_USE                // dwMerit
  39. , 2                               // nPins
  40. , psudSampleGrabberPins };        // lpPin
  41. // Needed for the CreateInstance mechanism
  42. CFactoryTemplate g_Templates[]=
  43. {
  44. { L"Sample Grabber Example"
  45. , &CLSID_GrabberSample
  46. , CSampleGrabber::CreateInstance
  47. , NULL
  48. , &sudSampleGrabber }
  49. };
  50. int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
  51. //
  52. // Exported entry points for registration and unregistration
  53. // (in this case they only call through to default implementations).
  54. //
  55. STDAPI DllRegisterServer()
  56. {
  57. return AMovieDllRegisterServer2(TRUE);
  58. }
  59. STDAPI DllUnregisterServer()
  60. {
  61. return AMovieDllRegisterServer2(FALSE);
  62. }
  63. //
  64. // DllMain
  65. //
  66. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  67. BOOL WINAPI DllMain(HANDLE hModule,
  68. DWORD  dwReason,
  69. LPVOID lpReserved)
  70. {
  71. return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
  72. }
  73. //
  74. // CreateInstance
  75. //
  76. // Provide the way for COM to create a CSampleGrabber object
  77. //
  78. CUnknown * WINAPI CSampleGrabber::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
  79. {
  80. ASSERT(phr);
  81. // assuming we don't want to modify the data
  82. CSampleGrabber *pNewObject = new CSampleGrabber(punk, phr, FALSE);
  83. if(pNewObject == NULL) {
  84. if (phr)
  85. *phr = E_OUTOFMEMORY;
  86. }
  87. return pNewObject;
  88. } // CreateInstance
  89. //----------------------------------------------------------------------------
  90. //
  91. //----------------------------------------------------------------------------
  92. CSampleGrabber::CSampleGrabber( IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData )
  93. : CTransInPlaceFilter( TEXT("SampleGrabber"), (IUnknown*) pOuter,
  94. //CLSID_GrabberSample, phr, (BOOL)ModifiesData )
  95. CLSID_GrabberSample, phr)
  96. , m_callback( NULL )
  97. {
  98. // this is used to override the input pin with our own
  99. m_pInput = (CTransInPlaceInputPin*) new CSampleGrabberInPin( this, phr );
  100. if( !m_pInput )
  101. {
  102. if (phr)
  103. *phr = E_OUTOFMEMORY;
  104. }
  105. // Ensure that the output pin gets created.  This is necessary because our
  106. // SetDeliveryBuffer() method assumes that the input/output pins are created, but
  107. // the output pin isn't created until GetPin() is called.  The
  108. // CTransInPlaceFilter::GetPin() method will create the output pin, since we
  109. // have not already created one.
  110. IPin *pOutput = GetPin(1);
  111. // The pointer is not AddRef'ed by GetPin(), so don't release it
  112. }
  113. STDMETHODIMP CSampleGrabber::NonDelegatingQueryInterface( REFIID riid, void ** ppv)
  114. {
  115. CheckPointer(ppv,E_POINTER);
  116. if(riid == IID_IGrabberSample) {
  117. return GetInterface((IGrabberSample *) this, ppv);
  118. }
  119. else {
  120. return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
  121. }
  122. }
  123. //----------------------------------------------------------------------------
  124. // This is where you force the sample grabber to connect with one type
  125. // or the other. What you do here is crucial to what type of data your
  126. // app will be dealing with in the sample grabber's callback. For instance,
  127. // if you don't enforce right-side-up video in this call, you may not get
  128. // right-side-up video in your callback. It all depends on what you do here.
  129. //----------------------------------------------------------------------------
  130. HRESULT CSampleGrabber::CheckInputType( const CMediaType * pmt )
  131. {
  132. CheckPointer(pmt,E_POINTER);
  133. CAutoLock lock( &m_Lock );
  134. // if the major type is not set, then accept anything
  135. GUID g = *m_mtAccept.Type( );
  136. if( g == GUID_NULL )
  137. {
  138. return NOERROR;
  139. }
  140. // if the major type is set, don't accept anything else
  141. if( g != *pmt->Type( ) )
  142. {
  143. return VFW_E_INVALID_MEDIA_TYPE;
  144. }
  145. // subtypes must match, if set. if not set, accept anything
  146. g = *m_mtAccept.Subtype( );
  147. if( g == GUID_NULL )
  148. {
  149. return NOERROR;
  150. }
  151. if( g != *pmt->Subtype( ) )
  152. {
  153. return VFW_E_INVALID_MEDIA_TYPE;
  154. }
  155. // format types must match, if one is set
  156. g = *m_mtAccept.FormatType( );
  157. if( g == GUID_NULL )
  158. {
  159. return NOERROR;
  160. }
  161. if( g != *pmt->FormatType( ) )
  162. {
  163. return VFW_E_INVALID_MEDIA_TYPE;
  164. }
  165. // at this point, for this sample code, this is good enough,
  166. // but you may want to make it more strict
  167. return NOERROR;
  168. }
  169. //----------------------------------------------------------------------------
  170. // This bit is almost straight out of the base classes.
  171. // We override this so we can handle Transform( )'s error
  172. // result differently.
  173. //----------------------------------------------------------------------------
  174. HRESULT CSampleGrabber::Receive( IMediaSample * pms )
  175. {
  176. CheckPointer(pms,E_POINTER);
  177. HRESULT hr;
  178. AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
  179. RETAILMSG(1, (TEXT("Grabber: Receive! %x/r/n")));
  180. if (pProps->dwStreamId != AM_STREAM_MEDIA)
  181. {
  182. if( m_pOutput->IsConnected() )
  183. return m_pOutput->Deliver(pms);
  184. else
  185. return NOERROR;
  186. }
  187. /*  if (UsingDifferentAllocators())
  188. {
  189. // We have to copy the data.
  190. pms = Copy(pms);
  191. if (pms == NULL)
  192. {
  193. return E_UNEXPECTED;
  194. }
  195. }
  196. */
  197. // have the derived class transform the data
  198. hr = Transform(pms);
  199. if (FAILED(hr))
  200. {
  201. //       DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
  202. /*      if (UsingDifferentAllocators())
  203. {
  204. pms->Release();
  205. }
  206. */
  207. return hr;
  208. }
  209. if (hr == NOERROR)
  210. {
  211. hr = m_pOutput->Deliver(pms);
  212. }
  213. // release the output buffer. If the connected pin still needs it,
  214. // it will have addrefed it itself.
  215. /*  if (UsingDifferentAllocators())
  216. {
  217. pms->Release();
  218. }
  219. */
  220. return hr;
  221. }
  222. //----------------------------------------------------------------------------
  223. // Transform
  224. //----------------------------------------------------------------------------
  225. HRESULT CSampleGrabber::Transform ( IMediaSample * pms )
  226. {
  227. CheckPointer(pms,E_POINTER);
  228. CAutoLock lock( &m_Lock );
  229. RETAILMSG(1, (TEXT("Grabber: Transform! %x/r/n")));
  230. if( m_callback )
  231. {
  232. REFERENCE_TIME StartTime, StopTime;
  233. pms->GetTime( &StartTime, &StopTime);
  234. StartTime += m_pInput->CurrentStartTime( );
  235. StopTime  += m_pInput->CurrentStartTime( );
  236. BOOL * pTypeChanged = &((CSampleGrabberInPin*) m_pInput)->m_bMediaTypeChanged;
  237. HRESULT hr = m_callback( pms, &StartTime, &StopTime, *pTypeChanged );
  238. *pTypeChanged = FALSE; // now that we notified user, we can clear it
  239. return hr;
  240. }
  241. return NOERROR;
  242. }
  243. //----------------------------------------------------------------------------
  244. // SetAcceptedMediaType
  245. //----------------------------------------------------------------------------
  246. STDMETHODIMP CSampleGrabber::SetAcceptedMediaType( const CMediaType * pmt )
  247. {
  248. CAutoLock lock( &m_Lock );
  249. if( !pmt )
  250. {
  251. m_mtAccept = CMediaType( );
  252. return NOERROR;
  253. }
  254. HRESULT hr = TRUE;
  255. CopyMediaType( &m_mtAccept, pmt );
  256. return hr;
  257. }
  258. //----------------------------------------------------------------------------
  259. // GetAcceptedMediaType
  260. //----------------------------------------------------------------------------
  261. STDMETHODIMP CSampleGrabber::GetConnectedMediaType( CMediaType * pmt )
  262. {
  263. if( !m_pInput || !m_pInput->IsConnected( ) )
  264. {
  265. return VFW_E_NOT_CONNECTED;
  266. }
  267. return m_pInput->ConnectionMediaType( pmt );
  268. }
  269. //----------------------------------------------------------------------------
  270. // SetCallback
  271. //----------------------------------------------------------------------------
  272. STDMETHODIMP CSampleGrabber::SetCallback( SAMPLECALLBACK Callback )
  273. {
  274. CAutoLock lock( &m_Lock );
  275. m_callback = Callback;
  276. return NOERROR;
  277. }
  278. //----------------------------------------------------------------------------
  279. // inform the input pin of the allocator buffer we wish to use. See the
  280. // input pin's SetDeliverBuffer method for comments.
  281. //----------------------------------------------------------------------------
  282. STDMETHODIMP CSampleGrabber::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer )
  283. {
  284. // have the input/output pins been created?
  285. if( !InputPin( ) || !OutputPin( ) )
  286. {
  287. return E_POINTER;
  288. }
  289. // they can't be connected if we're going to be changing delivery buffers
  290. //
  291. if( InputPin( )->IsConnected( ) || OutputPin( )->IsConnected( ) )
  292. {
  293. return E_INVALIDARG;
  294. }
  295. return ((CSampleGrabberInPin*)m_pInput)->SetDeliveryBuffer( props, m_pBuffer );
  296. }
  297. //----------------------------------------------------------------------------
  298. // used to help speed input pin connection times. We return a partially
  299. // specified media type - only the main type is specified. If we return
  300. // anything BUT a major type, some codecs written improperly will crash
  301. //----------------------------------------------------------------------------
  302. HRESULT CSampleGrabberInPin::GetMediaType( int iPosition, CMediaType * pMediaType )
  303. {
  304. CheckPointer(pMediaType,E_POINTER);
  305. if (iPosition < 0) {
  306. return E_INVALIDARG;
  307. }
  308. if (iPosition > 0) {
  309. return VFW_S_NO_MORE_ITEMS;
  310. }
  311. mt=*pMediaType;
  312. *pMediaType = CMediaType( );
  313. pMediaType->SetType( ((CSampleGrabber*)m_pFilter)->m_mtAccept.Type());
  314. return S_OK;
  315. }
  316. //----------------------------------------------------------------------------
  317. // override the CTransInPlaceInputPin's method, and return a new enumerator
  318. // if the input pin is disconnected. This will allow GetMediaType to be
  319. // called. If we didn't do this, EnumMediaTypes returns a failure code
  320. // and GetMediaType is never called.
  321. //----------------------------------------------------------------------------
  322. STDMETHODIMP CSampleGrabberInPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
  323. {
  324. CheckPointer(ppEnum,E_POINTER);
  325. ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
  326. // if the output pin isn't connected yet, offer the possibly
  327. // partially specified media type that has been set by the user
  328. if( !((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->IsConnected() )
  329. {
  330. // Create a new reference counted enumerator
  331. *ppEnum = new CEnumMediaTypes( this, NULL );
  332. return (*ppEnum) ? NOERROR : E_OUTOFMEMORY;
  333. }
  334. // if the output pin is connected, offer it's fully qualified media type
  335. return ((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->GetConnected()->EnumMediaTypes( ppEnum );
  336. }
  337. //----------------------------------------------------------------------------
  338. //
  339. //----------------------------------------------------------------------------
  340. STDMETHODIMP CSampleGrabberInPin::NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly )
  341. {
  342. if( m_pPrivateAllocator )
  343. {
  344. if( pAllocator != m_pPrivateAllocator )
  345. {
  346. return E_FAIL;
  347. }
  348. else
  349. {
  350. // if the upstream guy wants to be read only and we don't, then that's bad
  351. // if the upstream guy doesn't request read only, but we do, that's okay
  352. if( bReadOnly && !SampleGrabber( )->IsReadOnly( ) )
  353. {
  354. return E_FAIL;
  355. }
  356. }
  357. }
  358. return CTransInPlaceInputPin::NotifyAllocator( pAllocator, bReadOnly );
  359. }
  360. //----------------------------------------------------------------------------
  361. //
  362. //----------------------------------------------------------------------------
  363. STDMETHODIMP CSampleGrabberInPin::GetAllocator( IMemAllocator **ppAllocator )
  364. {
  365. if( m_pPrivateAllocator )
  366. {
  367. CheckPointer(ppAllocator,E_POINTER);
  368. *ppAllocator = m_pPrivateAllocator;
  369. m_pPrivateAllocator->AddRef( );
  370. return NOERROR;
  371. }
  372. else
  373. {
  374. return CTransInPlaceInputPin::GetAllocator( ppAllocator );
  375. }
  376. }
  377. //----------------------------------------------------------------------------
  378. // GetAllocatorRequirements: The upstream filter calls this to get our
  379. // filter's allocator requirements. If the app has set the buffer, then
  380. // we return those props. Otherwise, we use the default TransInPlace behavior.
  381. //----------------------------------------------------------------------------
  382. HRESULT CSampleGrabberInPin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps )
  383. {
  384. CheckPointer(pProps,E_POINTER);
  385. if (m_pPrivateAllocator)
  386. {
  387. *pProps = m_allocprops;
  388. return S_OK;
  389. }
  390. else
  391. {
  392. return CTransInPlaceInputPin::GetAllocatorRequirements(pProps);
  393. }
  394. }
  395. //----------------------------------------------------------------------------
  396. //
  397. //----------------------------------------------------------------------------
  398. HRESULT CSampleGrabberInPin::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * pBuffer )
  399. {
  400. // don't allow more than one buffer
  401. if( props.cBuffers != 1 )
  402. {
  403. return E_INVALIDARG;
  404. }
  405. if( !pBuffer )
  406. {
  407. return E_POINTER;
  408. }
  409. m_allocprops = props;
  410. m_pBuffer = pBuffer;
  411. // If there is an existing allocator, make sure that it is released
  412. // to prevent a memory leak
  413. if (m_pPrivateAllocator)
  414. {
  415. m_pPrivateAllocator->Release();
  416. m_pPrivateAllocator = NULL;
  417. }
  418. HRESULT hr = S_OK;
  419. m_pPrivateAllocator = new CSampleGrabberAllocator( this, &hr );
  420. if( !m_pPrivateAllocator )
  421. {
  422. return E_OUTOFMEMORY;
  423. }
  424. m_pPrivateAllocator->AddRef( );
  425. return hr;
  426. }
  427. //----------------------------------------------------------------------------
  428. //
  429. //----------------------------------------------------------------------------
  430. HRESULT CSampleGrabberInPin::SetMediaType( const CMediaType *pmt )
  431. {
  432. m_bMediaTypeChanged = TRUE;
  433. return CTransInPlaceInputPin::SetMediaType( pmt );
  434. }
  435. //----------------------------------------------------------------------------
  436. // don't allocate the memory, just use the buffer the app provided
  437. //----------------------------------------------------------------------------
  438. HRESULT CSampleGrabberAllocator::Alloc( )
  439. {
  440. // look at the base class code to see where this came from!
  441. CAutoLock lck(this);
  442. // Check he has called SetProperties
  443. HRESULT hr = CBaseAllocator::Alloc();
  444. if (FAILED(hr)) {
  445. return hr;
  446. }
  447. // If the requirements haven't changed then don't reallocate
  448. if (hr == S_FALSE) {
  449. ASSERT(m_pBuffer);
  450. return NOERROR;
  451. }
  452. ASSERT(hr == S_OK); // we use this fact in the loop below
  453. // Free the old resources
  454. if (m_pBuffer) {
  455. ReallyFree();
  456. }
  457. // Compute the aligned size
  458. LONG lAlignedSize = m_lSize + m_lPrefix;
  459. if (m_lAlignment > 1)
  460. {
  461. LONG lRemainder = lAlignedSize % m_lAlignment;
  462. if (lRemainder != 0)
  463. {
  464. lAlignedSize += (m_lAlignment - lRemainder);
  465. }
  466. }
  467. // Create the contiguous memory block for the samples
  468. // making sure it's properly aligned (64K should be enough!)
  469. ASSERT(lAlignedSize % m_lAlignment == 0);
  470. // don't create the buffer - use what was passed to us
  471. //
  472. m_pBuffer = m_pPin->m_pBuffer;
  473. if (m_pBuffer == NULL) {
  474. return E_OUTOFMEMORY;
  475. }
  476. LPBYTE pNext = m_pBuffer;
  477. CMediaSample *pSample;
  478. ASSERT(m_lAllocated == 0);
  479. // Create the new samples - we have allocated m_lSize bytes for each sample
  480. // plus m_lPrefix bytes per sample as a prefix. We set the pointer to
  481. // the memory after the prefix - so that GetPointer() will return a pointer
  482. // to m_lSize bytes.
  483. for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize)
  484. {
  485. pSample = new CMediaSample(
  486. NAME("Sample Grabber memory media sample"),
  487. this,
  488. &hr,
  489. pNext + m_lPrefix,      // GetPointer() value
  490. m_lSize);               // not including prefix
  491. ASSERT(SUCCEEDED(hr));
  492. if (pSample == NULL)
  493. return E_OUTOFMEMORY;
  494. // This CANNOT fail
  495. m_lFree.Add(pSample);
  496. }
  497. m_bChanged = FALSE;
  498. return NOERROR;
  499. }
  500. //----------------------------------------------------------------------------
  501. // don't really free the memory
  502. //----------------------------------------------------------------------------
  503. void CSampleGrabberAllocator::ReallyFree()
  504. {
  505. // look at the base class code to see where this came from!
  506. // Should never be deleting this unless all buffers are freed
  507. ASSERT(m_lAllocated == m_lFree.GetCount());
  508. // Free up all the CMediaSamples
  509. CMediaSample *pSample;
  510. for (;;)
  511. {
  512. pSample = m_lFree.RemoveHead();
  513. if (pSample != NULL)
  514. {
  515. delete pSample;
  516. }
  517. else
  518. {
  519. break;
  520. }
  521. }
  522. m_lAllocated = 0;
  523. // don't free the buffer - let the app do it
  524. }
  525. //----------------------------------------------------------------------------
  526. // SetProperties: Called by the upstream filter to set the allocator
  527. // properties. The application has already allocated the buffer, so we reject
  528. // anything that is not compatible with that, and return the actual props.
  529. //----------------------------------------------------------------------------
  530. HRESULT CSampleGrabberAllocator::SetProperties(
  531. ALLOCATOR_PROPERTIES *pRequest,
  532. ALLOCATOR_PROPERTIES *pActual
  533. )
  534. {
  535. HRESULT hr = CMemAllocator::SetProperties(pRequest, pActual);
  536. if (FAILED(hr))
  537. {
  538. return hr;
  539. }
  540. ALLOCATOR_PROPERTIES *pRequired = &(m_pPin->m_allocprops);
  541. if (pRequest->cbAlign != pRequired->cbAlign)
  542. {
  543. return VFW_E_BADALIGN;
  544. }
  545. if (pRequest->cbPrefix != pRequired->cbPrefix)
  546. {
  547. return E_FAIL;
  548. }
  549. if (pRequest->cbBuffer > pRequired->cbBuffer)
  550. {
  551. return E_FAIL;
  552. }
  553. if (pRequest->cBuffers > pRequired->cBuffers)
  554. {
  555. return E_FAIL;
  556. }
  557. *pActual = *pRequired;
  558. m_lCount = pRequired->cBuffers;
  559. m_lSize = pRequired->cbBuffer;
  560. m_lAlignment = pRequired->cbAlign;
  561. m_lPrefix = pRequired->cbPrefix;
  562. return S_OK;
  563. }

//------------------------------------------------------------------------------ // File: Grabber.cpp // // Desc: DirectShow sample code - Implementation file for the SampleGrabber // example filter // // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ #include <streams.h> // Active Movie (includes windows.h) #include <initguid.h> // declares DEFINE_GUID to declare an EXTERN_C const. #include "grabber.h" //#pragma warning(disable: 4800) const AMOVIESETUP_PIN psudSampleGrabberPins[] = { { L"Input" // strName , FALSE // bRendered , FALSE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"" // strConnectsToPin , 0 // nTypes , NULL // lpTypes } , { L"Output" // strName , FALSE // bRendered , TRUE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"" // strConnectsToPin , 0 // nTypes , NULL // lpTypes } }; const AMOVIESETUP_FILTER sudSampleGrabber = { &CLSID_GrabberSample // clsID , L"SampleGrabber Example" // strName , MERIT_DO_NOT_USE // dwMerit , 2 // nPins , psudSampleGrabberPins }; // lpPin // Needed for the CreateInstance mechanism CFactoryTemplate g_Templates[]= { { L"Sample Grabber Example" , &CLSID_GrabberSample , CSampleGrabber::CreateInstance , NULL , &sudSampleGrabber } }; int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]); // // Exported entry points for registration and unregistration // (in this case they only call through to default implementations). // STDAPI DllRegisterServer() { return AMovieDllRegisterServer2(TRUE); } STDAPI DllUnregisterServer() { return AMovieDllRegisterServer2(FALSE); } // // DllMain // extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); } // // CreateInstance // // Provide the way for COM to create a CSampleGrabber object // CUnknown * WINAPI CSampleGrabber::CreateInstance(LPUNKNOWN punk, HRESULT *phr) { ASSERT(phr); // assuming we don't want to modify the data CSampleGrabber *pNewObject = new CSampleGrabber(punk, phr, FALSE); if(pNewObject == NULL) { if (phr) *phr = E_OUTOFMEMORY; } return pNewObject; } // CreateInstance //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- CSampleGrabber::CSampleGrabber( IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData ) : CTransInPlaceFilter( TEXT("SampleGrabber"), (IUnknown*) pOuter, //CLSID_GrabberSample, phr, (BOOL)ModifiesData ) CLSID_GrabberSample, phr) , m_callback( NULL ) { // this is used to override the input pin with our own m_pInput = (CTransInPlaceInputPin*) new CSampleGrabberInPin( this, phr ); if( !m_pInput ) { if (phr) *phr = E_OUTOFMEMORY; } // Ensure that the output pin gets created. This is necessary because our // SetDeliveryBuffer() method assumes that the input/output pins are created, but // the output pin isn't created until GetPin() is called. The // CTransInPlaceFilter::GetPin() method will create the output pin, since we // have not already created one. IPin *pOutput = GetPin(1); // The pointer is not AddRef'ed by GetPin(), so don't release it } STDMETHODIMP CSampleGrabber::NonDelegatingQueryInterface( REFIID riid, void ** ppv) { CheckPointer(ppv,E_POINTER); if(riid == IID_IGrabberSample) { return GetInterface((IGrabberSample *) this, ppv); } else { return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv); } } //---------------------------------------------------------------------------- // This is where you force the sample grabber to connect with one type // or the other. What you do here is crucial to what type of data your // app will be dealing with in the sample grabber's callback. For instance, // if you don't enforce right-side-up video in this call, you may not get // right-side-up video in your callback. It all depends on what you do here. //---------------------------------------------------------------------------- HRESULT CSampleGrabber::CheckInputType( const CMediaType * pmt ) { CheckPointer(pmt,E_POINTER); CAutoLock lock( &m_Lock ); // if the major type is not set, then accept anything GUID g = *m_mtAccept.Type( ); if( g == GUID_NULL ) { return NOERROR; } // if the major type is set, don't accept anything else if( g != *pmt->Type( ) ) { return VFW_E_INVALID_MEDIA_TYPE; } // subtypes must match, if set. if not set, accept anything g = *m_mtAccept.Subtype( ); if( g == GUID_NULL ) { return NOERROR; } if( g != *pmt->Subtype( ) ) { return VFW_E_INVALID_MEDIA_TYPE; } // format types must match, if one is set g = *m_mtAccept.FormatType( ); if( g == GUID_NULL ) { return NOERROR; } if( g != *pmt->FormatType( ) ) { return VFW_E_INVALID_MEDIA_TYPE; } // at this point, for this sample code, this is good enough, // but you may want to make it more strict return NOERROR; } //---------------------------------------------------------------------------- // This bit is almost straight out of the base classes. // We override this so we can handle Transform( )'s error // result differently. //---------------------------------------------------------------------------- HRESULT CSampleGrabber::Receive( IMediaSample * pms ) { CheckPointer(pms,E_POINTER); HRESULT hr; AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); RETAILMSG(1, (TEXT("Grabber: Receive! %x/r/n"))); if (pProps->dwStreamId != AM_STREAM_MEDIA) { if( m_pOutput->IsConnected() ) return m_pOutput->Deliver(pms); else return NOERROR; } /* if (UsingDifferentAllocators()) { // We have to copy the data. pms = Copy(pms); if (pms == NULL) { return E_UNEXPECTED; } } */ // have the derived class transform the data hr = Transform(pms); if (FAILED(hr)) { // DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace"))); /* if (UsingDifferentAllocators()) { pms->Release(); } */ return hr; } if (hr == NOERROR) { hr = m_pOutput->Deliver(pms); } // release the output buffer. If the connected pin still needs it, // it will have addrefed it itself. /* if (UsingDifferentAllocators()) { pms->Release(); } */ return hr; } //---------------------------------------------------------------------------- // Transform //---------------------------------------------------------------------------- HRESULT CSampleGrabber::Transform ( IMediaSample * pms ) { CheckPointer(pms,E_POINTER); CAutoLock lock( &m_Lock ); RETAILMSG(1, (TEXT("Grabber: Transform! %x/r/n"))); if( m_callback ) { REFERENCE_TIME StartTime, StopTime; pms->GetTime( &StartTime, &StopTime); StartTime += m_pInput->CurrentStartTime( ); StopTime += m_pInput->CurrentStartTime( ); BOOL * pTypeChanged = &((CSampleGrabberInPin*) m_pInput)->m_bMediaTypeChanged; HRESULT hr = m_callback( pms, &StartTime, &StopTime, *pTypeChanged ); *pTypeChanged = FALSE; // now that we notified user, we can clear it return hr; } return NOERROR; } //---------------------------------------------------------------------------- // SetAcceptedMediaType //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabber::SetAcceptedMediaType( const CMediaType * pmt ) { CAutoLock lock( &m_Lock ); if( !pmt ) { m_mtAccept = CMediaType( ); return NOERROR; } HRESULT hr = TRUE; CopyMediaType( &m_mtAccept, pmt ); return hr; } //---------------------------------------------------------------------------- // GetAcceptedMediaType //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabber::GetConnectedMediaType( CMediaType * pmt ) { if( !m_pInput || !m_pInput->IsConnected( ) ) { return VFW_E_NOT_CONNECTED; } return m_pInput->ConnectionMediaType( pmt ); } //---------------------------------------------------------------------------- // SetCallback //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabber::SetCallback( SAMPLECALLBACK Callback ) { CAutoLock lock( &m_Lock ); m_callback = Callback; return NOERROR; } //---------------------------------------------------------------------------- // inform the input pin of the allocator buffer we wish to use. See the // input pin's SetDeliverBuffer method for comments. //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabber::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer ) { // have the input/output pins been created? if( !InputPin( ) || !OutputPin( ) ) { return E_POINTER; } // they can't be connected if we're going to be changing delivery buffers // if( InputPin( )->IsConnected( ) || OutputPin( )->IsConnected( ) ) { return E_INVALIDARG; } return ((CSampleGrabberInPin*)m_pInput)->SetDeliveryBuffer( props, m_pBuffer ); } //---------------------------------------------------------------------------- // used to help speed input pin connection times. We return a partially // specified media type - only the main type is specified. If we return // anything BUT a major type, some codecs written improperly will crash //---------------------------------------------------------------------------- HRESULT CSampleGrabberInPin::GetMediaType( int iPosition, CMediaType * pMediaType ) { CheckPointer(pMediaType,E_POINTER); if (iPosition < 0) { return E_INVALIDARG; } if (iPosition > 0) { return VFW_S_NO_MORE_ITEMS; } mt=*pMediaType; *pMediaType = CMediaType( ); pMediaType->SetType( ((CSampleGrabber*)m_pFilter)->m_mtAccept.Type()); return S_OK; } //---------------------------------------------------------------------------- // override the CTransInPlaceInputPin's method, and return a new enumerator // if the input pin is disconnected. This will allow GetMediaType to be // called. If we didn't do this, EnumMediaTypes returns a failure code // and GetMediaType is never called. //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabberInPin::EnumMediaTypes( IEnumMediaTypes **ppEnum ) { CheckPointer(ppEnum,E_POINTER); ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *)); // if the output pin isn't connected yet, offer the possibly // partially specified media type that has been set by the user if( !((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->IsConnected() ) { // Create a new reference counted enumerator *ppEnum = new CEnumMediaTypes( this, NULL ); return (*ppEnum) ? NOERROR : E_OUTOFMEMORY; } // if the output pin is connected, offer it's fully qualified media type return ((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->GetConnected()->EnumMediaTypes( ppEnum ); } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabberInPin::NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly ) { if( m_pPrivateAllocator ) { if( pAllocator != m_pPrivateAllocator ) { return E_FAIL; } else { // if the upstream guy wants to be read only and we don't, then that's bad // if the upstream guy doesn't request read only, but we do, that's okay if( bReadOnly && !SampleGrabber( )->IsReadOnly( ) ) { return E_FAIL; } } } return CTransInPlaceInputPin::NotifyAllocator( pAllocator, bReadOnly ); } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- STDMETHODIMP CSampleGrabberInPin::GetAllocator( IMemAllocator **ppAllocator ) { if( m_pPrivateAllocator ) { CheckPointer(ppAllocator,E_POINTER); *ppAllocator = m_pPrivateAllocator; m_pPrivateAllocator->AddRef( ); return NOERROR; } else { return CTransInPlaceInputPin::GetAllocator( ppAllocator ); } } //---------------------------------------------------------------------------- // GetAllocatorRequirements: The upstream filter calls this to get our // filter's allocator requirements. If the app has set the buffer, then // we return those props. Otherwise, we use the default TransInPlace behavior. //---------------------------------------------------------------------------- HRESULT CSampleGrabberInPin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps ) { CheckPointer(pProps,E_POINTER); if (m_pPrivateAllocator) { *pProps = m_allocprops; return S_OK; } else { return CTransInPlaceInputPin::GetAllocatorRequirements(pProps); } } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- HRESULT CSampleGrabberInPin::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * pBuffer ) { // don't allow more than one buffer if( props.cBuffers != 1 ) { return E_INVALIDARG; } if( !pBuffer ) { return E_POINTER; } m_allocprops = props; m_pBuffer = pBuffer; // If there is an existing allocator, make sure that it is released // to prevent a memory leak if (m_pPrivateAllocator) { m_pPrivateAllocator->Release(); m_pPrivateAllocator = NULL; } HRESULT hr = S_OK; m_pPrivateAllocator = new CSampleGrabberAllocator( this, &hr ); if( !m_pPrivateAllocator ) { return E_OUTOFMEMORY; } m_pPrivateAllocator->AddRef( ); return hr; } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- HRESULT CSampleGrabberInPin::SetMediaType( const CMediaType *pmt ) { m_bMediaTypeChanged = TRUE; return CTransInPlaceInputPin::SetMediaType( pmt ); } //---------------------------------------------------------------------------- // don't allocate the memory, just use the buffer the app provided //---------------------------------------------------------------------------- HRESULT CSampleGrabberAllocator::Alloc( ) { // look at the base class code to see where this came from! CAutoLock lck(this); // Check he has called SetProperties HRESULT hr = CBaseAllocator::Alloc(); if (FAILED(hr)) { return hr; } // If the requirements haven't changed then don't reallocate if (hr == S_FALSE) { ASSERT(m_pBuffer); return NOERROR; } ASSERT(hr == S_OK); // we use this fact in the loop below // Free the old resources if (m_pBuffer) { ReallyFree(); } // Compute the aligned size LONG lAlignedSize = m_lSize + m_lPrefix; if (m_lAlignment > 1) { LONG lRemainder = lAlignedSize % m_lAlignment; if (lRemainder != 0) { lAlignedSize += (m_lAlignment - lRemainder); } } // Create the contiguous memory block for the samples // making sure it's properly aligned (64K should be enough!) ASSERT(lAlignedSize % m_lAlignment == 0); // don't create the buffer - use what was passed to us // m_pBuffer = m_pPin->m_pBuffer; if (m_pBuffer == NULL) { return E_OUTOFMEMORY; } LPBYTE pNext = m_pBuffer; CMediaSample *pSample; ASSERT(m_lAllocated == 0); // Create the new samples - we have allocated m_lSize bytes for each sample // plus m_lPrefix bytes per sample as a prefix. We set the pointer to // the memory after the prefix - so that GetPointer() will return a pointer // to m_lSize bytes. for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize) { pSample = new CMediaSample( NAME("Sample Grabber memory media sample"), this, &hr, pNext + m_lPrefix, // GetPointer() value m_lSize); // not including prefix ASSERT(SUCCEEDED(hr)); if (pSample == NULL) return E_OUTOFMEMORY; // This CANNOT fail m_lFree.Add(pSample); } m_bChanged = FALSE; return NOERROR; } //---------------------------------------------------------------------------- // don't really free the memory //---------------------------------------------------------------------------- void CSampleGrabberAllocator::ReallyFree() { // look at the base class code to see where this came from! // Should never be deleting this unless all buffers are freed ASSERT(m_lAllocated == m_lFree.GetCount()); // Free up all the CMediaSamples CMediaSample *pSample; for (;;) { pSample = m_lFree.RemoveHead(); if (pSample != NULL) { delete pSample; } else { break; } } m_lAllocated = 0; // don't free the buffer - let the app do it } //---------------------------------------------------------------------------- // SetProperties: Called by the upstream filter to set the allocator // properties. The application has already allocated the buffer, so we reject // anything that is not compatible with that, and return the actual props. //---------------------------------------------------------------------------- HRESULT CSampleGrabberAllocator::SetProperties( ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual ) { HRESULT hr = CMemAllocator::SetProperties(pRequest, pActual); if (FAILED(hr)) { return hr; } ALLOCATOR_PROPERTIES *pRequired = &(m_pPin->m_allocprops); if (pRequest->cbAlign != pRequired->cbAlign) { return VFW_E_BADALIGN; } if (pRequest->cbPrefix != pRequired->cbPrefix) { return E_FAIL; } if (pRequest->cbBuffer > pRequired->cbBuffer) { return E_FAIL; } if (pRequest->cBuffers > pRequired->cBuffers) { return E_FAIL; } *pActual = *pRequired; m_lCount = pRequired->cBuffers; m_lSize = pRequired->cbBuffer; m_lAlignment = pRequired->cbAlign; m_lPrefix = pRequired->cbPrefix; return S_OK; }

还有个头文件Grabber.h:

view plaincopy to clipboardprint?
  1. //------------------------------------------------------------------------------
  2. // File: Grabber.h
  3. //
  4. // Desc: DirectShow sample code - Header file for the SampleGrabber
  5. //       example filter
  6. //
  7. // Copyright (c) Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9. //------------------------------------------------------------------------------
  10. // Define new GUID and IID for the sample grabber example so that they do NOT
  11. // conflict with the official DirectX SampleGrabber filter
  12. //------------------------------------------------------------------------------
  13. // {2FA4F053-6D60-4cb0-9503-8E89234F3F73}
  14. DEFINE_GUID(CLSID_GrabberSample,
  15. 0x2fa4f053, 0x6d60, 0x4cb0, 0x95, 0x3, 0x8e, 0x89, 0x23, 0x4f, 0x3f, 0x73);
  16. DEFINE_GUID(IID_IGrabberSample,
  17. 0x6b652fff, 0x11fe, 0x4fce, 0x92, 0xad, 0x02, 0x66, 0xb5, 0xd7, 0xc7, 0x8f);
  18. // We define a callback typedef for this example.
  19. // Normally, you would make the SampleGrabber support a COM interface,
  20. // and in one of its methods you would pass in a pointer to a COM interface
  21. // used for calling back. See the DirectX documentation for the SampleGrabber
  22. // for more information.
  23. typedef HRESULT (*SAMPLECALLBACK) (
  24. IMediaSample * pSample,
  25. REFERENCE_TIME * StartTime,
  26. REFERENCE_TIME * StopTime,
  27. BOOL TypeChanged );
  28. // We define the interface the app can use to program us
  29. MIDL_INTERFACE("6B652FFF-11FE-4FCE-92AD-0266B5D7C78F")
  30. IGrabberSample : public IUnknown
  31. {
  32. public:
  33. virtual HRESULT STDMETHODCALLTYPE SetAcceptedMediaType(
  34. const CMediaType *pType) = 0;
  35. virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType(
  36. CMediaType *pType) = 0;
  37. virtual HRESULT STDMETHODCALLTYPE SetCallback(
  38. SAMPLECALLBACK Callback) = 0;
  39. virtual HRESULT STDMETHODCALLTYPE SetDeliveryBuffer(
  40. ALLOCATOR_PROPERTIES props,
  41. BYTE *pBuffer) = 0;
  42. };
  43. class CSampleGrabberInPin;
  44. class CSampleGrabber;
  45. //----------------------------------------------------------------------------
  46. // This is a special allocator that KNOWS that the person who is creating it
  47. // will only create one of them. It allocates CMediaSamples that only
  48. // reference the buffer location that is set in the pin's renderer's
  49. // data variable
  50. //----------------------------------------------------------------------------
  51. class CSampleGrabberAllocator : public CMemAllocator
  52. {
  53. friend class CSampleGrabberInPin;
  54. friend class CSampleGrabber;
  55. protected:
  56. // our pin who created us
  57. //
  58. CSampleGrabberInPin * m_pPin;
  59. public:
  60. CSampleGrabberAllocator( CSampleGrabberInPin * pParent, HRESULT *phr )
  61. : CMemAllocator( TEXT("SampleGrabberAllocator/0"), NULL, phr )
  62. , m_pPin( pParent )
  63. {
  64. };
  65. ~CSampleGrabberAllocator( )
  66. {
  67. // wipe out m_pBuffer before we try to delete it. It's not an allocated
  68. // buffer, and the default destructor will try to free it!
  69. m_pBuffer = NULL;
  70. }
  71. HRESULT Alloc( );
  72. void ReallyFree();
  73. // Override this to reject anything that does not match the actual buffer
  74. // that was created by the application
  75. STDMETHODIMP SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual);
  76. };
  77. //----------------------------------------------------------------------------
  78. // we override the input pin class so we can provide a media type
  79. // to speed up connection times. When you try to connect a filesourceasync
  80. // to a transform filter, DirectShow will insert a splitter and then
  81. // start trying codecs, both audio and video, video codecs first. If
  82. // your sample grabber's set to connect to audio, unless we do this, it
  83. // will try all the video codecs first. Connection times are sped up x10
  84. // for audio with just this minor modification!
  85. //----------------------------------------------------------------------------
  86. class CSampleGrabberInPin : public CTransInPlaceInputPin
  87. {
  88. friend class CSampleGrabberAllocator;
  89. friend class CSampleGrabber;
  90. CSampleGrabberAllocator * m_pPrivateAllocator;
  91. ALLOCATOR_PROPERTIES m_allocprops;
  92. BYTE * m_pBuffer;
  93. BOOL m_bMediaTypeChanged;
  94. protected:
  95. CSampleGrabber * SampleGrabber( ) { return (CSampleGrabber*) m_pFilter; }
  96. HRESULT SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer );
  97. public:
  98. CMediaType mt;
  99. CSampleGrabberInPin( CTransInPlaceFilter * pFilter, HRESULT * pHr )
  100. : CTransInPlaceInputPin( TEXT("SampleGrabberInputPin/0"), pFilter, pHr, L"Input/0" )
  101. , m_pPrivateAllocator( NULL )
  102. , m_pBuffer( NULL )
  103. , m_bMediaTypeChanged( FALSE )
  104. {
  105. memset( &m_allocprops, 0, sizeof( m_allocprops ) );
  106. }
  107. ~CSampleGrabberInPin( )
  108. {
  109. if( m_pPrivateAllocator ) delete m_pPrivateAllocator;
  110. }
  111. // override to provide major media type for fast connects
  112. HRESULT GetMediaType( int iPosition, CMediaType *pMediaType );
  113. // override this or GetMediaType is never called
  114. STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum );
  115. // override this to refuse any allocators besides
  116. // the one the user wants, if this is set
  117. STDMETHODIMP NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly );
  118. // override this so we always return the special allocator, if necessary
  119. STDMETHODIMP GetAllocator( IMemAllocator **ppAllocator );
  120. HRESULT SetMediaType( const CMediaType *pmt );
  121. // we override this to tell whoever's upstream of us what kind of
  122. // properties we're going to demand to have
  123. //
  124. STDMETHODIMP GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps );
  125. };
  126. //----------------------------------------------------------------------------
  127. //
  128. //----------------------------------------------------------------------------
  129. class CSampleGrabber : public CTransInPlaceFilter,
  130. public IGrabberSample
  131. {
  132. friend class CSampleGrabberInPin;
  133. friend class CSampleGrabberAllocator;
  134. protected:
  135. CMediaType m_mtAccept;
  136. BOOL m_bModifiesData;
  137. SAMPLECALLBACK m_callback;
  138. CCritSec m_Lock; // serialize access to our data
  139. BOOL IsReadOnly( ) { return !m_bModifiesData; }
  140. // PURE, override this to ensure we get
  141. // connected with the right media type
  142. HRESULT CheckInputType( const CMediaType * pmt );
  143. // PURE, override this to callback
  144. // the user when a sample is received
  145. HRESULT Transform( IMediaSample * pms );
  146. // override this so we can return S_FALSE directly.
  147. // The base class CTransInPlace
  148. // Transform( ) method is called by it's
  149. // Receive( ) method. There is no way
  150. // to get Transform( ) to return an S_FALSE value
  151. // (which means "stop giving me data"),
  152. // to Receive( ) and get Receive( ) to return S_FALSE as well.
  153. HRESULT Receive( IMediaSample * pms );
  154. public:
  155. static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
  156. // Expose ISampleGrabber
  157. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  158. DECLARE_IUNKNOWN;
  159. CSampleGrabber( IUnknown * pOuter, HRESULT * pHr, BOOL ModifiesData );
  160. // IGrabberSample
  161. STDMETHODIMP SetAcceptedMediaType( const CMediaType * pmt );
  162. STDMETHODIMP GetConnectedMediaType( CMediaType * pmt );
  163. STDMETHODIMP SetCallback( SAMPLECALLBACK Callback );
  164. STDMETHODIMP SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer );
  165. };

//------------------------------------------------------------------------------ // File: Grabber.h // // Desc: DirectShow sample code - Header file for the SampleGrabber // example filter // // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Define new GUID and IID for the sample grabber example so that they do NOT // conflict with the official DirectX SampleGrabber filter //------------------------------------------------------------------------------ // {2FA4F053-6D60-4cb0-9503-8E89234F3F73} DEFINE_GUID(CLSID_GrabberSample, 0x2fa4f053, 0x6d60, 0x4cb0, 0x95, 0x3, 0x8e, 0x89, 0x23, 0x4f, 0x3f, 0x73); DEFINE_GUID(IID_IGrabberSample, 0x6b652fff, 0x11fe, 0x4fce, 0x92, 0xad, 0x02, 0x66, 0xb5, 0xd7, 0xc7, 0x8f); // We define a callback typedef for this example. // Normally, you would make the SampleGrabber support a COM interface, // and in one of its methods you would pass in a pointer to a COM interface // used for calling back. See the DirectX documentation for the SampleGrabber // for more information. typedef HRESULT (*SAMPLECALLBACK) ( IMediaSample * pSample, REFERENCE_TIME * StartTime, REFERENCE_TIME * StopTime, BOOL TypeChanged ); // We define the interface the app can use to program us MIDL_INTERFACE("6B652FFF-11FE-4FCE-92AD-0266B5D7C78F") IGrabberSample : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetAcceptedMediaType( const CMediaType *pType) = 0; virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( CMediaType *pType) = 0; virtual HRESULT STDMETHODCALLTYPE SetCallback( SAMPLECALLBACK Callback) = 0; virtual HRESULT STDMETHODCALLTYPE SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE *pBuffer) = 0; }; class CSampleGrabberInPin; class CSampleGrabber; //---------------------------------------------------------------------------- // This is a special allocator that KNOWS that the person who is creating it // will only create one of them. It allocates CMediaSamples that only // reference the buffer location that is set in the pin's renderer's // data variable //---------------------------------------------------------------------------- class CSampleGrabberAllocator : public CMemAllocator { friend class CSampleGrabberInPin; friend class CSampleGrabber; protected: // our pin who created us // CSampleGrabberInPin * m_pPin; public: CSampleGrabberAllocator( CSampleGrabberInPin * pParent, HRESULT *phr ) : CMemAllocator( TEXT("SampleGrabberAllocator/0"), NULL, phr ) , m_pPin( pParent ) { }; ~CSampleGrabberAllocator( ) { // wipe out m_pBuffer before we try to delete it. It's not an allocated // buffer, and the default destructor will try to free it! m_pBuffer = NULL; } HRESULT Alloc( ); void ReallyFree(); // Override this to reject anything that does not match the actual buffer // that was created by the application STDMETHODIMP SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual); }; //---------------------------------------------------------------------------- // we override the input pin class so we can provide a media type // to speed up connection times. When you try to connect a filesourceasync // to a transform filter, DirectShow will insert a splitter and then // start trying codecs, both audio and video, video codecs first. If // your sample grabber's set to connect to audio, unless we do this, it // will try all the video codecs first. Connection times are sped up x10 // for audio with just this minor modification! //---------------------------------------------------------------------------- class CSampleGrabberInPin : public CTransInPlaceInputPin { friend class CSampleGrabberAllocator; friend class CSampleGrabber; CSampleGrabberAllocator * m_pPrivateAllocator; ALLOCATOR_PROPERTIES m_allocprops; BYTE * m_pBuffer; BOOL m_bMediaTypeChanged; protected: CSampleGrabber * SampleGrabber( ) { return (CSampleGrabber*) m_pFilter; } HRESULT SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer ); public: CMediaType mt; CSampleGrabberInPin( CTransInPlaceFilter * pFilter, HRESULT * pHr ) : CTransInPlaceInputPin( TEXT("SampleGrabberInputPin/0"), pFilter, pHr, L"Input/0" ) , m_pPrivateAllocator( NULL ) , m_pBuffer( NULL ) , m_bMediaTypeChanged( FALSE ) { memset( &m_allocprops, 0, sizeof( m_allocprops ) ); } ~CSampleGrabberInPin( ) { if( m_pPrivateAllocator ) delete m_pPrivateAllocator; } // override to provide major media type for fast connects HRESULT GetMediaType( int iPosition, CMediaType *pMediaType ); // override this or GetMediaType is never called STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum ); // override this to refuse any allocators besides // the one the user wants, if this is set STDMETHODIMP NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly ); // override this so we always return the special allocator, if necessary STDMETHODIMP GetAllocator( IMemAllocator **ppAllocator ); HRESULT SetMediaType( const CMediaType *pmt ); // we override this to tell whoever's upstream of us what kind of // properties we're going to demand to have // STDMETHODIMP GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps ); }; //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- class CSampleGrabber : public CTransInPlaceFilter, public IGrabberSample { friend class CSampleGrabberInPin; friend class CSampleGrabberAllocator; protected: CMediaType m_mtAccept; BOOL m_bModifiesData; SAMPLECALLBACK m_callback; CCritSec m_Lock; // serialize access to our data BOOL IsReadOnly( ) { return !m_bModifiesData; } // PURE, override this to ensure we get // connected with the right media type HRESULT CheckInputType( const CMediaType * pmt ); // PURE, override this to callback // the user when a sample is received HRESULT Transform( IMediaSample * pms ); // override this so we can return S_FALSE directly. // The base class CTransInPlace // Transform( ) method is called by it's // Receive( ) method. There is no way // to get Transform( ) to return an S_FALSE value // (which means "stop giving me data"), // to Receive( ) and get Receive( ) to return S_FALSE as well. HRESULT Receive( IMediaSample * pms ); public: static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr); // Expose ISampleGrabber STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv); DECLARE_IUNKNOWN; CSampleGrabber( IUnknown * pOuter, HRESULT * pHr, BOOL ModifiesData ); // IGrabberSample STDMETHODIMP SetAcceptedMediaType( const CMediaType * pmt ); STDMETHODIMP GetConnectedMediaType( CMediaType * pmt ); STDMETHODIMP SetCallback( SAMPLECALLBACK Callback ); STDMETHODIMP SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer ); };

另外还可以自己编译baseclasses里的工程生成mobile下的strmbasd.lib 和 strmbase.lib,当然,windows mobile6是有自己的strmbase.lib的,只有strmbasd.lib没有而已,不过你可以通过AKU目录下的baseclasses来编译生成wm下的baseclasses工程,这样便于调试. 其中strmbasd.lib和strmbase.lib分别用于Debug和Release下的。

转载于:https://www.cnblogs.com/aspxnets/archive/2011/08/04/2126832.html

windows mobile做一个摄象头预览程序相关推荐

  1. 简单的做一个图片上传预览(web前端)

    在做web项目很多的时候图片都是避免不了的,所以操作图片就成了一个相对比较棘手的问题,其实也不是说很麻烦,只是说上传然后直接预览的过程很恶心,今天简单的做一个处理. 效果预览: 代码: <!DO ...

  2. Windows Server 2016第三个技术预览版新技术

    Windows Server 2016第三个技术预览版本发布 究竟有哪些诱惑? Windows Server 2016第三个技术预览版本中究竟有哪些诱惑? 微软已经详细地介绍了Windows Serv ...

  3. 厉害了,手把手教你搭建一个代码在线编辑预览工具

    点击下方"前端开发博客",选择"设为星标" 回复"2"加入前端群 简介 大家好,我是一个闲着没事热衷于重复造轮子的不知名前端,今天给大家带来 ...

  4. 手把手教你快速搭建一个代码在线编辑预览工具

    简介 大家好,今天我跟大家分享的是一个代码在线编辑预览工具的实现教程,手把手教你完成这样一个项目. 目前这类工具使用很广泛,常见于各种文档网站及代码分享场景,相关工具也比较多,如codepen.jsr ...

  5. 服务器尚图片不显示缩率图,Windows Server 2008 R2 怎么看图预览图片(能不能显示缩略图)...

    Windows Server 2008 安装桌面体后就可以像看图软件一样预览图片,但 Windows Server 2008 R2 却不行,所有图片都显示一致的背景,给预览图片带来一定的麻烦,Win2 ...

  6. el-image做水印,给image预览图片添加图标

    实现效果:可以做水印,可以给预览图添加预览图标 实现:在鼠标hover时添加一个类名即可. <el-image style="width: 124px;":src=" ...

  7. 做一个p2p打洞的C#程序

    做一个p2p打洞的C#程序 转载于:https://www.cnblogs.com/cuihongyu3503319/archive/2011/03/15/1985021.html

  8. 用Python做一个“以图搜番“的应用程序,再也不用愁动漫图片的出处了!

    文章目录 前言 PyQt5界面设计 使用Qt Designer绘制界面 视频部件插入小技巧 解码器下载 功能实现 trace.moe API介绍与视频 使用Nuitka打包成exe文件 前言 喜欢看动 ...

  9. python可以做动漫吗_用Python做一个以图搜番的应用程序,再也不用愁动漫图片的出处了!...

    前言 喜欢看动漫的朋友们大概都能体会到一个难受的事情,就是在论坛或者群聊里面看到一张动漫截图,很想知道它的出处,但百度搜了一圈却也没有一个可靠结果,就很郁闷.今天就来带大家用Python做一个简单的& ...

最新文章

  1. JS基础-Array对象手册
  2. 网易青果后端系统设计窥探(二)
  3. HDU1285 确定名次 拓扑排序
  4. 安装安全类软件进行了android签名漏洞修补,魅族MX3怎么升级固件体验最新比较稳定的版本...
  5. c++11/14新特性学习
  6. 苹果官宣:这届“春晚”,好早!
  7. 晶澳独家供货40兆瓦全球最大漂浮式太阳能电站
  8. dubbo学习 二 dubbo源码大致查阅
  9. Robotium在输入框输入文字
  10. 系统体系结构框架 DoDAF
  11. 山东网通和电信的DNS
  12. 征途LINUX服务端脚本,征途【改版教程】-版本内脚本文件-转载于-喜欢玩网游单机站...
  13. Latex论文复杂组合图片设计
  14. 无座火车票为什么不能半价?
  15. 关于阿里云服务器可以怎么选择地域
  16. htmlparser 获取html,根据htmlparser写的一个提取页面纯文本的C#程序
  17. 移动硬盘使用注意事项
  18. docker部署codereview/gerrit
  19. 计算机专业夏令营英语面试范文,研究生夏令营面试英语自我介绍范文(精选5篇)...
  20. 7-223 sdut-C语言实验-求阶乘(循环结构)7-224 sdut-C语言实验-排序问题7-225 sdut-C语言实验- 冒泡排序中数据交换的次数

热门文章

  1. swift (Singleton)模式
  2. centos 6.* 修改时间
  3. eyoucms range 范围判断标签
  4. js 闭包 实战1
  5. 片元着色器(Fragment Shader)被称为像素着色器(Pixel Shader),但
  6. double和float计算精度不准的问题
  7. VirtualBox: Effective UID is not root
  8. IIS配置相关问题:Framework 4.5 在IIS 7.5中运行
  9. linux系统管理学习笔记之三----软件的安装
  10. cmd库的导入Java,在cmd命令窗口导入第三方jar包来运行java文件