IGraphBuilder

//
// CHDPlayerCore.h

#ifndef __CHDPlayerCore_h__
#define __CHDPlayerCore_h__


#include <DShow.h>
#include <D3D9.h>
#include <vmr9.h>


#include "dshowutil.h"


// Filter graph notification to the specified window
#define WM_GRAPHNOTIFY  (WM_USER+20)


class CHDPlayerCore
{
public:
CHDPlayerCore(void);
virtual ~CHDPlayerCore(void);


public:
HRESULT CreateGraph(HWND hWnd);


HRESULT RenderMovieFile(const wchar_t * file, bool bRenderAudio);


bool RunMovies(void);
bool StopMovies(void);
bool PauseMovies(void);


HRESULT GetNativeMovieSize(CRect & pos);
HRESULT SetMoviePosition(CRect & pos);
HRESULT GetMoviePosotion(CRect & pos);


// IMediaSeeking
HRESULT GetCurrentPosition(double * outPosition);
HRESULT GetStopPosition(double * outPosition);
HRESULT SetCurrentPosition(double inPosition);
HRESULT SetStartStopPosition(double inStart, double inStop);
HRESULT GetDuration(double * outDuration);
HRESULT SetPlaybackRate(double inRate);


HRESULT SetNotifyWindow(HWND inWindows);
void    HandleEvent(WPARAM wParam, LPARAM lParam);


IMediaEventEx * GetEventHandle() const;
OAFilterState GetCurrentState();


private:
inline void SafeRelease(IUnknown * filter)
{
if (NULL != filter)
{
filter->Release();
filter = NULL;
}
}


HRESULT GetInterface();


HRESULT UsedVideoMixingRenderer9();
BOOL IsWindowsMediaFile(const WCHAR *lpszFile);
HRESULT GetUnconnectedPin(IBaseFilter *pFilter,  PIN_DIRECTION PinDir, IPin **ppPin);
HRESULT RenderMoivesToVMR9(IGraphBuilder * pGB, const WCHAR * wFileName, BOOL bRenderAudio);


HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
void RemoveFromRot(DWORD pdwRegister);


void ShowMsg(TCHAR *szFormat, ...);


IBaseFilter* CreateEncodec(CString inFriendlyName);
HRESULT CreateFilter(REFCLSID clsid, IBaseFilter **ppFilter);


private:
IGraphBuilder  *  pGraphBuilder;
IMediaControl  *  pMediaControl;
IMediaSeeking  *  pMediaSeeking;
IMediaEventEx  *  pMediaEventEx;


IBaseFilter    * pVMR9;
IVMRWindowlessControl9 * pVMR9Control;


DWORD dwRegister;
HWND mPlayerHandle;
};


#endif // __CHDPlayerCore_h__



//
// CHDPlayerCore.cpp

#include "StdAfx.h"
#include "HDPlayerCore.h"


CHDPlayerCore::CHDPlayerCore(void)
{
pGraphBuilder = NULL;
pMediaControl = NULL;
pMediaSeeking = NULL;
pVMR9Control  = NULL;
pMediaEventEx = NULL;
pVMR9         = NULL;
}


CHDPlayerCore::~CHDPlayerCore(void)
{
#ifdef _DEBUG
RemoveFromRot(dwRegister);
#endif


SafeRelease(pMediaSeeking);
SafeRelease(pMediaControl);
SafeRelease(pVMR9Control);
SafeRelease(pMediaEventEx);
SafeRelease(pVMR9);
SafeRelease(pGraphBuilder);


CoUninitialize();
}


HRESULT CHDPlayerCore::CreateGraph(HWND hWnd)
{
HRESULT hr = NOERROR;
mPlayerHandle = hWnd;


if(S_OK != CoInitializeEx(NULL,COINIT_APARTMENTTHREADED))
{
return E_FAIL;
}


if (NULL == pGraphBuilder)
{
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                 IID_IGraphBuilder, (void **)&pGraphBuilder);


if (SUCCEEDED(hr))
{
hr |= pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
hr |= pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking);
hr |= pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEventEx);


