CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    Join Date
    Feb 2001
    Posts
    179

    Directx filter graph

    I am using to customize the async file reader filter graph, but I can't get it to play the MPEG video. If I add the filter in GraphEdit, it plays. The async file reader is for reading the MPEG file data.

    From the GrpahEdit, I know which components it is using, so I try to connect them in my code, but I can't get it to play. The Async file reader has an interface "Load" to accept the MPEG file name, but I don't know how and when to call it.

    Also, g_pGraphBuilder->Connect(OutPin, InPin) returns status of 0x80040218 which is "No Combination of Filters Could Be Found to Render the Stream"


    Following it my code and thanks in advance for your help.

    void CMainFrame::OnTestFilter()
    {
    // TODO: Add your command handler code here
    CoInitialize(NULL);

    // Create the filter graph manager and query for interfaces.
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, (void **)&g_pGraphBuilder);
    g_pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
    g_pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    CreateFilters();
    ConnectFilters();


    // Run the graph.
    pMediaControl->Run();

    // Wait for completion.
    long evCode;
    pEvent->WaitForCompletion(INFINITE, &evCode);

    // Clean up.
    pMediaControl->Release();
    pEvent->Release();
    g_pGraphBuilder->Release();
    CoUninitialize();

    }

    void CMainFrame::CreateFilters()
    {
    status = CoCreateInstance(CLSID_AsyncFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pAsyncFilter);
    if (FAILED(status))
    report(status);
    CoCreateInstance(CLSID_MPEG1Splitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pMPEG1Splitter);
    CoCreateInstance(CLSID_CMpegVideoCodec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pCMpegVideoCodec);
    CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pVideoRenderer);
    if (FAILED(status))
    report(status);
    status = g_pGraphBuilder->AddFilter(g_pAsyncFilter, NULL);
    if (FAILED(status))
    report(status);
    g_pGraphBuilder->AddFilter(g_pMPEG1Splitter, NULL);
    g_pGraphBuilder->AddFilter(g_pCMpegVideoCodec, NULL);
    g_pGraphBuilder->AddFilter(g_pVideoRenderer, NULL);
    }

    void CMainFrame::ConnectFilters()
    {
    IEnumPins* EnumPins;
    IPin* OutPin;
    IPin* InPin;
    ULONG fetched;
    PIN_INFO pinfo;
    g_pAsyncFilter->EnumPins(&EnumPins);
    // find AsyncFilter output
    EnumPins->Reset();
    status = EnumPins->Next(1, &OutPin, &fetched);
    if (FAILED(status))
    report(status);
    status = OutPin->QueryPinInfo(&pinfo);
    if (FAILED(status))
    report(status);
    pinfo.pFilter->Release();
    if (pinfo.dir == PINDIR_INPUT)
    {
    OutPin->Release();
    status = EnumPins->Next(1, &OutPin, &fetched);
    if (FAILED(status))
    report(status);
    }
    EnumPins->Release();

    // find MPEG1Splitter input
    g_pMPEG1Splitter->EnumPins(&EnumPins);
    EnumPins->Reset();
    status = EnumPins->Next(1, &InPin, &fetched);
    if (FAILED(status))
    report(status);
    status = InPin->QueryPinInfo(&pinfo);
    if (FAILED(status))
    report(status);
    pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
    if (pinfo.dir == PINDIR_OUTPUT) // check if we have wrong pin (not input pin)
    {
    InPin->Release();
    status = EnumPins->Next(1, &InPin, &fetched); // if so, get next pin
    if (FAILED(status))
    report(status);
    }

    // connect --
    status = g_pGraphBuilder->Connect(OutPin, InPin);
    if (FAILED(status))
    report(status);
    InPin->Release();
    OutPin->Release();

    // find MPEG1Splitter output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();
    if (pinfo.dir == PINDIR_INPUT)
    {
    OutPin->Release();
    EnumPins->Next(1, &OutPin, &fetched);
    }
    EnumPins->Release();

    // find CMpegVideoCodec input
    g_pCMpegVideoCodec->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    InPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
    if (pinfo.dir == PINDIR_OUTPUT) // check if we have wrong pin (not input pin)
    {
    InPin->Release();
    EnumPins->Next(1, &InPin, &fetched); // if so, get next pin
    }

    // connect --
    status = g_pGraphBuilder->Connect(OutPin, InPin);
    if (FAILED(status))
    report(status);
    InPin->Release();
    OutPin->Release();

    // find CMpegVideoCodec output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();
    if (pinfo.dir == PINDIR_INPUT)
    {
    OutPin->Release();
    EnumPins->Next(1, &OutPin, &fetched);
    }
    EnumPins->Release();

    // find VideoRenderer input
    g_pVideoRenderer->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched); // renderer has only 1 pin, so this is the pin we need
    EnumPins->Release();

    // connect --
    status = g_pGraphBuilder->Connect(OutPin, InPin);
    if (FAILED(status))
    report(status);
    InPin->Release();
    OutPin->Release();
    }

  2. #2
    Join Date
    Aug 1999
    Posts
    107
    have you tried looking at the filter graph you are building programatically in GraphEdit to make sure that you are really building the graph correctly??

    You can register the graph inside of your code so that it can be viewed in GraphEdit which can be a very useful debugging tool

    Code:
    	static DWORD rotID;
    HRESULT AddToGraphEdit(IUnknown *pUnkGraph, DWORD *pdwRegister)  
    {
        IMoniker * pMoniker;
        IRunningObjectTable *pROT;
        if (FAILED(GetRunningObjectTable(0, &pROT))) {
            return E_FAIL;
        }
        WCHAR wsz[256];
        wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
        HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
        if (SUCCEEDED(hr)) {
            hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
            pMoniker->Release();
        }
        pROT->Release();
        return hr;
    }
    void RemoveFromGraphEdit(DWORD pdwRegister)
    {
        IRunningObjectTable *pROT;
        if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
            pROT->Revoke(pdwRegister);
            pROT->Release();
        }
    }
    // Create the filter graph manager and query for interfaces.
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, (void **)&g_pGraphBuilder);

    **** register
    AddToGraphEdit(g_pGraphBuilder, &rotID);

    **** don't forget to unregister it when you are done. Quite a few of the microsoft sample apps that build filter graphs dynamically register their graphs for debugging purposes

  3. #3
    Join Date
    Feb 2001
    Posts
    179
    CJE,

    Thanks for your reply.

    My custom Async filter graph is running fine if I use it within the GraphEdit, but running it from my code is the problem (nothing happens).

    So where do I put your code AddToGraphEdit, in the filter graph or the app? Where/When do I call it? Is pUnkGraph the g_pAsyncFilter (my app)? What is pdwRegister and how do I get it?

  4. #4
    Join Date
    Aug 1999
    Posts
    107
    please look at microsoft sample code for building filter graphs you will then learn the basics... register the graph right after you create the instance

    **** this is your code
    // Create the filter graph manager and query for interfaces.
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, (void **)&g_pGraphBuilder);

    **** add this call
    AddToGraphEdit(g_pGraphBuilder, &rotID);

    once the graph is registered you can use GraphEdit to attach to it and see the graph to make sure it is connected properly and contains the filters that you expect.

  5. #5
    Join Date
    Dec 2000
    Location
    Slovakia
    Posts
    1,043
    I didnot look at your code at details because I am leaving company now... However why do you build your graph manually? You can use RenderEx() method of IFilterGraph2 inteface (query the FilterGraph for that interface) or you can directly use RenderFile() function of IGraphBuilder interface...

    1.) RenderEx(). Just create instance of FilterGraph and call IGraphBuilder::AddSourceFilter() method to create and add source filter for specified media file. Then enumerate output pins of the source filter and call IFilterGraph2::RenderEx() for all of these pins and then just run the graph...

    2.) RenderFile(). Create instance of FilterGraph and call IGraphBuilder::RenderFile() to build graph for the media fila automatically. The same as Render media file menu option in GraphEdit...

    The second one will connect the output of source filter to the default audio and video renderers. If you need to use some "advanced" renderers like VMR9 or special audio renderer then use the first possibility and call RenderEx() method with parameter AM_RENDEREX_RENDERTOEXISTINGRENDERERS. However, in this case you need to add renderers into the graph manually...

    Do you have some reason for not using these approaches???

    Martin

  6. #6
    Join Date
    Dec 2000
    Location
    Slovakia
    Posts
    1,043
    I am already back so I can continue and write you a little sample... Personally, I would use the second option...

    Code:
    #include <string>
    #include <comutil.h>
    #include <comdef.h>
    #include <dshow.h>
    #include <d3d9.h>
    #include <d3dc9tex.h>
    #include <vmr9.h>
    
    #define SafeRelease(p) if (p) { p.Release(); p = NULL; }
    #define com_call(m) if (FAILED(hr=m)) break;
    
    class CPlayer
    {
    public:
        CPlayer(HWND hWndPlayback);
        ~CPlayer();
    
    public:
        HRESULT LoadMedia(std::string strMediaFile);
        void Start();
        void Stop();
    
    protected:
        CComPtr<IGraphBuilder> m_pGraph;
        CComPtr<IBaseFilter> m_pVideoRenderer;
        CComPtr<IBaseFilter> m_pAudioRenderer;
        CComPtr<IMediaControl> m_pControl;
    
        HWND m_hWndPlayback;
    
        void CleanUp();
    
        HRESULT InitializeVmr();
        HRESULT ConnectFilters(IBaseFilter* pFilter, IFilterGraph2* pFg2);
    };
    
    CPlayer::CPlayer(HWND hWndPlayback) :
        m_hWndPlayback(hNwdPlayback)
    {
    }
    
    CPlayer::~CPlayer()
    {
        Stop();
        CleanUp();
    }
    
    void CPlayer::CleanUp()
    {
        SafeRelease(m_pVideoRenderer);
        SafeRelease(m_pAudioRenderer);
        SafeRelease(m_pControl);
        SafeRelease(m_pGraph);
    }
    
    void CPlayer::Stop()
    {
        if (m_pControl != NULL)
            m_pControl->Start();
    }
    
    void CPlayer::Start()
    {
        if (m_pControl != NULL)
            m_pControl->Run();
    }
    
    HRESULT CPlayer::LoadMedia(std::string strFileName)
    {
        HRESULT hr = S_OK;
    
        CleanUp();
    
        CComPtr<IBaseFilter> pSource = NULL;    
        CComPtr<IBaseFilter> pFilterGraph2 = NULL;
    
        do {
            com_call(m_pGraph.CoCreateInstance(CLSID_FilterGraph));
    
            com_call(m_pGraph->AddSourceFilter(_bstr_t(strMediaFile.c_str()), L"Source Filter", &pSource));
    
            com_call(InitializeVmr());
    
            com_call(m_pAudioRenderer.CoCreateInstance(CLSID_DSoundRenderer));
     
            com_call(m_pGraph->AddFilter(m_pAudioRenderer, L"Default DirectSound Renderer"));
    
            com_call(m_pGraph.QueryInterface(&pFilterGraph2));
     
            com_call(ConnectFilters(pSource, pFilterGraph2));
    
            com_call(m_pGraph.QueryInterface(&m_pControl));
    
            return S_OK;
        } while (false);
    
        SafeRelease(m_pVideoRenderer);
        SafeRelease(m_pAudioRenderer);
        SafeRelease(m_pControl);
        SafeRelease(m_pGraph);
        
        return hr;
    }
    
    // Uses VideoMixingRenderer9 in windowless mode.
    // It runs just under the WinXP.
    HRESULT CPlayer::InitializeVmr()
    {
        HRESULT hr = S_OK;
        hr = m_pVideoRenderer.CoCreateInstance(CLSID_VideoMixingRenderer9);
        if (FAILED(hr))
            return hr;
    
        hr = m_pGraph->AddFilter(m_pVideoRenderer);
        if (FAILED(hr))
            return hr;
    
        CComPtr<IVMRFilterConfig9> pConfig;
        hr = m_pVideoRenderer.QueryInterface(&pConfig);
        if (FAILED(hr))
            return hr;
    
        pConfig->SetNumberOfStreams(1); // Just one video stream to render
        pConfig->SetRenderingMode(VMR9Mode_Windowless);
        pConfig->SetRenderingPrefs(RenderPrefs_AllowOverlays);
    
        SafeRelease(pConfig);
    
        CComPtr<IVMRWindowlessControl9> pControl;
        hr = m_pVideoRenderer.QueryInterface(&pControl);
        if (FAILED(hr))
            return hr;
    
        RECT rc;
        GetClientRect(m_hWndPlayback, &rc);
        pControl->SetVideoClippingWindow(m_hWndPlayback);
        pControl->SetVideoPosition(NULL, &rc);
        pControl->SetAspecRatioMode(VMR9Mode_LetterBox);
        pControl->SetBorderColor(RGB(0, 0, 0));
    
        SafeRelease(pControl);
    
        return S_OK;
    }
    
    HRESULT CPlayer::ConnectFilters(IBaseFilter* pFilter, IFilterGraph2* pFg2)
    {
        CComPtr<IEnumPins> pEnum;
        CComPtr<IPin> pPin;
    
        HRESULT hr = pFilter->EnumPins(&pEnum);
        if (FAILED(hr))
            return hr;
    
        while (pEnum->Next(1, &pPin, NULL) == S_OK)
        {
            PIN_DIRECTION pdDirection;
            pPin->QueryDirection(&pdDirection);
            if (pdDirection == PINDIR_OUTPUT)
            {
                hr = pFg2->RenderEx(pPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS);
                if (FAILED(hr))
                    return hr;
            }
            pPin.Release();
        }
    
        return S_OK;
    }
    I didnot test directly this code however I used something like this in a couple projects...

    martin

  7. #7
    Join Date
    Feb 2001
    Posts
    179
    Martin,

    Thank you for your detail response.

    My goal is to have a player that can play the mpeg while the mpeg file is being encoded. Currently I can't play the mpeg file using mpeg player such as Windows Media Player because it can't access the file while the mpeg file is being build (encoded). That's why I need to setup an async file reader (filter) to read the mpeg file, and as more data is in the mpeg, the reader can read the additional data and continue to play the mpeg video (like a streaming file). In additional the player should be able to seek a frame and start playing from there.

    Do you have something like that or how do I go about doing it?

    Thanks again!

  8. #8
    Join Date
    Dec 2000
    Location
    Slovakia
    Posts
    1,043
    Hm.. Even Async File Reader can't open the file if it is locked by another filter (file writer in encoding graph). So once you run the graph for encoding is not possible to build graph for playing that file until the encoding process finishes.

    What do you want to achieve?
    Generally there are 2 possibilities where you need this...
    - implementation of something like time-shift functionality on live sources.
    - streaming mpeg file through network..

    What is your goal?

    Because there are already some filters in directshow 9.0 you can use for time-shifting. And also there are some samples how to stream mpeg through network in DirectShow documentation...

    martin

  9. #9
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940
    Sureley what you want to do is to set up the default reader object for MPEG to be your asynchronous object.

    There is documentation in the DirectX help files which tell you how to do this. Its actually only one registry setting.

    It saves all the mucking about with connecting/disconnecting pins I can tell you.

    Darwen.

  10. #10
    Join Date
    Feb 2001
    Posts
    179
    Daren,

    What do you mean by default reader object. If I use this to read the mpeg file, would pSourece be my default object?

    status = CoCreateInstance(CLSID_AsyncFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSource);

    Do you have some sample code?

    What is the registry setting in DirectX to set it?

    Thanks

  11. #11
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940
    Actually, what I mean is when you call Load on the filter graph it uses your object instead of the default.

    Look up what to do by doing a search for 'Registering a Custom File Type' in DirectX SDK documentation.

    Darwen.

  12. #12
    Join Date
    Feb 2001
    Posts
    179
    Darwen,

    I could not find the topic on 'Registering a Custom File Type'. Is that separatly help for directx and directx SDK? The title bar on my help is "Directx C++". Anyway, can you kindly copy and paste the text in here. Thanks.

    Thanks!

  13. #13
    Join Date
    Feb 2001
    Posts
    179
    Darwen,

    Never mind, I find the register topic. I think it is for assocaiate a filter with file types. It is not what I am looking for. I am looking for a filter that can read a MPEG file that's being build (encoded), and read more data from the file when it is available.

  14. #14
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940
    Yes ? Isn't that what you want ?

    What it enables you to do is to replace the source filter with whichever one you want.

    I've already used this page to insert into the filter graph for MPEGs the asynchronous reader, which is different from the default 'load all and then pass' reader.

    Maybe it doesn't solve your problem, but at least give it a shot.

    Darwen.

  15. #15
    Join Date
    Feb 2001
    Posts
    179
    Darwin,

    So you have the your asynchronous reader? Can you send me the code? I think that's what I am looking for.

    Thanks

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured