GStreamer, appsink and CRC32 |
2009-01-07
|
Slowly flexing my GStreamer muscles again in preparation for a real application.
Yesterday I wanted something that allowed me to calculate CRC's of decoded audio files, to be able to calculate the CRC of a ripped file.
There's a few ways to do this using GStreamer, none of them code-free.
I assume the 'correct' way would be to write a filter element that calculates the CRC as buffers come in. In the olden days this would involve a lot of boiler plate code in C, and a small processing function.
Today, in C, this would be easier, since you could probably simply subclass basetransform.
You could write either in Python as well these days.
Then there's the 'get data out of GStreamer' approach. This used to be done using identity and the handoff signal.
The new, approved, API-stable way is to do this using appsink, one of two elements (with a helper library, of which I don't yet see the point) recently moved to gst-plugins-base.
Using appsink is probably the approach that involves the least code to write. You can set up a pipeline, set it to PLAYING, and just pull buffers in a blocking fashion (which is easier code to write, but harder to slap a GUI on later)
Here's the example code. You might note that there is an ugly try/except which I suspect is some bad handling inside gst-python or pygtk for errors during signal handling/emission.
It is a deceptively simple way to get data out of a pipeline and processed, and I'm glad we have a guaranteed way of doing this sort of operation now for the many people who want to dip their toes into GStreamer instead of diving in. I do hope they will at least consider the full dive still though.
Side note 1: GStreamer heads are free to share their opinion on what *should* be the correct way for data analysis operations like this. Years of brainwashing still lead me to believe that the answer would be 'write a filter element'.
Side note 2: I've been toying with the idea of making a python class for 'asynchronous operations' that would wrap a GObject main loop doing the processing, and implementations can then subclass and implement some simple methods. This would make it easy to attach that operation to a GUI element (for example, a progress bar) automatically, or adapt it into a linear, blocking operation for command line applications. I can't imagine this would be a novel idea, I'm sure someone else has done this already, anyone know what I'm talking about or have any suggestions ?