UVC摄像头批量传输的StreamOn和StreamOff
在UVC规范中,UVC摄像头视频数据的传输方式支持两种,分别为批量传输和同步传输。
UVC摄像头数据传输的格式按负载数据头的方式按帧进行打包传输。
根据USB规范可知,同步传输方式是只要带中带有同步端点的接口,系统会定时从设备中读取数据,无论设备中是否有数据。而如要要停止数据的传输,只需要选中不带有同步端点的接口即可。
USB同步传输这种灵活的数据传输方式是依靠视频流接口的转换接口即我们常说的备份接口实现的。在默认情况下数据不传输时,视频数据流接口和备份接口ID为0,其它的备份接口是可根据视频数据传输的大小可按需选择。当然一般的UVC摄像头只有一个视频流备份接口,该接口用于视频数据的传输时的应用。
但对于没有转换接口的批量传输即我们所说的BULK传输方式,是怎么样的呢?
为了弄清问题,本人对手中的一个使用批量传输方式的H264摄像头进行抓包分析,分别抓取摄像头的打开与关闭时的包。
打开摄像头StreamOn
Device Length Phase Data Description
------ -------- ----- ----------------------------------------------------------------
43.0 CTL a1 81 00 01 02 00 22 00 GET CUR
43.0 34 IN 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 20 00 00 00 00 00 00 03 01 00 01
43.0 CTL 21 01 00 01 02 00 22 00 SET CUR
43.0 34 OUT 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 00 00 00 00 00 00 00 03 01 00 01
43.0 CTL a1 81 00 01 02 00 22 00 GET CUR
43.0 34 IN 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 20 00 00 00 00 00 00 03 01 00 01
43.0 CTL a1 83 00 01 02 00 22 00 GET MAX
43.0 34 IN 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 20 00 00 00 00 00 00 03 01 00 01
43.0 CTL a1 82 00 01 02 00 22 00 GET MIN
43.0 34 IN 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 20 00 00 00 00 00 00 03 01 00 01
43.0 CTL 21 01 00 02 02 00 22 00 SET CUR
43.0 34 OUT 01 00 01 01 15 16 05 00 00 00 00 00 00 00 00 00
00 00 00 00 50 00 00 20 00 00 00 00 00 00 03 01 00 01
43.0 CTL 01 0b 00 00 02 00 00 00 SET INTERFACE
从抓包的过程可以看到,前面是常见打开UVC摄像头支持的视频格式信息的获取。该摄像头只支持一种数据格式,一种分辨率。数据协商完成后,使用视频流接口的VS_COMMIT_CONTROL选择子提交给设备,让其以指定的数据格式进行数据采样。提交完成后,紧跟着的是SET_INTERFACE请求,用于选择该接口进行数据传输。
关闭摄像头StreamOff
43.3 RESET
43.0 CTL 01 0b 00 00 02 00 00 00 SET INTERFACE
可以看到,先是视频数据流传输的端点3进行复位,接着是SET_INTERFACE请求请求。
从以上可以看到,无论UVC摄像头是按批量传输还是同步传输,都会进行有一个SET_INTERFACE。
关于SET_INTERFACE,在USB规范中定义的是对设备的接口选择,这样系统总线会返回该接口的USBD_INTERFACE_INFORMATION信息,该结构体中包含其端点的USBD_PIPE_INFORMATION。在Windows环境下,对于同一接口,每次选择同一接口都会返回不同的信息,这样导致上一次的信息失效(BAD FLAG INFORMATION).通过这这样也实现了类似同步转换接口的功能。
typedef struct _USBD_INTERFACE_INFORMATION {
USHORT Length;
UCHAR InterfaceNumber;
UCHAR AlternateSetting;
UCHAR Class;
UCHAR SubClass;
UCHAR Protocol;
UCHAR Reserved;
USBD_INTERFACE_HANDLE InterfaceHandle;
ULONG NumberOfPipes;
USBD_PIPE_INFORMATION Pipes[1];
} USBD_INTERFACE_INFORMATION, *PUSBD_INTERFACE_INFORMATION;