Étape 1 : Déclarer la classe CPlayer
Cette rubrique est l’étape 1 du didacticiel Guide pratique pour lire des fichiers multimédias avec Media Foundation. Le code complet est présenté dans la rubrique Media Session Playback Example( Exemple de lecture de session multimédia).
Dans ce tutoriel, la fonctionnalité de lecture est encapsulée dans la CPlayer
classe . La classe CPlayer
est déclarée comme suit :
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.
};
Voici quelques points à noter sur CPlayer
:
- La constante WM_APP_PLAYER_EVENT définit un message de fenêtre privée. Ce message est utilisé pour informer l’application des événements media session. Consultez Étape 5 : Gérer les événements de session multimédia.
- L’énumération
PlayerState
définit les états possibles de l’objetCPlayer
. - La
CPlayer
classe implémente l’interface IMFAsyncCallback , qui est utilisée pour obtenir des notifications d’événements à partir de la session multimédia. - Le
CPlayer
constructeur est privé. L’application appelle la méthode statiqueCreateInstance
pour créer un instance de laCPlayer
classe . - Le
CPlayer
destructeur est également privé. LaCPlayer
classe implémente IUnknown, de sorte que la durée de vie de l’objet est contrôlée par son nombre de références (m_nRefCount). Pour détruire l’objet, l’application appelle IUnknown::Release, et non delete. - L’objet
CPlayer
gère à la fois la session multimédia et la source multimédia.
Implémenter IUnknown
La CPlayer
classe implémente IMFAsyncCallback, qui hérite de IUnknown.
Le code présenté ici est une implémentation assez standard de IUnknown. Si vous préférez, vous pouvez utiliser la bibliothèque active de modèles (ATL) pour implémenter ces méthodes. Toutefois, CPlayer
ne prend pas en charge CoCreateInstance ou des fonctionnalités COM avancées, il n’y a donc aucune raison écrasante d’utiliser ATL ici.
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;
}
Suivant : Étape 2 : Créer l’objet CPlayer
Rubriques connexes