Media Foundation学习笔记(八)编程练习:一个通用视频文件播放器


我将有关Media Foundation的函数调用封装到一个类CSpsPlayer中了,CSpsPlayer类的使用方法如下:


1)CSpsPlayer* pPlayer = new CSpsPlayer(hWndPlay);

2)pPlayer->OpenFile("c:\\ttt.asf");

3)获取视频时长pPlayer->GetTimeLen();单位是1/10^4毫秒;

4)pPlayer->Play();

5)暂定pPlayer->Pause();

6)暂停后继续pPlayer->Play();

7)获取播放位置pPlayer->GetCurrentPos();单位是1/10^4毫秒;

8)设置音量pPlayer->SetAudioVolumn(lVolumn);lVolumn取值是0~100

9)Seek操作pPlayer->Move(pos);pos单位是1/10^4毫秒;

10)播放窗口尺寸变化pPlayer->AdjustWindowPosition();

11)停止播放pPlayer->Stop();

12)关闭文件pPlayer->CloseFile();


SpsPlayer.h文件:

//
//	Class:		CSpsPlayer
//
//	Compiler:	Visual C++
//	Tested on:	Visual C++ 2010
//
//	Created:	08/March/2014
//
//	Author:		Liu Yang		464585657@qq.com
//
//
#ifndef SPSPLAYER_H
#define SPSPLAYER_H

#include <Windows.h>
#include <string>
#include <vector>
#include <new>
#include <shobjidl.h> 
#include <shlwapi.h>
#include <assert.h>
#include <strsafe.h>

// Media Foundation headers
#include <mfapi.h>
#include <mfidl.h>
#include <mferror.h>
#include <evr.h>

#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
#define SAFE_CLOSE_HANDLE(x) { if (x)CloseHandle(x); x = NULL; }

enum PlayerState//播放器状态
{
    Closed = 0,     // No session.
    Started,        // Session is playing a file.
    Paused,         // Session is paused.
    Stopped,        // Session is stopped (ready to play). 
};

class CMyCriticalSection
{
public:
	CMyCriticalSection()
	{
		::InitializeCriticalSection(&m_cs);
	}
	virtual ~CMyCriticalSection()
	{
		::DeleteCriticalSection(&m_cs);
	}
	void lock()
	{
		::EnterCriticalSection(&m_cs);
	}
	void unlock()
	{
		::LeaveCriticalSection(&m_cs);
	}
private:
	CRITICAL_SECTION m_cs;
};

class CMyAutoLock
{
public:
	CMyAutoLock(CMyCriticalSection * pCrit)
	{
		m_pCrit = pCrit;
		m_pCrit->lock();
	}
	virtual ~CMyAutoLock()
	{
		m_pCrit->unlock();
	}
private:
	CMyCriticalSection * m_pCrit;
};


class CSpsPlayer : public IMFAsyncCallback
{
public:
	CSpsPlayer(HWND hWndVideo);
	virtual ~CSpsPlayer();

	// 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);

	//播放控制函数
	std::string GetSpsFilePathName();//获取文件名
	BOOL OpenFile(const char * s);//打开文件
	BOOL CloseFile();//关闭文件
	long GetPlayStatus();//获取播放器状态,返回:0:停止;1:播放;2:暂停
	BOOL Play();//播放
	BOOL Pause();//暂停
	BOOL Stop();//停止
	LONGLONG GetTimeLen();//获取时长(单位是1/10^4毫秒)
	LONGLONG GetCurrentPos();//获取当前播放位置(单位是1/10^4毫秒)
	BOOL Move(LONGLONG pos);//跳到指定位置播放(单位是1/10^4毫秒)
	BOOL GetAudioIsOpenedOrClosed();//获取声音是开启还是关闭状态
	BOOL OpenOrCloseAudio(BOOL bOpen);//打开或关闭声音
	long GetAudioVolumn();//获取音量
	BOOL SetAudioVolumn(long lVolumn);//设置音量
	void AdjustWindowPosition();//播放窗口尺寸发生变化时调用
	void RepaitVideo();//暂停时,播放窗口重绘后调用

private:
	BOOL AddBranchToTopology( IMFTopology *pTopology, IMFMediaSource *pSource, IMFPresentationDescriptor *pPD, DWORD iStream);//添加流的分支到topology
	IMFGetService* GetMFGetService();
	IMFSimpleAudioVolume* GetSimpleAudioVolume();
	IMFPresentationClock* GetPresentationClock();
	IMFVideoDisplayControl* GetVideoDisplayControl();

private:
	CMyCriticalSection		m_csCrit;//播放器锁
	HWND					m_hWndVideo;//播放窗口
	std::string				m_sSpsFileName;//视频文件
	//
	IMFMediaSession*		m_pSession;//Media Session
	PlayerState				m_state;//播放器状态
	LONGLONG				m_llTimeLen;//1/10^4毫秒
	long                    m_nRefCount;        // Reference count.
};


