Elemets: basics
From PiTiViWiKi
The purpose of this tutorial is to give you a basic working PyGst plugin, and explain what each part does succinctly. This is a jumpstart, not a replacement for the GStreamer Plugin Tutorial.
I will try to walk you through creating a new element that acts as a filter (has both a sink and source, this one wont actually do any filtering :)), which recieves a buffer and pushes it forward. As such it should help you avoid the pain.
- source
explanations
- We will only be talking about the code in NewElement, the rest can be found in the source.
- still needs a lot of work.
The image below shows the most important parts of a filter element, the sink a gst.Pad, the elements chain function and the source a gst.Pad.
The image below shows how data flows through elements, and what type each element is.
All new elements are derived from gst.Element or a class derived from gst.Element, gst.PushSrc is such an example. There are several basic steps common to all plugins which include registering the element with gstreamer, and initalising the plugin like you would anyother object. When initialising a derivied gst.Element you must do several things, create the gst.Pads which describe media streams (buffers) the element can recieve and send, and make the pads by calling the gst.Element.add_pad(gst.Pad) method. You must also overide the functions specific to what you are trying to do, we are creating a filter (an element which both recieves and sends buffers) in this case we must at minimum override the gst.Pad.set_caps function which is used to negotiate which type of buffers can be recieved and the gst.Pad.chain function which handles incoming buffers.
NewElement is derived from gst.Element
class NewElement(gst.Element):
""" A basic, buffer forwarding gstreamer element """
Every new class derived from gst.Element (or another class derived from gst.Element) must register it's self
#here we register our plugin details
__gstdetails__ = (
"NewElement plugin",
"newelement.py",
"gst.Element, that passes a buffer from source to sink (a filter)",
"Stephen Griffiths <scgmk5@gmail.com>")
#source pad (template): we send buffers forward through here
_srctemplate = gst.PadTemplate ('src',
gst.PAD_SRC,
gst.PAD_ALWAYS,
gst.caps_new_any())
#sink pad (template): we recieve buffers from our sink pad
_sinktemplate = gst.PadTemplate ('sink',
gst.PAD_SINK,
gst.PAD_ALWAYS,
gst.caps_new_any())
#register our pad templates
__gsttemplates__ = (_srctemplate, _sinktemplate)
When we initialise the class, we must create the pads required to communicate with other elements.
def __init__(self, *args, **kwargs):
#initialise parent class
gst.Element.__init__(self, *args, **kwargs)
#source pad, outgoing data
self.srcpad = gst.Pad(self._srctemplate)
#sink pad, incoming data
self.sinkpad = gst.Pad(self._sinktemplate)
self.sinkpad.set_setcaps_function(self._sink_setcaps)
self.sinkpad.set_chain_function(self._sink_chain)
#make pads available
self.add_pad(self.srcpad)
self.add_pad(self.sinkpad)
the pad setcaps function is called when we need to negotiate the capabilities of our element relative to the element we are negotiating with.
def _sink_setcaps(self, pad, caps):
#we negotiate our capabilities here, this function is called
#as autovideosink accepts anything, we just say yes we can handle the
#incoming data
return True
the pad chain function is called on sink caps (the ones recieving data), a buffer is recieved and pushed forward. Normally this is where we would make changes to a buffer.
def _sink_chain(self, pad, buf):
#this is where we do filtering
#and then push a buffer to the next element, returning a value saying
it was either successful or not.
return self.srcpad.push(buf)



