2

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 its 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.

Redoman
  • 3,059
  • 3
  • 34
  • 62
Rudey
  • 4,717
  • 4
  • 42
  • 84
  • See also somewhat related http://stackoverflow.com/questions/14050074/how-to-change-directshow-filter-properties-c/27931102#27931102 – rogerdpack Feb 10 '15 at 20:52

3 Answers3

4

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.

Community
  • 1
  • 1
Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • As I stated in my edit, EnumFilters is not correct either, because in the end I'm still using (parts of) the name to identify filters. And about your answer to my 1st question: can it be done without these user-unfriendly property pages? – Rudey Nov 14 '12 at 10:04
  • Not correct? It's perfectly reliable. It is just names that cannot be trusted. On the 1st question - yes, using private interfaces, specific to filters, you need to know which interface to use for specific filter, e.g. for MS filter you can look up MSDN. Wtih third party filter you typically refer to their own docs. – Roman R. Nov 14 '12 at 10:08
  • With 'not correct' I meant that my solution using EnumFilters is not correct, because it is still using names while enumerating through the filters. So even though I'm using EnumFilters, I'm still depending on those untrusty names. – Rudey Nov 14 '12 at 10:19
  • 1
    For example, if you need to look up the crossbar, instead of trusting names you just need to find the first filter (or, the closest upstream filter to the respective video capture filter) which supports `IAMCrossbar` interface. – Roman R. Nov 14 '12 at 10:21
  • +1 for the `IAMCrossbar` interface. I was using IBaseFilter all the time. ¬¬ – Rudey Nov 14 '12 at 10:26
  • I'm interested in the saving of filter properties, could you elaborate [or a link perhaps?] on "loading from/saving to stream" please? – rogerdpack Dec 30 '14 at 15:32
  • 1
    @rogerdpack: individual filters implement [`IPersistStream`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms690091%28v=vs.85%29.aspx), this is optional however when it comes to loading/saving state then it is the interface in question. You can use `Load` and `Save` methods for state operations. – Roman R. Dec 30 '14 at 18:04
  • I found out that when you're dealing with an undocumented filter, you can see what interfaces it implements by opening the filter properties in graphedit or graphbuilder and then by looking at the interfaces tab. I think this can be a good starting point for googling more about those interfaces and learning what you can do with them. – Redoman Oct 27 '20 at 06:28
0

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.

0

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.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388