转:Directshow开发的一些例子

来源:互联网 发布:nginx rtmp win 下载 编辑:程序博客网 时间:2024/06/01 23:40

DirectShow Filter 开发典型例子分析 ——字幕叠加 (FilterTitleOverlay)1

本文分析一下《DirectShow开发指南》中的一个典型的Transform Filter的例子:字幕叠加(FilterTitleOverlay)。通过分析该例子,我们可以学习到DirectShow Transform Filter 开发的方式。

直接打开项目工程(我这里是VC2010),看到项目的结构如下图所示:

先看一下运行的结果:

注意,DirectShow的Filter是不可以直接运行进行调试的。一般情况下需要借助于Graphedit.exe这个程序进行调试。当然这不是绝对的,也可以用graph-studio-next这样的开源程序。

选择右键点击工程->属性->调试->命令。在栏中输入Graphedit.exe的路径,如图所示

这样就可以调试Filter了。

拖入一个文件"五月天 咸鱼.mp4",然后插入本工程的Filter,如图所示。

播放视频,效果如图,可见左上角显示出 "Hello, DirectShow!" 的字样。

看完了结果,就要开始分析代码了~

回顾一下工程结构图:

先看一下CFilterTitleOverlay.h(已经在重要的地方加了注释):

复制代码
//// CFilterTitleOverlay.h//#ifndef __H_CFilterTitleOverlay__#define __H_CFilterTitleOverlay__#include "ITitleOverlay.h"#include "COverlayController.h"#include "OverlayDefs.h"class CFilterTitleOverlay : public CTransInPlaceFilter                            , public ISpecifyPropertyPages                            , public ITitleOverlay  {  private:      OVERLAY_TYPE            mOverlayType;      COverlayController *    mOverlayController;      CCritSec                mITitleOverlaySync;  BOOL                    mNeedEstimateFrameRate;  private:      CFilterTitleOverlay(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);      ~CFilterTitleOverlay();  HRESULT SetInputVideoInfoToController(void);  void ReleaseOverlayController(void);  void SideEffectOverlayTypeChanged(void);  public:  static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);  //说明必须重写NonDelegatingQueryInterface    DECLARE_IUNKNOWN;  // Basic COM - used here to reveal our own interfaces//暴露接口,使外部程序可以QueryInterface,关键!    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);  // check if you can support mtInvirtual HRESULT CheckInputType(const CMediaType* mtIn); // PURE//必须重写的核心函数virtual HRESULT Transform(IMediaSample *pSample); // PURE// Delegating methodsvirtual HRESULT CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin);  virtual HRESULT StartStreaming();  virtual HRESULT StopStreaming();  // --- ISpecifyPropertyPages ---    STDMETHODIMP GetPages(CAUUID *pPages);  // --- ITitleOverlay methods ---//都是接口函数    STDMETHODIMP put_TitleOverlayType(long inOverlayType);      STDMETHODIMP get_TitleOverlayType(long * outOverlayType);      STDMETHODIMP put_TitleOverlayStyle(int inUsingCover);      STDMETHODIMP get_TitleOverlayStyle(int * outUsingCover);      STDMETHODIMP put_Title(const char * inTitle, int inLength);      STDMETHODIMP get_Title(char * outBuffer, int * outLength);      STDMETHODIMP put_TitleColor(BYTE inR, BYTE inG, BYTE inB);      STDMETHODIMP get_TitleColor(BYTE * outR, BYTE * outG, BYTE * outB);      STDMETHODIMP put_TitleStartPosition(POINT inStartPos);      STDMETHODIMP get_TitleStartPosition(POINT * outStartPos);      STDMETHODIMP put_TitleFont(LOGFONT inFont);      STDMETHODIMP get_TitleFont(LOGFONT * outFont);      STDMETHODIMP put_TitleDuration(double inStart, double inEnd);      STDMETHODIMP get_TitleDuration(double * outStart, double * outEnd);  };  #endif // __H_CFilterTitleOverlay__
复制代码

CFilterTitleOverlay继承了CTransInPlaceFilter,意味着Transform()函数输入和输出的数据位于同一块内存中。

以下几个函数是必须有的:

CreateInstance():创建Filter 
NonDelegatingQueryInterface():暴露接口,使外部程序可以QueryInterface 
CheckInputType():检查输入类型 
Transform():核心处理函数(字幕叠加)

