显示标签为“DirectShow”的博文。显示所有博文
显示标签为“DirectShow”的博文。显示所有博文
0
Posted on 01:28:00 by Unknown and filed under

  在用 DirectShow 写程序的时候,被 Renderer Filter 的问题折腾了好几次,有的问题一开始不了解还觉得莫名其妙,虽然说到现在也不是完全明白,但好歹解决了。

  我曾经遇到的问题有:

  1. 将一个解码器封装成 ActiveX 控件,但是遇到刷新问题,就是拖动窗口的时候才刷新。奇怪的是,在有的机器上就没有问题,即使配置一样,而且和 IE 版本也没什么关系。
  2. 在一个桌面播放器中同时播放4个视频,都附着到一个窗口上,但是左上角一路异常,总是打开比其他几个慢,而且拖动窗口时会反应迟缓,总之就是它特殊,但是程序中完全是一样对待的。
  3. 使用远程桌面连接的时候,看不到播放的视频。这个是小事。

  以上问题通过搜索,主要解决方法有:

  1. 折腾 OnDraw(), OnPaint(), OnEraseBkGnd() 这几个函数,要 put_owner 在窗体上,由窗体的 WM_PAINT 来刷新。
  2. 修改控件属性,添加处理消息。
  3. 不使用默认的 Renderer Filter,手动使用 VMR-9。

  也是我水平不高,还就替换 Renderer Filter 好用,手动刷新的方法在上面第二个问题的时候就不怎么好使。而且 DirectShow 提供了多个 Renderer Filter,换一个更高级的往往能解决问题。

  但是,我只是知道,比如 VMR-9 中自己管理了刷新机制,所以上述这些问题都能解决,但是如何处理的还不明白。

  DirectShow 中自带的 Renderer Filter 挺多的,甚至还有同名但是 CLSID 不同的,在 MSDN: Choosing the Right Video Renderer 中有一个较详细的介绍。通过以下 CLSID 以及 MSDN 上的资料应该能回答有关 Renderer Filter 的疑惑。

  • CLSID_OverlayMixer // {CD8743A1-3736-11d0-9E69-00C04FD7C15B}
  • CLSID_VideoRenderer // {70E102B0-5556-11CE-97C0-00AA0055595A}
  • CLSID_VideoRendererDefault // {6BC1CFFA-8FC1-4261-AC22-CFB4CC38DB50}
  • CLSID_VideoMixingRenderer // {B87BEB7B-8D29-423f-AE4D-6582C10175AC}
  • CLSID_VideoMixingRenderer9 // {51b4abf3-748f-4e3b-a276-c828330e926a}
  • CLSID_EnhancedVideoRenderer // {FA10746C-9B63-4b6c-BC49-FC300EA5F256}

  以上 CLSID 都可以在 Windows SDK 中的 uuids.h 找到。

   Overlay Mixer 不怎么用,Enhanced Video Renderer (EVR) 是 Vista 之后的,还没用过。VMR-9 最强大,如果能用(系统软硬件支持),一般能解决问题。VMR-7 以及更早的,我也分不太清楚细致的区别,其中 VMR-7 本身就有两个Filter,其中一个还和 Video Renderer Filter 的 friendly name 相同,都是 "Video Renderer"。

  因为 Renderer 接收的是 RGB/YUV 数据,然后交由显卡处理显示,所以显卡的差别会导致性能的差别。此外,VMR-9 因为有更强的功能和更好的质量,所以会占用更多的资源,在不同的显卡上,可能会有实例 (instance) 的限制,比如只能显示 7-8 个窗口,而 VMR-7 则限制小很多。

  在陆其明的书上有一些介绍,网上很多文章都是这本书上相应章节内容,搜一下"关于VMR7、VMR9、Video Renderer"就能找到。

  一句话总结,系统资源允许的情况下,使用高级的 Renderer Filter,否则就只能使用较低版本的 Renderer Filter,手动解决出现的种种问题。

