|
libfreenect2 0.4
Open source driver for the Kinect for Windows v2 (K4W2) sensor
|
Advanced reference for how libfreenect2 moves data off the sensor, why the Kinect v2 is unusually demanding of a USB 3.0 controller, and when the four transfer-pool environment variables are the right tool.
For a symptom-first walkthrough, start with Troubleshooting instead. Most of this page is Linux-specific, but the transfer-pool section applies to every platform.
The sensor streams two things at once:
The IR stream is the demanding one. Depth is reconstructed from ten raw subframes per depth frame at 512×424, delivered at 30 Hz, and the isochronous endpoint reserves bandwidth up front whether or not it is used. Combined with color, a single Kinect v2 consumes most of a 5 Gbps USB 3.0 link — real-world throughput on a SuperSpeed link is well under the nominal 5 Gbps once encoding and protocol overhead are accounted for.
The practical consequences:
Upstream worked the reservation out from the kernel's SuperSpeed bandwidth formula (xhci_get_ss_bw_consumed()):
| Endpoint | Consumption |
|---|---|
| IR (isochronous) | 2.47 Gbps reserved, whether or not it is used |
| Color (bulk) | ~0.25 Gbps effective; bulk reserves nothing |
That is roughly 2.7 Gbps before any other device on the controller, and both endpoints transfer in bursts and idle in between, so headroom matters more than the average suggests. Treat 3 Gbps as the practical minimum for one sensor.
Against that: PCIe v1 x1 carries 2 Gbps — not enough for the isochronous endpoint alone. PCIe v2 x1 carries 4 Gbps, which works but has little room. This is also the arithmetic that decides whether a multi-Kinect configuration is feasible at all: two sensors need two controllers on two adequately-wide links, not one wider link.
The 33792-byte (0x8400) isochronous packet comes from wBytesPerInterval, and equals (Mult + 1) × (bMaxBurst + 1) × wMaxPacketSize. bMaxBurst is 10 as reported by lsusb, which puts the result below the 49152-byte maximum the Linux kernel permits. The value appears to be fixed by the Kinect's firmware rather than negotiated, so it should be the same on every platform.
A Kinect plugged into a USB 3.0 port can still fall back to 480 Mbps on a bad cable or a marginal port. On Linux, check the advertised speed in the topology:
The Kinect's port must show 5000M. Anything lower (480M, 12M) means the link did not come up at SuperSpeed and depth streaming will not work — replace the cable, try a different port, and confirm you are using the Kinect's own powered adapter.
A healthy sensor looks like this:
Four interfaces, two vendor-specific and two audio, all at 5000M. The empty Driver= on the vendor-specific interfaces is correct — libusb claims them at runtime. snd-usb-audio holding the audio interfaces is also correct and does not conflict with libfreenect2, which never touches them (see Frequently asked questions for what that means if you want the microphones). The interface layout is explained in Kinect v2 USB protocol.
On macOS the equivalent is:
Look for Xbox NUI Sensor with Speed: Up to 5 Gb/s.
Include this in bug reports — the numeric [vendor:Initialization and Device Control] ID identifies the controller far better than a brand name.
libfreenect2 allocates two pools of libusb transfers when the device is opened, sized differently per platform. The library logs the result at Info level every time it opens a device:
Read as rgb: <transfers>*<bytes> and ir: <transfers>*<packets>*<packet bytes>. The IR packet size is not a constant — it is read from the device's isochronous endpoint descriptor at open time and must be at least 0x8400 (33792) bytes, or the open fails.
| Platform | RGB_TRANSFERS | RGB_TRANSFER_SIZE | IR_TRANSFERS | IR_PACKETS |
|---|---|---|---|---|
| Linux (and any other platform) | 20 | 0x4000 (16384) | 60 | 8 |
| macOS | 20 | 0x4000 (16384) | 4 | 128 |
| Windows | 3 | 1048576 (1 MiB) | 8 | 64 |
macOS uses few, large isochronous transfers; Linux uses many small ones. Windows uses very few, very large bulk transfers because poll() there has a 64 file descriptor limit, which a multi-Kinect setup would otherwise exhaust.
Total IR pool bytes are IR_TRANSFERS × IR_PACKETS × packet size. On macOS with a 33792-byte packet that is 4 × 128 × 33792 ≈ 17.3 MB; the Linux default 60 × 8 × 33792 works out to roughly the same total, split across many more in-flight transfers.
| Variable | Tunes |
|---|---|
| LIBFREENECT2_RGB_TRANSFERS | Number of bulk transfers in the color pool |
| LIBFREENECT2_RGB_TRANSFER_SIZE | Bytes per color transfer |
| LIBFREENECT2_IR_TRANSFERS | Number of isochronous transfers in the depth pool |
| LIBFREENECT2_IR_PACKETS | Isochronous packets per depth transfer |
Each overrides its platform default at device open. Verify an override took effect by reading the log line back:
Reach for these only after ruling out topology, cabling, and link speed — those cause far more failures than pool sizing does, and no pool size compensates for two sensors on one controller.
Keep the product of transfers and packets in the same ballpark as the default unless you are deliberately trading memory for jitter tolerance, and change one variable at a time.
These are enforced below libfreenect2, so exceeding them fails the transfer submission outright rather than degrading performance:
| Limit | Value | Enforced by |
|---|---|---|
| Isochronous packets per transfer | 128 | Linux usb/core/devio.c, returns -EINVAL |
| Bytes per isochronous packet | 49152 | Linux, same path (1024 × 16 × 3) |
| Frames per isochronous transfer | 1000 | macOS AppleUSBXHCI::UIMCreateIsochTransfer |
| Total pinned transfer memory | usbfs_memory_mb | Linux, returns -ENOMEM (see below) |
LIBFREENECT2_IR_PACKETS above 128 therefore cannot work on Linux — which is also why the macOS default of 128 is exactly at the ceiling. libusb additionally splits a submission into multiple URBs once num_iso_packets × packet_length exceeds 6 MB.
The kernel caps how much memory a process may pin for USB transfers. The default is often too low for even one Kinect, and definitely too low for several. Check and raise the current limit:
That change does not survive a reboot. To persist it, add usbcore.usbfs_memory_mb=1000 to the kernel command line, or set options usbcore usbfs_memory_mb=1000 in a file under /etc/modprobe.d/.
Symptoms of an insufficient limit are transfer submission failures at start, often reported as -ENOMEM in dmesg. This limit does not exist on macOS or Windows.
Linux may suspend an idle USB device, which the Kinect does not tolerate well mid-session. Scope any change to the sensor rather than disabling autosuspend globally — the blanket echo -1 over every device in /sys/bus/usb/devices/* that circulates online also affects keyboards, storage, and anything else attached.
Find the Kinect's device path and disable autosuspend for that node only:
To reverse it, write auto back to the same file, or simply replug the sensor — the setting does not persist across reconnects unless a udev rule applies it.
Two suggestions that circulate for Kinect v2 USB problems have system-wide effects well beyond this driver, and should be a last resort with a recorded reversal step:
Prefer fixing topology, link speed, and the usbfs limit first. If you do apply either of the above, note it in any bug report — it changes the baseline your results are measured against.