directshow实现视频捕获(源码)vs2005

PS:原来发表在百度空间的,但百度空间已发展成交友网站了,so,挪个地儿。原帖地址:http://hi.baidu.com/%C0%DA%CE%DE%B5%D02008/blog/item/60196025ba35b5104c088d8c.html

 

我用visual studio 2005编了一个摄像头预览程序,还可以导出成avi文件,前提是要安装directshow,并搭建好环境,我安装的是directx 9.0b,搭建环境很简单,网上有很多,注意在项目-属性-配置属性-链接器-输入中要加上strmbasd.lib winmm.lib(中间有空格)。源代码如下:

/*CaptureClass.h*/

#pragma once
#include <atlbase.h>
#include <windows.h>
#include <DShow.h>
#include <qedit.h>//ISampleGrabber接口要求的

#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
#endif


class CCaptureClass
{
public:
CCaptureClass(void);
public:
~CCaptureClass(void);
int EnumDevices(HWND hList);
//void SaveGraph(TCHAR *wFileName);       //保存滤波器链表
void ConfigCameraPin(HWND hwndParent);      //配置摄像头的视频格式
void ConfigCameraFilter(HWND hwndParent);     //配置摄像头的图像参数
HRESULT CaptureImages(CString inFileName);     //捕获保存视频
HRESULT PreviewImages(int iDeviceID , HWND hWnd);   //采集预览视频
private:
HWND m_hWnd;            //视频显示窗口的句柄
IGraphBuilder *m_pGB;          //滤波器链表管理器
ICaptureGraphBuilder2 *m_pCapture;       //增强型捕获滤波器链表管理器
IBaseFilter *m_pBF;           //捕获滤波器
IMediaControl *m_pMC;          //媒体控制接口
IVideoWindow *m_pVW;          //视频显示窗口接口
IBaseFilter *pMux;           //写文件滤波器
protected:
bool BindFilter(int deviceId,IBaseFilter **pFilter); //把指定的设备滤波器捆绑到链表中

void ResizeVideoWindow();         //更改视频显示窗口
HRESULT SetupVideoWindow();         //设置视频显示窗口的特性
HRESULT InitCaptureGraphBuilder();       //创建滤波器链表管理器,查询其各种控制接口
};

/*CaptureClass.cpp*/

#include "StdAfx.h"
#include "CaptureClass.h"

/************************************************************************/
/* 类构造函数实现                                                       */
/************************************************************************/
CCaptureClass::CCaptureClass(void)
{
CoInitialize(NULL);   //COM库初始化
m_hWnd = NULL;    //视频显示窗口的句柄
m_pVW = NULL ;    //视频窗口接口指针清空
m_pMC = NULL ;    //媒体控制接口指针清空
m_pGB = NULL ;    //滤波器链表管理器接口指针清空
m_pBF = NULL ;    //捕获滤波器接口指针清空
m_pCapture = NULL ;   //增强型捕获滤波器链表管理器接口指针清空
}

/************************************************************************/
/* 析构函数                                                             */
/************************************************************************/
CCaptureClass::~CCaptureClass(void)
{
if(m_pMC) m_pMC ->Stop(); //首先停止媒体
if(m_pVW){
   m_pVW->put_Visible(OAFALSE); //视频窗口不可见
   m_pVW->put_Owner(NULL);    //视频窗口的父窗口清空
}
SAFE_RELEASE(m_pCapture);    //释放增强型捕获滤波器链表管理器接口
SAFE_RELEASE(m_pMC);     //释放媒体控制接口
SAFE_RELEASE(m_pGB);     //释放滤波器链表管理器接口
SAFE_RELEASE(m_pBF);     //释放捕获滤波器接口
CoUninitialize( );      //卸载COM库
}

