We got a number of replies to my previous call for feedback, which is absolutely wonderful. I figure I might as well address one of the most common issues that everyone talks about: Gapless playback in Amarok.
Just so you all know, a solution for it is in the works. However, it isn’t an easy fix. Large portions of the GStreamer backend are being retooled, redesigned, and rewritten to make it happen. Regardless, progress is being made, and has been since I started on this adventure about 3 weeks ago.
I’ll admit, Phonon GStreamer’s code isn’t exactly pretty. Sure, it plays every file format known to mankind, offers to install the codecs you’re missing, and has very high performance at the same time, but the design is far from optimal.
Part of gstreamer’s base plugins package is a nifty little element called “playbin2″. Using it is really easy, and can be demonstrated at the command line:
$ gst-launch playbin2 uri="file:///srv/media/Music/Paul and Storm - Your Love Is....flac"
That replaces the previously lengthy process of building a pipeline by hand:
$ gst-launch filesrc location="/srv/media/Music/Paul and Storm - Your Love Is....flac" ! \ decodebin2 ! autoaudiosink
decodebin2 and the auto*sink elements hide away another layer of mess involving codec detection, audio device configuration, massaging of raw audio data, and so forth.
Getting to the point of discussion, here’s a rough layout of phonon-gstreamer’s average pipeline, taken from our debugging page:
filesrc -> decodebin2 -> queue -> audioresample -> audioconvert -> pulsesink
\
-> ffmpegcolorspace -> queue -> xvimagesink
Each pipeline is hand-assembled with a bunch of calls to gst_element_factory_make, property setting, some linking of decoded audio/video streams to the proper sub-graphs, etc. Since each pipeline is hand-assembled, there is one big problem: we’re basically writing our own playbin2. This involves automatic connection of decoded audio/video streams to the proper output graphs, keeping track of the elements, setting properties across different interfaces, and worst of all: duplicating effort.
By now you’re likely wondering where gapless playback comes into this. Turns out that playbin2 handles all the trickiness of switching input streams at exactly the right time and feeding some buffers in just as the current buffers are pumped out to the soundcard. All that’s needed is to set the “uri” property at exactly the right time (when the “about-to-finish” signal is emitted). As proof of concept, have a look at my hacks repository and play with my ‘gapless’ hack:
$ make gapless-test
Work has been ongoing inside the ‘plumbing’ branch in phonon-gstreamer’s git. The first few steps have been refactoring the massive MediaObject implementation into two components: one to handle the state engine, and another to handle interfacing with GStreamer. That bit is as done as I can comfortably make it without adding a zillion tiny functions to enforce total encapsulation, yet introducing coupling of an insane degree between the two classes. The next step is converting the handmade pipeline to a playbin2 based one. Earlier today, I was successful in hacking together a prototype that handles simple file/URL MediaSources. Here’s some off-the-cuff metrics to demonstrate how significant of an improvement this really is:
$ wc -l pipeline.cpp mediaobject.cpp 224 pipeline.cpp 1952 mediaobject.cpp
For reference, no pipeline code has been removed from the MediaObject. The Pipeline object currently handles the total life cycle of the gstreamer pipeline, including codec detection, creating the appropriate transport source, plugin installation, and feeding data to VideoWidgets and AudioOutputs.

