2025-11-28 00:35:46 +09:00

210 lines
6.2 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#ifndef __TEDPLAYER__
#define __TEDPLAYER__
#include "tedobj.h"
#include "tedutil.h"
#define METHODASYNCCALLBACKEX(Callback, Parent, Flag, Queue) \
class Callback##AsyncCallback; \
friend class Callback##AsyncCallback; \
class Callback##AsyncCallback : public IMFAsyncCallback \
{ \
public: \
STDMETHOD_( ULONG, AddRef )() \
{ \
Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
return pThis->AddRef(); \
} \
STDMETHOD_( ULONG, Release )() \
{ \
Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
return pThis->Release(); \
} \
STDMETHOD( QueryInterface )( REFIID riid, void **ppvObject ) \
{ \
if(riid == IID_IMFAsyncCallback || riid == IID_IUnknown) \
{ \
(*ppvObject) = this; \
AddRef(); \
return S_OK; \
} \
(*ppvObject) = NULL; \
return E_NOINTERFACE; \
} \
STDMETHOD( GetParameters )( \
DWORD *pdwFlags, \
DWORD *pdwQueue) \
{ \
*pdwFlags = Flag; \
*pdwQueue = Queue; \
return S_OK; \
} \
STDMETHOD( Invoke )( IMFAsyncResult * pResult ) \
{ \
Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
pThis->Callback( pResult ); \
return S_OK; \
} \
} m_x##Callback;
////////////////////////////////////////////////////////
//
#define METHODASYNCCALLBACK(Callback, Parent) \
METHODASYNCCALLBACKEX(Callback, Parent, 0, MFASYNC_CALLBACK_QUEUE_STANDARD)
///////////////////////////////////////////////////////////////////////////////
// window for video playback
class CTedVideoWindow
: public CWindowImpl<CTedVideoWindow>
{
public:
CTedVideoWindow();
~CTedVideoWindow();
void Init(CTedApp * pApp);
protected:
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
BEGIN_MSG_MAP(CTedVideoWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
END_MSG_MAP()
};
///////////////////////////////////////////////////////////////////////////////
// Renders a media file to a full topology
class CTedMediaFileRenderer
{
public:
CTedMediaFileRenderer(LPCWSTR szFileName, ITedVideoWindowHandler* pVideoWindowHandler, HRESULT& hr);
HRESULT Load(IMFTopology** ppOutputTopology);
protected:
HRESULT CreatePartialTopology(IMFTopology** ppPartialTopology);
HRESULT CreateSource(IMFMediaSource** ppSource);
HRESULT BuildTopologyFromSource(IMFTopology* pTopology, IMFMediaSource* pSource);
HRESULT CreateRendererForStream(IMFStreamDescriptor* pSD, IMFTopologyNode** ppRendererNode);
private:
LPCWSTR m_szFileName;
CComPtr<ITedVideoWindowHandler> m_spVideoWindowHandler;
CComPtr<IMFTopoLoader> m_spTopoLoader;
};
///////////////////////////////////////////////////////////////////////////////
// Manages playback of a topology
class CTedMediaEventHandler
{
public:
virtual void NotifyEventError(HRESULT hr) = 0;
virtual void HandleMediaEvent(IMFMediaEvent* pEvent) = 0;
};
class CTedPlayer
{
public:
CTedPlayer(CTedMediaEventHandler* pMediaEventHandler, IMFContentProtectionManager* pCPM);
~CTedPlayer();
HRESULT InitClear();
HRESULT InitProtected();
// for callbacks
LONG AddRef();
LONG Release();
HRESULT Reset();
HRESULT GetFullTopology(IMFTopology ** ppFullTopo);
HRESULT GetPartialTopology(IMFTopology ** ppPartialTopo);
HRESULT SetTopology(CComPtr<IMFTopology> pPartialTopo, BOOL fTranscode);
HRESULT Start();
HRESULT Stop();
HRESULT Pause();
HRESULT PlayFrom(MFTIME time);
HRESULT GetDuration(MFTIME& hnsTime);
HRESULT GetTime( MFTIME *phnsTime );
HRESULT GetRateBounds(MFRATE_DIRECTION eDirection, float* pflSlowest, float* pflFastest);
HRESULT SetRate(float flRate);
bool IsPlaying() const;
bool IsPaused() const;
bool IsTopologySet() const;
void SetCustomTopoloader(GUID gidTopoloader);
HRESULT GetCapabilities(DWORD* pdwCaps);
protected:
METHODASYNCCALLBACK(OnClearSessionEvent, CTedPlayer);
METHODASYNCCALLBACK(OnProtectedSessionEvent, CTedPlayer);
void OnClearSessionEvent(IMFAsyncResult* pResult);
void OnProtectedSessionEvent(IMFAsyncResult* pResult);
HRESULT HandleEvent(IMFMediaEvent* pEvent);
HRESULT HandleSessionStarted(IMFMediaEvent* pEvent);
HRESULT HandleNotifyPresentationTime(IMFMediaEvent* pEvent);
HRESULT InitFromSession();
HRESULT RemoveResamplerNode(IMFTopology* pTopology);
private:
LONG m_cRef;
CTedApp * m_pApp;
CTedMediaEventHandler* m_pMediaEventHandler;
CComPtr<IMFMediaSession> m_spSession;
CComPtr<IMFMediaSession> m_spClearSession;
CComPtr<IMFMediaSession> m_spProtectedSession;
CComPtr<IMFMediaSource> m_spSource;
CAtlArray<IMFTopology*> m_aTopologies;
IMFContentProtectionManager* m_pCPM;
CComPtr<IMFTopology> m_spFullTopology;
CComPtr<IMFPresentationClock> m_spSessionClock;
// sequencer for multiple sources and using the same source in two consecutive topologies
MFSequencerElementId m_LastSeqID;
bool m_fReceivedTime;
MFTIME m_hnsStartTime;
MFTIME m_hnsOffsetTime;
MFTIME m_hnsStartTimeAtOutput;
MFTIME m_hnsDuration;
MFTIME m_hnsMediastartOffset;
bool m_bIsPlaying;
bool m_bIsPaused;
bool m_fTopologySet;
BOOL m_fIsTranscoding;
GUID m_gidCustomTopoloader;
bool m_fPendingClearCustomTopoloader;
bool m_fPendingProtectedCustomTopoloader;
};
#endif