Archive for May 12th, 2010

Gstreamer to the rescue

A week ago, I sent my laptop and the Utopium test-board and samples, with Will and Andrew to the Async symposium. This was to present the chips at the demo session. I didn’t go but I was planning to control the laptop remotely from the office and just needed Andrew to connect everything up on the demo. I configured the laptop to auto-login to the special user who had all the necessary programs on the desktop. Most importantly, that user had desktop sharing turned on. In case you didn’t know, this uses VNC screen 0 on port 5900. When you connect to WiFi spots, you don’t tend to get web visible IP addresses, so I also added a “phone home” button which would ssh to my work desktop machine and forward a port to the desktop VNC port. If you have set your ssh keys correctly, it won’t ask for a password. For voice and video I set up an Ekiga account so I could call the laptop.

What I didn’t expect is for just about every outgoing port under the sun to be filtered. This was rather scary because no one could contact me as all instant messenger ports were blocked. Eventually, Andrew managed to get a word though to tell me. The most useful port to get through is ssh (port 22). If you can ssh out, you can do pretty much anything. Port forwarding has become much easier nowadays with the GUI tools. If you compare setting up some forwarding in the GUI

to the equivalent in the iptables rules

*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i eth+ -p tcp --dport 5920 -j DNAT --to-destination :5900
-A PREROUTING -i eth+ -p tcp --dport 995 -j DNAT --to-destination :22
COMMIT

you can see how easy we have it now. So nice and customisable, I translated my custom iptables rules files, for the group machines, into the GUI ones. So at this point, Andrew could ssh out by adding “-o Port=995” to the ssh line.

But this is only half the solution, as I could only get a couple ports through, with limited time (I had some 20 minutes before the demo to fix everything), there was little chance of getting Ekiga working. Instead I quickly created a poor person’s internet telephony solution using Gstreamer. First you need to establish an ssh connection forwarding one port in each direction. I used 5000 and 5001 and it makes things simpler if you do the port swap in the ssh pipe like so:

ssh -L5000:localhost:5001 -R5000:localhost:5001 remote_machine.domain

This transfers connections to local port 5000 to the remote port 5001 (and vice-versa). So the servers should sit on port 5001 and clients should connect to port 5000. To create a server run:

gst-launch -v alsasrc ! audio/x-raw-int,rate=16000,channels=1 ! audioconvert ! speexenc ! tcpserversink host=127.0.0.1 port=5001

One server is needed at each end (assuming you wish to talk both ways). Only once the server has been created can a client connect to it using:

gst-launch -v  tcpclientsrc host=127.0.0.1 port=5000 ! speexdec ! alsasink sync=false

And there you have two way audio communication. It is possible to disconnect and reconnect to the server. Also, I noticed that when there was a complete network cut-out (happened several times) the audio would cut out, but then resynchronise and return.

You can do the same with video by swap forwarding ports 5002 and 5003 and running the server:

gst-launch -v v4l2src ! video/x-raw-yuv,framerate=\(fraction\)5/1 ! smokeenc threshold=1000 ! tcpserversink host=127.0.0.1 port=5003

and the client:

gst-launch -v tcpclientsrc host=127.0.0.1 port=5002 ! smokedec ! xvimagesink sync=false

This uses “smoke”, which is like motion JPEG but detects where there were no changes between frames.

So with that in place, the demo went quite smoothly with some people happily asking questions to the laptop and others being a bit surprised at voices coming from nowhere.

So, thank you Gstreamer! You saved my demo.