Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在DirectShow中渲染捕获的视频/音频并将其保存为自定义文件/过滤器格式?_C++_Com_Directshow - Fatal编程技术网

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

C++ 如何在DirectShow中渲染捕获的视频/音频并将其保存为自定义文件/过滤器格式?,c++,com,directshow,C++,Com,Directshow,基本上,我想捕获音频/视频。通过mp4 muxer运行它并将其保存到磁盘上的文件中。在我使用ICaptureGraphBuilder2之前,但在保存为自定义格式时,它似乎无法使用 我的代码到目前为止 我列举了视频/音频设备。在这个示例中,我只尝试捕获音频。我得到了正确的设备,并使用GetPin枚举过滤器引脚以获得其输出引脚 hr = pMoniker2->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc2); hr = pGraph

基本上,我想捕获音频/视频。通过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);
这就是我迷路的地方,我不知道如何采取下一步渲染并将输出保存到磁盘上的文件。因此,任何后续步骤的帮助都将不胜感激,提前感谢

编辑:文件链接代码

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

您需要知道特定任务需要什么样的过滤图拓扑。你在抓捕,这里-很好。所以你们有了音频捕获过滤器,你们为它提供了代码片段。然后,您可以压缩音频(您的首选应该是
AAC
AKA MPEG-4第3部分,前提是您要生成MP4文件),或者保持音频未压缩。然后,您可以像这样连接MPEG-4多路复用器。多路复用器产生输出流,您需要用它来完成管道

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

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


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

如果我理解正确的话。将麦克风输出端连接至MP4多路复用器输入端。如果这是正确的,那么我就走在正确的道路上。然后我被卡住了。所以我应该创建一个FileLink,找到输入引脚并将其连接到MP4多路复用器输出?然后一切都设置好了,我只需要像以前一样在我的filtergraph上使用启动-停止的MediaControl?如果我是对的,如果你不介意我问的话,你有没有找到IFileSinkFilter引脚的建议?也非常感谢这张图片,我相信它让一切都更加清晰:)
Temp.mp4
在我的截图上是
filewriter
,它既有
IBaseFilter
又有
IFileSinkFilter
。也就是说,你添加了它,将它的pin连接到输入,设置文件名,你就可以开始了。请原谅我对COM和Directshow缺乏经验。我不能100%确定如何使用这两个过滤器实现Filewriter。我在我的帖子中添加了一些代码,这些代码符合我认为你的意思,但是在连接filewriter输入和mpeg4mux输出时失败了。如果你能在有时间的时候看一看,并指出我做错了什么,我会非常感激。你的代码差不多是对的。在
SetFileName
call中不需要媒体类型,毕竟您在那里提供了视频媒体类型,而您的问题是关于录制音频。途中是否有
hr
错误?考虑使用智能指针<代码> CCOPTR <代码>以更好地管理代码和可读性。好的,坏的消息。似乎你对媒体类型的看法是对的,如果我将其设置为NULL,那么即使我将捕获源更改为视频,一切都会正常运行。但在这两种情况下,即使没有错误,也不会创建输出文件。我在每次调用后放置if(FAILED(hr)){printf(“error”);},但没有错误弹出。可能是媒体类型吗?有什么想法吗?我还更新了更改,并在媒体控件中添加了代码的最后一部分,以防我搞砸了。再次感谢你的坚持和耐心。