Шаг 1. Объявление класса CPlayer

Этот раздел является шагом 1 руководства по воспроизведению файлов мультимедиа с помощью Media Foundation. Полный код показан в разделе "Пример воспроизведения сеанса мультимедиа".

В этом руководстве функции воспроизведения инкапсулируются в CPlayer классе. Класс CPlayerобъявляется следующим образом:

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

Ниже приведены некоторые моменты, которые следует учитывать:CPlayer

  • Константная WM_APP_PLAYER_EVENT определяет частное сообщение окна. Это сообщение используется для уведомления приложения о событиях сеанса мультимедиа. См. шаг 5. Обработка событий сеанса мультимедиа.
  • Перечисление PlayerState определяет возможные состояния CPlayer объекта.
  • Класс CPlayer реализует интерфейс IMFAsyncCallback , который используется для получения уведомлений о событиях из сеанса мультимедиа.
  • CPlayer Конструктор является закрытым. Приложение вызывает статический CreateInstance метод для создания экземпляра CPlayer класса.
  • Деструктор CPlayer также является частным. Класс CPlayer реализует IUnknown, поэтому время существования объекта контролируется с помощью счетчика ссылок (m_nRefCount). Чтобы уничтожить объект, приложение вызывает IUnknown::Release, а не удаление.
  • Объект CPlayer управляет сеансом мультимедиа и источником мультимедиа.

Реализация IUnknown

Класс CPlayer реализует IMFAsyncCallback, который наследует IUnknown.

Приведенный здесь код представляет собой довольно стандартную реализацию IUnknown. При желании для реализации этих методов можно использовать библиотеку активных шаблонов (ATL). Тем не менее, CPlayer не поддерживает CoCreateInstance или какие-либо расширенные функции COM, поэтому здесь нет подавляющей причины использовать ATL.

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

Далее. Шаг 2. Создание объекта CPlayer

Воспроизведение звука/видео

Воспроизведение файлов мультимедиа с помощью Media Foundation