基于DirectShow的WinCE多媒体编程

基于DirectShowWinCE多媒体编程 by斜风细雨QQ:253786989    2012-02-17

(1) 简介

  DirectShow是由微软开发的处理多媒体文件的应用程序接口(API),基于COM(组件对象模型)框架。

  下图截自MSDN,展示了应用程序与DirectShow以及一些软硬件组件之间的关系。

  如图所示,DirectShow主要由FiltersFilter Graph Manager组成。其中Filters有好多种,Source Filters叫做源过滤器,主要作用是从多媒体文件(来自本地或者Internet等)引入源数据流。Transform Filters叫做传输过滤器,作用是对源数据流进行处理,如编解码(包括软解码和硬解码)、转换格式、解压缩等等。Rendering Filters是渲染过滤器,它会在最后将处理完的数据流传送给相关硬件播放,如通过DirectDraw控制显卡显示图形,通过DirectSound控制声卡发出声音等等。除此之外,DirectShow还包含其它很多过滤器,以后再详细了解。

  图中Source Filters、Transform Filters、Rendering Filters组合在一起,称为过滤器图。DirectShow就是由这些完成各自分工的Filters前后串联在一起来完成工作。Filter Graph Manager称为“过滤器图管理对象”,主要作用是协调不同的Filters,建立参考时钟供Filters使用,采用队列机制将DirectShow事件传递给应用程序等等。

  图中每个过滤器,都包含有称为Pin(引脚)的私有对象,它们派生自IPinPin分为两类:输入Pin和输出Pin。如多媒体数据流从输入Pin进入Source Filters,然后从Source Filters的输出PinTransform Filters的输入Pin连接。多媒体数据流经过Source Filters的处理之后,通过Pin连接进入Transform Filters

(2) DirectShow接口

  WM/WinCE平台下的DirectShow有几十个接口,下面是常用接口及接口中的常用方法。

a) IGraphBuilder:此接口用来创建filter graph

  其中常用方法RenderFile,用来渲染指定类型的文件。

b) IMediaControl:控制Filter Graph中的多媒体数据流。

  其中常用方法如Run开始播放,Pause暂停播放,Stop停止播放。

c) IMediaEvent,IMediaEventEx:处理Filter Graph产生的事件。应用程序通过此接口获得播放过程中发生的事件,如EC_COMPLETE(播放完毕)等等。主要方法如SetNotifyWindow指定处理事件的窗口,GetEvent获取事件,FreeEventParams释放与事件参数相关联的资源。

d) IVideoWindow:用于设置多媒体播放窗口的属性。主要方法如put_Owner指定视频播放窗口的父窗口,put_FullScreenMode指定全屏播放模式,SetWindowPosition指定视频窗口的位置,put_Visible显示或隐藏视频窗口,get_Visible获取当前视频窗口是否可视,put_WindowStyle设置视频窗口风格属性,put_MessageDrain指定一个窗口,从视频窗口接收鼠标和键盘消息。

e) IMediaSeeking:对多媒体数据流的播放位置等属性进行控制。主要方法如SetPositions设置当前播放位置和终止播放位置,GetCurrentPositions获得当前播放位置,SetRate设置播放速率,GetRate获取播放速率等,GetDuration以纳秒为单位获取多媒体文件的总时间长度。

f) IBasicAudio:控制音频的音量和平衡。主要方法如put_Volume设置音量大小,get_Volume获取音量大小,put_Balance设置声道平衡,get_Balance获取声道平衡等。

g) IBasicVideo:控制视频属性。主要方法如get_BitRate获取视频流的比特率,GetVideoSize获取视频尺寸。

(3) WinCE组件

  同样的程序,同样的代码。在有些平台上可以正常使用,播放音视频文件,采集摄像头图像等等。但有的平台就不可以。原因就是WinCE系统在定制的时候,每个厂家所添加的Media相关组件不同,所以不同厂家的WinCE平台所具备的多媒体能力也不同。

  下面是WinCE7下的Media相关组件:

