1. DSPack 2.3.4 安装

 

一. 下载
由于sourceforge最近不能访问,所以可以去 http://www.progdigy.com/ 下载。
下载 http://www.progdigy.com/files/DSPACK234.zip 后,解压缩到一个目录(我用的是C:\Borland\VCL\DSPACK234)。

二. 安装

1 增加搜索路径 (DSPackDir)\src\DirectX9 和 (DSPackDir)\src\DSPack

在delphi7中选择菜单【Tools】-【Enviroment Options】,在打开的窗口中选择Library页签,在Library Path一项中添加这两个目录C:\Borland\VCL\DSPACK234\src\Directx9 ;C:\Borland\VCL\DSPACK234\src\DSPack

(将其直接粘贴在原有内容的后面,或者点击Library Path后面的...按钮添加)

2 编译 (DSPackDir)\packages\DirectX9_D7.dpk

双击(DSPackDir)\packages\DirectX9_D7.dpk,在delphi7中会显示一个关于重新创建资源文件的对话框,点击OK就可以了。
在delphi7中的打开窗口中点击compile按钮,完成编译。
在delphi7中选择菜单【File】-【Close All】,在提问是否保存时,选择保存。

3 编译 (DSPackDir)\packages\DSPack_D7.dpk

双击(DSPackDir)\packages\DSPack_D7.dpk,在delphi7中会显示一个关于重新创建资源文件的对话框,点击OK就可以了。 
在delphi7中的打开窗口中,点击compile按钮,完成编译。

在delphi7中选择菜单【File】-【Close All】,在提问是否保存时,选择保存。

4 编译并安装 (DSPackDir)\packages\DSPackDesign_D7.dpk

双击(DSPackDir)\packages\DSPackDesign_D7.dpk,在delphi7中会显示一个关于重新创建资源文件的对话框,点击OK就可以了。 
在delphi7中的打开窗口中,点击compile按钮,完成编译。 点击Install按钮,完成安装。
在delphi7中选择菜单【File】-【Close All】,在提问是否保存时,选择保存。

至此,安装已完成,在delphi的控件面板上可以找到DSPack的页签了。

如果在Delphi5或6中安装,则选择对应的D5或D6的文件。

(安装过程中遇到了一个编译错误,说找不到Jedi.inc。这个文件在src\Directx9目录下,为什么不能搜索。原来文档里写的路径是 (DSPackDir)\src\Directx9,而实际解压缩出来的目录名是DirectX9,所以添加搜索路径的时候一定要注意这个问题。把x改成X后,编译就通过了)

2. 用DSPack播放视频

 

安装完后,开始学习DSPack。
首先,要阅读一下(DSPackDir)\help目录下的help.chm文件,粗略地看了一下,内容太多看不出头绪。
还是先学习一下(DSPackDir)\Demos\D6-D7目录下的那些例子,边动手做边学习吧。

研究的第一个例子是PlayWin。研究了一下,主要使用TFilterGraph和TVideoWindow来完成。
TFilterGraph是DSPack中的核心类,其他类都要围绕着它,但是怎么理解它还不清楚。TVideoWindow是个显示播放视频的控件。这两个类的关系好像是数据库控件中Dataset控件和DBGrid控件的关系一样。

看得差不多后,自己照葫芦画瓢仿制一个。

1. 新建一个应用,在界面上先放4、5个按钮。
2. 在控件面板上选择DSPack那页,把前两个控件(TFilterGraph和TVideoWindow)在窗口上各放一个。
3. 关联
   选中VideoWindow1控件,在属性窗口中将FilterGraph属性设置为FilterGraph1。
   选中FilterGraph1控件,确认属性窗口中的Mode属性为gmNormal。

4.为Form1增加一个onCreate事件处理程序。
内容为:
    if not FilterGraph1.Active then FilterGraph1.Active := true;
    FilterGraph1.ClearGraph;
    FilterGraph1.RenderFile('E:\v\951.wmv'); // 简化一点,这里用你本地硬盘上的一个视频文件

5. 为Form1增加一个onCloseQuery事件处理程序。
内容为:
    FilterGraph1.Active := false ;

6.把button1的Caption改为Start,并增加一个OnClick事件
内容为:
    FilterGraph1.Play;

运行一下,就可以播放了。下面再增加几个功能按钮,如pause、stop。

