简体   繁体   English

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

[英]How to render and save captured Video/Audio into a custom file/filter format in DirectShow?

Basiclly, I want to capture audio/video. 基本上,我想捕获音频/视频。 Run it through a mp4 muxer and save it to a file on disk. 通过mp4混合器运行它,并将其保存到磁盘上的文件中。 Before I used ICaptureGraphBuilder2, but it seems unusuable when saving to custom formats. 在使用ICaptureGraphBuilder2之前,但保存为自定义格式时似乎没用。

My code so far, 到目前为止,我的代码

I enumerate video/audio devices. 我列举了视频/音频设备。 In this sample I only try to capture audio. 在此示例中,我仅尝试捕获音频。 I get the correct device and use GetPin to enumerate the filters pins to get its output pin. 我得到正确的设备,并使用GetPin枚举过滤器引脚以获取其输出引脚。

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

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

This is the custom filter, a MP4 muxer. 这是自定义过滤器,一个MP4混合器。 It properly loads and I can get the input pin and connect it with my output pin. 它加载正确,我可以得到输入引脚并将其连接到我的输出引脚。 So far so good. 到现在为止还挺好。

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);

This is where I get lost, I can't find out how to take the next steps to Render and save the output to a file on disk. 这是我迷路的地方,我找不到如何执行下一步渲染并将输出保存到磁盘上的文件的方法。 So any help with the next steps would be greatfully appreciated, thanks in advance! 因此,在此先感谢您对下一步的任何帮助!

EDIT: Filesink code 编辑: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();  

You need to have an idea what filter graph topology you need for specific task. 您需要了解特定任务需要哪种过滤器图拓扑。 You are doing capture, here - fine. 您正在捕获,在这里-很好。 So you have audio capture filter you provided code snippet for. 因此,您有提供了代码段的音频捕获过滤器。 Then you either compress audio (where your preferred choice should be AAC AKA MPEG-4 Part 3, provided that you are to produce MP4 file), or keep audio uncompressed PCM. 然后,要么压缩音频(如果要生成MP4文件,则首选为AAC AKA MPEG-4第3部分),或者使音频保持未压缩的PCM。 Then you connect MPEG-4 multiplexer as you do. 然后,您就可以连接MPEG-4多路复用器了。 The multiplexer produces output stream and you are expected to complete the pipeline with File Writer Filter . 多路复用器产生输出流,您应该使用File Writer Filter完成流水线。

You can manually build the chain in GraphEdit SDK application (or there are alternate richer tools). 您可以在GraphEdit SDK应用程序中手动构建链(或者有其他更丰富的工具)。 Your filter graph looks like this: 您的过滤器图形如下所示:

筛选图

Note that you can expose filter graph in your application, and connect to it remotely and inspect the topology. 请注意,您可以在应用程序中公开过滤器图,然后远程连接到它并检查拓扑。 This makes debugging much easier. 这使调试更加容易。 Starting/stopping the filter graph ( IMediaControl::Run , ::Stop from code) creates you the file. 启动/停止过滤器图形(代码中的IMediaControl::Run::Stop )将为您创建文件。

My understanding is that you get lost immediately after adding multiplexer. 我的理解是,添加多路复用器后,您会立即迷路。 Now you need to find its output pin, add File Writer , query its IFileSinkFilter , set the destination file name using it, find its input pin, connect the two unconnected pins (mux output, writer input). 现在,您需要找到其输出引脚,添加File Writer ,查询其IFileSinkFilter ,使用它设置目标文件名,找到其输入引脚,连接两个未连接的引脚(多路复用器输出,写入器输入)。 Your pipeline is ready to run. 您的管道已准备就绪,可以运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM