爱学习的站长www.mmic.net.cn

www.mmic.net.cn 欢迎学习共同成长
公告信息
www.mmic.net.cn 欢迎学习共同成长
文章分类
文章档案
文章
windows mobile做一个摄象头预览代码
2011/8/3 23:57:39

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

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

主要构建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):

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

还有个头文件Grabber.h:

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

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

新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"
 技术   浏览(2368)   评论(0)   关键字
  
Copyright © 2010-2020 power by CYQ.Blog - 秋色园 v2.0 All Rights Reserved