2
Posted on 15:45:00 by Unknown and filed under ,

  我编写了一个 Windows Mobile 下的 Directshow Filter,但是如何注册却成了问题。在 Windows 下面只要使用 Regsvr32 即可,但是这个程序在 Windows Mobile 的模拟器中不存在。

  首先参考 MSDN:Registering DirectShow FiltersCreating a DLL in DirectShow

  为了偷懒,我决定使用 eMbedded Visual C++ 4.0(下载)附带的 RegsvrCE.exe 来注册 DLL。把 regsvrce.exe 和 dllname.dll 一起复制到模拟器中,设法运行(比如编一个小程序)"regsvrce.exe dllname.dll"即可。

  中间我还遇到了一个小问题,当我注册一个 Filter 的时候,返回错误:

Loadlibrary("dllname.dll") failed. GetLastError returns 7e.

  错误代码 7e 的含义是没有找到特定的模块,应该是这个 DLL 调用了当前系统中不存在的 DLL。经过检查发现是我在编译 Filter 的时候,运行时库选择了"多线程 DLL(/MD)",而它所需要的 msvcr90.dll 在模拟器中似乎不存在。于是我从 Visual Studio 目录下面的把相应的 msvcr90.dll 复制到模拟器然后注册,就可以注册我的 Filter 了。如果不想复制这个文件,把运行时库改为"多线程(/MT)"也可以。

  如何在程序中使用"RegsvrCE.exe",下面有一个例子:


SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = _T("regsvrce.exe");
ShExecInfo.lpParameters = _T("Program Files\\H264VideoDecoder\\H264VideoDecoder.ax");
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);

  其实还有一个好的方法,就是在路其明的《DirectShow 开发指南》第10页介绍的方法。在应用程序中使用 LoadLibrary 装载这个 Filter 文件,找到它的导出函数 DllRegisterServer(或 DllUnregisterServer)的入口地址,然后执行它即可。不过书中的参考代码有些错误,就是在 typedef 的时候,下面是修改后的代码:


BOOL RegisterFilter(LPCWSTR inFilterAx)   
{   
    typedef HRESULT (WINAPI * REGISTER_FUNC) (void);   
    REGISTER_FUNC   MyFunc = NULL;   
   
    HMODULE hModule = ::LoadLibrary(inFilterAx);   
    if (hModule)   
    {   
        MyFunc = (REGISTER_FUNC) GetProcAddress(hModule, _T("DllRegisterServer"));   
        BOOL pass = (MyFunc != NULL);   
        if (pass)   
        {   
            MyFunc();  
        }   
        ::FreeLibrary(hModule);   
        return pass;   
    }   
    
    return FALSE;   
}  

  使用的时候,只需要调用:


RegisterFilter(_T("Storage Card\\H264VideoDecoder.ax"));
0
Posted on 10:22:00 by Unknown and filed under

  从原来的 DirectX Summer 2004 换到 Windows SDK 以后,发现在 GraphEdit 中在 Filter 上点右键不能查看属性了。

  需要将 SDK 中的 proppage.dll 文件注册一下:regsvr32 ...\proppage.dll

0
Posted on 00:48:00 by Unknown and filed under ,

  今天重新配置了 Visual Studio 2008 + Windows SDK 6.1,编译 BaseClasses 很轻松通过。但是在编译之前写的一个程序的时候却提示:

...\directshow\baseclasses\refclock.h(80) :
                        error C2061: 语法错误 : 标识符"CAMSchedule"      
...\directshow\baseclasses\refclock.h(139) : 
                        error C2143: 语法错误 : 缺少";"(在"*"的前面)   

之类的错误。

  问题出在 refclock.h 引用的 Schedule.h 文件在 Include 和 BaseClasses 重复出现了,而且内容不一致。所以需要在引用路径的时候把 BaseClasses 的路径提前。

