Link to home
Start Free TrialLog in
Avatar of Babycorn-Starfish
Babycorn-StarfishFlag for United States of America

asked on

Manually Construct FilterGraph

I'm new to DirectX/DirectShow and experimenting with manually constructing graphs.

How would i go about manually constructing a FilterGraph whereby i have

MP3 File -> MPEG1 Stream Splitter -> MPEG Layer3 Decoder -> -DirectSound Renderer

this is basically the graph that is constructed if i use graph edit and choose File->Render Media File

Thanks for your help.
Avatar of jkr
jkr
Flag of Germany image

Building a filter graph basically means creating appropriate filters and joining them through pins so that they perform required operation successfully. See http://msdn2.microsoft.com/en-us/library/ms783701.aspx ("Overview of Graph Building") on how to do that. So you would first

IGraphBuilder* pIGB;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
    NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
    (void **)&pIGB);

and then add each filter by calling AddFilter, enumerate the pins on the filters, and connect them by calling either Connect or ConnectDirect. See also

http://msdn2.microsoft.com/en-us/library/ms779722.aspx ("Interfaces for Building Filter Graphs")

http://msdn2.microsoft.com/en-us/library/ms783753.aspx ("Graph-Building Components")

You will find an outline of the whole process at http://msdn2.microsoft.com/en-us/library/ms779725.aspx ("Building a VMR-9 Filter Graph") and a sample at http://www.codeguru.com/forum/archive/index.php/t-263290.html
Avatar of Babycorn-Starfish

ASKER

Hi,

here is the code i created that lead to me posting my Q, i abbreviated a lot of my error handling code for brevity. What i've basically tried to do is re-create the graph that graph edit creates when i select Render Media File, currently it does nothing so i guess there's something missing. I will look at the sites you posted, although i've read most of the MSDN documentation that comes with the DirectX SDK and the Platform SDK.

//create the GraphBuilder
                              IGraphBuilder* pGB;
                              HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGB);  
                              if(FAILED(hr)) {/*error*/}

                              //create the means by which to open the file
                              IBaseFilter* pSource;
                              hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSource);
                              if(FAILED(hr)) {/*error*/}

                              //create the file source
                              IFileSourceFilter* pFile;
                              hr =  pSource->QueryInterface(IID_IFileSourceFilter, (void**)&pFile);
                              if(FAILED(hr)) {/*error*/}

                              hr = pFile->Load(TEXT("C:\\Documents and Settings\\Jason\\My Documents\\My Music\\Ryan Adams\\Gold [Bonus Disc] Disc 1\\10 Enemy Fire.mp3"), NULL);
                              if(FAILED(hr))
                              {
                                    MessageBoxEx(NULL, TEXT("ERROR"), TEXT("Error Loading File Source"), MB_OK, 0);  
                              }
                              else
                              {
                                    pSource->Release();
                              }                   

                              //create the MPEG1Splitter
                              IBaseFilter* pMP3Splitter;
                              hr = CoCreateInstance(CLSID_MPEG1Splitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMP3Splitter);
                              if(FAILED(hr)) {/*error*/}

                              //create the MPEG Layer 3 Decoder
                              IBaseFilter* pDecoder;
                              hr = CoCreateInstance(CLSID_CMpegAudioCodec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pDecoder);
                              if(FAILED(hr)) {/*error*/}

                              //create the renderer
                              IBaseFilter* pRenderer;
                              hr = CoCreateInstance(CLSID_AudioRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pRenderer);
                              if(FAILED(hr)) {/*error*/}

                              //hook it all together somehow

                              //addFilters
                              pGB->AddFilter(pSource, NULL);
                              pGB->AddFilter(pMP3Splitter, NULL);
                              pGB->AddFilter(pDecoder, NULL);
                              pGB->AddFilter(pRenderer, NULL);

                              //sort out pins
                              IEnumPins* pEnumPins;
                              IPin* pInPin;
                              IPin* pOutPin;
                              ULONG fetched;
                              PIN_INFO pinInfo;

                              //get source output  
                              pSource->EnumPins(&pEnumPins);
                              pEnumPins->Reset();
                              if(FAILED(pEnumPins->Next(1, &pOutPin, &fetched))){/*error*/}

                              if(FAILED(pOutPin->QueryPinInfo(&pinInfo)))      {/*error*/}

                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_INPUT)
                              {
                                    pOutPin->Release();
                                    pEnumPins->Next(1, & pOutPin, &fetched);
                              }

                              pEnumPins->Release();

                              //get splitter input
                              pMP3Splitter->EnumPins(&pEnumPins);
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pInPin, &fetched);
                              pInPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_OUTPUT)
                              {
                                    pInPin->Release();
                                    pEnumPins->Next(1, &pInPin, &fetched);
                              }

                              //connect source output to splitter input
                              pGB->Connect(pOutPin, pInPin);
                              pInPin->Release();
                              pOutPin->Release();

                              //get the output from the splitter
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pOutPin, &fetched);
                              pOutPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();       
                              if(pinInfo.dir == PINDIR_INPUT)
                              {       
                                    pOutPin->Release();
                                    pEnumPins->Next(1, &pOutPin, &fetched);
                              }

                              pEnumPins->Release();              

                              //get Decoder input
                              pDecoder->EnumPins(&pEnumPins);
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pInPin, &fetched);
                              pInPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_OUTPUT)
                              {
                                    pInPin->Release();
                                    pEnumPins->Next(1, &pInPin, &fetched);
                              }

                              //connect splitter to decoder
                              pGB->Connect(pOutPin, pInPin);
                              pInPin->Release();
                              pOutPin->Release();

                              //get Decoder output
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pOutPin, &fetched);
                              pOutPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_INPUT)
                              {
                                    pOutPin->Release();
                                    pEnumPins->Next(1, &pOutPin, &fetched);
                              }

                              pEnumPins->Release();

                              //get renderer input pin
                              pRenderer->EnumPins(&pEnumPins);
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pInPin, &fetched);
                              pInPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_OUTPUT)
                              {
                                    pInPin->Release();
                                    pEnumPins->Next(1, &pInPin, &fetched);
                              }

                              //connect decoder to renderer
                              pGB->Connect(pOutPin, pInPin);
                              pInPin->Release();
                              pOutPin->Release();

                              //get renderer output pin
                              pEnumPins->Reset();
                              pEnumPins->Next(1, &pOutPin, &fetched);
                              pInPin->QueryPinInfo(&pinInfo);
                              pinInfo.pFilter->Release();
                              if(pinInfo.dir == PINDIR_INPUT)
                              {
                                    pOutPin->Release();
                                    pEnumPins->Next(1, &pOutPin, &fetched);
                              }
                              
                              //pGB->Render(pOutPin);
                              IMediaControl *pMC = NULL;
                              pGB->QueryInterface(IID_IMediaControl, (void**)&pMC);
                              pMC->Run();  
Hm, where in the above does it fail?
Hi,

it doesn't fail (or doesn't seem to) it just never actually does anything. I know if i let the filtergraph do all the work i just use RenderFile and pass the file name and it does all of the hardwork i was wondering whether there was maybe something the filtergraph does automatically that i need to do manually.


thx
ASKER CERTIFIED SOLUTION
Avatar of Babycorn-Starfish
Babycorn-Starfish
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Closed, 500 points refunded.
Vee_Mod
Community Support Moderator