if (FAILED(hr))
{
return hr;
}
}
}


UsedVideoMixingRenderer9();


return hr;
}


HRESULT CHDPlayerCore::RenderMovieFile(const wchar_t * file, bool bRenderAudio)
{
if (NULL != file)
{
if (NULL == pGraphBuilder)
{
MessageBox(NULL, L"The IGraphBuilder is NULL", L"Error Information", S_OK);
}


HRESULT hr = RenderMoivesToVMR9(pGraphBuilder, file, bRenderAudio);


CRect rc;
SetRect(&rc, 0, 0, 0, 0);
hr |= GetNativeMovieSize(rc);
hr |= SetMoviePosition(rc);


if (SUCCEEDED(hr))
{
return hr;
}
}


#ifdef _DEBUG
AddToRot(pGraphBuilder, &dwRegister);
#endif


return E_FAIL;
}


bool CHDPlayerCore::RunMovies()
{
if (NULL != pGraphBuilder && NULL != pMediaControl)
{
if (State_Paused == GetCurrentState() || State_Stopped == GetCurrentState())
{
if (SUCCEEDED(pMediaControl->Run()))
{
return true;
}
else
{
return false;
}
}
}


return false;
}


bool CHDPlayerCore::StopMovies()
{
if (NULL != pGraphBuilder && NULL != pMediaControl)
{
if (State_Running == GetCurrentState())
{
if (SUCCEEDED(pMediaControl->Stop()))
{
return true;
}
else
{
return false;
}
}
}


return false;
}


bool CHDPlayerCore::PauseMovies()
{
if (NULL != pGraphBuilder && NULL != pMediaControl)
{
if (State_Running == GetCurrentState())
{
if (SUCCEEDED(pMediaControl->Pause()))
{
return true;
}
else
{
return false;
}
}
}


return false;
}


HRESULT CHDPlayerCore::GetNativeMovieSize(CRect & pos)
{
HRESULT hr = NOERROR;


if (NULL != pVMR9Control)
{
hr = pVMR9Control->GetNativeVideoSize(&pos.right, &pos.bottom, NULL, NULL);


if (SUCCEEDED(hr))
{
return hr;
}


SetRect(&pos, 0, 0, 0, 0);
}


return E_FAIL;
}


HRESULT CHDPlayerCore::GetMoviePosotion(CRect & pos)
{
HRESULT hr = NOERROR;
CRect src;


if (NULL != pVMR9Control)
{
hr = pVMR9Control->GetVideoPosition(&src, &pos);


if (SUCCEEDED(hr))
{
return hr;
}


SetRect(&pos, 0, 0, 0, 0);
}


return E_FAIL;
}


HRESULT CHDPlayerCore::SetMoviePosition(CRect & pos)
{
HRESULT hr = NOERROR;


if (NULL != pVMR9Control)
{
hr = pVMR9Control->SetVideoPosition(NULL, &pos);


if (SUCCEEDED(hr))
{
return hr;
}
}


return E_FAIL;
}


HRESULT CHDPlayerCore::GetCurrentPosition(double * outPosition)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
__int64 position = (__int64)0.0;


