问题定位:USB 带宽不足导致 VIDIOC_STREAMON failed: No space left on device
这个错误不是设备节点分配问题,而是USB 带宽不足。RDK X5/X3 的 USB 口通过一个 USB 3.0 Hub 分出,默认情况下第一个摄像头会占满带宽,导致第二个摄像头无法启动。
解决方案:限制 uvcvideo 带宽
步骤1:加载 uvcvideo 模块并限制带宽
# 卸载现有模块
sudo rmmod uvcvideo
# 重新加载并设置 quirks=128(限制带宽)
sudo modprobe uvcvideo quirks=128
参数说明:
quirks=128会限制每个 UVC 设备的带宽占用,允许多设备共享 USB 总线
步骤2:验证模块加载
# 查看模块是否加载成功
lsmod | grep uvcvideo
# 查看模块参数
cat /sys/module/uvcvideo/parameters/quirks
预期输出:128
步骤3:设置开机自动生效(可选)
# 创建模块配置文件
sudo vim /etc/modprobe.d/uvcvideo.conf
写入内容:
options uvcvideo quirks=128
步骤4:降低摄像头分辨率/格式(关键!)
即使设置了 quirks=128,如果两路摄像头总带宽超过 USB 3.0 上限,仍会报错。推荐配置:
| 分辨率 | 格式 | 帧率 | 单路带宽估算 | 双路是否可行 |
|---|---|---|---|---|
| 640x480 | MJPEG | 30fps | ~15MB/s | |
| 1280x720 | MJPEG | 30fps | ~30MB/s | |
| 1920x1080 | MJPEG | 30fps | ~60MB/s | |
| 640x480 | YUYV | 30fps | ~30MB/s |
测试命令:
# 查看摄像头支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext
# 设置摄像头为 MJPEG 格式 720p
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG
步骤5:代码中指定格式和分辨率
import cv2
cap1 = cv2.VideoCapture('/dev/video_CAM1')
cap2 = cv2.VideoCapture('/dev/video_CAM2')
# 强制设置格式和分辨率(关键!)
cap1.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap1.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap1.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap1.set(cv2.CAP_PROP_FPS, 30)
cap2.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap2.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap2.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap2.set(cv2.CAP_PROP_FPS, 30)
# 测试读取
ret1, frame1 = cap1.read()
ret2, frame2 = cap2.read()
print(f"Cam1: {ret1}, Cam2: {ret2}")
步骤6:验证带宽使用情况
# 查看 USB 拓扑和带宽分配
lsusb -t
# 查看内核日志中是否有带宽相关报错
dmesg | grep -i "uvc\|bandwidth\|usb"
完整操作速查表
| 步骤 | 命令 | 说明 |
|---|---|---|
| 限制带宽 | sudo rmmod uvcvideo && sudo modprobe uvcvideo quirks=128 |
必须执行 |
| 验证参数 | cat /sys/module/uvcvideo/parameters/quirks |
确认值为 128 |
| 开机生效 | echo "options uvcvideo quirks=128" | sudo tee /etc/modprobe.d/uvcvideo.conf |
可选 |
| 查看格式 | v4l2-ctl -d /dev/video0 --list-formats-ext |
确认为 MJPEG |
| 设置格式 | v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG |
推荐 720p MJPEG |
| 测试读取 | Python OpenCV 代码 | 同时读取两路 |
注意事项
- 必须使用 MJPEG 格式:YUYV/NV12 等未压缩格式带宽占用太大
- 分辨率不要超过 720p:双路 1080p 必超限
- USB 口尽量分开:如果有多个 USB 控制器,分散连接
- MIPI + USB 组合:如果一个用 MIPI 接口,一个用 USB,不会有带宽冲突
如果仍然失败
请提供以下信息:
# 1. 当前 uvcvideo 参数
cat /sys/module/uvcvideo/parameters/quirks
# 2. 摄像头支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext
v4l2-ctl -d /dev/video1 --list-formats-ext
# 3. USB 拓扑
lsusb -t
# 4. 内核日志
dmesg | tail -100
把报错信息和以上输出发出来,我帮你进一步分析!
相关帖子参考: