该应用程序使用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显示了与图形的远程连接。通过在GraphEdit中手动将SmartTee捕获链接到MuxFilter,图形可以正常运行。
非常感谢有关可能的错误原因的任何提示。
答案 0 :(得分:1)
如果没有看到对ICaptureGRaphBuilder2.RenderStream的实际调用,我只能对E_INVALIDARG错误做一些假设。 但是,从远程连接到图形,我可以看到图形存在严重错误。两个输出引脚不应连接到同一输入引脚。 您应该始终首先为Capture路径调用RenderStream,因为它是协商媒体类型的Capture引脚。您的源过滤器上已经有Capture pin(其中有2个为什么?)。我认为您需要像这样调用Capture RenderStream:
RenderStream(PIN_CATEGORY_CAPTURE,MEDIATYPE_Video,pSource,pMux,pWriter);
其中: pSource是Video Camera Terminal CapFilter的IBaseFilter接口, pMux是MuxFilter的IBaseFilter接口(图中只应添加一个MuxFilter!), pWriter是Writer过滤器的IBaseFilter接口(interview.avi)。
您应该只添加一个Video Camera Terminal CapFilter实例,只添加一个MuxFilter实例(AVI Mux)和一个File Writer过滤器实例(interview.avi)。 使用此设置,Capture路径的RenderStream调用应该会成功。之后,您可以尝试调用RenderStream作为预览路径,如果尚未添加第一个调用,则应添加智能tee。 如果我能帮助你进一步解决这个问题,请告诉我。