DirectShow编程资料(写代码必看)

转载 2011年07月16日 19:56:36
 
Filter Graph Manager接口
IGraphBuilder: 负责 Filter Graph的创建
应用程序通过此接口建立过滤器流水线。主要方法为:RenderFile,自动识别多媒体文件的类型、格式,建立适用于该格式的过滤器流水线。
IMediaControl: 操作Filter Graph 中的多媒体数据流
控制过滤器流水线的运行。主要方法为:Run开始运行;Pause,暂停运行;Stop,停止运行。
IMediaEvent(Ex): 处理 Filter Graph (Event)的事件
应用程序通过此接口获得播放过程中发生的事件,如 EC_COMPLETE(播放完毕)等。主要方法为:SetNotifyWindow,指定处理事件通知的窗口;GetEvent,获得事件。
IVideoWindow: 用于设置多媒体播放窗口的属性
控制视频窗口的属性。主要方法为:put_Owner,指定视频窗口的父窗口;put_FullScreenMode,指定全屏播放模式;SetWindowPosition,指定视频窗口的位置;put_MessagerDrain,指定一个窗口,用于接收视频窗口发出的鼠标等消息。
IMediaSeeking:提供了一些简单的搜索功能
提供了对多媒体数据流的播放位置等属性的精确控制。主要方法为:SetPositons,设置播放的起始和终止位置;GetCurrentPosition,获得当前播放位置。
IFilterMapper2:对注册表中的滤波器进行枚举
IBasicAudio:
控制音频数据流的基本属性:音量和均衡。主要方法:put_Volume、get_Volume,设置或获得音量;put_Balance、get_Balance,设置或获得均衡。

在实现多媒体文件的播放时需要用到上述的接口,这些接口的每个方法只执行一个简单的操作。因此,有必要对这些接口进行封装,见(VC下利用DirectShow播放多媒体文件.PDF)

创建 Filter Graph Manager接口
以下是创建 Filter Graph Manager接口的例子:
//首先申明并且初始化必需的接口。由于接口的索引值是自动加1 ,所以不要调用
// Iunknow::Addref
IGraphBuilder pGraph = NULL;
IMediaControl pMediaControl = NULL;
IMediaEvent pEvent = NULL;
IVideoWindow pVW = NULL;
IMediaSeeking pMS = NULL;
IFilterMapper2 pMapper = NULL;
// 实例化一个 Filter Graph Manager ,并且查询各接口
CoCreateInstance(CLSID_FilterGraph, NULL , CLSCTX_ INPROC_SERVER,
IID_ IGraphBuilder , (void **) &pGraph) ;
pGraph -> QueryInterface ( IID_IMediaControl , ( void **)&pMediaControl2 ) ;
pGraph ->QueryInterface(IID_IMediaEvent , (void** ) &pEvent) ;
pGraph ->QueryInterface(IID_IVideoWindow, (void**) &pVW) ;
pGraph2>QueryInterface IID_IMediaSeeking, void(**)&pMS ;
CoCreateInstance(CLSID_FilterMapper2 , NULL , CLSCTX _INPROC,
IID_IFilterMapper2 ,(void **) &pMapper) ;

 

播放MP3音乐
MIDI音乐的问题是对声卡的依赖性过大,好声卡和差声卡的播放效果实在相差太远。WAV音乐虽然绝对足够精确,但占用的空间之大不可小视。MP3恐怕是一个较好的解决方案。值得注意的是,播放MP3并不需要DirectX   Audio,需要的是DirectShow。所以,我们要#include   <dshow.h> ,并在工程中加入strmiids.lib。

7.7.1   调入MP3文件
下面把初始化DirectShow和调入MP3合起来说说吧。首先,我们要定义三个对象,其中IGraphBuilder*类型的可以认为是媒体播放设备,IMediaControl*类型的变量负责媒体的播放控制,而IMediaPosition*类型的变量负责媒体的播放位置设定。

#define SAFE_RELEASE(o) if(o){o->Release();o=NULL;}

