There are questions asking on how to get Registration free COM working, and this is not one of those. I have a DirectShow video source filter (catagory 860BB310-5D01-11d0-BD3B-00A0C911CE86
) implemented in .Net
with the help of an edited version of the code available here: Pure .Net DirectShow Filters by Maxim Kartavenkov.
I need to get ffmpeg
to recognize my .Net
DirectShow filter as a video source using Registration Free COM (Side by Side / sxs). Built into the .Net
framework is support for COM component servers, so theoretically as long as the manifests are correct, ffmpeg
should detect the filters.
Here is a snippet of the relevant sections of my manifest files currently.
<!-- 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>
So, I get no errors when running ffmpeg
(like you would if there was a manifest error) - and I am confident that everything that is configured correctly (related to traditional sxs com loading), the problem I think (unconfirmed) is that ffmpeg
loads DShow filters via DirectShow's intelligent connect system, which requires the filter and pins to be registered. Here are some documents that talk about how filters need to be registered that I've found:
Now, in Maxim Kartavenkov's DShow base classes, he takes care of #2 automatically. Here is a significantly shortened version of the method that registers the filters implementing 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);
}
That is the method (particularly mapper2.RegisterFilter
) that allows ffmpeg
to find the DShow filter when it is registered traditionally (with RegAsm
) into the registry, which creates registry keys for the filter and pins as described by #2 link.
tldr;
So the question is, how to emulate the function of RegisterFilter
or the intelligent connect registry entries this within a manifest file as to allow the sxs context to find my DirectShow filter when ffmpeg
searches for it.
This is almost one of those questions asking on how to get registration-free COM working.
As you correctly say, it's not a problem with getting it to work at the most basic level. However, the fact that the manifest doesn't generate SxS loading errors only means it's a valid manifest XML. To know if it's semantically correct, such as finding missing dependencies or typos in names, CLSIDs and/or versions, test with CLSIDFromProgID
followed by CoCreateInstance
natively, or Type.GetTypeFromCLSID
/Type.GetTypeFromProgID
followed by Activator.CreateInstance
in .NET.
Unfortunately for cases like this, registration-free COM is only applicable for base COM functionality, like typical class, interface proxy/stub and type library registration, with a tiny bit of OLE (see miscStatus attributes). For categories or subkeys not used by COM itself, registration is necessary.
Why? Because no one else followed lead, not even COM+.