DirectShow Filter 基础与简单的示例程序

DirectShow 是一个 Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。

Filter 实质是一个 COM 组件,所以学习开发 Filter 前你应该对 COM 相关知识有点了解。COM 组件的实质是实现了纯虚指针接口的 C++ 对象。

应用程序开发者只需要基本的 COM 组件知识:实例化COM组件、调用接口、管理接口的引用计数。Filter 开发者则需要更多。

选择一个基类,声明自己的类。

应该清楚这个 Filter 在整个 Filter Graph 的位置,这个 Filter 的输入是什么数据,输出是什么数据,有几个输入 Pin、几个输出 Pin 等,可以画出这个 Filter 的草图。

Win7: DirectShow SDK 做为 Windows SDK(GRMSDK_EN_DVD.iso) 的一部分,不再有单独的 DirectX SDK 包。

在 DirectShow 中,应用程序要实现功能就必须将这些 Filter 链接在一起,因而一个 Filter 的输出就变成了另一个 Filter 的输入。这一系列串在一起的 Filter 称为 Filter Graph。

使用 VS2008 建立 Filter 开发工程的过程如下:

(1) 新建

Visual C++/Win32 项目,工程名如:FilterSample。点击“确定”进入下一步;

(2) 应用程序类型选择:DLL,一般不选择 MFC 和 ATL;

工程的建立完成,编译后可以先将输入文件改名。方法如下:

属性页/链接器/常规/输出文件,修改为:$(OutDir)/FilterSample.ax

DirectShow 必须用到以下头文件的库文件:

 1 #include "streams.h"
 2 #include "initguid.h"
 3 strmbasd.lib
 4 winmm.lib
 5 uuid.lib
 6 Quartz.lib   输出 AMGetErrorText 函数,如果不调用此函数,此库不是必需的。
 7
 8 FilterSample.def 文件的内容:
 9 LIBRARY FilterSample.ax
10 EXPORTS
11 ; 需要定义的导出函数
12 DllMain PRIVATE
13 DllRegisterServer PRIVATE
14 DllUnregisterServer PRIVATE
15 ; 在基类中已经定义的导出函数
16 DllGetClassObject PRIVATE
17 DllCanUnloadNow PRIVATE
18
19 dllmain.cpp 的代码如下:
20 // dllmain.cpp : 定义 DLL 应用程序的入口点。
21 #include "stdafx.h"
22 #include "streams.h"
23
24 // BOOL APIENTRY DllMain( HMODULE hModule,
25 //                        DWORD  ul_reason_for_call,
26 //                        LPVOID lpReserved
27 //           )
28 // {
29 //  switch (ul_reason_for_call)
30 //  {
31 //  case DLL_PROCESS_ATTACH:
32 //  case DLL_THREAD_ATTACH:
33 //  case DLL_THREAD_DETACH:
34 //  case DLL_PROCESS_DETACH:
35 //    break;
36 //  }
37 //  return TRUE;
38 // }
39
40 STDAPI DllRegisterServer()
41 {
42   return AMovieDllRegisterServer2(TRUE);
43 }
44 STDAPI DllUnregisterServer()
45 {
46   return AMovieDllRegisterServer2(FALSE);
47 }
48
49 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
50 BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason,   LPVOID lpReserved)
51 {
52   return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
53 }  

编译时,可能会遇到如下问题:

1>e:\work\sourcecode\testcode\filtersample\dllmain.cpp(23) : error C3861: “AMovieDllRegisterServer2”: 找不到标识符

1>e:\work\sourcecode\testcode\filtersample\dllmain.cpp(27) : error C3861: “AMovieDllRegisterServer2”: 找不到标识符

编译错误, 一般是头文件没有包含。所以,包含: #include "streams.h"

1>dllmain.obj : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 [email protected] 中被引用

1>dllmain.obj : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 [email protected] 中被引用

