Я пытаюсь создать пользовательский (Directshow) filtergraph в С#.NET с помощью Directshow.net Lib. Lib основан на интерфейсах Directshow Microsoft C++.
Создание графика работает, и я могу добавить к нему один или несколько фильтров. Однако при попытке сохранить граф в файл он записывает несколько байтов, но редактор Graph (graphedt.exe) не может его открыть.
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);
}
}
Если я сравниваю содержимое файла, который я сгенерировал с тем, который я создал вручную в редакторе, они выглядят иначе.
График, сделанный с помощью редактора
Класс MyStreamWriter, который реализует ComTypes.IStream:
IPersistStream.Save() вызывает только вызовы Seek() и Write() в потоковом потоке.
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);
}
}
Directshow lib не делает ничего странного в IPersistStream, это просто делает доступным интерфейс C++... Таким образом, проблема должна быть где-то в другом месте.
Любая помощь действительно ценится.
Я думаю, что решение намного проще. CSharp DirectShow lib позволяет сохранять график в файле.
Этот код работает для меня:
использование DirectShowLib.Utils;
FilterGraphTools.SaveGraphFile(this.m_TheGraphBuilder, FilePath);