Dynamically change filter value without Property Page
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);
}
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.
精彩评论