在Directshow中使用VMR9

声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息。  

本文链接:http://blog.csdn.net/li_007/archive/2010/03/02/5338976.aspx

开拓进取的小乌龟------->CSDN点滴点点滴滴Blog 

废话就少说了,把这段时间做的某***活动要用播发器的部分Directshow代码发出来,方便大家使用(声明:遵循LGPL协议)。本来同事想用openframeworks使用quicktime来播放这个3084*720的高清AD片子的,可是播放的时候有点卡,所以没办法就只有再次自己用directshow来写,现在分享的代码可以方便大家直接使用,做一个简单的播放器。

// // CHDPlayerCore.h // // Written by Leezhm, 3rd Feb, 2010 // Contact : Leezhm@luxoom.cn // Last Modified by Leezhm, 3rd Feb, 2010 // #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 // // Written by Leezhm, 3rd Feb, 2010 // Contact : Leezhm@luxoom.cn // Last Modified by Leezhm, 3rd Feb, 2010 // #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();

 

其实封装好了,使用起来很简单的,我想应该可以方便大家使用,完成一个简单的播放器。当然还可以监听播放器事件,那段代码就没必要贴出来的,很简单,MSDN上就有的

转载于:https://www.cnblogs.com/leezhm/archive/2010/03/02/2560307.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值