# libuvc gives you raw UVC control, and the two transfer tuning options decide whether it streams at all

> A C library built on libusb that exposes the USB Video Class interface directly, so a developer can write a driver for a device the operating system does not support or talk to UVC hardware generically. The build is a plain CMake sequence, and the tuning knobs for queued transfers are where most integration problems show up.

**libuvc/libuvc** — a cross-platform library for USB video devices

- Repository: https://github.com/libuvc/libuvc
- Website: https://libuvc.github.io/
- Stars: 1,167 · Forks: 557
- Language: C
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/libuvc-libuvc

## The value is in bypassing the platform capture stack

libuvc is a cross platform library for USB video devices, built atop libusb. The README states the purpose directly: it enables fine grained control over USB video devices exporting the standard USB Video Class interface, which lets developers write drivers for previously unsupported devices, or just access UVC devices in a generic fashion.

Both halves of that sentence describe two different jobs. The first is writing a driver for a device the operating system does not support, which is the interesting one and the reason the library exists as a low level C component rather than a convenience wrapper. The second is generic access, which is the easier case and the one most people actually need.

The choice of libusb as the foundation is what makes this possible. libusb is a cross platform abstraction over the raw USB layer, so libuvc inherits its portability while staying close to the hardware. What you get is the UVC device class handled by the library, and the USB transfer mechanics handled by libusb, with your application in the middle deciding what to do with the frames.

The primary language is C, and the repository layout matches a mature C library rather than a project with a build system bolted on. There is a `src/` directory for the implementation, an `include/` directory for the public headers, a `test/` directory, a `cameras/` directory, and a `cmake/` directory with the CMake modules. The `libuvc.pc.in` template and `libuvcConfig.cmake` are the two halves of the installation story, a pkg-config file for consumers using the autotools convention and a CMake package config for consumers using CMake. The `doxygen.conf` at the root generates the API documentation, which is then published at libuvc.github.io, and that site is where the developer documentation lives.

There is also a `standard-units.yaml` at the root, which is the kind of file you only find in a project that cares about units, and a `changelog.txt` that predates the GitHub releases.

## Building it is a clone, a mkdir and cmake

The build instructions are short enough to state in full, which is unusual for a library of this kind and worth having.

The prerequisites are libusb and CMake, both installed. Then the build is four commands.

```bash
git clone https://github.com/libuvc/libuvc
cd libuvc
mkdir build
cd build
cmake ..
make && sudo make install
```

The out of tree build with a separate `build` directory is the recommended arrangement and the README notes that if you want to change the build configuration you can edit `CMakeCache.txt` in the build directory, or use a CMake GUI to make the desired changes.

Two optional targets are gated behind options. `BUILD_EXAMPLE` and `BUILD_TEST` enable the compilation of the `example` and `uvc_test` programs, and to use them you replace the `cmake ..` command with one that passes both flags.

```bash
cmake .. -DBUILD_TEST=ON -DBUILD_EXAMPLE=ON
```

Then you run `./example` and `./uvc_test` respectively, and the README notes that you need OpenCV to build the latter, for displaying the image. That OpenCV requirement is only for the test program, not for the library itself, which matters if you are building a minimal image.

The `sudo make install` is the one line to think about. Installing into the system prefix is the conventional approach for a C library with a pkg-config file, and on a container or a build agent it is usually fine. On a workstation it means the library joins your system library set, and the version you link against is whatever was there at build time unless you manage it with rpath or a toolchain file. A local install prefix with the environment pointing at it is the tidier arrangement for development.

## The transfer queue defaults are tuned for desktops, not phones

Two tuning options control how much data is queued for a stream, and they are left at their defaults when unset. Both defaults assume a desktop-class machine, and the failure mode is common enough that the README documents it.

`LIBUVC_PACKETS_PER_TRANSFER_MAX` has a default of 32 and is the maximum number of isochronous packets in one USB transfer. The documented symptom is that starting a stream fails with `submiturb failed, errno=12` with ENOMEM, and the README says this is as is common on Android, and the fix is to lower the value, for example to 8.

```bash
cmake .. -DLIBUVC_PACKETS_PER_TRANSFER_MAX=8
```

`LIBUVC_NUM_TRANSFER_BUFS` has a default of 100, and 20 on macOS, and is the number of transfers queued at once.

The mechanism behind the ENOMEM failure is worth understanding rather than memorising. Isochronous transfers are reserved in the kernel at submission time, and the memory for a large batch of them is allocated up front. On a phone, where the application is competing with everything else for memory, the reservation fails and the kernel reports it as an out of memory condition even though the process has plenty of memory available. Lowering the packet count per transfer reduces the size of each reservation and makes the stream start.

The macOS difference in the second default is the same kind of observation applied to a different platform, and the fact that the two defaults are not the same number tells you they were tuned empirically rather than picked.