#endif


SpsPlayer.cpp文件:

//
//	Class:		CSpsPlayer
//
//	Compiler:	Visual C++
//	Tested on:	Visual C++ 2010
//
//	Created:	08/March/2014
//
//	Author:		Liu Yang		464585657@qq.com
//
//
#include "SpsPlayer.h"

#include <assert.h>

#pragma comment(lib, "shlwapi")

static const GUID MY_MR_VIDEO_RENDER_SERVICE ={0x1092a86c,0xab1a,0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} };

CSpsPlayer::CSpsPlayer(HWND hWndVideo)
{
	m_hWndVideo = hWndVideo;
	//
	m_pSession = NULL;
	m_state = Closed;
	m_llTimeLen = 0;
}

CSpsPlayer::~CSpsPlayer()
{
	CloseFile();
}

HRESULT CSpsPlayer::QueryInterface(REFIID riid, void** ppv)
{
    static const QITAB qit[] = 
    {
        QITABENT(CSpsPlayer, IMFAsyncCallback),
        { 0 }
    };
    return QISearch(this, qit, riid, ppv);
}

ULONG CSpsPlayer::AddRef()
{
    return InterlockedIncrement(&m_nRefCount);
}

ULONG CSpsPlayer::Release()
{
    ULONG uCount = InterlockedDecrement(&m_nRefCount);
    if (uCount == 0)
    {
        delete this;
    }
    return uCount;
}

std::string CSpsPlayer::GetSpsFilePathName()
{
	CMyAutoLock lock(&m_csCrit);

	return m_sSpsFileName;
}

BOOL CSpsPlayer::OpenFile(const char * s)
{
	CloseFile();

	CMyAutoLock lock(&m_csCrit);

	std::string sSpsFileName;
	sSpsFileName = s;

	//初始化Media Foundataion平台
	HRESULT hr = MFStartup(MF_VERSION);
	if (FAILED(hr))
	{
		return FALSE;
	}

	//创建Media Session对象
    hr = MFCreateMediaSession(NULL, &m_pSession);
    if (FAILED(hr))
    {
        MFShutdown();
		return FALSE;
    }

    //开始从Media Session接收事件
    hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);
    if (FAILED(hr))
    {
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }

	MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;

    IMFSourceResolver* pSourceResolver = NULL;//Media Source选择器
    IUnknown* pSource = NULL;
    IMFMediaSource* pMFMediaSource = NULL;

    //根据给定的文件路径,创建Media Source对象,并获取IMFMediaSource接口
    hr = MFCreateSourceResolver(&pSourceResolver);
    if (FAILED(hr))
    {
        SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }
	WCHAR szwFile[MAX_PATH] = {0};
	MultiByteToWideChar(CP_ACP, 0, sSpsFileName.c_str(), -1, szwFile, MAX_PATH);
    hr = pSourceResolver->CreateObjectFromURL( szwFile, MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &pSource );
    if (FAILED(hr))
    {
        SAFE_RELEASE(pSourceResolver);
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }
    hr = pSource->QueryInterface(IID_PPV_ARGS(&pMFMediaSource));
	if (FAILED(hr))
    {
		SAFE_RELEASE(pSource);
        SAFE_RELEASE(pSourceResolver);
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }	
	SAFE_RELEASE(pSource);
    SAFE_RELEASE(pSourceResolver);

    IMFPresentationDescriptor* pSourcePD = NULL;

	//创建Presentation描述符
    hr = pMFMediaSource->CreatePresentationDescriptor(&pSourcePD);
    if (FAILED(hr))
    {
		SAFE_RELEASE(pMFMediaSource);        
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }

	MFTIME mDuration = 0;
	hr = pSourcePD->GetUINT64(MF_PD_DURATION, (UINT64*)&mDuration);
	if (FAILED(hr))
	{
		SAFE_RELEASE(pSourcePD); 
		SAFE_RELEASE(pMFMediaSource);        
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }
	m_llTimeLen = mDuration;

	DWORD cSourceStreams = 0;

    //获取Media Source对象的流的数目
    hr = pSourcePD->GetStreamDescriptorCount(&cSourceStreams);
    if (FAILED(hr))
	{
		SAFE_RELEASE(pSourcePD);   
        SAFE_RELEASE(pMFMediaSource);      
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }

	IMFTopology *pTopology = NULL;

	//创建topology对象
    hr = MFCreateTopology(&pTopology);
    if (FAILED(hr))
    {
		SAFE_RELEASE(pSourcePD);   
        SAFE_RELEASE(pMFMediaSource);      
		SAFE_RELEASE(m_pSession);
        MFShutdown();
		return FALSE;
    }

	//为每一个流创建节点,并将节点添加到topology中
    for (DWORD i = 0; i < cSourceStreams; i++)
    {
        BOOL bRet = AddBranchToTopology(pTopology, pMFMediaSource, pSourcePD, i);
        if (!bRet)
        {
			SAFE_RELEASE(pTopology);   
			SAFE_RELEASE(pSourcePD);   
			SAFE_RELEASE(pMFMediaSource);      
			SAFE_RELEASE(m_pSession);
			MFShutdown();
			return FALSE;
        }
    }

	//将topology对象设置到Media Session对象中
	hr = m_pSession->SetTopology(0, pTopology);
    if (FAILED(hr))
    {
		SAFE_RELEASE(pTopology);   
		SAFE_RELEASE(pSourcePD);   
		SAFE_RELEASE(pMFMediaSource);      
		SAFE_RELEASE(m_pSession);
		MFShutdown();
		return FALSE;
    }

	m_sSpsFileName = sSpsFileName;

	m_state = Stopped;

	return TRUE;
}

