Last Updated: February 25, 2016
·
15.58K
· christurnbull

Low Latency Desktop Stream to Raspberry Pi using Hardware Decoding

Unimpressed by how slow the raspberry pi is at HTML5 I set about trying to harness the CPU of another PC (workstation or VPS) to handle the browser processing and then to stream the desktop to the Pi using H264 hardware decoding.

Inspired by this hardware accelerated citrix receiver I started a proof of concept experiment to see if it would be feasible to utilise GPU hardware decoding to improve performance of remote control apps such as X2GO, NX, VNC, RDesktop, etc

The result after much tinkering is quite impressive. Running a youtube video on the PC and viewing it streamed over LAN to Pi was smooth and low latency (< 250ms) and used about 30% CPU.
It's not remote control of the PC, it's only a one way stream but I reckon there's definite potential in getting one of the current apps (nicely collated here) to utilise hardware decoding for a better thin client Pi.

The drawbacks...

  • I couldn't stream desktop much larger than 1024x768. Not sure why.
  • Pi has to use gstreamer1.0 to hardware decode (ffmpeg doesn't have a plugin for Pi openmax GPU)

Here's how I did it

Make sure Pi is up to date and use latest Raspian OS image.
Install precompiled gstreamer1.0 using these instructions

Set the pi to listen for incoming stream of the desktop:

gst-launch-1.0 -v udpsrc port=5000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" ! rtph264depay ! h264parse ! omxh264dec ! videoconvert ! autovideosink sync=false

This uses openmax decoder to play H264 encoded video sent using real-time protocol over UDP.
In theory you can alternatively use TS instead of RTP but I couldn't get TS to work.
I did get an MJPEG stream working over HTTP using omxmjpegdec but the CPU was up around 50% and the image didn't scale as well as H264.

Now use ffmpeg to stream the desktop from the PC:

ffmpeg -f x11grab -show_region 1 -s 1024x768 -r 25 -i :0.0+10,10 -vcodec libx264 -preset ultrafast -tune zerolatency -f rtp rtp://192.168.0.11:5000

This uses x11grab (linux only afraid, sorry Mac/Windows fans) to capture 1024x768 portion of the desktop (10 pixels in from corner), software encode it with h264, mux it into RTP and send it using UDP to pi.
The preset and tune options make it low latency.

I also got this working using VLC but it was very laggy.
I tried and failed to make it work using gstreamer ximagesrc

Tips:

  • If ssh'd to pi first run 'export DISPLAY=:0' before running gstreamer
  • gstreamer can take a seemingly endless and confusing list options. This matrix makes it a lot easier to understand compatible streaming options.
  • Use gst-inspect-1.0 to see what other plugins are installed.
  • Remember to change the ip address to that of your pi