1

我一直在开发一个使用Directshow.NET的应用程序,并决定开始修补 GraphEd.exe 以找出我需要采取的确切路线。

图形化图

我想要的最简单版本在上图中(其中“test.mpeg”是“文件编写器”过滤器)。

果然,在 GraphEd 中看起来很简单的事情并不像编码那么简单。几秒钟后,我意识到 directshow 是我不理解的东西。这是我的 C# 代码尝试:

int hr;

IBaseFilter cameraStream = null;
IBaseFilter mpegEncoder = null;
IBaseFilter fileWriter = null;
ICaptureGraphBuilder2 capGraph = null;

filterGraph = (IFilterGraph2)new FilterGraph();
try
{
    capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
    hr = capGraph.SetFiltergraph(filterGraph);
    Marshal.ThrowExceptionForHR(hr);

    hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out cameraStream);
    Marshal.ThrowExceptionForHR(hr);

    IPin cameraData = null;
    hr = capGraph.FindPin(cameraStream, PinDirection.Output, PinCategory.Capture, MediaType.Video, true, 0, out cameraData );
    //hr = cameraStream.FindPin("Capture", out cameraData);
    Marshal.ThrowExceptionForHR(hr);

    mpegEncoder = (IBaseFilter)new MJPGEnc();
    hr = filterGraph.AddFilter(mpegEncoder, "mpeg encoder");
    //hr = filterGraph.FindFilterByName("Microsoft MPEG-2 Video Encoder", out mpegEncoder);
    Marshal.ThrowExceptionForHR(hr);

    IPin mpegInput = null;
    //hr = mpegEncoder.FindPin("Input0", out mpegInput);
    hr = capGraph.FindPin(mpegEncoder, PinDirection.Input, null, null, true, 0, out mpegInput);
    Marshal.ThrowExceptionForHR(hr);

    filterGraph.Connect(cameraData, mpegInput);

    IPin mpegOutput = null;
    //hr = mpegEncoder.FindPin("Output", out mpegOutput);
    hr = capGraph.FindPin(mpegEncoder, PinDirection.Output, null, null, true, 0, out mpegOutput);
    Marshal.ThrowExceptionForHR(hr);

    //hr = filterGraph.FindFilterByName("File writer", out fileWriter);
    fileWriter = (IBaseFilter)new FileWriter();
    IFileSinkFilter test = fileWriter as IFileSinkFilter2;
    AMMediaType mtype = new AMMediaType();
    mtype.majorType = MediaType.Video;
    mtype.subType = MediaSubType.RGB24;
    mtype.formatPtr = IntPtr.Zero;
    test.SetFileName(videoPath, mtype );

    IPin fwriterIn = null;
    //hr = fileWriter.FindPin("in", out fwriterIn);
    hr = capGraph.FindPin(fileWriter, PinDirection.Input, null, null, true, 0, out fwriterIn);
    Marshal.ThrowExceptionForHR(hr);

    filterGraph.Connect(mpegOutput, fwriterIn);

    hr = capGraph.RenderStream(null, null, cameraStream, null, fileWriter); // *** Breaks on this line! ***
    Marshal.ThrowExceptionForHR(hr);

    mediaControl = filterGraph as IMediaControl;

}
finally
{
    if (cameraStream != null)
    {
        Marshal.ReleaseComObject(cameraStream);
        cameraStream = null;
    }
    if (mpegEncoder != null)
    {
        Marshal.ReleaseComObject(mpegEncoder);
        mpegEncoder = null;
    }
    if (fileWriter != null)
    {
        Marshal.ReleaseComObject(fileWriter);
        fileWriter = null;
    }
    if (capGraph != null)
    {
        Marshal.ReleaseComObject(capGraph);
        capGraph = null;
    }
}

在编写并查看了我的代码有多荒谬(就编程逻辑而言)之后,我意识到我需要一些帮助。

谁能指导我某种结构化的directshow教程,向我解释事情,就好像我是一个巨大的新手一样,或者可能将我链接到某种处理网络摄像头到文件记录的C#库?我一般不是win32程序员,所以任何减轻痛苦的东西都应该是好的:)

另外,我确实有似乎可以工作的相机设备枚举代码:

private void rescan_camera()
{
    comboBox1.Items.Clear();

    DsDevice[] cameraDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

    for(int i=0; i < cameraDevices.Length; i++) {
        comboBox1.Items.Add(cameraDevices[i].Name);
    }
    if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
}

我可以从 DsDevice 获取名字对象数据,我知道这是告诉 directshow 过滤器图表我想从哪里记录的关键部分,但这与我的知识范围有关。

编辑:更新的代码,显示换行符的确切位置。

4

1 回答 1

0

重复评论:所以,我最终更改了文件输出:我没有为 setFileName 设置媒体类型,而是将其更改为 null,现在一切都很好:)

于 2012-10-22T17:36:17.123 回答