Multimedia dedicated weblog.

How filters are described in the Registry database

February 16th, 2008 Posted in DirectShow

While working on the GraphStudio project I have come upon a problem that might be worth writing an article about. The point was to find as much information about filters as possible using the data stored in the registry.

COM OBJECTS

Basically DirectShow filters are COM objects. This means they need to be registered according to COM rules so they could be instantiated using the standard means of the CoCreateInstance method. For the purpose of this article I will be using the MONOGRAM AAC Encoder filter which has a GUID of {88F36DB6-D898-40b5-B409-466A0EECC26A}.

COM objects are registered in the HKEY_CLASSES_ROOT\CLSID registry key. With the object’s CLSID as the key name and it’s name (string value) as the default key value. The AAC Encoder filter would thus have a HKEY_CLASSES_ROOT\CLSID\{88F36DB6-D898-40B5-466A0EECC26A} key and it’s default value would be the name. You can see this on the picture below.

Each COM object also has an InprocServer32 subkey where the path to the library is stored.

FILTERS

Each filter also needs to be registered with the Filter Mapper object. The registration process is handled by provided interface so it is easy and straightforward, but there is no interface to retrieve information once the filter is already registered. So if you want to get detailed information on a filter you need to get your hands a little bit dirty.

In the registry there is a COM object named “ActiveMovie Filter Class Manager” and has the GUID of {083863F1-70DE-11D0-BD40-00A0C911CE86} which contains records of all registered filters.

The values for these records can be read by using the IMoniker interface which describes filters when enumerating either from the System Device Enumerator or IFilterMapper2. Each record contains the following values:

  • FriendlyName - name of the filter
  • CLSID - GUID of the filter
  • FilterData - binary encoded pin information and mediatype information

If you need to see an example of how to use the System Device Enumerator, you can follow this MSDN article.

The IMoniker interface can be identified by it’s DisplayName. This string value can give additional information on the type of filter. It can look like this.

@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{88F36DB6-D898-40B5-B409-466A0EECC26A}

I have not found any documentation on this so these are just plain guesses and observations. If you find any mistakes please do report them. The @device part appears to be constant for all types of filters. Then the next part can have the following options:

  • :sw: - classic DirectShow filter
  • :dmo: - DMO object
  • :cm: - ACM or ICM
  • :pnp: - plug & play device filter

There is also a KS-Proxy type of filters but I did not have any KS-Proxy devices installed so I can’t tell what substring it has :-\.

The rest of the string may contain filter category CLSID and filter CLSID or name but it is not mandatory and you should not rely on that. But you can be sure that if there are multiple identical devices plugged into the system board they will have a different DisplayName.

It is important to realize that not all filters can be instantiated by the CoCreateInstance method. Classic DirectShow filters should work with no problems but if you want to instantiate a plug & play device filter you need to use the IMoniker::BindToObject method. That’s why it is a good practice to keep the display name as a way to identify favorite filters.

To find an IMoniker object identified by a DisplayName you can use the MkParseDisplayName function.

PINS & MEDIA TYPES

Information about pins and mediatypes for a filter is encoded in binary form in the FilterData field. Again… I could not find any documentation on the meaning of these bytes so a little observation and googling revealed these results.

The FilterData for MONOGRAM AAC Encoder may look like this:

