如何渲染和保存捕获的视频/音频到自定义文件/过滤器格式在DirectShow? [英] How to render and save captured Video/Audio into a custom file/filter format in DirectShow?

查看:699
本文介绍了如何渲染和保存捕获的视频/音频到自定义文件/过滤器格式在DirectShow?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Basicly,我想要捕获音频/视频。通过mp4 muxer运行它,并将其保存到磁盘上的文件。在我使用ICaptureGraphBuilder2之前,但它似乎无法保存到自定义格式。



我的代码到目前为止,



我枚举了视频/音频设备。在这个例子中,我只试图捕获音频。我得到正确的设备,并使用GetPin枚举过滤器引脚以获得其输出引脚。

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

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

这是自定义过滤器,MP4 muxer。它正确加载,我可以得到输入引脚,并与我的输出引脚连接。到目前为止这么好。

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

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

这是我迷路的地方,我找不到如何进行下一步骤并将输出保存到磁盘上的文件。所以任何帮助下一步将被非常感谢,提前感谢!



EDIT: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;
//不是100%确定媒体格式的设置。

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,LAudioCap);
hr = GetPin(pSrc2,PINDIR_OUTPUT,& outPin); // ADDED

hr = pGraph-> AddFilter(iFiltera,LFileWriter);
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,LPrivate 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;错误0x80040217(VFW_E_CANNOT_CONNECT?)//现在工作

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

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


解决方案

需要具体任务。你在捕获,这里 - 罚款。所以你有你提供的代码段的音频捕获过滤器。然后你要么压缩音频(你的首选应该是 AAC AKA MPEG-4第3部分,前提是你要生产MP4文件),或保持音频未压缩的PCM。然后你像你一样连接MPEG-4多路复用器。多路复用器会生成输出流,您需要使用完成管道文件编写器过滤器



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





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

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


Basiclly, I want to capture audio/video. Run it through a mp4 muxer and save it to a file on disk. Before I used ICaptureGraphBuilder2, but it seems unusuable when saving to custom formats.

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.

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. 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

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. Then you connect MPEG-4 multiplexer as you do. The multiplexer produces output stream and you are expected to complete the pipeline with File Writer Filter.

You can manually build the chain in GraphEdit SDK application (or there are alternate richer tools). 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.

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). Your pipeline is ready to run.

这篇关于如何渲染和保存捕获的视频/音频到自定义文件/过滤器格式在DirectShow?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