Martin - you're right, it does look harder than it is. There's a steep (but short) learning curve but once you have the basics down, it will make sense.
Some snippets of code using DirectShow.NET...
A basic graph builder class including code to clean up. I've included two filters to use in the next snippets.
Adding filters to a graph.
Connecting filters.
Some snippets of code using DirectShow.NET...
A basic graph builder class including code to clean up. I've included two filters to use in the next snippets.
Code:
public class DvbRadioGraphBuilder : IDisposable
{
DsROTEntry rot = null;
IFilterGraph2 graph = null;
IBaseFilter lameEncoder = null;
IBaseFilter fileWriter = null;
...
public DvbRadioGraphBuilder(object ParentLog, bool AddToROT)
{
graph = (IFilterGraph2) new FilterGraph();
rot = new DsROTEntry(graph);
}
...
protected void Decompose()
{
int hr = 0;
try
{
// Decompose the graph
FilterState pfs;
if (graph != null)
{
hr = (graph as DirectShowLib.IMediaControl).GetState(500, out pfs);
if (pfs != FilterState.Stopped)
{
//
// Not sure why I call both StopWhenReady() and Stop()...there must have been a reason
//
hr = (graph as DirectShowLib.IMediaControl).StopWhenReady();
hr = (graph as DirectShowLib.IMediaControl).Stop();
}
}
FilterGraphTools.RemoveAllFilters(graph);
//
// Release or dispose of all of the DShow components here
//
...
if (lameEncoder != null)
{
Marshal.ReleaseComObject(lameEncoder);
lameEncoder = null;
}
if (fileWriter != null)
{
Marshal.ReleaseComObject(fileWriter);
fileWriter = null;
}
if (rot != null)
{
rot.Dispose();
rot = null;
}
if (graph != null)
{
Marshal.ReleaseComObject(graph);
graph = null;
}
}
catch (Exception e)
{
// Handle exception
}
}
#region IDisposable Members
public void Dispose()
{
Decompose();
}
#endregion
}
Code:
private bool AddLAMEEncoderFilter()
{
int hr = 0;
DsDevice[] devices;
bool FoundLAMEEncoder = false;
try
{
//
// Get all of the filters normally listed in the "DirectShow Filters" category of GraphEdit
//
devices = DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory);
if (devices.Length == 0)
Log.WriteLine("No LegacyAmFilterCategory filters found!!!!");
else
{
for (int i = 0; i < devices.Length; i++)
{
try
{
if (devices[i].Name.Equals("LAME Audio Encoder"))
{
FoundLAMEEncoder = true;
hr = graph.AddSourceFilterForMoniker(devices[i].Mon, null, devices[i].Name, out lameEncoder);
DsError.ThrowExceptionForHR(hr);
break;
}
}
catch (NullReferenceException e)
{
// Handle exception
}
}
}
}
catch (Exception e)
{
// Handle exception
}
return FoundLAMEEncoder;
}
Connecting filters.
Code:
private bool ConnectFiltersForRadio(string RecordingName)
{
int hr = 0;
...
IPin pinLameEncOut = null;
IPin pinFileWriterIn = null;
bool Success = false;
try
{
IFileSinkFilter2 fs = (IFileSinkFilter2) fileWriter;
hr = fs.SetMode(AMFileSinkFlags.None);
DsError.ThrowExceptionForHR(hr);
hr = fs.SetFileName(RecordingName, null);
DsError.ThrowExceptionForHR(hr);
...
//
// The first parameter of FindPin(...) is the actual pin name as shown in GraphEdit
//
hr = lameEncoder.FindPin("Out", out pinLameEncOut);
DsError.ThrowExceptionForHR(hr);
hr = fileWriter.FindPin("Input", out pinFileWriterIn);
DsError.ThrowExceptionForHR(hr);
hr = graph.Connect(pinLameEncOut, pinFileWriterIn);
DsError.ThrowExceptionForHR(hr);
Success = true;
}
catch (Exception e)
{
// Handle exception
}
finally
{
...
if (pinLameEncOut != null)
Marshal.ReleaseComObject(pinLameEncOut);
if (pinFileWriterIn != null)
Marshal.ReleaseComObject(pinFileWriterIn);
}
return Success;
}