hr = pMediaSeeking->GetCurrentPosition(&position);
if (SUCCEEDED(hr))
{
*outPosition = ((double)position) / 10000000.0;
return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::GetStopPosition(double *outPosition)
{


HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
__int64 position = (__int64)0.0;


hr = pMediaSeeking->GetStopPosition(&position);
if (SUCCEEDED(hr))
{
*outPosition = ((double)position) / 10000000.0;
return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::SetCurrentPosition(double inPosition)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
__int64 position = (__int64)(10000000 * inPosition);


hr = pMediaSeeking->SetPositions(&position, AM_SEEKING_AbsolutePositioning |
                            AM_SEEKING_SeekToKeyFrame, 0, AM_SEEKING_NoPositioning);


if (SUCCEEDED(hr))
{
return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::SetStartStopPosition(double inStart, double inStop)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
__int64 start = (__int64)(10000000 * inStart);
__int64 stop  = (__int64)(10000000 * inStop);


hr = pMediaSeeking->SetPositions(&start, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,
                            &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame);


if (SUCCEEDED(hr))
{
return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::GetDuration(double * outDuration)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
__int64 length = (__int64)0.0;


hr = pMediaSeeking->GetDuration(&length);


if (SUCCEEDED(hr))
{
*outDuration = ((double)length / 10000000.0);


return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::SetPlaybackRate(double inRate)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaSeeking)
{
hr = pMediaSeeking->SetRate(inRate);


if (SUCCEEDED(hr))
{
return hr;
}
}


return hr;
}


HRESULT CHDPlayerCore::SetNotifyWindow(HWND inWindows)
{
HRESULT hr = E_FAIL;


if (NULL != pMediaEventEx)
{
hr = pMediaEventEx->SetNotifyWindow((OAHWND)inWindows, WM_GRAPHNOTIFY, 0);


if (SUCCEEDED(hr))
{
return hr;
}
}


return hr;
}


void CHDPlayerCore::HandleEvent(WPARAM wParam, LPARAM lParam)
{
if (NULL != pMediaEventEx)
{
LONG eventCode = 0;
LONG_PTR eventParam1 = 0;
LONG_PTR eventParam2 = 0;


while(SUCCEEDED(pMediaEventEx->GetEvent(&eventCode, &eventParam1, &eventParam2, 0)))
{
pMediaEventEx->FreeEventParams(eventCode, eventParam1, eventParam2);
switch (eventCode)
{
case EC_COMPLETE:
break;


case EC_USERABORT:
case EC_ERRORABORT:
break;


default:
break;
}
}
}
}


IMediaEventEx * CHDPlayerCore::GetEventHandle() const
{
if (NULL != pMediaEventEx)
{
return pMediaEventEx;
}


return NULL;
}


HRESULT CHDPlayerCore::UsedVideoMixingRenderer9()
{
HRESULT hr = NOERROR;


hr |= CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC,
                  IID_IBaseFilter, (void **)&pVMR9);


if (SUCCEEDED(hr))
{
hr |= pGraphBuilder->AddFilter(pVMR9, L"Video Mixing Render 9");


if (SUCCEEDED(hr))
{
IVMRFilterConfig9 * pConfig9 = NULL;
hr |= pVMR9->QueryInterface(IID_IVMRFilterConfig9, (void **)&pConfig9);


if (SUCCEEDED(hr))
{
hr |= pConfig9->SetNumberOfStreams(2);
hr |= pConfig9->SetRenderingMode(VMR9Mode_Windowless);
hr |= pConfig9->SetRenderingPrefs(RenderPrefs_AllowOverlays);


pConfig9->Release();
}
pConfig9 = NULL;


IVMRMonitorConfig9 * pMonitorConfig = NULL;
hr |= pVMR9->QueryInterface(IID_IVMRMonitorConfig9, (void **)&pMonitorConfig);
if(SUCCEEDED(hr))
{
UINT iCurrentMonitor;
hr |= pMonitorConfig->GetMonitor(&iCurrentMonitor);
pMonitorConfig->Release();
}
pMonitorConfig = NULL;


hr |= pVMR9->QueryInterface(IID_IVMRWindowlessControl9, (void **)&pVMR9Control);
}
}


SafeRelease(pVMR9);


if (SUCCEEDED(hr))
{
hr |= pVMR9Control->SetVideoClippingWindow(mPlayerHandle);
hr |= pVMR9Control->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
}
else
{
SafeRelease(pVMR9Control);
}


return hr;
}


HRESULT CHDPlayerCore::RenderMoivesToVMR9(IGraphBuilder * pGB, const WCHAR * wFileName, BOOL bRenderAudio = TRUE)
{
HRESULT hr = NOERROR;
CComPtr <IPin> pOutputPin;
CComPtr <IPin> pInputPin;
CComPtr <IBaseFilter> pSource;
CComPtr <IBaseFilter> pAudioRenderer;
CComPtr <IFilterGraph2> pFG;
CComPtr <IFileSourceFilter> pFileSource;


// Render audio if requested (defaults to TRUE)
if (bRenderAudio)
{
// Because we will be rendering with the RENDERTOEXISTINGRENDERERS flag,
// we need to create an audio renderer and add it to the graph.
// Create an instance of the DirectSound renderer (for each media file).
//
// Note that if the system has no sound card (or if the card is disabled),
// then creating the DirectShow renderer will fail.  In that case,
// handle the failure quietly.
if (SUCCEEDED(CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **)&pAudioRenderer)))
{
// The audio renderer was successfully created, so add it to the graph
hr |= pGB->AddFilter(pAudioRenderer, L"Audio Renderer");
if (FAILED(hr))
{
return hr;
}
}
}


// Add a file source filter for this media file
if (!IsWindowsMediaFile(wFileName))
{
// Add the source filter to the graph
if (FAILED(hr |= pGB->AddSourceFilter(wFileName, L"SOURCE", &pSource)))
{
USES_CONVERSION;
WCHAR szMsg[MAX_PATH + 128] = {0};


hr = StringCchPrintf(szMsg, NUMELMS(szMsg), TEXT("Failed to add the source filter to the graph!  hr=0x%x/r/n/r/n")
TEXT("Filename: %s/0"), hr, wFileName);
MessageBox(NULL, szMsg, TEXT("Failed to render file to VMR9"), MB_OK | MB_ICONERROR);


return hr;
}


hr |= GetUnconnectedPin(pSource, PINDIR_OUTPUT, &pOutputPin);
if (FAILED(hr))
{
return hr;
}


// Get an IFilterGraph2 interface to assist in building the
// multifile graph with the non-default VMR9 renderer
hr |= pGB->QueryInterface(IID_IFilterGraph2, (void **)&pFG);
if (FAILED(hr))
{
return hr;
}


// Render the output pin, using the VMR9 as the specified renderer.  This is
// necessary in case the GraphBuilder needs to insert a Color Space convertor,
// or if multiple filters insist on using multiple allocators.
// The audio renderer will also be used, if the media file contains audio.
hr |= pFG->RenderEx(pOutputPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
if (FAILED(hr))
{
return hr;
}


// If this media file does not contain an audio stream, then the
// audio renderer that we created will be unconnected.  If left in the
// graph, it could interfere with rate changes and timing.
// Therefore, if the audio renderer is unconnected, remove it from the graph.
if (pAudioRenderer != NULL)
{
IPin *pUnconnectedPin=0;


// Is the audio renderer's input pin connected?
HRESULT hrPin = GetUnconnectedPin(pAudioRenderer, PINDIR_INPUT, &pUnconnectedPin);


// If there is an unconnected pin, then remove the unused filter
if (SUCCEEDED(hrPin) && (pUnconnectedPin != NULL))
{
// Release the returned IPin interface
pUnconnectedPin->Release();


// Remove the audio renderer from the graph
hrPin = pGB->RemoveFilter(pAudioRenderer);
}
}
}
else
{
// Load the improved ASF reader filter by CLSID
hr |= CreateFilter(CLSID_WMAsfReader, &pSource);
if(FAILED(hr))
{
ShowMsg(TEXT("Failed to create WMAsfWriter filter!  hr=0x%x/0"), hr);
return hr;
}


// Add the ASF reader filter to the graph.  For ASF/WMV/WMA content,
// this filter is NOT the default and must be added explicitly.
hr |= pGB->AddFilter(pSource, L"WMV ASF Reader");
if(FAILED(hr))
{
ShowMsg(TEXT("Failed to add ASF reader filter to graph!  hr=0x%x/0"), hr);
return hr;
}


// Set its source filename
hr |= pSource->QueryInterface(IID_IFileSourceFilter, (void **) &pFileSource);


// Attempt to load this file
hr |= pFileSource->Load(wFileName, NULL);


if (FAILED(hr))
{
ShowMsg(TEXT("Failed to load file in source filter (pFileSource->Load())!  hr=0x%x/0"), hr);
return hr;
}


ULONG count = 0;
CountTotalFilterPins(pSource, &count);


for (ULONG i = 0; i < count; i ++)
{
pOutputPin = GetOutPin(pSource, i);
PIN_INFO info;
pOutputPin->QueryPinInfo(&info);


CComPtr<IBaseFilter> Codec;


if (_tcsstr(info.achName, TEXT("Video")))
{
Codec = CreateEncodec(_T("WMVideo Decoder DMO"));
if (NULL != pGraphBuilder)
{
pGraphBuilder->AddFilter(Codec, _T("WMVideo Decoder DMO"));
pInputPin = GetInPin(Codec, 0);


hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);
if (FAILED(hr))
{
ShowMsg(_T("Video Connected Failed.  hr=0x%x/0"), hr);
return hr;
}


pOutputPin = GetOutPin(Codec, 0);
pInputPin = GetInPin(pVMR9, 0);


hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);
if (FAILED(hr))
{
ShowMsg(_T("Video Connected Failed.  hr=0x%x/0"), hr);
return hr;
}
}
}
else if (_tcsstr(info.achName, TEXT("Audio")))
{
Codec = CreateEncodec(_T("WMAudio Decoder DMO"));
if (NULL != pGraphBuilder)
{
pGraphBuilder->AddFilter(Codec, _T("WMAudio Decoder DMO"));
pInputPin = GetInPin(Codec, 0);


hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);
if (FAILED(hr))
{
ShowMsg(_T("Audio Connected Failed.  hr=0x%x/0"), hr);
return hr;
}


pOutputPin = GetOutPin(Codec, 0);


if (NULL == pAudioRenderer)
{
if (SUCCEEDED(CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **)&pAudioRenderer)))
{
// The audio renderer was successfully created, so add it to the graph
hr |= pGB->AddFilter(pAudioRenderer, L"Audio Renderer");
if (FAILED(hr))
{
return hr;
}
}
}


pInputPin = GetInPin(pAudioRenderer, 0);


hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);
if (FAILED(hr))
{
ShowMsg(_T("Audio Connected Failed.  hr=0x%x/0"), hr);
return hr;
}
}
}
}
}