BOOL CSpsPlayer::CloseFile()
{
	Stop();

	CMyAutoLock lock(&m_csCrit);

	SAFE_RELEASE(m_pSession);
    MFShutdown();
	m_sSpsFileName = "";
	return TRUE;
}

long CSpsPlayer::GetPlayStatus()
{
	CMyAutoLock lock(&m_csCrit);

	switch(m_state)
	{
	case Closed://还没有打开文件
	case Stopped://停止了--打开文件后就是此状态
		return 0;
		break;
	case Started://开始播放了
		return 1;
		break;
	case Paused://暂停了
		return 2;
		break;
	default:
		return -1;
		break;
	}
}

BOOL CSpsPlayer::Play()
{
	CMyAutoLock lock(&m_csCrit);

	if (m_state != Paused && m_state != Stopped)
    {
        return FALSE;
    }

	PROPVARIANT varStart;
    PropVariantInit(&varStart);

    HRESULT hr = m_pSession->Start(&GUID_NULL, &varStart);

	PropVariantClear(&varStart);

    if (SUCCEEDED(hr))
    {
        // Note: Start is an asynchronous operation. However, we
        // can treat our state as being already started. If Start
        // fails later, we'll get an MESessionStarted event with
        // an error code, and we will update our state then.
        m_state = Started;
		return TRUE;
    }

	return FALSE;
}

BOOL CSpsPlayer::Pause()
{
	CMyAutoLock lock(&m_csCrit);

	if (m_state != Started)
    {
        return FALSE;
    }

    HRESULT hr = m_pSession->Pause();
    if (SUCCEEDED(hr))
    {
        m_state = Paused;
		return TRUE;
    }
	return FALSE;
}

BOOL CSpsPlayer::Stop()
{
	CMyAutoLock lock(&m_csCrit);

	if (m_state != Started && m_state != Paused)
    {
        return FALSE;
    }

	HRESULT hr = m_pSession->Stop();
    if (SUCCEEDED(hr))
    {
        m_state = Stopped;
		return TRUE;
    }
	return FALSE;
}

LONGLONG CSpsPlayer::GetTimeLen()
{
	CMyAutoLock lock(&m_csCrit);

	return m_llTimeLen;
}

LONGLONG CSpsPlayer::GetCurrentPos()
{
	CMyAutoLock lock(&m_csCrit);

	IMFPresentationClock* pPresentationClock = GetPresentationClock();
	if (!pPresentationClock)
		return 0;

	MFTIME pos = 0;
	HRESULT hr = pPresentationClock->GetTime(&pos);
	SAFE_RELEASE(pPresentationClock);
	if (FAILED(hr))
		return 0;

	return pos;
}

BOOL CSpsPlayer::Move(LONGLONG pos)
{
	CMyAutoLock lock(&m_csCrit);

	if (!m_pSession)
        return FALSE;

	PROPVARIANT varStart;
    varStart.vt = VT_I8;
    varStart.hVal.QuadPart = pos;

    HRESULT hr =  m_pSession->Start(NULL, &varStart);
	if (FAILED(hr))
		return FALSE;

	return TRUE;
}

