I'm writing program which captures audio in C# using DirectShow library and writes it to ogg container. I created a graph in GraphEditPlus. It generates a GraphBuilder method code which I copied to my code. This code is:
class AudioCapture
{
public static void checkHR开发者_如何学C(int hr, string msg)
{
if (hr < 0)
{
MessageBox.Show(msg);
DsError.ThrowExceptionForHR(hr);
}
}
public static void BuildGraph (IGraphBuilder pGraph, string dstFile)
{
int hr = 0;
//graph builder
ICaptureGraphBuilder2 pBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = pBuilder.SetFiltergraph(pGraph);
checkHR(hr, "Can't SetFiltergraph");
Guid CLSID_XiphOrgVorbisEncoder = new Guid("{5C94FE86-B93B-467F-BFC3-BD6C91416F9B}");
Guid CLSID_XiphOrgOggMuxer = new Guid("{1F3EFFE4-0E70-47C7-9C48-05EB99E20011}");
//add microphone
IBaseFilter pMicrophone = (IBaseFilter) new AudioRecord();
hr = pGraph.AddFilter(pMicrophone, "Microphone");
checkHR(hr, "Can't add microphone to graph");
//add Vorbis Encoder
IBaseFilter pVorbisEncoder = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_XiphOrgVorbisEncoder));
checkHR(hr, "Can't add Vorbis Encoder to graph");
//connect Microphone and Vorbis Encoder
hr = pGraph.ConnectDirect(GetPin(pMicrophone, "Capture"), GetPin(pVorbisEncoder, "PCM In"), null);
checkHR(hr, "Can't connect Microphone and Vorbis Encoder");
//add Ogg Muxer
IBaseFilter pOggMuxer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_XiphOrgOggMuxer));
checkHR(hr, "Can't add Ogg Muxer to graph");
//set destination filename
IFileSinkFilter pOggMuxer_sink = pOggMuxer as IFileSinkFilter;
if (pOggMuxer_sink == null)
checkHR(unchecked((int)0x80004002), "Can't get IFileSinkFilter");
hr = pOggMuxer_sink.SetFileName(dstFile, null);
checkHR(hr, "Can't set filename");
//connect Vorbis Encoder and Ogg Muxer
hr = pGraph.ConnectDirect(GetPin(pVorbisEncoder, "VorbisOut"), GetPin(pOggMuxer, "Ogg Packet In"), null);
checkHR(hr, "Can't connect Vorbis Encoder and Ogg Muxer");
}
static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
checkHR(-1, "Pin not found");
return null;
}
}
When I'm trying to execute this code program throws me a message "Pin can't found" after trying to connect microphone and vorbis encoder filters. After debugging I found out that it can't find the microphone pin. Does anybody knows where is my error?
You should not look for pins by their names, as this is not quite reliable. Perhaps it might be still more or less acceptable if you are absolutely sure what filter/class you are dealing with, but it is definitely not the way to do with generic audio source filter (more specifically: noone gives a promise that capture pin is named "Capture", instead pins implement IKsPropertySet
to indicate that).
Your best approach would be using ICaptureGraphBuilder::RenderStream
with PIN_CATEGORY_CAPTURE
argument so that it could pick up capture pin for you. See MSDN for details http://msdn.microsoft.com/en-us/library/dd311932%28v=vs.85%29.aspx and I am pretty sure you will easily find sample code for doing this too.
Try do something like this when you looking for pins
pinout = FindPinByDirection( Source, PinDirection.Output);
pinin = FindPinByDirection( Target, PinDirection.Input);
Graph.Connect(pinout, pinin);
This is better way then depending on names.
精彩评论