IGraphBuilder*   pGBuilder;
IMediaControl*   pMControl;
IMediaPosition*   pMPos;
CoInitialize(NULL);   //初始化COM
//创建各个对象
CoCreateInstance(CLSID_FilterGraph,   NULL,
CLSCTX_INPROC,   IID_IGraphBuilder,   (void**)&pGBuilder);
pGBuilder-> QueryInterface(IID_IMediaControl,   (void**)&pMControl);
pGBuilder-> QueryInterface(IID_IMediaPosition,   (void**)&pMPos);

CHAR   strSoundPath[MAX_PATH];   //存储音乐所在路径
WCHAR   wstrSoundPath[MAX_PATH];   //存储UNICODE形式的路径
GetCurrentDirectory(MAX_PATH,   strSoundPath);
strcat(strSoundPath,   "\\Sounds\\ ");
strcat(strSoundPath,   "a.mp3 ");   //假设要播放的是Sounds子目录下的a.mp3
MultiByteToWideChar(CP_ACP,   0,   strSoundPath,   -1,wstrSoundPath,   MAX_PATH);
pGBuilder-> RenderFile(wstrSoundPath,   NULL);   //调入文件

7.7.2   播放MP3文件
播放MP3的方法十分简单:
pMPos-> put_CurrentPosition(0);   //移动到文件头
pMControl-> Run();   //播放

7.7.3   停止播放和释放对象
最后,我们要停止播放音乐并释放各个对象:
pMControl-> Stop();   //停止播放

Stop方法使filter graph停止,这个方法非常重要,因为在媒体文件播放结束后filter graph不会自己停止。
//释放对象
SAFE_RELEASE(pMControl);
SAFE_RELEASE(pMPos);
SAFE_RELEASE(pGBuilder);
CoUninitialize();   //释放COM

 

问题:

Q:如何能知道一个mp3文件播完没有?

A:DSHOW中是使用事件通知机制和应用程序进行通讯,在播放完成后Graph Menager会发送EC_COMPLETE事件通知。 

关于事件接收:查看下一篇文章《DirectShow事件通知概述》

具体代码:

先得到IMediaEvent接口实例:

IGraphBuilder*   m_pGBuilder; 
IMediaEvent* m_pMEvent;

CoCreateInstance(CLSID_FilterGraph,NULL, CLSCTX_INPROC,IID_IGraphBuilder,(void**)&m_pGBuilder);  
m_pGBuilder->QueryInterface(IID_IMediaEvent, (void**)&m_pMEvent);

两种方法:

一:使用IMediaEvent接口的GetEvent方法:

   可以放到一个线程里去轮询。

   if(SUCCEEDED(CPS->m_pMEvent->GetEvent(&event_code, &param1, &param2, 1)))
   {
      if(event_code == EC_COMPLETE)
      {//播放结束
          // frees resources associated with the parameters of an events.
          CPS->m_pMEvent->FreeEventParams(event_code, param1, param2);

          break;
      }else
      {
            CPS->m_pMEvent->FreeEventParams(event_code, param1, param2);
      }
  } 

二:在run之后等待

    long evCode = 0;
    pEvent->WaitForCompletion(INFINITE, &evCode);

    这个方法在播放期间被阻塞,直至播放结束或超时。 
 

 

 
Q:如何进行播放循环?

