Langkah 1: Nyatakan Kelas CPlayer
Topik ini adalah langkah 1 dari tutorial Cara Memutar File Media dengan Media Foundation. Kode lengkap ditampilkan dalam topik Contoh Pemutaran Sesi Media.
Dalam tutorial ini, fungsionalitas pemutaran dienkapsulasi di CPlayer
kelas . Kelas CPlayer
dideklarasikan sebagai berikut:
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.
};
Berikut adalah beberapa hal yang perlu diperhatikan tentang CPlayer
:
- Konstanta WM_APP_PLAYER_EVENT menentukan pesan jendela privat. Pesan ini digunakan untuk memberi tahu aplikasi tentang peristiwa Sesi Media. Lihat Langkah 5: Menangani Peristiwa Sesi Media.
-
PlayerState
Enumerasi mendefinisikan kemungkinan statusCPlayer
objek. - Kelas mengimplementasikan
CPlayer
antarmuka IMFAsyncCallback , yang digunakan untuk mendapatkan pemberitahuan peristiwa dari Media Session. -
CPlayer
Konstruktor bersifat pribadi. Aplikasi memanggil metode statisCreateInstance
untuk membuat instansCPlayer
kelas . - Destruktor
CPlayer
juga bersifat pribadi. Kelas mengimplementasikanCPlayer
IUnknown, sehingga masa pakai objek dikontrol melalui jumlah referensinya (m_nRefCount). Untuk menghancurkan objek, aplikasi memanggil IUnknown::Release, bukan menghapus. - Objek
CPlayer
mengelola Sesi Media dan sumber media.
Menerapkan IUnknown
Kelas ini CPlayer
mengimplementasikan IMFAsyncCallback, yang mewarisi IUnknown.
Kode yang ditunjukkan di sini adalah implementasi IUnknown yang cukup standar. Jika mau, Anda dapat menggunakan Pustaka Templat Aktif (ATL) untuk mengimplementasikan metode ini. Namun, CPlayer
tidak mendukung CoCreateInstance atau fitur COM canggih apa pun, sehingga tidak ada alasan yang luar biasa untuk menggunakan ATL di sini.
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;
}
Berikutnya: Langkah 2: Buat Objek CPlayer
Topik terkait