7. 把button2的Caption改为Pause,并增加一个OnClick事件
内容为:
   FilterGraph1.Pause;

8. 把button3的Caption改为Stop,并增加一个OnClick事件
内容为:
    FilterGraph1.stop;

可以看出4-8步都是调用了TFilterGraph类的方法。

下面,再增加个全屏功能吧。
9. 把button4的Caption改为FullScreen,并增加一个OnClick事件
内容为:
    VideoWindow1.FullScreen :=true ;
   
10. 为VideoWindow1增加一个OnClick事件
内容为:
if videowindow1.FullScreen then
    videowindow1.FullScreen := false ; //退出全屏方式

一般的视频播放创窗口都有一个进度条,现在我们也来加一个。
A.1. 在DSPack控件面板上选择倒数第2个控件(TDSTrackBar),放到在窗口上。
A.2. 关联
   选中DSTrackBar1控件,在属性窗口中将FilterGraph属性设置为FilterGraph1。(这一步好像很熟悉哦)

重新运行程序,你就会看到一个进度条,并且能够使用这一进度条来调整播放的进度。

3. 使用DSPack打开摄像头

 

现在我们来看看(DSPackDir)\Demos\D6-D7目录下的PlayVideoCap,这是一个打开本机的视频输入设备的例子。

在这个例子中,又用到了一个新类:TFilter。

在我们依葫芦画瓢之前,你要装个摄像头或虚拟摄像头。虚拟摄像头可以用VCDCut、Softcam或Vcam等软件,也可以使用9158(http://www.9158.com/)或MVBox(http://www.mvbox.cn/)的虚拟视频。

先跟上次一样:

1. 新建一个应用,在界面上先放4、5个按钮,这次多放一个Listbox,这个列表框中将列出系统中安装的视频输入设备。
2. 在控件面板上选择DSPack那页,把前两个控件(TFilterGraph和TVideoWindow)在窗口上各放一个。

下面该有所不同了

3.在DSPack中选择TFilter控件,放到窗口上。
4.选中FilterGraph1控件,在属性窗口中将Mode属性设为gmCapture。
5. 关联
   选中VideoWindow1控件,将FilterGraph属性设置为FilterGraph1。
   选中Filter1控件,将FilterGraph属性设置为FilterGraph1。

6. 在代码模式中,在Interface后的Uses中增加
DSUtil, DirectShow9,
在implementation前面的Var中增加
SysDev: TSysDevEnum;

7. 为Form1增加一个onCreate事件处理程序,读取系统中的视频输入设备。
内容为:
var
i: integer;
begin
// 读取系统中的视频输入设备
SysDev:= TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);
if SysDev.CountFilters > 0 then
    for i := 0 to SysDev.CountFilters - 1 do
    begin
      Listbox1.Items.Add(SysDev.Filters[i].FriendlyName)
    end;

end;

7. 同前。为Form1增加一个onCloseQuery事件处理程序。
内容为:
    SysDev.Free;
    FilterGraph1.ClearGraph;
    FilterGraph1.Active := false ;

8. 为Listbox1增加一个onClick事件处理程序
内容为:
FilterGraph1.ClearGraph;
FilterGraph1.Active := false;
//设filter为所选视频输入设备
Filter1.BaseFilter.Moniker := SysDev.GetMoniker(Listbox1.ItemIndex);
FilterGraph1.Active := true;
// 打开所选的视频输入设备
with FilterGraph1 as ICaptureGraphBuilder2 do
    RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter1 as IBaseFilter, nil, VideoWindow1 as IbaseFilter);
// 显示出来
FilterGraph1.Play;

运行一下试试,看是否能看到自己的摄像头的内容。

几个按钮没用,等到下一个例子用吧。

4. DSPack抓帧

 
在例子PlayVideoCap中,还有抓帧和回放的功能。这用到第4个控件TSampleGrabber。

我们以前两个例子为基础,增加抓帧的功能。
打开前面的例子,然后:

1. 在DSPack中选择TSampleGrabber控件,放到窗口上。然后将其FilterGraph属性设置为FilterGraph1。
2. 在选择一个标准控件TImage(在Additional页签中),放在窗口上。
3.讲一个没用的按钮的Caption改为“Snapshot”,在它的OnClick事件中写:
SampleGrabber1.GetBitmap(Image1.Picture.Bitmap);