1>E:\Work\SourceCode\TestCode\FilterSample\Debug\FilterSample.dll : fatal error LNK1120: 2 个无法解析的外部命令

链接错误, 一般是库文件没有包含。所以,库输入中包含: strmbasd.lib

1>正在链接...

1>strmbasd.lib(wxdebug.obj) : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 "void __stdcall DbgInitialise(struct HINSTANCE__ *)" ([email protected]@[email protected]@@Z) 中被引用

1>strmbasd.lib(wxutil.obj) : error LNK2001: 无法解析的外部符号 [email protected]

1>strmbasd.lib(wxutil.obj) : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 "unsigned int __cdecl CompatibleTimeSetEvent(unsigned int,unsigned int,void (__stdcall*)(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long),unsigned long,unsigned int)" ([email protected]@[email protected]@Z) 中被引用

1>E:\Work\SourceCode\TestCode\FilterSample\Debug\FilterSample.dll : fatal error LNK1120: 4 个无法解析的外部命令

包含  winmm.lib, 可以解决 timeGetTime 链接错误的问题

增加头文件 FilterSample.h,其内容如下:

其中 GUID 的生成,需要用到下面的工具: Microsoft SDKs\Windows\v7.1\Bin\guidgen.exe

 1 #ifndef _FILTER_SAMPLE_H_
 2 #define _FILTER_SAMPLE_H_
 3
 4 // {33B57142-BD07-4a77-AE91-A8F6C24A8F40}
 5 DEFINE_GUID(CLSID_FilterSample,
 6     0x33b57142, 0xbd07, 0x4a77, 0xae, 0x91, 0xa8, 0xf6, 0xc2, 0x4a, 0x8f, 0x40);
 7
 8 class CFilterSample: public CCritSec, public CBaseFilter
 9 {
10 public:
11   CFilterSample(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *hr);
12   virtual ~CFilterSample();
13   static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
14   CBasePin *GetPin(int n);
15   int GetPinCount();
16 };
17
18 #endif  

FilterSample.cpp 的内容如下:

 1 // FilterSample.cpp : 定义 DLL 应用程序的导出函数。
 2 //
 3
 4 #include "stdafx.h"
 5 #include "streams.h"
 6 #include "initguid.h"
 7
 8 #include "FilterSample.h"
 9
10 // Using this pointer in constructor
11 #pragma warning(disable:4355 4127)
12
13 //////////////////////////////////////////////////////////////////////////
14 // AMOVIESETUP_FILTER 描述一个 Filter
15 // AMOVIESETUP_PIN 描述 pin
16 // AMOVIESETUP_MEDIATYPE 描述数据类型
17 const AMOVIESETUP_MEDIATYPE sudPinTypes =
18 {
19   &MEDIATYPE_NULL,         // Major CLSID
20   &MEDIASUBTYPE_NULL       // Minor type
21 };
22
23 const AMOVIESETUP_PIN psudPins[] =
24 {
25   {
26     L"Input",             // Pin‘s string name
27     FALSE,                // Is it rendered
28     FALSE,                // Is it an output
29     FALSE,                // Allowed none
30     FALSE,                // Allowed many
31     &CLSID_NULL,          // Connects to filter
32     L"Output",            // Connects to pin
33     1,                    // Number of types
34     &sudPinTypes          // Pin information
35   },
36   {
37     L"Output",            // Pin‘s string name
38     FALSE,                // Is it rendered
39     TRUE,                 // Is it an output
40     FALSE,                // Allowed none
41     FALSE,                // Allowed many
42     &CLSID_NULL,          // Connects to filter
43     L"Input",             // Connects to pin
44     1,                    // Number of types
45     &sudPinTypes          // Pin information
46   }
47 };
48
49 const AMOVIESETUP_FILTER sudInfTee =
50 {
51   &CLSID_FilterSample,           // CLSID of filter
52   L"Filter Sample Test Lib",     // Filter‘s name
53   MERIT_DO_NOT_USE,              // Filter merit
54   2,                             // Number of pins
55   psudPins                       // Pin information
56 };
57 //////////////////////////////////////////////////////////////////////////
58
59 CFactoryTemplate g_Templates[1] =
60 {
61   {
62     L"Filter Sample",                // Name
63     &CLSID_FilterSample,             // CLSID
64     CFilterSample::CreateInstance,   // Method to create an instance of MyComponent
65     NULL,                            // Initialization function
66     &sudInfTee                       // Set-up information (for filters)
67   }
68 };
69 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
70
71
72 CFilterSample::CFilterSample(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *hr)
73   :CBaseFilter(NAME("Filter Sample"), pUnk, this, CLSID_FilterSample)
74 {
75 }
76
77 CFilterSample::~CFilterSample()
78 {
79 }
80
81 CBasePin * CFilterSample::GetPin(int n)
82 {
83   return NULL;
84 }
85 int CFilterSample::GetPinCount()
86 {
87   return 0;
88 }
89
90 CUnknown * WINAPI CFilterSample::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
91 {
92   CFilterSample *pFilter = new CFilterSample(NAME("Filter Sample"), pUnk, pHr);
93   if (pFilter== NULL)
94   {
95     *pHr = E_OUTOFMEMORY;
96   }
97   return pFilter;
98 }  

