CSourceSeeking class

[The feature associated with this page, DirectShow, is a legacy feature. It has been superseded by MediaPlayer, IMFMediaEngine, and Audio/Video Capture in Media Foundation. Those features have been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use MediaPlayer, IMFMediaEngine and Audio/Video Capture in Media Foundation instead of DirectShow, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]

csourceseeking class hierarchy

The CSourceSeeking class is an abstract class for implementing seeking in source filters with one output pin.

This class supports the IMediaSeeking interface. It provides default implementations for all of the IMediaSeeking methods. Protected member variables store the start time, stop time, and current rate. By default, the only time format supported by the class is TIME_FORMAT_MEDIA_TIME (100-nanosecond units). See Remarks for more information.

Protected Member Variables Description
m_rtDuration Duration of the stream.
m_rtStart Start time.
m_rtStop Stop time.
m_dRateSeeking Playback rate.
m_dwSeekingCaps Seeking capabilities.
m_pLock Pointer to a critical section object for locking.
Protected Methods Description
CSourceSeeking Constructor method.
Pure Virtual Methods Description
ChangeRate Called when the playback rate changes.
ChangeStart Called when the start position changes.
ChangeStop Called when the stop position changes.
IMediaSeeking Methods Description
IsFormatSupported Determines whether a specified time format is supported.
QueryPreferredFormat Retrieves the object's preferred time format.
SetTimeFormat Sets the time format.
IsUsingTimeFormat Determines whether a specified time format is the format currently in use.
GetTimeFormat Retrieves the current time format.
GetDuration Retrieves the duration of the stream.
GetStopPosition Retrieves the time at which the playback will stop, relative to the duration of the stream.
GetCurrentPosition Retrieves the current position, relative to the total duration of the stream.
GetCapabilities Retrieves all the seeking capabilities of the stream.
CheckCapabilities Queries whether the stream has specified seeking capabilities.
ConvertTimeFormat Converts from one time format to another.
SetPositions Sets the current position and the stop position.
GetPositions Retrieves the current position and the stop position.
GetAvailable Retrieves the range of times in which seeking is efficient.
SetRate Sets the playback rate.
GetRate Retrieves the playback rate.
GetPreroll Retrieves the preroll time.

Remarks

Whenever the start position, stop position, or playback rate changes, the CSourceSeeking object calls a corresponding pure virtual method:

The derived class must implement these methods. After any seek operation, a filter must do the following:

  1. Call the IPin::BeginFlush method on the downstream input pin.
  2. Halt the worker thread that is delivering data.
  3. Call the IPin::EndFlush method on the input pin.
  4. Restart the worker thread.
  5. Call the IPin::NewSegment method on the input pin.
  6. Set the discontinuity property on the first sample. Call the IMediaSample::SetDiscontinuity method.

The call to BeginFlush frees the worker thread, if the thread is blocked waiting to deliver a sample.

In step 2, make sure that the thread has stopped sending data. Depending on the implementation, you might need to wait for the thread to exit, or for the thread to signal a response of some kind. If your filter uses the CSourceStream class, the CSourceStream::Stop method blocks until the worker thread replies.

Ideally, the new segment (step 5) should be delivered from the worker thread. It can also be done by the CSourceSeeking object, as long as the filter serializes it with the samples.

The following example shows a possible implementation. It assumes that the source filter's output pin is derived from CSourceSeeking and CSourceStream. This example defines a helper method, UpdateFromSeek, that performs steps 1 4. The CSourceStream::OnThreadStartPlay method is overridden to send the new segment, and to set a flag indicating the discontinuity. The worker thread picks up this flag and calls the IMediaSample::SetDiscontinuity method:

void CMyStream::UpdateFromSeek()
{
    if (ThreadExists()) 
    {
        DeliverBeginFlush();
        Stop();
        DeliverEndFlush();
        Run();
    }
}

HRESULT CMyStream::OnThreadStartPlay()
{
    m_bDiscontinuity = TRUE;
    return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
}

Supporting Additional Time Formats

By default, this class supports seeking only in units of reference time (TIME_FORMAT_MEDIA_TIME). To support additional time formats, override the IMediaSeeking methods that deal with time formats:

In addition, override the remaining IMediaSeeking methods to perform the necessary conversions between time formats. After the SetTimeFormat method is called, all IMediaSeeking methods must treat incoming and outgoing time parameters as being in the new time format. For example, if the m_rtDuration variable represents the duration in units of reference time, but the current time format is frames, then the GetDuration method must return the value m_rtDuration converted to frames. For example:

STDMETHODIMP GetDuration(LONGLONG *pDuration)
{
    HRESULT hr = CSourceSeeking::GetDuration(pDuration);
    if (SUCCEEDED(hr))
    {
        if (m_TimeFormat == TIME_FORMAT_FRAME)
        {
            // Convert from reference time to frames.
            *pDuration = TimeToFrame(*pDuration);  // Private method.
        }
    }
    return hr
} 

Also, make sure to check for the AM_SEEKING_ReturnTime flag in the IMediaSeeking::SetPositions method. If this flag is present, convert the position values into reference times when you return them to the caller.

Requirements

Requirement Value
Header
Ctlutil.h (include Streams.h)
Library
Strmbase.lib (retail builds);
Strmbasd.lib (debug builds)

See also

Supporting Seeking in a Source Filter