该应用程序使用DirectShowLib和USB摄像头(Logitech C930e)在C#中实现。该图是使用RenderStream方法编译的。由于未提供预览图钉,因此会自动生成SmartTee筛选器。

一次调用RenderStream进行预览,然后进行捕获。但是,即使交换(捕获然后预览),它也无法将第二个呼叫连接到SmartTee。引发的错误处理程序为:-2147024809(0x80070057; E_INVALIDARG;参数不正确)

代码片段如下

    DirectShowLib.ISampleGrabber sg = null;
    DirectShowLib.ICaptureGraphBuilder2 cg = null;
    DirectShowLib.IGraphBuilder fg = null;

    IBaseFilter capFilter;
    IBaseFilter videoCompressorFilter;
    IBaseFilter muxFilter;
    IBaseFilter grabFilter;
    IBaseFilter VideoRendererFilter;

    Guid captureCat = PinCategory.Capture;
    Guid previewCat = PinCategory.Preview;
    Guid med = MediaType.Video;

    DsGuid DSCaptureCat = (DsGuid)captureCat;
    DsGuid DSPreviewCat = (DsGuid)previewCat;
    DsGuid DSmed = (DsGuid)med;

    /*GetInterfaces*/
    Type comType = null;
    object comObj = null;
    fg = (IGraphBuilder)new FilterGraph();
    comType = Type.GetTypeFromCLSID(CgGuid);
    comObj = Activator.CreateInstance(comType);
    cg = (ICaptureGraphBuilder2)comObj; comObj = null;
    sg = (ISampleGrabber)new SampleGrabber();
    grabFilter = (IBaseFilter)sg;
    VideoRendererFilter = (IBaseFilter)new VideoRenderer();

    /*CreateCaptureDevice*/
    object capObj = null;
    capFilter = (IBaseFilter)capObj;

    /*SetupGraph*/
    hr = cg.SetFiltergraph(fg);

    if (renderFromDevice && deviceSet)
    {
        hr = fg.AddFilter(capFilter, "CapFilter");
    }

    AMMediaType media = new AMMediaType();
    media.majorType = MediaType.Video;
    media.subType = MediaSubType.RGB24;
    media.formatType = FormatType.VideoInfo;
    hr = sg.SetMediaType(media);

    DsUtils.FreeAMMediaType(media);
    media = null;


[1]
    /*RenderToScreen*/
    hr = fg.AddFilter(grabFilter, "FrameGrabFilter");

    hr = cg.RenderStream(DSPreviewCat, DSmed, capFilter, grabFilter, null);

[2]
    /*DerenderGraph*/
    if (renderFromDevice)
        removeDownstream(capFilter, videoCompressorFilter == null);
    else if (grabFilter != null)
        removeDownstream(grabFilter, true);

[3]
    /*RenderToMovie*/
    videoFilename = Path.Combine(dirname, "interview.avi");

    cg.SetOutputFileName(MediaSubType.Avi, videoFilename, out muxFilter, out fileWriterFilter); //this automatically adds muxFilter to graph!

    string s;
    AMMediaType media = new AMMediaType();
    hr = fileWriterFilter.GetCurFile(out s, media);
    hr = fileWriterFilter.SetFileName(videoFilename, media);
    DsUtils.FreeAMMediaType(media);
    media = null;

    hr = fg.AddFilter(muxFilter, "MuxFilter"); //this adds the second muxFilter! now removed

    hr = cg.RenderStream(DSCaptureCat, DSmed, capFilter, null, muxFilter);

[4]
    /*RenderToScreen2*/
    hr = fg.AddFilter(grabFilter, "FrameGrabFilter");

    hr = fg.AddFilter(VideoRendererFilter, "VideoRendererFilter");

    IEnumFilters enumFilters = null;
    FilterInfo pInfo;
    IBaseFilter pFilter1, pFilter2, pFilter3;
    IPin outPin1, inPin1, outPin2, inPin2, inPin3;

    hr = fg.EnumFilters(out enumFilters);

    IBaseFilter[] filters = new IBaseFilter[1];
    int fetched;

    while (enumFilters.Next(1, filters, out fetched) == 0)
    {
        hr = filters[0].QueryFilterInfo(out pInfo);

        hr = fg.FindFilterByName("Smart Tee", out pFilter1);

        inPin1 = DsFindPin.ByDirection(pFilter1, PinDirection.Input, 0);
        outPin1 = DsFindPin.ByName(pFilter1, "Preview");

        hr = fg.FindFilterByName("FrameGrabFilter", out pFilter2);

        inPin2 = DsFindPin.ByDirection(pFilter2, PinDirection.Input, 0);
        outPin2 = DsFindPin.ByDirection(pFilter2, PinDirection.Output, 0);

        hr = fg.FindFilterByName("VideoRendererFilter", out pFilter3);

        inPin3 = DsFindPin.ByDirection(pFilter3, PinDirection.Input, 0);

        hr = fg.Connect(outPin1, inPin2);

        hr = fg.Connect(outPin2, inPin3);
    }


下面的GraphEdit显示了到图形的远程连接。通过手动将SmartTee捕获链接到GraphEdit中的MuxFilter,图形可以正常运行。

 

关于可能的错误原因的任何提示将不胜感激。

最佳答案

在没有看到对ICaptureGRaphBuilder2.RenderStream的实际调用的情况下,我只能对E_INVALIDARG错误做出一些假设。
但是,从远程连接到图形,我可以看到您的图形存在严重错误。两个输出引脚不应连接到同一输入引脚。
您应该始终始终首先为Capture路径调用RenderStream,因为协商媒体类型的是Capture引脚。您的源滤波器上已经有Capture引脚(为什么连2个也如此?)。我认为您需要像这样调用Capture RenderStream:

RenderStream(PIN_CATEGORY_CAPTURE,MEDIATYPE_Video,pSource,pMux,pWriter);

哪里:
pSource是摄像机终端CapFilter的IBaseFilter接口,
pMux是MuxFilter的IBaseFilter接口(应该只向图中添加一个MuxFilter!),
pWriter是Writer筛选器(interview.avi)的IBaseFilter接口。

您应该仅添加一个摄像机终端CapFilter实例,仅添加一个MuxFilter(AVI Mux)实例,以及仅一个File Writer过滤器(interview.avi)实例。
通过此设置,对Capture路径的RenderStream调用应该会成功。之后,您可以尝试调用RenderStream作为预览路径,并且如果尚未在第一个调用中添加Smart tee,则应添加Smart tee。
让我知道是否可以进一步帮助您。

10-02 03:30