STDMETHODIMP CBaseReferenceClock::GetTime(REFERENCE_TIME *pTime) { HRESULT hr; if (pTime) { REFERENCE_TIME rtNow; Lock(); rtNow = GetPrivateTime(); if (rtNow > m_rtLastGotTime) { m_rtLastGotTime = rtNow; hr = S_OK; } else { hr = S_FALSE; } *pTime = m_rtLastGotTime; Unlock(); MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) ); } else hr = E_POINTER; return hr; }
STDMETHODIMP CBaseReferenceClock::GetTime(__out REFERENCE_TIME *pTime) { HRESULT hr; if (pTime) { REFERENCE_TIME rtNow; Lock(); rtNow = GetPrivateTime(); if (rtNow > m_rtLastGotTime) { m_rtLastGotTime = rtNow; hr = S_OK; } else { hr = S_FALSE; } *pTime = m_rtLastGotTime; Unlock(); MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) ); #ifdef DXMPERF PERFLOG_GETTIME( (IReferenceClock *) this, *pTime ); #endif // DXMPERF } else hr = E_POINTER; return hr; }
BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn) { REFERENCE_TIME trStart, trStopAt; HRESULT hr = pIn->GetTime(&trStart, &trStopAt); // Don't skip frames with no timestamps if (hr != S_OK) return FALSE; int itrFrame = (int)(trStopAt - trStart); // frame duration if(S_OK==pIn->IsSyncPoint()) { MSR_INTEGER(m_idFrameType, 1); if ( m_nKeyFramePeriod < m_nFramesSinceKeyFrame ) { // record the max m_nKeyFramePeriod = m_nFramesSinceKeyFrame; } m_nFramesSinceKeyFrame = 0; m_bSkipping = FALSE; } else { MSR_INTEGER(m_idFrameType, 2); if ( m_nFramesSinceKeyFrame>m_nKeyFramePeriod && m_nKeyFramePeriod>0 ) { // We haven't seen the key frame yet, but we were clearly being // overoptimistic about how frequent they are. m_nKeyFramePeriod = m_nFramesSinceKeyFrame; } } // Whatever we might otherwise decide, // if we are taking only a small fraction of the required frame time to decode // then any quality problems are actually coming from somewhere else. // Could be a net problem at the source for instance. In this case there's // no point in us skipping frames here. if (m_itrAvgDecode*4>itrFrame) { // Don't skip unless we are at least a whole frame late. // (We would skip B frames if more than 1/2 frame late, but they're safe). if ( m_itrLate > itrFrame ) { // Don't skip unless the anticipated key frame would be no more than // 1 frame early. If the renderer has not been waiting (we *guess* // it hasn't because we're late) then it will allow frames to be // played early by up to a frame. // Let T = Stream time from now to anticipated next key frame // = (frame duration) * (KeyFramePeriod - FramesSinceKeyFrame) // So we skip if T - Late < one frame i.e. // (duration) * (freq - FramesSince) - Late < duration // or (duration) * (freq - FramesSince - 1) < Late // We don't dare skip until we have seen some key frames and have // some idea how often they occur and they are reasonably frequent. if (m_nKeyFramePeriod>0) { // It would be crazy - but we could have a stream with key frames // a very long way apart - and if they are further than about // 3.5 minutes apart then we could get arithmetic overflow in // reference time units. Therefore we switch to mSec at this point int it = (itrFrame/10000) * (m_nKeyFramePeriod-m_nFramesSinceKeyFrame - 1); MSR_INTEGER(m_idTimeTillKey, it); // For debug - might want to see the details - dump them as scratch pad #ifdef VTRANSPERF MSR_INTEGER(0, itrFrame); MSR_INTEGER(0, m_nFramesSinceKeyFrame); MSR_INTEGER(0, m_nKeyFramePeriod); #endif if (m_itrLate/10000 > it) { m_bSkipping = TRUE; // Now we are committed. Once we start skipping, we // cannot stop until we hit a key frame. } else { #ifdef VTRANSPERF MSR_INTEGER(0, 777770); // not near enough to next key #endif } } else { #ifdef VTRANSPERF MSR_INTEGER(0, 777771); // Next key not predictable #endif } } else { #ifdef VTRANSPERF MSR_INTEGER(0, 777772); // Less than one frame late MSR_INTEGER(0, m_itrLate); MSR_INTEGER(0, itrFrame); #endif } } else { #ifdef VTRANSPERF MSR_INTEGER(0, 777773); // Decode time short - not not worth skipping MSR_INTEGER(0, m_itrAvgDecode); MSR_INTEGER(0, itrFrame); #endif } ++m_nFramesSinceKeyFrame; if (m_bSkipping) { // We will count down the lateness as we skip each frame. // We re-assess each frame. The key frame might not arrive when expected. // We reset m_itrLate if we get a new Quality message, but actually that's // not likely because we're not sending frames on to the Renderer. In // fact if we DID get another one it would mean that there's a long // pipe between us and the renderer and we might need an altogether // better strategy to avoid hunting! m_itrLate = m_itrLate - itrFrame; } MSR_INTEGER(m_idLate, (int)m_itrLate/10000 ); // Note how late we think we are if (m_bSkipping) { if (!m_bQualityChanged) { m_bQualityChanged = TRUE; NotifyEvent(EC_QUALITY_CHANGE,0,0); } } return m_bSkipping; }