MFormats SDK: variable speed playback & seeking

Unlike DirectShow and other pipeline-based video frameworks, MFormats SDK is frame-based and provides true random access to video frames. This makes fast forward, rewind and slow motion very easy to implement. This post explains how to do it.


In MFormats the process of playback is a sequence of frames displayed in a loop. So, to control the rate of playback (start, pause or change speed and direction) we need to manage the way we receive and show frames from the source objects.


The SourceFrameConvertedGetByTime method returns a frame according to its absolute position in the file, if the time value is positive. If the time value is negative, the frame is selected according to its relative position in the file.


For example, let's set a positive time value "5":

 

SourceFrameConvertedGetByTime(ref m_avProps, 5, -1, out pFrame, "");


As a result it returns the frame from the fifth second of the file. In other words, the resulting frame characterized by position 5.0 in the file, irrespective of the current playback position. 


Now, let's set a negative time value "-5":

 

SourceFrameConvertedGetByTime(ref m_avProps, -5, -1, out pFrame, "");


As a result it returns the frame, that is located five frames ahead of the current playback position. In other words, the position of the frame is relative to the playback position.


The second parameter for playback control is _bdHints. It is possible to reverse playback or pause it with the help of this parameter.


If _bdHints = "pause=true", the playback is paused on the received frame. If _bdHints = "reverse=true", the playback is reversed.


Here are some examples of this method and its results:


1. Normal playback:


SourceFrameConvertedGetByTime(ref m_avProps, -1, -1, out pFrame, "");


2. Reverse playback:


SourceFrameConvertedGetByTime(ref m_avProps, -1, -1, out pFrame, "reverse=true");


3. Fast-forward playback (x5 rate):


SourceFrameConvertedGetByTime(ref m_avProps, -5, -1, out pFrame, "");


4. Fast reverse playback (-x5 rate):


SourceFrameConvertedGetByTime(ref m_avProps, -5, -1, out pFrame, "reverse=true");


5. Paused playback (for frame by frame playback, for example):


SourceFrameConvertedGetByTime(ref m_avProps, -1, -1, out pFrame, "pause=true");


File seeking

Similarly, it is possible to perform seeking in file. We just need to get a frame by the required position and then continue to get frames according to required playback mode. Common seeking is performed with the same method (to seek on the 20.1 second of the source file):


SourceFrameConvertedGetByTime(ref m_avProps, 20.1, -1, out pFrame, "");


To continue normal playback we need to start our frame-getting process with the following:


SourceFrameConvertedGetByTime(ref m_avProps, -1, -1, out pFrame, "");


Slow motion playback

Slow motion is archived by sending a frame to the receiver (preview and output device) multiple times. If you would like to slow down playback twofold, you can use the following example:

 

myPreview.ReceiverFramePut(pFrame, -1, "");
myPreview.ReceiverFramePut(pFrame, -1, "");


Playback at various speed and seeking is illustrated in File Playback sample.