8

I'm writing an application that uses the Python Gstreamer bindings to play audio, but I'm now trying to also just decode audio -- that is, I'd like to read data using a decodebin and receive a raw PCM buffer. Specifically, I want to read chunks of the file incrementally rather than reading the whole file into memory.

Some specific questions: How can I accomplish this with Gstreamer? With pygst specifically? Is there a particular "sink" element I need to use to read data from the stream? Is there a preferred way to read data from a pygst Buffer object? How do I go about controlling the rate at which I consume data (rather than just entering a "main loop")?

adrian
  • 1,447
  • 15
  • 24
  • More future reference: this is the solution I came up with (with elmarco's help), which might be useful in other projects as well. http://github.com/sampsyo/pylastfp/blob/master/lastfp/gstdec.py – adrian Aug 28 '10 at 22:24

1 Answers1

5

To get the data back in your application, the recommended way is appsink.

Based on a simple audio player like this one (and replace the oggdemux/vorbisdec by decodebin & capsfilter with caps = "audio/x-raw-int"), change autoaudiosink to appsink, and connect "new-buffer" signal to a python function + set "emit-signals" to True. The function will receive decoded chunks of PCM/int data. The rate of the decoding will depend on the rate at which you can decode and consume. Since the new-buffer signal is in the Gstreamer thread context, you could just sleep/wait in that function to control or slow down the decoding speed.

elmarco
  • 31,633
  • 21
  • 64
  • 68
  • Thank you! I didn't know about appsink. This helps a lot! – adrian Aug 20 '10 at 05:10
  • 2
    One additional note (for future reference) after trying this: it seems that you need to set the "sync" property of the appsink to false in order to get data as quickly as possible. Otherwise, you'll consume data in real time. – adrian Aug 28 '10 at 22:19
  • 2
    One detail: the Python bindings for appsink don't bind gst_appsink_pull_buffer() method; instead you need to call appsink.emit('pull-buffer'). – daf Jul 29 '11 at 19:02