BOOL CSpsPlayer::GetAudioIsOpenedOrClosed()
{
	CMyAutoLock lock(&m_csCrit);

	if (!m_pSession)
    {
        return FALSE;
    }

	IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();
	if(pa)
	{
		BOOL bMute = FALSE;
		HRESULT hr = pa->GetMute(&bMute);
		if (FAILED(hr))
			return FALSE;
		return bMute;
	}
	return FALSE;
}

BOOL CSpsPlayer::OpenOrCloseAudio(BOOL bOpen)
{
	CMyAutoLock lock(&m_csCrit);

	if (!m_pSession)
    {
        return FALSE;
    }

	IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();
	if(pa)
	{
		HRESULT hr;
		if (bOpen)
		{
			hr = pa->SetMute(FALSE);
			if (FAILED(hr))
				return FALSE;
		}
		else
		{
			hr = pa->SetMute(TRUE);
			if (FAILED(hr))
				return FALSE;
		}
	}	
	return TRUE;
}

long CSpsPlayer::GetAudioVolumn()
{
	CMyAutoLock lock(&m_csCrit);

	if (!m_pSession)
    {
        return 0;
    }

	IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();
	if(pa)
	{
		HRESULT hr;
		float f = 0.0f;
		hr = pa->GetMasterVolume(&f);
		if (FAILED(hr))
			return 0;
		f = (f < 0.0f ? 0.0f : (f > 1.0f ? 1.0f : f));
		return (long)(f * 100.0f);
	}
	return 0;
}

BOOL CSpsPlayer::SetAudioVolumn(long ll)
{
	CMyAutoLock lock(&m_csCrit);

	if (!m_pSession)
    {
        return FALSE;
    }

	IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();
	if(pa)
	{
		HRESULT hr;
		ll = (ll < 0 ? 0 : (ll > 100 ? 100 : ll));
		float f = ((float)ll / 100.0f);
		f = (f < 0.0f ? 0.0f : (f > 1.0f ? 1.0f : f));
		hr = pa->SetMasterVolume(f);
		if (FAILED(hr))
			return FALSE;
		return TRUE;
	}
	return FALSE;
}

void CSpsPlayer::AdjustWindowPosition()
{
	CMyAutoLock lock(&m_csCrit);

	IMFVideoDisplayControl* pVideoDisplayControl = GetVideoDisplayControl();
	if (pVideoDisplayControl)
	{
		RECT rcDest;
		GetWindowRect(m_hWndVideo, &rcDest);
		POINT pt;
		pt.x = rcDest.left;
		pt.y = rcDest.top;
		ScreenToClient(m_hWndVideo, &pt);
		rcDest.left = pt.x;
		rcDest.top = pt.y;
		pt.x = rcDest.right;
		pt.y = rcDest.bottom;
		ScreenToClient(m_hWndVideo, &pt);
		rcDest.right = pt.x;
		rcDest.bottom = pt.y;
		pVideoDisplayControl->SetVideoPosition(0, &rcDest);
	}	
}

void CSpsPlayer::RepaitVideo()
{
	CMyAutoLock lock(&m_csCrit);

	IMFVideoDisplayControl* pVideoDisplayControl = GetVideoDisplayControl();
	if (pVideoDisplayControl)
		pVideoDisplayControl->RepaintVideo();
}

