Python GStreamer

Sample code

Jono Bacon posted an intro to programming with python gstreamer and glade:

Alessandro Decina (twism) posted some sample code for a simple video player in python gstreamer to xvimagesink:

Mike Smith posted some minimal code for a playbin based player:

Documentation

Some docs are at:

General documentation for the GStreamer C API is available in devhelp. On Debian based systems:

apt-get install devhelp libgtk2.0-doc libglib2.0-doc libpango1.0-doc libgstreamer0.10-doc gstreamer0.10-plugins-base-doc

Video Playback

Getting ready to play a video

Set up the pipeline, set it to READY and preroll

When you want to play, set it to PLAY

To put text on a video, use textoverlay

Prerolling

Prerolling is what the elements/pipeline do when they set up for PAUSED or PLAYING. if an element is at READY and you ask it to go to PAUSED, then it will set itself up to go to paused (decode keyframes etc) and send an asynchronous message when it is at paused.

Hence, you can wait for all the async messages to come in.

Alternatively, you can call gst_element_get_state() with an infinite timeout GST_CLOCK_TIME_NONE

Switching between video streams

To switch between video streams, it may be necessary to set up a pipeline for each video. However, you only want one output video sink. In order to set a pipeline to READY or PAUSED without having a video sink connected, you need to block the output pads, then preroll the video (tho paused will incur actual decode CPU etc. so you might not want to do that to set up lots of videos).

pad blocking: devhelp://GStreamer Core/GstPad :: gst_pad_set_blocked

Then, to switch video, connect to the videosink and set to PLAY.

Switching to images

You don't need to preroll images; data doesn't flow until you set it going. You can't play the image, but you can simply set its pipeline to PAUSED to force the image to be displayed.

To put text on an image, use textrender

Hooking an xvimagesink into a given x window (eg. a fullscreen window)

0. create a fullscreen window

1. Get its xid

To get the drawable for a widget: widget->window

To get the xid for a drawable:

devhelp://GDK/API/gdk_x11_drawable_get_xid()

widget.window.xid

http://www.daa.com.au/pipermail/pygtk/2005-March/009720.html

2. xvimagesink implements the interface for XOverlay

devhelp://GStreamer Base/Interfaces/gstxoverlay

xvimagesink uses synchronous events. The sample code in devhelp shows how to set up a sync handler such that on receipt of the "prepare-xwindow-id" message, you can connect the xvimagesink to the xid.

ie. create the pipeline containing an xvimagesink, then wait for it to send a prepare-xwindow-id message (once you've started mainloop) and hook it up to the xid you prepared earlier.

gst_x_overlay_set_xwindow_id()

Buffers ; text buffers

Buffers contain data, start time and duration.

For textoverlay, the input buffer can be plaintext or pangotext (pangotext allows some simple markup like bold, italic and colors).

Textoverlay has properties for the type of input, and for the x,y placement and padding.

Static text can be set as a property instead of being read in from a buffer.

Twism suggests to "place a queue element infront of the textoverlay before pushing data to it." His example code "pushes data into the pipeline from the main thread. The sink could block the main thread waiting for buf.timestamp. If the main thread is blocked, all the events dispatched by the GMainLoop would be delayed.

"If you insert a queue element (gst.element_factory_make ("queue")) that will create a new thread and the main thread and the queue thread will work like a producer-consumer so the main thread returns in the main loop as soon as the buffer enters the queue."

Caveat: gst_clock_id_*() are not wrapped, and they're what is needed to synchronze to the clock. GstClockID is not a GObject, so it needs to be GBoxed in order to wrap it.

Wrapping GStreamer in Python: Codegen

Codegen is the Python parser used to wrap Gtk/GObject/GStreamer/anything using GObjects. It reduces the amount of boring code you have to write, and makes it more fun by using a Lisp-like syntax.

http://www.smh.com.au/ffximage/2006/09/08/python_wideweb__470x325,2.jpg

Codegen is shipped with gst-python, in gst-python/gst/ you have a bunch of *.defs and *.override files. For structs that are GObjects, you need to add a definition in a def file. For structs that are not GObjects (such as GstClockID), you additionally need to write the boxed_copy and boxed_free functions ... and then submit a patch. In order to do all this, only gst-python needs to be run from cvs.

Credits

Thanks to Jan Schmidt (thaytan) and Alessandro Decina (twism) for the explanations. Thanks to Jono and Mike for the tutorials and useful code.