Here it comes a new technical blog, and this time it’s also related to xine,s o you get a double important post.
xine, like many other modern software, uses a plug-in architecture. This is pretty nice especially for a multimedia application, as it allows even binary distributions to provide granularity like Gentoo does with the USE flags, and allows the processes not to load all the backend libraries that aren’t needed at once.
Or does it?
Unfortunately the architecture of xine has a few problems. One of these is that at the moment, almost every plugin is loaded at application startup, rather than as needed. The first time it’s comprehensible, as xine need to produce a cache file, but the other times?
The first problem was with settings: a lot of plugins had settings to be loaded at startup, but luckily Thibaut took care of this and implemented cache for settings too. This solves one problem.
Then there is another problem: most of the times we can’t trust the extension of a file, so the default is to test the demuxer by content. Testing the demuxer by content requires loading all the demuxers and try them one by one. This is expensive. The reverse detection method is good for files, as we first try to identify the demuxer by the extension, if that doesn’t work, and just then, we do load all the demuxers and try them one by one. For stream, we can’t trust the extension at all.
So what are the problems here? Well first off even if we decided to use the reverse method as default, we’ll be losing all the advantage at the first file that fails the extension detection or at the first stream; then there is the problem that we end up even testing demuxers that, well, can’t just play files. This is the case of the cdda demuxer, for instance, or some network demuxers.
What we need then is to solve two problems:
- detect streams without using the by-content detection, this can be done once I’ll have time to complete reading mime-types from input (HTTP Content-type, but also Content-type saved in extended attributes for local files); this should solve the problem of running content-detection for every stream; most stream sources will report correct Content-type, as most likely would gnome-vfs and other VFS implementations;
- get a way to tell xine-lib that a given demuxer works only with a certain input plugin (and vice-versa, as the dvd demuxer will always use the same mpeg demuxer).
This solves a bit of problems by itself, by avoiding loading unneeded plugins, but the architecture of xine’s plugin system is still rough.
That happens because of the way the data is currently exported by the plugin itself, through a global exported structure, containing the a literal string, and the pointer to a static function used to allocate and fill the next structure. This structure contains pointers, the pointers need to be relocated, so it’s in .data.rel.ro
, which gets COW’d once the plugin is loaded and relocated; as prelink does not work with plugins, we can’t even rely on that to solve the problem for us.
With the COW, all the xine plugins gets 4KB of memory used up per plugin, per process.
What I would like instead would be a new xine_plugin_get_info()
which allocates in heap the structure, and fills it. It will be slower most likely, but it will a) avoid the difference between structures loaded from cache (which are allocated in heap), and those loaded from plugins (which are mapped in .data.rel.ro
) b) avoid the 4KB waste per plugin per process, by just allocating the right amount of memory needed to keep the structure in memory.
If I have extra time I might actually try this on a branch, it might be a decent improvement after all.