另外还包含了ITitleOverlay中的函数put_TitleOverlayType()等等一大堆。

下面看一下CFilterTitleOverlay.cpp吧,先列出注册信息部分:

复制代码
//唯一标识符// {E3FB4BFE-8E5C-4aec-8162-7DA55BE486A1}DEFINE_GUID(CLSID_HQTitleOverlay,   0xe3fb4bfe, 0x8e5c, 0x4aec, 0x81, 0x62, 0x7d, 0xa5, 0x5b, 0xe4, 0x86, 0xa1);  // {E70FE57A-19AA-4a4c-B39A-408D49D73851}DEFINE_GUID(CLSID_HQTitleOverlayProp,   0xe70fe57a, 0x19aa, 0x4a4c, 0xb3, 0x9a, 0x40, 0x8d, 0x49, 0xd7, 0x38, 0x51);  //// setup data////注册时候的信息const AMOVIESETUP_MEDIATYPE sudPinTypes =  {      &MEDIATYPE_NULL,            // Major type    &MEDIASUBTYPE_NULL          // Minor type};  //注册时候的信息const AMOVIESETUP_PIN psudPins[] =  {      {          L"Input",           // String pin name        FALSE,              // Is it rendered        FALSE,              // Is it an output        FALSE,              // Allowed none        FALSE,              // Allowed many        &CLSID_NULL,        // Connects to filter        L"Output",          // Connects to pin        1,                  // Number of types        &sudPinTypes },     // The pin details      { L"Output",          // String pin name        FALSE,              // Is it rendered        TRUE,               // Is it an output        FALSE,              // Allowed none        FALSE,              // Allowed many        &CLSID_NULL,        // Connects to filter        L"Input",           // Connects to pin        1,                  // Number of types        &sudPinTypes        // The pin details    }  };  //注册时候的信息const AMOVIESETUP_FILTER sudFilter =  {      &CLSID_HQTitleOverlay,       // Filter CLSID    L"HQ Title Overlay Std.",    // Filter name    MERIT_DO_NOT_USE,        // Its merit    2,                       // Number of pins    psudPins                 // Pin details};  // List of class IDs and creator functions for the class factory. This// provides the link between the OLE entry point in the DLL and an object// being created. The class factory will call the static CreateInstance//注意g_Templates名称是固定的CFactoryTemplate g_Templates[] =   {      {           L"HQ Title Overlay Std.",          &CLSID_HQTitleOverlay,          CFilterTitleOverlay::CreateInstance,          NULL,          &sudFilter       },      {           L"HQ Title Overlay Property Page",          &CLSID_HQTitleOverlayProp,          CTitleOverlayProp::CreateInstance       }  };  int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
复制代码

这一部分并不属于CFilterTitleOverlay这个类。主要是DirectShow Filter的一些注册信息。其结构是非常固定的。

再来看看CFilterTitleOverlay中函数实现部分(只列了几个函数,不然内容太多= =):

CreateInstance():

复制代码
//// CreateInstance//// Override CClassFactory method.// Provide the way for COM to create a CNullInPlace object////创建CUnknown * WINAPI CFilterTitleOverlay::CreateInstance(LPUNKNOWN punk, HRESULT *phr)   {  #if 1//防伪??!!char    szCreatorPath[256], szCreatorName[256];      ::strcpy(szCreatorPath, "");      ::strcpy(szCreatorName, "");  HMODULE hModule = ::GetModuleHandle(NULL);      ::GetModuleFileName(hModule, szCreatorPath, 256);  char * backSlash = ::strrchr(szCreatorPath, '\\');  if (backSlash)      {          strcpy(szCreatorName, backSlash);      }      ::_strlwr(szCreatorName);  // Please specify your app name with lowercase// 检查调用该Filter的程序// 一开始调试不了,就卡在这了 = =if (::strstr(szCreatorName, "graphedit") == NULL &&          ::strstr(szCreatorName, "ourapp") == NULL)      {          *phr = E_FAIL;  return NULL;      }  #endif//通过New对象的方法    CFilterTitleOverlay *pNewObject = new CFilterTitleOverlay(NAME("TitleOverlay"), punk, phr);  if (pNewObject == NULL)       {          *phr = E_OUTOFMEMORY;      }  return pNewObject;  }
复制代码

NonDelegatingQueryInterface():

