USB媒体设备端口绑定(以海康会议摄像头为例)

Posted kidecr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USB媒体设备端口绑定(以海康会议摄像头为例)相关的知识,希望对你有一定的参考价值。

一.问题描述

        1. 连接摄像头时,因连接顺序不一样,导致系统给摄像头分配的设备名不一样。
        2. 运行雷达站代码时,由于未知原因,可能运行途中摄像头端口号改变,导致读不到图像。

二.查询设备

        1. 显示设备详细信息

//先用lsusb查询所有USB设备
-> % lsusb
Bus 002 Device 002: ID 114d:8589 Alpha Imaging Technology Corp. 
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 048d:c100 Integrated Technology Express, Inc. 
Bus 001 Device 003: ID 04ca:7070 Lite-On Technology Corp. 
Bus 001 Device 002: ID 1ea7:0064  
Bus 001 Device 005: ID 8087:0aaa Intel Corp. 
Bus 001 Device 007: ID 046d:c345 Logitech, Inc. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

//根据设备ID查看设备详细信息
-> % lsusb -d 114d:8589 -v
Bus 002 Device 002: ID 114d:8589 Alpha Imaging Technology Corp. 
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               3.10
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 ?
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0         9
  idVendor           0x114d Alpha Imaging Technology Corp.
  idProduct          0x8589 
  bcdDevice           14.00
  iManufacturer           1 
  iProduct                2 
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
  ...

        2. 显示设备USB信息

        使用udevadm命令,如果没有请apt安装udev
        执行:udevadm info --name=设备名 --attribute-walk

-> % udevadm info --name=/dev/video2 --attribute-walk 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4:1.0/video4linux/video2':
    KERNEL=="video2"
    SUBSYSTEM=="video4linux"
    DRIVER==""
    ATTRdev_debug=="0"
    ATTRindex=="0"
    ATTRname=="DS-2CS54U0B-SD"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4:1.0':
    KERNELS=="2-4:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="uvcvideo"
    ATTRSauthorized=="1"
    ATTRSbAlternateSetting==" 0"
    ATTRSbInterfaceClass=="0e"
    ATTRSbInterfaceNumber=="00"
    ATTRSbInterfaceProtocol=="00"
    ATTRSbInterfaceSubClass=="01"
    ATTRSbNumEndpoints=="01"
    ATTRSiad_bFirstInterface=="00"
    ATTRSiad_bFunctionClass=="0e"
    ATTRSiad_bFunctionProtocol=="00"
    ATTRSiad_bFunctionSubClass=="03"
    ATTRSiad_bInterfaceCount=="02"
    ATTRSsupports_autosuspend=="1"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-4':
    KERNELS=="2-4"

 三.绑定端口

        打开/etc/udev/rules.d,在里面新建一个.rules文件,向里面添加绑定规则。

-> % cd /etc/udev/rules.d
-> % sudo touch HK_video.rules
-> % sudo vim HK_video.rules

         向文件中写入绑定规则

# link HK video to static devname video4 
SUBSYSTEM=="video4linux", ATTRname=="DS-2CS54U0B-SD", ATTRdev_debug=="0", ATTRindex=="0", MODE:="0666", SYMLINK+="video4" 


# SUBSYSTEM: 查找层级,和udevadm命令查询得到的一样,一下信息必须和SUBSYSTEM在一个层级。
# ATTR的3条为查找条件,用这些信息确定你想要的设备,所以请保证以下信息能确定唯一设备
# MODE这个不知道是啥
# SYMLINK+="你要新命名的设备名“
# 规则必须写在同一行,换行不会生效,采用换行符号'\\'也没有用

        查找规则必须和SUBSYSTEM在同一层,比如
        指定SUBSYSTEM=="video4linux"时,规则必须在下图中的部分

        指定SUBSYSTEM=="usb"时,则规则必须在下图中的部分

 四.生效

        使用以下命令使配置生效

sudo udevadm control --reload-rules
sudo udevadm trigger

Linux笔记(固定USB摄像头硬件端口,绑定前后置摄像头)

