最近在开发一个视频播放软件,主要要求就是循环播放多个视频文件,并且要求两个视频文件切换时,不能有黑屏现象发生。
无论是使用Winform的Mediaplayer控件还是WPF的MediaElement控件,在一个视频播放完毕切换到另一个视频时,都会有一个短暂的黑屏情况,于是我就把目光放在了DirectShow上面。下面说一下如何使用DirectShow进行视频播放。
1.quartz.dll和Tlbimp.exe
使用DirectShow,需要用到C:\Windows\System32文件夹下的quartz.dll文件,但此文件并不能直接在Visual Studio中使用,需要通过Tlbimp.exe(类型库导入程序),将quartz.dll转化为互操作程序集。这里只需要执行以下命令
tlbimp c:\windows\system32\quartz.dll /out:QuartzTypeLib.dll
这个命令并不是直接在cmd中执行,而是在Vs的开发工具中。
执行结果如下
2.相关代码
首先创建FilgraphManager等相关的实例
private const int WM_APP = 0x8000;
private const int WM_GRAPHNOTIFY = WM_APP + 1;
FilgraphManager _filGraphManager = null;
private IBasicVideo _basicVideo = null;
IVideoWindow _videoWindow = null;
IMediaEvent _mediaEvent = null;
IMediaEventEx _mediaEventEx = null;
IMediaPosition _mediaPosition = null;
IMediaControl _mediaControl = null;
加载视频文件
private void LoadVideo(string fileName)
{
_filGraphManager = new FilgraphManager();
_filGraphManager.RenderFile(fileName);
_basicVideo = _filGraphManager as IBasicVideo;
try
{
_videoWindow = _filGraphManager as IVideoWindow;
_videoWindow.Owner = (int) PlVideo.Handle;
_videoWindow.WindowStyle = 0x40000000;
_videoWindow.SetWindowPosition(PlVideo.ClientRectangle.Left, PlVideo.ClientRectangle.Top,
PlVideo.ClientRectangle.Width, PlVideo.ClientRectangle.Height);
}
catch (Exception)
{
throw;
}
_mediaEvent = _filGraphManager as IMediaEvent;
_mediaEventEx = _filGraphManager as IMediaEventEx;
_mediaEventEx.SetNotifyWindow((int) this.Handle, WM_GRAPHNOTIFY, 0);
_mediaPosition = _filGraphManager as IMediaPosition;
_mediaControl = _filGraphManager as IMediaControl;
}
视频播放只需要调用FilgraphManager实例中的Run方法即可
3.类和接口的说明
FilgraphManager 用于建立和控制graph的对象
RenderFile方法用于加载指定文件,Run,Stop,Pause方法对filters进行控制
IBasicVideo 接口 设置video的属性,如宽高,比特率等内容,通过owner属性设置video在哪个控件上显示
IMediaEvent 接口 获取事件通知的接口 IMediaEventEx是前者的扩展
IMediaPosition 接口 用于获取stream中的位置 get_CurrentPosition方法可以获取当前位置,当需要进度条显示视频播放位置时,可以使用此方法
IMediaControl 接口 这个根据名称就可以知道用途