A:在事件处理函数中处理EC_COMPLETE事件代码,就是把GRAPH定位到时间线的开头(不需要再次调用run方法,因为媒体文件播放完毕后并没有stop

 

Q:播放a.mp3完毕后进行stop,然后重新Render进去一个新的B.wma文件,结果出现重叠播放B.wma和a.mp3文件的状况,我已经stop了啊,stop不是释放资源了吗??

A换文件必须重新构建Filter Graph,所以需要把原来的FG释放再生成一个新的FG,再Render

 


Q:如何调节播放器的声音?

A:使用IBasicAudio接口

本来这个问题没有任何悬念,但是,事实上并不是简单调用一下IBasicAudio.put_Volume就成了。我的实现代码如下,已在调试中通过,多谢VC+DirectShow+AVS的“上海--阿易”兄的帮助。
        int volumes[] = {-10000,-6418,-6147,-6000,
        -5892,-4826,-4647,-4540
        -4477, -4162,-3876, -3614, -3500,
        -3492,-3374,-3261,-3100,-3153,-3048,-2947,-2849,-2755,-2700,
        -2663,-2575,-2520,-2489,-2406,-2325,-2280,-2246,-2170,-2095,-2050,
        -2023,-1952,-1900, -1884,-1834, -1820, -1800,-1780, -1757,-1695,-1636,-1579,
        -1521,-1500,-1464,-1436,-1420, -1408,-1353,-1299,-1246,-1195,-1144,
        -1096,-1060, -1049,-1020,-1003,-957,-912,-868, -800, -774,-784, -760, -744,
        -705,-667,-630,-610,-594,-570 ,-558,-525,-493,-462,-432,-403,
        -375,-348,-322,-297,-285, -273,-250,-228,-207,-187,-176, -168,
        -150,-102,-75,-19,-10,0,0};
   /// <summary>
        /// 获得、设置音量
        /// </summary>
          get
            {
                if (basicAudio == null) return 0;
                int hr = 0, volume = 0;
                hr = basicAudio.get_Volume(out volume);
                DsError.ThrowExceptionForHR(hr);
                foreach (int v in volumes)
                    if (v >= volume) { volume = v; break; }
                return volume;
            }
            set
           

新人学编程必看——HTML学习资料

原文:新人学编程必看——HTML学习资料 今天,NanShan 小编总结了下HTML的学习方法,新手如果按照这样的套路学习应该会比较方便简单 所有HTML语句都是结构,表示描述开始,表示描述结束。...

用16进制编辑器写Dll文件---学习PE必看的资料之一

原作者   :newjueqi /*该文章的原来出处找不到了,Witch再次表示歉意。*/                   PE文件格式     ***************...

directshow的中文资料之设备列举和捕捉接口

这篇解释和示例如何通过DirectShow的接口去初始化和访问系统的硬件设备。代表性的,DirectShow应用程序使用下面类型的硬件。   音/视频捕捉卡   音频或视频回放卡   音频或视频...

CCIR656,YUV,Decoder,Encoder,Directshow问题资料收集

656输出的是串行数据,行场同步信号嵌入在数据流中; 601是并行数据,行场同步有单独输出; 656只是数据传输接口而已,可以说是作为601的一个传输方式。 简单的说ITU-R BT.601是"...

DirectShow的中文资料之设备列举和捕捉接口

DirectShow的中文资料之设备列举和捕捉接口 http://dev.gameres.com/Program/Visual/Other/DirectShow_1.htm ...
  • yulinxx
  • yulinxx
  • 2015年11月11日 11:12
  • 470

IT运维人员必看!超全信息化建设之运维资料

随着IT建设的不断深入和完善,计算机硬软件系统的运行维护已经成为了各行各业各单位领导和信息服务部门普遍关注和不堪重负的问题,据统计,IT运维服务占到IT部门工作量的80%左右。IT运维普遍存在以下现象...

【热门收藏】iOS开发人员必看的精品资料(100个) ...

【热门收藏】iOS开发人员必看的精品资料(100个)——下载目录 iPhone、iPad产品风靡全球,巨大的用户群刺激着iOS软件开发需求,然而国内人才缺口很大,正处于供不应求的...

win phone开发必看资料,下载地址收藏啦!收藏后可有选择性的下载,希望大家喜欢!(转载)

win phone开发必看资料,下载地址收藏啦!收藏后可有选择性的下载,希望大家喜欢! 完整附件下载:http://down.51cto.com/data/414417 附件预览:...

【热门收藏】iOS开发人员必看的精品资料(100个)——下载目录

【热门收藏】iOS开发人员必看的精品资料(100个)——下载目录 iPhone、 iPad产品风靡全球,巨大的用户群刺激着iOS软件开发需求,然而国内人才缺口很大,正处于供不...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DirectShow编程资料(写代码必看)
举报原因:
原因补充:

(最多只允许输入30个字)