创建一个基于命令行的简单的播放器
2008-05-15 15:39:01
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://zjyzjy.blog.51cto.com/329429/77136 |
1. 概述这本篇文章给出创建DirectShow程序的一个简单的示例。DirectShow中使用了大量的COM,确切讲DirectShow就是构建在COM基础上的,但关于COM的基础知识不在这里敷述。这个程序是一个简单的可以播放声音或者是视频的控制台程序。这个示例程序只有简单的几行,但是却演示了一个强大的DirectShow的程序。
一个DirectShow应用程序包括以下几个步骤:
1. 创建一个Filter Graph Manager 的实例;
2. 使用Filter Graph Manager创建一个Filter Graph
3. 运行这个 graph,这样就会使数据通过这些过滤器(filter)
2. 详细叙述首先,调用CoInitialize初始化COM库:
//初始化COM库. HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("ERROR - 不能初始化COM库"); return 1; } 为了使这个示例程序简单一些,程序中忽略了返回值,但是你可以从任何方法调用中检查HRESULT的值。
其次,调用CoCreateInstance创建Filter Graph Manager:
//创建过滤器图像管理器,查询接口 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); if (FAILED(hr)) { printf("ERROR - 不能够创建 Filter Graph Manager."); return 0; } 如上面的代码所示,这个类标识符(CLSID)是CLSID_FilterGraph。这个Filter Graph Manager由进程中的Dll提供,所以创建时的执行空间上下文是CLSCTX_INPROC_SERVER。DirectShow支持自由线程模式,所以你也可以用CoInitializeEx调用COINIT_MULTITHREADED标识符。
调用CoCreateInstance返回IGraphBuilder这个接口,这个接口包含了创建filter graph的大多数方法。另外示例中还需要其余的两个接口:
l IMediaControl接口控制数据流。这个接口里面包含了开始和结束播放画面的方法。
l IMediaEvent接口包含从Filter Graph Manager中取得的事件。在这个示例里面,这个接口用来等待视频播放完成。
这两个接口都是通过Filter Graph Manager暴露出来的。使用IGraphBuilder指针可以查询这两个接口:
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); 现在,你可以创建Filter Graph。这个可以用一个简单的命令调用。
// 创建graph,此处为要打开的影片 hr = pGraph->RenderFile((LPCWSTR)wText, NULL); IGraphBuilder::RenderFile 这个方法用来创建一个Filter Graph 用来播放一个特定的文件。第一个参数是一个文件名,这个文件名为一个Unicode字符串,第二个参数是一个保留字符,一般为NULL。
如果打开的文件不存在,或者是文件格式识别这个返回值HRESULT为FAIL。假设这个方法成功了,filter就可以播放了。调用IMediaControl::Run就可以播放视频了。
//运行graph. hr = pControl->Run(); 当这个过滤器开始运行后,数据通过filter过滤器后分解成视频和音频。系统播放视频时会创建一个独立的进程,你可以通过调用IMediaEvent::WaitForCompletion事件方法来监视播放事件当前的状态。
// 等待影片播放完成 long evCode; pEvent->WaitForCompletion(INFINITE, &evCode); 这个事件阻塞到文件完成播放时,或者是到这个线程分配到的时间片丢失掉的时候。INFINITE这个值意味着应用程序阻塞到整个影片播放完成。
当应用程序完成了整个影片的播放,释放这些接口的指针,然后关闭这些COM组件库。
pControl->Release(); pEvent->Release(); pGraph->Release(); //卸载COM组件 CoUninitialize(); 3. 源程序3.1. 说明程序中用到了DirectShow示例文件中的基本类库,在编译之前先编译DX安装目录\Samples\C++\DirectShow \BaseClasses 下面的工程,进行以下设置菜单Project->Setting
添加strmbase.lib
![]() 3.2. 源码1. /********************************************************************
2. created: 2008/05/15
3. created: 15:5:2008 13:39
4. file base: FirstDX
5. file ext: cpp
6. author: ZJY
7.
8. purpose: 这个小程序主要是为了演示DirectShow的最基本的一个步骤
9. *********************************************************************/
10. #include "stdafx.h"
11. #include <dshow.h>
12. #include <iostream>
13.
14. int main(int argc,char *argv[])
15. {
16. char strAviName[256];
17. if (argc == 1)
18. {
19. std::cout << "没有输出影片,请添加要播放的影片..." <<std::endl;
20. return 1;
21. }
22. else if (argc == 2)
23. {
24. strcpy(strAviName,argv[1]);
25. }
26. else
27. {
28. std::cout <<"参数传递错误..." <<std::endl;
29. return 1;
30. }
31.
32. IGraphBuilder *pGraph = NULL;
33. IMediaControl *pControl = NULL;
34. IMediaEvent *pEvent = NULL;
35.
36. //初始化COM库.
37. HRESULT hr = CoInitialize(NULL);
38. if (FAILED(hr))
39. {
40. printf("ERROR - 不能初始化COM库");
41. return 1;
42. }
43.
44. //创建过滤器图像管理器,查询接口
45. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
46. IID_IGraphBuilder, (void **)&pGraph);
47. if (FAILED(hr))
48. {
49. printf("ERROR - 不能够创建 Filter Graph Manager.");
50. return 0;
51. }
52.
53. hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
54. hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
55.
56. //由于DirectShow主要是Unicode格式,我们使用Windows自带函数
57. //转换文件名char数组为Unicode格式
58. int len = strlen(strAviName)+1;
59. wchar_t *wText = new wchar_t[len];
60. if ( wText == NULL)
61. {
62. std::cout <<"ERROR - 文件打开错误..."<<std::endl;
63. return 1;
64. }
65. memset(wText,0,len);
66. ::MultiByteToWideChar( CP_ACP, NULL,strAviName, -1, wText,len );
67.
68. // 创建graph,此处为要打开的影片
69. hr = pGraph->RenderFile((LPCWSTR)wText, NULL);
70.
71. if (SUCCEEDED(hr))
72. {
73. //运行graph.
74. hr = |


