VS2010基于DirectShows实现视频预览控件
来源:互联网 发布:网络机顶盒看电视软件 编辑:程序博客网 时间:2024/05/22 12:37
之前用VFW实现视频预览控件,使用的时候经常会弹出视频源选择窗口,为了解决这个问题,采用最新的DirectShow来实现视频预览,而且VFW目前基本上已经不使用了,DirectX的功能比较强大。因需求比较单一,还是只实现简单的视频预览功能,并没有实时存储视频。实现过程完全参照MSDN实现。要使用DirectShow的功能首先需要包含头文件
#include<dshow.h>,并引入库 #pragma comment(lib,"strmiids.lib")
一、控件界面
界面还是和上篇VFW实现方法一样。
视频预览大致流程是“枚举视频设备 -> 初始化并绑定视频采集过滤器 -> 将视频导入特定的流中” ,具体实现方法参考MSDN上的DirectShow部分。
为显示界面添加CPreviewWindow类,下面是PreviewWindow.h的实现。
#pragma once#include "afxwin.h"#include <atlbase.h>#include <windows.h>#include <dshow.h>#include <vector>using namespace std;#ifndef SAFE_RELEASE#define SAFE_RELEASE( x ) if ( NULL != x ) { x->Release( ); x = NULL; }#endif#pragma comment(lib,"strmiids.lib")typedef struct Device{CString Description;CString FrindlyName;int WaveInID;CString DevicePath;}Device,*PDevice;// CPreviewWindow 对话框class CPreviewWindow : public CDialogEx{DECLARE_DYNAMIC(CPreviewWindow)public:CPreviewWindow(CWnd* pParent = NULL); // 标准构造函数virtual ~CPreviewWindow();HWND GetHwnd();//返回对话框类句柄// 对话框数据enum { IDD = IDD_VIDEOVIEW };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持DECLARE_MESSAGE_MAP()public:CStatic m_video;public://CVideoCapture(void);//~CVideoCapture(void);HRESULT EnumDevices(REFGUID category);//枚举设备HRESULT InitCaptureGraphBuilder();<span style="white-space:pre"></span>//初始化视频采集过滤器BOOL InitPreview();void StartPreview();void StopPreview();void CancelPreview();void PausePreview();public:IEnumMoniker *pEnum;IMoniker *pMoniker;vector<Device> m_device;IBaseFilter *pCap;//视频采集过滤器//IBaseFilter *SmartTee;//Smart Tee Filter//IBaseFilter *pRender;//Video Render FilterICaptureGraphBuilder2 *pBuilder;//视频采集过滤器图表IGraphBuilder *pGraph;//过滤器图表管理器IVideoWindow *pVideoWindow;IMediaControl *pControl;//用户命令接口,用来控制过滤器图表IMediaEvent *pEvent;//过滤器图表事件接口//HWND hWnd;afx_msg void OnSizing(UINT fwSide, LPRECT pRect);};枚举视频设备实现如下:
HRESULT CPreviewWindow::EnumDevices(REFGUID category){// Create the System Device Enumerator.ICreateDevEnum *pDevEnum;HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pDevEnum));if(SUCCEEDED(hr)){// Create an enumerator for the category.hr = pDevEnum->CreateClassEnumerator(category,&pEnum,0);if(hr == S_FALSE){pDevEnum->Release();return VFW_E_NOT_FOUND;// The category is empty. Treat as an error.}//show device listDevice dev;CString str;while(pEnum->Next(1,&pMoniker,NULL) == S_OK){IPropertyBag *pPropBag;HRESULT hr = pMoniker->BindToStorage(0,0,IID_PPV_ARGS(&pPropBag));if(FAILED(hr)){pMoniker->Release();continue;}VARIANT var;VariantInit(&var);// Get description or friendly name.hr = pPropBag->Read(L"Description",&var,0);if(SUCCEEDED(hr)){dev.Description = var.bstrVal;VariantClear(&var);}hr = pPropBag->Read(L"FriendlyName",&var,0);if(SUCCEEDED(hr)){dev.FrindlyName = var.bstrVal;//MessageBox(dev.FrindlyName);OutputDebugString(var.bstrVal);VariantClear(&var);}hr = pPropBag->Write(L"FrindlyName",&var);hr = pPropBag->Read(L"WaveInID",&var,0);if(SUCCEEDED(hr)){dev.WaveInID = var.lVal;VariantClear(&var);}hr = pPropBag->Read(L"DevicePath",&var,0);if(SUCCEEDED(hr)){dev.DevicePath = var.bstrVal;VariantClear(&var);}m_device.push_back(dev);//增加设备pPropBag->Release();pMoniker->Release();}pDevEnum->Release();}return hr;}初始化视频采集过滤器:
HRESULT CPreviewWindow::InitCaptureGraphBuilder(){// Create the Capture Graph BuilderHRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2,(void**)&pBuilder);if(SUCCEEDED(hr)){// Create the Filter Graph Manager.hr = CoCreateInstance(CLSID_FilterGraph,0,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGraph);if(SUCCEEDED(hr)){pBuilder->SetFiltergraph(pGraph);return S_OK;}else{pBuilder->Release();}}return hr;}初始化好视频采集过滤器之后就可以将其绑定到视频源上采集数据,那么采集到的数据如何显示到界面上呢?这是最关键的问题。
首先定义一个IVideoWindow类型的对象,该对象用于连接视频图像数据与MFC窗口界面。下面就实现这个功能:
BOOL CPreviewWindow::InitPreview(){if(pMoniker == NULL)EnumDevices(CLSID_VideoInputDeviceCategory);//枚举设备HRESULT hr = pMoniker->BindToObject(0,0,IID_IBaseFilter,(void**)&pCap);if(SUCCEEDED(hr)){hr = pGraph->AddFilter(pCap,L"Capture Filter");}hr = pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,pCap,NULL,NULL);hr = pGraph->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow);if(SUCCEEDED(hr)){pVideoWindow->put_Owner((OAHWND)this->m_hWnd);//设定视频窗口为主窗口的一个子窗口pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);//设定窗口模式CRect rectClient;::GetClientRect(this->m_hWnd,rectClient);pVideoWindow->SetWindowPosition(0,0,rectClient.right,rectClient.bottom);//设定窗口大小}else{return FALSE;}hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);if(FAILED(hr)){return FALSE;}return TRUE;}
到目前已经可以显示视频预览了,那么如何控制视频预览呢?
定义一个IMediaControl pControl对象来控制视频的预览,下面就具体实现视频预览的控制方法:
void CPreviewWindow::PausePreview(){if(pControl)pControl->Pause();//暂停}void CPreviewWindow::StopPreview(){if(pControl)pControl->Stop();//停止pVideoWindow->put_Visible(FALSE);}void CPreviewWindow::StartPreview(){pVideoWindow->put_Visible(OATRUE);//设定可视pControl->Run();//开始预览}
调用方法:
在控件CVideoPreviewCtrl类中添加如下代码:
public:
CPreviewWindow m_PreviewWin;
BOOL InitFlag;
void EnumDevices(void);
void StartPreview(void);
void PausePreview(void);
void StopPreview(void);
重写OnCreate方法:
int CVideoPreviewCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
if(!m_PreviewWin.Create(IDD_VIDEOVIEW,this))
MessageBox(L"创建对话框失败");
m_PreviewWin.InitCaptureGraphBuilder();
InitFlag = m_PreviewWin.InitPreview();
return 0;
}
添加接口供外部调用:
void CVideoPreviewCtrl::StartPreview(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
//MessageBox(L"开始预览");
//m_PreviewWin.EnumDevices(CLSID_VideoInputDeviceCategory);
if(InitFlag)
m_PreviewWin.StartPreview();
}
void CVideoPreviewCtrl::PausePreview(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
m_PreviewWin.PausePreview();
}
void CVideoPreviewCtrl::StopPreview(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
m_PreviewWin.StopPreview();
}
测试方法参见VFW实现。
CVideoWindow.cpp
- VS2010基于DirectShows实现视频预览控件
- 趁热打铁之---VS2010基于VFW的视频控件编写,实现预览、拍照功能
- VS2010 C++学习(5):基于DirectShow的视频预览录像程序
- VS2010 C++学习(5):基于DirectShow的视频预览录像程序
- 基于VFW的视频预览
- DirectShow .Net 实现视频预览
- mvc实现上传视频预览
- #Testin杯#基于android的远程视频监控系统——学习第一步:实现Camera预览
- 基于flowplayer的视频缩略图的视频预览
- 基于flowplayer的视频缩略图的视频预览
- 基于flowplayer的视频缩略图的视频预览
- WIFI视频实时预览功能的实现
- VS2010自定义控件实现信号灯
- 基于VS2010的上传文件控件
- 预览: 基于wap的Msn Messenger实现...
- 附件在线预览控件实现的市场调研
- directshow学习笔记四-----视频预览(将预览视频播放到指定picture控件中,个人学习所用,仅供参考)
- DirectShow .Net 实现视频预览(重点源码记录)
- Unity骑士团一个月的训练
- 23种设计模式(8):组合模式
- 高性能IO模型浅析
- d第十六周上机项目2 用指针玩字符串
- spring iBATIS 整合
- VS2010基于DirectShows实现视频预览控件
- Android学习之生命周期
- 【HEVC学习与研究】12.HEVC的高层语法结构
- android开发AIDL实例
- NEERC2013 Kabaleo Lite
- 【HEVC学习与研究】13.NAL unit解码
- Linux系统各种监控命令
- android 利用WakeLock延迟系统深度睡眠
- Android Notificaton