Delen via


Stap 1: De CPlayer-klasse declareren

Dit onderwerp is stap 1 van de zelfstudie Mediabestanden afspelen met Media Foundation. De volledige code wordt weergegeven in het onderwerp Media Sessie Afspelen Voorbeeld.

In deze handleiding wordt de afspeelfunctionaliteit ingekapseld in de klasse CPlayer. De CPlayer klasse wordt als volgt gedeclareerd:

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.
};

Hier volgen enkele dingen die u moet weten over CPlayer:

  • De constante WM_APP_PLAYER_EVENT definieert een privévensterbericht. Dit bericht wordt gebruikt om de toepassing op de hoogte te stellen van mediasessie-gebeurtenissen. Zie stap 5: Mediasessie-gebeurtenissen afhandelen.
  • De opsomming PlayerState definieert de mogelijke statussen van het CPlayer-object.
  • De CPlayer-klasse implementeert de interface IMFAsyncCallback, die wordt gebruikt voor het ophalen van gebeurtenismeldingen van de mediasessie.
  • De CPlayer constructor is privé. De toepassing roept de statische CreateInstance methode aan om een exemplaar van de CPlayer-klasse te maken.
  • De CPlayer destructor is ook privé. De CPlayer klasse implementeert IUnknown-, zodat de levensduur van het object wordt bepaald door het aantal verwijzingen (m_nRefCount). Om het object te vernietigen, roept de toepassing IUnknown::Release, niet verwijderen.
  • Het CPlayer-object beheert zowel de mediasessie als de mediabron.

IUnknown implementeren

De CPlayer klasse implementeert IMFAsyncCallback--, welke IUnknown-overerft.

De hier getoonde code is een redelijk standaard implementatie van IUnknown. Als u wilt, kunt u de Active Template Library (ATL) gebruiken om deze methoden te implementeren. CPlayer biedt echter geen ondersteuning voor CoCreateInstance- of geavanceerde COM-functies, dus er is hier geen overweldigende reden om ATL te gebruiken.

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;
}

Volgende: stap 2: het CPlayer-object maken

audio/video afspelen

Mediabestanden afspelen met Media Foundation