当前位置:首页 > > 充电吧
[导读]DirectShow 是一个 Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。 Filter 实质是一个 COM 组件,所以学习开发 Filter 前你应该对 COM 相关知

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 必须用到以下头文件的库文件:

#include "streams.h"
#include "initguid.h"
strmbasd.lib
winmm.lib
uuid.lib
Quartz.lib   输出 AMGetErrorText 函数,如果不调用此函数,此库不是必需的。

FilterSample.def 文件的内容:
LIBRARY FilterSample.ax 
EXPORTS
; 需要定义的导出函数
DllMain PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
; 在基类中已经定义的导出函数
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE

dllmain.cpp 的代码如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "streams.h"

// BOOL APIENTRY DllMain( HMODULE hModule,
//                        DWORD  ul_reason_for_call,
//                        LPVOID lpReserved
//           )
// {
//  switch (ul_reason_for_call)
//  {
//  case DLL_PROCESS_ATTACH:
//  case DLL_THREAD_ATTACH:
//  case DLL_THREAD_DETACH:
//  case DLL_PROCESS_DETACH:
//    break;
//  }
//  return TRUE;
// }

STDAPI DllRegisterServer()
{
  return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
  return AMovieDllRegisterServer2(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason,   LPVOID lpReserved)
{
  return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}


编译时,可能会遇到如下问题: 1>e:worksourcecodetestcodefiltersampledllmain.cpp(23) : error C3861: “AMovieDllRegisterServer2”: 找不到标识符 1>e:worksourcecodetestcodefiltersampledllmain.cpp(27) : error C3861: “AMovieDllRegisterServer2”: 找不到标识符 编译错误, 一般是头文件没有包含。所以,包含: #include "streams.h"
1>dllmain.obj : error LNK2019: 无法解析的外部符号 _AMovieDllRegisterServer2@4,该符号在函数 _DllRegisterServer@0 中被引用 1>dllmain.obj : error LNK2019: 无法解析的外部符号 _DllEntryPoint@12,该符号在函数 _DllMain@12 中被引用 1>E:WorkSourceCodeTestCodeFilterSampleDebugFilterSample.dll : fatal error LNK1120: 2 个无法解析的外部命令 链接错误, 一般是库文件没有包含。所以,库输入中包含: strmbasd.lib
1>正在链接... 1>strmbasd.lib(wxdebug.obj) : error LNK2019: 无法解析的外部符号 __imp__timeGetTime@0,该符号在函数 "void __stdcall DbgInitialise(struct HINSTANCE__ *)" (?DbgInitialise@@YGXPAUHINSTANCE__@@@Z) 中被引用 1>strmbasd.lib(wxutil.obj) : error LNK2001: 无法解析的外部符号 __imp__timeGetTime@0 1>strmbasd.lib(wxutil.obj) : error LNK2019: 无法解析的外部符号 __imp__timeSetEvent@20,该符号在函数 "unsigned int __cdecl CompatibleTimeSetEvent(unsigned int,unsigned int,void (__stdcall*)(unsigned int,unsigned int,unsigned long,unsigned long,unsigned long),unsigned long,unsigned int)" (?CompatibleTimeSetEvent@@YAIIIP6GXIIKKK@ZKI@Z) 中被引用 1>E:WorkSourceCodeTestCodeFilterSampleDebugFilterSample.dll : fatal error LNK1120: 4 个无法解析的外部命令 包含  winmm.lib, 可以解决 timeGetTime 链接错误的问题
增加头文件 FilterSample.h,其内容如下: 其中 GUID 的生成,需要用到下面的工具: Microsoft SDKsWindowsv7.1Binguidgen.exe

#ifndef _FILTER_SAMPLE_H_
#define _FILTER_SAMPLE_H_

// {33B57142-BD07-4a77-AE91-A8F6C24A8F40}
DEFINE_GUID(CLSID_FilterSample, 
    0x33b57142, 0xbd07, 0x4a77, 0xae, 0x91, 0xa8, 0xf6, 0xc2, 0x4a, 0x8f, 0x40);

class CFilterSample: public CCritSec, public CBaseFilter
{
public:
  CFilterSample(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *hr);
  virtual ~CFilterSample(); 
  static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr); 
  CBasePin *GetPin(int n);
  int GetPinCount();  
};

