Перейти до основного вмісту

USB-камери

Камери USB Video Class (UVC), які виявляє через V4L2 провайдер camera.v4l2. Після кожної uevent video4linux виконується повторне сканування.

Провайдер обходить /sys/class/video4linux і залишає лише вузли, що мають предка USB, тож вузли платформи та ISP ніколи не відкриваються. Кожен кандидат відкривається з прапорцями O_RDONLY | O_NONBLOCK і отримує лише ioctl-запити (VIDIOC_QUERYCAP, VIDIOC_ENUM_FMT, VIDIOC_ENUM_FRAMESIZES, VIDIOC_ENUM_FRAMEINTERVALS). Вузли лише з метаданими, лише для виведення та типу memory-to-memory відкидаються після VIDIOC_QUERYCAP, тож UVC-камера з вузлом метаданих з’являється один раз.

Ідентифікація​

id — це camera:v4l2:<16 hex digits>, хеш FNV-1a від identity.stable_key (sysfs:<USB topology>:interface=<bInterfaceNumber>:index=<node index>). Він не змінюється після повторного підключення до того самого порту та перенумерації /dev/videoN. Інший порт означає іншу камеру, а однакові камери в різних портах мають різні id.

identity.camera_name, наявний для вузлів драйвера uvcvideo, — це ім'я, за яким UsbCameraInput у Neat відкриває камеру (UsbCameraInputOptions::camera_name). Його побудовано так само, як його будує Neat слідом за libcamera: вузол прошивки USB-пристрою або його найближчого предка з вузлом прошивки (шлях у дереві пристроїв під /sys/firmware/devicetree, інакше його ACPI-шлях firmware_node/path), ім'я інтерфейсу без номера шини та idVendor:idProduct, наприклад /base/pci@7000000000-3.1:1.0-1a2b:3c4d. Його пропущено, якщо будь-яку частину не вдається прочитати.

Поля​

ПолеНаявністьЗначення
typeзавждиcamera
idзавждиДив. вище
backendзавждиv4l2 (USB-камера)
modelякщо відомоРядок USB product, інакше назва картки (card) драйвера
device_pathзавжди/dev/videoN; лише для маршрутизації, не для ідентифікації
by_id_pathза наявності посилання udevПосилання /dev/v4l/by-id/..., яке вказує на device_path
identityзавждиstable_key, topology, interface, node_index і, якщо USB-пристрій їх повідомляє, vendor_id, product_id, serial, manufacturer та speed (швидкість із sysfs у Мбіт/с у тому вигляді, як її виводить ядро, наприклад "480"); driver — драйвер ядра, прив'язаний до USB-інтерфейсу вузла (наприклад, uvcvideo), якщо такий є; camera_name (див. вище)
availabilityзавжди{"state": "unknown", "reason": ...}: виявлення ніколи не відкриває потік, тому не може визначити, чи використовується камера
modesзавждиЩо камера може виводити; див. нижче

Режими​

Один режим на кожну комбінацію формату й розміру кадру, відсортовані за форматом, а потім за розміром. Одноплощинні та багатоплощинні переліки одного формату об’єднуються.

ПолеНаявністьЗначення
formatзавждиV4L2 FourCC, наприклад MJPG, YUYV, NV12
format_descriptionякщо драйвер його надаєОпис із VIDIOC_ENUM_FMT, наприклад Motion-JPEG
width, heightдискретні розміриРозмір кадру
size_rangeступінчасті або неперервні розміриtype (stepwise або continuous), min_width, min_height, max_width, max_height, step_width, step_height
frame_intervalsзавждиДля кожного опитаного розміру (width, height) — кожен інтервал, який оголошує пристрій: {"type": "discrete", "numerator", "denominator"} або {"type": "stepwise" or "continuous", "minimum", "maximum", "step"}

Діапазон розмірів опитується за його мінімальним і максимальним розміром. Розмір без інтервалів кадрів не має режиму. Кожен режим також має available і, якщо воно false, reason (див. каталог). UsbCameraInput у Neat відкриває камеру uvcvideo за її camera_name і захоплює MJPEG із розмірами та інтервалами кадрів, які перелічує камера, тож режим MJPG такої камери доступний, якщо його не перелічує раніший вузол камери (див. нижче). Інші формати недоступні, як і кожен режим камери з іншим драйвером. Режими MJPG камери uvcvideo без camera_name недоступні, бо UsbCameraInput не може її відкрити; режими вузла без driver, інтерфейс якого під час сканування прив'язувався або відв'язувався, не мають рішення.

Камера з кількома інтерфейсами потокового передавання має кілька вузлів захоплення на своєму інтерфейсі VideoControl, і вони мають спільне camera_name; пристрій із кількома інтерфейсами VideoControl має camera_name для кожного з них. UsbCameraInput пробує вузли камери за шляхом пристрою, коротші першими (/dev/video2 перед /dev/video10), і відкриває перший, який перелічує запитані розмір і частоту MJPEG: дискретний інтервал — точно, діапазон — у його межах. Тому режим MJPG недоступний, коли раніші вузли камери перелічують його розмір для кожного з його інтервалів кадрів, і не має рішення, коли лише для деяких.

Обмеження та помилки​

Будь-який збій спричиняє невдачу сканування провайдера, про що повідомляється в полі errors каталогу:

  • io.permission_denied: EACCES від вузла або sysfs, або EPERM під час відкриття вузла.
  • io.open: будь-яка інша помилка драйвера або sysfs; список, довший за 1024 елементи; понад 4096 запитів переліку для одного пристрою; некоректний розмір або інтервал.
  • peripherals.discovery_failed: USB-камера без номера інтерфейсу або індексу вузла.

Камеру, від’єднану під час сканування, буде пропущено, а не зараховано як збій сканування, — щонайпізніше під час повторного сканування, яке запускає її від’єднання.

Приклад​

Ілюстративний запис; топологію sysfs і шлях ACPI спрощено.

{"type": "camera", "id": "camera:v4l2:295faa7ac0d61654", "backend": "v4l2",
"model": "UVC Webcam", "device_path": "/dev/video97",
"by_id_path": "/dev/v4l/by-id/usb-1a2b_UVC_Webcam_A1B2-video-index0",
"identity": {"stable_key": "sysfs:devices/pci0000:00/usb1/1-2.3:interface=00:index=0",
"topology": "devices/pci0000:00/usb1/1-2.3", "interface": "00",
"node_index": "0", "vendor_id": "1a2b", "product_id": "3c4d",
"serial": "A1B2", "manufacturer": "Example Vendor", "speed": "480",
"driver": "uvcvideo", "camera_name": "\\_SB_.PCI0-2.3:1.0-1a2b:3c4d"},
"availability": {"state": "unknown", "reason": "V4L2 does not expose a reliable read-only ownership state; discovery does not acquire, configure, or stream from the camera."},
"modes": [{"format": "MJPG", "format_description": "Motion-JPEG",
"width": 1920, "height": 1080,
"frame_intervals": [{"width": 1920, "height": 1080, "intervals": [
{"type": "discrete", "numerator": 1, "denominator": 30}]}],
"available": true}]}