I am trying to create a custom (Directshow) filtergraph in C#.NET with the help of the Directshow.net Lib. The lib is based on Microsoft's C++ directshow interfaces.
Creating the graph works and I can add one or more filters to it. However, when trying to save the graph to a file, it writes some bytes, but the Graph editor (graphedt.exe) cannot open it.
DsDevice[] videoInputDevices =
DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
IGraphBuilder graphBuilder = (IGraphBuilder) new FilterGraph();
ICaptureGraphBuilder2 captureGraphBuilder = (ICaptureGraphBuilder2) new CaptureGraphBuilder2();
captureGraphBuilder.SetFiltergraph(graphBuilder);
object source;
videoInputDevices[0].Mon.BindToObject(
null,
null,
typeof(IBaseFilter).GUID,
out source);
IBaseFilter filter = (IBaseFilter)source;
graphBuilder.AddFilter(filter, "Video Capture");
try
{
int renderStreamComResult = captureGraphBuilder.RenderStream(
PinCategory.Preview,
MediaType.Video,
filter,
null,
null);
MyStreamWriter r = new MyStreamWriter();
IPersistStream p = (IPersistStream)graphBuilder;
p.Save(r, true);
// ugly, only temporary...
r.bWriter.Flush();
r.bWriter.Close();
//
//DsError.ThrowExceptionForHR(renderStreamComResult);
}
finally
{
if (filter != null)
{
Marshal.ReleaseComObject(filter);
}
if (graphBuilder != null)
{
Marshal.ReleaseComObject(graphBuilder);
}
if (captureGraphBuilder != null)
{
Marshal.ReleaseComObject(captureGraphBuilder);
}
}
If I compare the contents of the file that I generated with one that I created manually in the editor, they do look different.
MyStreamWriter class that implements ComTypes.IStream:
IPersistStream.Save() only calls Seek() and Write() on the streamwriter.
public class MyStreamWriter : IStream
{
public BinaryWriter bWriter;
public MyStreamWriter()
{
this.bWriter = new BinaryWriter(
File.OpenWrite("graph.grf"),
Encoding.UTF8);
}
public void Clone(out iop.ComTypes.IStream ppstm)
{
throw new NotImplementedException();
}
public void Commit(int grfCommitFlags)
{
bWriter.Flush();
throw new NotImplementedException();
}
public void CopyTo(iop.ComTypes.IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
throw new NotImplementedException();
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
throw new NotImplementedException();
}
public void Revert()
{
throw new NotImplementedException();
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
bWriter.Seek((int)dlibMove, (SeekOrigin)dwOrigin);
}
public void SetSize(long libNewSize)
{
throw new NotImplementedException();
}
public void Stat(out iop.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
throw new NotImplementedException();
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
bWriter.Write(pv);
}
}
The directshow lib doesn't do anything weird in IPersistStream, it just makes the C++ interface available... So the problem must be somewhere else.
Any help is really appreciated.
I think that the solution is much more simple CSharp DirectShow lib allows you to save the graph in a file.
This code works for me :
using DirectShowLib.Utils;
FilterGraphTools.SaveGraphFile(this.m_TheGraphBuilder, FilePath);