复制代码
//// Basic COM - used here to reveal our own interfaces//暴露接口,使外部程序可以QueryInterface,关键!STDMETHODIMP CFilterTitleOverlay::NonDelegatingQueryInterface(REFIID riid, void ** ppv)  {      CheckPointer(ppv, E_POINTER);  //根据不同的REFIID,获得不同的接口指针if (riid == IID_ISpecifyPropertyPages)       {  return GetInterface((ISpecifyPropertyPages *) this, ppv);      }  else if (riid == IID_ITitleOverlay)      {  return GetInterface((ITitleOverlay *) this, ppv);      }  else    {  //不是以上的REFIID的话,调用父类的return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);      }  } // NonDelegatingQueryInterface
复制代码

CheckInputType():

复制代码
// Only RGB 32/24/565/555 supported HRESULT CFilterTitleOverlay::CheckInputType(const CMediaType* mtIn)  {  // Dynamic format change will never be allowed!if (IsStopped() && *mtIn->Type() == MEDIATYPE_Video)      {  if (*mtIn->Subtype() == MEDIASUBTYPE_RGB32 ||              *mtIn->Subtype() == MEDIASUBTYPE_RGB24 ||              *mtIn->Subtype() == MEDIASUBTYPE_RGB555 ||              *mtIn->Subtype() == MEDIASUBTYPE_RGB565)          {  return NOERROR;          }      }  return E_INVALIDARG;  }
复制代码

Transform():

