Tag Archives: rtl-sdr

Bugs when using rtl_tcp / Memory usage of rtl_tcp

Memory usage and buffers of rtl_tcp

The way rtl_tcp acquires memory and and how much memory it needs, depending on the parameters is very cryptic.

According to the man page the options are:

-b number of buffers (default: 15, set by library)
-n max number of linked list buffers to keep (default: 500)

This leaves the questions: how big is a buffer and linked list buffer? In short:

The linked list buffer will overflow only if tcp transport is not fast enough.

The buffers will overflow when you receive usb data faster than you can process it.

A linked list is a special kind of buffer which is very efficient for hunks of data of different size. It contains information of the next element and is allocated when needed.

Linked List

The buffers have a statically allocated size of 32kByte when called from rtl_tcp. Therefore initially there will be b x 32kBytes of memory reserved for asynchronous callback from the USB port. When these data return, they are copied in a linked list buffer. The linked list buffer is dynamically allocated, based on the actual size of the received data (which can be smaller than one buffer size). The maximum size of one linked list buffer is therefore about the size of one buffer. The total memory usage can therefore be estimated by:

static: 32kB * ( b )
dynamic: 32kB * (n )

As you can see it is totally of none importance if these numbers are even or odd. With the default settings, the theoretical maximum memory usage should be:

32kB(15+500) = 16’480 kByte.

If there are problems with your linked list buffer, e.g. the linked list adds or removes elements (because the data is not transferred in time) you will get such  messages when running rtl_tcp in command line:

ll+, now 1
ll+, now 2
ll+, now 3
ll+, now 4
ll+, now 5
ll+, now 6
ll+, now 7
ll-, now 0

Which basically just show you that you could not handle to send out the tcp packages fast enough, but instead had to create a new linked list buffer. ll+ means a new element is added, ll- an element is removed from the buffered list. Ideally for “live” streaming you dont want such messages at all. However, as long as you dont hit your max number of linked list buffer (-n) you will not lose packages.

However the practical memory usage is way higher, because of the underlying libusb transport layer that also allocates memory. The minimum memory usage on MIPS32 (WR703N with OpenWRT) with -b 1 and -n 0 is around 5700 kBytes with one client

Further I have observed that on MIPS32 the asynchronous transport only used one of the offered buffers in rtl_tcp, possibly because the only operation after a callback is to copy the buffer into a linked list. I think therefore that it is safe to use a small number of buffers, and a number of linked-list as can be conveniently used on the given device.

Bugs using rtl_tcp with SDR#

A very nice tool for windows is SDR#, which is now developed in closed source. There is a nice article over at hamradioscience that describes how to set up rtl_tcp with SDR#.  It still is my favorite tool when using the rtl-sdr directly connected over USB. However there are many reports of problems with “ringing” and a garbage signal, which can be recognized by this characteristic signal spectrum, which is also described on reddit. I have had this problems with the latest SDR# rev. 1337 too.

SDR# failing with rtl_tcp


I have analyzed the packages with wireshark, transmitted test packages and taken a glance at old SDR# code. In conclusion, rtl_tcp works just fine without any package loss. SDR# is not fast enough to process the received data synchronously.

Solution? Since SDR# is closed source none yet. You can give other open-source software a try, such as  the very extensive GnuRadio.


Crash of rtl_tcp when disconnecting/connecting a client

This problem has been reported most significantly on Raspberry Pi. It is caused by an old version of libusb (1.0.11) shipped still with the latest Raspbian image (03/2015). The issue does not occur with a newer libusb1.0.19.

As a workaround, enable the testing sources and update the libusb1.0.0 package.

  1. Login as root Open file /etc/apt/sources.list in your favourite editor

    gedit /etc/apt/sources.list

  2. Adding the testing repo. Add the below line.

    deb http://http.us.debian.org/debian/ testing non-free contrib main

  3. sudo apt-get update
  4. sudo apt-get install libusb1.0.0

Compiling custom OpenWRT firmware / packages

OpenWRT is a nifty thing. However, if you want to test some custom or self written programs it can be tricky.

For most instances, e.g. on a Raspberry or other embedded device, you can install a compile toolchain to just configure and make your project. Due to space constraints this is often not necessary. Cross-compiling for these embedded devices (for instance WR703N is MIPS32) is quite tricky. The easiest way therefore is to use the OpenWRT build root to compile these packages (and complete OpenWrt firmares).

I will not go into detail how to get, configure and build OpenWRT, you can find detailled instructions at the OpenWRT Wiki, and in addition how you can compile only a single package.

Assuming you have configured your OpenWRT install, you can build and include custom packages by editing the corresponding Makefiles.
For instance rtl-sdr you can find in the feeds directory:
Or the hamlib

Everytime you install and compile the package, the source files will be downloaded newly from the internet and compiled. Therefore the easiest way is to provide a repository and commit where is the newer version.

So for instance, replacing the rtl-sdr/Makefile with this content can receive my custom version of rtl-sdr.

# Copyright (C) 2013 OpenWrt.org
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.

include $(TOPDIR)/rules.mk