a) 音频编解码器和渲染器

  比如想播放MP3格式的音乐,就必须勾选上MP3 Codec

b) 视频编解码器和渲染器

c) DirectShow

  这里面包括DirectShow的核心组件和filtersDirectShowfilters完成核心功能。如果相关DirectShow组件没有添加的话,那使用该系统所导出的SDK,很可能我们的DirectShow应用程序编译都通不过。即使编译通过,也肯定不能正常工作。

  除此之外,还有Media Formats、Media Library、Media Renderer、Windows Media Player等相关组件。有关这些内容可以看Wince7的帮助文档。下面是使用DirectShow需要添加的相关组件的简单介绍:

(4) 枚举系统中注册的filters

  利用DirectShowIEnumRegFilters接口枚举系统中注册的filters,下面是实现代码:

  1. HRESULT hr = 0;  
  2. IFilterMapper *pMapper = NULL;  
  3. IEnumRegFilters *pEnum = NULL;  
  4. REGFILTER *pRegFilter = NULL;  
  5. ULONG cFetched = 0;  
  6.   
  7. // 初始化COM环境  
  8. CoInitialize(NULL);  
  9.   
  10. // 获取IFilterMapper接口  
  11. hr = CoCreateInstance(CLSID_FilterMapper, NULL, CLSCTX_INPROC, IID_IFilterMapper, (void **)&pMapper);  
  12. if (FAILED(hr))  
  13. {  
  14.     MessageBox(TEXT("得到IFilterMapper接口失败!"));  
  15.     return;  
  16. }  
  17.   
  18. // 获取IEnumRegFilters接口  
  19. hr = pMapper->EnumMatchingFilters(&pEnum, 0, FALSE, GUID_NULL, GUID_NULL, FALSE, FALSE, GUID_NULL, GUID_NULL);  
  20. if (FAILED(hr))  
  21. {  
  22.     MessageBox(TEXT("得到IEnumRegFilters接口失败!"));  
  23.     return;  
  24. }  
  25.   
  26. // 枚举系统中注册的filters  
  27. CString strFilters, strTemp;  
  28. while (pEnum->Next(1, &pRegFilter, &cFetched) == S_OK)  
  29. {  
  30.     for (int i = 0; i < cFetched; ++i)  
  31.     {  
  32.         strTemp.Format(TEXT("%s\r\n"), (pRegFilter+i)->Name);  
  33.     }  
  34.   
  35.     strFilters += strTemp;  
  36.   
  37.     // 释放内存  
  38.     CoTaskMemFree(pRegFilter);  
  39. }  
  40.   
  41. SetDlgItemText(IDC_FILTERS, strFilters);  
  42.   
  43. // 释放接口  
  44. pEnum->Release();  
  45. pMapper->Release();  
  46.   
  47. // 释放COM环境  
  48. CoUninitialize();  

  某次运行结果如图:

