已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。DirectShow为多媒体的捕捉和回放提供了强有力的支持。运用DirectShow我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等等,使得多媒体数据的回放变得轻而易举。另外,DirectShow还集成了DirectX其它部分(比如DirectDraw、DirectSound)的技术,直接支持DVD播放,视频的非线性编辑,以及与数据摄像机的交换换。更值得一提的是,DirectShow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。(引)入门DirectShow使用一种叫做Filter Graph的模型来管理整个数据流的处理过程,参与数据流处理的各个功能模块称做Filter,各个Filter在Filter Graph中按一定的顺序连成一条流水线协调工作,完成一些相对独立的功能,如Filter可以完成如下的一些功能:l 读文件l 从视频设备中获取视频l 对视频流进行解码l 将数据送往声卡或显卡每个Filter都有输入端和输出端,例如一个MPEG-1解码Filter它的输入是MPEG编码的流数据,它的输出端是一解码过的流数据。DirectShow正是通过将不同的Filter连接在一起完成特定的功能的,我们将这些Filter的连接叫做Filter Graph,如下图A给出是播放AVI的Filter Graph:图A播放AVI文件的Graph Filter图上图中每个模块分别代表了不同的Filter,媒体文件Filter从硬盘读取AVI文件,AVI分离Filter将文件分离为音频流和视频流,AVI解码Filter对视频流进行解码并送往Video表现Filter,由后者将各帧在显示器上显示,默认的DirectSound设备用DirectSound将音频流输出。我们的应用并不需要对这当中的所以的数据流进行管理,在DirectShow提供一个称做Filter Graph管理器的高级组件。在我们的应用中只需要调用它的API即可,如Run、Stop等,如果你想对其中的数据流做更进一步的控制,你可以对这些Filter直接通过COM接口进行存取。Filter Graph管理器同时也提供了另一个功能:应用程序可以通过管理器控制Filter Graph如何生成。DirectShow应用从广义上说,所有的DirectShow应用都必须完成三件事情,如下图B所示:图B1 生成Filter Graph管理器的一个实例。2 利用Filter Grapth实例生成Filter Graph,具体应该由哪些Filter组成Filter Graph视我们的应用的需要而定。3 通过对Filter Graph管理器的方法调用和来自Filter Graph的消息的响应Filter Graph和数据流进行控制。DirectShow是基于COM的,Filter Graph管理器和Filter都是COM对象 ,在开始着手之前你应该对COM有个基本的认识。下面让我们着手开始做一个简单的DirectShow应用,在这个应用中我们实现这样的功能:打开一个媒体文件,并对其进行播放。设置环境在利用DirectShow进行流媒体的处理之前,必须正确安装DirectX的SDK,DirectX SDK可以到微软的网站上下载,目前,DirectX最新版本为9.0。本文将对DirectShow的应用进行入门级的应用。在正确安装好DirectX SDK后,我们必须设置DirectX SDK的头文件和库文件,使其在Visual Studio的搜索路径内。对于Visual Studio .NET 2003可如下进行设置:菜单工具选项项目VC+目录,在包含文件中加入D:DXSDKInclude,在库文件中加入D:DXSDKlib(我的SDK的安装路径是D:DXSDK):头文件文件名称描述Dshow.h所有的DirectShow应用都必须包含库文件文件名称描述Strmiids.lib此库文件中导出类标识(CLSID)和接口标识(IID),所有的DirectShow应用都必须包含此文件。Quartz.lib此库文件中导出函数AMGetErrorText,如果你的程序中调用了此函数,则必须包含此库文件。开始工程打开Visual Studio .NET 2003,文件新建项目1.生成基于MFC的应用程序,名称PlayWnd。2.选择应用程序类型基于对话框,点击完成。3.设置工程属性项目PlayWnd属性配置属性链接器输入附加依赖项,添加库文件Strmiids.lib 和Quartz.lib。由于Dshow.h头文件是在任何DirectShow工程中都要用到的,因此我们stdafx.h加入如下行:#include 4.设计对话框,如下:IDC_STATIC控件类型Static TextCaption媒体文件名:IDC_MEDIAFILE_EDIT控件类型Edit ControlIDC_BROWSE_BUTTON控件类型ButtonCaption浏览IDC_VW_FRAME控件类型Picture ControlTypeRectangleIDC_PLAY_BUTTON控件类型ButtonCaption播放IDC_PAUSE_BUTTON控件类型ButtonCaption暂停IDCANCEL控件类型ButtonCaption关闭5.COM的初始化和卸载,修改PlayWnd.cpp添加初始化代码(加入的代码用黑体表示,下同)BOOL CPlayWndApp:InitInstance()/ 如果一个运行在 Windows XP 上的应用程序清单指定要/ 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,/则需要 InitCommonControls()。否则,将无法创建窗口。InitCommonControls();/初始化COM接口HRESULT hr = CoInitialize(NULL);if (FAILED(hr)TRACE(ERROR - Could not initialize COM library.n);return FALSE;CWinApp:InitInstance();AfxEnableControlContainer();修改PlayWnd.cpp添加卸载COM代码,注意需要对虚函数ExitInstance进行重载,并在PlayWnd.h文件中声明:public:virtual int ExitInstance();int CPlayFileApp:ExitInstance()/ TODO: 在此添加专用代码和/或调用基类/关闭COMCoUninitialize();return CWinApp:ExitInstance();6.定义媒体控制成员变量修改PlayWndDlg.h如下: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()/和媒体控制相关的成员变量private:IGraphBuilder *m_pGraph;/IGraphBuilder 接口提供了生成Filter Graph相/关的方法IMediaControl *m_pMediaControl;/IMediaControl 接口提供了控制流经Filter /Graph数据流的相关方法IMediaEventEx *m_pEvent;/IMediaEventEx 继承自IMediaEvent,提供了从/Filter Graph 管理器获取事件消息的方法IMediaSeeking *m_pMediaSeeking;/IMediaSeeking 提供了控制流的播放位置和播放/速度的方法CString m_strMediaFile;/当前播放的媒体文件的名称BOOL m_isPlaying;/当前的播放状态;在CPlayWndDlg的构造函数中添加初始化代码CPlayWndDlg:CPlayWndDlg(CWnd* pParent /*=NULL*/): CDialog(CPlayWndDlg:IDD, pParent)m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME);m_pGraph= NULL;m_pMediaControl = NULL;m_pEvent= NULL;m_pMediaSeeking = NULL;m_strMediaFile = ;m_isPlaying = FALSE;由于一些和窗体控制有关的初始化代码不能放在构造函数中进行,我们将其放在CPlayWndDlg:OnInitDialog()中,我们必须在此必须对CPlayWndDlg添加WS_CLIPCHILDREN 的Style,因为在我们的应用中把视频窗体作为CPlayWndDlg的一个子窗体来使用的,这是非常重要的,许多开发人员在刚开始使用DirectShow时,父窗体的Style没有设置正确,造成视频不能正确显示,代码如下:/ 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动/ 执行此操作SetIcon(m_hIcon, TRUE);/ 设置大图标SetIcon(m_hIcon, FALSE);/ 设置小图标/ TODO: 在此添加额外的初始化代码ModifyStyle(0, WS_CLIPCHILDREN);(CEdit*)GetDlgItem(IDC_MEDIAFILE_EDIT)-SetReadOnly(TRUE);return TRUE; / 除非设置了控件的焦点,否则返回 TRUE添加相应的清除代码,重载CPlayWndDlg的DestoryWindow方法,如下:BOOL CPlayWndDlg:DestroyWindow()/ TODO: 在此添加专用代码和/或调用基类if(m_pGraph)m_pGraph-Release();if(m_pMediaControl)m_pMediaControl-Release();if(m_pEvent)m_pEvent-Release();if(m_pMediaSeeking)m_pMediaSeeking-Release();m_pGraph = NULL;m_pMediaControl = NULL;m_pEvent = NULL;m_pMediaSeeking = NULL;return CDialog:DestroyWindow();7修改CPlayWndDlg:OnPaint(),由于现在视频显示区域必须由我们自己进行重画:void CPlayWndDlg:OnPaint() if (IsIconic()CPaintDC dc(this); / 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast(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);elseif(m_isPlaying = FALSE)CClientDC dc(GetDlgItem(IDC_VW_FRAME);dc.SetBkColor(RGB(0,0,0);CRect rc;GetDlgItem(IDC_VW_FRAME)-GetClientRect(rc);/ClientToScreen(rc);dc.FillRect(rc, CBrush:FromHandle(HBRUSH)GetStockObject(BLACK_BRUSH);GetDlgItem(IDC_VW_FRAME)-Invalidate();CDialog:OnPaint();添加浏览、播放、暂停、关闭四按钮的相应事件响应函数,同时在CPlayWndDlg中添加如下四个私有方法:void MoveVideoWindow(void);void CleanUp(void);BOOL Stop(void);BOOL Play(void);上述方法的实现如下:/ IDC_VW_FRAME控件Picture Control主要作用是控制Vedio Window的显示位置void CPlayWndDlg:MoveVideoWindow(void)IVideoWindow* pVideoWinow = NULL;if(m_pGraph)m_pGraph-QueryInterface(IID_IVideoWindow, (void *)&pVideoWinow);CRect rc;GetDlgItem(IDC_VW_FRAME)-GetWindowRect(rc);ScreenToClient(rc);pVideoWinow-SetWindowPosition(rc.left, rc.top, rc.Width(), rc.Height();pVideoWinow-Release();pVideoWinow = NULL;void CPlayWndDlg:CleanUp(void)long levCode;IVideoWindow *pVidWin = NULL;if(!m_pGraph)return;m_pGraph-QueryInterface(IID_IVideoWindow, (void *)&pVidWin);m_pEvent-WaitForCompletion(INFINITE, &levCode);pVidWin-put_Visible(OAFALSE);pVidWin-Release();m_pMediaSeeking-Release();m_pMediaControl-Release();m_pEvent-Release();m_pGraph-Release();m_pMediaSeeking = NULL;m_pMediaControl = NULL;m_pEvent = NULL;m_pGraph = NULL;UpdateData(FALSE);CClientDC dc(GetDlgItem(IDC_VW_FRAME);dc.SetBkColor(RGB(0,0,0);CRect rc;GetDlgItem(IDC_VW_FRAME)-GetClientRect(rc);ClientToScreen(rc);dc.FillRect(rc, CBrush:FromHandle(HBRUSH)GetStockObject(BLACK_BRUSH);Invalidate();BOOL CPlayWndDlg:Stop(void)IVideoWindow *pVidWin = NULL;HRESULT hr;if(m_pMediaControl)LONGLONG pos = 0;hr = m_pMediaControl-Stop();hr = m_pMediaSeeking-SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,&pos, AM_SEEKING_NoPositioning);m_pGraph-QueryInterface(IID_IVideoWindow, (void *)&pVidWin);pVidWin-put_Visible(OAFALSE);m_isPlaying = FALSE;GetDlgItem(IDC_PLAY_BUTTON)-EnableWindow(TRUE);GetDlgItem(IDC_PAUSE_BUTTON)-EnableWindow(FALSE);pVidWin-Release();long levCode;m_pEvent-WaitForCompletion(INFINITE, &levCode);m_pMediaControl-Release();return TRUE;return FALSE;BOOL CPlayWndDlg:Play(void)/ 运行IVideoWindow *pVidWin = NULL;if(m_pGraph)m_pGraph-QueryInterface(IID_IVideoWindow, (void *)&pVidWin);pVidWin-put_Visible(OATRUE);m_pGraph-QueryInterface(IID_IMediaControl, (void *)&m_pMediaControl);m_pMediaControl-Run();m_isPlaying = TRUE;GetDlgItem(IDC_PLAY_BUTTON)-EnableWindow(FALSE);GetDlgItem(IDC_PAUSE_BUTTON)-EnableWindow(TRUE);return TRUE;return FALSE;浏览、播放、暂停、关闭四按钮的相应事件响应函数如下:void CPlayWndDlg:OnBnClickedBrowseButton()CFileDialog dlgFile(TRUE, NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,Movie Files (*.avi;*.mpg;*.mpeg) |*.avi;*.mpg;*.mpeg |Audio Files (*.wav;*mp3;*.mpa;*.mpu;*.au) |*.wav;*.mp3;*.mpa;*.mpu;*.au |Midi Files (*.mid;*.midi;*.rmi) |*.mid;*.midi;*.rmi| | , this);if(dlgFile.DoModal() = IDOK)m_strMediaFile = dlgFile.GetPathName();GetDlgItem(IDC_MEDIAFILE_EDIT)-SetWindowText(m_strMediaFile);elsereturn;CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void *)&m_pGraph);HRESULT hr = m_pGraph-RenderFile(CA2W(m_strMediaFile), NULL);if(FAILED(hr)char szMsg200;AMGetErrorText(hr, szMsg, sizeof(szMsg);AfxMessageBox(szMsg);/指定父窗体IVideoWindow* pVidWin = NULL;m_pGraph-QueryInterface(IID_IVideoWindow, (void *)&pVidWin);pVidWin-put_Owner(OAHWND)m_hWnd);pVidWin-put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);CRect rc;GetDlgItem(IDC_VW_FRAME)-GetWindowRect(rc);ScreenToClient(rc);pVidWin-SetWindowPosition(rc.left, rc.top, rc.Width(), rc.Height();/ 注意此处Filter Graph Manager的事件以WM_GRAPHNOTIFY发出(用户定义的消息).m_pGraph-QueryInterface(IID_IMediaEventEx, (void *)&m_pEvent);m_pEvent-SetNotifyWindow(OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);/ 设置Seekingm_pGraph-QueryInterface(IID_IMediaSeeking, (void *)&m_pMediaSeeking);void CPlayWndDlg:OnBnClickedPlayButton()Play();void CPlayWndDlg:OnBnClickedPauseButton()m_pMediaControl-Pause();m_isPlaying = TRUE;GetDlgItem(IDC_PLAY_BUTTON)-EnableWindow(TRUE);GetDlgItem(IDC_PAUSE_BUTTON)-EnableWindow(FALSE);void CPlayWndDlg:OnBnClickedCancel()/ TODO: 在此添加控件通知处理程序代码CleanUp();OnCancel();8添加对WM_GRAPHNOTIFY消息,及其响应函数在PlayWndDlg添加消息ID定义:#define WM_GRAPHNOTIFY WM_USER
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026届新疆师范大学附属实验高中化学高二第一学期期末经典试题含答案
- 社工站建设运营合同
- 重庆市下学期小学六年级数学期中素养测评试卷
- 贵州省小学五年级上学期数学第二单元测试卷-位置(在线学习)
- 2025年7-9月销售部门三季度总结与Q4客户拓展方案
- 2025年Q1环保工程施工方案优化及工期缩短工作总结
- 贵州省仁怀市三年级下学期语文建议书写作针对性评估
- 日本奶茶店转让合同
- 代表签订合同
- 烧烤美食园转让合同
- 架梁施工安全培训课件
- (新版)M9执照英语易考易错高频考试题库500道(含答案)
- 华为集团薪酬管理制度
- 十五五蓝图照进青春现实+课件-2025-2026学年高二上学期二十届四中全会精神主题团课
- 2025年事业单位招聘考试《公共基础知识》试题库审定版
- 2024年3月青少年机器人技术等级考试理论综合试卷五级真题(含答案)
- 消化内科消化道出血护理流程探讨
- 中泰证券2025届秋季校园招聘笔试历年常考点试题专练附带答案详解试卷3套
- 产后恶露排出不畅的中医外治方案
- 2025年中国氧化镁现状分析及市场前景预测
- 2025年智能衣架市场分析现状
评论
0/150
提交评论