/************************************************************************/
/* 把指定采集设备与滤波器捆绑                                           */
/************************************************************************/
bool CCaptureClass::BindFilter(int deviceId,IBaseFilter **pFilter)
{
if( deviceId < 0) return false ;
//枚举所有的视频捕获设备
ICreateDevEnum *pCreateDevEnum ;
//生成设备枚举器pCreateDevEnum
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**)&pCreateDevEnum);
if( hr != NOERROR ) return false ;
IEnumMoniker *pEm;
//创建视频输入设备类枚举器
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm,0);
if( hr != NOERROR ) return false ;
pEm->Reset(); //复位该设备
ULONG cFetched;
IMoniker *pM;
int index = 0 ;
//获取设备
while( hr = pEm->Next(1,&pM,&cFetched),hr == S_OK , index <= deviceId )
{
   IPropertyBag *pBag;
   //获取该设备的属性集
   hr = pM->BindToStorage(0,0,IID_IPropertyBag,(void**)&pBag);
   if(SUCCEEDED(hr))
   {
    VARIANT var ;
    var.vt = VT_BSTR; //保存的是二进制的数据
    hr = pBag->Read(L"FriendlyName",&var,NULL); //获取FriendlyName形式的信息
    if( hr == NOERROR )
    {
     //采集设备与捕获滤波器捆绑
     if( index == deviceId ) pM->BindToObject(0,0,IID_IBaseFilter,(void**)pFilter);
     SysFreeString(var.bstrVal);   //释放二进制数据资源,必须释放
    }
    pBag ->Release();
   }
   pM->Release();
   index++;
}
return true ;
}

/************************************************************************/
/* 设置视频显示窗口的特性                                               */
/************************************************************************/
HRESULT CCaptureClass::SetupVideoWindow()
{
HRESULT hr ;
//m_hWnd为类CCaptureClass的成员变量,在使用该函数前须初始化
hr = m_pVW->put_Visible(OAFALSE); //视频窗口不可见
hr = m_pVW->put_Owner((OAHWND)m_hWnd); //窗口所有者:传入的窗口句柄
if(FAILED(hr)) return hr ;
hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN); //窗口风格设置
if( FAILED(hr)) return hr ;
ResizeVideoWindow();   //更改窗口大小
hr = m_pVW->put_Visible(OATRUE); //视频窗口可见
return hr ;
}

/************************************************************************/
/* 更改视频窗口大小                                                     */
/************************************************************************/
void CCaptureClass::ResizeVideoWindow()
{
if( m_pVW ){
   //让图像充满整个指定窗口
   CRect rc ;
   ::GetClientRect(m_hWnd,&rc); //获取显示窗口的客户区
   m_pVW->SetWindowPosition(0,0,rc.right,rc.bottom); //设置视频显示窗口的位置
}
}

/************************************************************************/
/* 开始预览视频设备                                                     */
/************************************************************************/
HRESULT CCaptureClass::PreviewImages(int iDeviceID , HWND hWnd)
{
HRESULT hr ;
//初始化视频捕获滤波器链表管理器
hr = InitCaptureGraphBuilder();
if(FAILED(hr)){
   AfxMessageBox(_T("Failed to get video interfaces!"));
   return hr ;
}

//把指定采集设备与滤波器绑定
if( !BindFilter(iDeviceID,&m_pBF)) return S_FALSE;
//把滤波器添加到滤波器链表中
hr = m_pGB->AddFilter(m_pBF,L"Capture Filter");
//渲染媒体,把链表中的滤波器链接起来
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,m_pBF,NULL,NULL);
if(FAILED(hr)){
   AfxMessageBox(_T("Can't build the graph"));
   return hr ;
}

//设置视频显示窗口
m_hWnd = hWnd; //初始化窗口句柄
SetupVideoWindow(); //设置显示窗口

hr = m_pMC->Run();
if(FAILED(hr)){
   AfxMessageBox(_T("Couldn't run the graph!"));
   return hr ;
}
return S_OK ;
}

/************************************************************************/
/* 设置捕获视频的文件,开始捕捉视频数据写文件                           */
/************************************************************************/
HRESULT CCaptureClass::CaptureImages(CString inFileName)
{
HRESULT hr = 0 ;
m_pMC ->Stop(); //先停止视频
//设置文件名,注意第二个参数的类型
hr = m_pCapture->SetOutputFileName(&MEDIASUBTYPE_Avi,inFileName.AllocSysString(),&pMux,NULL) ;
//渲染媒体,链接所有滤波器
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_pBF,NULL,pMux);
pMux->Release();
m_pMC->Run(); //回复视频
return hr ;
}