(5) 初始化DirectShow接口

  下面的代码演示如何获取(2)中所提到的DirectShow常用接口,如果获取这些接口成功,接下来的工作就是利用这些接口提供的方法来播放、控制视频文件了。编写DirectShow应用程序时需要#include <dshow.h>,并且引用strmiids.lib。如果提示找不到dshow.h,那很可能是使用的sdk不支持,也就是该sdk所对应的wince平台没有添加DirectShow相关组件。

  1. // 第1步:创建IGraphBuilder接口  
  2. hResult = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);  
  3. if (hResult != S_OK)  
  4. {  
  5.     return FALSE;  
  6. }  
  7.   
  8. // 第2步:利用IGraphBuilder接口渲染视频文件  
  9. hResult = m_pGB->RenderFile(strFileName,NULL);  
  10. if (hResult != S_OK )  
  11. {  
  12.     return FALSE;  
  13. }  
  14.   
  15. // 第3步:得到媒体播放控制接口IMediaControl  
  16. hResult = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);   
  17. if (hResult != S_OK)  
  18. {  
  19.     return FALSE;  
  20. }  
  21.   
  22. // 第4步:得到媒体播放位置搜索接口IMediaSeeking  
  23. hResult = m_pGB->QueryInterface(IID_IMediaSeeking,(void**)&m_pMS);  
  24. if (hResult != S_OK)  
  25. {  
  26.     return FALSE;  
  27. }  
  28.   
  29. // 设置查找定位的时间单位  
  30. GUID guid_timeFormat = TIME_FORMAT_MEDIA_TIME;  
  31. m_pMS->SetTimeFormat(&guid_timeFormat);  
  32.   
  33. // 第5步:得到媒体事件接口IMediaEventEx  
  34. hResult = m_pGB->QueryInterface(IID_IMediaEventEx,(void**)&m_pME);  
  35. if (hResult != S_OK)  
  36. {  
  37.     return FALSE;  
  38. }  
  39.   
  40. // 第6步:得到IVideoWindow接口  
  41. hResult = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);  
  42. if (hResult != S_OK)  
  43. {  
  44.     return FALSE;  
  45. }  
  46.   
  47. // 第7步:得到基础视频流接口IBasicVideo  
  48. hResult = m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV);  
  49. if (hResult != S_OK)  
  50. {  
  51.     return FALSE;  
  52. }  
  53.   
  54. // 第8步:得到基础音频流接口IBasicAudio  
  55. hResult = m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA);  
  56. if (hResult != S_OK)  
  57. {  
  58.     return FALSE;  
  59. }  

(6) 小结

  通过上面的学习,熟悉了DirectShow的相关接口和接口的常用方法之后,就可以编写多媒体应用程序了。可以先从codeproject、pudn等网站上找些别人已经封装好的DirectShow c++ wrapper,仔细看看那些比较成熟的库是如何封装的,是如何初始化并使用那些DirectShow接口的,最后再在其基础上进行修改,以适应自己的需要或者加强它们的功能。这样上手的速度能更快些。

基于DirectShowWinCE多媒体编程 by斜风细雨QQ:253786989    2012-02-17


发布了14 篇原创文章 · 获赞 5 · 访问量 13万+

基于DirectShowWinCE多媒体编程 by斜风细雨QQ:253786989    2012-02-17

(1) 简介

  DirectShow是由微软开发的处理多媒体文件的应用程序接口(API),基于COM(组件对象模型)框架。

  下图截自MSDN,展示了应用程序与DirectShow以及一些软硬件组件之间的关系。

  如图所示,DirectShow主要由FiltersFilter Graph Manager组成。其中Filters有好多种,Source Filters叫做源过滤器,主要作用是从多媒体文件(来自本地或者Internet等)引入源数据流。Transform Filters叫做传输过滤器,作用是对源数据流进行处理,如编解码(包括软解码和硬解码)、转换格式、解压缩等等。Rendering Filters是渲染过滤器,它会在最后将处理完的数据流传送给相关硬件播放,如通过DirectDraw控制显卡显示图形,通过DirectSound控制声卡发出声音等等。除此之外,DirectShow还包含其它很多过滤器,以后再详细了解。

  图中Source Filters、Transform Filters、Rendering Filters组合在一起,称为过滤器图。DirectShow就是由这些完成各自分工的Filters前后串联在一起来完成工作。Filter Graph Manager称为“过滤器图管理对象”,主要作用是协调不同的Filters,建立参考时钟供Filters使用,采用队列机制将DirectShow事件传递给应用程序等等。

  图中每个过滤器,都包含有称为Pin(引脚)的私有对象,它们派生自IPinPin分为两类:输入Pin和输出Pin。如多媒体数据流从输入Pin进入Source Filters,然后从Source Filters的输出PinTransform Filters的输入Pin连接。多媒体数据流经过Source Filters的处理之后,通过Pin连接进入Transform Filters

(2) DirectShow接口

  WM/WinCE平台下的DirectShow有几十个接口,下面是常用接口及接口中的常用方法。

a) IGraphBuilder:此接口用来创建filter graph

  其中常用方法RenderFile,用来渲染指定类型的文件。

