The application is implemented in C# using DirectShowLib and a USB camera (Logitech C930e). The graph is compiled using RenderStream method. SmartTee filter is automatically generated as there is no preview pin provided.
RenderStream is called once for preview and then for capture. However, it fails to connect the second call to the SmartTee even if swapped (capture then preview). The error handler thrown is: -2147024809 (0x80070057; E_INVALIDARG
; The parameter is incorrect)
code snippet as follows
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 below shows the remote connection to the graph. The graph runs fine by manually linking SmartTee capture to MuxFilter within GraphEdit.
Any hints regarding the possible error cause will be very much appreciated.