Search code examples
c#filtercomdirectshow

get filters(com devices) using DirectShow


from code project I got this code but I don't understand.

This function shall get all the filters(com devices) after its category and it fill it in the innerlist

can someone explain in details I have searched about each part all seems for me new I don't understand what is ICreateDevEnum ,UCOMIEnumMoniker and UCOMIMoniker and how we get the filters using them

protected void getFilters(Guid category)
        {
            int                 hr;
            object              comObj = null;
            ICreateDevEnum      enumDev = null;
            UCOMIEnumMoniker    enumMon = null;
            UCOMIMoniker[]      mon = new UCOMIMoniker[1];

            try 
            {
                // Get the system device enumerator
                Type srvType = Type.GetTypeFromCLSID( Clsid.SystemDeviceEnum );
                if( srvType == null )
                    throw new NotImplementedException( "System Device Enumerator" );
                comObj = Activator.CreateInstance( srvType );
                enumDev = (ICreateDevEnum) comObj;

                // Create an enumerator to find filters in category
                hr = enumDev.CreateClassEnumerator( ref category, out enumMon, 0 );
                if( hr != 0 )
                    throw new NotSupportedException( "No devices of the category" );

                // Loop through the enumerator
                int f;
                do
                {
                    // Next filter
                    hr = enumMon.Next( 1, mon, out f );
                    if( (hr != 0) || (mon[0] == null) )
                        break;

                    // Add the filter
                    Filter filter = new Filter( mon[0] );
                    InnerList.Add( filter );

                    // Release resources
                    Marshal.ReleaseComObject( mon[0] );
                    mon[0] = null;
                }
                while(true);

                // Sort
                InnerList.Sort();
            }
            finally
            {
                enumDev = null;
                if( mon[0] != null )
                    Marshal.ReleaseComObject( mon[0] ); mon[0] = null;
                if( enumMon != null )
                    Marshal.ReleaseComObject( enumMon ); enumMon = null;
                if( comObj != null )
                    Marshal.ReleaseComObject( comObj ); comObj = null;
            }
        }

Solution

  • You are using [undocumented] managed wrapper over native API, however the API itself is well-documented on MSDN and the interface names have direct mappings.

    See Using the System Device Enumerator, which describes the identifiers in question.

    To use the System Device Enumerator, do the following:

    1. Create the system device enumerator by calling CoCreateInstance. The class identifier (CLSID) is CLSID_SystemDeviceEnum.
    2. Obtain a category enumerator by calling ICreateDevEnum::CreateClassEnumerator with the CLSID of the desired category. This method returns an IEnumMoniker interface pointer. If the category is empty (or does not exist), the method returns S_FALSE rather than an error code. If so, the returned IEnumMoniker pointer is NULL and dereferencing it will cause an exception. [...]