I did not understand every detail
but it is great to hear, that work is going on for gapless playback in amarok. I never thought that it would be so complicated.
Just for interest: What does amarok do for playing a playlist? Does it offer the whole playlist to phonon in one go or just one file after another with the right timing?
Thanks,
Arno
I listen to MP3 music streams at low volume settings, and really require the equalizer. At much louder levels a flat response is fine, but at the very quiet volume I find I really like having the equalizer available. Hence I still use the xine backend. And will continue to do so until an equalizer is available in some other non-xine backend.
Will not utilize Pulseaudio. While playing music, whenever there is a system event sound it creates a large ‘spitch’ before the system event plays the sound.
In either situation I am happier with non-regressive behaviors. Until such a time the development of these projects reaches a point where they are superior to what they replace, I will continue to use what works best.
This is from a strictly end-user perspective. I salute all the work that is going on in the world to make these softwares better. Great Thank-You to all!
-Mike
phonon-gstreamer has an equalizer in the latest version.
Concerning pulseaudio, you should file a bug with your distribution’s packager. Just about everyone has been using Pulseaudio for the last few years without any problem.
Is this amarok-only? I think no, but “Gapless playback in Amarok” makes me worried…?
Nope, thats just marketing
Gapless playback will work in anything that uses Phonon.
I want to thank you for making equalizer work in Amarok with GStreamer. It will be wonderful when you complete gapless playback work, too.
Very interesting, I would have learned something today
This will surely end in XtremeMP for sure !
But well.. if the current phonon-gstreamer pipeline is hand-made, what was preventing you from adding some “equalizer-10bands” element in it ? Equalizer support in phonon-gstreamer is expected for ages now…
Plus, don’t you think that switching to playbin2 will make your work harder when it comes to customize your pipeline ? I mean, if you want to add a processing Element in it, for instance to adjust image hue in a video, you then will have to deconstruct you pipeline, add the processing Element at the right place and refire it, no ?
Anyway, happy to see that phonon-gst isn’t dead ^^
Nope. This will actually make it easier. The current code that uses playbin2 affects only the mediaobject. It still creates a raw audio and a raw video stream that we then pipe into other filters (or effects) before piping it into the AudioOutput or VideoWidget.
The lengths we go to – to listen to Dark Side of the Moon w/o gaps. Great
Hi,
That is brilliant news
Would someone be so kind and explain to me if this is also applicable to crossfading … or is this another nut to crack?
Nope, crossfading is another problem to solve. It likely involves creating two of these playbin2 elements and combining them into an audio mixer element prior to handing the data off to the rest of the pipeline. I have a neat way to do it in my head, but it involves some trickery inside phonon. Idealy, I’d actually end up writing a crossfade element for GStreamer itself. Thats one thing that GStreamer is seriously lacking. That would surely solve a lot of the trickery, leaving only controlling the crossfading up to Phonon as opposed to controlling the audio mixing itself.
There is a way to do it with gnonlin told me a gstreamer dev. Anyway, tricky is the word
For now, every gstreamer-based player I looked into crossfades with two pipelines.
There was an attempt : http://support.kangaroot.net/gstreamer/ but was never pushed upstream. Wish you more success
Cheers for the answer. It doesn’t appear that anyone is dealing with crossfading at the moment. If you are up to task Trever then I am sure that you could even collect some money for it. I know that many people miss both features (crossfading and gapless) and some of us would definitely pay for this feature to show up in our beloved Amarok (I would help with a code but am 100% rubbish at coding. Can only scrap some basic Python and even more basic Java code :S )
Thanks a lot for your time Trever. Good luck
I’m sure you know since you’ve probably looked at it, but for others, doing cross-fading correctly is a lot more tricky than it sounds.
You need to start the transition before the end of the song, but also optionally cross-fade on manual changes (pressing Next, changing songs, etc). Running a visualiser off it doesn’t get more complicated if it’s just driven off the audio, but can get a bit funky if you want to do things like write the song title on screen or use video if it’s something like a music-video file.
(from a former Rhythmbox dev who saw someone else implement out crossfading backend)
Yup, transitioning before the end of the song is the real difficulty.
The crossfading element I want to implement would essentially take only two inputs and a double that represents which input has priority. For instance, a value of ’0′ would mean the first input is full volume and the second isn’t even mixed. A ’1′ would imply the opposite, while ’0.5′ means both inputs can be heard equally.
To make it easier to implement, I’d have an additional gint64 property called ‘duration’ that automatically handles the crossfading once the pipeline’s duration has that quantity of time units left. Using the element would then be as simple as setting a primary input stream and attaching another element to the ‘next-input’ property. Once the ‘finished’ signal is recieved, you know its time to set the ‘next-input’ property again.
Pingback: Phonon GStreamer at Randa | wm161.net
Hi, I was using your code with video files, .avi exactly but it doesn’t work, I appreciate any suggestion. Thanks
Rossana
Erm, what are you trying do do?
HI, thanks for your concern. I tryed your gapless example, I just run it.
I call my project playbin2, so I do from the console:
./playbin2 file:///home/rossana/lista.txt
where lista.txt has the following content:
“file:///home/rossana/video1.avi”
“file:///home/rossana/video2.avi”
The name with or without ” ” don’t make difference.
- When I try with quotes, this is the error message:
ERROR from element decodebin20: It’s seem to be a text file
Debugging info: gstdecodebin2.c(2062): type_found (): /GstPlayBin2:playbin20/GstURIDecodeBin:uridecodebin0/GstDecodeBin2:decodebin20:
decodebin2 cannot decode plain text files
ERROR from element decodebin20: A GStreamer complement is missing for this installation.
Debugging info: gstdecodebin2.c(3233): gstdecodebin_expose (): /GstPlayBin2:playbin20/GstURIDecodeBin:uridecodebin0/GstDecodeBin2:decodebin20:
no suitable plugins found
Thanks for your help.
Rossana
Sorry the second example correspond to the list names without quotes,
Regards.
Rossana