虽然网上已有很多关于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流程 + 源代码(内附详细注释)的更多相关文章

  1. DirectShow中写push模式的source filter流程 + 源码(内附具体凝视)

    尽管网上已有非常多关于DirectShow写source filter的资料.只是非常多刚開始学的朋友总说讲的不是非常清楚(可能当中作者省略了很多他觉得简 单的过程).读者总希望看到象第一步怎么做,第 ...

  2. 从1.6W名面试者中收集的Java面试题精选汇总(内附知识脑图)

      本篇的面试题是接之前读者的要求,发出来的. 首先,声明下,以下知识点并非全部来自BAT的面试题. 如果觉得在本文中笔者总结的内容能对你有所帮助,可以点赞关注一下. 本文会以引出问题为主,后面有时间 ...

  3. 【Filter 不登陆无法访问】web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面的功能

    在web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面,而重定向到登陆界面的功能. 项目是用springMVC+spring+hibernate实现 (和这个没有多大关系) 第一步: 首先 ...

  4. 在mybatis中写sql语句的一些体会

    本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...

  5. 在DirectShow中支持DXVA 2.0(Supporting DXVA 2.0 in DirectShow)

    这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档.并准备记录一下用ffmpeg实现dxva2,将在第三篇写到.这是第二篇.,英文原址:https://msdn.microso ...

  6. 安卓中的Model-View-Presenter模式介绍

    转载自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0425/2782.html 英文原文:Introduction to M ...

  7. COM中的线程模式

      Choosing the threading model for an object depends on the object's function. An object that does e ...

  8. (转)MVC中的Repository模式

    1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...

  9. php中的MVC模式运用

    [size=5][color=Red]php中的MVC模式运用[/color][/size] 首先我来举个例子: 一个简单的文章显示系统 简单期间,我们假定这个文章系统是只读的,也就是说这个例子将不涉 ...

随机推荐

  1. centos 下安装 Jre 及 selenium

    下载软件包 下载链接: jre-7u55-linux-i586.tar.gz : http://pan.baidu.com/s/14cjds selenium-server-standalone-2. ...

  2. win7 重装 docker 启动后无法启动错误解决

    描述 win7 重新安装Docker 后启动  Docker Quickstart Terminal 出现如下错误 Starting "default"... (default) ...

  3. xBIM 插入复制功能

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  4. java递归

    package com.sun.test; import java.util.ArrayList; import java.util.List; /** * 递归 * */ public class ...

  5. ChineseUtils

    这里获得汉字的拼音使用了pinyin4j这个插件,因为多音字的原因效果并不理想 /** * 获得汉字拼音 * @param name * @return */ @SuppressWarnings(&q ...

  6. youtube视频字幕下载

    视频下载 安装TamperMonkey插件 字幕下载 http://mo.dbxdb.com/setting.html https://zhuwei.me/y2b/

  7. git添加本地仓库与远程仓库连接

    在本地建立一个文件夹,需要与远程git仓库进行连接,具体方法: <1>首先进入所在文件目录执行:  git init 初始化git,紧接着 git  add . git commit -m ...

  8. iOS 8 UIAlertController 和 UIAlertAction

    将alertView 和 actionSheet 封装在UIAlertController 里面化整为零,使开发者更便利 当我们一味的追求高内聚,低耦合的时候,伟大的苹果反其道而行之,这也告诉了我们一 ...

  9. Windows Server 2016-存储新增功能

    本章给大家介绍有关Windows Server 2016 中存储方面的新增功能,具体内容如下: 1.Storage Spaces Direct: 存储空间直通允许通过使用具有本地存储的服务器构建高可用 ...

  10. npm注意事项(附带Vue-cli安装)

    下载完nodeJS后,可选择更改配置目录 1.npm config set prefix "D:\node\node-global"<!--配置全局安装目录--> 2. ...