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 /**//*=NULL*/)
: 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;

/**//* mCB.pOwner = this;
mCB.lWidth = vih->bmiHeader.biWidth;
mCB.lHeight = vih->bmiHeader.biHeight;*/
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例子中能找到.