Implement trick-play in VLC Player as reasonably as possible.
LinuxMCE supports the CMD_Change_Playback_Speed() command to implement trick-play by specifying a transport speed. Positive values go foward, negative values go in reverse, and these are measured in rate * 1000. e.g. 1000 is 1x, 2000 is 2x, 4000, 4x. and these values are explicitly processed by the Media Plugin as such, so that successive presses of FF or REW, change the effective rate.
libvlc does have a video player API, with a function for setting rate, which is a floating point number directly corresponding to the playback rate, e.g. 1.0 is 1x, 2.0 is 2x. However, it is subject to the following implementation warts:
- While Playback speeds from 1x to 4x give desired trick play functionality in slower speeds, with subsequent increase in audio speed, faster rates from 8x on cause unpredictable player behavior, while audio dropping out at these faster speeds is acceptable, the video distortion from selecting an intra-frame instead of a keyframe is unacceptable.
- Rewind does not work at all with set_rate, for local media.
Given this, the following approach must be done:
For forward speeds
- For playback speeds less than 8000 (8x), set rate is used.
- For playback speeds greater than 8000 (8x), pause and set time method is used (described below)
For reverse speeds
- for any reverse speed, pause and set time method must be used.
Pause and set time method
libvlc has a method to set an absolute position within media. Once set, libvlc seeks to that position immediately, and finds the nearest keyframe and uses that point, guaranteeing a stable picture. This is called set time.
The media duration and the current media time are used with a relative offset to calculate an absolute position within the media which is a multiplier of the resulting requested playback rate. This is also used in conjunction with a recurring timer to repeat this action for X number of times within a second, but never faster than what the user can accurately see (a scaling factor to be hand tweaked for now. Lots of user testing ensuing.)
Set time can be called while paused, ensuring that the media does not play once the seek happens, but it will show the resulting still frame. This ensures that any jarring "stutter" action will not happen as a result of playback continuing before the next seek is done.
I had started an implementation of this, but had not mapped out all the states until this morning. So now it's trying to implement this, while hand-tweaking to produce a fast forward/rewind action that makes sense.