DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)
虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简
单的过程),读者总希望看到象第一步怎么做,第二步怎么做....这样的demo。其实写你的第一个filter是有一定难度的,只要过了这关以后
就容易多了。
由于最近需要自己写一个push推模式的source filter,加上刚激活了Blog,不好意思Blog上没有一篇文章,所以将写这个filter的过程写下来
,为了照顾刚开始学的朋友,我采用第一步第二步....这样的方式尽可能的讲解详细,相信你按照这个步骤一定没问题的,对于vc中DirectSho
w开发环境的配置,这里不做讲解。下面开始:
(vc 6.0 + DirectShow 9.0)
我也记得刚学时候的迷茫,所以会尽量详细每个过程,所以很多是sdk的例子我没改动它,没讲的是我提供的源代码里面我加有比较详细的注释
,可以配合我提供的源代码一起看。
第一步:建立工程
File->New->Project选择Win32 Dynamic-Link Library,(由于是个demo,名字我用的Push_Test_01)->Next后选择A simple DLL project(这里
为了避免自己写DllMain的麻烦,所以没选An empty DLL project)->可以Finish了
到这里工程建立结束。
第二步:相关设置和需要加入的文件等操作
首先将Debug方式改为Release。接着Project->Seetings->Link里的Output file
name从Release/Push_Test_01.dll改为Release/Push_Test_01.ax。
在工程目录下建立一个文本文件,修改名字为Push_Test_01.def。将其加入工程:Project->Add to project->Files 选择Push_Test_01.def后
加入。
对Push_Test_01.def进行修改,FileView->Source Files 双击Push_Test_01.def后输入:
LIBRARY Push_Test_01.ax
EXPORTS
DllMain PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
,确定project->Seetings->link下Object/library modules里面为:
strmbase.lib msvcrt.lib quartz.lib vfw32.lib winmm.lib kernel32.lib advapi32.lib version.lib largeint.lib user32.lib
gdi32.lib comctl32.lib ole32.lib olepro32.lib oleaut32.lib uuid.lib
添加头文件:
#include <streams.h>
#include <olectl.h>
#include <initguid.h>
生成全球唯一标识,这里这样
DEFINE_GUID(CLSID_PushTest,
0xfd501041, 0x8ebe, 0x11ce, 0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa1);
第三步:注册等函数的添加
首先修改入口函数,并添加注册和反注册函数,操作后的内容如下:
//注册
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
//反注册
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
//filter的入口函数
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
此时编译会有class CFactoryTemplate没实现等错误,下面我们来实现它。
添加下面的代码,每个地方我基本都加了大体意思的注释:
/**************开始填写注册信息***************/
//媒体类型
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
&MEDIATYPE_Video, // Major type 主类型
&MEDIASUBTYPE_NULL // Minor type sub类型,可以为MEDIASUBTYPE_NULL
};
//pin的信息
const AMOVIESETUP_PIN sudOpPin =
{
L"Output", // Pin string name pin的名字
FALSE, // Is it rendered 输入pin有用,输出pin一般为FALSE
TRUE, // Is it an output TRUE表示是输出pin,不然是输入pin
FALSE, // Can we have none 是否能不实例化
FALSE, // Can we have many 是否能创建多个同这样类型的pin
&CLSID_NULL, // Connects to filter 连接的filter类
NULL, // Connects to pin 该pin要连接的pin的类
1, // Number of types 该pin支持的媒体类型
&sudOpPinTypes // Pin details 该pin的媒体类型的描述
};
const AMOVIESETUP_FILTER sudBallax =
{
&CLSID_PushTest, // Filter CLSID 该filter的类标志
L"Push_Test", // String name 该filter的名字
MERIT_DO_NOT_USE, // Filter merit 该filter的Merit值
1, // Number pins 该filter的pin的数目
&sudOpPin // Pin details 该filter的pin的描述
};
//创建实例时用,有类,名字等需要的信息
CFactoryTemplate g_Templates[] = {
{
L"Push_Test" //filter的名字
, &CLSID_PushTest //对象的类标识
, PushTestFilter::CreateInstance //创建一个实例用的函数
, NULL //
, &sudBallax //filter的注册信息
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
通过上面的注释,我们看到该filter有一个输出pin,支持Video类型等等信息,不多说了。
这里主要对PushTestFilter::CreateInstance //创建一个实例用的函数
说明一下!!PushTestFilter就是我们的filter类!!在下面实现它。
第四步:filter类的实现
添加新类PushTestFilter,使其继承自CSource。这就是我们的filter类,在这个类里面没有过多的操作,就只有2个函数而已:
//filter的主类,继承自CSource
class PushTestFilter : public CSource
{
public:
// 唯一能创建该类实例的接口
static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
private:
//只能通过CreateInstance()的调用创建实例
PushTestFilter(LPUNKNOWN lpunk, HRESULT *phr);
};
这里有2点需要注意:
构造函数PushTestFilter()是private的,不是一般的public!!!!!!!!!!!
CreateInstance()函数是static的,因为它不能通过对象来调用!!!!
2个函数的具体实现如下:
//构造函数,注意这里是private属性的,不是public,
//所以要创建它的实例,只能是通过CreateInstance()函数的方式
PushTestFilter::PushTestFilter(LPUNKNOWN lpunk, HRESULT *phr):
CSource(NAME("PushTest"), lpunk, CLSID_PushTest)
{
ASSERT(phr);
CAutoLock cAutoLock(&m_cStateLock);
//m_paStreams是从CSource基类继承来的指针数组。由于这个demo我们只
//有1个pin,所以分配了1个空间
m_paStreams = (CSourceStream **) new PushTesiPin*[1];
if(m_paStreams == NULL)
{
if(phr)
*phr = E_OUTOFMEMORY;
return;
}
//为刚分配的那个空间付值,这就自动给filter加入了一个pin,析构的
//时候会自动释放
m_paStreams[0] = new PushTesiPin(phr,this,L"Push_Test");
if(m_paStreams[0] == NULL)
{
if(phr)
*phr = E_OUTOFMEMORY;
return;
}
}
//CreateInstance()该函数是static属性的,因为不能通过对象来调用
CUnknown * WINAPI PushTestFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
{
ASSERT(phr);
//这里调用了private属性的构造函数
CUnknown *punk = new PushTestFilter(lpunk, phr);
if(punk == NULL)
{
if(phr)
*phr = E_OUTOFMEMORY;
}
return punk;
}
这里的类PushTesiPin就是我们的pin类,在后面要实现!!其实主要的操作是在pin类PushTesiPin里面的。
第五步:pin类的实现
添加类PushTesiPin,使其继承自CSourceStream。这里需要重载的函数会多一点!不过没关系!我会一个一
个的进行说明。
主要是这3个:
//由于我们的filter就一种媒体类型,所以重载了GetMediaType(CMediaType *pMediaType)
//如果有多种类型,就应该重载另外2个函数了,具体参考基类CSourceStream
HRESULT GetMediaType(CMediaType *pMediaType);
//这个函数是用来设置Sample大小的,在pin连接成功后会被调用
HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc,ALLOCATOR_PROPERTIES *pProperties);
//对Sample数据的填充
HRESULT FillBuffer(IMediaSample *pms);
我在源代码里面都家了比较详细的注释,参考源代码一起看容易明白。
其实这个filter没做别的,就相当与将sdk下的PushSource例子自己再写了一遍,主要是为了说明这个过程,
到这里相信你应该有个大概的概念了,那么恭喜!
我也写累了,如果对大家有帮助就找个时间再将写pull拉
模式的过程也写出来。
DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)的更多相关文章
- DirectShow中写push模式的source filter流程 + 源码(内附具体凝视)
尽管网上已有非常多关于DirectShow写source filter的资料.只是非常多刚開始学的朋友总说讲的不是非常清楚(可能当中作者省略了很多他觉得简 单的过程).读者总希望看到象第一步怎么做,第 ...
- 从1.6W名面试者中收集的Java面试题精选汇总(内附知识脑图)
本篇的面试题是接之前读者的要求,发出来的. 首先,声明下,以下知识点并非全部来自BAT的面试题. 如果觉得在本文中笔者总结的内容能对你有所帮助,可以点赞关注一下. 本文会以引出问题为主,后面有时间 ...
- 【Filter 不登陆无法访问】web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面的功能
在web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面,而重定向到登陆界面的功能. 项目是用springMVC+spring+hibernate实现 (和这个没有多大关系) 第一步: 首先 ...
- 在mybatis中写sql语句的一些体会
本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...
- 在DirectShow中支持DXVA 2.0(Supporting DXVA 2.0 in DirectShow)
这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档.并准备记录一下用ffmpeg实现dxva2,将在第三篇写到.这是第二篇.,英文原址:https://msdn.microso ...
- 安卓中的Model-View-Presenter模式介绍
转载自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0425/2782.html 英文原文:Introduction to M ...
- COM中的线程模式
Choosing the threading model for an object depends on the object's function. An object that does e ...
- (转)MVC中的Repository模式
1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...
- php中的MVC模式运用
[size=5][color=Red]php中的MVC模式运用[/color][/size] 首先我来举个例子: 一个简单的文章显示系统 简单期间,我们假定这个文章系统是只读的,也就是说这个例子将不涉 ...
随机推荐
- Python之Suds库调用WCF时复杂参数序列化
今天主要做自动化测技术支持工作,最近一直在做接口自动化这块,前些天在研究将web页面模拟http进行接口自动化,这周杭州那边想测试WCF服务,所以这两天一直在探索.遇到的第一个问题就是服务参数传参序列 ...
- POJ 1681 Painter's Problem [高斯消元XOR]
同上题 需要判断无解 需要求最小按几次,正确做法是枚举自由元的所有取值来遍历变量的所有取值取合法的最小值,然而听说数据太弱自由元全0就可以就水过去吧.... #include <iostream ...
- Hibernate之HelloWorld
1. 步骤 0. 导入相关Jar包. 1. 编写Hibernate的持久化文件 (默认为hibernate.cfg.xml). 2. 编写持久化类. 3. 创建对象 - 关系文件(.htm.xml文件 ...
- [HAOI2009]毛毛虫
题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...
- [Python Study Notes]Socket模拟ssh执行cmd并记录遇到的问题
服务器端: 流程: 1.创建servert实例 2.绑定地址和端口 3.开始监听 4.创建客户端连接实例 5.等待客户端的消息 6.......... # The_author = 'liu66' # ...
- 异步任务利器Celery(一)介绍
django项目开发中遇到过一些问题,发送请求后服务器要进行一系列耗时非常长的操作,用户要等待很久的时间.可不可以立刻对用户返回响应,然后在后台运行那些操作呢? crontab定时任务很难达到这样的要 ...
- Jetty容器
♣Jetty和Tomcat的区别 ♣Jetty下载.安装 ♣eclipse安装jetty插件 ♣第一个jetty测试(maven+jetty) 1.Jetty和Tomcat的区别 Jetty 是一 ...
- mdb导入SqlServer
弄了一份医案数据库,打开一看...命名全中文,好吧,导入SQLServer走起 SQL: SELECT * INTO newtable FROM OPENDATASOURCE ('Microsoft. ...
- php常用面试知识点
1.php基础 2.mysql基础 3.js基础 4.jq 5.正则 6.面向对象 7.分页类,购物车类,数据库类,上传类,图片处理类 8.smarty模板技术(以及自己写模板引擎) 9.ajax 1 ...
- Elasticsearch-深入理解索引原理
最近开始大面积使用ES,很多地方都是知其然不知其所以然,特地翻看了很多资料和大牛的文档,简单汇总一篇.内容多为摘抄,说是深入其实也是一点浅尝辄止的理解.希望大家领会精神. 首先学习要从官方开始地址如下 ...