手順 1: CPlayer クラスを宣言する

このトピックは、 Media Foundation を使用してメディア ファイルを再生する方法に関するチュートリアルの手順 1 です。 完全なコードは、「 メディア セッション再生の例」のトピックに示されています。

このチュートリアルでは、再生機能を クラスに CPlayer カプセル化します。 CPlayer クラスは次のように宣言されます。

const UINT WM_APP_PLAYER_EVENT = WM_APP + 1;   

    // WPARAM = IMFMediaEvent*, WPARAM = MediaEventType

enum PlayerState
{
    Closed = 0,     // No session.
    Ready,          // Session was created, ready to open a file. 
    OpenPending,    // Session is opening a file.
    Started,        // Session is playing a file.
    Paused,         // Session is paused.
    Stopped,        // Session is stopped (ready to play). 
    Closing         // Application has closed the session, but is waiting for MESessionClosed.
};

class CPlayer : public IMFAsyncCallback
{
public:
    static HRESULT CreateInstance(HWND hVideo, HWND hEvent, CPlayer **ppPlayer);

    // IUnknown methods
    STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();

    // IMFAsyncCallback methods
    STDMETHODIMP  GetParameters(DWORD*, DWORD*)
    {
        // Implementation of this method is optional.
        return E_NOTIMPL;
    }
    STDMETHODIMP  Invoke(IMFAsyncResult* pAsyncResult);

    // Playback
    HRESULT       OpenURL(const WCHAR *sURL);
    HRESULT       Play();
    HRESULT       Pause();
    HRESULT       Stop();
    HRESULT       Shutdown();
    HRESULT       HandleEvent(UINT_PTR pUnkPtr);
    PlayerState   GetState() const { return m_state; }

    // Video functionality
    HRESULT       Repaint();
    HRESULT       ResizeVideo(WORD width, WORD height);
    
    BOOL          HasVideo() const { return (m_pVideoDisplay != NULL);  }

protected:
    
    // Constructor is private. Use static CreateInstance method to instantiate.
    CPlayer(HWND hVideo, HWND hEvent);

    // Destructor is private. Caller should call Release.
    virtual ~CPlayer(); 

    HRESULT Initialize();
    HRESULT CreateSession();
    HRESULT CloseSession();
    HRESULT StartPlayback();

    // Media event handlers
    virtual HRESULT OnTopologyStatus(IMFMediaEvent *pEvent);
    virtual HRESULT OnPresentationEnded(IMFMediaEvent *pEvent);
    virtual HRESULT OnNewPresentation(IMFMediaEvent *pEvent);

    // Override to handle additional session events.
    virtual HRESULT OnSessionEvent(IMFMediaEvent*, MediaEventType) 
    { 
        return S_OK; 
    }

protected:
    long                    m_nRefCount;        // Reference count.

    IMFMediaSession         *m_pSession;
    IMFMediaSource          *m_pSource;
    IMFVideoDisplayControl  *m_pVideoDisplay;

    HWND                    m_hwndVideo;        // Video window.
    HWND                    m_hwndEvent;        // App window to receive events.
    PlayerState             m_state;            // Current state of the media session.
    HANDLE                  m_hCloseEvent;      // Event to wait on while closing.
};

に関 CPlayerして注意すべき点を次に示します。

  • 定数 WM_APP_PLAYER_EVENT は、プライベート ウィンドウ メッセージを定義します。 このメッセージは、メディア セッション イベントについてアプリケーションに通知するために使用されます。 「手順 5: メディア セッション イベントを処理する」を参照してください。
  • 列挙体は PlayerState 、オブジェクトの考えられる状態を CPlayer 定義します。
  • クラスは CPlayer 、メディア セッションからイベント通知を取得するために使用される IMFAsyncCallback インターフェイスを実装します。
  • コンストラクターは CPlayer プライベートです。 アプリケーションは静的 CreateInstance メソッドを呼び出して、 クラスのインスタンスを CPlayer 作成します。
  • CPlayerデストラクターもプライベートです。 クラスは CPlayerIUnknown を実装するため、オブジェクトの有効期間は参照カウント (m_nRefCount) によって制御されます。 オブジェクトを破棄するために、アプリケーションは削除ではなく IUnknown::Release を呼び出 します
  • オブジェクトは CPlayer 、メディア セッションとメディア ソースの両方を管理します。

IUnknown を実装する

クラスはCPlayerIUnknown を継承する IMFAsyncCallback を実装します。

ここに示すコードは、 IUnknown のかなり標準的な実装です。 必要に応じて、Active Template Library (ATL) を使用してこれらのメソッドを実装できます。 ただし、 CPlayerCoCreateInstance や高度な COM 機能はサポートされていないため、ここでは ATL を使用する圧倒的な理由はありません。

HRESULT CPlayer::QueryInterface(REFIID riid, void** ppv)
{
    static const QITAB qit[] = 
    {
        QITABENT(CPlayer, IMFAsyncCallback),
        { 0 }
    };
    return QISearch(this, qit, riid, ppv);
}

ULONG CPlayer::AddRef()
{
    return InterlockedIncrement(&m_nRefCount);
}

ULONG CPlayer::Release()
{
    ULONG uCount = InterlockedDecrement(&m_nRefCount);
    if (uCount == 0)
    {
        delete this;
    }
    return uCount;
}

次へ: 手順 2: CPlayer オブジェクトを作成する

オーディオ/ビデオの再生

Media Foundation でメディア ファイルを再生する方法