当前位置: 首页 > 编程日记 > 正文

windows mobile做一个摄象头预览程序

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 (HINSTANCELPTSTR);
  49. BOOL                InitInstance    (HINSTANCEint);
  50. LRESULT CALLBACK    WndProc         (HWNDUINTWPARAMLPARAM);
  51. LRESULT CALLBACK    About           (HWNDUINTWPARAMLPARAM);
  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(HINSTANCEULONGLPVOID);
  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

相关文章:

初学者的机器学习入门实战教程!

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」&#xff0c;购票请扫码咨询 ↑↑↑作者 | Adrian Rosebrock译者 | kbsc13&#xff0c;京东算法工程师&#xff0c;研究领域计算机视觉来源 | 机器学习与计算机视觉&#xff08;ID&#xff1a;AI_Developer&#xff09;这是…

【Qt】调用Python函数:无参数、单个参数、多个参数、数组参数

一、链接配置 如果缺少头文件需要安装python3-dev: sudo apt-get install python3-dev链接libpython3.4库,添加头文件路径,以Qt为例: INCLUDEPATH += /usr/include/python3.4 LIBS += -L /usr/lib/python3.4/config-3.4m-x86_64-linux-gnu -lpython3.4二、头文件 因为p…

分布式系统的问题

本文内容翻译自《Designing Data-Intensive Applications》一书的第8章。 近几章主要介绍系统如何处理错误。例如&#xff0c;我们讨论了副本故障转移&#xff0c;复制滞后和事务的并发控制。当我们理解实际系统中可能出现的各种边界情况时&#xff0c;我们就能更好地处理它们。…

php-cgi占用cpu资源过高的解决方法

转的网上的&#xff0c;不过对PHP-CGI菜鸟的人&#xff0c;还是有点帮助的。 1. 一些php的扩展与php版本兼容存在问题&#xff0c;实践证明 eAccelerater与某些php版本兼容存在问题&#xff0c;具体表现时启动php-cgi进程后&#xff0c;运行10多分钟&#xff0c;奇慢无比&#…

请收下这份NLP热门词汇解读

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」&#xff0c;购票请扫码咨询 ↑↑↑本文转载自微软研究院AI头条&#xff08;ID:MSRAsia&#xff09;编者按&#xff1a;在过去的一段时间&#xff0c;自然语言处理领域取得了许多重要的进展&#xff0c;Transformer、BERT、…

【Ubuntu】dpkg: 处理软件包 XXXX (--configure)时出错解决方法

1、使用apt-get --purge remove删除安装包时报错 dpkg: 处理软件包 python-gflags (–configure)时出错&#xff1a; 子进程 已安装 post-installation 脚本 返回了错误号 1 正在设置 python-sklearn (0.14.1-2) … Traceback (most recent call last): File “/usr/bin/pycom…

c#devexpress GridContorl添加进度条

demo 的实现图 下边是步骤和代码 1定义 时钟事件,定时的增加进度条的增量. 2: 添加进度条 3;定义字段属性 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; …

信达充值旗舰店

在淘宝上新开了一个话费 游戏点卡充值的小店&#xff0c;以后大家话费没了可以联系我啊&#xff0c;速度还是蛮快的&#xff0c;都是赔本卖的只想提高点信誉&#xff0c;所以价格也是最最低的了&#xff0c;感谢大家的支持&#xff0c;多多帮忙啊^_^ http://sjzxinda.taobao.co…

完整代码+实操!手把手教你操作Faster R-CNN和Mask R-CNN

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」全日程揭晓&#xff0c;请扫码咨询 ↑↑↑机器视觉领域的核心问题之一就是目标检测&#xff08;Object Detection&#xff09;&#xff0c;它的任务是找出图像当中所有感兴趣的目标&#xff08;物体&#xff09;&#xff0c…

【Dlib】使用dlib_face_recognition_resnet_model_v1.dat无法实现微调fune-tuning

