# UVC Camera Guide

## Overview

This article describes how to use the uvc-gadget demo, including how to configure the K230 Linux device as a UVC Gadget (USB camera), and how to view real-time video streams via USB on a PC.

## Feature Demonstration

### Hardware Connection

```text
+---------+         +---------+
|  K230   |---USB---|  PC     |
|  Linux  |         | (Host)  |
+---------+         +---------+
    |
    | UART
    |
+---------+
|  PC     |
| (Serial |
|  Debug) |
+---------+
```

### Starting uvc-gadget on K230

Run the following command on the K230 Linux command line to start uvc-gadget:

```bash
# Start the uvc-gadget service
/root/app/uvc-gadget/uvc-gadget.sh start

# Or run the uvc-gadget program directly
uvc-gadget -v /dev/video1
```

> **Tip**: Use the `v4l2-ctl --list-devices` command to confirm the camera device, which is generally `/dev/video1`.

### Viewing Video on PC

1. Open a video application on the PC (such as PotPlayer, OBS, Cheese, etc.)
1. Select the corresponding camera device for K230
1. Set the video format to **MJPEG 1080p**
1. Open the camera to view the video stream

![PC Settings Diagram](https://www.kendryte.com/api/post/attachment?id=868)
![PC Settings Diagram](https://www.kendryte.com/api/post/attachment?id=867)

![Open Camera](https://www.kendryte.com/api/post/attachment?id=869)
![Video Preview](https://www.kendryte.com/api/post/attachment?id=870)

> **Note**: The video stream latency is approximately 220ms.

---

## Implementation Explanation

### Configuration Instructions

The `BR2_PACKAGE_UVC_GADGET` needs to be enabled in the Buildroot configuration:

```bash
# buildroot-overlay/package/uvc-gadget/Config.in
config BR2_PACKAGE_UVC_GADGET
    bool "uvc-gadget"
    select BR2_PACKAGE_LIBV4L
```

If the `uvc-gadget` program is not found, please make sure the above configuration is enabled.

---

### uvc-gadget.sh Script Description

**Script Location**: `buildroot-overlay/package/uvc-gadget/uvc-gadget.sh`

This script is used to configure the device as a USB camera device in an embedded Linux system.

#### Main Functions

| Function              | Description                                                                                                              |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `create_frame()`      | Creates video frame configuration, supporting three formats (uncompressed/YUYV, MJPEG) and three resolutions (360p, 720p, 1080p) |
| `start_uvc_gadget()`  | Starts the UVC device, loads kernel modules, mounts configfs, and creates the USB Gadget configuration                 |
| `stop_uvc_gadget()`   | Stops the UVC device, terminates processes, unbinds the UDC, and unloads kernel modules                                  |

#### Usage

```bash
./uvc-gadget.sh start    # Start the UVC device
./uvc-gadget.sh stop     # Stop the UVC device
./uvc-gadget.sh restart  # Restart the UVC device
```

#### Core Configuration

- **USB ID**: Vendor ID: `0x29f1`, Product ID: `0x0104`
- **Vendor Information**: Canaan
- **USB Controller**: `91500000.usb`

---

### uvc-gadget Program Description

K230's uvc-gadget is based on the [uvc-gadget](https://gitlab.freedesktop.org/camera/uvc-gadget.git) open-source project, with added support for K230 VPU hardware encoding.

**Code location**: `buildroot-overlay/package/uvc-gadget/`

#### Data Flow

```text
Camera (V4L2) → FFmpeg → VPU Encoder → Packet Queue → UVC Streamer → USB Host
```

1. **Camera Capture**: Read raw frames from the V4L2 device via `libavformat`
1. **Hardware Encoding**: Use the `mjpeg_v4l2m2m` encoder for VPU-accelerated encoding
1. **Packet Queue**: Encoded data is stored in a circular queue (default size 2-4)
1. **UVC Transfer**: Data is taken from the queue and written to the UVC sink buffer

#### Thread Model

| Thread   | Responsibilities                                       |
| -------- | ----------------------------------------------------- |
| Main     | Handles the UVC events loop, responding to sink buffer dequeue events |
| VPU      | Continuously captures camera data and feeds it to the encoder          |

Threads are synchronized via mutex + condition variable.

---

## References

- [uvc-gadget Open Source Project](https://gitlab.freedesktop.org/camera/uvc-gadget.git)
- [Linux Kernel UVC Gadget Documentation](https://docs.kernel.org/usb/gadget_uvc.html)
