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
소멸자도 프라이빗입니다. 클래스는CPlayer
IUnknown을 구현하므로 개체의 수명은 참조 횟수(m_nRefCount)를 통해 제어됩니다. 개체를 삭제하기 위해 애플리케이션은 삭제가 아닌 IUnknown::Release를 호출합니다. - 개체는
CPlayer
미디어 세션과 미디어 원본을 모두 관리합니다.
IUnknown 구현
클래스는 CPlayer
IUnknown을 상속하는 IMFAsyncCallback을 구현합니다.
여기에 표시된 코드는 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;
}
관련 항목