SoC Midterm Evaluations

July 28, 2013 - 6 minute read -
gsoc

TARGET: Create a Python API for gst-switch

Gst-switch is a replacement of DVswitch. Gst-switch has a huge advantage that it is capable of using gstreamer elements and pipelines. A Python API is needed not only to control the gst-switch, but to also allow extensive testing of gst-switch components.

A (Quick) Recap

The GSoC started from 28th May and the coding period officially started on 17th June. The intermediate time was "Community Bonding Period". It was an excellent time to think over the things to do ahead, along with trying them out a bit, and understanding difficulties.

The Community Bonding period also served as a great time to read up existing code and figure how things work out. I mainly concentrated on reading the files: gstswitchserver.c, gstswitchcontroller.c, gstswitchclient.c and test_switch_server.c.

Installing

The first task was to explore gst-switch and also learn how to get it working. Gst-switch uses gstreamer-1.0. In the start, I installed gstreamer-1.0 from ubuntu's repository (which is wrong). Then I did something like this:

Here, I my mistake was that I did not include any arguments to the ./autogen

Initially, I was not aware of this. By executing the above lines, some executables - gst-switch-srv, gst-switch-ui were created in the gst-switch/tools/ directory. Since building gst-switch was done, I could learn how to play around with it. I figured how the gst-switch-ui causes changes in the output. The only page of documentation of gst-switch is perhaps the Readme file :)

The above things worked fine for the master branch. I tried to build the speakertrack branch of gst-switch by doing:

This time running the executables made me realize that I was on the wrong path.

I realized that the the speakertrack branch needs a custom version of gstreamer's gst-plugins-bad. This is hosted at https://github.com/duzy/gst-plugins-bad.git

.

I followed installation instructions which I have posted at http://hyades.github.io/blog/Speakertrack-working. I use gstreamer's uninstalled script for this.

The components of gst-switch

Gst-switch works something like this:

  • First the gst-switch-srv is run and input sources are added to it
  • Then the UI/output is connected.
  • The communication between the server and the UI/output occurs over DBus.

DBus is a system of inter-process communication. DBus has two components: the dbus daemon and dbus library. The dbus daemon runs an actual bus over which messages can be transported. Any number of processes can connect to the daemon using the library. Mutiple buses can be active at the same time on any system. In a GNOME environment, two buses - System Bus: for miscellaneous system-wide communication and Session Bus: used by a single user's ongoing GNOME session. A bus has some properties. A very nice analogy is given here.

Gst-switch uses a custom dbus for communication. The address of this bus is unix:abstract=gstswitch.

Interacting through DBus is one of the most important and challenging part of making API. My first step towards learning dbus was through command-line tools namely dbus-monitor and dbus-send. dbus-monitor is used to view all messages over a specified bus. dbus-call can be used to send a message over dbus. These tools work great while interacting with session bus and system bus. However on a custom message bus, these methods require an object at path /org/freedesktop/DBus. It gives an error:

These dbus modules also have a higher level Python API. But this also results in same problem. I have mentioned these here.

Along with doing all these I also started writing code for creating gst-switch processes. Initially this code could simply run the gst-switch-srv and gst-switch-ui and then later kill them off.

Another command line tool is

gdbus

. This also interacts with dbus, but does so at a lower level. Using this tool one can do the same things as dbus-monitor and dbus-call. Every message bus should have a introspect interface. The introspect is an XML containing interfaces and property values for the remote object. Gst-switch's introspection is available at introspect.txt.

Since it has low level interactions, most of the usage and documentation for this is available in C here. Similar thing for python is also available. It can be accessed using from gi.repository import Gio. The only problem here was the lack of any proper documentation or examples. The only page regarding this is http://developer.ubuntu.com/api/ubuntu-12.10/python/Gio-2.0.html. The Python API for Gio is merly a wrapper over the C code. Thus almost all functions perform the same task. For example

becomes:

Help also came from reading the D-Feet source code. D-Feet is a GUI based DBus debugger written in python. The file bus_watch.py was very uselful to me in understanding how to interact using the python bindings of Gio.

This served as a base for writing modules which provide access to remote methods for the gst-switch. Currently I have two files: connection.py and controller.py which have almost the same function names defined inside them. The difference here is that the functions mentioned in connection.py interact at the low-level. They ensure things like making a dbus connection and how to call a remote method. I would also like to add information about GVariants here. There is very very less information on this available in python. In python GVariants are used like this:

Note that each remote object call also returns a GVariant which can be parsed using __str__ method of GVariant. Thus one can simply do str(variant) to obtain a tuple containing the desired information. The format of this information can be obtained from the introspection of the method.

Exception Handling & Unittests

This is perhaps the part which I personally don't like. It is boring but is hugely important. I was completely new to the concept of exception handling in python before this. In beginning I was putting bare exception statements everywhere. Now, I am catching the possible exceptions and raising appropriate messages. I have covered most of the exceptions, but one or two are still left, and I am still thinking what to do with them.

Unittests and Integration Tests

Unittests are tests which check the functionality of a small portion or code. For example, if a particular code does some calculation and finally returns a value, an exception might occur while doing the computation. Thus we need to check if the exception is raised properly. For this a unit test is run where only this particular part of the code is executed. Any external methods are generally mocked. This can be done in two ways - use pymock or create your own mocking objects and functions. Some functions which require external libraries can be mocked using monkeypatch. For running unittests I am using py.test. ANother important point about unittests is that it should always have 100% coverage. Coverage is the percentage of statements executed in the code.

Integration Tests are tests which check if modules of the software work well together as a group. This may not have 100% coverage. However one must aim to get a higher percentage.

I have also added a Makefile for generating pylint, py.test and coverage reports. The commands are make lint and make coverage.

Pylint report can be viewed at http://hyades.github.io/gst-switch/reports/pylint/pylint_global.html. The pylint_global term in the url can be replaced by filename from https://github.com/hyades/gst-switch/tree/gh-pages/reports/pylint.

The coverage part can be viewed at http://hyades.github.io/gst-switch/reports/coverage/. The testsource file requires some work here.

Currently, a partial integration test is test.py. This is not exactly an integration test, but it demonstrates how the API works.

Comments Section

Feel free to comment on the post but keep it clean and on topic.

blog comments powered by Disqus