b) IMediaControl:控制Filter Graph中的多媒体数据流。

  其中常用方法如Run开始播放,Pause暂停播放,Stop停止播放。

c) IMediaEvent,IMediaEventEx:处理Filter Graph产生的事件。应用程序通过此接口获得播放过程中发生的事件,如EC_COMPLETE(播放完毕)等等。主要方法如SetNotifyWindow指定处理事件的窗口,GetEvent获取事件,FreeEventParams释放与事件参数相关联的资源。

d) IVideoWindow:用于设置多媒体播放窗口的属性。主要方法如put_Owner指定视频播放窗口的父窗口,put_FullScreenMode指定全屏播放模式,SetWindowPosition指定视频窗口的位置,put_Visible显示或隐藏视频窗口,get_Visible获取当前视频窗口是否可视,put_WindowStyle设置视频窗口风格属性,put_MessageDrain指定一个窗口,从视频窗口接收鼠标和键盘消息。

e) IMediaSeeking:对多媒体数据流的播放位置等属性进行控制。主要方法如SetPositions设置当前播放位置和终止播放位置,GetCurrentPositions获得当前播放位置,SetRate设置播放速率,GetRate获取播放速率等,GetDuration以纳秒为单位获取多媒体文件的总时间长度。

f) IBasicAudio:控制音频的音量和平衡。主要方法如put_Volume设置音量大小,get_Volume获取音量大小,put_Balance设置声道平衡,get_Balance获取声道平衡等。

g) IBasicVideo:控制视频属性。主要方法如get_BitRate获取视频流的比特率,GetVideoSize获取视频尺寸。

(3) WinCE组件

  同样的程序,同样的代码。在有些平台上可以正常使用,播放音视频文件,采集摄像头图像等等。但有的平台就不可以。原因就是WinCE系统在定制的时候,每个厂家所添加的Media相关组件不同,所以不同厂家的WinCE平台所具备的多媒体能力也不同。

  下面是WinCE7下的Media相关组件:

a) 音频编解码器和渲染器

  比如想播放MP3格式的音乐,就必须勾选上MP3 Codec

b) 视频编解码器和渲染器

c) DirectShow

  这里面包括DirectShow的核心组件和filtersDirectShowfilters完成核心功能。如果相关DirectShow组件没有添加的话,那使用该系统所导出的SDK,很可能我们的DirectShow应用程序编译都通不过。即使编译通过,也肯定不能正常工作。

  除此之外,还有Media Formats、Media Library、Media Renderer、Windows Media Player等相关组件。有关这些内容可以看Wince7的帮助文档。下面是使用DirectShow需要添加的相关组件的简单介绍:

(4) 枚举系统中注册的filters

  利用DirectShowIEnumRegFilters接口枚举系统中注册的filters,下面是实现代码:

  1. HRESULT hr = 0;  
  2. IFilterMapper *pMapper = NULL;  
  3. IEnumRegFilters *pEnum = NULL;  
  4. REGFILTER *pRegFilter = NULL;  
  5. ULONG cFetched = 0;  
  6.   
  7. // 初始化COM环境  
  8. CoInitialize(NULL);  
  9.   
  10. // 获取IFilterMapper接口  
  11. hr = CoCreateInstance(CLSID_FilterMapper, NULL, CLSCTX_INPROC, IID_IFilterMapper, (void **)&pMapper);  
  12. if (FAILED(hr))  
  13. {  
  14.     MessageBox(TEXT("得到IFilterMapper接口失败!"));  
  15.     return;  
  16. }  
  17.   
  18. // 获取IEnumRegFilters接口  
  19. hr = pMapper->EnumMatchingFilters(&pEnum, 0, FALSE, GUID_NULL, GUID_NULL, FALSE, FALSE, GUID_NULL, GUID_NULL);  
  20. if (FAILED(hr))  
  21. {  
  22.     MessageBox(TEXT("得到IEnumRegFilters接口失败!"));  
  23.     return;  
  24. }  
  25.   
  26. // 枚举系统中注册的filters  
  27. CString strFilters, strTemp;  
  28. while (pEnum->Next(1, &pRegFilter, &cFetched) == S_OK)  
  29. {  
  30.     for (int i = 0; i < cFetched; ++i)  
  31.     {  
  32.         strTemp.Format(TEXT("%s\r\n"), (pRegFilter+i)->Name);  
  33.     }  
  34.   
  35.     strFilters += strTemp;  
  36.   
  37.     // 释放内存  
  38.     CoTaskMemFree(pRegFilter);  
  39. }  
  40.   
  41. SetDlgItemText(IDC_FILTERS, strFilters);  
  42.   
  43. // 释放接口  
  44. pEnum->Release();  
  45. pMapper->Release();  
  46.   
  47. // 释放COM环境  
  48. CoUninitialize();  

  某次运行结果如图:

