Шаг 1. объявление класса Кплайер

В этом разделе приведен шаг 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 определяет сообщение частного окна. Это сообщение используется для уведомления приложения о событиях сеанса мультимедиа. См. Шаг 5. Работа с событиями сеанса мультимедиа.
  • PlayerStateПеречисление определяет возможные состояния CPlayer объекта.
  • CPlayerКласс реализует интерфейс имфасинккаллбакк , который используется для получения уведомлений о событиях из сеанса мультимедиа.
  • CPlayerКонструктор является закрытым. Приложение вызывает статический CreateInstance метод для создания экземпляра CPlayer класса.
  • CPlayerДеструктор также является закрытым. CPlayerКласс реализует IUnknown, поэтому время существования объекта регулируется с помощью счетчика ссылок (m _ нрефкаунт). Чтобы уничтожить объект, приложение вызывает IUnknown:: Release, а не Delete.
  • CPlayerОбъект управляет сеансом мультимедиа и источником мультимедиа.

Реализация IUnknown

CPlayerКласс реализует имфасинккаллбакк, который наследует 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. Создание объекта кплайер

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

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