c#中用DirectShow实现媒体播放器的核心

用.net做多媒体开发的似乎不多,所以网上资源也少,看的人更少。不过我的博客上居然还有几位在等新文章的人,有点出乎我的意料了。目前我已不再从事多媒体相关的工作,加入新公司至今都忙到吐血,再加上害怕水平不够误人子弟,所以一直都没有更新这个系列。但是之前有承诺过得着空就一定要更新,现在总算稍微空了那么一点点,继续烂着这个坑的理由就没有了。

DirectShow是微软平台上处理多媒体相关事务的一个平台,本身是基于COM技术上的框架,所以可以和.net配合的非常好。在这套框架里,多媒体相关事务被分成一个一个的子任务,每个任务都放在一些名为Filter的COM组件里。如果你只是做一些简单的工作,那么微软自带的那些filter估计已经够用了;但是如果你还有更高级的任务要完成,那么写filter估计就不可避免了。在陷入到细节的泥潭之前,我们先给DirectShow拍个快照以便有一个整体的印象。

一开始
火星人用竹竿捅下地球人的探测器后,在里面发现了一张光盘,火星人的计算机水平都巨高无比,他们在硬盘上用小刀刻一个操作系统只需要三分钟(相信我,还是破解版的),他们很想看看光盘里的内容,因为火星人是如此的土,以至于饭岛爱去世的新闻都不知道,还都在等她的无码片。

现在他们有操作系统了,他们也有光驱,他们什么都有,可是他们没有播放器。火星人上有个广电不急,时刻准备把那一小撮不明真相的不看电视的群众消灭干净。火星人只看电视。

可是在饭岛爱面前,广电不急一败涂地,火星人打算用他们的智慧开发出一款播放器,来观看精彩的饭岛爱无码片,他们不怕死。很快他们就画出了草图:


后来

火星人发现把所有的功能都放到一个盒子里不好。虽然没有老板检测他们的代码,逼他们加班重写,扣他们工资,但他们都是计算机水平巨高无比的生物,他们甚至知道27种设计模式,他们忍受不了如此丑陋的代码。火星人中最顶尖的精英们在火星人领袖的“带三个表”理论中悟出真理,他们认为,把盒子分成三部分一定是完美无缺的,于是他们又画出了这样的草图:

富有远见的火星人料想到播放的源一定会变,必须在源上抽象出一个名叫Capture Filter的东西来。他们还专门给声卡显卡等硬件抽象出一个Render Filter,因为火星上的雕刻家三分钟就能雕刻出一款新的声卡或者显卡,他们还向全火星人民保证,坚决不跟低版本的硬件相兼容。剩下所有的逻辑都塞在名为Transfer Filter的小黑盒子里。

再后来
火星人在眼睛更重要还是耳朵更重要的原则问题上一直有分歧,后来这种分歧越来越大,以至于到了不可调和的程度。他们终于分裂成了眼睛派和耳朵派。十分不幸的是,最初开发播放器的那两个核心火星人分属于不同的派别,他们互相看不起对方,认为自己的Transfer Filter居然有异教徒参与,根本就是对自己的侮辱,所以在一个月黑风高的夜晚,他们把Transfer Filter也分裂了:


在名为Demux的小屋里,多媒体流被分成了视频流和音频流两路,从此分道扬镳老死不相往来,但是每天新闻不联播之后整点报时那会儿,他们俩却会不约而同的掏出手表校对时间,仿佛冥冥中有人安排了他们的命运一样(Demux在后面哈哈狞笑)。

最后
源于想看饭岛爱的这款播放器越来越流行,以至于所有的火星人都拥有一款。火星上的五毛党为了让更多的火星人能用播放器倾听老大哥的教诲,开发出了接收地面电视信号的Capture filter。火星人不久之后还发明了网络,见网游吐过三次血的一猥琐男在第一时间开发了接收网络信号的Capture Filter。如此等等。随着时间的流失,最初只有一条的多媒体流分支越来越多,挂在线上的Filter也越来越多。地球探测器登录火星一百周年庆上,火星人给播放器最后拍了一张照片,看起来像这个样子:


他们管这套框架叫DirectShow

