how to receive RTP stream with python-gst-1.0

A year ago, I explained how to send Raspberry Pi camera stream over network to feed Gem through V4L2loopback device.
Today I wrote a small Python script to receive the same stream (to use it with pupil-labs).
It uses Python 3 (but should work with 2.7 too) and python-gst-1.0.

Here is the script :


#!/usr/bin/python3

# this example shows how to receive, decode and display a RTP h264 stream
# I'm using it to receive stream from Raspberry Pi
# This is the pipeline :
# gst-launch-1.0 -e -vvvv udpsrc port=5000 ! application/x-rtp, payload=96 ! rtpjitterbuffer ! rtph264depay ! avdec_h264 ! fpsdisplaysink sync=false text-overlay=false

import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, Gtk

# Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
from gi.repository import GdkX11, GstVideo

GObject.threads_init()
Gst.init(None)

class RTPStream:
def __init__(self):
self.window = Gtk.Window()
self.window.connect('destroy', self.quit)
self.window.set_default_size(800, 450)

self.drawingarea = Gtk.DrawingArea()
self.window.add(self.drawingarea)

# Create GStreamer pipeline
self.pipeline = Gst.Pipeline()

# Create bus to get events from GStreamer pipeline
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message::error', self.on_error)

# This is needed to make the video output in our DrawingArea:
self.bus.enable_sync_message_emission()
self.bus.connect('sync-message::element', self.on_sync_message)

# Create GStreamer elements
self.udpsrc = Gst.ElementFactory.make('udpsrc', None)
self.udpsrc.set_property('port', 5000)
self.buffer = Gst.ElementFactory.make('rtpjitterbuffer',None)
self.depay = Gst.ElementFactory.make('rtph264depay', None)
self.decoder = Gst.ElementFactory.make('avdec_h264', None)
self.sink = Gst.ElementFactory.make('autovideosink', None)

# Add elements to the pipeline
self.pipeline.add(self.udpsrc)
self.pipeline.add(self.buffer)
self.pipeline.add(self.depay)
self.pipeline.add(self.decoder)
self.pipeline.add(self.sink)

self.udpsrc.link_filtered(self.depay, Gst.caps_from_string("application/x-rtp, payload=96"))
self.depay.link(self.decoder)
self.decoder.link(self.sink)

def run(self):
self.window.show_all()
# You need to get the XID after window.show_all(). You shouldn't get it
# in the on_sync_message() handler because threading issues will cause
# segfaults there.
self.xid = self.drawingarea.get_property('window').get_xid()
self.pipeline.set_state(Gst.State.PLAYING)
Gtk.main()

def quit(self, window):
self.pipeline.set_state(Gst.State.NULL)
Gtk.main_quit()

def on_sync_message(self, bus, msg):
if msg.get_structure().get_name() == 'prepare-window-handle':
print('prepare-window-handle')
msg.src.set_property('force-aspect-ratio', True)
msg.src.set_window_handle(self.xid)

def on_error(self, bus, msg):
print('on_error():', msg.parse_error())

rtpstream = RTPStream()
rtpstream.run()