Improved retransmission scheme and multiplexing
This post presents some changes to my wifibroadcast project (https://befinitiv.wordpress.com/2015/01/25/true-unidirectional-wifi-broadcasting-of-video-data-for-fpv/ ) that improve reliability and functionality
When playing around with my rx and tx tools I noticed something odd. I tried to find the right setting for the retransmission count. To recall, the retransmission count is the number an identical data packet is being sent. The idea is to simply increase the probability that at least a single packet makes its way. The strange thing I’ve encountered was that it made no difference whether I was sending the data two times or six times. In both cases I had nearly the same packet loss. By using wireshark I was able to find the cause of that problem: Beacon frames from hidden terminals.
The hidden terminal problem:
A ~~~~ B ~~~~ C
Assume A wants to talk to B. Before A sends a packet it monitors if the channel is free. If so, it sends its packet. Unfortunately, C is doing the same thing as A at the exact same time. Since A cannot head C and vice versa since they are too far apart they both assume the channel to be free. At station B the frames from A and C collide and get lost.
What does this have to do with retransmission? Well, beacon frames are sent at the lowest possible rate (1Mbit/s). They carry usually between 150 and 250 bytes so the duration of them can be up to two miliseconds. In contrast to that the wifi card I used was sending its data at 26Mbit/s. Thus the duration of the frames was significantly shorter. Because of that, a single beacon frame from a hidden station was able to destroy a whole retransmission block. Lets visualize that. Assuming a retransmission rate of 3 the data packets a,b and c would be sent like this:
Now lets assume a beacon B starts after the first packet of a:
Whops, you have just lost the packet b because the beacon blocked every transmission of it.
The solution to this problem is simple: Retransmission blocks. Packets are gathered to form a block which is then sent several times. Let’s assume a block size of 8 packets, a retransmission rate of 3 and the packets a,b,c,d,e,f,g and h to send. On the air the packets are now sent as follows:
When our nasty beacon arrives it looks as follows:
The total number of packets is identical but we lost no packet 🙂
This comes at a little price: Latency. But if the blocks are small enough it is pretty low. I found block sizes of 8 or 16 packets quite useful. They really made the link quality much much better. If you choose a block size of 1 then the program behaves as before (this is also the default setting). A little caution is needed: both rx and tx need to agree on the block size!
What retransmission rates are sensible? In my experience you need at least two. Then the video stream will be mostly error-free at good reception. If you are having a bad link (long range or high noise) that you should set this value as high as you can. This really improves the range you can get. The limit for this factor is the available bandwidth. Just multiply your video bitrate with the retransmission count and try to fit that product into the maximum bandwidth (Assuming a TL-WN722N this would be roughly 14mbit/s at MCS3 26mbit/s air data rate)
The first version of rx and tx was able to transfer only a single stream of data at once. Since it would be nice to transport also other data over the same channel (think of GPS, etc) I added a “port” feature to both programs. The last byte of the fake MAC address used by rx and tx is replaced by this port number. This allows you to define up to 256 channels.
Testing video transmission using the raspberry camera
On the receiver side:
sudo ./rx -p 0 -b 16 wlan0 | gst-launch-1.0 fdsrc ! h264parse ! avdec_h264 ! xvimagesink sync=false
On the raspberry side:
raspivid -t 0 -w 1280 -h 720 -fps 30 -b 3000000 -n -pf baseline -o - | sudo ./tx -p 0 -r 3 -b 16 -f 1024 wlan1
This creates a transmission on port 0 (-p) with three retransmissions (-r), a retransmission block size of 16 (-b) and packets with the length of 1024 bytes (-f).
So far it looks pretty good. The latency is roughly (not measured) in the range of 100ms and the range is satisfying. I tested it with two TL-WN722N with 3dbi dipoles and had good video quality throughout my apartment. The longest distance covered was 20m with 4 concrete walls in between. I already saw lots of packets dropping but a retransmission rate of 5 fixed that and gave a clear image.
If you want to try that by yourself:
hg clone https://bitbucket.org/befi/wifibroadcast/
If you are using the same wifi cards you might also take a look at https://befinitiv.wordpress.com/2015/02/22/finding-the-right-wifi-dongle-and-patching-its-kernel-driver-and-firmware/ .
What’s next? I guess building a double biquad antenna for the receiver 🙂