1、问题描述 dlib官方使用resnet训练人脸识别&#xff0c;训练了300万的数据&#xff0c;网络参数保存在dlib_face_recognition_resnet_model_v1.dat中。 测试中识别lfw数据时&#xff0c;准确率能达到99.13%&#xff0c;但是在识别自己的数据时&#xff0c;准确率有点低&…

Visual Studio 2017 - Windows应用程序打包成exe文件(1)- 工具简单总结

最近有对一个Windows应用程序少许维护和修改。修改之后要发布新的exe安装文件&#xff0c;打包exe文件时&#xff0c;遇到了很头疼的问题&#xff0c;还好最后解决了&#xff0c;记录一下。 Visual Studio版本&#xff1a;Visual Studio 2017 Visual Studio 2017 打包插件 新建…

NET也有闭包

NET也有闭包在.NET中&#xff0c;函数并不是第一级成员&#xff0c;所以并不能像JavaScript那样通过在函数中内嵌子函数的方式实现闭包&#xff0c;通常而言&#xff0c;形成闭包有一些值得总结的非必要条件&#xff1a; 嵌套定义的函数。 匿名函数。 将函数作为参数或…

【opencv】ubuntu14.04上编译opencv2.4

参考博客 https://blog.csdn.net/c406495762/article/details/62896035 1、安装依赖库 sudo apt-get install build-essential cmake libgtk2.0-dev pkg-config python-dev python-numpy libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install libv4l-0 libv…

1024块TPU在燃烧!BERT训练从3天缩短到76分钟 | 技术头条

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」全日程揭晓&#xff0c;请扫码咨询 ↑↑↑作者 | 琥珀出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;“Jeff Dean称赞&#xff0c;TensorFlow官方推特支持&#xff0c;BERT目前工业界最耗时的应用&#xff0c;计…

牵引力教育设计总监解密9大2018潮流UI设计趋向

作为一名紧跟时代潮流的UI设计师&#xff0c;设计的风格一定要紧跟上最新的设计趋势&#xff0c;因为更为有效且颇具趣味的响应式图标必将得到关注。同时&#xff0c;鲜艳丰富的色彩&#xff0c;精彩纷呈的插图设计都会博得用户眼球。这样你的设计更容易获得更多人的认可与热爱…

Android媒体相关开发应用程序接口

翻译自&#xff1a;http://developer.android.com/guide/topics/media/index.html MediaAndroid框架支持各种普通media类型的编解码&#xff0c;因此你可以很容易地把音频&#xff0c;视频和图片整合到你的应用程序中。通过使用MediaPlayer的接口&#xff0c;你可以播放各种音视…

Facebook开源图嵌入“神器”:无需GPU,高效处理数十亿级实体图形 | 极客头条...

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」全日程揭晓&#xff0c;请扫码咨询 ↑↑↑编译 | Major、一一出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;有效处理大规模图对于促进人工智能的研究和应用至关重要&#xff0c;但特别是在工业应用中的图&…

【opencv】ubuntu14.04上编译opencv-4.0.1 + opencv_contrib-4.0.1

1、要求 编译器版本&#xff1a;c11 cmake版本&#xff1a;3.5.1 2、安装camke 2.1 官网下载&#xff1a;https://cmake.org/download/ 选择&#xff1a;Linux x86_64 cmake-3.14.1-Linux-x86_64.sh 2.2 安装&#xff1a; 将cmake-3.14.1-Linux-x86_64.sh拷贝考ubuntu中&…

软件开发文档模板 (学习)

1 可行性研究报告   可行性研究报告的编写目的是&#xff1a;说明该软件开发项目的实现在技术、经济和社会条件方面的可行性&#xff1b;评述为了合理地达到开发目标而可能先择的各种方案&#xff1b;说明论证所选定的方案。 可行性研究报告的编写内容要求如下&#xff1a; …

Unix数据中心主宠儿

曾几何时UNIX一直是除个人电脑之外的领域中应用最为广泛的操作系统&#xff0c;并且为现代操作系统的成型奠定了基础&#xff0c;可以说UNIX的历史就像应用程序本身一样耐人寻味。UNIX的过去回首1983年&#xff0c;肯.托马森和D.里奇由于对操作系统发展史以及UNIX操作系统应用所…

