如何在DirectShow中将捕获的视频/音频渲染并保存为自定义文件/过滤器格式?

时间:2012-06-26 08:01:14

标签: c++ com directshow

基本上,我想捕获音频/视频。通过mp4 muxer运行它并将其保存到磁盘上的文件中。在我使用ICaptureGraphBuilder2之前,但在保存为自定义格式时似乎不可用。

我的代码到目前为止,

我列举了视频/音频设备。在此示例中,我只尝试捕获音频。我得到了正确的器件,并使用GetPin枚举滤波器引脚以获得其输出引脚。

hr = pMoniker2->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc2);
hr = pGraph->AddFilter(pSrc2, L"AudioCap");

hr = GetPin(pSrc2, PINDIR_OUTPUT, &outPin);

这是自定义过滤器,MP4复用器。它正确加载,我可以得到输入引脚并将其与我的输出引脚连接。到目前为止一切都很好。

HRESULT hr = CreateObjectFromPath(TEXT("c:\\filters\\mp4mux.dll"), clsid, &pUnk);
if (SUCCEEDED(hr))
{
    IBaseFilterPtr pFilter = pUnk;
    HRESULT hr = pGraph->AddFilter(pFilter, L"Private Filter");
    hr = GetPin(pFilter, PINDIR_INPUT, &inPin);
}

hr = pGraph->Connect(outPin, inPin);

这是我迷路的地方,我无法找到如何采取后续步骤渲染并将输出保存到磁盘上的文件。因此,非常感谢任何有关后续步骤的帮助,提前感谢!

编辑:Filesink代码

AM_MEDIA_TYPE mType;

mType.majortype = MEDIATYPE_Video;
mType.subtype = MEDIASUBTYPE_H264;
mType.bFixedSizeSamples = FALSE;
mType.bTemporalCompression = TRUE;
mType.lSampleSize = 0;
mType.formattype = FORMAT_None;
mType.pUnk = NULL;
mType.cbFormat = 0;
mType.pbFormat = NULL;
//Not 100% sure about the setup of the media format.

IBaseFilter * iFiltera = NULL; 
IFileSinkFilter* iFilter = NULL; 
IGraphBuilder *pGraph;

hr = pMoniker2->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc2); //audio capture
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  IID_IGraphBuilder, (void**)&pGraph);
hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&iFiltera);

hr = pBuild->SetFiltergraph(pGraph);

hr = pGraph->AddFilter(pSrc2, L"AudioCap");
hr = GetPin(pSrc2, PINDIR_OUTPUT, &outPin); //ADDED

hr = pGraph->AddFilter(iFiltera, L"FileWriter");
hr = iFiltera->QueryInterface(IID_IFileSinkFilter, (void**)&iFilter);

iFilter->SetFileName((LPCOLESTR)"c:\\wav\\tester.mp4", NULL); //UPDATED mType set to NULL

HRESULT hr = CreateObjectFromPath(TEXT("c:\\filters\\mp4mux.dll"), clsid, &pUnk);

IBaseFilterPtr pFilter = pUnk;
if (SUCCEEDED(hr))
{

    HRESULT hr = pGraph->AddFilter(pFilter, L"Private Filter");
    hr = GetPin(pFilter, PINDIR_INPUT, &inPin); //mux in

    hr = GetPin(pFilter, PINDIR_OUTPUT, &mOutPin); //mux out
    hr = GetPin(iFiltera, PINDIR_INPUT, &filePin); // filewriter in
}

hr = pGraph->Connect(outPin, inPin); //connect audio out and mux in
hr = pGraph->Connect(mOutPin, filePin); //connect mux out and file in; Error 0x80040217(VFW_E_CANNOT_CONNECT?) //works now

//ADDED code
IMediaControl *pMC = NULL;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);

hr = pMC->Run();
Sleep(4000);
hr = pMC->Stop();  

1 个答案:

答案 0 :(得分:1)

您需要了解特定任务所需的过滤器图形拓扑。你在捕捉,这里 - 很好。所以你有音频捕获过滤器,你提供了代码片段。然后你压缩音频(你首选的选择应该是AAC AKA MPEG-4 Part 3,前提是你要生成MP4文件),或者保持音频未压缩的PCM。然后像您一样连接MPEG-4多路复用器。多路复用器生成输出流,您需要使用File Writer Filter完成管道。

您可以在GraphEdit SDK应用程序中手动构建链(或者有其他更丰富的工具)。您的过滤器图形如下所示:

Filter Graph

请注意,您可以在应用程序中公开过滤器图形,并远程连接到该图形并检查拓扑。这使调试更容易。从代码中启动/停止过滤器图表(IMediaControl::Run::Stop)会为您创建文件。

我的理解是你在添加多路复用器后立即迷路了。现在您需要找到其输出引脚,添加File Writer,查询其IFileSinkFilter,使用它设置目标文件名,找到其输入引脚,连接两个未连接的引脚(多路复用输出,写入器输入)。您的管道已准备好运行。