return hr;
}


BOOL CHDPlayerCore::IsWindowsMediaFile(const WCHAR *lpszFile)
{
USES_CONVERSION;
WCHAR szFilename[MAX_PATH] = {0};


// Copy the file name to a local string and convert to lowercase
(void)StringCchCopy(szFilename,NUMELMS(szFilename), lpszFile);
szFilename[MAX_PATH-1] = 0;
_tcslwr_s(szFilename, 260);


if (_tcsstr(szFilename, TEXT(".asf")) ||
_tcsstr(szFilename, TEXT(".wma")) ||
_tcsstr(szFilename, TEXT(".wmv")))
{
return TRUE;
}
else
{
return FALSE;
}
}


OAFilterState CHDPlayerCore::GetCurrentState()
{
OAFilterState states = 0;


if (NULL != pGraphBuilder && NULL != pMediaControl)
{
pMediaControl->GetState(INFINITE, &states);
}


return states;
}




//Register the filter graph to Rot
HRESULT CHDPlayerCore::AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
HRESULT hr = NOERROR;
IMoniker * pMoniker = NULL;
IRunningObjectTable * pROT = NULL;
if(FAILED(GetRunningObjectTable(0,&pROT)))
{
return E_FAIL;
}


WCHAR wsz[256];
::memset(wsz,0,256);