(B) = BYTE
(DW) = DWORD
(QW) = QUADWORD
(G) = GUID
------------------------------
Header
------------------------------
0000 | 02 00 00 00 00 00 60 00 - ......`. - (DW)Version, (DW)Merit
0008 | 02 00 00 00 00 00 00 00 - ........ - (DW)Count1, (DW)Count2
------------------------------
Pins : Header + TypesHeader
------------------------------
0010 | 30 70 69 33 00 00 00 00 - 0pi3.... - (B)Index, "pi3", (DW)Flags
0018 | 00 00 00 00 01 00 00 00 - ........ - (DW)Unknown, (DW)Type-Count
0020 | 00 00 00 00 00 00 00 00 - ........ - (QW)Unknown
------------------------------
Types for pin 0
------------------------------
0028 | 30 74 79 33 00 00 00 00 - 0ty3.... - (B)Index, "ty3", (DW)Unknown
0030 | 60 00 00 00 70 00 00 00 - `...p... - (DW)Maj-Offset, (DW)Sub-Offset
------------------------------
Header for pin 1
------------------------------
0038 | 31 70 69 33 08 00 00 00 - 1pi3....
0040 | 00 00 00 00 01 00 00 00 - ........
0048 | 00 00 00 00 00 00 00 00 - ........
------------------------------
Types for pin 1
------------------------------
0050 | 30 74 79 33 00 00 00 00 - 0ty3....
0058 | 60 00 00 00 80 00 00 00 - `.......
------------------------
MediaTypes
------------------------
0060 | 61 75 64 73 00 00 10 00 - auds.... - (G) Majortype or Subtype
0068 | 80 00 00 AA 00 38 9B 71 - .....8.q
0070 | 01 00 00 00 00 00 10 00 - ........ - (G) Majortype or Subtype
0078 | 80 00 00 AA 00 38 9B 71 - .....8.q
0080 | FF 00 00 00 00 00 10 00 - ........ - (G) Majortype or Subtype
0088 | 80 00 00 AA 00 38 9B 71 - .....8.q

The Flags field may have following bits set:

  • 0×02 - Rendered
  • 0×04 - Many
  • 0×08 - If set it’s an output pin, otherwise it’s an input pin
  1. 9 Responses to “How filters are described in the Registry database”

  2. By sjei on Mar 15, 2008

    Interesting article. How does a filter get loaded by the DShow engine? For example, if I were to open a video file in Media Player, what values get checked in the file and which registry keys gets enumerated and looked up to locate the filter plugin?

    It would be great if you could write an article on this. Thanks.

  3. By Igor Janos on Mar 15, 2008

    Hi.

    That’s a nice idea. I’ll go study the MSDN for a while and prepare that article… hopefully this weekend.

    Igor

  4. By Peter Clare on May 31, 2008

    You say that: “The rest of the [DeviceName] string may contain filter category CLSID…”

    Whilst other components (such as inclusion of the friendly name) of the device path appear to be optional, I believe that the category GUID is always present.

    One thing that I am trying to fully understand is that the FilterData registry key and value is present in two places. It is in the ActiveMovie Filter Class Manager Instance, as you describe. But it is also present in the relevant Instance key for filter under the category GUID. These two copies of the filter data don’t always seem to be in step. This seems to explain why the merit value reported by GraphEdit can differ from that reported by other filter management tools.

    I’m not sure whose job it is to keep these separate FilterData blocks coherent or if one is meant to override the other. Any light that you or anyone else can shed on this would be interesting.

    BTW, for KsProxy filters, you need to use the device path to form a registry key to examine under the HKLM\System\CurrentControlSet\Enum path.

    Pete

  5. By Igor Janos on Jun 1, 2008

    Actually the category GUID is not always present. At least for my stupid webcam it’s not.

    Thanks for the ksproxy hint. I’ll check on that and see what I can learn.

  6. By Mechi Fendel on Mar 23, 2009

    >There is also a KS-Proxy type of filters >but I did not have any KS-Proxy devices >installed so I can’t tell what substring it >has :-\.

    My Logitech camera, after plugging it in, shows the following DisplayName in GraphEdit:
    @device:pnp:\\?/usb#vid_046d&pid_08ca&mi_00#6&17f9619a&0&0000#{ CLSID }\global

    What all the parts are, I have no idea.

    >The rest of the string may contain filter >category CLSID and filter CLSID or name but >it is not mandatory and you should not rely >on that. But you can be sure that if there >are multiple identical devices plugged into >the system board they will have a different >DisplayName.

    I’m trying to figure out how to give to 2 devices using the same driver different DisplayNames. How is this done?

    Thanks for any input.
    Mechi

  7. By sky on Jun 12, 2009

    Hi, I want to know filterdata’s structor too.
    I read directshow sdk and find a interface IAMFilterData, it was said could analyse filterdata, but i write the interface in delphi and get a wrong data.
    Directshow sdk said: “Note This interface has been deprecated. New applications should not use it.”.
    Does any one know how to analys FilterData? shoud you tell me? sky@flyingsoft.com please, Thanks.
    these is a sample code in directshow SDK.

    HRESULT CMapperDlg::GetMerit(IPrOpertyBag*pPropBag,DWORD*pdwMerit)
    {
    HRESULT hr;
    IAMFilterData*pData=0;
    *pdwMerit=0:
    VARIANT varFilData={0};
    varFilData.vt=VT_Ull|VT_ARRAY;
    varFilData.parray=0; //docs say to zero this
    BYTE*pbFiiterData=0; // 0 if not read
    DWORD dwcbFilterDAta=0; //0 if not read
    //得到描述Filter的一个数据块
    hr=pPropBag->Read(L”FilterData”,&varFilData,O);
    if(SUCCEEDED(hr))
    ASSERT(varFilData.vt==(VT Ull | VT ARRAy));
    dwcbFilterDAta=varFilData.parray->rgsabound[0].cElements;
    //Access the filter data
    HRESULT hrTmp=SafeArrayAccessData(varFilData.parray,(void**)
    &pbFilterData);
    ASSERT(hrTmp=。s_OK);
    ASSERT(pbFilterData);
    }
    else
    {
    ASSERT(dwcbFilterDAta==0&&pbFilterData==0);
    return E_FAIL;
    //Get the IAMFilterData interface for parsing the filter data
    hr=m_pMapper->QueryInterface(uuidof(IAMFilterData),(void**)
    &pData);
    if(SUCCEEDED(hr))
    BYTE*pb=O;
    //对描述的Filter数据块进行分析,获取其中Merit部分
    hr=pData->ParseFilterData(pbFilterData,dwcbFilterDAta, &pb);
    if(SUCCEEDED(hr))
    REGFILTER2*pFil=((REGFILTER2**)pb)[0];
    if(pbFilterData)
    {
    HRESULT hrTmp=SafeArrayUnaccessData(varFilData.parray);
    ASSERT(hrTmp==S_OK);
    hrTmp=VariantClear(&varFilData);
    ASSERT(hrTmp==S_OK);
    }
    //从REGFILTER2数据结构中获取Merit值
    if(pEil)
    *pdwMerit=pFil->dwMerit;
    //Free the memory allocated by ParseFilterData
    if(pb)
    CoTaskMemFree(pb);
    }
    //Release the IAMFilterData interface
    pData->Release();
    }
    return hr;
    }

  8. By Igor Janos on Jun 14, 2009

    Try this file :
    http://dev.monogram.sk/websvn/filedetails.php?repname=graphstudio&path=%2Ftrunk%2Fsrc%2Fdsutil.cpp

    And look for FilterTemplate::Load
    That’s as much as I could find out.

  9. By Brandon Cernicky on Nov 12, 2009

    What are the pros and cons anyone has found using this direct read from the registry versus using EnumMatchingFilters and IEnumRegFilters?

    I’ve found pretty good success with the parsing notes above. My exception is that one of my devs put Pinnacle Real Media Renderer 2 on their box and it doesn’t completely comply. I’ll debug what exactly is in this stream but version is not 2 like all the others and the pin count is way off.

    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{03B6F948-3143-45A0-8FE5-F3CF47E013DE}]
    “FriendlyName”=”Pinnacle Real Media Renderer 2″
    “CLSID”=”{03B6F948-3143-45A0-8FE5-F3CF47E013DE}”
    “FilterData”=hex:02,00,00,20,02,00,00,00,30,69,00,00,00,00,01,00,00,00,00,00,\
    30,79,00,00,60,00,70,00,31,69,00,00,00,00,01,00,00,00,00,00,30,79,00,00,70,\
    00,70,00,76,64,00,10,80,00,00,9b,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
    00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
    00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
    00,00,00,00,00,00,00,00

  10. By Car insurance claims >> http://onlinecarinsuranceclaims.com/ on Nov 23, 2009

    [… - blog.monogram.sk is another wonderful source of advice. Online Car insurance claims [… -

Post a Comment