前面两个例子都可以这样增加抓帧功能。不过,对于第二个例子(即操作摄像头的例子),需要做额外的修改,就是:

    RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter, nil, VideoWindow as IbaseFilter);
改为
    RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter, SampleGrabber as IBaseFilter, VideoWindow as IbaseFilter);

这样就可以了

5. DirectShow基本概念

 

到这里,我基本用DSPack做了一点东西,了解了DSPack中的3个基本类及其一些方法。但要理解它们,还要了解一下DirectShow中Filter Graph、Filter、Pin的基本概念。

在网上找了一些资料,比较好资料的地址为 http://www.yesky.com/259/1854259.shtml ,大部分资料都来自于陆其明写的《DirectShow开发指南》和《DirectShow实务精选》两本书。
总结如下:

1) DirectShow的系统结构

DirectShow的体系结构如图1所示。

图1 DirectShow系统

DirectShow位于应用层中。它使用一种叫Filter Graph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫Filter;各个Filter 在Filter Graph中按一定的顺序连接成一条“流水线”协同工作。

( 可以看出TFilterGraph是个Filter的容器 )

按照功能来分,Filter大致分为三类:Source Filters、Transform Filters和Rendering Filters。
Source Filters主要负责取得数据,数据源可以是文件、因特网、或者计算机里的采集卡、数字摄像机等,然后将数据往下传输;
Transform Fitlers主要负责数据的格式转换、传输;
Rendering Filtes主要负责数据的最终去向,我们可以将数据送给声卡、显卡进行多媒体的演示,也可以输出到文件进行存储。

在DirectShow系统之上,我们看到的,即是我们的应用程序(Application)。应用程序要按照一定的意图建立起相应的Filter Graph,然后通过Filter Graph Manager来控制整个的数据处理过程。DirectShow能在Filter Graph运行的时候接收到各种事件,并通过消息的方式发送到我们的应用程序。这样,就实现了应用程序与DirectShow系统之间的交互。

2) Filter概述以及连接

过滤器(Filter)是DirectShow中最基本的概念。DirectShow是通过Filter Graph来管理Filter的。Filter Graph是Filter的“容器”,而Filter是Filter Graph中的最小功能模块

Filter是一种COM组件,对于每个Filter,都有其自己的Pin,它是由Filter创建的COM对象。 Filter通过Pin来进行他们之间的连接。

Pin分为两种:输出Pin和输入Pin。输出的Pin把Filter处理后的数据传送到Filter的外 部,而输入Pin则是把Filter外部的数据接收到Filter中,以便Filter对这些数据进行处理。

对于三种类型的Filter(Source Filter,Transform Filter,Rendering Filter)的连接图如下:

 
图2 Filter的连接

可以根据Filter所包含的输入Pin和输出Pin的熟练来判断Filter的类型:
只有输出Pin,没有输入pin,为Source Filter
既有输出Pin,又有输入pin,为Transform Filter
没有输出Pin,只有输入pin,为Rendering Filter

3)DirectShow 的重要接口

DirectShow采用了COM标准,所以很多重要的功能都是通过COM接口来完成。下面就列举一些重要的DirectShow的接口。

(1) IGraphBuilder接口

用于构造Filter Graph的接口,建立和管理一系列的Filter,过滤和处理源媒体流。

(2) IMediaControl接口

用于控制多媒体流在Filter Graph中的流动,如流的启动和停止。

(3) IMediaEvent接口

用于捕获播放过程中发生的事件,并通知应用程序,如EC_COMPLETE等。

(4) IVideoWindow接口

用于控制视频窗口的属性。

(5) IMeadiaSeeking接口

用于查找媒体的接口,定位流媒体,控制多媒体数据播放提供精确控制。

(6) IBaseFilter接口

从ImediaFilter接口继承,用来定义一个具体的过滤器指针,并对多媒体数据进行处理。

(7) IPin接口

用于管理两个过滤器之间的Pin,从而连接过滤器。

(8) IsampleGrabberCB接口

是Sample Grabber过滤器的一个接口,用于当流媒体数据通过过滤器时进行采样以获得帧图象。

还有一个可以参考的介绍,地址为:http://www.yesky.com/259/1854259.shtml