(5) 初始化DirectShow接口

  下面的代码演示如何获取(2)中所提到的DirectShow常用接口,如果获取这些接口成功,接下来的工作就是利用这些接口提供的方法来播放、控制视频文件了。编写DirectShow应用程序时需要#include <dshow.h>,并且引用strmiids.lib。如果提示找不到dshow.h,那很可能是使用的sdk不支持,也就是该sdk所对应的wince平台没有添加DirectShow相关组件。

  1. // 第1步:创建IGraphBuilder接口  
  2. hResult = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);  
  3. if (hResult != S_OK)  
  4. {  
  5.     return FALSE;  
  6. }  
  7.   
  8. // 第2步:利用IGraphBuilder接口渲染视频文件  
  9. hResult = m_pGB->RenderFile(strFileName,NULL);  
  10. if (hResult != S_OK )  
  11. {  
  12.     return FALSE;  
  13. }  
  14.   
  15. // 第3步:得到媒体播放控制接口IMediaControl  
  16. hResult = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);   
  17. if (hResult != S_OK)  
  18. {  
  19.     return FALSE;  
  20. }  
  21.   
  22. // 第4步:得到媒体播放位置搜索接口IMediaSeeking  
  23. hResult = m_pGB->QueryInterface(IID_IMediaSeeking,(void**)&m_pMS);  
  24. if (hResult != S_OK)  
  25. {  
  26.     return FALSE;  
  27. }  
  28.   
  29. // 设置查找定位的时间单位  
  30. GUID guid_timeFormat = TIME_FORMAT_MEDIA_TIME;  
  31. m_pMS->SetTimeFormat(&guid_timeFormat);  
  32.   
  33. // 第5步:得到媒体事件接口IMediaEventEx  
  34. hResult = m_pGB->QueryInterface(IID_IMediaEventEx,(void**)&m_pME);  
  35. if (hResult != S_OK)  
  36. {  
  37.     return FALSE;  
  38. }  
  39.   
  40. // 第6步:得到IVideoWindow接口  
  41. hResult = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);  
  42. if (hResult != S_OK)  
  43. {  
  44.     return FALSE;  
  45. }  
  46.   
  47. // 第7步:得到基础视频流接口IBasicVideo  
  48. hResult = m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV);  
  49. if (hResult != S_OK)  
  50. {  
  51.     return FALSE;  
  52. }  
  53.   
  54. // 第8步:得到基础音频流接口IBasicAudio  
  55. hResult = m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA);  
  56. if (hResult != S_OK)  
  57. {  
  58.     return FALSE;  
  59. }  

(6) 小结

  通过上面的学习,熟悉了DirectShow的相关接口和接口的常用方法之后,就可以编写多媒体应用程序了。可以先从codeproject、pudn等网站上找些别人已经封装好的DirectShow c++ wrapper,仔细看看那些比较成熟的库是如何封装的,是如何初始化并使用那些DirectShow接口的,最后再在其基础上进行修改,以适应自己的需要或者加强它们的功能。这样上手的速度能更快些。

基于DirectShowWinCE多媒体编程 by斜风细雨QQ:253786989    2012-02-17

猜你喜欢

转载自blog.csdn.net/laoyouji/article/details/8130370