//---------------------------------------------------------------------------- //! @brief 値を設定する //---------------------------------------------------------------------------- void tTVPDSMixerVideoOverlay::SetAmpControl( float v, int flag ) { if(Shutdown) return; VMR9ProcAmpControl proc = { sizeof(VMR9ProcAmpControl) }; HRESULT hr; if(FAILED(hr = MixerControl()->GetProcAmpControl( 0, &proc )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::GetProcAmpControl.", hr); if( proc.dwFlags & flag ) { proc.dwFlags = flag; switch( flag ) { case ProcAmpControl9_Contrast: proc.Contrast = v; break; case ProcAmpControl9_Brightness: proc.Brightness = v; break; case ProcAmpControl9_Hue: proc.Hue = v; break; case ProcAmpControl9_Saturation: proc.Saturation = v; break; } if(FAILED(hr = MixerControl()->SetProcAmpControl( 0, &proc )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::SetProcAmpControl.", hr); } else { ThrowDShowException(L"Not supported parameter. IVMRMixerControl9::SetProcAmpControl.", hr); } }
//---------------------------------------------------------------------------- //! @brief 値を得る //---------------------------------------------------------------------------- void tTVPDSMixerVideoOverlay::GetAmpControl( float *v, int flag ) { if(Shutdown) return; VMR9ProcAmpControl proc = { sizeof(VMR9ProcAmpControl) }; proc.dwFlags = flag; HRESULT hr; if(FAILED(hr = MixerControl()->GetProcAmpControl( 0, &proc )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::GetProcAmpControl.", hr); switch( flag ) { case ProcAmpControl9_Contrast: *v = proc.Contrast; break; case ProcAmpControl9_Brightness: *v = proc.Brightness; break; case ProcAmpControl9_Hue: *v = proc.Hue; break; case ProcAmpControl9_Saturation: *v = proc.Saturation; break; } }
//---------------------------------------------------------------------------- //! @brief ミキシングするビデオストリームの背景色を設定する //! @param col : 設定する背景色 //---------------------------------------------------------------------------- void __stdcall tTVPDSMixerVideoOverlay::SetMixingMovieBGColor( unsigned long col ) { HRESULT hr; COLORREF cr = ChangeEndian32(col<<8); if(FAILED(hr = MixerControl()->SetBackgroundClr( cr )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::SetBackgroundClr.", hr); }
//---------------------------------------------------------------------------- //! @brief ミキシングしているビットマップの設定を解除する //---------------------------------------------------------------------------- void __stdcall tTVPDSMixerVideoOverlay::ResetMixingBitmap() { HRESULT hr; VMR9AlphaBitmap bmpInfo; if(FAILED(hr = m_VMR9MixerBmp->GetAlphaBitmapParameters(&bmpInfo)) ) ThrowDShowException(L"Failed to set IVMRMixerBitmap9::GetAlphaBitmapParameters.", hr); if( bmpInfo.hdc == NULL ) // 設定されていないのでリターン return; ZeroMemory(&bmpInfo, sizeof(bmpInfo)); // 設定せずにこのメソッドをコールすると、ビットマップを解除するという仕様らしい。 if(FAILED(hr = MixerBmp()->UpdateAlphaBitmapParameters( &bmpInfo )) ) ThrowDShowException(L"Failed to set IVMRMixerBitmap9::UpdateAlphaBitmapParameters.", hr); }
//---------------------------------------------------------------------------- //! @brief ビデオ ウィンドウのメッセージの送信先ウィンドウを指定する。 //! @param window : 送信先ウィンドウ //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::SetMessageDrainWindow( HWND window ) { HRESULT hr; if( FAILED(hr = VideoWindow()->put_MessageDrain((OAHWND)window)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_MessageDrain.", hr); } }
//---------------------------------------------------------------------------- //! @brief 表示矩形を設定する //! @param rect : 表示矩形 //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::SetRect( RECT *rect ) { if(Shutdown) return; HRESULT hr; Rect = *rect; if( FAILED(hr = VideoWindow()->SetWindowPosition(Rect.left, Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top)) ) { ThrowDShowException(L"Failed to call IVideoWindow::SetWindowPosition.", hr); } }
//---------------------------------------------------------------------------- //! @brief ステップサイズを得る //---------------------------------------------------------------------------- void tTVPDSMixerVideoOverlay::GetAmpControlStepSize( float *v, int flag ) { if(Shutdown) return; VMR9ProcAmpControlRange proc = { sizeof(VMR9ProcAmpControlRange) }; proc.dwProperty = static_cast<VMR9ProcAmpControlFlags>(flag); HRESULT hr; if(FAILED(hr = MixerControl()->GetProcAmpControlRange( 0, &proc )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::GetProcAmpControlRange.", hr); *v = proc.StepSize; }
//---------------------------------------------------------------------------- //! @brief ビデオを再生する //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::Play() { if( Shutdown ) return; HRESULT hr; if( FAILED(hr = VideoWindow()->SetWindowPosition( Rect.left, Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top )) ) { ThrowDShowException(L"Failed to call IVideoWindow::SetWindowPosition.", hr); } if( FAILED(hr = Controller()->Run()) ) { ThrowDShowException(L"Failed to call IMediaControl::Run.", hr); } if( FAILED(hr = VideoWindow()->SetWindowPosition(Rect.left, Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top)) ) { ThrowDShowException(L"Failed to call IVideoWindow::SetWindowPosition.", hr); } }
//---------------------------------------------------------------------------- //! @brief 表示/非表示を設定する //! @param b : 表示/非表示 //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::SetVisible( bool b ) { if(Shutdown) return; HRESULT hr; if (OwnerWindow ) { if( FAILED(hr = VideoWindow()->put_Visible(b?OATRUE:OAFALSE)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_Visible.", hr); } } Visible = b; }
//---------------------------------------------------------------------------- //! @brief ビデオ ウィンドウを所有する親ウィンドウを設定する。 //! //! ビデオ ウィンドウを所有する親ウィンドウを設定し、表示矩形も同時に設定する。 //! @param window : 親ウィンドウ //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::SetWindow( HWND window ) { if(Shutdown) return; HRESULT hr; if(OwnerWindow != window) { if(window == NULL) { if( FAILED(hr = VideoWindow()->put_Visible(OAFALSE)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_Visible(OAFALSE).", hr); } } if( FAILED(hr = VideoWindow()->put_Owner((OAHWND)window)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_Owner.", hr); } if(window != NULL) { if( FAILED(hr = VideoWindow()->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_WindowStyle.", hr); } if( FAILED(hr = VideoWindow()->SetWindowPosition(Rect.left, Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top)) ) { ThrowDShowException(L"Failed to call IVideoWindow::SetWindowPosition.", hr); } if( FAILED(hr = VideoWindow()->put_Visible(Visible?OATRUE:OAFALSE)) ) { ThrowDShowException(L"Failed to call IVideoWindow::put_Visible.", hr); } } OwnerWindow = window; } }
//---------------------------------------------------------------------------- //! @brief VMR9フィルタをフィルタグラフへ追加する //! @param pVMR9 : VMR9フィルタ //---------------------------------------------------------------------------- void tTVPDSMixerVideoOverlay::AddVMR9Filer( CComPtr<IBaseFilter> &pVMR9 ) { HRESULT hr = S_OK; if( FAILED(hr = pVMR9.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC) ) ) ThrowDShowException(L"Failed to create VMR9 Filter. This component requires DirectX9.", hr); if( FAILED(hr = GraphBuilder()->AddFilter( pVMR9, L"Video Mixing Render 9")) ) ThrowDShowException(L"Failed to call GraphBuilder()->AddFilter( pVMR9, L\"Video Mixing Render 9\").", hr); { CComPtr<IVMRFilterConfig9> pConfig; if( FAILED(hr = pVMR9.QueryInterface(&pConfig) ) ) ThrowDShowException(L"Failed to query IVMRFilterConfig9.", hr); if( FAILED(hr = pConfig->SetNumberOfStreams(1) ) ) ThrowDShowException(L"Failed to call IVMRFilterConfig9::SetNumberOfStreams(1).", hr); if( FAILED(hr = pConfig->SetRenderingMode(VMR9Mode_Renderless ) ) ) ThrowDShowException(L"Failed to call IVMRFilterConfig9::SetRenderingMode(VMR9Mode_Renderless).", hr); // Negotiate Renderless mode if( FAILED(hr = pVMR9.QueryInterface( &m_VMR9SurfAllocNotify ) ) ) ThrowDShowException(L"Failed to query IVMRSurfaceAllocatorNotify9.", hr); CComPtr<IVMRSurfaceAllocator9> alloc; if( FAILED(hr = AllocatorPresenter()->QueryInterface( IID_IVMRSurfaceAllocator9, reinterpret_cast<void**>(&alloc.p) ) ) ) ThrowDShowException(L"Failed to query IVMRSurfaceAllocator9.", hr); if( FAILED(hr = AllocatorNotify()->AdviseSurfaceAllocator( reinterpret_cast<DWORD_PTR>(this), alloc ) ) ) ThrowDShowException(L"Failed to call IVMRSurfaceAllocatorNotify9::AdviseSurfaceAllocator().", hr); if( FAILED(hr = Allocator()->AdviseNotify( AllocatorNotify() ) ) ) ThrowDShowException(L"Failed to call IVMRSurfaceAllocator9::AdviseNotify().", hr); // query monitor config // if( FAILED(hr = pVMR9.QueryInterface(&m_VMR9MonitorConfig)) ) // ThrowDShowException(L"Failed to query IVMRMonitorConfig9.", hr); } }
void __stdcall tTVPMFPlayer::GetPosition(unsigned __int64 *tick) { HRESULT hr = S_OK; if( PresentationClock.p ) { MFTIME mftime; if( SUCCEEDED(hr = PresentationClock->GetTime(&mftime)) ) { *tick = mftime / (ONE_SECOND / ONE_MSEC); } else { // 失敗した場合は 0 を返すようにしておく hr = S_OK; *tick = 0; } } else { *tick = 0; } if( FAILED(hr) ) { //TVPThrowExceptionMessage(L"Faild to get position."); ThrowDShowException(L"Faild to get position.",hr); } }
//---------------------------------------------------------------------------- //! @brief ミキシングするビットマップを設定する //! @param hdc : 設定しているビットマップを保持しているデバイスコンテキスト //! @param dest : 転送先位置 //! @param alpha : アルファ値 (0.0 - 1.0で指定) //---------------------------------------------------------------------------- void __stdcall tTVPDSMixerVideoOverlay::SetMixingBitmap( HDC hdc, RECT *dest, float alpha ) { HRESULT hr; VMR9AlphaBitmap bmpInfo; ZeroMemory(&bmpInfo, sizeof(bmpInfo)); bmpInfo.dwFlags = VMR9AlphaBitmap_hDC | VMR9AlphaBitmap_FilterMode; bmpInfo.hdc = hdc; bmpInfo.rSrc.left = 0; bmpInfo.rSrc.top = 0; bmpInfo.rSrc.right = dest->right - dest->left; bmpInfo.rSrc.bottom = dest->bottom - dest->top; long width; long height; // GetVideoSize( &width, &height ); // ビデオサイズではなく、最終出力画像のサイズで位置を計算する width = Rect.right - Rect.left; height = Rect.bottom - Rect.top; // 0割り回避 if( width <= 0 ) width = 1; if( height <= 0 ) height = 1; if( dest ) { bmpInfo.rDest.left = (static_cast<float>(dest->left)+0.5f)/static_cast<float>(width); bmpInfo.rDest.top = (static_cast<float>(dest->top)+0.5f)/static_cast<float>(height); bmpInfo.rDest.right = (static_cast<float>(dest->right)+0.5f)/static_cast<float>(width); bmpInfo.rDest.bottom = (static_cast<float>(dest->bottom)+0.5f)/static_cast<float>(height); } else { // NULLの時は、全体にブレンドするようにする bmpInfo.rDest.left = 0.0f; bmpInfo.rDest.top = 0.0f; bmpInfo.rDest.right = 1.0f; bmpInfo.rDest.bottom = 1.0f; } bmpInfo.fAlpha = alpha; bmpInfo.dwFilterMode = MixerPref_PointFiltering; if(FAILED(hr = MixerBmp()->SetAlphaBitmap( &bmpInfo )) ) ThrowDShowException(L"Failed to set IVMRMixerBitmap9::SetAlphaBitmap.", 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(); }
//---------------------------------------------------------------------------- //! @brief ミキシングするビデオストリームのアルファ値を取得する //! @param a : アルファ値を受け取るポインタ //---------------------------------------------------------------------------- void __stdcall tTVPDSMixerVideoOverlay::GetMixingMovieAlpha( float *a ) { HRESULT hr; if(FAILED(hr = MixerControl()->GetAlpha( 0, a )) ) ThrowDShowException(L"Failed to set IVMRMixerControl9::GetAlpha.", hr); }
//---------------------------------------------------------------------------- //! @brief フィルタグラフの構築 //! @param callbackwin : メッセージを送信するウィンドウ //! @param stream : 読み込み元ストリーム //! @param streamname : ストリームの名前 //! @param type : メディアタイプ(拡張子) //! @param size : メディアサイズ //---------------------------------------------------------------------------- void __stdcall tTVPDSVideoOverlay::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); } if( IsWindowsMediaFile(type) ) { CComPtr<IBaseFilter> pVRender; // for video renderer filter if( FAILED(hr = pVRender.CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER)) ) ThrowDShowException(L"Failed to create video renderer filter object.", hr); if( FAILED(hr = GraphBuilder()->AddFilter(pVRender, L"Video Renderer")) ) ThrowDShowException(L"Failed to call IFilterGraph::AddFilter.", hr); BuildWMVGraph( pVRender, stream ); } 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, NULL)) ) 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); } else { CComPtr<IBaseFilter> pVRender; // for video renderer filter if( FAILED(hr = pVRender.CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER)) ) ThrowDShowException(L"Failed to create video renderer filter object.", hr); if( FAILED(hr = GraphBuilder()->AddFilter(pVRender, L"Video Renderer")) ) ThrowDShowException(L"Failed to call IFilterGraph::AddFilter.", hr); BuildMPEGGraph( pVRender, m_Reader); // may throw an exception } } // 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_BasicVideo )) ) ThrowDShowException(L"Failed to query IBasicVideo", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_VideoWindow )) ) ThrowDShowException(L"Failed to query IVideoWindow", hr); if( FAILED(hr = m_GraphBuilder.QueryInterface( &m_BasicAudio )) ) ThrowDShowException(L"Failed to query IBasicAudio", hr); // check whether the stream has video if(!m_VideoWindow || !m_BasicVideo ) TVPThrowExceptionMessage(L"The stream has no video components."); { long visible; if(FAILED(hr = VideoWindow()->get_Visible(&visible))) ThrowDShowException(L"The stream has no video components or has unsupported video format.", hr); } // disable AutoShow VideoWindow()->put_AutoShow(OAFALSE); // 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(); // ここでこれを呼ぶとまずそうな気がするけど、大丈夫なのかなぁ }