Filter是一种COM组件。为了实现在Filter Graph中的统一操作,每个Filter上都至少实现了一个IBaseFilter接口。实现Filter的文件一般是一个DLL,扩展名可以是.dll,但更多的时候是.ax。

Filter必须加入到Filter Graph并接入到工作链路中才能发挥作用。如果想绕过Filter Graph而直接使用Filter实现的功能模块,那就要将Filter功能移植成DirectX媒体对象(DMO)。

在使用Filter之前,必须注册。 命令格式为
regsvr32 c:\yourdirectory\yourfilter.ax

Filter Chain是相互连接着的一条Filter链路,并且链路中的每个Filter全都有一个处于“已连接”状态的输入Pin,至多有一个处于“已连接”状态的输出Pin,这条Filter链路中的数据流不依赖链路外的其他Filter。Filter Chain通过IFilterChain接口来进行相关操作。

当Filter Graph处于运行状态下,Filter Chain可以在运行和停止状态之间切换;
当Filter Graph处于暂停状态下,Filter Chain可以在暂停和停止状态之间切换。这是Filter Chain仅有的两种状态转换。

Filter的数据传送
Filter之间以Sample的形式传送数据。Sample是一个封装了一定大小数据内存的COM组件。用于数据传输的一般是输入pin上实现的IMemInputPin接口。

Filter有3种状态:停止、暂停和运行。

DSPack各种使用方法的更多相关文章

  1. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  2. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  3. 【.net 深呼吸】细说CodeDom(6):方法参数

    本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...

  4. IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法

    直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...

  5. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  6. [C#] C# 基础回顾 - 匿名方法

    C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...

  7. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  8. [BOT] 一种android中实现“圆角矩形”的方法

    内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...

  9. JS 判断数据类型的三种方法

    说到数据类型,我们先理一下JavaScript中常见的几种数据类型: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Functi ...

随机推荐

  1. [C#学习]在多线程中如何调用Winform[转]

    问题的产生: 我的WinForm程序中有一个用于更新主窗口的工作线程(worker thread),但文档中却提示我不能在多线程中调用这个form(为什么?),而事实上我在调用时程序常常会崩掉.请问如 ...

  2. JS面向对象思想(OOP)

    直接看js好了,模拟创建一个奥运会 function 奥运会Class(主题) { // 删除主题 // delete this.主题; this.主题 = 主题; this.开幕时间; this.闭 ...

  3. Linux脚本(二)

    1.for循环以及加法的使用 portStr=`lsof -i:56801 | head -2`count=0for str in `lsof -i:56801 | head -2`do ((coun ...

  4. python 学习笔记整理

    首先自我批评一下,说好的一天写一篇博客,结果不到两天,就没有坚持了,发现自己做什么事情都没有毅力啊!不能持之以恒.但是,这次一定要从写博客开始来改掉自己的一个坏习惯. 可是写博客又该写点什么呢? 反正 ...

  5. 【产品体验】ONE一个

    第二篇博客,加油加油~~本人产品新人,学习中,希望大家多多指教!  先来两张ONE的界面图镇楼——        ONE简介: “复杂世界里,一个就够了.”这是一款轻量级的文艺阅读应用,每日更新一张图 ...

  6. 听同事讲 Bayesian statistics: Part 1 - Bayesian vs. Frequentist

    听同事讲 Bayesian statistics: Part 1 - Bayesian vs. Frequentist   摘要:某一天与同事下班一同做地铁,刚到地铁站,同事遇到一熟人正从地铁站出来. ...

  7. rm加转义很危险

    rm -r 想转义一个空格字符,转得不对 -r, -R, --recursive 递归删除目录及其内容 连续rm了n个不想rm的文件夹.%>_<% 想起来以前有人也因为rm的失误把整个wo ...

  8. iOS-NSString-Base64String-Base64原理

    之前看到好多人找Str2Base64Str,还有好多自己写了方法的,仔细研究了下base64的编码原理(这个我写在下面),发现官方的API已经可以完成这项功能,这里贴出来供大家参考. 一言不合就上代码 ...

  9. DJANGO增加超级用户

    from django.contrib.auth.models import User user=User.objects.create_superuser('name','emailname@dem ...

  10. Android 文件上传 使用AsyncHttpClient开源框架

    public void upload(View view) { AsyncHttpClient client = new AsyncHttpClient(); RequestParams reques ...