View Full Version : using IFileSourceFilter in .NET


stax76
19th May 2004, 21:12
Hi,
can anyone explain me how to use this interface in .NET or point me to sample code?

in C++ it looks like this (taken from usenet)



IBaseFilter* g_pSource;
IBaseFilter* g_pVideoRenderer;

CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&g_pSource);

CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&g_pVideoRenderer);

IFileSourceFilter* FileSource=NULL;

hr = g_pSource->QueryInterface(IID_IFileSourceFilter, (void**)&FileSource);

DShowUtils::MessageBoxError(hr);

hr = FileSource->Load(L"D:\\MPG2\\MP2 von Telergional\\WöhrlJeans.mpg", NULL);

DShowUtils::MessageBoxError(hr);

if (FileSource)
FileSource->Release();

hr = m_Graph1->AddFilter(g_pSource, L"AsyncReader");

DShowUtils::MessageBoxError(hr);

hr = m_Graph1->AddFilter(g_pVideoRenderer, L"Video Renderer");

DShowUtils::MessageBoxError(hr);

IPin *pFileOut = NULL, *pVideoIn = NULL;

pFileOut = DShowUtils::GetPin(g_pSource, PINDIR_OUTPUT);

if (pFileOut != NULL) {

pVideoIn = DShowUtils::GetPin(g_pVideoRenderer, PINDIR_INPUT);

if (pVideoIn != NULL)
{
hr = DShowUtils::ConnectAndFreePins(m_Graph1, pFileOut, pVideoIn);
DShowUtils::MessageBoxError(hr);
}



this is what I've done so far with NETMaster's DShowNET lib and some fixes and helper functions (in DShowNET I had to fix IEnumPins.Next and add the definition of IFileSourceFilter)


IBaseFilter aviSrc = GetFilter(Guids.FileSourceAsync);
ShowPinCount(aviSrc); // debug info showing how many pins the filter has
(aviSrc as IFileSourceFilter).Load(
@"D:\Video\test files\Tweet\tweet.avi", null);
ShowPinCount(aviSrc); // shows 0 so I guess something is wrong


the interop is a hassle for people who lack the required knowledge, if I knew C++ better I wouldn't bother and do it in C++ but this is even a bigger problem for me.

Thank you

Nic
20th May 2004, 09:35
(disclaimer: My knowlegde of .net is sketchy at best)

Is there anyway you could get the return value when you're doing the .Load(...) in .net ? If it's the same as C++ it will return the error and then we'll know why it's failing. If it's not throwing an exception I can only assume the way your doing it is correct...

However, if it is correct, it is strange, you'd think there was a better way of exposing the interface than using "as" which is really a cast...

Sorry I couldn't be more help,
-Nic

stax76
20th May 2004, 10:49
Is there anyway you could get the return value when you're doing the .Load(...) in .net ?


I'm not used to this type of error handling, you are right of course. It returns 0 so it means no error I think


int hr = (aviSrc as IFileSourceFilter).Load(
@"D:\Video\test files\Tweet\tweet.avi", null);

if (hr != 0)
Marshal.ThrowExceptionForHR(hr);



However, if it is correct, it is strange, you'd think there was a better way of exposing the interface than using "as" which is really a cast...


I've been doing this before, it's also described in MSDN:


Using Casts Instead of QueryInterface

A C# coclass is not very useful until you can access an interface that it implements. In C++ you would navigate an object's interfaces using the QueryInterface method on the IUnknown interface. In C# you can do the same thing by explicitly casting the COM object to the desired COM interface. If the cast fails, then an invalid cast exception is thrown:


there is however a alternative method I think (Marshal.QueryInterface)

I'm going to code the same thing in C++ now, maybe this gives me the hint

stax76
21st May 2004, 01:48
I couldn't get this working accessing DirectShow interfaces directly although I think I was near (I think it requires some magic with ICaptureGraphBuilder::RenderStream). I found out the ActiveMovie control library which was created for VB6 provides everything needed except setting the filepath for file writer which is no problem since the underlying DirectShow interface for the filter can be accessed. I think it's easier this way anyway because all interfaces are wrapped to new interfaces that are very handy


Private graph As New FilgraphManager

Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
Dim src As IFilterInfo
graph.AddSourceFilter("D:\Video\test files\Outkast 20 MB\Outkast 20 MB.avi", src)
Dim mux As IFilterInfo = GetFilter("3ivx D4 Media Muxer")
Dim writer As IFilterInfo = GetFilter("File writer")
Dim srcAudio As IFilterInfo = GetFilter("File Source (Async.)")
srcAudio.Filename = "D:\Video\test files\Outkast 20 MB\Outkast 20 MB.mp4"
CType(writer.Filter, IFileSinkFilter).SetFileName("D:\Video\test files\Outkast 20 MB\test.mp4", Nothing)
GetPin(src, 0).Connect(GetPin(mux, 0))
GetPin(srcAudio, 0).Connect(GetPin(mux, 1))
GetPin(mux, 3).ConnectDirect(GetPin(writer, 0))
MsgBox("start")
graph.Run()
Dim iEvent As IMediaEvent = CType(graph, IMediaEvent)
iEvent.WaitForCompletion(900000000, 0)
graph.Stop()
MsgBox("done")
End Sub

Private Function GetPin(ByVal f As IFilterInfo, ByVal index As Integer) As IPinInfo
Dim pins As New ArrayList

For Each i As IPinInfo In f.Pins
pins.Add(i)
Next

Return CType(pins(index), IPinInfo)
End Function

Private Function GetFilter(ByVal name As String) As IFilterInfo
For Each i As IRegFilterInfo In graph.RegFilterCollection
If i.Name = name Then
Dim ret As IFilterInfo
i.Filter(ret)
Return ret
End If
Next

Throw New Exception
End Function

<ComVisible(True), _
ComImport(), _
Guid("a2104830-7c70-11cf-8bce-00aa00a3f1a6"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IFileSinkFilter
<PreserveSig()> Function SetFileName(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszFileName As String, <[In](), MarshalAs(UnmanagedType.LPStruct)> ByVal pmt As AMMediaType) As Integer
<PreserveSig()> Function GetCurFile(<Out(), MarshalAs(UnmanagedType.LPWStr)> ByRef pszFileName As String, <Out(), MarshalAs(UnmanagedType.LPStruct)> ByVal pmt As AMMediaType) As Integer
End Interface

<StructLayout(LayoutKind.Sequential), _
ComVisible(False)> _
Public Class AMMediaType
Public majorType As Guid
Public subType As Guid
<MarshalAs(UnmanagedType.Bool)> _
Public fixedSizeSamples As Boolean
<MarshalAs(UnmanagedType.Bool)> _
Public temporalCompression As Boolean
Public sampleSize As Integer
Public formatType As Guid
Public unkPtr As IntPtr
Public formatSize As Integer
Public formatPtr As IntPtr
End Class