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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}