다음을 통해 공유


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 생성자는 프라이빗입니다. 애플리케이션은 정적 CreateInstance 메서드를 호출하여 CPlayer 클래스의 인스턴스를 만듭니다.
  • CPlayer 소멸자도 비공개입니다. CPlayer 클래스는 IUnknown 구현하므로 개체의 수명은 참조 수(m_nRefCount)를 통해 제어됩니다. 개체를 파괴하기 위해 애플리케이션은 IUnknown::Release를 호출하고, delete를 사용하지 않습니다.
  • CPlayer 개체는 미디어 세션과 미디어 원본을 모두 관리합니다.

IUnknown 구현

CPlayer 클래스는 IMFAsyncCallback을(를) 구현하고 IUnknown을(를) 상속합니다.

여기에 표시된 코드는 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 사용하여 미디어 파일을 재생하는 방법