Hello all
I was building a graph loader from a xml translated .GRF file and I was not able to connect the pins. I used the created code from GraphEditPlus but it did not work sometimes on ceratain graphs.
Now I found a working solution:
My first graph loader created the filters by CLSID:
// Code created by GraphEditPlus after loading the graph from GRF file.
Guid CLSID_WMVideoDecoderDMO = new Guid("{94297043-BD82-4DFD-B0DE-8177739C6D20}"); //qasf.dll
Guid CLSID_WMAudioDecoderDMO = new Guid("{94297043-BD82-4DFD-B0DE-8177739C6D20}"); //qasf.dll
...
//add WMVideo Decoder DMO
IBaseFilter pWMVideoDecoderDMO = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_WMVideoDecoderDMO));
hr = pGraph.AddFilter(pWMVideoDecoderDMO, "WMVideo Decoder DMO");
checkHR(hr, "Can't add WMVideo Decoder DMO to graph");
//add WMAudio Decoder DMO
IBaseFilter pWMAudioDecoderDMO = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_WMAudioDecoderDMO));
hr = pGraph.AddFilter(pWMAudioDecoderDMO, "WMAudio Decoder DMO");
checkHR(hr, "Can't add WMAudio Decoder DMO to graph");
Such loaded filters did not all eumerate pins! (and failed to connect as a result)
Then I realized that some filters with different names have the same CLSID:
<name>WMAudio Decoder DMO</name><guid>{94297043-BD82-4DFD-B0DE-8177739C6D20}</guid>
<name>WMVideo Decoder DMO</name><guid>{94297043-BD82-4DFD-B0DE-8177739C6D20}</guid>
To get pin enumerating filters you have to load them by DisplayName (see other created C# code from GraphEditPlus)
FriendlyName: "WMAudio Decoder DMO"
DisplayName: "@device:dmo:{2EEB4ADF-4578-4D10-BCA7-BB955F56320A}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}"
//add WMAudio Decoder DMO
IBaseFilter pWMAudioDecoderDMO = CreateFilter(@"@device:dmo:{2EEB4ADF-4578-4D10-BCA7-BB955F56320A}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}");
hr = pGraph.AddFilter(pWMAudioDecoderDMO, "WMAudio Decoder DMO");
checkHR(hr, "Can't add WMAudio Decoder DMO to graph");
//add WMAudio Encoder DMO
IBaseFilter pWMAudioEncoderDMO = CreateFilter(@"@device:dmo:{70F598E9-F4AB-495A-99E2-A7C4D3D89ABF}{33D9A761-90C8-11D0-BD43-00A0C911CE86}");
hr = pGraph.AddFilter(pWMAudioEncoderDMO, "WMAudio Encoder DMO");
checkHR(hr, "Can't add WMAudio Encoder DMO to graph");
.....
public static IBaseFilter CreateFilter(string displayName)
{
.....
hr = CreateBindCtx( 0, out bindCtx );
Marshal.ThrowExceptionForHR( hr );
int eaten;
hr = MkParseDisplayName( bindCtx, displayName, out eaten, out moniker );
Marshal.ThrowExceptionForHR( hr );
Guid guid = typeof( IBaseFilter ).GUID;
object obj;
moniker.BindToObject( bindCtx, null, ref guid, out obj );
filter = ( IBaseFilter ) obj;
....
}
To get the DisplayName you have to enumerate all categories and their filters of the system:
// Enumerate all categories:
DsDevice[] devices = DsDevice.GetDevicesOfCat( FilterCategory.ActiveMovieCategories );
foreach ( DsDevice device in devices )
{
CategoryInfo ci = new CategoryInfo( );
ci.name = device.Name;
ci.guid = GetCLSID( device );
categories.Add( ci );
}
Now foreach through all CategoryInfo with EnumFiltersByCategory(..)
public static FilterInfo[] EnumFiltersByCategory( string category_GUID, string category_friendlyName )
{
List<FilterInfo> filterInfos = new List<FilterInfo>( 128 );
DsDevice[] devices = DsDevice.GetDevicesOfCat( new Guid( category_GUID ) );
foreach ( DsDevice device in devices )
{
FilterInfo fi = new FilterInfo( );
fi.name = device.Name; // friendlyName
fi.displayName = device.DevicePath;
fi.guid = GetCLSID( device );
fi.category = category_friendlyName;
filterInfos.Add( fi );
}
return filterInfos.ToArray( );
}
I hope this may help other to develop filter graphs. It took me two days research to figure that out.
Armin