Good day all,

With suffient time before a looming release, I would like to commit http://www.rockbox.org/tracker/task/12069 - Playback Rewrite - first stages. There is a small amount of follow up work to do immediately afterwords in the area of codecs that write directly into the WPS through the ID3 pointer, of which, thankfully, there are few.

It has had significant testing not only by myself for a couple months but a few others over the last week or so and noone has reported any issues (not to me anyway).

What does it do? Mostly it addresses the area of codec control. track skipping, buffering and metadata handling.

* Unlike current SVN, playback says what codecs do, codecs do not control playback - playback engine is not helpless when no codec is present.

* Playlist are advanced in-time with the playing audio (you might have noticed the track number going up several second ahead of time if using gapless transtions - not crossfaded ones).

* Thus, resume at track transitions is automatically correct becuase the playlist is in the correct place.

* Autoresume will work properly whether or not the track is kept on the buffer; this bug would be most noticeable on targets with >=16 MB of RAM where many tracks are commonly buffered at once.

* Track skipping while in transitional state works whether at the end of the playlist or just in transition without it being a hack (while delt with in a reasonable way, at the end of directories, some functions are locked out since playlist advances must occur before finishing the last track in a directory -- playlist issue). The current hack is to skip backwards by one and then seek but this creates lots of phony transitional activity that should not exist because no transition is in fact in progress. It can also lead to incorrect results in playlist boundaries were crossed, such as ending up the the wrong track altogether because playlists do not always go in reverse the same way they went forward. At the final few seconds of the end of a playlist, skipping and rewinding does not work at all in SVN because no codec is loaded to help. With resident codecs, the last codec used is still present to run again to perform the seek and for a skip the engine needs no assistance.

* Buffer only as many codecs as required at format transitions.

* Atomic formats are reliably locked in place while the codec is working with them.

* Rebuffer on skip is handled slighly differently for atomic formats if track load was incomplete - if necessary, playback will attempt to reset the buffer so that the buffer is available in its entirety. Only an atomic type that is actually too large for the available RAM should fail to buffer, barring other complications.

* Addresses the fact the watermarking is essentially meaningless for atomic audio.

* Essential information such as the runtime-db and autoresume info is not clobbered. The playing track's metadata is the playing track's metadata and is always available in the same place. Information is kept properly up to date that is changed late in the load process.

* Track end/change events really are track end/change events. There is one compulsory exception when skipping back to time 0 tagtree expects a track finish event.

* Watermark handling is better. Low buffer events trigger only discard of old tracks and filling continues after the last loaded track where previously all tracks but the current track would be pointlessly discarded. Spurious buffering events are eliminated and handled on the audio thread alone. Refill point is never above 75% of the buffer so that continuous buffering and disk spinning does not happen no matter how generous the anti-skip buffer.

* Handle broken tracks and playlists without playback dying or being out of sync.

* Many more arcane details were worked out. Codec-based gapless playback and latency hiding is *not* simple and never will be. The current approach fails to sync up with reality in that regard! Do it right or don't bother! :)

Essential changes:
* Codecs are essentially TSR at load time and stay resident until a codec change is required.

* Use of naked variables in the codec API to control codec operation is eliminated.

* Codec load/unload and run entrypoints are separate - codec_main is called for load/unload and codec_run for each track to be decoded.

* Codecs can rely on their metadata being correct and available when they are called to decode a track - no wait loop is required.

* The codec's mp3entry is it's own and is private to it and playback and as mentioned prior, it is stably available while executing in codec_run. It is undefined in codec_main.

* Codec interface and implementation is simpler - codec just responds to commands by consistently listening to its message queue though ci->get_command.

* Codecs must set their initial read positions before decoding - playback will not do this any longer. Playback initializes ci.curpos to where the handle left off or where buffering first began (if freshly-buffered) by using bufftell. The initial position in the id3 is still set by playback for resume purposes. Current codecs have been corrected (correctly, I think).

* The playback engine implements the hard stuff in the area of codec control to suit its own requirements; codecs can still be run in other environments such as within the test_codec plugin.

Other features:
* Speedier previewing when skipping and the tracks are not yet buffered; this code can be left out if it has little benefit on a particular target. * Handle short files (one less than the PCM buffer length) nicely and have the WPS display them properly as they are common with some videogame formats and not a truly unusual case at all.

Added support:
* A more powerful function, queue_peek_ex is included and is also used as the backend to implement the current APIs queue_remove_from_head and queue_peek. This allows peeking and optionally removal without blocking using a message filter list, each being a range of messages to check. We need this to reliably remove events from of the audio queue that might, and often do, arrive while backing out of transitional states. This method combined with knowing what the codec and pcmbuffer is doing is implemented to be non-racy.

* Queue functions can take NULL for the event parameter if message removal in not desired but blocking for a message is.

Note:
* With some improved support in surrounding areas, most notably with playlists, this will likely be able shed a bit of weight because fewer internal states would be needed.

Regards,
Michael Sevakis (jhMikeS)

Reply via email to