For anyone deploying this on embedded hardware or a mobile device, these two options are the first thing to reach for when a stream will not start, and they are the first thing to check when the failure message mentions errno 12.

## What the library does not do for you

The scope is narrow and the omission is total: there is no image processing, no frame format conversion, no colour handling, no video encoding and no device enumeration convenience beyond the UVC class itself.

That is not criticism, it is the design. A UVC device negotiates a format, and the library handles that negotiation and the transfer of the resulting bytes. What you do with those bytes, whether you convert them to RGB, scale them, encode them or feed them to a computer vision pipeline, is application work.

The consequence for an integrator is that a working libuvc program still has a long way to go before it displays a picture. The test program in the repository uses OpenCV for exactly that reason, and the example program exists to show the device side of it. A team coming from a high level capture API will find that the hard part is not the USB traffic, which the library handles, but everything that sits above it.

The other boundary worth naming is the driver situation. libuvc is the lower layer, and the operating system may also have its own UVC driver loaded for the same device. On Linux, a kernel UVC driver and a libusb based user space stack can both try to claim the interface, and the result is that one of them fails to open the device. Working around that means detaching the kernel driver or ensuring it is not loaded, which is a platform detail the library does not abstract away.

The `cameras/` directory in the repository is suggestive here, since it implies per device handling, and the README's framing of writing drivers for previously unsupported devices tells you the library expects you to deal with the specifics of a particular camera.

## Licence, releases and the state of a long running C library

The licence is one that GitHub could not classify from the repository metadata, so the authoritative text is in the `LICENSE.txt` file at the root. For a library that sits underneath other people's applications, that file is the thing to read before you commit, and it is worth reading rather than assuming it matches a permissive grant you have seen elsewhere.

The release history is thin in a way that is typical of a C library that has been around for a long time. There is a single GitHub release, v0.0.8 from 2026-09-13, and the repository also carries a `changelog.txt` at the root, which suggests the project has kept its changelog outside the release system for most of its life.

The last push to the repository was on 2026-10-01, three weeks before that release, and the repository is not archived. So the project is maintained, and the version numbering tells you something about how it is managed. A v0.0.8 that is still being released in 2026 after a long history means the maintainers use the version number conservatively, which is a pattern you often see in libraries where the public API is considered stable enough that a major version change would be more disruptive than useful.

For a consumer, the practical implications are the same as for any long lived C library. The API changes slowly, which is good. The build is plain CMake, which is good. And the documentation lives on a separate site rather than in the repository, so the Doxygen configuration in the repository is what generates the API reference you will actually read.

## Conclusion

Adopt libuvc if you need direct control of a UVC camera, especially one your operating system does not have a driver for, and you are prepared to work at the USB transfer level. Do not adopt it if you only need to capture frames from a camera that already works, because the platform's own capture stack will save you a lot of low level work. Verify first that your device exposes a standard UVC interface, that your libusb installation supports the platform you are on, and that the transfer queue settings are configured for the machine you will run on, since the defaults are tuned for desktops and are known to fail on Android.

## FAQ

### What is libuvc and what does it do?

libuvc is a cross platform C library for USB video devices, built on top of libusb. It gives fine grained control over devices exporting the standard USB Video Class interface, so you can write drivers for previously unsupported devices or access UVC devices generically.

### How do I build and install libuvc?

You need libusb and CMake installed. Clone the repository, create a build directory, run cmake .. there, then make && sudo make install. You can edit CMakeCache.txt in the build directory or use a CMake GUI to change the configuration.

### How do I build the libuvc example and test programs?

Pass -DBUILD_TEST=ON -DBUILD_EXAMPLE=ON to cmake instead of a plain cmake .., then run ./example and ./uvc_test. You need OpenCV installed to build the test program, for displaying the image.

### My libuvc stream fails to start with submiturb failed, errno=12, what should I change?

Lower LIBUVC_PACKETS_PER_TRANSFER_MAX, which defaults to 32, for example to 8 with cmake .. -DLIBUVC_PACKETS_PER_TRANSFER_MAX=8. The README notes this ENOMEM failure is common on Android. LIBUVC_NUM_TRANSFER_BUFS, default 100 and 20 on macOS, controls how many transfers are queued at once.

### Where can I find the libuvc documentation and licence?

The developer documentation is published at libuvc.github.io, generated from the doxygen.conf in the repository. The licence text is in the LICENSE.txt file at the repository root, since GitHub could not classify the licence from the repository metadata.

## Sources

- [Issues](https://github.com/libuvc/libuvc/issues)
- [libuvc/libuvc on GitHub](https://github.com/libuvc/libuvc)
- [Project website](https://libuvc.github.io/)
- [README](https://github.com/libuvc/libuvc/blob/master/README.md)
- [Releases](https://github.com/libuvc/libuvc/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/libuvc-libuvc
