免注册 (sxs) COM DirectShow 过滤器

Registration free (sxs) COM DirectShow filter

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

我需要 ffmpeg 将我的 .Net DirectShow 过滤器识别为使用免注册 COM(并排/sxs)的视频源。 .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 过滤器,这需要注册过滤器和引脚。以下是我发现的一些关于如何注册过滤器的文档:

现在,在 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 link.

所述的过滤器和引脚

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

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

正如您所说的那样,让它在最基本的级别上运行不是问题。但是,清单不会生成 SxS 加载错误这一事实仅意味着它是一个有效的清单 XML。要知道它在语义上是否正确,例如在名称、CLSID and/or 版本中查找缺失的依赖项或拼写错误,请使用 CLSIDFromProgID 后跟 CoCreateInstance 本机或 Type.GetTypeFromCLSID/[= 进行测试13=] 后跟 .NET 中的 Activator.CreateInstance

不幸的是,对于这种情况,免注册 COM 仅适用于基本 COM 功能,如典型 class、接口 proxy/stub 和类型库注册,带有少量 OLE(请参阅miscStatus 个属性)。对于COM本身不使用的类别或子键,需要注册。

为什么?因为没有其他人效仿,甚至 COM+ 也没有。