다음을 통해 공유


1단계: CPlayer 클래스 선언

이 항목은 Media Foundation을 사용하여 미디어 파일을 재생하는 방법 자습서의 1단계입니다. 전체 코드는 미디어 세션 재생 예제 항목에 나와 있습니다.

이 자습서에서는 재생 기능이 클래스에 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 생성자는 private입니다. 애플리케이션은 정적 CreateInstance 메서드를 호출하여 클래스의 instance 만듭니다CPlayer.
  • CPlayer 소멸자도 프라이빗입니다. 클래스는 CPlayerIUnknown을 구현하므로 개체의 수명은 참조 횟수(m_nRefCount)를 통해 제어됩니다. 개체를 삭제하기 위해 애플리케이션은 삭제가 아닌 IUnknown::Release를 호출합니다.
  • 개체는 CPlayer 미디어 세션과 미디어 원본을 모두 관리합니다.

IUnknown 구현

클래스는 CPlayerIUnknown을 상속하는 IMFAsyncCallback을 구현합니다.

여기에 표시된 코드는 IUnknown의 상당히 표준 구현입니다. 원하는 경우 ATL(활성 템플릿 라이브러리)을 사용하여 이러한 메서드를 구현할 수 있습니다. 그러나 는 CPlayerCoCreateInstance 또는 고급 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을 사용하여 미디어 파일을 재생하는 방법