/* 创建VMR,添加、设置VMR */ HRESULT CVMR_Capture::InitializeWindowlessVMR(HWND hWnd) { IBaseFilter* pVmr = NULL; // 创建VMR HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { //添加VMR到滤波器链表中 hr = m_pGB->AddFilter(pVmr, L"Video Mixing Renderer"); if (SUCCEEDED(hr)) { // 设置无窗口渲染模式 IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if( SUCCEEDED(hr)) { pConfig->SetRenderingMode(VMRMode_Windowless); pConfig->Release(); } // 设置传入的窗口为显示窗口 hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&m_pWC); if( SUCCEEDED(hr)) { m_pWC->SetVideoClippingWindow(hWnd); } } pVmr->Release(); } return hr; }
HRESULT CVMR_Capture::InitializeWindowlessVMR(HWND hWnd) { IBaseFilter* pVmr = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = m_pGB->AddFilter(pVmr, L"Video Mixing Renderer"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams. IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if( SUCCEEDED(hr)) { pConfig->SetRenderingMode(VMRMode_Windowless); pConfig->Release(); } hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&m_pWC); if( SUCCEEDED(hr)) { m_pWC->SetVideoClippingWindow(hWnd); } } pVmr->Release(); } return hr; }
/******************************Public*Routine******************************\ * AddVideoMixingRendererToFG * \**************************************************************************/ HRESULT CMovie::AddVideoMixingRendererToFG() { IBaseFilter* pBF = NULL; HRESULT hRes = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (LPVOID *)&pBF); if(SUCCEEDED(hRes)) { hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer 9"); if(SUCCEEDED(hRes)) { // Test VMRConfig, VMRMonitorConfig IVMRFilterConfig9* pConfig; HRESULT hRes2 = pBF->QueryInterface(IID_IVMRFilterConfig9, (LPVOID *)&pConfig); if(SUCCEEDED(hRes2)) { hRes2 = pConfig->SetNumberOfStreams(2); hRes2 = pConfig->SetRenderingMode(VMR9Mode_Windowless); //hRes2 = pConfig->SetRenderingPrefs(RenderPrefs_AllowOverlays); pConfig->Release(); } IVMRMonitorConfig9* pMonitorConfig; HRESULT hRes3 = pBF->QueryInterface(IID_IVMRMonitorConfig9, (LPVOID *)&pMonitorConfig); if(SUCCEEDED(hRes3)) { UINT iCurrentMonitor; HRESULT hr4 = pMonitorConfig->GetMonitor(&iCurrentMonitor); pMonitorConfig->Release(); } hRes = pBF->QueryInterface(IID_IVMRWindowlessControl9, (LPVOID *)&m_Wc); } } if(pBF) { pBF->Release(); } if(SUCCEEDED(hRes)) { HRESULT hr = m_Wc->SetVideoClippingWindow(m_hwndApp); hr = m_Wc->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); } else { if(m_Wc) { m_Wc->Release(); m_Wc = NULL; } } return hRes; }
// // FindSubtitleFilter // // be careful with this method, can cause deadlock with CSync::Stop, so should only be called in Run() HRESULT CTsReaderFilter::FindSubtitleFilter() { if( m_pDVBSubtitle ) { return S_OK; } //LogDebug( "FindSubtitleFilter - start"); IEnumFilters * piEnumFilters = NULL; if (GetFilterGraph() && SUCCEEDED(GetFilterGraph()->EnumFilters(&piEnumFilters))) { IBaseFilter * pFilter; while (piEnumFilters->Next(1, &pFilter, 0) == NOERROR ) { FILTER_INFO filterInfo; if (pFilter->QueryFilterInfo(&filterInfo) == S_OK) { if (!wcsicmp(L"MediaPortal DVBSub2", filterInfo.achName)) { HRESULT fhr = pFilter->QueryInterface( IID_IDVBSubtitle2, ( void**)&m_pDVBSubtitle ); assert( fhr == S_OK); //LogDebug("Testing that DVBSub2 works"); m_pDVBSubtitle->Test(1); } filterInfo.pGraph->Release(); } pFilter->Release(); pFilter = NULL; } piEnumFilters->Release(); } //LogDebug( "FindSubtitleFilter - End"); return S_OK; }
HRESULT FindFilterInterface( IGraphBuilder *pGraph, // Pointer to the Filter Graph Manager. REFGUID iid, // IID of the interface to retrieve. void **ppUnk) // Receives the interface pointer. { if (!pGraph || !ppUnk) return E_POINTER; HRESULT hr = E_FAIL; IEnumFilters *pEnum = NULL; IBaseFilter *pF = NULL; if (FAILED(pGraph->EnumFilters(&pEnum))) { return E_FAIL; } // Query every filter for the interface. while (S_OK == pEnum->Next(1, &pF, 0)) { hr = pF->QueryInterface(iid, ppUnk); pF->Release(); if (SUCCEEDED(hr)) { break; } } pEnum->Release(); return hr; }
HRESULT CDShowUtility::FindFilterInterface(IGraphBuilder *pGraph, REFGUID iid, void **ppUnk) { if (!pGraph || !ppUnk) { return E_POINTER; } HRESULT hr = E_FAIL; IEnumFilters *pEnum = NULL; IBaseFilter *pF = NULL; if (FAILED(pGraph->EnumFilters(&pEnum))) { return E_FAIL; } //分别调用 Queryinterface, 枚举filter Graph 中的所有Filter while (S_OK == pEnum->Next(1, &pF, 0)) { hr = pF->QueryInterface(iid, ppUnk); pF->Release(); if (SUCCEEDED(hr)) { break; } } pEnum->Release(); return hr; }
HRESULT CBDReaderFilter::FindSubtitleFilter() { if (m_pDVBSubtitle) return S_OK; HRESULT hr = S_FALSE; ULONG fetched = 0; IEnumFilters * piEnumFilters = NULL; if (GetFilterGraph() && SUCCEEDED(GetFilterGraph()->EnumFilters(&piEnumFilters))) { IBaseFilter * pFilter; while (piEnumFilters->Next(1, &pFilter, &fetched) == NOERROR) { FILTER_INFO filterInfo; if (pFilter->QueryFilterInfo(&filterInfo) == S_OK) { if (!wcsicmp(L"MediaPortal DVBSub3", filterInfo.achName)) hr = pFilter->QueryInterface(IID_IDVBSubtitle3, (void**)&m_pDVBSubtitle); filterInfo.pGraph->Release(); } pFilter->Release(); pFilter = NULL; } piEnumFilters->Release(); } return hr; }
HRESULT recChannel_t::unmap(void) { __CONTEXT("recChannel_t::unmap"); IBaseFilter * pFilter = NULL; int hr =0; hr = pGraph->FindFilterByName(L"Video Renderer",&pFilter); if (!hr) { IVideoWindow *pWindowInfo = NULL; hr = pFilter->QueryInterface(IID_IVideoWindow, (void **)&pWindowInfo); errorCheck(hr); pWindowInfo->put_Visible(OAFALSE); pWindowInfo->put_AutoShow(OAFALSE); pWindowInfo->Release(); } pControl->StopWhenReady(); #ifdef _WINDOWS if (fControl) { fControl->CWnd::ShowWindow(SW_HIDE); } #endif mapping = false; return 0; }
HRESULT FindInterfaceAnywhere( IGraphBuilder *pGraph, REFGUID iid, void **ppUnk) { if (!pGraph || !ppUnk) return E_POINTER; HRESULT hr = E_FAIL; IEnumFilters *pEnum = 0; if (FAILED(pGraph->EnumFilters(&pEnum))) { return E_FAIL; } // Loop through every filter in the graph. IBaseFilter *pF = 0; while (S_OK == pEnum->Next(1, &pF, 0)) { hr = pF->QueryInterface(iid, ppUnk); if (FAILED(hr)) { // The filter does not expose the interface, but maybe // one of its pins does. hr = FindPinInterface(pF, iid, ppUnk); } pF->Release(); if (SUCCEEDED(hr)) { break; } } pEnum->Release(); return hr; }
/*****************************Public*Routine******************************\ * FindInterfaceFromFilterGraph * \**************************************************************************/ HRESULT CMovie::FindInterfaceFromFilterGraph( REFIID iid, // interface to look for LPVOID *lp // place to return interface pointer in ) { IEnumFilters* pEF; IBaseFilter* pFilter; // Grab an enumerator for the filter graph. HRESULT hr = m_Fg->EnumFilters(&pEF); if(FAILED(hr)) { return hr; } // Check out each filter. while(pEF->Next(1, &pFilter, NULL) == S_OK) { hr = pFilter->QueryInterface(iid, lp); pFilter->Release(); if(SUCCEEDED(hr)) { break; } } pEF->Release(); return hr; }
//查找Filter上某一个接口,只要找到FilterGraph上某一个Filter有该接口即返回 BOOL FindFilterInterface(IGraphBuilder* pGraphBuilder, REFGUID iid, void** ppUnk) { if(!pGraphBuilder || !ppUnk) return FALSE; IEnumFilters* pEnumFilter = NULL; IBaseFilter* pFilter = NULL; if(FAILED(pGraphBuilder->EnumFilters(&pEnumFilter))) { return FALSE; } HRESULT hr = E_FAIL; while(S_OK == pEnumFilter->Next(1,&pFilter,NULL)) { hr = pFilter->QueryInterface(iid,ppUnk); pFilter->Release(); if(SUCCEEDED(hr)) { pEnumFilter->Release(); return TRUE; } } pEnumFilter->Release(); return FALSE; }
//Добавляет к текущему Filter Graph оболочку 'DMOWrapper' и вызывает инициализацию //DMO объекта с именем lpwDMOName //Перед вызовом этой функции необходимо вызвать UpdateDMOArray(...) (если она не вызывалась) //В случае ошибки функция вернет значение меньше нуля int CDirectShow::AddDMOToFilterGraph(LPCWSTR lpwDMOName) { if (!m_pGraphBuilder) return -1; if (!m_lDMOCount) return -1; IBaseFilter *pDMOWBaseFilter = NULL; IDMOWrapperFilter *pDMOWrapper; for (m_lCounter = 0; m_lCounter < m_lDMOCount; m_lCounter++) { if (_wcsicmp(m_lpwDMONames[m_lCounter], lpwDMOName) == 0) { if (FAILED(CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC, IID_IBaseFilter, (LPVOID *)&pDMOWBaseFilter))) return -1; if (FAILED(pDMOWBaseFilter->QueryInterface(IID_IDMOWrapperFilter, (LPVOID *)&pDMOWrapper))) return -1; pDMOWrapper->Init(m_cDMOCLSIDs[m_lCounter], m_gidRecentDMOCat); pDMOWrapper->Release(); m_pGraphBuilder->AddFilter(pDMOWBaseFilter, m_lpwDMONames[m_lCounter]); pDMOWBaseFilter->Release(); } else { if (m_lCounter >= (m_lDMOCount - 1)) return -1; else continue; } } return 0; }
void CFilterProp::ShowProperties() { if ( !pGB ) return; HRESULT hr; IBaseFilter *pFilter = NULL; TCHAR szNameToFind[128]; ISpecifyPropertyPages *pSpecify; // Read the current filter name from the list box int nCurSel = m_ListFilters.GetCurSel(); m_ListFilters.GetText(nCurSel, szNameToFind); // Read the current list box name and find it in the graph pFilter = FindFilterFromName(szNameToFind); if (!pFilter) return; // Discover if this filter contains a property page hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpecify); if (SUCCEEDED(hr)) { do { FILTER_INFO FilterInfo; hr = pFilter->QueryFilterInfo(&FilterInfo); if (FAILED(hr)) break; CAUUID caGUID; hr = pSpecify->GetPages(&caGUID); if (FAILED(hr)) break; pSpecify->Release(); // Display the filter's property page OleCreatePropertyFrame( m_hWnd, // Parent window 0, // x (Reserved) 0, // y (Reserved) FilterInfo.achName, // Caption for the dialog box 1, // Number of filters (IUnknown **)&pFilter, // Pointer to the filter caGUID.cElems, // Number of property pages caGUID.pElems, // Pointer to property page CLSIDs 0, // Locale identifier 0, // Reserved NULL // Reserved ); CoTaskMemFree(caGUID.pElems); FilterInfo.pGraph->Release(); } while(0); } pFilter->Release(); }
/******************************Public*Routine******************************\ * AddVideoMixingRendererToFG * \**************************************************************************/ HRESULT CMpegMovie::AddVideoMixingRendererToFG() { if ( m_Vw ) { return FALSE; } else { IBaseFilter* pBF = NULL; HRESULT hRes = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (LPVOID *)&pBF); if(SUCCEEDED(hRes)) { hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer"); if(SUCCEEDED(hRes)) { hRes = SetRenderingMode(pBF, VMRMode_Renderless); hRes = pBF->QueryInterface(IID_IVMRSurfaceAllocatorNotify, (LPVOID *)&m_San); hRes = CreateDefaultAllocatorPresenter(); hRes = m_San->AdviseSurfaceAllocator(MY_USER_ID, this); } } if(pBF) { pBF->Release(); } if(SUCCEEDED(hRes)) { HRESULT hr = m_Wc->SetVideoClippingWindow(m_hwndApp); hr = m_Wc->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); } else { if(m_Wc) { m_Wc->Release(); m_Wc = NULL; } } return hRes; } }
HRESULT CFilterProp::EnumFilters() { if ( !pGB ) return E_FAIL; HRESULT hr; IEnumFilters *pEnum = NULL; IBaseFilter *pFilter = NULL; ULONG cFetched; // Clear filters list box m_ListFilters.ResetContent(); // Get filter enumerator hr = pGB->EnumFilters(&pEnum); if (FAILED(hr)) { m_ListFilters.AddString(TEXT("<ERROR>")); return hr; } // Enumerate all filters in the graph while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) { FILTER_INFO FilterInfo; TCHAR szName[256]; hr = pFilter->QueryFilterInfo(&FilterInfo); if (FAILED(hr)) { m_ListFilters.AddString(TEXT("<ERROR>")); } else { ISpecifyPropertyPages *pSpecify; hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpecify); if (SUCCEEDED(hr)) { pSpecify->Release(); // Add the filter name to the filters listbox USES_CONVERSION; lstrcpy(szName, W2T(FilterInfo.achName)); m_ListFilters.AddString(szName); } FilterInfo.pGraph->Release(); } pFilter->Release(); } pEnum->Release(); return hr; }
HRESULT InitializeWindowlessVMR(void) { IBaseFilter* pVmr = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams. IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if( SUCCEEDED(hr)) { hr = pConfig->SetRenderingMode(VMRMode_Windowless); // Set two streams - video and alpha-blended bitmap hr = pConfig->SetNumberOfStreams(2); pConfig->Release(); } hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWC); if( SUCCEEDED(hr)) { hr = pWC->SetVideoClippingWindow(ghApp); hr = pWC->SetBorderColor(RGB(0,0,0)); } // Get alpha-blended bitmap interface hr = pVmr->QueryInterface(IID_IVMRMixerBitmap, (void**)&pBMP); } pVmr->Release(); } return hr; }
HRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9) { IBaseFilter* pVmr = NULL; if (!ppVmr9) return E_POINTER; *ppVmr9 = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer 9"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams SmartPtr <IVMRFilterConfig9> pConfig; JIF(pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig)); JIF(pConfig->SetRenderingMode(VMR9Mode_Windowless)); hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC); if( SUCCEEDED(hr)) { hr = pWC->SetVideoClippingWindow(ghApp); hr = pWC->SetBorderColor(RGB(0,0,0)); } // Get alpha-blended bitmap interface hr = pVmr->QueryInterface(IID_IVMRMixerBitmap9, (void**)&pBMP); } // Don't release the pVmr interface because we are copying it into // the caller's ppVmr9 pointer *ppVmr9 = pVmr; } return hr; }
HRESULT CNetworkProvider::RegisterDeviceFilter(IUnknown* pUnkFilterControl,ULONG* ppvRegisitrationContext) { RegisterDevice* device; FILTER_INFO filterinfo; HRESULT hr; IBaseFilter* filter; LOG4CPLUS_INFO(logger,"RegisterDeviceFilter start"); IMpeg2Demultiplexer* demux; if (m_pNetworkProviderPin->GetConnected() != NULL){ hr = m_pNetworkProviderPin->CreateOutputPin(m_pNetworkProviderPin->GetConnected()); } CAutoLock lock(&m_Lock); if (pUnkFilterControl == NULL){ return E_POINTER; } if (&ppvRegisitrationContext == NULL ){ return E_POINTER; } hr = pUnkFilterControl->QueryInterface(IID_IBaseFilter, (void**) &filter); if (hr != S_OK ){ return S_FALSE; } hr = filter->QueryFilterInfo(&filterinfo); filterinfo.pGraph = NULL; if (hr != S_OK ){ return S_FALSE; } LOG4CPLUS_DEBUG(logger,"RegisterDeviceFilter checks finished"); m_fid = m_fid + 1; device = new RegisterDevice(); device->id = m_fid; device->control = filter; wcstombs( device->name, filterinfo.achName, sizeof(device->name)); ppvRegisitrationContext = &m_fid; hr = pUnkFilterControl->QueryInterface(IID_IMpeg2Demultiplexer, (void**) &demux); if (hr == S_OK ){ LOG4CPLUS_DEBUG(logger,"RegisterDeviceFilter device prepared for registration - Name: "<<device->name<<" - "<<m_fid<<" - "<<&m_fid); device->control = NULL; delete device; LOG4CPLUS_INFO(logger,"RegisterDeviceFilter demux skipped"); return S_FALSE; }else{ LOG4CPLUS_INFO(logger,"RegisterDeviceFilter device prepared for registration - Name: "<<device->name<<" - "<<m_fid<<" - "<<&m_fid); IBDA_DeviceControl* ctrl; if( filter->QueryInterface(_uuidof(IBDA_DeviceControl), (void**) &ctrl)==S_OK){ device->deviceControl=ctrl; } m_vecDevices.push_back(device); CheckCapabilities(filter); } LOG4CPLUS_DEBUG(logger,"RegisterDeviceFilter finished"); return S_OK; }
HRESULT Captura::IniciarWindowlessVMR(HWND hWnd) { IBaseFilter* pVmr = NULL; // Crear el VMR y añadirlo al FilterGraph HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = m_pGB->AddFilter(pVmr, L"Video Mixing Renderer"); if (SUCCEEDED(hr)) { // Establecer el modo de rendeado IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if( SUCCEEDED(hr)) { pConfig->SetRenderingMode(VMRMode_Windowless); pConfig->Release(); } hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&m_pWC); if( SUCCEEDED(hr)) { m_pWC->SetVideoClippingWindow(hWnd); } } else { } pVmr->Release(); } return hr; }
void CInMin::Setup() { ISpecifyPropertyPages *pSpec = NULL; IBaseFilter* pBF = m_VideoCaptureDevice.GetIBaseFilter(); if( pBF ) { if( pBF->QueryInterface(IID_ISpecifyPropertyPages,(void **)&pSpec) == S_OK ) { if( pSpec ) { CAUUID cauuid; pSpec->GetPages(&cauuid); OleCreatePropertyFrame(0, 30, 30, NULL, 1, (IUnknown **)&pBF, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); CoTaskMemFree(cauuid.pElems); pSpec->Release(); } } } }
HRESULT VideoCapture::AddSampleGrabber(IBaseFilter** ppGrabberFilter) { IBaseFilter* pFilter; hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pFilter); if (FAILED(hr)) return hr; *ppGrabberFilter = pFilter; hr = m_pGraph->AddFilter(pFilter, L"Sample Grabber"); if (FAILED(hr)) { pFilter->Release(); return hr; } SAFE_RELEASE(m_pGrabber); pFilter->QueryInterface(IID_ISampleGrabber, (void **)&m_pGrabber); AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; hr = m_pGrabber->SetMediaType(&mt); if (FAILED(hr)) { m_pGrabber->Release(); pFilter->Release(); return hr; } FreeMediaType(mt); hr = m_pGrabber->SetOneShot(FALSE); hr = m_pGrabber->SetBufferSamples(TRUE); (*ppGrabberFilter)->AddRef(); pFilter->Release(); return hr; }
HRESULT CDXGraph::RenderFile(CString mSourceFile) { if(pGraph != NULL) { //pGraph->RenderFile(mSourceFile, NULL); //add grabber filter IBaseFilter *pGrabberF = NULL; this->AddGrabber(&pGrabberF); //add source filter IBaseFilter *pSrc; HRESULT hr = pGraph->AddSourceFilter(mSourceFile, L"Source", &pSrc); if(FAILED(hr)) return hr; /*IBaseFilter *pSrc; HRESULT hr = CoCreateInstance(CLSID_FFSrcFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pSrc); if (FAILED(hr)) return hr; hr = pGraph->AddFilter(pSrc, L"SrcFilter"); if (FAILED(hr)) return hr;*/ hr = pSrc->QueryInterface(IID_INetDvr, (void **)&pNetDvr); if (FAILED(hr)) return hr; //add renderer filter IBaseFilter *pRender; hr = CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pRender); if (FAILED(hr)) return hr; hr = pGraph->AddFilter(pRender, L"Renderer"); if (FAILED(hr)) return hr; hr = ConnectFilters(pGraph, pSrc, pGrabberF, MEDIATYPE_NULL); hr = ConnectFilters(pGraph, pGrabberF, pRender, MEDIATYPE_NULL); pGrabberF->Release(); pSrc->Release(); pRender->Release(); //test the graph SaveGraphFile(pGraph, L"D:\\SliderPlayer_264.grf"); return hr; } return E_FAIL; }
int TffDecoder::loadAVInameAndPreset(void) { IEnumFilters *eff=NULL; int cnt=0; if (m_pGraph->EnumFilters(&eff)==S_OK) { eff->Reset(); IBaseFilter *bff; while (eff->Next(1,&bff,NULL)==S_OK) { CLSID iffclsid; bff->GetClassID(&iffclsid); if (iffclsid==CLSID_FFDSHOW) cnt++; if (AVIname[0]=='\0') { FILTER_INFO iff; bff->QueryFilterInfo(&iff); IFileSourceFilter *ifsf=NULL; bff->QueryInterface(IID_IFileSourceFilter,(void**)&ifsf); if (ifsf) { LPOLESTR aviNameL; ifsf->GetCurFile(&aviNameL,NULL); ifsf->Release(); WideCharToMultiByte(CP_ACP,0,aviNameL,-1,AVIname,511, NULL, NULL ); if (globalSettings.autoPreset) { TpresetSettings *preset=presets.getAutoPreset(AVIname,globalSettings.autoPresetFileFirst); if (preset) setPresetPtr(preset); } } if (iff.pGraph) iff.pGraph->Release(); } bff->Release(); } eff->Release(); } return cnt; }
//查找FilterGraph上某一个接口,不管在Filter还是Pin上,找到即返回 BOOL FindInterface(IGraphBuilder* pGraphBuilder, REFGUID iid, void** ppUnk) { if(!pGraphBuilder || !ppUnk) return FALSE; HRESULT hr = E_FAIL; IEnumFilters* pEnumFilter = NULL; if(FAILED(pGraphBuilder->QueryInterface(&pEnumFilter))) return FALSE; BOOL bRet = FALSE; IBaseFilter* pFilter = NULL; while(S_OK == pEnumFilter->Next(1,&pFilter,NULL)) { hr = pFilter->QueryInterface(iid,ppUnk); if(SUCCEEDED(hr)) { bRet = TRUE; pFilter->Release(); break; } else { bRet = FindPinInterface(pFilter,iid,ppUnk); if(bRet) { pFilter->Release(); break; } } pFilter->Release(); } pEnumFilter->Release(); return FALSE; }
void DSManager::initCaptureDevices() { HRESULT ret = 0; VARIANT name; ICreateDevEnum* devEnum = NULL; IEnumMoniker* monikerEnum = NULL; IMoniker* moniker = NULL; if(m_devices.size() > 0) { /* clean up our list in case of reinitialization */ for(std::list<DSCaptureDevice*>::iterator it = m_devices.begin() ; it != m_devices.end() ; ++it) { delete *it; } m_devices.clear(); } /* get the available devices list */ ret = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&devEnum); if(FAILED(ret)) { return; } ret = devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &monikerEnum, 0); /* error or no devices */ if(FAILED(ret) || ret == S_FALSE) { devEnum->Release(); return; } /* loop and initialize all available capture devices */ while(monikerEnum->Next(1, &moniker, 0) == S_OK) { DSCaptureDevice* captureDevice = NULL; IPropertyBag* propertyBag = NULL; { IBaseFilter* cp = NULL; if(!FAILED(moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&cp))) { IAMVfwCaptureDialogs* vfw = NULL; if(!FAILED( cp->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)&vfw))) { if(vfw) { vfw->Release(); cp->Release(); continue; } } } } /* get properties of the device */ ret = moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&propertyBag); if(!FAILED(ret)) { VariantInit(&name); ret = propertyBag->Read(L"FriendlyName", &name, 0); if(FAILED(ret)) { VariantClear(&name); propertyBag->Release(); moniker->Release(); continue; } /* create a new capture device */ captureDevice = new DSCaptureDevice(name.bstrVal); /* wprintf(L"%ws\n", name.bstrVal); */ if(captureDevice && captureDevice->initDevice(moniker)) { /* initialization success, add to the list */ m_devices.push_back(captureDevice); } else { /* printf("failed to initialize device\n"); */ delete captureDevice; } /* clean up */ VariantClear(&name); propertyBag->Release(); } moniker->Release(); } /* cleanup */ monikerEnum->Release(); devEnum->Release(); }
HRESULT CVMR9Subgraph::AddCaptureFilter(LPCWSTR lpPath ,LPCWSTR pszVidComName,LPCWSTR lpszAudDevice ,LPCWSTR pszAudComName ,IMultiVMR9Wizard* pWizard ) { HRESULT hr = S_OK; IGraphBuilder* pGb = 0; ICaptureGraphBuilder2 * pBuild = 0; IBaseFilter* pStreamFt = 0; IBaseFilter* pAudFt = 0; IBaseFilter* pAudCom = 0;//音频压缩 IBaseFilter* pVidCom = 0;//视频压缩 IBaseFilter* pAviMux = 0; IFileSinkFilter *pSink = 0;//file IConfigAviMux *pConfigMux = NULL; CMediaHelper Helper; if(m_pCapGraph) hr = DelCaptureFilter(); if(FAILED(hr) || m_pCapGraph) return E_INVALIDARG; try { // create graph hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph, (void**)&(m_pCapGraph) ); if( FAILED(hr))throw hr; hr = m_pCapGraph->QueryInterface( IID_IGraphBuilder, (void**)&(pGb) ); if( FAILED(hr))throw hr; hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&pBuild); if( FAILED(hr))throw hr; hr =pBuild->SetFiltergraph(pGb); if( FAILED(hr))throw hr; //连接输出流filter///////////////////////////////////////// // // filter ---> |-------| // |AVI MUX| ----> Avi File // sound device ---> |-------| // /////////////////////////////////////////////////////////// hr = pWizard->InitializeOutStream(m_dwID); if( FAILED(hr)) throw hr; hr = pWizard->GetOutStreamFilter(m_dwID,&pStreamFt); if( FAILED(hr)) throw hr; if(pStreamFt == 0) throw E_INVALIDARG; hr = m_pCapGraph->AddFilter( pStreamFt, L"OutFilter"); if( FAILED(hr))throw hr; //create AVI MUX Filter hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,lpPath, &pAviMux, &pSink); if( FAILED(hr) || !pAviMux) throw hr; if(pszVidComName){//视频压缩 hr = Helper.GetVidCompression(pszVidComName,&pVidCom); if( SUCCEEDED(hr) && pVidCom){ hr = m_pCapGraph->AddFilter(pVidCom,L"VidCom"); if( FAILED(hr) ) throw hr; } } if( lpszAudDevice){//音频采集 hr = Helper.GetAudCapDevice(lpszAudDevice,&pAudFt); if( FAILED(hr) || !pAudFt) throw hr; hr = m_pCapGraph->AddFilter(pAudFt,L"AudFt"); if( FAILED(hr) ) throw hr; if(pszAudComName){ hr = Helper.GetAudCompression(pszAudComName,&pAudCom); if( FAILED(hr) || !pAudCom) throw hr; hr = m_pCapGraph->AddFilter(pAudCom,L"AudCom"); if( FAILED(hr) ) throw hr; } } //开始连接 hr = pBuild->RenderStream(0, &MEDIATYPE_Video,pStreamFt,pVidCom,pAviMux); if( FAILED(hr) ) throw hr; if(pAudFt){ pBuild->RenderStream(0,0,pAudFt,pAudCom,pAviMux); if( FAILED(hr) ) throw hr; hr = pAviMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux); if( SUCCEEDED(hr)) { pConfigMux->SetMasterStream(1); } } /*IConfigInterleaving *pInterleave = NULL; hr = pAviMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave); if (SUCCEEDED(hr)) { pInterleave->put_Mode(INTERLEAVE_CAPTURE); pInterleave->Release(); }*/ //连接完成 hr = CheckConnection(pStreamFt); if( FAILED(hr))throw hr; //// Done ///////////////////////////////////////////// // ok, all is rendered, now get MediaControl hr = m_pCapGraph->QueryInterface( IID_IMediaControl, (void**)&(m_pCapMc) ); if( FAILED(hr))throw hr; } catch(HRESULT hr1) { hr = hr1; } RELEASE(pStreamFt); RELEASE(pGb); RELEASE(pBuild); RELEASE(pConfigMux); RELEASE(pAudFt); RELEASE(pAudCom ); RELEASE(pVidCom ); RELEASE(pAviMux ); RELEASE(pSink); return hr; }
HRESULT RecordGraph::BuildGraph(CString recordFileName) { HRESULT hr; ICreateDevEnum *pSysAudioCaptureEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysAudioCaptureEnum); if (FAILED(hr)) { return hr; } IBaseFilter *pAudioCapture = NULL; IEnumMoniker *pEnumMoniker = NULL; hr = pSysAudioCaptureEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumMoniker, 0); if (hr == S_OK) { IMoniker *pMoniker = NULL; ULONG fetched; BOOL findMicrophone = FALSE; while(pEnumMoniker->Next(1, &pMoniker, &fetched) == S_OK && !findMicrophone) { IPropertyBag *pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); if(SUCCEEDED(hr)) { VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if(SUCCEEDED(hr)) { ASSERT(varName.vt == VT_BSTR); CString friendlyName(varName.bstrVal); if(friendlyName.Find(L"Microphone") >= 0) { hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void **)&pAudioCapture); findMicrophone = TRUE; } VariantClear(&varName); pPropBag->Release(); } } } pEnumMoniker->Release(); } pSysAudioCaptureEnum->Release(); if(pAudioCapture == NULL) { return S_FALSE; } pBuilder->AddFilter(pAudioCapture, L"Audio Capture"); IBaseFilter *pWaveDest = NULL; hr = CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pWaveDest); if(FAILED(hr)) { return hr; } pBuilder->AddFilter(pWaveDest, L"Wave Dest"); IBaseFilter *pFileWriter = NULL; hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pFileWriter); if(FAILED(hr)) { return hr; } pBuilder->AddFilter(pFileWriter, L"File Writer"); IFileSinkFilter *pFileSetter = NULL; hr = pFileWriter->QueryInterface(IID_IFileSinkFilter, (void **)&pFileSetter); if(FAILED(hr)) { return hr; } AM_MEDIA_TYPE pmt; pmt.majortype = MEDIATYPE_Stream; pmt.subtype = MEDIASUBTYPE_WAVE; pmt.formattype = FORMAT_WaveFormatEx; hr = pFileSetter->SetFileName(recordFileName, &pmt); hr = ConnectFilters(pBuilder, pAudioCapture, pWaveDest, MEDIATYPE_NULL);if(FAILED(hr)) return hr; hr = ConnectFilters(pBuilder, pWaveDest, pFileWriter, MEDIATYPE_NULL);//if(FAILED(hr)) return hr; SaveGraphFile(pBuilder, L"D:\\Record.grf"); pFileSetter->Release(); pFileWriter->Release(); pWaveDest->Release(); pAudioCapture->Release(); }
void gui::dx::audio_playerX::initialize_speedup_filter() { if (speedup_filter_available_valid && !speedup_filter_available) { // We don't seem to have the filter. Too bad. return; } // Either the filter exists or we haven't tried yet. Let's try to create // it and remember whether it worked. IBaseFilter *pNewFilter = NULL; HRESULT res; res = CoCreateInstance(CLSID_TPBVupp69, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNewFilter); if (res != S_OK) { traceX("dx_audio_player: Speedup filter not available, error 0x%x", res); speedup_filter_available = false; speedup_filter_available_valid = true; return; } res = m_graph_builder->AddFilter(pNewFilter, NULL); if (res != S_OK) { traceX("dx_audio_player: AddFilter(Speedup filter): error 0x%x", res); pNewFilter->Release(); return; } speedup_filter_available = true; speedup_filter_available_valid = true; // AM_DBG lib::debugX("dx_audio_player: added speedup filter to graph"); // Next step: find out where we want to add the filter to the graph. // We iterate over the filter graph, then for each item in the graph // we iterate over the connected output pins util we find one we like. IPin *pOutputPin = NULL; IPin *pInputPin = NULL; IEnumFilters *pEnumFilters = NULL; res = m_graph_builder->EnumFilters(&pEnumFilters); if (res != S_OK) { traceX("dx_audio_filter: EnumFilters: error 0x%x", res); return; } IBaseFilter *pCurFilter; while (pOutputPin == NULL && (res=pEnumFilters->Next(1, &pCurFilter, NULL)) == S_OK) { AM_DBG { FILTER_INFO info; LPWSTR vendorInfo; res = pCurFilter->QueryFilterInfo(&info); if (res != S_OK) info.achName[0] = 0; res = pCurFilter->QueryVendorInfo(&vendorInfo); if (res != S_OK) vendorInfo = L""; //ambulant::lib::textptr tInfo(info.achName); //ambulant::lib::textptr tVendorInfo(vendorInfo); //lib::debugX("dx_audio_filter: filter found: '%s' vendor '%s'", tInfo.c_str(), tVendorInfo.c_str()); } IEnumPins *pEnumPins; res = pCurFilter->EnumPins(&pEnumPins); IPin *pCurPin; while (pOutputPin == NULL && (res=pEnumPins->Next(1, &pCurPin, NULL)) == S_OK) { AM_MEDIA_TYPE mediaType; PIN_DIRECTION curPinDir; res = pCurPin->QueryDirection(&curPinDir); HRESULT res2 = pCurPin->ConnectionMediaType(&mediaType); if (res == S_OK && res2 == S_OK && curPinDir == PINDIR_OUTPUT && mediaType.majortype == MEDIATYPE_Audio&& mediaType.subtype == MEDIASUBTYPE_PCM){ pOutputPin = pCurPin; res = pOutputPin->ConnectedTo(&pInputPin); if (res != S_OK) { // This output pin was the correct type, but not connected. // So it cannot be the one we're looking for. pOutputPin = pInputPin = NULL; } else { // Found it! pOutputPin->AddRef(); pInputPin->AddRef(); } } if (res2 == S_OK) { if (mediaType.cbFormat != 0) { CoTaskMemFree((PVOID)mediaType.pbFormat); } } pCurPin->Release(); } if (res != S_FALSE && res != S_OK) traceX("dx_audio_filter: enumerating pins: error 0x%x", res); pEnumPins->Release(); pCurFilter->Release(); } if (res != S_FALSE && res != S_OK) traceX("dx_audio_filter: enumerating filters: error 0x%x", res); pEnumFilters->Release(); // We have the correct pins now. if (pOutputPin) { traceX("dx_audio_filter: found the right pins!"); } else { traceX("dx_audio_filter: could not find a good pin"); pOutputPin->Release(); pInputPin->Release(); return; } // Now we need to find the pins on our speedup filter. IPin *pFilterInputPin = NULL; IPin *pFilterOutputPin = NULL; IEnumPins *pEnumPins; res = pNewFilter->EnumPins(&pEnumPins); IPin *pCurPin; while (res=pEnumPins->Next(1, &pCurPin, NULL) == S_OK) { PIN_DIRECTION pinDir; res = pCurPin->QueryDirection(&pinDir); //assert(res == S_OK); if (pinDir == PINDIR_INPUT) { if (pFilterInputPin) { traceX("dx_audio_filter: multiple input pins on filter"); goto bad; } pFilterInputPin = pCurPin; pFilterInputPin->AddRef(); } else { if (pFilterOutputPin) { traceX("dx_audio_filter: multiple output pins on filter"); goto bad; } pFilterOutputPin = pCurPin; pFilterOutputPin->AddRef(); } } if (!pFilterInputPin) { traceX("dx_audio_filter: no input pin on filter"); goto bad; } if (!pFilterOutputPin) { traceX("dx_audio_filter: no output pin on filter"); goto bad; } // We have everything. Sever the old connection and insert the filter. res = m_graph_builder->Disconnect(pOutputPin); if (res) { traceX("dx_audio_filter: Severing old connection: error 0x%x", res); goto bad; } res = m_graph_builder->Disconnect(pInputPin); if (res) { traceX("dx_audio_filter: Severing old connection: error 0x%x", res); goto bad; } res = m_graph_builder->Connect(pOutputPin, pFilterInputPin); if (res) { traceX("dx_audio_filter: Creating filter input connection: error 0x%x", res); goto bad; } res = m_graph_builder->Connect(pFilterOutputPin, pInputPin); if (res) { traceX("dx_audio_filter: Creating filter output connection: error 0x%x", res); goto bad; } // Finally remember the interface to set speedup/slowdown, and register ourselves // in the global pool (so Amis can change our speed). res = pNewFilter->QueryInterface(IID_IVuppInterface, (void**) &m_audio_speedup); if (res != S_OK) { traceX("dx_audio_filter: filter does not provide IVuppInterface"); goto bad; } set_rate(s_current_playback_rate); bad: if (pOutputPin) pOutputPin->Release(); if (pInputPin) pInputPin->Release(); if (pFilterOutputPin) pFilterOutputPin->Release(); if (pFilterInputPin) pFilterInputPin->Release(); return; }
// // CFilePlayer::BuildGraph(): Builds a AVI/MPEG/.. playback graph rendering via // OverlayMixer which uses app's given DDraw params. // HRESULT CFilePlayer::BuildGraph(HWND hWndApp, LPDIRECTDRAW pDDObj, LPDIRECTDRAWSURFACE pDDPrimary) { DbgLog((LOG_TRACE, 5, TEXT("CFilePlayer::BuildGraph() entered"))) ; HRESULT hr ; IBaseFilter *pOvM ; WCHAR achwFileName[MAX_PATH] ; LPWSTR lpszwFileName = NULL ; IBaseFilter *pVR ; // First release any existing interface pointer(s) ReleaseInterfaces() ; SetColorKey(253) ; // default magenta for 8bpp // Check if a file name has been specified; if so, use that if (lstrlen(GetFileName()) > 0) // if something was specified before { #ifdef UNICODE lstrcpy(achwFileName, GetFileName()) ; #else MultiByteToWideChar(CP_ACP, 0, GetFileName(), -1, achwFileName, MAX_PATH) ; #endif lpszwFileName = achwFileName ; } else // no file specified, but we should have detected it before!!! return E_FAIL ; // // Instantiate Overlay Mixer, add it to the graph and set DDraw params // hr = AddOvMToGraph(&pOvM, pDDObj, pDDPrimary) ; if (FAILED(hr)) { return E_FAIL ; } // // First render the graph for the selected file // hr = m_pGraph->RenderFile(lpszwFileName, NULL) ; if (S_OK != hr) { DbgLog((LOG_ERROR, 0, TEXT("Rendering the given file didn't succeed completely (Error 0x%lx)"), hr)) ; m_pGraph->RemoveFilter(pOvM) ; // remove from graph pOvM->Release() ; // release filter return E_FAIL ; } // // Because there are some AVI files which on some machines decide to rather go // through the Color Space Converter filter, just making sure that the OverlayMixer // is actually being used. Otherwise we have to do some more (bull)work. // if (! IsOvMConnected(pOvM) ) { DbgLog((LOG_TRACE, 1, TEXT("OverlayMixer is not used in the graph. Try again..."))) ; // // Check that the specified file has a video stream. Otherwise OverlayMixer // will never be used and DDraw exclusive mode playback doesn't make any sense. // if (FAILED(GetVideoRendererInterface(&pVR))) { DbgLog((LOG_TRACE, 1, TEXT("Specified file doesn't have any video stream. Aborting graph building."))) ; m_pGraph->RemoveFilter(pOvM) ; // remove from graph pOvM->Release() ; // release filter return E_FAIL ; } // // Put the video stream to go through the OverlayMixer. // hr = PutVideoThroughOvM(pOvM, pVR) ; if (FAILED(hr)) { DbgLog((LOG_TRACE, 1, TEXT("Couldn't put video through the OverlayMixer."))) ; m_pGraph->RemoveFilter(pOvM) ; // remove OvMixer from graph pOvM->Release() ; // release OvMixer filter pVR->Release() ; // release VR interface (before giving up) return E_FAIL ; } pVR->Release() ; // done with VR interface } // // We are successful in building the graph. Now the rest... // GetInterfaces(hWndApp) ; // Get IDDrawExclModeVideo interface of the OvMixer and store it hr = pOvM->QueryInterface(IID_IDDrawExclModeVideo, (LPVOID *)&m_pDDXM) ; ASSERT(SUCCEEDED(hr)) ; // Get the color key to be used and store it hr = GetColorKeyInternal(pOvM) ; ASSERT(SUCCEEDED(hr)) ; pOvM->Release() ; // done with it return S_OK ; }
HRESULT InitializeWindowlessVMR(void) { IBaseFilter* pVmr = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams. IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if( SUCCEEDED(hr)) { hr = pConfig->SetRenderingMode(VMRMode_Windowless); // Set two streams - video and alpha-blended bitmap hr = pConfig->SetNumberOfStreams(2); pConfig->Release(); } hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWC); if( SUCCEEDED(hr)) { hr = pWC->SetVideoClippingWindow(ghApp); hr = pWC->SetBorderColor(RGB(0,0,0)); } // Request point filtering (instead of bilinear filtering) // to improve the text quality. In general, if you are // not scaling the app Image, you should use point filtering. // This is very important if you are doing source color keying. IVMRMixerControl *pMix; hr = pVmr->QueryInterface(IID_IVMRMixerControl, (void**)&pMix); if( SUCCEEDED(hr)) { DWORD dwPrefs=0; hr = pMix->GetMixingPrefs(&dwPrefs); if (SUCCEEDED(hr)) { dwPrefs |= MixerPref_PointFiltering; dwPrefs &= ~(MixerPref_BiLinearFiltering); hr = pMix->SetMixingPrefs(dwPrefs); } pMix->Release(); } // Get alpha-blended bitmap interface hr = pVmr->QueryInterface(IID_IVMRMixerBitmap, (void**)&pBMP); } else Msg(TEXT("Failed to add VMR to graph! hr=0x%x\r\n"), hr); pVmr->Release(); } else Msg(TEXT("Failed to create VMR! hr=0x%x\r\n"), hr); return hr; }