手順 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
デストラクターもプライベートです。 クラスはCPlayer
IUnknown を実装するため、オブジェクトの有効期間は参照カウント (m_nRefCount) によって制御されます。 オブジェクトを破棄するために、アプリケーションは削除ではなく IUnknown::Release を呼び出 します。 - オブジェクトは
CPlayer
、メディア セッションとメディア ソースの両方を管理します。
IUnknown を実装する
クラスはCPlayer
、IUnknown を継承する IMFAsyncCallback を実装します。
ここに示すコードは、 IUnknown のかなり標準的な実装です。 必要に応じて、Active Template Library (ATL) を使用してこれらのメソッドを実装できます。 ただし、 CPlayer
CoCreateInstance や高度な 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;
}
関連トピック