int CCaptureClass::EnumDevices(HWND hList)
{
if (!hList)
   return -1;
int id = 0;

//枚举视频扑捉设备
ICreateDevEnum *pCreateDevEnum;            /*此接口生成一个特殊类别的设备枚举器,The System Device Enumerator exposes this interface*/
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)return -1;

IEnumMoniker *pEm=0;              //此接口用来枚举一个"名字"组件或者枚举名字表中的名字
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);//CreateClassEnumerator方法为指定的设备类生成一个类枚举器

if (hr != NOERROR)return -1;

pEm->Reset();                //由于IEnumMoniker接口有一个标准的参考计数,pEm->Release(),一定要释放此接口
ULONG cFetched;

IMoniker *pM;                //此接口包含允许你使用“名字”对象的方法,而名字对象包含能唯一确定COM对象的方法
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)       //返回枚举器队列中指定数目的条款,下“1”个
{
   IPropertyBag *pBag;              //接口IPropertyBag提供一个有属性包的对象,对象可以在包里存储它的特征
   hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);   //返回包含被“moniker”确定的对象的存储位置的接口指针
   if(SUCCEEDED(hr))
   {
    VARIANT var;              //VARIANT结构体包括很多类型
    var.vt = VT_BSTR;             //vt, describes which of the union members is valid,bstrVal是有效的
    hr = pBag->Read(L"FriendlyName", &var, NULL);      //Asks the property bag to read the named

    //property into a caller-initialized VARIANT,var接收
    if (hr == NOERROR)
    {
     //CP_ACP:The current system Windows "ANSI" code page
     //var.bstrVal被转化的
     //-1表示长度被自动计算;str表示转化侯接收目标的地方;两个NULL使函数更快
     id++;
   
     //此函数处理指定的消息,hList窗口的句柄,此窗口处理此消息;CB_ADDSTRING要处理的消息
     ::SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)var.bstrVal);
   
     SysFreeString(var.bstrVal);
    }
    pBag->Release();
   }
   pM->Release();
}
return id;
}

HRESULT CCaptureClass::InitCaptureGraphBuilder()
{
HRESULT hr ;
//创建IGraphBuilder接口
hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&m_pGB);
if(FAILED(hr)) return hr ;
//创建ICaptureGraphBuilder2接口
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,CLSCTX_INPROC,IID_ICaptureGraphBuilder2,(void**)&m_pCapture) ;
if(FAILED(hr)) return hr ;
//初始化滤波器链表管理器IGraphBuilder
m_pCapture->SetFiltergraph(m_pGB);
//查询媒体控制接口
hr = m_pGB->QueryInterface(IID_IMediaControl,(void**)&m_pMC);
if(FAILED(hr)) return hr ;
//查询视频窗口接口
hr = m_pGB -> QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
if(FAILED(hr)) return hr ;
return hr ;
}

//
//配置摄像头数据源格式:分辨率、RGB/I420等
void CCaptureClass::ConfigCameraPin(HWND hwndParent)
{
HRESULT hr ;    //返回值
IAMStreamConfig *pSC ; //流配置接口
ISpecifyPropertyPages *pSpec ; //属性页接口
//只有停止后,才能进行引脚属性的设置
m_pMC ->Stop();
//首先查询捕获CAPTURE、视频VIDEO接口
hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_pBF,IID_IAMStreamConfig,(void**)&pSC);
CAUUID cauuid ;   //所有属性页结构体
hr = pSC->QueryInterface(IID_ISpecifyPropertyPages,(void**)&pSpec);
if( hr == S_OK ){
   hr = pSpec->GetPages(&cauuid); //获取所有属性页
   //显示属性页
   hr = OleCreatePropertyFrame(hwndParent,30,30,NULL,1,(IUnknown**)&pSC,cauuid.cElems,(GUID*)cauuid.pElems,0,0,NULL);
   //释放内存、资源
   CoTaskMemFree(cauuid.pElems);
   pSpec->Release();
   pSC->Release();
}

//回复运行
m_pMC->Run();
}

