Dynamically change filter value without Property Page

荒凉一梦 提交于 2019-12-07 18:26:48

问题


I just wrote a simple DirectShow Filter (which inherits from CTransformFilter).

But I want to be able to set a variable of my filter dynamically. 
This can be done today using Property Page. 
But what i want is change this property programatically. 

I defined a custom COM interface to set a variable in the filter but can not figure out how to use it -access it...

How to set a DirectShow filter's properties value without open the 
filter's property page ?

Any one has idea?

More Details:

Well

i) Firt i just defined simple interface

DEFINE_GUID(IID_IApplyFilterControl,  X, X, X, X, X, X, X, X, X, X, X);


interface IApplyFilterControl : public IUnknown
{
    STDMETHOD(SetWillApplyFilterX)(bool applyFilter) = 0;
};

ii) Then in my Filter C++ Code i implement this interface

class MyFilter : public CTransformFilter , public IApplyFilterControl 
{
    ....
    STDMETHODIMP SetWillApplyFilter(bool apply)
    {
        CAutoLock lock(&m_csShared);
        willApplyFilter = apply;
        return S_OK;

    }
    ...

}

iii) In my C# Code (using DirectShowNet)

I want to able to access my filter

IBaseFilter myFilter = 
(IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(myFilterGuid));
....
IApplyFilterControl filterControl = (IApplyFilterControl ) myFilter;
.....

filterControl->SetWillApplyFilter(true)

Finally I Fix It

Take the advice of yms and use hints from the link : Some advices about custom filters

Source: http://social.msdn.microsoft.com/Forums/en-US/windowsdirectshowdevelopment/thread/e02aa741-776c-42cf-869f-640747e197e4

i) Your COM Interface

// The GUID that identifies your interface
// {13F23FD9-A90C-480d-A597-F46BA20070AC}

static const GUID IIDTransformFilterControl =

{
      0x13f23fd9, 0xa90c, 0x480d, { 0xa5, 0x97, 0xf4, 0x6b, 0xa2, 0x0, 0x70, 0xac }
};

DECLARE_INTERFACE_(ITransformFilterControl, IUnknown)

{
    STDMETHOD(setGreyscale)(bool enable) = 0;
};

ii) Your transform Filter

class YourTransformFilter : 
public CTransformFilter, public ITransformFilterControl

{
    public:
    STDMETHODIMP    NonDelegatingQueryInterface(REFIID riid, void **ppv);
    STDMETHODIMP    setGreyscale(bool enable);
};

....

STDMETHODIMP  YourTransformFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)

{
    CheckPointer(ppv, E_POINTER);

    if(riid==IIDTransformFilterControl)   
      return GetInterface((ITransformFilterControl*) this, ppv);

    return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}

STDMETHODIMP  YourTransformFilter:: setGreyscale(bool enable)

{
    bGreyscale    = enable;
    return S_OK;
}

iii) Finally In your C# host application Define COM Interface

[ComImport, System.Security.SuppressUnmanagedCodeSecurity, 
Guid("13F23FD9-A90C-480d-A597-F46BA20070AC"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface ITransformControl

{
        [PreserveSig]
        int setGreyscale(bool enable);
}

iv) And Use in your C# code

ITransformFilterControl transformControl = 
     yourFilterInstance as ITransformFilterControl;

if(transformControl!=null)

{
    transformControl->setGreyscale(true);
}

回答1:


If you defined a COM interface to access your filter, all you need to do now is to declare the same interface (using the same GUIs) in C#/VB.Net or whatever .net language you are using. Then you can do a type cast of your filter to the new interface. Here is a C# example on how to declare such an interface:

using System.Runtime.InteropServices;

// Declare IMediaControl as a COM interface which 
// derives from the IDispatch interface. 
[Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"),
    InterfaceType(ComInterfaceType.InterfaceIsDual)] 
interface IMediaControl // cannot list any base interfaces here 
{ 
    // Note that the members of IUnknown and Interface are NOT
    // listed here 
    //
    void Run();

    void Pause();

    void Stop();

    void GetState( [In] int msTimeout, [Out] out int pfs);

    void RenderFile(
    [In, MarshalAs(UnmanagedType.BStr)] string strFilename);

    void AddSourceFilter(
    [In, MarshalAs(UnmanagedType.BStr)] string strFilename, 
    [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk);

    [return : MarshalAs(UnmanagedType.Interface)]
    object FilterCollection();

    [return : MarshalAs(UnmanagedType.Interface)]
    object RegFilterCollection();

    void StopWhenReady(); 
}

EDIT:

About the issue with E_NOINTERFACE during casting, it looks like a threading problem. 1- Creating your filter with Activator is not a good idea, you should always allow your DS graph to create your filters, try using "enumarate filters" instead. 2- Verify that the treading model you are using for your filter is "Both".Read here and here for some more information.



来源:https://stackoverflow.com/questions/6041618/dynamically-change-filter-value-without-property-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!