Media Player Classic - HC 源代码分析 9:CFGManager类详细分析(CFGManager)

上一篇文章分析了Media Player Classic - HC(mpc-hc)的源代码中的CFGManager类的RenderFile函数:

Media Player Classic - HC 源代码分析 8:RenderFile函数详细分析(CFGManager)

这一篇文章我们全面了解一下CFGManager类,这个类从IFilterGraph2接口继承,是DirectShow的Filter Graph Manager类。负责管理整个Graph链中的Filter。源码声明如下:

class CFGManager
    : public CUnknown
    , public IGraphBuilder2
    , public IGraphBuilderDeadEnd
    , public CCritSec
{
public:
    struct path_t {
        CLSID clsid;
        CString filter, pin;
    };

    class CStreamPath : public CAtlList<path_t>
    {
    public:
        void Append(IBaseFilter* pBF, IPin* pPin);
        bool Compare(const CStreamPath& path);
    };

    class CStreamDeadEnd : public CStreamPath
    {
    public:
        CAtlList<CMediaType> mts;
    };

private:
    CComPtr<IUnknown> m_pUnkInner;
    DWORD m_dwRegister;

    CStreamPath m_streampath;
    CAutoPtrArray<CStreamDeadEnd> m_deadends;

protected:
    CComPtr<IFilterMapper2> m_pFM;
    CInterfaceList<IUnknown, &IID_IUnknown> m_pUnks;
    CAtlList<CFGFilter*> m_source, m_transform, m_override;

    static bool CheckBytes(HANDLE hFile, CString chkbytes);

    HRESULT EnumSourceFilters(LPCWSTR lpcwstrFileName, CFGFilterList& fl);
    HRESULT AddSourceFilter(CFGFilter* pFGF, LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppBF);
    HRESULT Connect(IPin* pPinOut, IPin* pPinIn, bool bContinueRender);

    // IFilterGraph

    STDMETHODIMP AddFilter(IBaseFilter* pFilter, LPCWSTR pName);
    STDMETHODIMP RemoveFilter(IBaseFilter* pFilter);
    STDMETHODIMP EnumFilters(IEnumFilters** ppEnum);
    STDMETHODIMP FindFilterByName(LPCWSTR pName, IBaseFilter** ppFilter);
    STDMETHODIMP ConnectDirect(IPin* pPinOut, IPin* pPinIn, const AM_MEDIA_TYPE* pmt);
    STDMETHODIMP Reconnect(IPin* ppin);
    STDMETHODIMP Disconnect(IPin* ppin);
    STDMETHODIMP SetDefaultSyncSource();

    // IGraphBuilder

    STDMETHODIMP Connect(IPin* pPinOut, IPin* pPinIn);
    STDMETHODIMP Render(IPin* pPinOut);
    STDMETHODIMP RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList);
    STDMETHODIMP AddSourceFilter(LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter);
    STDMETHODIMP SetLogFile(DWORD_PTR hFile);
    STDMETHODIMP Abort();
    STDMETHODIMP ShouldOperationContinue();

    // IFilterGraph2

    STDMETHODIMP AddSourceFilterForMoniker(IMoniker* pMoniker, IBindCtx* pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter);
    STDMETHODIMP ReconnectEx(IPin* ppin, const AM_MEDIA_TYPE* pmt);
    STDMETHODIMP RenderEx(IPin* pPinOut, DWORD dwFlags, DWORD* pvContext);

    // IGraphBuilder2

    STDMETHODIMP IsPinDirection(IPin* pPin, PIN_DIRECTION dir);
    STDMETHODIMP IsPinConnected(IPin* pPin);
    STDMETHODIMP ConnectFilter(IBaseFilter* pBF, IPin* pPinIn);
    STDMETHODIMP ConnectFilter(IPin* pPinOut, IBaseFilter* pBF);
    STDMETHODIMP ConnectFilterDirect(IPin* pPinOut, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt);
    STDMETHODIMP NukeDownstream(IUnknown* pUnk);
    STDMETHODIMP FindInterface(REFIID iid, void** ppv, BOOL bRemove);
    STDMETHODIMP AddToROT();
    STDMETHODIMP RemoveFromROT();

    // IGraphBuilderDeadEnd

    STDMETHODIMP_(size_t) GetCount();
    STDMETHODIMP GetDeadEnd(int iIndex, CAtlList<CStringW>& path, CAtlList<CMediaType>& mts);

public:
    CFGManager(LPCTSTR pName, LPUNKNOWN pUnk);
    virtual ~CFGManager();

    DECLARE_IUNKNOWN;
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
};

从上面类声明中我们可以看到CFGManager继承自IGraphBuilder2接口,而IGraphBuilder2接口刚好是从IFilterGraph2接口继承的。

另外CComPtr<IUnknown> m_pUnkInner这个成员变量很重要,CFGManager将所有IFilterGraph2接口函数的调用都转接给这个对象。m_pUnkInner 为DirectShow现实的Filter Graph Manager基类对象。这个对象在CFGManager构造函数中创建,我们看一下具体创建代码:

CFGManager::CFGManager(LPCTSTR pName, LPUNKNOWN pUnk)
    : CUnknown(pName, pUnk)
    , m_dwRegister(0)
{
    m_pUnkInner.CoCreateInstance(CLSID_FilterGraph, GetOwner());
    m_pFM.CoCreateInstance(CLSID_FilterMapper2);
}

我们再看一下CFGManager类使如何将IFilterGraph2接口的调用转接给m_pUnkInner对象的。

CFGManager类的几个函数实现就能看出,源码如下:

STDMETHODIMP CFGManager::AddFilter(IBaseFilter* pFilter, LPCWSTR pName)
{
    if (!m_pUnkInner) {
        return E_UNEXPECTED;
    }

    CAutoLock cAutoLock(this);

    HRESULT hr;

    if (FAILED(hr = CComQIPtr<IFilterGraph2>(m_pUnkInner)->AddFilter(pFilter, pName))) {
        return hr;
    }

    // TODO
    hr = pFilter->JoinFilterGraph(nullptr, nullptr);
    hr = pFilter->JoinFilterGraph(this, pName);

    return hr;
}
STDMETHODIMP CFGManager::RemoveFilter(IBaseFilter* pFilter)
{
    if (!m_pUnkInner) {
        return E_UNEXPECTED;
    }

    CAutoLock cAutoLock(this);

    return CComQIPtr<IFilterGraph2>(m_pUnkInner)->RemoveFilter(pFilter);
}
STDMETHODIMP CFGManager::Reconnect(IPin* ppin)
{
    if (!m_pUnkInner) {
        return E_UNEXPECTED;
    }

    CAutoLock cAutoLock(this);

    return CComQIPtr<IFilterGraph2>(m_pUnkInner)->Reconnect(ppin);
}
STDMETHODIMP CFGManager::Disconnect(IPin* ppin)
{
    if (!m_pUnkInner) {
        return E_UNEXPECTED;
    }

    CAutoLock cAutoLock(this);

    return CComQIPtr<IFilterGraph2>(m_pUnkInner)->Disconnect(ppin);
}

从以上几个函数我们可以看出,CFGManger将IFilterGraph2接口函数全部转接给m_pUnkInner 对象的同名函数。

总结:由上面分析可知,CFGManger类只是对DirectShow已经实现的Filter Graph Manager的一种包装,具体的工作还是由DirectShow自己处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值