|
| 1 | +--- |
| 2 | +title: MaixCAM MaixPy Video Streaming UVC Streaming / As a UVC camera to display custom image |
| 3 | +update: |
| 4 | + - date: 2024-12-20 |
| 5 | + author: taorye |
| 6 | + version: 1.0.0 |
| 7 | + content: 初版文档 |
| 8 | +--- |
| 9 | + |
| 10 | +## Introduction |
| 11 | + |
| 12 | +`MaixCAM` as a `UVC camera`, where `UVC` stands for `USB video(device) class`. |
| 13 | + |
| 14 | +Here, two methods are provided to display custom content: |
| 15 | + |
| 16 | +- Refresh the target image using the `show` method of `maix.uvc.UvcStreamer` (supports YUYV and MJPEG). |
| 17 | +- Refresh the target image by registering a custom image refresh callback function with `maix.uvc.UvcServer` (only supports MJPEG). Much more complex than the method above. |
| 18 | + |
| 19 | + |
| 20 | +## Example |
| 21 | + |
| 22 | +**First, you need to enable the `UVC` function in the `USB settings` section of the `Settings` app.** |
| 23 | + |
| 24 | +**Note:** |
| 25 | +Once the `UVC` function is enabled, due to Linux's implementation of the `UVC Gadget`, a user program is still required to handle `UVC` device events. |
| 26 | +Otherwise, the entire `USB` functionality will pause and wait, affecting other simultaneously enabled `Gadget` features like `Rndis` and `NCM`, which may cause network disconnection. |
| 27 | +Therefore, for users who also need other `USB` functionalities, it is recommended to use the `UvcStreamer` method when developing UVC display functionality based on `MaixPy`. |
| 28 | +Otherwise, ensure that the `MaixCAM` device has other network access methods, such as `WIFI`, to ensure proper development and debugging. |
| 29 | + |
| 30 | + |
| 31 | +### UvcStreamer |
| 32 | + |
| 33 | +This method does not affect normal USB functionality. The underlying principle is to split the task into two processes. The official implementation uses a `server` process to handle `UVC` device events and encapsulates an easy-to-use, unified image refresh interface `show(img)` for users. You can treat it as a simple `display` linear logic operation. |
| 34 | + |
| 35 | +**Reference example source code path:** |
| 36 | +`MaixPy/examples/vision/streaming/uvc_stream.py` |
| 37 | + |
| 38 | +### **Example Source (Usage Instructions):** |
| 39 | + |
| 40 | +1. **Initialize the UvcStreamer object** |
| 41 | + |
| 42 | +```python |
| 43 | +uvcs = uvc.UvcStreamer() |
| 44 | +``` |
| 45 | + |
| 46 | +- (Optional) Switch to MJPEG streaming mode (YUYV default) |
| 47 | + |
| 48 | +```python |
| 49 | +uvcs.use_mjpg(1) |
| 50 | +``` |
| 51 | + |
| 52 | +2. Refresh the image (automatically handles the format, medium performance loss for MJPEG, and high loss for YUYV) |
| 53 | + |
| 54 | +```python |
| 55 | +uvcs.show(img) |
| 56 | +``` |
| 57 | + |
| 58 | +### UvcServer |
| 59 | + |
| 60 | +This approach offers high performance with a single-process implementation, but USB functionality will only be available when the process is running. Therefore, when stopping this process, it's important to note that the enabled `Rndis` and `NCM` functionalities will temporarily become inactive, causing a network disconnection. |
| 61 | + |
| 62 | +**Reference example source code path:** |
| 63 | +`MaixPy/examples/vision/streaming/uvc_stream.py` |
| 64 | + |
| 65 | +**Also packaged as an app source code path:** |
| 66 | +`MaixCDK/projects/app_uvc_camera/main/src/main.cpp` |
| 67 | + |
| 68 | +### **Example Source (Usage Instructions):** |
| 69 | + |
| 70 | +1. **Initialize the UvcServer object (requires a callback function for image refresh)** |
| 71 | + |
| 72 | +A helper function `helper_fill_mjpg_image` is provided to assist in placing more general `Image` objects into the `UVC` buffer. |
| 73 | + |
| 74 | +```python |
| 75 | +cam = camera.Camera(640, 360, fps=60) # Manually set resolution |
| 76 | + # | 手动设置分辨率 |
| 77 | + |
| 78 | +def fill_mjpg_img_cb(buf, size): |
| 79 | + img = cam.read() |
| 80 | + return uvc.helper_fill_mjpg_image(buf, size, img) |
| 81 | + |
| 82 | +uvcs = uvc.UvcServer(fill_mjpg_img_cb) |
| 83 | +``` |
| 84 | +The reference implementation will `fill_mjpg_img_cb` only trigger a buffer refresh when it returns `0`. |
| 85 | +Therefore, it is recommended to use the helper function in the last line: |
| 86 | +`return uvc.helper_fill_mjpg_image(buf, size, img)` |
| 87 | + |
| 88 | +2. Start the UVC, which launches a background thread, non-blocking operation: |
| 89 | + |
| 90 | +```python |
| 91 | +uvcs.run() |
| 92 | +``` |
| 93 | + |
| 94 | +3. Stop the UVC when it's no longer needed. This will restore the background process from the `UvcStreamer` method implementation to ensure normal USB functionality. |
| 95 | + |
| 96 | +Currently, there is a **BUG** in the MaixPy framework where it forcibly terminates processes upon exit, preventing the functions after the `while not app.need_exit():` loop from being executed, meaning the `stop()` method may not run as expected. |
| 97 | +Therefore, for users who require **normal USB functionality**, it is recommended to switch to the `UvcStreamer` method or use the original C++ API from **MaixCDK**. |
| 98 | + |
| 99 | +**Reference example:** |
| 100 | +`MaixCDK/examples/uvc_demo/main/src/main.cpp` |
| 101 | + |
| 102 | +```python |
| 103 | +uvcs.stop() |
| 104 | +``` |
0 commit comments