5GHz Wifi On the Raspberry Pi 2


After much searching I found a way to get 5MHz Wifi Dongles working on the Raspberry Pi 2 without having to compile a new kernel.  I can’t claim any credit here;  that belongs to MrEngman on the RaspberryPi.org forums who has done all the compiling and has made the kernel modules available to download.

One thing I did discover is that the high gain 5GHz wifi dongles draw more power that the Raspberry Pi 2 would like to deliver.  To fix this I have made a special USB cable with a dedicated 5V power supply for the dongle.


I have two 5 GHz Wifi dongles: an Edimax AC600 EW-7811USC Dual Band and an Alfa Network AWUS036AC Long-Range Dual-Band AC1200.

Edimax AC600

Edimax AC600

Alfa AC1200

Alfa Network AWUS036AC Long-Range Dual-Band AC1200

I could get the Edimax AC600 to work, but not the Alfa AC1200 even though they have the same chipset.  When I tried running the Pi2 on batteries through a BEC I found that the AC600 would not always come up either.  As the dongle was getting quite hot in use I summised that it was trying to draw more current than the Pi was able to supply.

To test this out I took a USB extension lead and chopped some cable out of the middle to make it shorter.  At the same time I added a dedicated 5V power supply for WiFi dongle, fed from the BEC.  The joins were insulated with heat shrink tube and insulation tape.


USB Power Booster Cable

USB Power Booster Cable

With this in place I was now able to use both the Edimax AC600 and the Also AC1200.

Power Booster Setup

Power Booster Setup