hr = StringCchPrintfW(wsz, NUMELMS(wsz), L"FilterGraph %08x pid %08x",
(DWORD_PTR)pUnkGraph,GetCurrentProcessId());


hr = CreateItemMoniker(L"!",wsz,&pMoniker);
if(SUCCEEDED(hr))
{
hr = pROT->Register(0,pUnkGraph,pMoniker,pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}


void CHDPlayerCore::RemoveFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT = NULL;
if(SUCCEEDED(GetRunningObjectTable(0,&pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
}


HRESULT CHDPlayerCore::GetUnconnectedPin(
  IBaseFilter *pFilter,   // Pointer to the filter.
  PIN_DIRECTION PinDir,   // Direction of the pin to find.
  IPin **ppPin)           // Receives a pointer to the pin.
{
IEnumPins *pEnum = 0;
IPin *pPin = 0;


if (!ppPin)
return E_POINTER;
*ppPin = 0;


// Get a pin enumerator
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
return hr;


// Look for the first unconnected pin
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
PIN_DIRECTION ThisPinDir;


pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir)
{
IPin *pTmp = 0;


hr = pPin->ConnectedTo(&pTmp);
if (SUCCEEDED(hr))  // Already connected, not the pin we want.
{
pTmp->Release();
}
else  // Unconnected, this is the pin we want.
{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
}
pPin->Release();
}


// Release the enumerator
pEnum->Release();


// Did not find a matching pin
return E_FAIL;
}


IBaseFilter* CHDPlayerCore::CreateEncodec(CString inFriendlyName)
{
HRESULT hr = NOERROR;
ICreateDevEnum * enumHardware =NULL;
IBaseFilter    * hardwareFilter = NULL;


hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,(void **)&enumHardware);


if(FAILED(hr))
{
return NULL;
}


IEnumMoniker * enumMoniker = NULL;


hr = enumHardware->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &enumMoniker,0);


if(FAILED(hr))
{
return NULL;
}


if(enumMoniker)
{
enumMoniker->Reset();


IMoniker * moniker = NULL;
char friendlyName[256];
ZeroMemory(friendlyName,256);


while(S_OK == enumMoniker->Next(1,&moniker,0))
{
if(moniker)
{
IPropertyBag * proBag = NULL;
VARIANT    name;


hr = moniker->BindToStorage(NULL,NULL,IID_IPropertyBag,(void **)&proBag);


if(SUCCEEDED(hr))
{
name.vt = VT_BSTR;
proBag->Read(L"FriendlyName",&name,NULL);
}


if(SUCCEEDED(hr))
{
WideCharToMultiByte(CP_ACP, 0, name.bstrVal, -1,friendlyName, 256,
NULL, NULL);
CString str = (CString)friendlyName;
if(inFriendlyName == str)
{
moniker->BindToObject(NULL,NULL,IID_IBaseFilter,
(void **)&hardwareFilter);
}
}
if(proBag)
{
proBag->Release();
proBag = NULL;
}
moniker->Release();
}
}
enumMoniker->Release();
}
enumHardware->Release();


return hardwareFilter;
}


