How to visualize and save captured video / audio to a user file / filter format in DirectShow?

Basically, I want to capture audio / video. Run it through the mp4 multiplexer and save it to a file on disk. Before I used ICaptureGraphBuilder2, but this seems unusual when saving in custom formats.

My code is still

I list video / audio devices. In this example, I'm only trying to capture audio. I get the correct device and use GetPin to list filter contacts to get output.

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

This is a custom filter, MP4 multiplexer. It loads correctly, and I can get the input pin and connect it to the 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); 

Here I am lost, I can’t find out how to take the following steps for rendering and save the output to a file on disk. So any help with the following steps would be greatly appreciated, thanks in advance!

EDIT: File 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(); 
0
source share
1 answer

You need to have an idea of ​​the topology of the filter topology that you need for a specific task. You make a capture, here it’s fine. So you have a sound capture filter that you provided a piece of code. Then you either compress the audio (where your preferred choice should be AAC AKA MPEG-4 Part 3, provided you have to create the MP4 file), or save the audio files without PCM compression. Then you connect the MPEG-4 multiplexer, just like you. The multiplexer creates an output stream, and you expect to complete the pipeline using File Writer Filter .

You can manually create a chain in the GraphEdit SDK application (or there are alternative richer tools). The filter graph is as follows:

Filter graph

Please note that you can open the filter graph in your application and connect to it remotely and check the topology. This greatly facilitates debugging. Starting / stopping the filter graph ( IMediaControl::Run , ::Stop from the code) creates a file.

I understand that you are lost right after adding the multiplexer. Now you need to find the output, add a File Writer , request its IFileSinkFilter , set the name of the destination file using it, find its input contact, connect two unconnected contacts (multiplexer output, write input). Your pipeline is ready to go.

0
source

Source: https://habr.com/ru/post/918955/


All Articles