复制代码
HRESULT CFilterTitleOverlay::Transform(IMediaSample *pSample)  {  // If we cann't read frame rate info from input pin's connection media type,// We estimate it from the first sample's time stamp!if (mNeedEstimateFrameRate)      {          mNeedEstimateFrameRate = FALSE;          REFERENCE_TIME  startTime = 0;          REFERENCE_TIME  endTime   = 0;  double          estimated = 25;  if (SUCCEEDED(pSample->GetTime(&startTime, &endTime)))          {              estimated = 1.0 * UNITS / (endTime - startTime);          }          mOverlayController->SetEstimatedFrameRate(estimated);      }  if (mOverlayType != OT_NONE)      {  //PBYTE是unsigned charPBYTE  pData = NULL;  //获取IMediaSample中的数据        pSample->GetPointer(&pData);  //叠加        mOverlayController->DoTitleOverlay(pData);      }  return NOERROR;  }
复制代码

下面列出实现ITitleOverlay接口的函数的实现,就列了一个。

STDMETHODIMP CFilterTitleOverlay::get_Title(char * outBuffer, int * outLength)  {      CAutoLock   lockit(&mITitleOverlaySync);      *outLength = mOverlayController->GetTitle(outBuffer);  return NOERROR;  }

暂且分析到这里。

书上提供的代码有误,这是经过修改后,添加了注释的代码:

http://download.csdn.net/detail/leixiaohua1020/6371819

一个简单的基于 DirectShow 的播放器 1(封装类)

DirectShow最主要的功能就是播放视频,在这里介绍一个简单的基于DirectShow的播放器的例子,是用MFC做的,今后有机会可以基于该播放器开发更复杂的播放器软件。

注:该例子取自于《DirectShow开发指南》

首先看一眼最终结果,如图所示,播放器包含了:打开,播放,暂停,停止等功能。该图显示正在播放周杰伦的《听妈妈的话》。

迅速进入主题,看一看工程是由哪些文件组成的,如下图所示

从上图可以看出,该工程最重要的cpp文件有两个:SimplePlayerDlg.cpp和CDXGraph.cpp。前者是视频播放器对话框对应的类,而后者是对DirectShow功能进行封装的类。尤其是后面那个类,写的很好,可以说做到了“可复用”,可以移植到其他DirectShow项目中。

本文首先分析CDXGraph这个类,SimplePlayerDlg在下篇文章中再进行分析。

首先看看它的头文件:

CDXGraph.h

复制代码
/* 雷霄骅 * 中国传媒大学/数字电视技术 * leixiaohua1020@126.com * */// CDXGraph.h#ifndef __H_CDXGraph__#define __H_CDXGraph__// Filter graph notification to the specified window#define WM_GRAPHNOTIFY  (WM_USER+20)class CDXGraph  {  private:  //各种DirectShow接口    IGraphBuilder *     mGraph;        IMediaControl *     mMediaControl;      IMediaEventEx *     mEvent;      IBasicVideo *       mBasicVideo;      IBasicAudio *       mBasicAudio;      IVideoWindow  *     mVideoWindow;      IMediaSeeking *     mSeeking;  DWORD               mObjectTableEntry;   public:      CDXGraph();  virtual ~CDXGraph();  public:  //创建IGraphBuilder,使用CoCreateInstancevirtual bool Create(void);  //释放virtual void Release(void);  virtual bool Attach(IGraphBuilder * inGraphBuilder);      IGraphBuilder * GetGraph(void); // Not outstanding reference count    IMediaEventEx * GetEventHandle(void);  bool ConnectFilters(IPin * inOutputPin, IPin * inInputPin, const AM_MEDIA_TYPE * inMediaType = 0);  void DisconnectFilters(IPin * inOutputPin);  bool SetDisplayWindow(HWND inWindow);  bool SetNotifyWindow(HWND inWindow);  bool ResizeVideoWindow(long inLeft, long inTop, long inWidth, long inHeight);  void HandleEvent(WPARAM inWParam, LPARAM inLParam);  //各种操作bool Run(void);        // Control filter graphbool Stop(void);  bool Pause(void);  bool IsRunning(void);  // Filter graph statusbool IsStopped(void);  bool IsPaused(void);  bool SetFullScreen(BOOL inEnabled);  bool GetFullScreen(void);  // IMediaSeekingbool GetCurrentPosition(double * outPosition);  bool GetStopPosition(double * outPosition);  bool SetCurrentPosition(double inPosition);  bool SetStartStopPosition(double inStart, double inStop);  bool GetDuration(double * outDuration);  bool SetPlaybackRate(double inRate);  // Attention: range from -10000 to 0, and 0 is FULL_VOLUME.bool SetAudioVolume(long inVolume);  long GetAudioVolume(void);  // Attention: range from -10000(left) to 10000(right), and 0 is both.bool SetAudioBalance(long inBalance);  long GetAudioBalance(void);  bool RenderFile(const char * inFile);  bool SnapshotBitmap(const char * outFile);  private:  void AddToObjectTable(void) ;  void RemoveFromObjectTable(void);  //各种QueryInterface,初始各种接口bool QueryInterfaces(void);  };  #endif // __H_CDXGraph__
复制代码

该头文件定义了CDXGraph类封装的各种DirectShow接口,以及提供的各种方法。在这里因为方法种类特别多,所以只能选择最关键的方法进行分析。下面打开CDXGraph.cpp看看如下几个方法吧:

Create():用于创建IGraphBuilder

复制代码
//创建IGraphBuilder,使用CoCreateInstancebool CDXGraph::Create(void)  {  if (!mGraph)      {  if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,              IID_IGraphBuilder, (void **)&mGraph)))          {              AddToObjectTable();  return QueryInterfaces();          }          mGraph = 0;      }  return false;  }
复制代码

需要注意的是,Create()调用了QueryInterfaces()

QueryInterfaces():用于初始化各种接口

复制代码
//各种QueryInterface,初始各种接口bool CDXGraph::QueryInterfaces(void)  {  if (mGraph)      {  HRESULT hr = NOERROR;          hr |= mGraph->QueryInterface(IID_IMediaControl, (void **)&mMediaControl);          hr |= mGraph->QueryInterface(IID_IMediaEventEx, (void **)&mEvent);          hr |= mGraph->QueryInterface(IID_IBasicVideo, (void **)&mBasicVideo);          hr |= mGraph->QueryInterface(IID_IBasicAudio, (void **)&mBasicAudio);          hr |= mGraph->QueryInterface(IID_IVideoWindow, (void **)&mVideoWindow);          hr |= mGraph->QueryInterface(IID_IMediaSeeking, (void **)&mSeeking);  if (mSeeking)          {              mSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);          }  return SUCCEEDED(hr);      }  return false;  }
复制代码

Release():释放各种接口

复制代码
//释放void CDXGraph::Release(void)  {  if (mSeeking)      {          mSeeking->Release();          mSeeking = NULL;      }  if (mMediaControl)      {          mMediaControl->Release();          mMediaControl = NULL;      }  if (mEvent)      {          mEvent->Release();          mEvent = NULL;      }  if (mBasicVideo)      {          mBasicVideo->Release();          mBasicVideo = NULL;      }  if (mBasicAudio)      {          mBasicAudio->Release();          mBasicAudio = NULL;      }  if (mVideoWindow)      {          mVideoWindow->put_Visible(OAFALSE);          mVideoWindow->put_MessageDrain((OAHWND)NULL);          mVideoWindow->put_Owner(OAHWND(0));          mVideoWindow->Release();          mVideoWindow = NULL;      }      RemoveFromObjectTable();  if (mGraph)       {          mGraph->Release();           mGraph = NULL;      }  }
复制代码

Run():播放

复制代码
bool CDXGraph::Run(void)  {  if (mGraph && mMediaControl)      {  if (!IsRunning())          {  if (SUCCEEDED(mMediaControl->Run()))              {  return true;              }          }  else        {  return true;          }      }  return false;  }
复制代码

Stop():停止

复制代码
bool CDXGraph::Stop(void)  {  if (mGraph && mMediaControl)      {  if (!IsStopped())          {     if (SUCCEEDED(mMediaControl->Stop()))              {  return true;              }          }  else        {  return true;          }      }  return false;  }
复制代码

Pause():暂停

复制代码
bool CDXGraph::Pause(void)  {  if (mGraph && mMediaControl)      {  if (!IsPaused())          {     if (SUCCEEDED(mMediaControl->Pause()))              {  return true;              }          }  else        {  return true;          }      }  return false;  }
复制代码

SetFullScreen():设置全屏

复制代码
bool CDXGraph::SetFullScreen(BOOL inEnabled)  {  if (mVideoWindow)      {  HRESULT hr = mVideoWindow->put_FullScreenMode(inEnabled ? OATRUE : OAFALSE);  return SUCCEEDED(hr);      }  return false;  }
复制代码

GetDuration():获得视频时长

复制代码
bool CDXGraph::GetDuration(double * outDuration)  {  if (mSeeking)      {  __int64 length = 0;  if (SUCCEEDED(mSeeking->GetDuration(&length)))          {              *outDuration = ((double)length) / 10000000.;  return true;          }      }  return false;  }
复制代码

SetAudioVolume():设置音量

复制代码
bool CDXGraph::SetAudioVolume(long inVolume)  {  if (mBasicAudio)      {  HRESULT hr = mBasicAudio->put_Volume(inVolume);  return SUCCEEDED(hr);      }  return false;  }
复制代码

RenderFile():关键!

复制代码
bool CDXGraph::RenderFile(const char * inFile)  {  if (mGraph)      {  WCHAR    szFilePath[MAX_PATH];          MultiByteToWideChar(CP_ACP, 0, inFile, -1, szFilePath, MAX_PATH);  if (SUCCEEDED(mGraph->RenderFile(szFilePath, NULL)))          {  return true;          }      }  return false;  }
复制代码

一个简单的基于 DirectShow 的播放器 2(对话框类)

上篇文章分析了一个封装DirectShow各种接口的封装类(CDXGraph):一个简单的基于 DirectShow 的播放器  1(封装类)

本文继续上篇文章,分析一下调用这个封装类(CDXGraph)的对话框类(CSimplePlayerDlg),看看在MFC中如何使用这个类(CDXGraph)。

首先来看看CSimplePlayerDlg这个类的定义,瞧瞧SimplePlayerDlg.h这个头文件。

复制代码
/* 雷霄骅 * 中国传媒大学/数字电视技术 * leixiaohua1020@126.com * */// SimplePlayerDlg.h : header file//#if !defined(AFX_SIMPLEPLAYERDLG_H__3599FE35_3322_4CC7_B30B_6D6050C2EDFF__INCLUDED_)#define AFX_SIMPLEPLAYERDLG_H__3599FE35_3322_4CC7_B30B_6D6050C2EDFF__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000/////////////////////////////////////////////////////////////////////////////// CSimplePlayerDlg dialog#include <streams.h>#include "CDXGraph.h"#define SLIDER_TIMER   100class CSimplePlayerDlg : public CDialog  {  // Constructionpublic:      CSimplePlayerDlg(CWnd* pParent = NULL); // standard constructor    ~CSimplePlayerDlg();  // Dialog Data//{{AFX_DATA(CSimplePlayerDlg)enum { IDD = IDD_SIMPLEPLAYER_DIALOG };      CSliderCtrl mSliderGraph;      CStatic mVideoWindow;  //}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CSimplePlayerDlg)public:  virtual BOOL PreTranslateMessage(MSG* pMsg);  virtual BOOL DestroyWindow();  protected:  virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected:  HICON m_hIcon;      CDXGraph *   mFilterGraph;     // Filter Graph封装    CString      mSourceFile;      // 源文件UINT         mSliderTimer;     // 定时器ID//创建Graphvoid CreateGraph(void);        // 创建Filter Graphvoid DestroyGraph(void);       // 析构Filter Graphvoid RestoreFromFullScreen(void);  // Just for testing...HRESULT FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter);  void ShowVRPropertyPage(void);  // Generated message map functions//{{AFX_MSG(CSimplePlayerDlg)virtual BOOL OnInitDialog();      afx_msg void OnPaint();      afx_msg HCURSOR OnQueryDragIcon();  //打开    afx_msg void OnButtonOpen();  //播放    afx_msg void OnButtonPlay();  //暂停    afx_msg void OnButtonPause();  //停止    afx_msg void OnButtonStop();      afx_msg void OnButtonGrab();      afx_msg void OnButtonFullscreen();      afx_msg BOOL OnEraseBkgnd(CDC* pDC);      afx_msg void OnTimer(UINT nIDEvent);      afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);      afx_msg void OnButtonTest();  //}}AFX_MSG    afx_msg LRESULT OnGraphNotify(WPARAM inWParam, LPARAM inLParam);      DECLARE_MESSAGE_MAP()  };  //{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_SIMPLEPLAYERDLG_H__3599FE35_3322_4CC7_B30B_6D6050C2EDFF__INCLUDED_)
复制代码

从头文件来看,和普通的MFC对话框类并没有什么不同,无非是一些消息响应函数,或者MFC控件对应的类。需要注意一下,有一个变量:

CDXGraph *   mFilterGraph

接下来看看CSimplePlayerDlg函数的实现部分吧。 
OnButtonOpen():打开媒体文件按钮的响应函数

复制代码
//打开void CSimplePlayerDlg::OnButtonOpen()   {  // TODO: Add your control notification handler code here    CString    strFilter = "AVI File (*.avi)|*.avi|";      strFilter += "MPEG File (*.mpg;*.mpeg)|*.mpg;*.mpeg|";      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();  // Rebuild the file playback filter graph//创建Graph        CreateGraph();      }  }
复制代码

其中CreateGraph()函数如下所示:

复制代码
//创建Graphvoid CSimplePlayerDlg::CreateGraph(void)  {  //(如果有)销毁Graph    DestroyGraph();  //新建一个核心类    mFilterGraph = new CDXGraph();  if (mFilterGraph->Create())      {  // Render the source clip        mFilterGraph->RenderFile(mSourceFile);  // Set video window and notification window        mFilterGraph->SetDisplayWindow(mVideoWindow.GetSafeHwnd());          mFilterGraph->SetNotifyWindow(this->GetSafeHwnd());  // Show the first frame        mFilterGraph->Pause();      }  }
复制代码

与CreateGraph()相反的还有一个DestroyGraph()

复制代码
//(如果有)销毁Graphvoid CSimplePlayerDlg::DestroyGraph(void)  {  if (mFilterGraph)      {  // Stop the filter graph first        mFilterGraph->Stop();          mFilterGraph->SetNotifyWindow(NULL);  delete mFilterGraph;          mFilterGraph = NULL;      }  }
复制代码

OnButtonPlay():播放按钮的响应函数

复制代码
//播放void CSimplePlayerDlg::OnButtonPlay()   {  if (mFilterGraph)      {          mFilterGraph->Run();  // Start a timerif (mSliderTimer == 0)          {              mSliderTimer = SetTimer(SLIDER_TIMER, 100, NULL);          }      }  }
复制代码

OnButtonPause():暂停按钮的响应函数

复制代码
void CSimplePlayerDlg::OnButtonPause()   {  if (mFilterGraph)      {          mFilterGraph->Pause();  // Start a timerif (mSliderTimer == 0)          {              mSliderTimer = SetTimer(SLIDER_TIMER, 100, NULL);          }      }  }
复制代码

OnButtonStop():停止按钮的响应函数

复制代码
void CSimplePlayerDlg::OnButtonStop()   {  if (mFilterGraph)      {          mFilterGraph->SetCurrentPosition(0);          mFilterGraph->Stop();  // Stop the timerif (mSliderTimer)          {              KillTimer(mSliderTimer);              mSliderTimer = 0;          }      }  }
复制代码

其他的函数不再一一列举,但意思都是一样的。

0 0
原创粉丝点击