尽管网上已有非常多关于DirectShow写source filter的资料。只是非常多刚開始学的朋友总说讲的不是非常清楚(可能当中作者省略了很多他觉得简

单的过程)。读者总希望看到象第一步怎么做,第二步怎么做....这种demo。事实上写你的第一个filter是有一定难度的,仅仅要过了这关以后

就easy多了。

因为近期须要自己写一个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);

我在源码里面都家了比較具体的凝视,參考源码一起看easy明确。

事实上这个filter没做别的,就相当与将sdk下的PushSource样例自己再写了一遍,主要是为了说明这个过程。
到这里相信你应该有个大概的概念了。那么恭喜!

我也写累了,假设对大家有帮助就找个时间再将写pull拉
模式的过程也写出来。

DirectShow中写push模式的source filter流程 + 源码(内附具体凝视)的更多相关文章

  1. DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)

    虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简 单的过程),读者总希望看到象第一步怎么做,第二步怎 ...

  2. eclipse中导入外部包却无法查看对应源码或Javadoc的入坑指南

    eclipse中导入外部包却无法查看对应源码或Javadoc的 入坑指南 出现这个错误的原因是,你虽然导入了.jar包,但没有配置对应的Javadoc或源码路径,所以在编辑器中无法查看源 码和对应AP ...

  3. Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析

    Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析 生鲜电商搜索引擎的特点 众所周知,标准的搜索引擎主要分成三个大的部分,第一步是爬虫系统,第二步是数据分析,第三步才 ...

  4. c# winform 中的 工具栏自动隐藏 splitter用法 带源码

    c# winform 中的 工具栏自动隐藏 splitter用法 带源码 代码下载地址 http://download.csdn.net/detail/simadi/7649313

  5. 量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python)(转)

    量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python) 原文地址:http://blog.csdn.net/u012234115/article/details/728300 ...

  6. Java中的容器(集合)之HashMap源码解析

    1.HashMap源码解析(JDK8) 基础原理: 对比上一篇<Java中的容器(集合)之ArrayList源码解析>而言,本篇只解析HashMap常用的核心方法的源码. HashMap是 ...

  7. beego 0.9.0 中智能路由AutoRouter的使用方法及源码解读

    了解beego的开发者肯定知道,beego的路由设计来源于sinatra,原来是不支持自动路由的,每一个路由都要自己配置的,如: type MainController struct { beego. ...

  8. MapReduce中一次reduce方法的调用中key的值不断变化分析及源码解析

    摘要:mapreduce中执行reduce(KEYIN key, Iterable<VALUEIN> values, Context context),调用一次reduce方法,迭代val ...

  9. <Flume><Source Code><Flume源码阅读笔记>

    Overview source采集的日志首先会传入ChannelProcessor, 在其内首先会通过Interceptors进行过滤加工,然后通过ChannelSelector选择channel. ...

随机推荐

  1. 【FTP】使用org.apache.commons.net.ftp.FTPClient 实现FTP的上传下载

    在此之前,在项目中加上FTP的架包 第一步:配置FTP服务器的相关配置 FtpConfig.java  实体类(配置类) package com.sxd.ftp; public class FtpCo ...

  2. Ceph源码解析:概念

    Peering:一个PG内的所有副本通过PG日志来达成数据一致的过程.(某PG如果处于Peering将不能对外提供读写服务) Recovery:根据Peering的过程中产生的.依据PG日志推算出的不 ...

  3. github之无命令可视化界面操作——GitHub DeskTop

    Git是Linuxs之父Lunus用C语言写的一个非常好用的分布式版本控制系统. GitHub可以给我们提供免费的代码仓库,并用Git可以在上面提交代码并进行版本控制.使用Git一般要安装Git ,并 ...

  4. lumisoft邮件内容中文乱码问题

    修改MIME_b_Text.cs文件,红色字体为添加的部分,绿色为修改部分 private static Encoding m_pEncoding = Encoding.Default; #regio ...

  5. 正确遍历删除List中的元素方法(推荐)

    遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...

  6. VLC 源代码结构

    x64 sudo apt-get install -y liblua5.2-dev libmad0-dev libavutil-dev libavcodec-dev libavformat-dev l ...

  7. 探寻C++最快的读取文件的方案

    https://www.byvoid.com/blog/fast-readfile/ 在竞赛中,遇到大数据时,往往读文件成了程序运行速度的瓶颈,需要更快的读取方式.相信几乎所有的C++学习者都在cin ...

  8. IBM-ETP 实训项目前一天

    明天就要开始项目了,实训项目,虽然之前做了几个项目,但是明天就要被一个有着8年项目经验的大牛带着做这个项目了.心中还是不免有点兴奋的.希望能学到更多的东西,来充实自己. 自己也搭建了一个小的demo ...

  9. UITextField,UITextView字数限制

    UITextField,UITextView字数限制 主要是使用他们的两个代理方法 //标题限制在 30个字以内 - (BOOL)textField:(UITextField *)textField ...

  10. Openerp开发进销存系统总结

    转自 :http://blog.sina.com.cn/s/blog_7cb52fa80101ngt8.html 差不多用了2个星期的闲余事件,对于openerp v7.0进行了学习和应用开发.细节总 ...