免注册 (sxs) COM DirectShow 过滤器

本文关键字:COM DirectShow 过滤器 sxs 注册 | 更新日期: 2023-09-27 18:13:43

有一些问题询问如何让注册免费COM工作,这不是其中之一。我有一个DirectShow视频源过滤器(类别860BB310-5D01-11d0-BD3B-00A0C911CE86(在.Net中实现,并借助此处提供的代码的编辑版本:Maxim Kartavenkov的Pure .Net DirectShow过滤器。

我需要让ffmpeg使用免注册 COM(并排/sxs(将我的.Net DirectShow 过滤器识别为视频源。.Net框架中内置了对 COM 组件服务器的支持,因此理论上只要清单正确,ffmpeg就应该检测到筛选器。

以下是我目前清单文件相关部分的片段。

<!-- FFMPEG MANIFEST -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity name="ffmpeg.exe" version="1.0.0.0" type="win32" processorArchitecture="*"/>
<dependency>
 <dependentAssembly asmv2:codebase="DShowVideoFilter.manifest">
  <assemblyIdentity name="DShowVideoFilter" version="1.0.0.0" publicKeyToken="26A05D7C90FBA3E8"/>
 </dependentAssembly>
</dependency>
</assembly>


<!-- DIRECTSHOW FILTER MANIFEST -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity name="DShowVideoFilter" version="1.0.0.0" publicKeyToken="26A05D7C90FBA3E8" />
   <clrClass
      clsid="{65722BE6-3449-4628-ABD3-74B6864F9739}"
      progid="DShowVideoFilter.VideoCaptureFilter"
      threadingModel="Both"
      runtimeVersion="v2.0.50727"/>
   <file name="DShowVideoFilter.dll">
   </file>
   <file name="DShowVideoFilter.tlb">
     <typelib
        tlbid="{B618E67B-64C8-48E9-9F94-F13214B76808}"
        version="1.0"
        helpdir=""
        flags="hasdiskimage"/>
   </file>
</assembly>

因此,我在运行ffmpeg时没有收到任何错误(就像出现清单错误时一样( - 我相信正确配置的所有内容(与传统的 sxs com 加载相关(,我认为(未经证实(的问题是ffmpeg通过 DirectShow 的智能连接系统加载 DShow 过滤器,这需要注册过滤器和引脚。以下是我发现的一些文档,这些文档讨论了如何注册过滤器:

  • #1 注册直接显示过滤器
  • #2 实现 DllRegisterServer

现在,在Maxim Kartavenkov的DShow基类中,他会自动处理#2。这是注册实现BaseFilter的过滤器的方法的显着缩短版本。

[ComRegisterFunction]
public static void RegisterFunction(Type _type)
{
    AMovieSetup _setup = (AMovieSetup)Attribute.GetCustomAttribute(_type, typeof(AMovieSetup));
    BaseFilter _filter = (BaseFilter)Activator.CreateInstance(_type);
    string _name = _filter.Name;
    DsGuid _category = new DsGuid(_setup.Category);
    IFilterMapper2 _mapper2 = (IFilterMapper2)new FilterMapper2();
    RegFilter2 _reg2 = new RegFilter2();
    _reg2.dwVersion = (int)_setup.Version;
    _reg2.dwMerit = _setup.FilterMerit;
    _reg2.rgPins = IntPtr.Zero;
    _reg2.cPins = 0;
    IntPtr _register = Marshal.AllocCoTaskMem(Marshal.SizeOf(_reg2));
    Marshal.StructureToPtr(_reg2, _register, true);
    hr = _mapper2.RegisterFilter(_type.GUID, _name, IntPtr.Zero, _category, _instance, _register);
    Marshal.FreeCoTaskMem(_register);
}

这是方法(特别是mapper2.RegisterFilter(,它允许ffmpeg在传统上(使用 RegAsm(注册到注册表中时找到 DShow 过滤器,该方法为过滤器和引脚创建注册表项,如 #2 链接所述。

TLDR;
所以问题是,如何在清单文件中模拟RegisterFilter或智能连接注册表项的功能,以允许 sxs 上下文在搜索时找到我的 DirectShow 过滤器ffmpeg

免注册 (sxs) COM DirectShow 过滤器

几乎是询问如何使免注册COM工作的问题之一。

正如您正确所说,让它在最基本的层面上工作不是问题。 但是,清单不会生成 SxS 加载错误这一事实仅意味着它是有效的清单 XML。 若要了解它在语义上是否正确,例如查找名称、CLSID 和/或版本中缺少的依赖项或拼写错误,请在 .NET 中使用 CLSIDFromProgID 后跟本机CoCreateInstance进行测试,或在 .NET 中使用 Type.GetTypeFromCLSID/Type.GetTypeFromProgID 后跟Activator.CreateInstance进行测试。

不幸的是,对于这种情况,免注册 COM 仅适用于基本 COM 功能,例如典型类、接口代理/存根和类型库注册,并带有少量 OLE(请参阅 miscStatus 属性(。 对于 COM 本身不使用的类别或子项,必须注册。

为什么? 因为没有其他人跟随领导,甚至连COM+也没有。