2

Приложение реализовано на C# с использованием DirectShowLib и USB-камеры (Logitech C930e). График скомпилирован с использованием метода RenderStream. Фильтр SmartTee генерируется автоматически, так как нет предустановленного штифта.Невозможно захватить подачу камеры при предварительном просмотре с помощью DirectShow

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 к MuxFilter в GraphEdit.

Любые намеки относительно возможную причину ошибки будет очень высоко ценится.

ответ

1

Не видя фактического вызова ICaptureGRaphBuilder2.RenderStream, я могу сделать только некоторые предположения об ошибке E_INVALIDARG. Однако из удаленного подключения к графику я вижу, что с вашим графиком что-то ужасно. Два выходных контакта не должны быть подключены к одному входному выводу. Вы всегда должны сначала вызвать RenderStream для пути Capture, потому что это контакт Capture, который согласовывает тип носителя. У вас уже есть Capture pin на исходном фильтре (даже 2 из них почему?). Я думаю, что вам нужно вызвать свой Capture RenderStream следующим образом:

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

Где: pSource является интерфейсом IBaseFilter видеокамеры Терминала CapFilter, PMUX является интерфейсом IBaseFilter к MuxFilter (! Там должен быть только один MuxFilter добавлен к графику), pWriter является интерфейсом IBaseFilter к Фильтр Writer (interview.avi).

Вы должны добавить только один экземпляр терминала Video Camera Terminal CapFilter, только один экземпляр MuxFilter (AVI Mux) и только один экземпляр фильтра File Writer (interview.avi). С помощью этой настройки вызов RenderStream для пути захвата должен быть успешным. После этого вы можете попробовать позвонить RenderStream для предварительного просмотра, и Smart Tee следует добавить, если он еще не добавлен с первым вызовом. Сообщите мне, смогу ли я помочь вам в этом.

+0

Большое спасибо за ваш ответ и помощь. Я добавил фрагмент кода для большей ясности. Возможно, вы, вероятно, правы в том, чтобы сначала вызвать RenderStream для Capture. Тем не менее, в моем случае, мне нужно сначала просмотреть видео в моем приложении, после чего захват будет добавлен пользователем, если потребуется. Последовательность, которая генерирует приведенный выше график, является [1] - [2] - [3] - [1] или [1] - [2] - [1] - [3]. Мое последнее грязное средство - это добавить ручное построение графа для второго вызова предварительного просмотра. Эта последовательность [1] - [2] - [3] - [4] работает. –

+0

1-2-3-4 выглядит нормально на первый взгляд. В противном случае, если вам нужно его оптимизировать (если это вообще возможно), вы можете попробовать перестроить весь график, удалив все фильтры и повторно добавив их, а затем выполните RenderStream (Capture ...) и RenderStream (Preview ...), когда пользователь решает включить захват в предварительный просмотр. – VuVirt

+0

Каков наилучший способ удалить существующий график? –

Смежные вопросы