directxShow的視訊采集,9.0版本之後的sdk把directshow從中分離出來了,是以本人下了後面的幾個版本都沒有找到要的SDK,汗啊.......
是以下載下傳9.0b,在微軟的網站上有,後面好像有個(2003)字樣.去下吧.
好了,從裡面提出一個隻采集視訊的程式.
1.
// TestVideoDlg.h : 頭檔案
//
#pragma once
#include " afxwin.h "
// CTestVideoDlg 對話框
class CTestVideoDlg : public CDialog
... {
// 構造
public:
CTestVideoDlg(CWnd* pParent = NULL); // 标準構造函數
// 對話框資料
enum ...{ IDD = IDD_TESTVIDEO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支援
// 實作
protected:
HICON m_hIcon;
// 生成的消息映射函數
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CStatic m_wndVideo;
protected:
CComPtr< IGraphBuilder > m_pGraph;
CComPtr< ISampleGrabber > m_pGrabber;
HRESULT InitStillGraph( );
void Error( TCHAR * pText );
void GetDefaultCapDevice( IBaseFilter ** ppCap );
} ;
2.實作部分
// TestVideoDlg.cpp : 實作檔案
//
#include " stdafx.h "
#include " TestVideo.h "
#include " TestVideoDlg.h "
#include " ......commondshowutil.h "
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#ifdef DEBUG
#define REGISTER_FILTERGRAPH
#endif
// 用于應用程式“關于”菜單項的 CAboutDlg 對話框
class CAboutDlg : public CDialog
... {
public:
CAboutDlg();
// 對話框資料
enum ...{ IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支援
// 實作
protected:
DECLARE_MESSAGE_MAP()
} ;
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
... {
}
void CAboutDlg::DoDataExchange(CDataExchange * pDX)
... {
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CTestVideoDlg 對話框
HWND g_hwnd = 0 ;
DWORD g_dwGraphRegister = 0 ; // For running object table
CTestVideoDlg::CTestVideoDlg(CWnd * pParent )
: CDialog(CTestVideoDlg::IDD, pParent)
... {
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTestVideoDlg::DoDataExchange(CDataExchange * pDX)
... {
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_VIDEO, m_wndVideo);
}
BEGIN_MESSAGE_MAP(CTestVideoDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
// }}AFX_MSG_MAP
END_MESSAGE_MAP()
// CTestVideoDlg 消息處理程式
BOOL CTestVideoDlg::OnInitDialog()
... {
CDialog::OnInitDialog();
// 将“關于...”菜單項添加到系統菜單中。
// IDM_ABOUTBOX 必須在系統指令範圍内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
...{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
...{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 設定此對話框的圖示。當應用程式主視窗不是對話框時,架構将自動
// 執行此操作
SetIcon(m_hIcon, TRUE); // 設定大圖示
SetIcon(m_hIcon, FALSE); // 設定小圖示
// TODO: 在此添加額外的初始化代碼
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
g_hwnd = GetSafeHwnd();
// start up the still image capture graph
//
HRESULT hr = InitStillGraph( );
m_wndVideo.ModifyStyle(0, WS_CLIPCHILDREN);
return TRUE; // 除非設定了控件的焦點,否則傳回 TRUE
}
void CTestVideoDlg::OnSysCommand(UINT nID, LPARAM lParam)
... {
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
...{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
...{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如果向對話框添加最小化按鈕,則需要下面的代碼
// 來繪制該圖示。對于使用文檔/視圖模型的 MFC 應用程式,
// 這将由架構自動完成。
void CTestVideoDlg::OnPaint()
... {
if (IsIconic())
...{
CPaintDC dc(this); // 用于繪制的裝置上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使圖示在工作矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 繪制圖示
dc.DrawIcon(x, y, m_hIcon);
}
else
...{
CDialog::OnPaint();
}
}
// 當使用者拖動最小化視窗時系統調用此函數取得光标顯示。
HCURSOR CTestVideoDlg::OnQueryDragIcon()
... {
return static_cast<HCURSOR>(m_hIcon);
}
void CTestVideoDlg::Error( TCHAR * pText )
... {
::MessageBox( NULL, pText, TEXT("Error!"), MB_OK | MB_TASKMODAL | MB_SETFOREGROUND );
}
HRESULT CTestVideoDlg::InitStillGraph( )
... {
HRESULT hr;
// create a filter graph
//
hr = m_pGraph.CoCreateInstance( CLSID_FilterGraph );
if( !m_pGraph )
...{
Error( TEXT("Could not create filter graph") );
return E_FAIL;
}
// get whatever capture device exists
//
CComPtr< IBaseFilter > pCap;
GetDefaultCapDevice( &pCap );
if( !pCap )
...{
Error( TEXT("No video capture device was detected on your system. ")
TEXT("This sample requires a functional video capture device, such ")
TEXT("as a USB web camera. Video capture will be disabled.") );
return E_FAIL;
}
// add the capture filter to the graph
//
hr = m_pGraph->AddFilter( pCap, L"Cap" );
if( FAILED( hr ) )
...{
Error( TEXT("Could not put capture device in graph"));
return E_FAIL;
}
// create a sample grabber
//
hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber )
...{
Error( TEXT("Could not create SampleGrabber (is qedit.dll registered?)"));
return hr;
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
// force it to connect to video, 24 bit
//
CMediaType VideoType;
VideoType.SetType( &MEDIATYPE_Video );
VideoType.SetSubtype( &MEDIASUBTYPE_RGB24 );
hr = m_pGrabber->SetMediaType( &VideoType ); // shouldn't fail
if( FAILED( hr ) )
...{
Error( TEXT("Could not set media type"));
return hr;
}
// add the grabber to the graph
//
hr = m_pGraph->AddFilter( pGrabBase, L"Grabber" );
if( FAILED( hr ) )
...{
Error( TEXT("Could not put sample grabber in graph"));
return hr;
}
// build the graph
CComPtr<ICaptureGraphBuilder2> pCGB2;
hr = pCGB2.CoCreateInstance (CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC);
if (FAILED( hr ))
...{
Error(TEXT ("Can't get a ICaptureGraphBuilder2 reference"));
return hr;
}
hr = pCGB2->SetFiltergraph( m_pGraph );
if (FAILED( hr ))
...{
Error(TEXT("SetGraph failed"));
return hr;
}
// If there is a VP pin present on the video device, then put the
// renderer on CLSID_NullRenderer
CComPtr<IPin> pVPPin;
hr = pCGB2->FindPin(
pCap,
PINDIR_OUTPUT,
&PIN_CATEGORY_VIDEOPORT,
NULL,
FALSE,
0,
&pVPPin);
// If there is a VP pin, put the renderer on NULL Renderer
CComPtr<IBaseFilter> pRenderer;
if (S_OK == hr)
...{
hr = pRenderer.CoCreateInstance(CLSID_NullRenderer);
if (S_OK != hr)
...{
Error(TEXT("Unable to make a NULL renderer"));
return S_OK;
}
hr = m_pGraph->AddFilter(pRenderer, L"NULL renderer");
if (FAILED (hr))
...{
Error(TEXT("Can't add the filter to graph"));
return hr;
}
}
hr = pCGB2->RenderStream(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Interleaved,
pCap,
pGrabBase,
pRenderer);
if (FAILED (hr))
...{
// try to render preview pin
hr = pCGB2->RenderStream(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pCap,
pGrabBase,
pRenderer);
// try to render capture pin
if( FAILED( hr ) )
...{
hr = pCGB2->RenderStream(
&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video,
pCap,
pGrabBase,
pRenderer);
}
}
if( FAILED( hr ) )
...{
Error( TEXT("Can't build the graph") );
return hr;
}
// ask for the connection media type so we know how big
// it is, so we can write out bitmaps
//
AM_MEDIA_TYPE mt;
hr = m_pGrabber->GetConnectedMediaType( &mt );
if ( FAILED( hr) )
...{
Error( TEXT("Could not read the connected media type"));
return hr;
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
FreeMediaType( mt );
// don't buffer the samples as they pass through
//
hr = m_pGrabber->SetBufferSamples( FALSE );
// only grab one at a time, stop stream after
// grabbing one sample
//
hr = m_pGrabber->SetOneShot( FALSE );
// set the callback, so we can grab the one sample
//
// hr = m_pGrabber->SetCallback( &mCB, 1 );
// find the video window and stuff it in our window
//
CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;
if( !pWindow )
...{
Error( TEXT("Could not get video window interface"));
return E_FAIL;
}
// set up the preview window to be in our dialog
// instead of floating popup
//
HWND hwndPreview = NULL;
GetDlgItem( IDC_STATIC_VIDEO, &hwndPreview );
RECT rc;
::GetWindowRect( hwndPreview, &rc );
hr = pWindow->put_Owner( (OAHWND) hwndPreview );
hr = pWindow->put_Left( 0 );
hr = pWindow->put_Top( 0 );
hr = pWindow->put_Width( rc.right - rc.left );
hr = pWindow->put_Height( rc.bottom - rc.top );
hr = pWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS );
hr = pWindow->put_Visible( OATRUE );
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
//#ifdef REGISTER_FILTERGRAPH
// hr = AddGraphToRot(m_pGraph, &g_dwGraphRegister);
// if (FAILED(hr))
// {
// Error(TEXT("Failed to register filter graph with ROT!"));
// g_dwGraphRegister = 0;
// }
//#endif
// run the graph
//
CComQIPtr< IMediaControl, &IID_IMediaControl > pControl = m_pGraph;
hr = pControl->Run( );
if( FAILED( hr ) )
...{
Error( TEXT("Could not run graph"));
return hr;
}
// UpdateStatus(_T("Previewing Live Video"));
return 0;
}
void CTestVideoDlg::GetDefaultCapDevice( IBaseFilter ** ppCap )
... {
HRESULT hr;
ASSERT(ppCap);
if (!ppCap)
return;
*ppCap = NULL;
// create an enumerator
//
CComPtr< ICreateDevEnum > pCreateDevEnum;
pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
ASSERT(pCreateDevEnum);
if( !pCreateDevEnum )
return;
// enumerate video capture devices
//
CComPtr< IEnumMoniker > pEm;
pCreateDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEm, 0 );
ASSERT(pEm);
if( !pEm )
return;
pEm->Reset( );
// go through and find first video capture device
//
while( 1 )
...{
ULONG ulFetched = 0;
CComPtr< IMoniker > pM;
hr = pEm->Next( 1, &pM, &ulFetched );
if( hr != S_OK )
break;
// get the property bag interface from the moniker
//
CComPtr< IPropertyBag > pBag;
hr = pM->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
if( hr != S_OK )
continue;
// ask for the english-readable name
//
CComVariant var;
var.vt = VT_BSTR;
hr = pBag->Read( L"FriendlyName", &var, NULL );
if( hr != S_OK )
continue;
// set it in our UI
//
USES_CONVERSION;
// SetDlgItemText( IDC_CAPOBJ, W2T( var.bstrVal ) );
// ask for the actual filter
//
hr = pM->BindToObject( 0, 0, IID_IBaseFilter, (void**) ppCap );
if( *ppCap )
break;
}
return;
}
3.其中要的類庫都在directshow的SDK例子中能找到.