Bagikan melalui


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 status CPlayer objek.
  • Kelas mengimplementasikan CPlayer antarmuka IMFAsyncCallback , yang digunakan untuk mendapatkan pemberitahuan peristiwa dari Media Session.
  • CPlayer Konstruktor bersifat pribadi. Aplikasi memanggil metode statis CreateInstance untuk membuat instans CPlayer kelas .
  • Destruktor CPlayer juga bersifat pribadi. Kelas mengimplementasikan CPlayerIUnknown, 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

Pemutaran Audio/Video

Cara Memutar File Media dengan Media Foundation