Date

Media Foundation の一部のインターフェイスは IUnknown::QueryInterface ではなくIMFGetService::GetService を呼んで取得する。IMFGetService::GetService のラッパーとしてMFGetService がある。

例えば この記事にある動画プレイヤーアプリケーション では Media Session から IMFVideoDisplayControl を取得するために MFGetService を呼んでいる。

1
2
3
4
MFGetService(m_MFSession,
    MR_VIDEO_RENDER_SERVICE,
    __uuidof(IMFVideoDisplayControl),
    (void**)&m_VideoDisplay);

ちなみにMFGetServiceは、次のコードと同じ。

1
2
3
4
5
6
7
CComQIPtr<IMFGetService> get_service;
CComPtr<IMFVideoDisplayControl> m_VideoDisplay;
get_service = m_MFSession;
get_service->GetService(
    MR_VIDEO_RENDER_SERVICE,
    __uuidof(IMFVideoDisplayControl),
    (void**)&m_VideoDisplay);

あるオブジェクトのインターフェイスを問い合わせる、という点でQueryInterface と似ているが仕組みが異なる。

QueryInterface ではインターフェイス ID を引数として指定する。そして返ってくる値は、同じオブジェクト上の指定した ID のインターフェイスである。(つまりC++のdynamic_castの COM 実装。)

MFGetService では、インターフェイス ID の他に Service identifier (SID、サービスID) を指定する。また、返ってくるインターフェイスは同じオブジェクト上のものではないことがある。

ところで MFGetService は関数であるため QueryInterface と書き方が違う。 ATL を使っていて統一するならこういうのはどうだろう? (CComQIPtrのようにはいかないし、使う場面は少ないが。)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
template <class T>
class CComMFPtr : public CComPtr<T>
{
public:
    template <class S>
    HRESULT GetService(REFGUID service, S **result)
    {
        return MFGetService(p, service, __uuidof(S), (LPVOID *)result);
    }
};
// 呼び出し例
CComPtr<IMFVideoDisplayControl> m_VideoDisplay;
hr = m_MFSession.GetService(MR_VIDEO_RENDER_SERVICE, &m_VideoDisplay);
// または
hr = m_MFSession.GetService<IMFVideoDisplayControl>(MR_VIDEO_RENDER_SERVICE, &m_VideoDisplay);

Comments

comments powered by Disqus