HRESULT CAnalyzerWriterFilter::GetMediaPositionInterface(REFIID riid, __deref_out void **ppv) { CAutoLock cObjectCreationLock(&m_ObjectCreationLock); if (m_pPosition) { return m_pPosition->NonDelegatingQueryInterface(riid,ppv); } CBasePin *pPin = GetPin(0); if (NULL == pPin) { return E_OUTOFMEMORY; } HRESULT hr = NOERROR; // Create implementation of this dynamically since sometimes we may // never try and do a seek. The helper object implements a position // control interface (IMediaPosition) which in fact simply takes the // calls normally from the filter graph and passes them upstream m_pPosition = new CAnalyzerPosPassThru(NAME("Renderer CPosPassThru"), CBaseFilter::GetOwner(), (HRESULT *) &hr, pPin, m_analyzer); if (m_pPosition == NULL) { return E_OUTOFMEMORY; } if (FAILED(hr)) { delete m_pPosition; m_pPosition = NULL; return E_NOINTERFACE; } return GetMediaPositionInterface(riid,ppv); }
//---------------------------------------------------------------------------- //! @brief レンダリング前にコールされる //! //! メディアサンプルにメディアタイムを記録する。 //! メディアタイムは開始フレームに現在のストリーム時間を加算したものになる。 //! もし、フィルタのIMediaSeekingインターフェイスが利用できない場合は、 //! このレンダーフィルタが描画したフレーム数とドロップしたフレーム数を加算する。 //! この場合、より上位のフィルタでドロップしたフレーム数はわからないので、 //! 若干精度が落ちる。 //! @param pMediaSample : メディアサンプル //---------------------------------------------------------------------------- void TBufferRenderer::OnRenderStart( IMediaSample *pMediaSample ) { CBaseVideoRenderer::OnRenderStart(pMediaSample); HRESULT hr; bool bGetTime = false; LONGLONG Current = 0, Stop = 0; IMediaSeeking *mediaSeeking = NULL; if( GetMediaPositionInterface( IID_IMediaSeeking, (void**)&mediaSeeking) == S_OK ) { GUID Format; if( SUCCEEDED(hr = mediaSeeking->GetTimeFormat( &Format ) ) ) { if( SUCCEEDED(hr = mediaSeeking->GetCurrentPosition( &Current )) && SUCCEEDED(hr = mediaSeeking->GetStopPosition( &Stop )) ) { if( IsEqualGUID( TIME_FORMAT_MEDIA_TIME, Format ) ) { double renderTime = Current / 10000000.0; double stopTime = Stop / 10000000.0; REFTIME AvgTimePerFrame; // REFTIME : 秒数を示す小数を表す倍精度浮動小数点数。 if( SUCCEEDED( hr = get_AvgTimePerFrame( &AvgTimePerFrame ) ) ) { Current = (LONGLONG)(renderTime / AvgTimePerFrame + 0.5); Stop = (LONGLONG)(stopTime / AvgTimePerFrame + 0.5); bGetTime = true; } } else if( IsEqualGUID( TIME_FORMAT_FRAME, Format ) ) { bGetTime = true; } } } mediaSeeking->Release(); mediaSeeking = NULL; } LONGLONG TimeStart = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; LONGLONG TimeEnd = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; if( bGetTime == true ) { TimeStart = m_StartFrame + Current; TimeEnd = m_StartFrame + Current; m_StopFrame = m_StartFrame + static_cast<LONG>(Stop); } else { TimeStart = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; TimeEnd = m_StartFrame + m_cFramesDrawn + m_cFramesDropped;; m_StopFrame = 0; } pMediaSample->SetMediaTime( &TimeStart, &TimeEnd ); }