Measuring RpiCam Bandwidth Performance
BOARD
Measuring RpiCam Bandwidth Performance
2016-10-11
By
David "DeMO" Martínez Oliveira

I have a couple of project in mind, involving video streaming. For those projects, the bandwidth usage is important and I was wondering how well the Rpi Camera hardware H264 encoder performs. These is what I have found.
For the test I have used a Rpi 3 with a camera module and gstreamer for the SW side. Check this post Quick and Dirty Raspberry Pi Spy Cam for details on how to stream video using gstreamer.

For these tests, I was mainly interested on checking how well the HW encoder can keep the bitrate as well as, how much the stream exceeds the maximum value. I started every test running raspivid without a bandwidth constraint to measure the natural bitrate from the camera. Then I progressively decrease the bandwidth to verify how it performs.

With Regards to quality, I haven't carried out objective measurements. I'm just providing some subjective quality estimation as reference.

Measurements

I used a slightly modified version of the bandwidth measurement script I described in Real-time Bandwidth Monitoring
#!/bin/bash

rm $2.bw $2.cpu

(while true; do (ifstat -b -i $1 1 1 | awk 'NR>2{print $1, $2}' >> $2.bw ; cat /proc/loadavg | awk '{print $1}' >> $2.cpu); done)

As you can see I was also monitoring the CPU usage. However, the values were always very low so I will not report any data on that. Let's say that, in a sense, we can be sure that the H264 encoding was performed using the hardware accelerations capabilities.

I also wrote a very simplistic script to extract minimal statistics from the captured data. In case you are curious, this is how it does look like.

#!/usr/bin/perl

use List::Util qw(sum max min);
use POSIX;

@F=<>;

printf "%-7s : %f\n" x 3,
    "Min", min(@F),
    "Max", max(@F),
    "Average", sum(@F)/@F;

I use this script for other tasks and it just process files with all the data in one single column. Our bandwidth script produces two columns, one for the incoming traffic and another one for the outgoing traffic. This means that we need to filter the bw data before feeding it into the statistics module.

I use awk for this:

$  cat data.bw | awk  '{print $1}' | ./stats.pl

Depending on the machine you launch the bw script, you may need to change $1 to $2.

Finally, each dataset is composed of 20 seconds of a static image followed by 20 seconds of a constantly changing image.

Full HD Streaming

First test was at Full HD (1920x1080). Without imposing any bandwidth or framerate condition, the statistics we get are:

Min     : 7330.530000
Max     : 19897.850000
Average : 11711.743171

So the average bandwidth required is around 12 Mbps. However we can see that, at some point the bandwidth get doubled. Let's take a look to the graph to know more.

As we can see, the first 20 seconds, that corresponds to a static image, used around 8Mbps to stream the video feed. When the image starts to constantly change, the bandwidth gets increased considerably. Roughly it looks like the average for the last 20 secs is around 16 Mbps and we reach a peak of almost 20Mbps

The video quality was excellent and the frame rate was a steady 30 fps.

Now, let's reduce the bandwidth to a half of the peak for the native streaming mode: 10Mbps

Min     : 6744.500000
Max     : 14242.150000
Average : 8817.024222

Again, the average is in general below the requested bandwidth, however we have 14Mbps peaks that way above the average. Let's take a look again to the run-time bandwidth usage

Again we can see how the bandwidth required cannot be maintained for the last 20 seconds of the test. In this case we see a higher variance. Average seems to be around 10, but there the bandwidth required is far from being steady.

Image quality and frame rate was all OK with this bandwidth. Let's reduce the bandwidth now to 5 Mbps:

Min     : 3172.670000
Max     : 6007.200000
Average : 5062.105500

This is a lot better. The average is pretty close to the required bandwidth and the peak bandwidth is only 1Mbps above the average (20%). Let's take a look to the graph

As expected from the statistics, this one is a lot flatter than the previous plots. We can see he big peaks happening when just after the 20 seconds, but this time, the average seems to stay around the requested value for the second period.

The image quality was also good and the framerate still 30 fps steady.

Now, let's move to 2 Mbps

Min     : 1409.230000
Max     : 2827.400000
Average : 2035.182000

The average bandwidth is pretty much the one required. The peak is close to 50% more than the requested bandwidth. The plot is very similar to the one we got with 5Mbps.

In this case, the video quality is poor, specially when something changes in the image. No variations on the frame rate.

Going 720p

So, it looks like we cannot go below 2Mbps without a massive degradations of the image, and 5Mbps seems to be the minimum for a decent quality. Now we are going to reduce the resolution and check the minimum bandwidth for a decent quality video.

First, let's check bandwidth without any parameter to get our reference statistics.

Min     : 2831.870000
Max     : 13382.100000
Average : 7227.804750

And this is the graph:

The situation is very similar to what we have seen with the initial full HD test. The static image video requires something around 3Mbps, but the moving video goes as high as 14 Mbps (a bit less). After the still 20 seconds we see how the bandwidth goes to a roughly average of 8 to 10 Mbps. Again, quality and framerate are perfect.

So, let's try 8 Mbps.

Min     : 3009.310000
Max     : 10255.040000
Average : 5543.662326

The average is below the requested 8 Mbps. However the bandwidth peaks actually doubles the required bandwidth. The bandwidth plot shows that again a similar shape.

Let's halve the bandwidth. 4 Mbps give us those results:
Min     : 3153.340000
Max     : 5762.350000
Average : 3902.724762

And this is the plot.

Finally let's go down to 2 Mbps....

Min     : 1405.580000
Max     : 2939.410000
Average : 2010.246829

Around 50% extra peaks. Let's look at the graph

As we've also seen in the previous test, there is no longer a huge difference between the steady image and the moving image, however, the moving image produces a more unstable bandwidth pattern.

At this bandwidth visual artefacts are already noticeable. Frame rate is stable.

Once again we can see a big peak when we start changing the image (what makes sense) and then a average value roughly in the spot but peaks goes over 1 Mbps extra.

Finally we will test 1Mbps.

Min     : 525.790000
Max     : 1520.210000
Average : 1021.731739

We can see the usual 50% extra bandwidth peak. However the plot in this case is curious:

The quality is clearly degraded

CONCLUSIONS

Overall, the Rpi Camera hardware acceleration bandwidth setting is rough estimation. In general, we will get peaks of around 50% extra with respect to the request bandwidth. These values are summarized in the tables below:

MAX10Mbps5Mbps2Mbps5Mbps-2
Min7330.53 6744.5 3172.671409.234013.41
Max19897.8514242.156007.22827.46485.22
Average11711.748817.025062.102035.185061.81
Peak ratio0.6990.6150.1870.3890.281

For the Full HD case, we can see that for 5Mbps the streaming behaves more stable, exposing a very low peak ratio. For the HD case (720p), all values below 5Mbps shows similar rations but quite close to 50%.

Yes, I measure again the 5Mbps... similar results as you can see

MAX8Mbps4Mbps2Mbps1Mbps5 Mbps
Min2831.873009.313153.341405.58525.792691.64
Max13382.110255.045762.352939.411520.216792.55
Average7227.805543.663902.722010.251021.734403.91
Peak Ration0.8510.8490.4760.4620.4880.542

So... you better check your network characteristics (size and duration of a allowed traffic burst) when selecting your bandwidth for streaming from your Rpi Cam.

Maybe I should also measure the impact of the framerate... but let's leave this for other post.