BOOL CSpsPlayer::AddBranchToTopology( IMFTopology *pTopology, IMFMediaSource *pSource, IMFPresentationDescriptor *pPD, DWORD iStream)
{
    IMFStreamDescriptor *pSD = NULL;
    IMFTopologyNode     *pSourceNode = NULL;
    IMFTopologyNode     *pOutputNode = NULL;

    BOOL fSelected = FALSE;

	//获取流描述符
    HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
    if (FAILED(hr))
    {
        return FALSE;
    }

    if (fSelected)
    {
		// Create the media sink activation object.
        IMFMediaTypeHandler *pHandler = NULL;
		IMFActivate         *pActivate = NULL;

		//获取流的IMFMeidaTypeHandle
		HRESULT hr = pSD->GetMediaTypeHandler(&pHandler);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//获取流的主类型
		GUID guidMajorType;
		hr = pHandler->GetMajorType(&guidMajorType);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pHandler);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		SAFE_RELEASE(pHandler);
 
		// 根据流的主类型为Render创建IMFActivate对象
		if (MFMediaType_Audio == guidMajorType)
		{
			hr = MFCreateAudioRendererActivate(&pActivate);
			if (FAILED(hr))
			{
				SAFE_RELEASE(pSD);
				return FALSE;
			}
		}
		else if (MFMediaType_Video == guidMajorType)
		{
			hr = MFCreateVideoRendererActivate(m_hWndVideo, &pActivate);
			if (FAILED(hr))
			{
				SAFE_RELEASE(pSD);
				return FALSE;
			}
		}		

		//创建源节点
		hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pSourceNode);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//设置源节点的源属性
		hr = pSourceNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//设置源节点的Presentation描述符
		hr = pSourceNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//设置源节点的流的描述符
		hr = pSourceNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}
    
		//添加源节点到topology.
		hr = pTopology->AddNode(pSourceNode);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//创建输出节点
		hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pOutputNode);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//设置输出节点的指针
		hr = pOutputNode->SetObject(pActivate);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pOutputNode);
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pActivate);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		SAFE_RELEASE(pActivate);

		//设置输出节点所在流的id
		hr = pOutputNode->SetUINT32(MF_TOPONODE_STREAMID, 0);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pOutputNode);
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		hr = pOutputNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pOutputNode);
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

		//添加输出节点到topology.
		hr = pTopology->AddNode(pOutputNode);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pOutputNode);
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pSD);
			return FALSE;
		}

        hr = pSourceNode->ConnectOutput(0, pOutputNode, 0);
		if (FAILED(hr))
		{
			SAFE_RELEASE(pOutputNode);
			SAFE_RELEASE(pSourceNode);
			SAFE_RELEASE(pSD);
			return FALSE;
		}
    }

	SAFE_RELEASE(pOutputNode);
	SAFE_RELEASE(pSourceNode);
	SAFE_RELEASE(pSD);
    return TRUE;
}

HRESULT CSpsPlayer::Invoke(IMFAsyncResult *pResult)
{
    MediaEventType meType = MEUnknown;  // Event type

    IMFMediaEvent *pEvent = NULL;

	m_csCrit.lock();

    // Get the event from the event queue.
    HRESULT hr = m_pSession->EndGetEvent(pResult, &pEvent);
    if (FAILED(hr))
    {
		m_csCrit.unlock();
		return S_OK;
    }

    // Get the event type. 
    hr = pEvent->GetType(&meType);
    if (FAILED(hr))
    {
		SAFE_RELEASE(pEvent);
		m_csCrit.unlock();
		return S_OK;
    }

	if (meType == MEEndOfPresentation)
    {
		SAFE_RELEASE(pEvent);

        m_csCrit.unlock();

		Stop();

		return S_OK;
    }
    else
    {
		SAFE_RELEASE(pEvent);
        // For all other events, get the next event in the queue.
        hr = m_pSession->BeginGetEvent(this, NULL);
        if (FAILED(hr))
        {
			//error
        }
    }

	m_csCrit.unlock();
    return S_OK;
}

IMFGetService* CSpsPlayer::GetMFGetService()
{
	if (!m_pSession)
		return NULL;

	IMFGetService* pGetService = NULL;

	HRESULT hr = m_pSession->QueryInterface(IID_IMFGetService, (void **)&pGetService);
	if(FAILED(hr))
		return NULL;

	return pGetService;
}

IMFSimpleAudioVolume* CSpsPlayer::GetSimpleAudioVolume()
{
	if (!m_pSession)
		return NULL;

	IMFGetService* pGetService = GetMFGetService();
	if(!pGetService)
		return NULL;

	IMFSimpleAudioVolume* pa = NULL;
	HRESULT hr = pGetService->GetService(MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&pa));
	SAFE_RELEASE(pGetService);
	if(FAILED(hr))
		return NULL;

	return pa;
}

IMFPresentationClock* CSpsPlayer::GetPresentationClock()
{
	if (!m_pSession)
		return NULL;

	IMFClock* pClock = NULL;
	HRESULT hr = m_pSession->GetClock(&pClock);
	if(FAILED(hr))
		return NULL;

	IMFPresentationClock* pPresentationClock = NULL;
	hr = pClock->QueryInterface(IID_PPV_ARGS(&pPresentationClock));
	SAFE_RELEASE(pClock);
    if(FAILED(hr))
		return NULL;

	return pPresentationClock;
}

IMFVideoDisplayControl* CSpsPlayer::GetVideoDisplayControl()
{
	if (!m_pSession)
		return NULL;

	IMFVideoDisplayControl* pVideoDisplay = NULL;
	HRESULT hr = MFGetService(m_pSession, MY_MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pVideoDisplay));
	if(FAILED(hr))
		return NULL;

	return pVideoDisplay;
}



评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值