DirectShow学习之二做一个简单的媒体文件播放器

本文介绍了如何利用DirectShow技术开发一个简单的媒体文件播放器。内容涵盖DirectShow的基本概念,如filters和graph的构建,以及处理buffer和依赖性的关键步骤。
摘要由CSDN通过智能技术生成

作者:liguisen

 
       或许你现在还不知道directshow是什么东西,不过你应该知道它可以用来播放电影,ok,我们就做一个简单的媒体文件播放器。什么?我还不知道ds的原理呢,我不懂com呢,我甚至没有什么windows程序的经验呢。都没关系,我们先有一点成就感,再逐步深入。愣是够!
 
       首先,我们需要找两个叫做CDXGraph.h和CDXGraph.cpp的文件。在DX90SDK安装目录搜索了一遍,没有,在网上搜索一把,嗯,有很多,原来是一个“使用directShow播放mpeg的基类”,是“自定义的Filter Graph Manager的一个封装类”,(不知道Filter Graph Manager?没关系),作者不详,本文后面将列出。
 
第一步:(本文使用vs2005)建立一个名叫MyPlayer的MFC dialog based工程。
第二步:配置链接库,假设当前工程是debug版本(这都不清楚的话,嗯,还是慢慢来,先掌握基础好了),则打开project->properties->configuration properties->Linker ->Input->Additional Dependencies增加strmbasd.lib uuid.lib winmm.lib(以后不会说这么详细了)。
第三步:COM库的初始化和清除,直接列出代码了(把系统的注释去掉了)
BOOL CMyPlayerApp::InitInstance()
{
       INITCOMMONCONTROLSEX InitCtrls;
       InitCtrls.dwSize = sizeof(InitCtrls);
       InitCtrls.dwICC = ICC_WIN95_CLASSES;
       InitCommonControlsEx(&InitCtrls);
       CWinApp::InitInstance();
       AfxEnableControlContainer();      
       SetRegistryKey(_T("Local AppWizard-Generated Applications"));
 
       CoInitialize(NULL);//这是我们要增加的,com库的初始化
 
       CMyPlayerDlg dlg;
       m_pMainWnd = &dlg;
       INT_PTR nResponse = dlg.DoModal();
       if (nResponse == IDOK)
       {    
       }
       else if (nResponse == IDCANCEL)
       {
       }
       return FALSE;
}
//友情提示,下面这个函数系统并没有自动添加,在CMyPlayerApp类
//的properties里单击overrides可找到,发现很多用惯了vc6的“老程序员”
//没有了向导很不习惯呢。
int CMyPlayerApp::ExitInstance()
{
       CoUninitialize();//这是我们要增加的,清除com库
       return CWinApp::ExitInstance();
}
第四步:界面开发。
在对话框上放置一个Picture Control,(此类静态控件默认ID为IDC_STATIC,如果在程序中不对它们进行控制,不用修改ID,如果要控制,必须修改其ID号,才可对它进行代码控制,包括添加变量),修改ID为IDC_VIDEO_WINDOW,关联一个Control变量mVideoWindow。
添加一个“打开”和“播放”按钮。
 
第五步:添加CDXGraph.h和CDXGraph.cpp到工程。首先把这两个文件复制到工程源代码所在的地方,然后打开Project->Add Existing Item把它们真正加到工程。
 
第六步: MyPlayerDlg.h 增加include,如下:
#include "afxwin.h"
#include <streams.h>
#include "CDXGraph.h"
再增加两个成员变量:
CDXGraph *    mFilterGraph;     // Filter Graph封装
CString       mSourceFile;      // 源文件
并做一些初始化工作:
CMyPlayerDlg::CMyPlayerDlg(CWnd* pParent /*=NULL*/)
       : CDialog(CMyPlayerDlg::IDD, pParent)
{
       m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
       mFilterGraph = NULL;
       mSourceFile = "";
}
 
此时F7编译,如果出现问题,请参考第一篇 DirectShow学习之一在vs2005中配置directshow开发环境  
 
第七步:添加成员函数CreateGraph和DestroyGraph,编写代码如下:
void CMyPlayerDlg::CreateGraph(void)
{
       DestroyGraph();
       mFilterGraph = new CDXGraph();
       if (mFilterGraph->Create())
       {
              mFilterGraph->RenderFile(mSourceFile);
              mFilterGraph->SetDisplayWindow(mVideoWindow.GetSafeHwnd());
              mFilterGraph->SetNotifyWindow(this->GetSafeHwnd());
              mFilterGraph->Pause();
       }
}
 
void CMyPlayerDlg::DestroyGraph(void)
{
       if (mFilterGraph)
       {
              mFilterGraph->Stop();
              mFilterGraph->SetNotifyWindow(NULL);
              delete mFilterGraph;
              mFilterGraph = NULL;
       }
}
 
 
第八步:实现“打开”功能。
添加一个实现函数:
void CMyPlayerDlg::OnBnClickedButtonOpen()
{
       // TODO: Add your control notification handler code here
       CString    strFilter = "MPEG File (*.mpg;*.mpeg)|*.mpg;*.mpeg|";
       strFilter += "AVI File (*.avi)|*.avi|";
       strFilter += "Mp3 File (*.mp3)|*.mp3|";
       strFilter += "Wave File (*.wav)|*.wav|";
       strFilter += "All Files (*.*)|*.*|";
       CFileDialog dlgOpen(TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
              strFilter, this);
       if (IDOK == dlgOpen.DoModal())
       {
              mSourceFile = dlgOpen.GetPathName();
              CreateGraph();
       }
}
 
此时,编译运行程序,打开一个mpeg文件,应该能显示第一帧的画面了。
第九步:实现“播放”功能。
添加一个实现函数:
void CMyPlayerDlg::OnBnClickedButtonPlay()
{
       // TODO: Add your control notification handler code here
       if (mFilterGraph)
       {
              mFilterGraph->Run();
       }
}
基本上,我们现在就可以用它来看电影了,呵呵。不过,还是有点小问题,当画面被其它窗口挡住之后,再重新出来,画面没了,不能更新,这是小问题:在OnInitDialog()里的return TRUE;前加一句mVideoWindow.ModifyStyle(0, WS_CLIPCHILDREN);然后添加主对话框的WM_ERASEBKGND消息响应:
BOOL CMyPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
       // TODO: Add your message handler code here and/or call default
       CRect rc;
          mVideoWindow.GetWindowRect(&rc);
           ScreenToClient(&rc);
           pDC->ExcludeClipRect(&rc);
       return CDialog::OnEraseBkgnd(pDC);
}
 
尽管太过于简陋,但是&
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值