HRESULT FMPlayerDShow::BuildTheGraph() { CComQIPtr<IGraphBuilder> pGraphBuilder = m_FilterGraph; HRESULT hr = E_FAIL; if (pGraphBuilder) { CComPtr<IPin> Pin1 = GetOutPin(m_AviSplitter, 0); CComPtr<IPin> Pin2 = GetOutPin(m_AviSplitter, 1); CComPtr<IPin> PinXV = GetInPin(m_xVid, 0); if (Pin1 && Pin2 && PinXV) { hr = m_FilterGraph->ConnectDirect(Pin1, PinXV, NULL); if (FAILED(hr)) { hr = m_FilterGraph->ConnectDirect(Pin2, PinXV, NULL); } if (SUCCEEDED(hr)) { CComPtr<IPin> PinOutXV = GetOutPin(m_xVid, 0); CComPtr<IPin> PinInRenderer = GetInPin(m_VideoRenderer, 0); if (PinOutXV && PinInRenderer) { CComPtr<IPin> PinConnected; if (PinOutXV->ConnectedTo(&PinConnected) & VFW_E_NOT_CONNECTED) { //Disconnect renderer from any filters; PinInRenderer->Disconnect(); hr = m_FilterGraph->ConnectDirect(PinOutXV, PinInRenderer, NULL); } if (SUCCEEDED(hr)) { hr = RenderOutputPins(pGraphBuilder, m_AviSplitter); if (FAILED(hr)) _DBGAlertM("FMediaMgr: **RenderOutputPins: %s\n", GetErrorDescription(hr)); m_GraphBuilt = TRUE; } else _DBGAlertM("FMediaMgr: **Connect PinOutXV to PinInRenderer: %s\n", GetErrorDescription(hr)); } else _DBGAlertM("FMediaMgr: **PinOutXV or PinInRenderer is NULL\n"); } else _DBGAlertM("FMediaMgr: **Connect Splitter to xvid: %s\n", GetErrorDescription(hr)); } else _DBGAlertM("FMediaMgr: **Pin1 or Pin2 or PinXV is NULL.\n"); } return hr; }
//---------------------------------------------------------------------------- //! @brief フィルタグラフの構築 //! @param callbackwin : メッセージを送信するウィンドウ //! @param stream : 読み込み元ストリーム //! @param streamname : ストリームの名前 //! @param type : メディアタイプ(拡張子) //! @param size : メディアサイズ //---------------------------------------------------------------------------- void __stdcall tTVPDSMixerVideoOverlay::BuildGraph( HWND callbackwin, IStream *stream, const wchar_t * streamname, const wchar_t *type, unsigned __int64 size ) { HRESULT hr; //CoInitialize(NULL); // detect CMediaType from stream's extension ('type') try { if( FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)) ) ThrowDShowException(L"Failed to call CoInitializeEx.", hr); // create IFilterGraph instance if( FAILED(hr = m_GraphBuilder.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC)) ) ThrowDShowException(L"Failed to create FilterGraph.", hr); // Register to ROT if(GetShouldRegisterToROT()) { AddToROT(m_dwROTReg); } { CAutoLock Lock(&m_VMRLock); OwnerWindow = callbackwin; // copy window handle for D3D m_OwnerInst = GetModuleHandle(NULL); } m_AllocatorPresenter = new CVMRCustomAllocatorPresenter9(this,m_VMRLock); m_AllocatorPresenter->AddRef(); m_AllocatorPresenter->Initialize(); if( IsWindowsMediaFile(type) ) { CComPtr<IBaseFilter> pVMR9; AddVMR9Filer( pVMR9 ); BuildWMVGraph( pVMR9, stream ); if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerCtrl ) ) ) ThrowDShowException(L"Failed to query IVMRMixerControl9.", hr); if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerBmp ) ) ) ThrowDShowException(L"Failed to query IVMRMixerBitmap9.", hr); } else { CMediaType mt; mt.majortype = MEDIATYPE_Stream; ParseVideoType( mt, type ); // may throw an exception // create proxy filter m_Proxy = new CIStreamProxy( stream, size ); hr = S_OK; m_Reader = new CIStreamReader( m_Proxy, &mt, &hr ); if( FAILED(hr) || m_Reader == NULL ) ThrowDShowException(L"Failed to create proxy filter object.", hr); m_Reader->AddRef(); // add fliter if( FAILED(hr = GraphBuilder()->AddFilter( m_Reader, L"Stream Reader")) ) ThrowDShowException(L"Failed to call IFilterGraph::AddFilter.", hr); // AddFilterしたのでRelease m_Reader->Release(); if( mt.subtype == MEDIASUBTYPE_Avi || mt.subtype == MEDIASUBTYPE_QTMovie ) { // render output pin if( FAILED(hr = GraphBuilder()->Render(m_Reader->GetPin(0))) ) ThrowDShowException(L"Failed to call IGraphBuilder::Render.", hr); CComPtr<IBaseFilter> pRender; if( FAILED(hr = FindVideoRenderer( &pRender ) ) ) ThrowDShowException(L"Failed to call FindVideoRenderer( &pRender ).", hr); CComPtr<IPin> pRenderPin; pRenderPin = GetInPin(pRender, 0); // get decoder output pin CComPtr<IPin> pDecoderPinOut; if( FAILED(hr = pRenderPin->ConnectedTo( &pDecoderPinOut )) ) ThrowDShowException(L"Failed to call pRenderPin->ConnectedTo( &pDecoderPinOut ).", hr); // dissconnect pins if( FAILED(hr = pDecoderPinOut->Disconnect()) ) ThrowDShowException(L"Failed to call pDecoderPinOut->Disconnect().", hr); if( FAILED(hr = pRenderPin->Disconnect()) ) ThrowDShowException(L"Failed to call pRenderPin->Disconnect().", hr); // remove default render if( FAILED(hr = GraphBuilder()->RemoveFilter( pRender ) ) ) ThrowDShowException(L"Failed to call GraphBuilder->RemoveFilter(pRenderPin).", hr); CComPtr<IBaseFilter> pVMR9; AddVMR9Filer( pVMR9 ); CComPtr<IPin> pRdrPinIn; pRdrPinIn = GetInPin(pVMR9, 0); if( FAILED(hr = GraphBuilder()->ConnectDirect( pDecoderPinOut, pRdrPinIn, NULL )) ) ThrowDShowException(L"Failed to call GraphBuilder()->ConnectDirect( pDecoderPinOut, pRdrPinIn, NULL ).", hr); if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerCtrl ) ) ) ThrowDShowException(L"Failed to query IVMRMixerControl9.", hr); if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerBmp ) ) ) ThrowDShowException(L"Failed to query IVMRMixerBitmap9.", hr); } else { CComPtr<IBaseFilter> pVMR9; AddVMR9Filer( pVMR9 ); BuildMPEGGraph( pVMR9, m_Reader); // may throw an exception if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerCtrl ) ) ) ThrowDShowException(L"Failed to query IVMRMixerControl9.", hr); if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9MixerBmp ) ) ) ThrowDShowException(L"Failed to query IVMRMixerBitmap9.", hr); } } #if 1 { // 平均フレーム表示時間を取得する CComPtr<IBaseFilter> pRender; if( FAILED(hr = FindVideoRenderer( &pRender ) ) ) ThrowDShowException(L"Failed to call FindVideoRenderer( &pRender ).", hr); CComPtr<IPin> pRenderPin; pRenderPin = GetInPin(pRender, 0); AM_MEDIA_TYPE mt; if( FAILED(hr = pRenderPin->ConnectionMediaType(&mt)) ) ThrowDShowException(L"Failed to call IPin::ConnectionMediaType(pmt).", hr); if( mt.formattype == FORMAT_VideoInfo && mt.cbFormat != 0 ) { VIDEOINFOHEADER *vih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat); m_AvgTimePerFrame = vih->AvgTimePerFrame; m_Width = vih->bmiHeader.biWidth; m_Height = vih->bmiHeader.biHeight; } else if( mt.formattype == FORMAT_VideoInfo2 && mt.cbFormat != 0 ) { VIDEOINFOHEADER2 *vih = reinterpret_cast<VIDEOINFOHEADER2*>(mt.pbFormat); m_AvgTimePerFrame = vih->AvgTimePerFrame; m_Width = vih->bmiHeader.biWidth; m_Height = vih->bmiHeader.biHeight; } FreeMediaType(mt); } #endif // query each interfaces if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_MediaControl )) ) ThrowDShowException(L"Failed to query IMediaControl", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_MediaPosition )) ) ThrowDShowException(L"Failed to query IMediaPosition", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_MediaSeeking )) ) ThrowDShowException(L"Failed to query IMediaSeeking", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_MediaEventEx )) ) ThrowDShowException(L"Failed to query IMediaEventEx", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_BasicAudio )) ) ThrowDShowException(L"Failed to query IBasicAudio", hr); // set notify event if(callbackwin) { if(FAILED(hr = Event()->SetNotifyWindow((OAHWND)callbackwin, WM_GRAPHNOTIFY, (long)(this)))) ThrowDShowException(L"Failed to set IMediaEventEx::SetNotifyWindow.", hr); } } catch(const wchar_t *msg) { MakeAPause(true); ReleaseAll(); CoUninitialize(); TVPThrowExceptionMessage(msg); } catch(...) { MakeAPause(true); ReleaseAll(); CoUninitialize(); throw; } MakeAPause(false); CoUninitialize(); }
HRESULT FMPlayerDShow::LoadMedia(const tchar* pFileName, IMediaOptions* pOptions) { USES_CONVERSION; HRESULT hr = E_FAIL; if (m_FourCC == "divx" && m_StreamFormat == "divx") { Init(m_hWndParent, m_pNotify); } if (m_FilterGraph == NULL) return E_FAIL; m_MediaControl->Stop(); if (m_FileSource) { m_FilterGraph->RemoveFilter(m_FileSource); m_FileSource.Release(); } else { /* CComQIPtr<IGraphBuilder> pGraphBuilder = m_FilterGraph; if (SUCCEEDED(pGraphBuilder->RenderFile(T2OLE(pFileName), NULL))) { hr = Start(); return hr; } */ if (SUCCEEDED(DetermineVideoType(pFileName))) { InitFilters(pFileName); } else { _DBGAlertM("FMPlayerDShow: PlayVideo: **Unable to determine file format.\n"); return E_FAIL; } } _DBGAlertM("FMPlayerDShow: Starting playback: %s; offset = %I64d\n", pFileName, pOptions->rtOffset); CComQIPtr<IGraphBuilder> pGraphBuilder = m_FilterGraph; hr = pGraphBuilder->AddSourceFilter(T2OLE(pFileName), T2OLE(pFileName), &m_FileSource); if (SUCCEEDED(hr)) { CComPtr<IPin> PinSourceOut = GetOutPin(m_FileSource, 0); CComPtr<IPin> PinSplitterIn = GetInPin(m_AviSplitter, 0); if (PinSourceOut && PinSplitterIn) { PinSplitterIn->Disconnect(); hr = m_FilterGraph->ConnectDirect(PinSourceOut, PinSplitterIn, NULL); if (FAILED(hr)) _DBGAlertM("FMediaMgr: **Connect SourceOut to SplitterIn: %s\n", GetErrorDescription(hr)); } else _DBGAlertM("FMediaMgr: **PinSourceOut or PinSourceIn is NULL\n"); hr = BuildTheGraph(); if (SUCCEEDED(hr)) { m_FileName = pFileName; m_Offset = pOptions->rtOffset; hr = Start(); if (FAILED(hr)) _DBGAlertM("FMPlayerDShow: **Start() failed: %s\n", GetErrorDescription(hr)); else { SetVideoRect(m_VideoRect); } } else _DBGAlertM("FMPlayerDShow: **Cannot Start(): %s\n", GetErrorDescription(hr)); } else _DBGAlertM("FMPlayerDShow: **AddSourceFilter() failed: %s\n", GetErrorDescription(hr)); _DBGAlertM("FMPlayerDShow: StartPlayback() exiting: %s\n", GetErrorDescription(hr)); return hr; }
bool VideoCapture::InitCamera(int iDevice, int iResolution) { if (cameraInitialized) return false; HRESULT hr; bool ans; int iWidth = devices_resolutions[iDevice].x[iResolution]; int iHeight = devices_resolutions[iDevice].y[iResolution]; USES_CONVERSION; CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&pGrabber); if( !pGrabber ) return false; hr = pNull.CoCreateInstance(CLSID_NullRenderer); CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberBase( pGrabber ); ans = BindFilter(iDevice, &pSource); if( !pSource ) return false; hr = pGraph.CoCreateInstance( CLSID_FilterGraph ); if (hr!=S_OK) return false; hr = pGraph->AddFilter( pSource, L"Source" ); if (hr!=S_OK) return false; hr = pGraph->AddFilter( pGrabberBase, L"Grabber" ); if (hr!=S_OK) return false; hr = pGraph->AddFilter( pNull, L"NullRenderer" ); if (hr!=S_OK) return false; // Tell the grabber to grab 24-bit video. Must do this // before connecting it CMediaType GrabType; GrabType.SetType( &MEDIATYPE_Video ); GrabType.SetSubtype( &MEDIASUBTYPE_RGB24 ); hr = pGrabber->SetMediaType( &GrabType ); if (hr!=S_OK) return false; CComPtr< IPin > pGrabPinIn; CComPtr< IPin > pGrabPinOut; CComPtr< IPin > pNullPinIn; pSourcePin = GetOutPin( pSource, 0 ); pGrabPinIn = GetInPin( pGrabberBase, 0 ); pGrabPinOut = GetOutPin( pGrabberBase, 0 ); pNullPinIn = GetInPin( pNull, 0 ); CComPtr <ICaptureGraphBuilder2> pCaptB; pCaptB.CoCreateInstance(CLSID_CaptureGraphBuilder2); pCaptB->SetFiltergraph(pGraph); hr = pCaptB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSource, IID_IAMStreamConfig, (void**)&pConfig); if (hr!=S_OK) return false; SetResolution(iDevice, iResolution); // ... and connect them // hr = pGraph->Connect( pSourcePin, pGrabPinIn); if (hr!=S_OK) return false; hr = pGraph->Connect( pGrabPinOut, pNullPinIn ); if (hr!=S_OK) return false; // Ask for the connection media type so we know its size // AM_MEDIA_TYPE mt; hr = pGrabber->GetConnectedMediaType( &mt ); if (hr!=S_OK) return false; VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat; callback.im_width = iWidth; callback.im_height = iHeight; FreeMediaType( mt ); // Write the bitmap format // memset( &(callback.cbInfo.bih), 0, sizeof( callback.cbInfo.bih ) ); callback.cbInfo.bih.biSize = iWidth*iHeight*3; callback.cbInfo.bih.biWidth = iWidth; callback.cbInfo.bih.biHeight = iHeight; callback.cbInfo.bih.biPlanes = 1; callback.cbInfo.bih.biBitCount = 24; callback.cbInfo.pBuffer = new byte[callback.cbInfo.bih.biSize]; hr = pGrabber->SetBufferSamples( FALSE ); hr = pGrabber->SetOneShot( FALSE ); hr = pGrabber->SetCallback( &callback, 1); hr = pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &pControl); hr = pControl->Run( ); cameraInitialized = true; return true; }
HRESULT FindRenderer(IGraphBuilder *pGB, const GUID *mediatype, IBaseFilter **ppFilter) { HRESULT hr; IEnumFilters *pEnum = NULL; IBaseFilter *pFilter = NULL; IPin *pPin; ULONG ulFetched, ulInPins, ulOutPins; BOOL bFound=FALSE; // Verify graph builder interface if (!pGB) return E_NOINTERFACE; // Verify that a media type was passed if (!mediatype) return E_POINTER; // Clear the filter pointer in case there is no match if (ppFilter) *ppFilter = NULL; // Get filter enumerator hr = pGB->EnumFilters(&pEnum); if (FAILED(hr)) return hr; pEnum->Reset(); // Enumerate all filters in the graph while(!bFound && (pEnum->Next(1, &pFilter, &ulFetched) == S_OK)) { #ifdef DEBUG // Read filter name for debugging purposes FILTER_INFO FilterInfo; TCHAR szName[256]; hr = pFilter->QueryFilterInfo(&FilterInfo); if (SUCCEEDED(hr)) { // Show filter name in debugger #ifdef UNICODE lstrcpy(szName, FilterInfo.achName); #else WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); #endif FilterInfo.pGraph->Release(); } #endif // Find a filter with one input and no output pins hr = CountFilterPins(pFilter, &ulInPins, &ulOutPins); if (FAILED(hr)) break; if ((ulInPins == 1) && (ulOutPins == 0)) { // Get the first pin on the filter pPin=0; pPin = GetInPin(pFilter, 0); // Read this pin's major media type AM_MEDIA_TYPE type= {0}; hr = pPin->ConnectionMediaType(&type); if (FAILED(hr)) break; // Is this pin's media type the requested type? // If so, then this is the renderer for which we are searching. // Copy the interface pointer and return. if (type.majortype == *mediatype) { // Found our filter *ppFilter = pFilter; bFound = TRUE;; } // This is not the renderer, so release the interface. else pFilter->Release(); // Delete memory allocated by ConnectionMediaType() FreeMediaType(type); } else { // No match, so release the interface pFilter->Release(); } } pEnum->Release(); return hr; }