使用DirectShow捕获音频

时间:2011-10-07 11:04:58

标签: c# audio directshow

我正在编写使用DirectShow库在C#中捕获音频并将其写入ogg容器的程序。我在GraphEditPlus中创建了一个图形。它生成一个GraphBuilder方法代码,我将其复制到我的代码中。这段代码是:

class AudioCapture
{
  public static void checkHR(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;
  }
}

当我尝试执行此代码程序时,在尝试连接麦克风和vorbis编码器过滤器后,会向我发出“无法找到引脚”的消息。调试后我发现它找不到麦克风引脚。有谁知道我的错误在哪里?

2 个答案:

答案 0 :(得分:0)

你不应该按名字寻找别针,因为这不太可靠。如果你绝对确定你正在处理什么过滤器/类,或许它绝对不是通用音频源过滤器的方式(更具体地说:没有人给出捕获引脚被命名的承诺),也许它或多或少可以接受。 “捕获”,而不是引脚实现IKsPropertySet来表示)。

您最好的方法是使用带有ICaptureGraphBuilder::RenderStream参数的PIN_CATEGORY_CAPTURE,以便它可以为您选择捕获引脚。有关详细信息,请参阅MSDN http://msdn.microsoft.com/en-us/library/dd311932%28v=vs.85%29.aspx,我很确定您也可以轻松找到执行此操作的示例代码。

答案 1 :(得分:0)

在寻找引脚时尝试做这样的事情

    pinout = FindPinByDirection( Source, PinDirection.Output);
    pinin = FindPinByDirection( Target, PinDirection.Input);

    Graph.Connect(pinout, pinin);

这是更好的方式,然后取决于名称。