如何使用文件编写器过滤器呈现过滤器图

How to render filtergraph with FileWriter filter

本文关键字:过滤器 何使用 文件      更新时间:2023-10-16

过滤器图呈现器方法采用输出引脚的引用。但是文件编写器筛选器没有输出引脚。那么如何使筛选器图自行呈现呢?

HRESULT hr = pGraph->Render(FilefilterOutPin); //File Writer does not offer an outputpin

这是我使用过滤器构建图形的代码:

void static SaveFile()
{

    CoInitialize(NULL);
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent *pEvent = NULL;
    HRESULT myhr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
        IID_IFilterGraph, (void **) &pGraph);
    pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    pGraph->QueryInterface(IID_IMediaEvent, (void **) &pEvent);
    IBaseFilter *pFileWritter;
    IFileSinkFilter* fileSInk = NULL;
    CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pFileWritter);
    pFileWritter->QueryInterface(IID_IFileSinkFilter, (void **) &fileSInk);

    fileSInk->SetFileName(L"C:\TEMP\yc1.avi", NULL);
    //get source out pin
    IBaseFilter *pSource;
    IPin* SourcePin;
    pGraph->AddSourceFilter(L"C:\TEMP\sample.avi", L"sample", &pSource);
    SourcePin = GetPin(pSource, PINDIR_OUTPUT);
    //AVI SPLITTER
    IBaseFilter *aviSplitter;
    CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &aviSplitter);
    pGraph->AddFilter(aviSplitter, L"AVI-Splitter");
    IPin* avisplitIn;
    IPin* avisplitOut;
    avisplitIn = GetPin(aviSplitter, PINDIR_INPUT);
    avisplitOut = GetPin(aviSplitter, PINDIR_OUTPUT);
    pGraph->Connect(SourcePin, avisplitIn);
    //END

    //MyFilter//
    IBaseFilter *myFilter;
    CoCreateInstance(CLSID_MyFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &myFilter);
    IMyFilter *myfilterinterface;
    myFilter->QueryInterface(IID_IMyFilter, (void **) &myfilterinterface);
    myfilterinterface->StartRecording();
    pGraph->AddFilter(myFilter, L"MyFilter");
    IPin* myInputPin;
    IPin* myOutPutPin;
    myInputPin = myfilterinterface->GetMyPin(0);
    myOutPutPin = myfilterinterface->GetMyPin(3);
    pGraph->Connect(avisplitOut, myInputPin);
    //END//

    ///AVMUX
    IBaseFilter *avmux;
    CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &avmux);
    IPin* avmuxIn;
    IPin* avmuxOut;
    avmuxIn = GetPin(avmux, PINDIR_INPUT);
    avmuxOut = GetPin(avmux, PINDIR_OUTPUT);
    pGraph->AddFilter(avmux, L"AVmux");
    pGraph->Connect(myOutPutPin, avmuxIn);

    //END
    //get writer inpin
    IPin *writerPin;
    writerPin = GetPin(pFileWritter, PINDIR_INPUT);

    //connect pins
    pGraph->Connect(SourcePin, writerPin);
    //render
    HRESULT hr S_OK;
    if(SUCCEEDED(hr))
    {
        hr = pControl->Run();
        if(SUCCEEDED(hr))
        {
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);
            myfilterinterface->StopRecording();
            myFilter->Release();
                   CoUninitialize();
        }
    }



}

这可以编译并运行良好,但不生成任何文件。

引脚连接过滤器,使它们能够将数据传递到另一个。文件编写器没有任何要流式传输数据的内容 - 相反,它只是要文件的编写器。因此,没有输出引脚。

要指定IFileSinkFilter::SetFileName界面使用的文件名(请参阅更改文件名时,录制开始时间已过期 3 秒)。 OnTimer使用它的代码片段)。

因此,

如果我理解正确,您希望渲染到屏幕并渲染到文件。

为此,您需要在 AVI 分配器和 AVI 多路复用器之间放置一个无限引脚 T 恤。 三通的 1 个输出将继续转到 AVI 复用器,您可以使用另一个输出流式传输到视频渲染器(例如 VMR9)。

请在 MSDN 中阅读 Render 方法的作用,这不是您的想法。最接近你的想法的是RenderStream(从稍微不同的界面,查找一下),FileWriter在其最后一个参数中。但请先学习一些DirectShow基础知识。

首先,FileWriter Filter 只有输入引脚,因为它接收数据并写入文件。

其次,如果要播放文件,则应使用文件源(异步)过滤器。因此,创建一个文件源(异步)的实例,获取其输出引脚并传递给

pGraph->Render(FileSourceOutputPin);

第三,或者你可以像这样渲染文件:

pGraph->RenderFile("C:\test.avi", "");