用c#写的directshow简易视频播放器

很久没动directshow了,现在一直用c#写程序,突然看到directshow在.net下也有library,于是想试试在.net下的directshow。这个播放器是参照directshownet library中的例子改的,自己加了一些控制方面的。
先来看看效果图:directshow

先说一下directshownet,这是一个用c#写的directshow类库,是一个开源项目,sourceforge主页:http://directshownet.sourceforge.net/ 不过这个项目关注的人不是很多,代码也很久没更新了,毕竟使用directshow的大都是c++项目,实现起来也是c++更高效。在.net里也可以调用VB的directshow类库来实现,不过我觉得这样太麻烦了,还是用directshownet这个现成的类库来的快。

首先从上面的sourceforge主页里下载directshownet library,现在最新的版本是2.1(还是2010的,汗),加入c#项目的引用中,然后using DirectShowLib,就可以使用其中的类了。

上完整代码:

 
 
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using DirectShowLib;
  10. using System.Threading;
  11. using System.Runtime.InteropServices;
  12. namespace DirectShow
  13. {
  14. public partial class Form1 : Form
  15. {
  16. private const int WMGraphNotify = 0x0400 + 13;
  17. private Thread t = null;
  18. private IGraphBuilder graphBuilder = null;
  19. private IMediaControl mediaControl = null;
  20. private IMediaEventEx mediaEventEx = null;
  21. private IVideoWindow videoWindow = null;
  22. private IBasicAudio basicAudio = null;
  23. private IBasicVideo basicVideo = null;
  24. private IMediaSeeking mediaSeeking = null;
  25. private IMediaPosition mediaPosition = null;
  26. private IVideoFrameStep frameStep = null;
  27. public Form1()
  28. {
  29. InitializeComponent();
  30. trackBar2.SetRange(-1000, 0);
  31. }
  32. private void updateTimeBar(double current)
  33. {
  34. }
  35. private void updateTimeBarThread()
  36. {
  37. double time;
  38. int volu;
  39. while (true)
  40. {
  41. mediaPosition.get_CurrentPosition(out time);
  42. Console.WriteLine(time);
  43. basicAudio.get_Volume(out volu);
  44. Console.WriteLine(volu);
  45. this.BeginInvoke(new MethodInvoker(() =>
  46. {
  47. trackBar1.Value = (int)time;
  48. }));
  49. Thread.Sleep(1000);
  50. }
  51. }
  52. private void button1_Click(object sender, EventArgs e)
  53. {
  54. int hr = 0;
  55. if (this.graphBuilder == null)
  56. {
  57. String filename = textBox1.Text;
  58. this.graphBuilder = (IGraphBuilder)new FilterGraph();
  59. // Have the graph builder construct its the appropriate graph automatically
  60. hr = this.graphBuilder.RenderFile(filename, null);
  61. DsError.ThrowExceptionForHR(hr);
  62. // QueryInterface for DirectShow interfaces
  63. this.mediaControl = (IMediaControl)this.graphBuilder;
  64. this.mediaEventEx = (IMediaEventEx)this.graphBuilder;
  65. this.mediaSeeking = (IMediaSeeking)this.graphBuilder;
  66. this.mediaPosition = (IMediaPosition)this.graphBuilder;
  67. // Query for video interfaces, which may not be relevant for audio files
  68. this.videoWindow = this.graphBuilder as IVideoWindow;
  69. this.basicVideo = this.graphBuilder as IBasicVideo;
  70. // Query for audio interfaces, which may not be relevant for video-only files
  71. this.basicAudio = this.graphBuilder as IBasicAudio;
  72. hr = this.mediaEventEx.SetNotifyWindow(this.Handle, WMGraphNotify, IntPtr.Zero);
  73. DsError.ThrowExceptionForHR(hr);
  74. // Setup the video window
  75. hr = this.videoWindow.put_Owner(this.Handle);
  76. DsError.ThrowExceptionForHR(hr);
  77. hr = this.videoWindow.put_WindowStyle(WindowStyle.Child |
  78. WindowStyle.ClipSiblings | WindowStyle.ClipChildren);
  79. DsError.ThrowExceptionForHR(hr);
  80. this.Focus();
  81. hr = InitVideoWindow(1, 1);
  82. DsError.ThrowExceptionForHR(hr);
  83. double time;
  84. mediaPosition.get_Duration(out time);
  85. trackBar1.SetRange(0, (int)time);
  86. t = new Thread(new ThreadStart(updateTimeBarThread));
  87. t.IsBackground = true;
  88. t.Start();
  89. }
  90. if (button1.Text.Equals("播放"))
  91. {
  92. // Run the graph to play the media file
  93. hr = this.mediaControl.Run();
  94. DsError.ThrowExceptionForHR(hr);
  95. button1.Text = "暂停";
  96. }
  97. else
  98. {
  99. hr = this.mediaControl.Pause();
  100. DsError.ThrowExceptionForHR(hr);
  101. button1.Text = "播放";
  102. }
  103. }
  104. private int InitVideoWindow(int nMultiplier, int nDivider)
  105. {
  106. int hr = 0;
  107. int lHeight, lWidth;
  108. if (this.basicVideo == null)
  109. return 0;
  110. // Read the default video size
  111. hr = this.basicVideo.GetVideoSize(out lWidth, out lHeight);
  112. if (hr == DsResults.E_NoInterface)
  113. return 0;
  114. // Account for requests of normal, half, or double size
  115. lWidth = lWidth * nMultiplier / nDivider;
  116. lHeight = lHeight * nMultiplier / nDivider;
  117. this.ClientSize = new Size(lWidth, lHeight + 75);
  118. Application.DoEvents();
  119. hr = this.videoWindow.SetWindowPosition(0, 30, lWidth, lHeight);
  120. return hr;
  121. }
  122. private void closeVideo()
  123. {
  124. int hr = 0;
  125. // Stop media playback
  126. if (this.mediaControl != null)
  127. hr = this.mediaControl.Stop();
  128. // Free DirectShow interfaces
  129. CloseInterfaces();
  130. button1.Text = "播放";
  131. }
  132. private void CloseInterfaces()
  133. {
  134. int hr = 0;
  135. try
  136. {
  137. lock (this)
  138. {
  139. // Relinquish ownership (IMPORTANT!) after hiding video window
  140. hr = this.videoWindow.put_Visible(OABool.False);
  141. DsError.ThrowExceptionForHR(hr);
  142. hr = this.videoWindow.put_Owner(IntPtr.Zero);
  143. DsError.ThrowExceptionForHR(hr);
  144. if (this.mediaEventEx != null)
  145. {
  146. hr = this.mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero);
  147. DsError.ThrowExceptionForHR(hr);
  148. }
  149. // Release and zero DirectShow interfaces
  150. if (this.mediaEventEx != null)
  151. this.mediaEventEx = null;
  152. if (this.mediaSeeking != null)
  153. this.mediaSeeking = null;
  154. if (this.mediaPosition != null)
  155. this.mediaPosition = null;
  156. if (this.mediaControl != null)
  157. this.mediaControl = null;
  158. if (this.basicAudio != null)
  159. this.basicAudio = null;
  160. if (this.basicVideo != null)
  161. this.basicVideo = null;
  162. if (this.videoWindow != null)
  163. this.videoWindow = null;
  164. if (this.frameStep != null)
  165. this.frameStep = null;
  166. if (this.graphBuilder != null)
  167. Marshal.ReleaseComObject(this.graphBuilder); this.graphBuilder = null;
  168. GC.Collect();
  169. }
  170. }
  171. catch
  172. {
  173. }
  174. }
  175. private void buttonStop_Click(object sender, EventArgs e)
  176. {
  177. closeVideo();
  178. t.Abort();
  179. }
  180. private void trackBar1_ValueChanged(object sender, EventArgs e)
  181. {
  182. }
  183. private void trackBar1_Scroll(object sender, EventArgs e)
  184. {
  185. if (mediaPosition != null)
  186. {
  187. mediaPosition.put_CurrentPosition(trackBar1.Value);
  188. }
  189. }
  190. private void trackBar2_Scroll(object sender, EventArgs e)
  191. {
  192. if (basicAudio != null)
  193. {
  194. basicAudio.put_Volume(trackBar2.Value);
  195. }
  196. }
  197. }
  198. }

开头的成员变量都是directshow的接口,接触过directshow的一看他们的名字就应该知道他们的作用,我就不多说了。在点击开始播放按键后,接口实例化,然后我开启了一个线程——用于更新进度条。停止键就是开始键的反过程了,销毁接口和线程。
能力有限写的很简单,还有很多用法可以参考他自带的sample,都是很实用的demo。


from:https://wuyuans.com/2012/09/simple-media-player-using-csharp



猜你喜欢

转载自blog.csdn.net/imxiangzi/article/details/80280134