HRESULT CVideoRenderer::BreakConnect() { CAutoLock cInterfaceLock(&m_InterfaceLock); // Check we are in a valid state HRESULT hr = CBaseVideoRenderer::BreakConnect(); if (FAILED(hr)) { return hr; } // The window is not used when disconnected IPin *pPin = m_InputPin.GetConnected(); if (pPin) SendNotifyWindow(pPin,NULL); // The base class break connect disables us from sending any EC_REPAINT // events which is important otherwise when we come down here to remove // our palette we end up painting the window again - which in turn sees // there is no image to draw and would otherwise send a redundant event m_ImagePalette.RemovePalette(); m_mtIn.ResetFormatBuffer(); return NOERROR; } // BreakConnect
// // SetMediaType // // We store a copy of the media type used for the connection in the renderer // because it is required by many different parts of the running renderer // This can be called when we come to draw a media sample that has a format // change with it. We normally delay type changes until they are really due // for rendering otherwise we will change types too early if the source has // allocated a queue of samples. In our case this isn't a problem because we // only ever receive one sample at a time so it's safe to change immediately // HRESULT CVideoRenderer::SetMediaType(const CMediaType *pmt) { CheckPointer(pmt,E_POINTER); HRESULT hr = NOERROR; CAutoLock cInterfaceLock(&m_InterfaceLock); CMediaType StoreFormat(m_mtIn); // Fill out the optional fields in the VIDEOINFOHEADER m_mtIn = *pmt; VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_mtIn.Format(); m_Display.UpdateFormat(pVideoInfo); // We set the new palette before completing so that the method can look // at the old RGB colours we used and compare them with the new set, if // they're all identical colours we don't need to change the palette hr = m_ImagePalette.PreparePalette(&m_mtIn,&StoreFormat,NULL); if (FAILED(hr)) { return hr; } // Complete the initialisation m_DrawImage.NotifyMediaType(&m_mtIn); m_ImageAllocator.NotifyMediaType(&m_mtIn); return NOERROR; } // SetMediaType
STDMETHODIMP CMPAudioRenderer::SetRate(double dRate) { CAutoLock cInterfaceLock(&m_InterfaceLock); if (dRate < 0.1) return VFW_E_UNSUPPORTED_AUDIO; if (m_pTimeStretch) m_pTimeStretch->setRate(dRate); m_dRate = dRate; return S_OK; }
//---------------------------------------------------------------------------- //! @brief アロケータが決まったときに呼び出されます。 //! @param pAllocator 今回の接続で使用するアロケータを指定します。 //! @param bReadOnly このアロケータからのサンプルが読みとり専用ならTRUEを指定します。 //! @return エラーコード //---------------------------------------------------------------------------- STDMETHODIMP TBufferRendererInputPin::NotifyAllocator( IMemAllocator * pAllocator, BOOL bReadOnly ) { CAutoLock cInterfaceLock(m_pInterfaceLock); // 基底クラス呼び出し HRESULT hr = CBaseInputPin::NotifyAllocator(pAllocator, bReadOnly); if( FAILED(hr) ) return hr; //自前のアロケータが有効かどうかを記録します m_ActiveAllocator = (pAllocator == (&(m_pRenderer->m_Allocator))); return S_OK; }
STDMETHODIMP CMPAudioRenderer::SetRate(double dRate) { { CAutoLock cInterfaceLock(&m_csAudioRenderer); if (dRate < 0.1) return VFW_E_UNSUPPORTED_AUDIO; if (m_pTimeStretch) m_pTimeStretch->setRate(dRate); m_dRate = dRate; } return m_pPosition->SetRate(dRate); }
//---------------------------------------------------------------------------- //! @brief 自前のアロケータオブジェクトを割り当てます。 //! @param ppAllocator : 返すアロケーター //---------------------------------------------------------------------------- STDMETHODIMP TBufferRendererInputPin::GetAllocator( IMemAllocator **ppAllocator ) { CAutoLock cInterfaceLock(m_pInterfaceLock); CheckPointer(ppAllocator,E_POINTER); // アロケータがまだ設定されていないとき if (m_pAllocator == NULL) { m_pAllocator = &(m_pRenderer->m_Allocator); m_pAllocator->AddRef(); } // 参照カウントを残すのはインタフェースの仕様です。 m_pAllocator->AddRef(); *ppAllocator = m_pAllocator; return S_OK; }
// // GetAllocator // // This overrides the CBaseInputPin virtual method to return our allocator // we create to pass shared memory DIB buffers that GDI can directly access // When NotifyAllocator is called it sets the current allocator in the base // input pin class (m_pAllocator), this is what GetAllocator should return // unless it is NULL in which case we return the allocator we would like // STDMETHODIMP CVideoInputPin::GetAllocator(IMemAllocator **ppAllocator) { CheckPointer(ppAllocator,E_POINTER); CAutoLock cInterfaceLock(m_pInterfaceLock); // Has an allocator been set yet in the base class if (m_pAllocator == NULL) { m_pAllocator = &m_pRenderer->m_ImageAllocator; m_pAllocator->AddRef(); } m_pAllocator->AddRef(); *ppAllocator = m_pAllocator; return NOERROR; } // GetAllocator
// // NotifyAllocator // // The COM specification says any two IUnknown pointers to the same object // should always match which provides a way for us to see if they are using // our DIB allocator or not. Since we are only really interested in equality // and our object always hands out the same IMemAllocator interface we can // just see if the pointers match. If they are we set a flag in the main // renderer as the window needs to know whether it can do fast rendering // STDMETHODIMP CVideoInputPin::NotifyAllocator(IMemAllocator *pAllocator,BOOL bReadOnly) { CAutoLock cInterfaceLock(m_pInterfaceLock); // Make sure the base class gets a look HRESULT hr = CBaseInputPin::NotifyAllocator(pAllocator,bReadOnly); if (FAILED(hr)) return hr; // Whose allocator is the source going to use? m_pRenderer->m_DrawImage.NotifyAllocator(FALSE); if (pAllocator == &m_pRenderer->m_ImageAllocator) m_pRenderer->m_DrawImage.NotifyAllocator(TRUE); return NOERROR; } // NotifyAllocator
// // CompleteConnect // // When we complete connection we need to see if the video has changed sizes // If it has then we activate the window and reset the source and destination // rectangles. If the video is the same size then we bomb out early. By doing // this we make sure that temporary disconnections such as when we go into a // fullscreen mode do not cause unnecessary property changes. The basic ethos // is that all properties should be persistent across connections if possible // HRESULT CVideoRenderer::CompleteConnect(IPin *pReceivePin) { CAutoLock cInterfaceLock(&m_InterfaceLock); CBaseVideoRenderer::CompleteConnect(pReceivePin); m_DrawImage.ResetPaletteVersion(); // Has the video size changed between connections VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_mtIn.Format(); if (pVideoInfo->bmiHeader.biWidth == m_VideoSize.cx) { if (pVideoInfo->bmiHeader.biHeight == m_VideoSize.cy) { return NOERROR; } } // Pass the video window handle upstream HWND hwnd = m_VideoText.GetWindowHWND(); NOTE1("Sending EC_NOTIFY_WINDOW %x",hwnd); SendNotifyWindow(pReceivePin,hwnd); // Set them for the current video dimensions m_DrawImage.SetDrawContext(); m_VideoSize.cx = pVideoInfo->bmiHeader.biWidth; m_VideoSize.cy = pVideoInfo->bmiHeader.biHeight; m_VideoText.SetDefaultSourceRect(); m_VideoText.SetDefaultTargetRect(); m_VideoText.OnVideoSizeChange(); m_VideoText.ActivateWindow(); return NOERROR; } // CompleteConnect