//
//配置图像参数:亮度、色度、饱和度等
void CCaptureClass::ConfigCameraFilter(HWND hwndParent)
{
HRESULT hr = 0 ;
ISpecifyPropertyPages *pProp ;
hr = m_pBF->QueryInterface(IID_ISpecifyPropertyPages,(void**)&pProp);
if(SUCCEEDED(hr))
{
   //获取滤波器名称和IUnknown接口指针
   FILTER_INFO FilterInfo ;
   hr = m_pBF->QueryFilterInfo(&FilterInfo);
   IUnknown *pFilterUnk ;
   m_pBF->QueryInterface(IID_IUnknown,(void**)&pFilterUnk);
   //显示该页
   CAUUID caGUID ;
   pProp ->GetPages(&caGUID);
   OleCreatePropertyFrame(
    hwndParent,
    0,0,
    FilterInfo.achName,
    1,
    &pFilterUnk,
    caGUID.cElems,
    caGUID.pElems,
    0,
    0,NULL
   );
   //释放内存、资源
   CoTaskMemFree(caGUID.pElems);
   pFilterUnk->Release();
   FilterInfo.pGraph ->Release();
   pProp->Release();
}
m_pMC->Run();
}

在dialog类中声明一个CaptureClass的对象m_cap:

/*CaptureVideoDlg.h*/

#pragma once
#include "afxwin.h"
#include "CaptureClass.h"

// CCaptureVideoDlg 对话框
class CCaptureVideoDlg : public CDialog
{
// 构造
public:
CCaptureVideoDlg(CWnd* pParent = NULL); // 标准构造函数

// 对话框数据
enum { IDD = IDD_CAPTUREVIDEO_DIALOG };

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持


// 实现
protected:
HICON m_hIcon;

// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CStatic m_videoWindow;
public:
CComboBox m_listCtrl;
CCaptureClass m_cap ;
public:
afx_msg void OnBnClickedPreview();
public:
afx_msg void OnBnClickedCapture();
public:
afx_msg void OnBnClickedVideoFormat();
public:
afx_msg void OnBnClickedImageParameter();
public:
afx_msg void OnBnClickedExit();
};

/*CaptureVideoDlg.cpp*/

#include "stdafx.h"
#include "CaptureVideo.h"
#include "CaptureVideoDlg.h"

………………………………

BOOL CCaptureVideoDlg::OnInitDialog()
{

…………

// TODO: 在此添加额外的初始化代码

m_cap.EnumDevices(m_listCtrl);//枚举视频设备,并发送消息给设备下拉列表
m_listCtrl.SetCurSel(0);

…………

}

void CCaptureVideoDlg::OnBnClickedPreview()
{
// TODO: 在此添加控件通知处理程序代码
HWND hVWindow = m_videoWindow.GetSafeHwnd(); //获取视频显示窗口的句柄
int id = m_listCtrl.GetCurSel();     //获取当前选中的视频设备
m_cap.PreviewImages(id,hVWindow);
}

void CCaptureVideoDlg::OnBnClickedCapture()
{
// TODO: 在此添加控件通知处理程序代码
CString strFilter = _T("AVI FILE (*.avi)| *.avi|"); //文件类型过滤器
strFilter += "All File (*.*) | *.* |";
CFileDialog dlg( TRUE , NULL,NULL,OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,strFilter,this);
if(dlg.DoModal() == IDOK ){
   CString m_sourceFile = dlg.GetPathName(); //获取用户输入的文件路径名
   m_cap.CaptureImages(m_sourceFile);
}
}

void CCaptureVideoDlg::OnBnClickedVideoFormat()
{
// TODO: 在此添加控件通知处理程序代码
m_cap.ConfigCameraPin(this->m_hWnd);
}

void CCaptureVideoDlg::OnBnClickedImageParameter()
{
// TODO: 在此添加控件通知处理程序代码
m_cap.ConfigCameraFilter(this->m_hWnd);
}

void CCaptureVideoDlg::OnBnClickedExit()
{
// TODO: 在此添加控件通知处理程序代码
CDialog::OnOK();
}

源代码下载地址:

http://u.115.com/file/aq20aqgm#CaptureVideo.rar

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值