编译时,可能遇到如下问题:

1>FilterSample.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall CBaseFilter::CBaseFilter(wchar_t const *,struct IUnknown *,class CCritSec *,struct _GUID const &)" ([email protected]@[email protected][email protected]@[email protected]@[email protected]@@Z),该符号在函数 "public: __thiscall CFilterSample::CFilterSample(wchar_t *,struct IUnknown *,long *)" ([email protected]@[email protected][email protected]@[email protected]) 中被引用

1>E:\Work\SourceCode\TestCode\FilterSample\Debug\FilterSample.dll : fatal error LNK1120: 1 个无法解析的外部命令

解决方法: 属性页 常规->字符集 修改为“使用多字节字符集”

编译通过后,如何验证此 Filter 呢?

regsvr32 FilterSample.ax

regsvr32 提示错误:

模块“FilterSample.ax”已加载,但找不到入口点 DllRegisterServer。

请确保“FilterSample.ax”为有效的 DLL 或 OCX 文件,然后重试。

出现此错误的原因,是 FilterSample.def 未链接到工程中。在工程属性页,“链接器”/“输入”/“模块定义文件” 中输入: FilterSample.def 后,重新编译。

然后在命令行执行: regsvr32 FilterSample.ax,则提示成功。

如何确认成功了呢?可通过 Microsoft SDKs\Windows\v7.1\Bin\graphedt.exe 来查看。方法如下:

点击 graphedt.exe 的 Graph 菜单,选择 Insert Filters...。在弹出的对话框: Which filters do you want to insert? 中,选择 Directshow Filters/Filter Sample Test Lib。

这个名字看起来是不是很熟悉?看看上面的代码中是不是有这样的字符串,呵呵...。如果还不确认,请看 Filter Sample Test Lib 的 GUID 和 文件名分别是:

@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{33B57142-BD07-4A77-AE91-A8F6C24A8F40} 和 E:\Filters\FilterSample.ax(具体的目录与执行 regsvr32 时 FilterSample.ax 所在的路径相关)。

时间: 2024-08-08 05:38:38

DirectShow Filter 基础与简单的示例程序的相关文章

OpenGL入门和示例程序

大家好,今天雅乐网给大家介绍一下OpenGL的一些基本语法和一个简单的示例程序. OpenGL是什么呢?说简单一点,就是一个图形软件包,它提供了许多函数供我们调用.我们看看维基百科上的说法 开放图形库(英语:Open Graphics Library,缩写为OpenGL)是个定义了一个跨编程语言.跨平台的应用程序接口(API)的规范,它用于生成二维.三维图像.这个接口由近三百五十个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象.而另一种程序接口系统是仅用于Microsoft Wind

