Search code examples
c#.netgraphdirectshow

C#.NET DirectShow Lib: Saving custom graph to a file


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.

Graph from c# net

Graph made using the editor

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.


Solution

  • 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);