HRESULT CHDPlayerCore::CreateFilter(REFCLSID clsid, IBaseFilter **ppFilter)
{
HRESULT hr;


hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter,
(void **) ppFilter);


if(FAILED(hr))
{
//MessageBox(TEXT("CreateFilter: Failed to create filter!  hr=0x%x/n"));
if (ppFilter)
*ppFilter = NULL;
return hr;
}


return S_OK;
}


void CHDPlayerCore::ShowMsg(TCHAR *szFormat, ...)
{
TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs
const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
const int LASTCHAR = NUMCHARS - 1;


// Format the input string
va_list pArgs;
va_start(pArgs, szFormat);


// Use a bounded buffer size to prevent buffer overruns.  Limit count to
// character size minus one to allow for a NULL terminating character.
(void)StringCchVPrintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
va_end(pArgs);


// Ensure that the formatted string is NULL-terminated
szBuffer[LASTCHAR] = TEXT('/0');


// Display a message box with the formatted string
MessageBox(NULL, szBuffer, TEXT("Porsche HD Player"), MB_OK);
}


if (NULL == this->player)
{
this->player = new CHDPlayerCore();
}
        this->player->CreateGraph(this->playerDlg->GetSafeHwnd());
        this->player->RenderMovieFile(filePaths, true);
this->player->SetNotifyWindow(this->GetSafeHwnd());
this->player->SetStartStopPosition(0, 117.006);
this->player->RunMovies();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ww506772362

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值