The full post on how to install the Realtek RTL8812AU driver module is available on the raspberrypi.org forums.  I’ll expand on the details given there based on my experience.

  1. The first task is to establish the current kernel version on your Pi.  This is done with the command:
    uname -vr
  2. This command shows the details you need.  For instance a fresh install of the 2015-05-05 Raspbian build gives.
    3.18.11-v7+ #781 PREEMPT Tue Apr 21 18:07:59 BST 2015
  3. The information we want is the version number at the start, up to, but not including the plus sign (+) and the build number after the hash (#).  In this case 3.18.11-v7 and 781.
  4. These values are inserted into a url to get the modules relevant to your kernel.
  5. Replace {kernel version} and {build} with your values.  In my case the url becomes:
  6. Use this url with wget to download the compressed kernel module.
    wget https://dl.dropboxusercontent.com/u/80256631/8812au-3.18.11-v7-781.tar.gz
  7. If you get an error here, it probably means that there isn’t a pre-compiled modules for your kernel version. All is not lost however.  You can try upgrading your kernel to a version that is supported.
  8. Type the command:
    sudo rpi-update
  9. This can take a while, so go have a drink and periodically check-in to see if its finished.  When done, you will need to reboot your Pi.
  10. Now run ‘uname -vr’ again to get the new version and build numbers
    3.18.12-v7+ #782 SMP PREEMPT Tue Apr 28 19:54:13 BST 2015
  11. Try downloading a module with the new kernel version and build number.  Remember up to but not including the +. In my case:
    wget https://dl.dropboxusercontent.com/u/80256631/8812au-3.18.12-v7-782.tar.gz
  12. This worked for me leaving the file 8812au-3.18.9-v7-768.tar.gz in my home directory.  We extract the files from this with the command:
     tar zxvf 8812au-3.18.12-v7-782.tar.gz
  13. This creates some files in the current directory, one of which is ‘install.sh’.  Run this script with

    you don’t need a sudo at the start.

  14. Reboot your Pi.  If you already have the Realtek specific version of hostapd installed the 5GHz dongle will probably work straight away, although possibly on the 2.4Ghz band if your system was previously configured to do so.
  15. The 5GHz band is more regulated than 2.4GHz, so we need to install the Central Regulatory Domain Agent (CRDA) package that controls which frequencies and features are available to your country.  Hostapd does not work with the world domain (00).  You have to be specific.  If not already installed, get the necessary package with:
    sudo apt-get install iw crda
  16. Then to set the CRDA region edit the file /etc/default/crda
    sudo vi /etc/default/crda
  17. Append your domain to the line “REGDOMAIN=”, which in my case is GB
  18. Edit your /etc/hostapd/hostapd.conf to use the 5GHz band
    sudo vi  /etc/hostapd/hostapd.conf
  19. This is my configuration.
  20. Finally reboot again and hopefully you will have a 5GHz Wifi access point.  I use WiFi Analyzer on my android phone to check.


At home with the transmitter and receiver in close proximity, there were no issues, the latency being comparable to the 2.4 GHz WiFi.

Buoyed up by this result, the next step was to get outside and test the range.

I took my test rig to my club flying field one lunchtime.  With the Edimax AC600 connected directly to the Raspberry Pi, the maximum distance I could get before the picture froze was 28 metres.  This was in a level rural location, so the chance of interference was minimal.

For the second test I used the Alfa Network AWUS036AC (AC1200).  I had to use the power booster cable, as this Adapter requires too much power for the Pi to supply directly.   With the Alfa AC1200 I managed 100m before the video started stuttering; still not enough for a useable FPV system.  If the line of sight was blocked by a building or tree the video would freeze completely.


If these results are to be believed, then the future of this project looks bleak.  However, the WiFi adapter manufacturers claim that these devices should perform better for range and speed than the previous generation.  I need to check the performance of the WiFi adapter in the Laptop.  It is about three years old now and probably can’t cope with the latest WiFi protocols.  Perhaps the next stage is to obtain an extra AC600 and/or AC1200 and run the test again.

I’m also going to try measuring the current draw of these devices to see if the power consumption tallies with the 100mW permitted radiated power they are allowed.

Another possibility is to change the CRDA domain.  There are examples of people reporting that using BO allows for increased transmission power.  Obviously, do this may be breaking some rules in your country, unless you live in Bolivia.




FPiV Easy Setup.


Having ran through the installation procedure a number of times, I decided to write a script to automate it as much as possible.  The result was a script that covered about 95% of the installation and took about two minutes to run on a recent built of Raspbian (2015-05-05).  As more updates to Raspbian accumulate the run time can increase to 10 or 15 minutes.  The script is light on error checking, so is best run on a newly flashed image.

The full step by step procedure that this script automates can be found on the Configuring a System page.  For this example I will demonstrate a way to do the initial configuration without plugging the Pi into a monitor and keyboard.

Setting Up the Pi

Download the necessary files

  1. Download and install Win32 Disk Imager on your PC from Sourceforge:
  2. Download and unzip the latest Raspbian Image from RaspberryPi.org :
  3. Download and install the putty ssh client:
  4. Download and install the angry IP scanner:
  1. Insert your SD card into your computers card slot or use a USB card reader. Take a note of the drive letter allocated to the card (E.g. E:).
  2. Launch Win32DiskImager and make sure the selected Device matches the SD card location ( [E:\] ). Having the wrong letter here will corrupt that drive.
  3. Click the small blue folder icon and select the expanded Raspbian image.
  4. With everything set click the Write button. You will get a last chance warning about overwriting the drive. Click ‘Yes’ if you are happy to continue.
  5. Once the image has been written, a small ‘Done’ message box will pop-up. Click the button and then Exit Win32DiskImager.
  6. Eject/Safely remove the SD card from your computer and insert into your Pi.

Raspbian Configuration and Update.

  1. Connect the camera to the Pi.
  2. Connect the Pi to your LAN with an ethernet cable.
  3. Power it on.
  4. Run Angry IP Scanner and set the start and finish IP addresses to match your network.  Also, in the Tools menu, select “Fetchers…” and add MAC Vendor to the selected fetchers.  Click the OK button.
  5. Click the start button to scan your network.  When the results come up, look down the MAC Vendor column for “Raspberr” and then look to the first column to establish the matching IP address.  Don’t rely on the hostname column.  Depending on your network setup this may show the name of a device that was previously allocated the IP address by DHCP.
  6. Launch putty and enter the IP address. I like to save the address as a session as I go along to save having to type the full IP address every time. When you are ready to proceed, click ‘Open’ to launch a command window.
  7. At the prompt login as pi
  8. The password is raspberry
  9. The first time you login you will be dropped straight into raspi-config.
  10. Hit ‘Enter’ on “Expand the Filesystem” to fill the SD card and the ‘Enter’ again to clear the “resize on next boot” notice.
  11. Use the down arrow key to select “Enable Camera” and hit ‘Enter’. On the next screen use the right arrow to select ‘<Enable>’, then hit ‘Enter’ again.
  12. Enter “Advanced Options” and then “Hostname”. Give your install an identifiable name.
  13. Press the Tab key a couple of times to select ‘<Finish>’ and then press enter to exit raspi-config and reboot the Pi.  This will stop your ssh session.
  14. Wait a minute for the Pi to reboot and then restart the putty session, by right clicking in the putty window header and selecting “Restart Session”
  15. Login again.


  1. Download and extract the script.  Case is important.
    wget -O - https://goo.gl/NLuFFI | tar zxvf -
  2. Change to the install directory
    cd FPiV
  3. Run the script
  4. Let it run keeping an eye out for error messages.
  5. When all is finished the Pi will be configured with hostapd set to run with 2.4 GHz WiFi using a supported Realtek adapter.  The streaming scripts are dropped into the pi home directory.
  6. Reboot the pi.
  7. If all is well, when the pi restarts it should start advertising its WiFi connection as Pi_AP.

Get Streaming

  1. Connect the laptop WiFi to the Raspberry Pi’s Wifi Access Point
  2. Open a terminal on the Laptop
  3. run the ./go script on the laptop to update the configuration files on the Pi and set the time and date.
  4. The go script will leave you in a ssh session on the Pi
  5. run the ./ustream or ./utee scripts on the Pi.
  6. Open a second terminal on the laptop.
  7. run the ./tsplay or ./uts scripts on the Laptop
  8. The video will start streaming.

A Pi Straight Flush – Comparing the Pi 2


The Pi 2 Model B was release on the 2nd February 2015 promising a 1.5 to 6 times performance boost over the earlier generation one hardware.  If that boost occurred across the entire pipeline then even a minimal 1.5 improvement would reduce the latency from 120 to 80 milliseconds (a 33% reduction) and make a very useable FPV system.  Not enough for racing, but enough for most everything else.  Anyway, a 250mm racing quad would be too small to carry a Raspberry Pi.

In reality the processor is only one small part of the video streaming pipeline and while the Pi 2 does reduce the latency, the improvement is not nearly as much as you might think.  In fact most of the improvement over previous tests has come from a change in test procedure.  The final conclusion though is that the Pi 2 does at least allow us to break the 100ms barrier.  If I can just get a 5 GHz wifi system running on the Pi 2, then the next step is to actually get it airborne.

In addition to the Pi 2, I also have a Pi 1 A+ that had not been tested.  The A+ is smaller and lighter than the previous boards which is an advantage if you’re trying to fit it in a tight fuselage.  As I was using a new build of Raspbian, I thought I would run the test on all versions of the Pi: the A, B, B+, A+ and Pi 2B; a straight flush of Pi.



Nothing new here.  I used the build of Raspbian from the previous test.  As I haven’t managed to get 5 GHz WiFi running on the Pi 2 yet, the test was done using the Edimax EW-7612UAn V2 2.4GHz USB WiFi stick as this was compatible with all versions of the Pi.  Following the previous tests where the Dual Band AC600 Wifi Adapter had similar performance to the on board ethernet port, I also tested the B and 2B over LAN.  The idea being to see what the Pi 2B could achieve with a good WiFi adapter.


These tests were a straight comparison between the five Pi devices using the same settings and the same testing methodology as previously.  The resolution was 1280 x 720 pixels with a 6Mbps bit rate.


My first impression of the Pi 2B was that it was faster than the series one models, however when I started analysing the results, I could see no improvement after seven iterations.  So I went back and calculated the latency at each step.  This revealed a general trend for the latency to increase with each step.

With the Pi sampling at 48 fps, that’s 21ms for each frame.  The screen is refreshing at 60 fps or once every 17ms.  Depending on when the image appears on the screen bright enough for the camera to detect there could be a significant increase in latency towards the end of the iteration loop.  In practice these things tend to average out and the general trend seems to be a 20ms increase between iterations 1 and 7.

I started using the multiple iteration technique right back at the start of this testing when we were looking at a latency in the 200 to 300ms range. Back then there was also a lot of variation at each step and so this increasing trend was not immediately apparent.  Now that the latency is around 100ms and more consistent it has become so.

Straight Flush Iterations

Because of this, I have changed my result reporting to only use the average of the first iterations and I always collect at least 10.  From the above graph you can see that over WiFi the Pi 2B has the lowest latency at 103.3 ms, but that’s only  2.3 ms faster than the Pi 1B.

Using the ethernet port the Pi 2B does better with an average latency of 97.2 ms whereas the Pi 1B could only manage 107.4 ms.

Straight Flush Iterations Eth

Here is a summary of the final results.

Straight Flush Latency Summary

From fastest to slowest the final results are Pi2B, Pi1B, Pi1A+, Pi1A, Pi1B+.


So where is the 1.5 to 6 times performance improvement, the 33% reduction?  The best result achieved is a 10% reduction.  The answer is that the processor represents only a part of the complete video capture and transmission pipeline and each stage involves converting the stream into different forms through multiple processors.  Remember each device (camera, bus controller, Pi, USB controller, USB hub, WiFi Adapters, PC CPU, Video Card and display) has their own processor and most are not as powerful as the Pi.  Unfortunately, there is no easy way to measure the latency at each stage to determine where the main bottlenecks are.

Video Pipeline

It must also be remembered that gstreamer is a complete pipeline in itself, with multiple conversions between the raw video and the packetized stream sent to the WiFi adapter.

It is interesting to note that the A models were faster than the Pi1B+ even though they have half its memory.  The A models only have a single USB interface.  The B models don’t have multiple USB interfaces, they have the same single USB interface and that feeds a built-in two or  four port hub.  This adds an extra stage to the transmission pipeline making the Pi1B+ slower than the A models even with twice the memory.   I assume the two port hub in the Pi1B is faster than the four port hub in the Pi1B+ which combined with the extra memory makes it faster than the A models.


If the Pi 2B can be made to work with one of the dual band WiFi adapters and achieve this sub 100ms average latency then it has promise to finally deliver a low cost and useable high definition FPV system.

At the moment Raspbian is still optimised for the arm6 architecture of the first generation hardware.  With an operating system optimised for the arm7 in the Pi 2B further latency improvements should be possible.

There are no immediate plans for a Pi 2A.  If this was released with the 512MB of memory of the current B models, a single USB interface and a small form factor, it could be the idea platform for HD FPV.

Perhaps the way to improve the latency further is to switch from a raspivid/gstreamer RTSP (Real Time Streaming Protocol) solution to some other protocol.  Perhaps MpegStreamer holds the answer.  Only more testing will tell.

Nano FPV Race Course in a Box


During the winter my local RC club has an indoor session once a month a bowls hall.  This is crown bowls, rather than 10-pin.  Small quadcopters are popular at these meetings and post Christmas, there are now three Blade Nano QX FPV quads.  Now obviously whenever you have two or more FPV quads in one place there will be a desire for racing or at least some close proximity flying.  So an idea was born for a nano size FPV course, that would fold up small for easy transportation.  Additionally, it had to be cheap, preferably using materials I already had.

While the final package is a little bigger than I had originally hoped, it was cheap, quick to erect and still easily transportable in an 1/8 scale car carry bag.


I found some 12mm pine shelf and some orange ripstop nylon.  To this I added a pair of telescopic magnetic pickups for about £2 each.  These extend from 133mm to 645mm and are rated to lift 3.5kg.  The board was cut into trapezoids to maximize its use and a 10mm hole drilled near the back edge to accept the pickup, once I had removed the pen clip.  Some velco was added to the front edge and I got a sleeve cut out and sewn up, to form a mini corner pennant.

I had though to string a ribbon between two pennants to form a gate, but by the time the ribbon was deep enough to be clearly visible through a nano FPV camera, combined with it’s droop, there was only a small gap to fly under.

I found some bigger telescopic pickups at CPC Farnell that extend from 165 to 838mm.  The original base was not thick enough for the bigger pickup as it was 16mm diameter with a domed end.  I had some 1¾” x 5/8″ (45mm x 16mm) timber which I used to extend the mounting hole, however, I felt the base was not wide enough for stability.  I had plenty of the 1¾” x 5/8″ so I cut it into two 8″ (200mm) lengths and a 1¾” (45mm) square.  These were glued and nailed together and drilled through until the point just started to show.

Three generations of base.

Three generations of base.

Size comparison.

Size comparison.

Transportation size.

Transportation size.

As you can see these pennants fold down really small.  I couldn’t find a good solution to make the new bigger pennants into a gate, but one of the solutions I did considered was to use foam board as a beam between the pickups and this gave me an idea.

I had a stock of 5mm foam board that was too heavy for making into aircraft, but which was idea for FPV gates.  It was A1 size (840 x 597mm) which produced a nice size gate.  They are a lot bigger for transportation, but still very light.  I used red and yellow parcel tape to  make them highly visible.

For a start/finish gate I printed some A3 chequered pattern sheets that I glued onto the foam board and then covered with clear packing tape.

The foam board was cut to the sizes shown below which can be adjusted to suit your available foam board and timber.  The 50% score cuts were folded back to form a hinge which was reinforced with clear tape on both sides.  Small 20mm x 80mm rectangles of foam where added to give a bigger mounting point for the cross members.  These were covered with tape and then more tape was used to fix them in place.

Bases for these gates where made from the same 1¾” x 5/8″ (45mm x 16mm) timber.  One 10″ (250mm) length and three 1¾” (45mm) blocks.  The 20mm dimension on the foam board can be adjusted to suit your timber thickness.  It can be a little bigger than your timber but not smaller.   Once it’s assembled give it a good sanding to smooth off the edges.


Foam board column base

Start/Finish Gate
IMG_20150209_224111 IMG_20150209_225814

High Gate
IMG_20150209_223326 IMG_20150209_222755 IMG_20150209_223010 IMG_20150209_223056

Low Gate
IMG_20150209_224426 IMG_20150209_225040

The Plans

TallGate HighGateFill LowGate

Analogue FPV First Flight

I set up a small quad with a contemporary FPV system.  In this case an 25mW ImmersionRC video transmitter using my GoPro 3 Black as the camera.  I had wanted to compare the latency of this system against that of the Raspberry Pi.  The problem is that I can’t use the GoPro to measure the latency of itself.  I need to see if I can borrow another one.  For now it was just nice to get out and fly.

The quad is a Quadrixette 30 from http://www.eyefly.info.  It’s quite an old design now, but I like it because it is small (300mm), but still bale to carry some weight.  The flight controller is a OpenPilot CC3D and I’m using a Spektrum AR8000 receiver with telemetry module to report the flight battery voltage.

IMG_20150223_230817 IMG_20150223_230827

One of my club mates was also at the field with his Tricopter so we had some proximity flying.

Comparison of 2.4 GHz WiFi, 5 GHz WiFi and 100 MBit LAN


Up to now I have been using an Edimax EW-7812UAn V2 USB WiFi Dongle.  This has been very reliable and reasonably simple to install and configure.  The only problem is that it operates on the 2.4 GHz frequency band, which means it will interfere with the majority of modern radio control systems.  Up to now I have been using a 35 MHz RC system which was fine as long as I was flying on my own.  However, I’d like to fly with others who will be using 2.4 GHz systems.

There are now a number of Dual Band Wifi Dongles that operate in the 5 GHz band as well as at 2.4 GHz. This provides a solution so long as they work with the Raspberry Pi.  A couple of candidates were obtained, configured and tested on my Model B Raspberry Pi.  For an extra comparison I also ran a test over the wired LAN interface.

The results were interesting in that there was no clear winner in the speed stakes, there was however a clear loser.  What is clear is that useable 5 Ghz WiFi is possible but for now it’s not plug and play.


For these tests I used the following network devices.

  1. Raspberry Pi Model B Ethernet (100 Mbit/s)
  2. Tenga W522U Dual Band (2.4 GHz & 5 GHz)
  3. Edimax EW-7612UAn V2 (2.4 GHz)
  4. Edimax AC600 Dual Band (2.4 GHz & 5 GHz)

I setup my Model B, with the latest release of Raspbian (2015-01-31) and the current scripts.

5 GHz WiFi Prerequisites

To get 5GHz WiFi working you need to install the Central Regulatory Domain Agent (crda).  Basically, the 5 GHz band is more tightly regulated worldwide and you need to specify your regulatory domain so that hostapd knows which channels are available.

To install the necessary packages use:

sudo apt-get install hostapd crda iw

Then edit /etc/default/crda and set the REGDOMAIN variable to match your region.  Examples are US, JP, EU and in my case UK.



The amount of work needed to setup networking varied by device.  I’m not going to give a detailed description of configuring each device.  I’ll do that in separate posts.

1. LAN

This simply required plugging the Pi and the Laptop into a switch and running ipconfig on the receiving device to get its IP address.  This was then used in remote.conf to direct the UDP stream.

2. Tenga W522U

The W522U is nl80211 compatible.  This means it works with a standard install of hostapd.  No special configuration is needed.

3. Edimax EW-7612UAn V2 (2.4 GHz)

The EW-7612UAn V2 uses the RTL8191SU chipset.  The kernel supports this chipset for client networking, but not for AP mode.  However, Realtek provide a custom version of hostapd that needs to be downloaded, compiled and installed which does work.

4. Edimax AC600 Dual Band (2.4 GHz & 5 GHz)

The AC600 is not supported by the latest kernel.  All is not lost, it just takes a little more work.  You need to download the kernel source code and the code for a Realtek 8812U driver.  Then you need to install the latest version of GCC from the Jessie repository.  This lets you build the kernel module.  Finally you need the same hostapd build as for the Edimax EW-7612UAn V2 device.

Hostapd Configuration

There are four combinations of hostapd.conf depending on the driver and band.  I’ve set them out in the table below.

Hostapd Version 2.4 GHz 5 GHz







These tests were a straight comparison between the four devices using the same settings and the same testing methodology as previously.  The resolution was 1280 x 720 pixels with a 6Mbps bit rate.


The table below shows the resulting latency by device.

Device Latency
Edimax EW-7612UAn V2 – 2.4 Ghz 132 ms
Tenga W522U – 2.4 GHz & 5 GHz > 10 s
Edimax AC600 – 2.4 GHz 122 ms
Edimax AC600 – 5 GHz 126 ms
LAN 124 ms

Here they are as a graph.



The big surprise is how bad the Tenga W522U adapter was.  The latency was not just two or three times higher, it was two order of magnitudes higher.  There are a number of threads on various forums where other people have found similar issues, although not to this extent, but then they are probably not swamping the feed with a continuous video stream.  Whether this is just a compatibility issue with the Pi remains to be seen.

The Edimax AC600 was 10 ms faster than the previously used Edimax 7612UAn V2 at 2.4 GHz.  At 5GHz it was still faster, but only by 6ms.  Interestingly, the LAN connection was not any faster than the AC600.  On the Pi the LAN connection is 100 MBit/s as is the USB bus, so although the AC600 is theoretically capable of 433 Mbit/s it is never going to manage more than 100.


What we can take away from this test is that there is a limit to how much the latency can be reduced by changing the WiFi adapter.  It is a shame that to get a 5 GHz WiFi link requires a lot of compiling and configuration.  Hopefully this will improve with time.  For now we have another small reduction in the video latency to add to the current optimisations.


Just as these tests were being done, the new Raspberry Pi 2 was released promising a x1.5 to x6 speed increase.  As I had used the latest release of Raspbian, I swapped the microSD card from from the Model B to the Model 2B.  What I found was that the Edimax AC600 was no longer detected and I couldn’t find a way to compile the module so that it would.  So that’s my next task.  I may run a quick comparison of the B versus the 2B with the Edimax 7612UAn V2 to see how much improvement the new processor has made.

Raspivid v Gst-rpicamsrc (Updated)


User bocorps pointed me in the direction of gst-rpicamsrc.  This is “… a GStreamer wrapper around the raspivid/raspistill functionality of the RaspberryPi, providing a GStreamer source element capturing from the Rpi camera.”

What this means is that instead of piping the output of raspivid into gstreamer, gstreamer has a source element to read the camera directly.  This is similar to using the video4linux (v4l) source element, but negates the need for a v4l driver.

My hope was that by integrating the camera functionality into a gstreamer source element the latency would be reduced.  Unfortunately, I actually saw an 18% increase in latency.


Before I could use the gst-rpicamsrc element, I needed to download the source and build it.  As I was working with a minimal install of Raspbian Jessie, I needed to install the git package before I could do anything else

sudo apt-get install git

With git installed I could download the latest sources for gst-rpicamsrc.

git clone https://github.com/thaytan/gst-rpicamsrc.git

With that done a look in the REQUIREMENTS file indicated what other packages were needed in order to accomplish the build.

sudo apt-get install autoconf automake libtool libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libraspberrypi-dev

Finally, I was able to complete the build and install.

./autogen --prefix=/usr --libdir=/usr/lib/arm-linux-gnueabihf/
sudo make install

The command `gst-inspect-1.0 rpicamsrc’ produces a list of the available parameters.

Factory Details:
  Rank                     none (0)
  Long-name                Raspberry Pi Camera Source
  Klass                    Source/Video
  Description              Raspberry Pi camera module source
  Author                   Jan Schmidt <jan@centricular.com>

Plugin Details:
  Name                     rpicamsrc
  Description              Raspberry Pi Camera Source
  Filename                 /usr/lib/arm-linux-gnueabihf/gstreamer-1.0/libgstrpicamsrc.so
  Version                  1.0.0
  License                  LGPL
  Source module            gstrpicamsrc
  Binary package           GStreamer
  Origin URL               http://gstreamer.net/


Pad Templates:
  SRC template: 'src'
    Availability: Always
                  width: [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]
              framerate: [ 0/1, 2147483647/1 ]
          stream-format: byte-stream
              alignment: au
                profile: { baseline, main, high }

Element Flags:
  no flags set

Element Implementation:
  Has change_state() function: gst_base_src_change_state

Element has no clocking capabilities.
Element has no URI handling capabilities.

  SRC: 'src'
      Has getrangefunc(): gst_base_src_getrange
      Has custom eventfunc(): gst_base_src_event
      Has custom queryfunc(): gst_base_src_query
      Has custom iterintlinkfunc(): gst_pad_iterate_internal_links_default
    Pad Template: 'src'

Element Properties:
  name                : The name of the object
                        flags: readable, writable
                        String. Default: "rpicamsrc0"
  parent              : The parent of the object
                        flags: readable, writable
                        Object of type "GstObject"
  blocksize           : Size in bytes to read per buffer (-1 = default)
                        flags: readable, writable
                        Unsigned Integer. Range: 0 - 4294967295 Default: 4096 
  num-buffers         : Number of buffers to output before sending EOS (-1 = unlimited)
                        flags: readable, writable
                        Integer. Range: -1 - 2147483647 Default: -1 
  typefind            : Run typefind before negotiating
                        flags: readable, writable
                        Boolean. Default: false
  do-timestamp        : Apply current stream time to buffers
                        flags: readable, writable
                        Boolean. Default: true
  bitrate             : Bitrate for encoding
                        flags: readable, writable
                        Integer. Range: 1 - 25000000 Default: 17000000 
  preview             : Display preview window overlay
                        flags: readable, writable
                        Boolean. Default: true
  preview-encoded     : Display encoder output in the preview
                        flags: readable, writable
                        Boolean. Default: true
  preview-opacity     : Opacity to use for the preview window
                        flags: readable, writable
                        Integer. Range: 0 - 255 Default: 255 
  fullscreen          : Display preview window full screen
                        flags: readable, writable
                        Boolean. Default: true
  sharpness           : Image capture sharpness
                        flags: readable, writable
                        Integer. Range: -100 - 100 Default: 0 
  contrast            : Image capture contrast
                        flags: readable, writable
                        Integer. Range: -100 - 100 Default: 0 
  brightness          : Image capture brightness
                        flags: readable, writable
                        Integer. Range: 0 - 100 Default: 50 
  saturation          : Image capture saturation
                        flags: readable, writable
                        Integer. Range: -100 - 100 Default: 0 
  iso                 : ISO value to use (0 = Auto)
                        flags: readable, writable
                        Integer. Range: 0 - 3200 Default: 0 
  video-stabilisation : Enable or disable video stabilisation
                        flags: readable, writable
                        Boolean. Default: false
  exposure-compensation: Exposure Value compensation
                        flags: readable, writable
                        Integer. Range: -10 - 10 Default: 0 
  exposure-mode       : Camera exposure mode to use
                        flags: readable, writable
                        Enum "GstRpiCamSrcExposureMode" Default: 1, "auto"
                           (0): off              - GST_RPI_CAM_SRC_EXPOSURE_MODE_OFF
                           (1): auto             - GST_RPI_CAM_SRC_EXPOSURE_MODE_AUTO
                           (2): night            - GST_RPI_CAM_SRC_EXPOSURE_MODE_NIGHT
                           (3): nightpreview     - GST_RPI_CAM_SRC_EXPOSURE_MODE_NIGHTPREVIEW
                           (4): backlight        - GST_RPI_CAM_SRC_EXPOSURE_MODE_BACKLIGHT
                           (5): spotlight        - GST_RPI_CAM_SRC_EXPOSURE_MODE_SPOTLIGHT
                           (6): sports           - GST_RPI_CAM_SRC_EXPOSURE_MODE_SPORTS
                           (7): snow             - GST_RPI_CAM_SRC_EXPOSURE_MODE_SNOW
                           (8): beach            - GST_RPI_CAM_SRC_EXPOSURE_MODE_BEACH
                           (9): verylong         - GST_RPI_CAM_SRC_EXPOSURE_MODE_VERYLONG
                           (10): fixedfps         - GST_RPI_CAM_SRC_EXPOSURE_MODE_FIXEDFPS
                           (11): antishake        - GST_RPI_CAM_SRC_EXPOSURE_MODE_ANTISHAKE
                           (12): fireworks        - GST_RPI_CAM_SRC_EXPOSURE_MODE_FIREWORKS
  metering-mode       : Camera exposure metering mode to use
                        flags: readable, writable
                        Enum "GstRpiCamSrcExposureMeteringMode" Default: 0, "average"
                           (0): average          - GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_AVERAGE
                           (1): spot             - GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_SPOT
                           (2): backlist         - GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_BACKLIST
                           (3): matrix           - GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_MATRIX
  awb-mode            : White Balance mode
                        flags: readable, writable
                        Enum "GstRpiCamSrcAWBMode" Default: 1, "auto"
                           (0): off              - GST_RPI_CAM_SRC_AWB_MODE_OFF
                           (1): auto             - GST_RPI_CAM_SRC_AWB_MODE_AUTO
                           (2): sunlight         - GST_RPI_CAM_SRC_AWB_MODE_SUNLIGHT
                           (3): cloudy           - GST_RPI_CAM_SRC_AWB_MODE_CLOUDY
                           (4): shade            - GST_RPI_CAM_SRC_AWB_MODE_SHADE
                           (5): tungsten         - GST_RPI_CAM_SRC_AWB_MODE_TUNGSTEN
                           (6): fluorescent      - GST_RPI_CAM_SRC_AWB_MODE_FLUORESCENT
                           (7): incandescent     - GST_RPI_CAM_SRC_AWB_MODE_INCANDESCENT
                           (8): flash            - GST_RPI_CAM_SRC_AWB_MODE_FLASH
                           (9): horizon          - GST_RPI_CAM_SRC_AWB_MODE_HORIZON
  image-effect        : Visual FX to apply to the image
                        flags: readable, writable
                        Enum "GstRpiCamSrcImageEffect" Default: 0, "none"
                           (0): none             - GST_RPI_CAM_SRC_IMAGEFX_NONE
                           (1): negative         - GST_RPI_CAM_SRC_IMAGEFX_NEGATIVE
                           (2): solarize         - GST_RPI_CAM_SRC_IMAGEFX_SOLARIZE
                           (3): posterize        - GST_RPI_CAM_SRC_IMAGEFX_POSTERIZE
                           (4): whiteboard       - GST_RPI_CAM_SRC_IMAGEFX_WHITEBOARD
                           (5): blackboard       - GST_RPI_CAM_SRC_IMAGEFX_BLACKBOARD
                           (6): sketch           - GST_RPI_CAM_SRC_IMAGEFX_SKETCH
                           (7): denoise          - GST_RPI_CAM_SRC_IMAGEFX_DENOISE
                           (8): emboss           - GST_RPI_CAM_SRC_IMAGEFX_EMBOSS
                           (9): oilpaint         - GST_RPI_CAM_SRC_IMAGEFX_OILPAINT
                           (10): hatch            - GST_RPI_CAM_SRC_IMAGEFX_HATCH
                           (11): gpen             - GST_RPI_CAM_SRC_IMAGEFX_GPEN
                           (12): pastel           - GST_RPI_CAM_SRC_IMAGEFX_PASTEL
                           (13): watercolour      - GST_RPI_CAM_SRC_IMAGEFX_WATERCOLOUR
                           (14): film             - GST_RPI_CAM_SRC_IMAGEFX_FILM
                           (15): blur             - GST_RPI_CAM_SRC_IMAGEFX_BLUR
                           (16): saturation       - GST_RPI_CAM_SRC_IMAGEFX_SATURATION
                           (17): colourswap       - GST_RPI_CAM_SRC_IMAGEFX_COLOURSWAP
                           (18): washedout        - GST_RPI_CAM_SRC_IMAGEFX_WASHEDOUT
                           (19): posterise        - GST_RPI_CAM_SRC_IMAGEFX_POSTERISE
                           (20): colourpoint      - GST_RPI_CAM_SRC_IMAGEFX_COLOURPOINT
                           (21): colourbalance    - GST_RPI_CAM_SRC_IMAGEFX_COLOURBALANCE
                           (22): cartoon          - GST_RPI_CAM_SRC_IMAGEFX_CARTOON
  rotation            : Rotate captured image (0, 90, 180, 270 degrees)
                        flags: readable, writable
                        Integer. Range: 0 - 270 Default: 0 
  hflip               : Flip capture horizontally
                        flags: readable, writable
                        Boolean. Default: false
  vflip               : Flip capture vertically
                        flags: readable, writable
                        Boolean. Default: false
  roi-x               : Normalised region-of-interest X coord
                        flags: readable, writable
                        Float. Range:               0 -               1 Default:               0 
  roi-y               : Normalised region-of-interest Y coord
                        flags: readable, writable
                        Float. Range:               0 -               1 Default:               0 
  roi-w               : Normalised region-of-interest W coord
                        flags: readable, writable
                        Float. Range:               0 -               1 Default:               1 
  roi-h               : Normalised region-of-interest H coord
                        flags: readable, writable
                        Float. Range:               0 -               1 Default:               1


Because of the way gstreamer works, the parameters for the feed needed to be split and re-arranged in the streamer pipeline. Previously all the parameters are specified as part of raspivid.

/opt/vc/bin/raspivid -t $DURATION -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -n -pf high -o - | gst-launch-1.0 -v fdsrc ! 

GStreamer parameters like width, height and frame rate are configured through capabilities (caps) negotiation with the next element. Other parameters like the bit rate and preview screen are controlled as part of the source element.

gst-launch-1.0 rpicamsrc bitrate=$BITRATE preview=0 ! video/x-h264,width=$WIDTH,height=$HEIGHT,framerate=$FRAMERATE/1 !

The new stream script is


source remote.conf

if [ "$1" != "" ]
  export FRAMERATE=$1

NOW=`date +%Y%m%d%H%M%S`

gst-launch-1.0 rpicamsrc bitrate=$BITRATE preview=0 ! video/x-h264,width=$WIDTH,height=$HEIGHT,framereate=$FRAMERATE/1,profile=high ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$RX_IP port=$UDPPORT


This test was a straight comparison between the old and new scripts using the same settings and the same testing methodology as previously.  The resolution was 1280 x 720 pixels with a 6Mbps bitrate.

Update : Since the original article was published use Jan Schmitt spotted that I had misspelled “framerate” as “framereate” in the gst-rpicamsrc script.  He also suggested I should try using the baseline profile and a queue element to decouple the video capture from the UDP transmission.  With this in mind I have re-run the tests.


Almost immediately I had the feeling that gst-rpicamsrc has slower.  Analysis of the video showed I was correct.  The latency using gst-rpicamsrc was 18% higher than using raspivid.


Running the original erroneous script with debugging on showed that the capture was running at 30fps instead of the intended 48 fps. Here are the new results averaged from 10 cycles.

Script gst-rpicamsrc @ 48 fps
raspivid @ 48 fps
Profile No queue With queue No queue With queue
baseline 184.2 175.4 153.9 156.9
high 186.2 185 154.1 159.7

gst-rpicamsrc @ 30 fps, high profile, no queue = 198.2 ms


The first thing to note is that the raspivid latency (no queue, high profile) has risen from the 126ms found in the last tests to 154ms.  The only difference was that I cloned the Sandisk microSDHC card onto a Transcend 8GB.  I’ll set up some more tests to compare the cards.  As these tests were run from the same card and from the same boot, they are still valid for comparison.

It is immediately obvious that the gst-rpicamsrc latency is about 20% higher than the raspivid script, so the conclusion from the first publish of this article still stands.

What can be added is that using the baseline profile, does reduce the latency a little: 1 to 3ms in most cases.

Adding a queue element does provide a benefit for the gst-rpicamsrc script, especially with the baseline profile where a 9ms reduction in latency was observed.  For the raspivid script adding a queue element actually increased the latency by 3 to 4ms.  I suspect this is because the video stream is already decoupled from gstreamer by being piped in from an external process.


Using gst-rpicamsrc provides no benefit for reducing latency over raspivid.  That is not to say gst-rpicamsrc provides no other benefits.  For any use other than FPV, I would definitely use gst-rpicamsrc instead of having to pipe the video in through stdin.  It provides plenty of options for setting up the video stream as the command `gst-inspect-1.0 rpicamsrc’ above showed.

The problem here is that I am targeting this development for FPV use where low latency is the driving factor. At the moment my lowest latency for a adequate quality HD stream is 125ms and I really need to get this under 100ms to compete with current analog standard definition systems.  Whether it is possible to shave of another 25ms remains to be seen.

Update: Following the additional tests I would add that it is better to use the baseline profile over the high profile.

Effect of Frame & Bit rates on Latency


Back in March, an update to the Raspberry Pi camera software introduced some new video modes with higher frame rates for resolutions below full 1080p HD.  For 720p HD, frame rates up to 49 fps are now available and for VGA (640×480) there are new modes for 60 and 90 fps.  There were reports that, at these higher frame rates, the latency was reduced.  This didn’t come as a surprise as it has been known for a while that the GoPro video out has lower latency at 48 fps than at 30 fps.  The reasons for this are not totally clear, but is thought to be due to the differences between frames being less at the higher frame rates allowing for more efficient compression.

In order to investigate this I ran some back-to-back tests at various frame rates.  I was expecting that with twice as many frames being squeezed into the same bit rates, the video quality would suffer, so the tests where repeated at three different bit rates.  The result of this testing was a 25% reduction in latency, with a new minimum of 121 milliseconds at 720p and 48 fps.  As expected the video quality at the old bit rate of 2.5Mbps suffered for fast moving backgrounds, but even when increased to 6.0Mbps, the latency was still only 126 Mbps; a 23% reduction.

With VGA resolution at 60fps and 2.5 Mbps the latency dropped to 87 ms and while this is useful, in terms of hardware size, convenience and even latency, it is still bettered by dedicated FPV hardware.  If you include the cost of the laptop, it looses out on price too.  Where the Pi has the advantage is at the 1280 x 720p HD resolution where there is currently no affordable competition.


The test environment was set up the same as previously, with the camera pointing at the laptop screen.  The camera was positioned so that at least ten iterations of the image were visible at once. I used a single LED torch as the measurement indicator.  The tests were run with no overclocking.

I used a UDP stream with some improved scripts to simplify running all the variations. The scripts can be found on the Current Scripts Page.

A GoPro 3 Black was used to record the screen at 120 fps.

Tests were run at frame rates of 25, 30, 36, 42, 45, 48 and 49 fps and at bit rates of 2.5, 4.5 and 6.0 Mbps.   Up to 5 LED on/led off cycles were recorded on the GoPro for later analysis.  With 10 iteration for each of the 5 on/offs, the calculated latency represents the average of 100 tests.

Results 1 – Latency

Across all the bit rates, the results show a definite reduction in latency with increasing frame rate right up to 48 frames per second. At 49 fps the latency increased slightly. The lowest latency achieved was 121ms at 48 fps for the 2.5 Mbps stream.  A reduction of 25% over the 25 fps result.  The 6.0 Mps stream still managed a reduced latency of 126 ms at 48 fps and the 4.5 Mbps stream achieved 125 ms.

The VGA test showed a much lower latency at 87ms, even though it was using the same bit rate as the smallest 720p HD stream.

The graph shows some odd behavior between the 4.5 and 6.0 Mbps curves.  Below about 40 fps the 4.5 Mbps stream has higher latency than the 6.0 Mbps stream.  Beyond 40 fps the curves switch over to what you would expect.


In addition to the average latency, the graph below shows the minimum and maximums for each bit rate.  What is apparent is that there is a lot of overlap between the results and that the latency can vary +/- 20 fps, particularly at the lower bit rates.


Results 2 – Video Quality

The frame grabs below show a clear difference between the three bit rates at 48 fps. The 2.5 Mbps stream shows extreme pixelation and a general blurring of the image.


Frame grab from 2.5 Mbps stream @ 48 fps

The  4.5 Mbps shows a reduction in the pixelation.  This is apparent in the sky and on the tiled roof.


Frame grab from 4.5 Mbps Stream @ 48 fps

The 6.0 Mbps is the clear winner, with a minimum of pixelation and the sharpest image.


Frame grab from 6.0 Mbps Stream @ 48 fps


The total latency is made up of capture, compression, transmission and display components.  The capture and  display components should be the same for the three bit rates as the resolution is the same.  The transmission component should increase in relation to the higher bit rates.  That just leaves the compression component.  The compressor has to work hard to squeeze the stream into a smaller bit rate whilst maintaining the best video quality possible.  For this reason decreasing the bit rate can increase the latency, although there is probably a point where the extreme pixelation starts reducing the latency again.

These opposing affects between compression and transmission are likely what has caused the odd behavior between the 4.5 Mbps and 6.0 Mbps streams.  At the lower frame rates, the compression delay for the 4.5 Mbps stream was more significant.  At the higher frame rates the transmission delay in the 6.0 Mbps stream became more significant.

While the VGA test used the same 2.5 Mbps bit rate as the HD test, with only a third of the pixels, the capture, compression and display components resulted in a much lower latency of 87 ms.

While the lowest latency was achieved for the 2.5 Mbps stream, the extreme pixelation of the image renders it pretty much unusable.  The 4.5 Mbps stream could be used but it only has a 1 ms advantage over the superior image quality of the 6.0 Mbps stream.  For this reason I plan to adopt the 48 fps, 6.0 Mbps, 126 ms stream as my new baseline when flying.

I will probably also switch to a 24 fps pipeline for youtube videos to get the best image quality from the 48 fps video, dropping every other frame.  I have seen this done where people have used the 48 fps recording on GoPro cameras.

B or B+


The Raspberry Pi Model B+ has recently been released with improved USB hardware.  This test aimed to determine if this new hardware would reduce the latency compared to the Model B.  And the answer I’m afraid is No.

FPiV Model B v B+


The new USB hardware requires different firmware from previously.  As I was going to have to rebuild the operating system anyway, I opted to try a minimal installation using raspbian-ua-netinst.  There was a second reason for doing this, which was to install the “Jessie” build of Raspbian rather than “Wheezy” because “Jessie” comes with the latest build of gstreamer as standard.  This is currently at version 1.4.1.  In “Wheezy” you only have access to version 1.0.

Two installs were completed using identical procedures. One on my old model B and one on a new B+.

The test environment was set up the same as previously, with the camera pointing at the laptop screen.  The camera was positioned so that at least ten iterations of the image was visible at once. I used the LED on my phone with a flashlight app for measurement indicator.  The tests were run with no overclocking.

I used a UDP stream using the same scripts as for the previous Transport Stream and Overclocking Test.

A GoPro 3 Black was used to record the screen at 120 fps.

Three identical tests were run.  One for each Raspberry Pi using the operating system that had been built on it and then a third test using the B+ micro SD card in the model B with an adapter.  A number of led on/led off cycles were recorded and then two cycles from each run were picked at random for analysis.


The GoPro video was analyzed using VideoReDo H264 to establish the number of frames between the LED switch on (or off) and the tenth iteration switch on/off.  This value was then divided by 1.2 to get the latency in milliseconds.

  1. Model B, Native built OS : 156ms, 150ms, 138ms, 147 ms = an average of 147ms +/- 10ms
  2. Model B+, Native built OS : 153ms, 154ms, 157ms, 154ms = an average of 154 ms +/- 3ms
  3. Model B with B+ built OS : – 148ms, 142ms, 158ms, 148ms = an average of 149 ms +/- 8 ms


For now the Model B+ appears to give a slightly higher latency than the Model B.  This is a shame as the B+ has a much cleaner layout.  Hopefully, the latency will improve with time as the USB drivers are optimised.  The “Jessie” build of Raspbian has not been officially released yet.

The results for the Model B were slightly better than the previous Transport Stream and Overclocking Test by about 10 millseconds so it appears the minimal raspbian-ua-netinst build was worthwhile.  See this post for details on how to configure raspbian-ua-netinst for “Jessie”.