이 항목은 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(활성 템플릿 라이브러리)을 사용하여 이러한 메서드를 구현할 수 있습니다. 그러나 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;
}
관련 항목
-
Media Foundation 사용하여 미디어 파일을 재생하는 방법