【问题标题】:How to render and save captured Video/Audio into a custom file/filter format in DirectShow?如何在 DirectShow 中将捕获的视频/音频渲染并保存为自定义文件/过滤器格式?
【发布时间】:2012-06-26 08:01:13
【问题描述】:

基本上,我想捕捉音频/视频。通过 mp4 多路复用器运行它并将其保存到磁盘上的文件中。在我使用 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);

这是我迷路的地方,我不知道如何采取后续步骤进行渲染并将输出保存到磁盘上的文件中。因此,对于后续步骤的任何帮助将不胜感激,在此先感谢!

编辑:文件接收器代码

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

【问题讨论】:

    标签: c++ com directshow


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 如果我理解这个权利。将麦克风输出连接到 MP4 多路复用器输入。如果那是正确的,那么我就在正确的道路上。然后我卡住了。所以我应该创建一个文件接收器,找到输入引脚并将其连接到 MP4 多路复用器输出?然后一切都设置好了,我只是像以前一样在我的过滤器上使用媒体控件和开始停止?如果我是对的,如果你不介意我问,你有没有找到 IFileSinkFilter 引脚的建议?也非常感谢那张照片,我相信它让一切变得更加清晰:)
    • Temp.mp4 在我的屏幕截图中是File Writer,它同时具有IBaseFilterIFileSinkFilter。那就是你添加它,将它的引脚连接到输入,设置文件名,你就可以开始了。
    • 请原谅我对 COM 和 Directshow 的缺乏经验。我不是 100% 确定如何使用两个过滤器实现 Filewriter。我在我的帖子中添加了一些代码,这些代码符合我的意思,但是它无法将文件写入器输入与 mpeg4mux 输出连接起来。如果您有时间可以查看它并指出我做错了什么,非常感谢。
    • 您的代码是正确的。 SetFileName 通话中不需要媒体类型,毕竟您在此处提供视频媒体类型,而您的问题是关于录制音频。途中是否有任何hr 错误?考虑使用智能指针CComPtr 以获得更好的引用管理和代码的可读性。
    • 好吧,好消息和坏消息。看来您对媒体类型的看法是正确的,如果我将其设置为 NULL,即使我将捕获源更改为视频,一切似乎都运行良好。但是在这两种情况下,即使没有错误,也没有创建输出文件。我在每次通话后都放了 if(FAILED(hr)){printf("error");} 但没有错误弹出。会不会是媒体类型?有任何想法吗?我还更新了更改,并在我的代码的最后一部分添加了媒体控件,以防我以某种方式搞砸了。再次感谢您的坚持和耐心。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多