Schritt 1: Deklarieren der CPlayer-Klasse
Dieses Thema ist Schritt 1 des Tutorials Wiedergeben von Mediendateien mit Media Foundation. Der vollständige Code wird im Thema Media Session Playback Example (Beispiel für die Mediensitzungswiedergabe) angezeigt.
In diesem Tutorial wird die Wiedergabefunktionalität in der CPlayer
-Klasse gekapselt. Die CPlayer
-Klasse wird folgendermaßen deklariert:
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.
};
Beachten Sie folgendes CPlayer
:
- Die konstante WM_APP_PLAYER_EVENT definiert eine private Fensternachricht. Diese Meldung wird verwendet, um die Anwendung über Mediensitzungsereignisse zu benachrichtigen. Weitere Informationen finden Sie unter Schritt 5: Behandeln von Mediensitzungsereignissen.
- Die
PlayerState
-Enumeration definiert die möglichen Zustände desCPlayer
-Objekts. - Die
CPlayer
-Klasse implementiert die IMFAsyncCallback-Schnittstelle , die zum Abrufen von Ereignisbenachrichtigungen aus der Mediensitzung verwendet wird. - Der
CPlayer
Konstruktor ist privat. Die Anwendung ruft die statischeCreateInstance
Methode auf, um eine instance derCPlayer
-Klasse zu erstellen. - Der
CPlayer
Destruktor ist ebenfalls privat. DieCPlayer
-Klasse implementiert IUnknown, sodass die Lebensdauer des Objekts über die Verweisanzahl (m_nRefCount) gesteuert wird. Um das Objekt zu zerstören, ruft die Anwendung IUnknown::Release auf, nicht löschen. - Das
CPlayer
-Objekt verwaltet sowohl die Mediensitzung als auch die Medienquelle.
Implementieren von IUnknown
Die CPlayer
-Klasse implementiert IMFAsyncCallback, das IUnknown erbt.
Der hier gezeigte Code ist eine ziemlich standardmäßige Implementierung von IUnknown. Wenn Sie möchten, können Sie die Aktive Vorlagenbibliothek (Active Template Library, ATL) verwenden, um diese Methoden zu implementieren.
CPlayer
Unterstützt jedoch keine CoCreateInstance oder erweiterte COM-Features, sodass es hier keinen überwältigenden Grund gibt, ATL zu verwenden.
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;
}
Weiter: Schritt 2: Erstellen des CPlayer-Objekts
Zugehörige Themen