在Android的系统会有前置摄像头和后置摄像头的定义,摄像头分为SOC类型的摄像头和USB这一类的摄像头,接下要分析就是USB摄像头这一类 。

一般在android或者linux系统中分析一个模块,先从总体的框架上有一个认识,然后在局部细细的研究。

 一、Android 摄像头总体架构

上面的框架,分析的比较粗糙,主要是一些自己看代码后总结下来的东西。以USB摄像为例,在插入的USB摄像头后,会生成/dev/video0这样的设备节点,而在硬件抽象层中,会去判断是否存在该设备节点,以提供给android系统层使用。再往上分析就是android部分的了,先暂时不分析。

二、Linux层中UVC摄像头注册流程

在USB子系统判断有UVC设备接入后,会去调用uvc_probe(代码位置:/driver/media/uvc/uvc_driver.c)来完成USB摄像头的创建,通过一步一步的分析,最终会走到v4L2框架中,创建摄像头的设备节点。

三、固定USB摄像头硬件端口

前面分析了这么多,都是为了接下来的做准备。

 现在客户那么使用我们的主板机器,其中会使用两个USB摄像头,一个作为前置摄像头用于人脸识别,一个用于后置摄像头,由于在安装时并不知道那个端口的摄像头先插入,那个后插入(设备节点中先接入的就会分配video0,而在android中一般定义video0为后置摄像头,video1为前置摄像头),就导致android系统层前后置摄像头混乱。

为了解决该问题,就需要在驱动中,将前后置摄像头和USB的硬件端口做一个绑定。

具体改法如下:

(1) 在/include/media/v4l2-dev.h的video_device结构体中添加变量portnum

struct video_device
     struct list_head    fh_list; /* List of struct v4l2_fh */
 
     int debug;            /* Activates debug level*/
+    int portnum;        /*usb hw port*/

(2)在/drivers/media/usb/uvc/uvc_driver.c的uvc_register_video函数中添加vdev->portnum = dev->udev->portnum;

static int uvc_register_video(struct uvc_device *dev,
...
     stream->vdev = vdev;
     video_set_drvdata(vdev, stream);
 
+    vdev->portnum = dev->udev->portnum;
     ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);

这里先将USB的portnum存下来,在创建设备节点的是否,就会根据该变量来区分硬件的上哪个USB是前置,哪个USB是后置了

 (3)在/drivers/media/v4l2-core/v4l2-dev.c的__video_register_device函数中,修改

 int __video_register_device(struct video_device *vdev, int type, int nr,
 ...
     /* Pick a device node number */
     mutex_lock(&videodev_lock);+    if(vdev->vfl_type == VFL_TYPE_GRABBER) {
+        if(4 == vdev->portnum) {
+            nr = 1;
+        }else {
+            nr = 0;
+        }
+    }else {
+        nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
+    }
+
     if (nr == minor_cnt)
         nr = devnode_find(vdev, 0, minor_cnt);
     if (nr == minor_cnt) {

注意:这里的“4 == vdev->portnum”是根据时机板子的端口上的,在调试的时候,可以先将portnum变量的值打印出来,就知道如何区分了。

 

以上是关于USB媒体设备端口绑定(以海康会议摄像头为例)的主要内容,如果未能解决你的问题,请参考以下文章

JavaCV音视频开发宝典:使用javacv读取GB28181海康大华平台和网络摄像头sdk回调视频码流并转码推流rtmp流媒体服务

Linux笔记(固定USB摄像头硬件端口,绑定前后置摄像头)

浏览器低延时播放RTSP安防摄像头/海康大华硬盘录像机/NVR/流媒体服务器硬件开发机设备失去授权如何解决?

海康大华安防网络摄像头OnvifRTSP网络无插件直播流媒体服务解决方案EasyNVR表单重复提交的优化方案

2K 12|20倍HDMISDiipUsb3.0全接口音视频同步输出会议摄像机

RTSP_ONVIF协议视频流媒体网页无插件直播服务器EasyNVR配置海康大华等安防摄像头通道地址的方法