【AI】基本概念

1、什么是人工智能 人工智能&#xff08;AI&#xff09;是通过研究、开发&#xff0c;来找到用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的综合性的科学技术。其表现为&#xff0c;让计算机系统通过机器学习等方式&#xff0c;来获得可以履行原本只有依…

在浏览器中进行深度学习:TensorFlow.js (四)用基本模型对MNIST数据进行识别

2019独角兽企业重金招聘Python工程师标准>>> 在了解了TensorflowJS的一些基本模型的后&#xff0c;大家会问&#xff0c;这究竟有什么用呢&#xff1f;我们就用深度学习中被广泛使用的MINST数据集来进行一下手写识别的操作。 MINST数据集 MINST是一组0到9的手写数字…

不止临床应用,AI还要帮不懂编程的医生搞科研

近日&#xff0c;推想科技发布 AI 学者科研平台 InferScholar Center&#xff0c;该平台为更多的医生提供零门槛的 AI 科研能力&#xff0c;让医生可以快速将深度学习、影像组学以及文本数据处理相关的前沿技术应用到自己的临床科研实践中&#xff0c;他们将为平台上的医疗科研…

rhel6Inode详解

在Linux文件系统中&#xff0c;很多人对Inode都不太明白&#xff0c;今天我就和大家一起来分享一下我对Inode的认识&#xff0c;如果有理解错误的地方&#xff0c;请大家多多批评指点。在上一篇一天一点学习Linux之认识文件系统中&#xff0c;在最后给出了一张EXT3文件系统结构…

争论不休的TF 2.0与PyTorch,到底现在战局如何了? | 技术头条

点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」全日程揭晓&#xff0c;请扫码咨询 ↑↑↑作者 | Jeff Hale译者 | Jackey编辑 | Jane出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;【导语】 TensorFlow 2.0 和 PyTorch 1.0 陆续发布后&#xff0c;…

struts2实验2:struts2.xml action中* ,{}以及${}

p.s 关键在于struts.xml中的匹配&#xff0c;使用* ,{}以及${}可以让代码更加简洁清晰 代码核心思路 在struts.xml中通过路由(url)去指定控制逻辑的Action中的方法,例如 <package name"admin" namespace"/admin" extends"struts-global">&…

【Ubuntu】dpkg-deb -c :查看deb文件中的内容

1、dpkg-deb -c :查看deb文件中的内容 $ dpkg-deb -c packageeg&#xff1a; $ dpkg-deb -c sogoupinyin_2.2.0.0108_amd64.deb drwxr-xr-x root/root 0 2018-04-18 16:50 ./ drwxr-xr-x root/root 0 2018-04-18 16:50 ./etc/ drwxr-xr-x root/root …

捕获Camera并保存图片到本地(照相功能) -samhy

Flex博文 捕获Camera并保存图片到本地(照相功能) -samhy作者:admin 日期:2010-07-12字体大小: 小 中 大捕获Camera并保存图片到本地(照相功能)这几天对Camera类进行了一下规整&#xff0c;并利用JPGEncoder类实现了照相的功能,代码如下&#xff1a; XML/HTML代码import flash.m…

【C++】模板函数的声明和定义必须在同一个文件中

1、问题描述 习惯性的将函数的定义和实现&#xff0c;分别写在头文件和源文件&#xff08;.cpp&#xff09;中。今天也按照这个习惯实现了一个模板函数。然后编译时报错 ... error: undefined reference to ...2、原因分析 c中模板的声明和定义不能分开。C中每一个对象所占用…

基于AWS-ELK部署系统日志告警系统

前言 运维故障排障速度往往与监控系统体系颗粒度成正比&#xff0c;监控到位才能快速排障 在部署这套系统之前&#xff0c;平台所有系统日志都由GraylogZabbix&#xff0c;针对日志出现的错误关键字进行告警&#xff0c;这种做法在运维工作开展过程中暴露出多个不足点&#xff…