1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Diagnostics;
5using DirectShowLib;
6
7namespace SoundPlayer
8{
9 public class SoundPlayer
10 {
11 IFilterGraph2 graphBuilder;
12 IMediaSeeking mediaSeeking;
13 IMediaControl mediaControl;
14 IBasicAudio audioControl;
15 IVideoWindow window;
16 Stack<int> errorStack = new Stack<int>();
17 bool isValidate = false;
18 public bool Validate
19 {
20 get { return isValidate; }
21 }
22
23 string fileName = string.Empty;
24 public SoundPlayer( string file)
25 {
26 graphBuilder = (new FilterGraph()) as IFilterGraph2;
27 if (graphBuilder == null) return;
28 mediaControl = graphBuilder as IMediaControl;
29 mediaSeeking = graphBuilder as IMediaSeeking;
30 audioControl = graphBuilder as IBasicAudio;
31 if (mediaControl == null || mediaSeeking == null || audioControl == null) return;
32 int hr = mediaControl.RenderFile(file);
33 fileName = file;
34 if (hr != 0) errorStack.Push(hr);
35 if (hr != 0) return;
36 mediaSeeking.SetTimeFormat(TimeFormat.MediaTime);
37 window = graphBuilder as IVideoWindow;
38
39 isValidate = true;
40 }
41 public bool Play()
42 {
43 Debug.Assert(isValidate);
44 int hr = mediaControl.Run();
45 if (hr != 0) errorStack.Push(hr);
46 return (hr == 0);
47 }
48 public bool Stop()
49 {
50 Debug.Assert(isValidate);
51 int hr = mediaControl.Stop();
52 this.CurrentPosition = 0;
53 if (hr != 0) errorStack.Push(hr);
54 window.put_Visible(OABool.False);
55 return (hr == 0);
56 }
57 public bool Pause()
58 {
59 Debug.Assert(isValidate);
60 int hr = mediaControl.Pause();
61 if (hr != 0) errorStack.Push(hr);
62 return (hr == 0);
63 }
64
65 public long CurrentPosition
66 {
67 get
68 {
69 Debug.Assert(isValidate);
70 long cur = -1;
71 int hr = mediaSeeking.GetCurrentPosition(out cur);
72 if (hr != 0) errorStack.Push(hr);
73 return cur / (10000);
74 }
75 set
76 {
77 Debug.Assert(isValidate);
78 long stopPosition = -1;
79 int hr = mediaSeeking.GetStopPosition(out stopPosition);
80 if (hr != 0) errorStack.Push(hr);
81 hr = mediaSeeking.SetPositions(value * 10000, AMSeekingSeekingFlags.AbsolutePositioning,
82 stopPosition, AMSeekingSeekingFlags.AbsolutePositioning);
83 if (hr != 0) errorStack.Push(hr);
84 }
85 }
86
87 public void SetOwner(IntPtr ptr)
88 {
89 if (window != null)
90 {
91 window.put_Owner(ptr);
92
93 }
94 }
95
96 public string CurrentFile
97 {
98 get
99 {
100 return fileName;
101 }
102 }
103
104 public long Duration
105 {
106 get
107 {
108 Debug.Assert(isValidate);
109 long dur = -1;
110 int hr = mediaSeeking.GetDuration(out dur);
111 if (hr != 0) errorStack.Push(hr);
112 return dur / 10000;
113 }
114 }
115
116 public double Rate
117 {
118 get
119 {
120 Debug.Assert(isValidate);
121 double rate = 0.0;
122 int hr = mediaSeeking.GetRate(out rate);
123 if (hr != 0) errorStack.Push(hr);
124 return rate;
125 }
126 set
127 {
128 Debug.Assert(isValidate);
129 int hr = mediaSeeking.SetRate(value);
130 if (hr != 0) errorStack.Push(hr);
131 }
132 }
133
134 public int Volume
135 {
136 get
137 {
138 Debug.Assert(isValidate);
139 int volume = 0;
140 int hr = audioControl.get_Volume(out volume);
141 if (hr != 0) errorStack.Push(hr);
142 return volume;
143 }
144 set
145 {
146 Debug.Assert(isValidate);
147 int hr = audioControl.put_Volume(value);
148 if (hr != 0) errorStack.Push(hr);
149 }
150 }
151
152 public int GetLastErrorCode()
153 {
154 if (errorStack.Count != 0) return errorStack.Pop();
155 else return 0;
156 }
157
158 }
159}



本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2009/09/07/1562138.html,如需转载请自行联系原作者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值