问题
I'm working on an application that helps users configure their TV tuner cards. Basically the user selects a device, and the application generates a graph file (.GRF) as output. However, there are a few settings the user should be able to change. These settings include the video standard (PAL, NTSC, SECAM), video input (Tuner, Composite, SVideo), and so on.
In GraphEdit this can be accomplished by right clicking the desired filter, and select "Filter Properties...". However, I have no clue how to achieve the same in code.
Question 1: How do I change properties of DirectShow filters in code?
Because I use ICaptureGraphBuilder2::RenderStream to build my graph, I'm only holding references to the source filter and renderer. Most of the properties I would like to be able to change are found on other filters, such as the crossbar filter, which is added automatically by the RenderStream method.
Question 2: How do I obtain references to other filters in my graph, so I can change their properties?
Note: I won't use FindFilterByName because my application is supposed to work with most of the TV tuner cards, and every card as a different name.
Edit: I have found a way to obtain a reference to these filters by enumerating through EnumFilters. I then use QueryFilterInfo on every filter to find it's name. This is different than using FindFilterByName, because I can now use Contains to find certain words (like "Crossbar"). However, I already have an example where the crossbar filter is named ("... Xbar"), so I'm still looking for a more generic way to do this. I wish I could find filters by their category...
By the way, I'm currently using the DirectShow.Net library, but I believe the approach should be the same as with the C++ library. However, I don't fully understand the C++ syntax, so if you are planning to post (a reference to) a code example, it would be a big help if it were in C# or VB.NET.
Solution: See the accepted answers comments. I need to cast the filters which properties needs to be changed to their respective interface. For example, the crossbar filter needs to be casted to the IAMCrossbar interface. With this interface I can now change all crossbar related properties.
回答1:
2 - EnumFilters
is the correct approach. You should not trust names, because they are solely for the purpose of being developer friendly to be easily able to distinguish between filters in the graph, but they are not promised to be globally persistent and consistent. The same applies to pin names.
1 - in native API you create UI with property pages with OleCreatePropertyFrame function. See also Displaying a Filter's Property Pages on this.
I don't think DirectShow.NET has a wrapper over it, so you need to call this API via P/Invoke like this: C# : How to use directshow.net to show this dialog?
Settings are filter specific and are typically exposed via private interfaces, so there is no uniform access. Still, if a filter supports loading from/saving into stream, you can save/restore settings at once in a uniform way. The way GraphEdit saves/loads with .GRF files.
回答2:
2 - have you tried looking into the DeviceName provided by the filters IMoniker? I personally found it quite useful for blacklisting filters, and it seems you can tell a little bit about the device type through its IMoniker::DeviceName . I'm not sure if it's enough information for your needs, but it might be a start.
回答3:
for question one, to "find" the auto inserted crossbar filter, use ICaptureGraphBuilder2::FindInterface then you can either display its native property page "gui popup" (see Roman's answer) and allow users to control it using that, or use the normal crossbar enumerate/select API to do it programmatically.
来源:https://stackoverflow.com/questions/13375690/directshow-how-to-change-filter-properties