#endif


FilterSample.cpp 的内容如下:

// FilterSample.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "streams.h"
#include "initguid.h"

#include "FilterSample.h"

// Using this pointer in constructor
#pragma warning(disable:4355 4127)

//////////////////////////////////////////////////////////////////////////
// AMOVIESETUP_FILTER 描述一个 Filter
// AMOVIESETUP_PIN 描述 pin
// AMOVIESETUP_MEDIATYPE 描述数据类型
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
  &MEDIATYPE_NULL,         // Major CLSID
  &MEDIASUBTYPE_NULL       // Minor type
};

const AMOVIESETUP_PIN psudPins[] =
{
  { 
    L"Input",             // Pin's string name
    FALSE,                // Is it rendered
    FALSE,                // Is it an output
    FALSE,                // Allowed none
    FALSE,                // Allowed many
    &CLSID_NULL,          // Connects to filter
    L"Output",            // Connects to pin
    1,                    // Number of types
    &sudPinTypes          // Pin information
  },
  {
    L"Output",            // Pin's string name
    FALSE,                // Is it rendered
    TRUE,                 // Is it an output
    FALSE,                // Allowed none
    FALSE,                // Allowed many
    &CLSID_NULL,          // Connects to filter
    L"Input",             // Connects to pin
    1,                    // Number of types
    &sudPinTypes          // Pin information
  }
};

const AMOVIESETUP_FILTER sudInfTee =
{
  &CLSID_FilterSample,           // CLSID of filter
  L"Filter Sample Test Lib",     // Filter's name
  MERIT_DO_NOT_USE,              // Filter merit
  2,                             // Number of pins
  psudPins                       // Pin information
};
//////////////////////////////////////////////////////////////////////////

CFactoryTemplate g_Templates[1] = 
{
  {
    L"Filter Sample",                // Name
    &CLSID_FilterSample,             // CLSID
    CFilterSample::CreateInstance,   // Method to create an instance of MyComponent
    NULL,                            // Initialization function
    &sudInfTee                       // Set-up information (for filters)
  }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);


CFilterSample::CFilterSample(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *hr)
  :CBaseFilter(NAME("Filter Sample"), pUnk, this, CLSID_FilterSample)
{
}

CFilterSample::~CFilterSample()
{
} 

CBasePin * CFilterSample::GetPin(int n)
{
  return NULL;
}
int CFilterSample::GetPinCount()
{
  return 0;
}

CUnknown * WINAPI CFilterSample::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
  CFilterSample *pFilter = new CFilterSample(NAME("Filter Sample"), pUnk, pHr);
  if (pFilter== NULL)
  {
    *pHr = E_OUTOFMEMORY;
  }
  return pFilter;
}


编译时,可能遇到如下问题: 1>FilterSample.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall CBaseFilter::CBaseFilter(wchar_t const *,struct IUnknown *,class CCritSec *,struct _GUID const &)" (??0CBaseFilter@@QAE@PB_WPAUIUnknown@@PAVCCritSec@@ABU_GUID@@@Z),该符号在函数 "public: __thiscall CFilterSample::CFilterSample(wchar_t *,struct IUnknown *,long *)" (??0CFilterSample@@QAE@PA_WPAUIUnknown@@PAJ@Z) 中被引用 1>E:WorkSourceCodeTestCodeFilterSampleDebugFilterSample.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 SDKsWindowsv7.1Bingraphedt.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:FiltersFilterSample.ax(具体的目录与执行 regsvr32 时 FilterSample.ax 所在的路径相关)。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