4
Posted on 03:17:00 by Unknown and filed under ,

对于刚刚接触 DirectShow 的人来说,安装配置是一个令人头疼的问题,经常出现的情况是最基本的 baseclass 就无法编译。

一开始我也为此费了很大的功夫,比如说修改代码、修改编译选项使其编译通过。因为大家 Visual Studio 的版本与 DirectShow 的版本各不相同,导致问题多种多样。网上的参考也不可尽信,往往花费了大量的时间和精力,程序仍没有编译通过,而丧失学习 DirectShow 的兴趣和信心。

我在 Visual Stdio 6.0,2003,2005,2008 都尝试过了配置 DirectShow,基本可以达到不需要修改代码就可以编译通过。经验就是,要配合 Visual Studio 的版本选择不同的 DirectShow 的版本。一般来说,要选取 比同时期的 Visual Studio 略晚发行的 DirectShow 版本。(我觉得,微软至少要对新发行的 DirectShow SDK 在当前主流的编译环境中测试才对,所以一般这种匹配都是很容易一下子编译通过。)

Visual C++ 6.0

陆其明老师的《DirectShow 开发指南》是一本不错的书,使用的环境就是 VC 6.0。按照我刚才的理论,几乎所有的 DirectShow 版本都可以容易的安装在 VC 6 上,因为它太古老了。不过,要是安装最新的 SDK 反而不行,因为 VC 6 的编译器问题很多,对标准支持得也不是很好,所以导致最新的 SDK 无法编译。

陆的书上所用的版本其实是 dx9sdk.exe (2002.12.19),我这里给出的是微软官方的链接(他们把所有的版本都保留了),需要正版验证才能下载(应该不成问题吧...)。

我建议使用 DirectX SDK Summer 2004 版本,这个版本是最后一个整合 DirectShow 的 DirectX SDK版本。

之后微软把 DirectShow 分离出来了,比如需要安装 DirectX SDK April 2005 版本再加上 DirectX SDK February 2005 Extras。也就是说,DirectX 已经不含 DirectShow,这个时候(2005年)它被包含在 Extras 里面。所以安装了 Extras 基本上就可以进行 DirectShow 开发了。

Visual Studio 2003

这个版本建议安装 Summer 2004 这个版本。Extras 也没问题。

Visual Studio 2005

这个版本我用的不是很多,印象中安装 Summer 2004 没问题,甚至更低的 9.0b 也没问题。安装很新的版本就会出现我说的那种太超前反而编译不了的现象。

大概到 2006 年,DirectShow 就被包含在了 Windows Platform SDK 中。不知道最新的 Platform SDK 对 VS2005 支持地如何,我没有去试。之前有一个版本需要修改一些代码才能编译。

Visual Studio 2008

非常简单,安装最新版的 DirectX SDK June 2008Platform SDK (2006.03.15) 即可。另外,Platform SDK 的后续版本似乎叫 Windows SDK,内含的 Media Foundation 似乎要取代 DirectShow。(Windows SDK for Windows Server 2008 and .NET Framework 3.5 2008.02.05)

进行环境配置

如果 DirectShow 的版本比 VS 要新,则相应的头文件和库文件就会自动配置,否则就要手动添加。

如果安装的 DirectShow 比较早,那么在 baseclasses 里面就会有相应的工程文件,打开编译即可。如果安装的是 Platform SDK 就会只有一个 makefile,注意到在安装完 Platform SDK 以后,开始菜单会有一些进入不同编译环境的快捷方式,选一个想编译的版本进入,然后在 baseclasses 下 输入 nmake,就会自动编译了。

还需要注意的就是一些库的引用、编译链接的选项等等,在出现问题的时候搜索就行,一般不是大问题。

2008-07-29 Up:
有一篇文章可以在遇到编译错误的时候参考:Some DirectShow Samples Break in Visual Studio 2005