ROS indigo安装完成后运行小乌龟示例程序

安装ROS成功后,在Beginner Tutorials中有一个简单的示例程序. 在Terminal中运行以下命令:$ roscore新开一个terminal,运行以下命令,打开小乌龟窗口:$ rosrun turtlesim turtlesim_node新开一个terminal,运行以下命令,打开乌龟控制窗口,可使用方向键控制乌龟运动:$ rosrun turtlesim turtle_teleop_key选中控制窗口,按方向键,可看到小乌龟窗口中乌龟在运动.新开一个terminal,运行以下

Android 网络编程基础之简单聊天程序

前一篇讲了Android的网络编程基础,今天写了一个简单的聊天程序分享一下 首先是服务端代码: 1 package com.jiao.socketdemo; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter;

android示例:一个简单的登陆程序

最近写了个简单的登陆程序,有几点收获: 1.懂得如何在LinearLayout中嵌套LinearLayout,完善布局的行列: 2.用android:layout_weight控制控件的比重: 3.用getText()获取EditText内容: 4.熟悉控件的编写,不用再照着书抄写了=.= 代码如下: LoginActivity.java import android.os.Bundle; import android.app.Activity; import android.content.I

java基础学习02(简单的java程序)

简单的java程序 一.完成的目标 1. 理解java程序的基本组成 2. 如何对程序代码进行注释 3. java标识符的命名规则 4. 了解java中的关键字 5. 使用java定义变量或声明变量 二.一个简单的java程序 public class TestJava{ public static void main(String [] args){ //操作一个简单的范例,输出和乘方 int num = 10; //定义一个整型变量 num = 30; //修改变量 System.out.p

DirectShow Filter的开发实践

一.介绍 摄像头图像采集处理在业界有着多种成熟的方案.从老的DirectShow.Grabber技术,到新的Windows Media Foundation框架,网络上都有着丰富的参考资料.OpenCV库里面甚至提供了非常简洁的接口,用户只要一两行代码即可实现数据采集.编解码等功能,使用起来甚是方便.但是,如果把数据采集的任务放到我们自己的程序中来实现的话,CPU的占用率会比较高.这在某些情况下不太可取.虽然可以实现,但是在客户端使用时效率非常低下.而公司恰好有一项开发任务:要求采集到摄像头数据

OSG中的示例程序简介

OSG中的示例程序简介 转自:http://www.cnblogs.com/indif/archive/2011/05/13/2045136.html 1.example_osganimate一)演示了路径动画的使用(AnimationPath.AnimationPathCallback),路径动画回调可以作用在Camera.CameraView.MatrixTransform.PositionAttitudeTransform等四种类型的节点上.二)演示了osgSim::OverlayNode

ios开发UI基础—Kvc简单介绍

一.KVC简单介绍 KVC key valued coding 键值编码 KVC通过键值间接编码 补充: 与KVC相对的时KVO,即key valued observer 键值观察.监听某一个模型的属性,只要模型属性的值一变化就通知你. 二.使用KVC 1.KVC基本使用介绍 (1)代码示例: 新建一个命令行项目,用以演示KVC的用法 完成之后为项目添加一个Person类. 为Person类添加两个属性(name和age),注意这两个属性的类型. 1 #import <Foundation/Fo

epub、ocf等常用电子书格式浅析----附JAVA示例程序

一. 电子书介绍 转载请注明http://www.cnblogs.com/xckk/p/6020324.html Epub(Electronic Publication)是一个完全开放和免费的电子书标准.是一个自由的开放标 准,属于一种可以“自动重新编排”的内容. “自动重新编排”的原因是内部使用XHTML来展现文件的内容,用一系列CSS来定义格式和版面设计,达到了内容和编排的分离. 现在EpubEpub包括三项主要规格: 开放出版结构(Open Publication Structure,OP