IPC详细参数如下:
- 闪烁控制:50HZ,60HZ
- 拍照格式:Bmp,jpg.
- 传感器格式:CMOS
- 支持Netmeeting等各种视频会议软件
- 180M/bmp告诉处理器
- 接口类型:USB2.0
- 内置:吸音降噪麦克风
- 分辨率:1920x1080/1280x720
USB描述符信息:
Descriptor:
caozilong@caozilong-Vostro-3268:~$ lsusb -d 0c45:64ab -v
Bus 001 Device 011: ID 0c45:64ab Microdia
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.01
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2 ?
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0x0c45 Microdia
idProduct 0x64ab
bcdDevice 10.12
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 389
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 14 Video
bFunctionSubClass 3 Video Interface Collection
bFunctionProtocol 0
iFunction 4
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 1 Video Control
bInterfaceProtocol 0
iInterface 4
VideoControl Interface Descriptor:
bLength 13
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdUVC 1.00
wTotalLength 109
dwClockFrequency 48.000000MHz
bInCollection 1
baInterfaceNr( 0) 1
VideoControl Interface Descriptor:
bLength 18
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1
wTerminalType 0x0201 Camera Sensor
bAssocTerminal 0
iTerminal 0
wObjectiveFocalLengthMin 0
wObjectiveFocalLengthMax 0
wOcularFocalLength 0
bControlSize 3
bmControls 0x0000000e
Auto-Exposure Mode
Auto-Exposure Priority
Exposure Time (Absolute)
VideoControl Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 5 (PROCESSING_UNIT)
Warning: Descriptor too short
bUnitID 2
bSourceID 1
wMaxMultiplier 16384
bControlSize 2
bmControls 0x0000177f
Brightness
Contrast
Hue
Saturation
Sharpness
Gamma
White Balance Temperature
Backlight Compensation
Gain
Power Line Frequency
White Balance Temperature, Auto
iProcessing 0
bmVideoStandards 0x1d
None
PAL - 625/50
SECAM - 625/50
NTSC - 625/50
VideoControl Interface Descriptor:
bLength 29
bDescriptorType 36
bDescriptorSubtype 6 (EXTENSION_UNIT)
bUnitID 3
guidExtensionCode {7033f028-1163-2e4a-ba2c-6890eb334016}
bNumControl 4
bNrPins 1
baSourceID( 0) 2
bControlSize 4
bmControls( 0) 0x0f
bmControls( 1) 0x00
bmControls( 2) 0x00
bmControls( 3) 0x00
iExtension 0
VideoControl Interface Descriptor:
bLength 29
bDescriptorType 36
bDescriptorSubtype 6 (EXTENSION_UNIT)
bUnitID 4
guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d221d}
bNumControl 20
bNrPins 1
baSourceID( 0) 3
bControlSize 4
bmControls( 0) 0xff
bmControls( 1) 0xff
bmControls( 2) 0x71
bmControls( 3) 0x00
iExtension 0
VideoControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 5
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 4
iTerminal 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 8
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 0
iInterface 0
VideoStreaming Interface Descriptor:
bLength 15
bDescriptorType 36
bDescriptorSubtype 1 (INPUT_HEADER)
bNumFormats 2
wTotalLength 185
bEndPointAddress 129
bmInfo 0
bTerminalLink 5
bStillCaptureMethod 1
bTriggerSupport 1
bTriggerUsage 0
bControlSize 1
bmaControls( 0) 11
bmaControls( 1) 11
VideoStreaming Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 6 (FORMAT_MJPEG)
bFormatIndex 1
bNumFrameDescriptors 2
bFlags 1
Fixed-size samples: Yes
bDefaultFrameIndex 1
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 1 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
VideoStreaming Interface Descriptor:
bLength 30
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 1280
wHeight 720
dwMinBitRate 368640000
dwMaxBitRate 368640000
dwMaxVideoFrameBufferSize 1843200
dwDefaultFrameInterval 400000
bFrameIntervalType 1
dwFrameInterval( 0) 400000
VideoStreaming Interface Descriptor:
bLength 30
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 2
bmCapabilities 0x00
Still image unsupported
wWidth 640
wHeight 480
dwMinBitRate 122880000
dwMaxBitRate 122880000
dwMaxVideoFrameBufferSize 614400
dwDefaultFrameInterval 400000
bFrameIntervalType 1
dwFrameInterval( 0) 400000
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
VideoStreaming Interface Descriptor:
bLength 27
bDescriptorType 36
bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED)
bFormatIndex 2
bNumFrameDescriptors 2
guidFormat {59555932-0000-1000-8000-00aa00389b71}
bBitsPerPixel 16
bDefaultFrameIndex 1
bAspectRatioX 0
bAspectRatioY 0
bmInterlaceFlags 0x00
Interlaced stream or variable: No
Fields per frame: 2 fields
Field 1 first: No
Field pattern: Field 1 only
bCopyProtect 0
VideoStreaming Interface Descriptor:
bLength 30
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 1
bmCapabilities 0x01
Still image supported
wWidth 1280
wHeight 720
dwMinBitRate 147456000
dwMaxBitRate 147456000
dwMaxVideoFrameBufferSize 1843200
dwDefaultFrameInterval 1000000
bFrameIntervalType 1
dwFrameInterval( 0) 1000000
VideoStreaming Interface Descriptor:
bLength 30
bDescriptorType 36
bDescriptorSubtype 5 (FRAME_UNCOMPRESSED)
bFrameIndex 2
bmCapabilities 0x01
Still image supported
wWidth 640
wHeight 480
dwMinBitRate 98304000
dwMaxBitRate 98304000
dwMaxVideoFrameBufferSize 614400
dwDefaultFrameInterval 500000
bFrameIntervalType 1
dwFrameInterval( 0) 500000
VideoStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 13 (COLORFORMAT)
bColorPrimaries 1 (BT.709,sRGB)
bTransferCharacteristics 1 (BT.709)
bMatrixCoefficients 4 (SMPTE 170M (BT.601))
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x03fc 1x 1020 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 2
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x0bfc 2x 1020 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 3
bNumEndpoints 1
bInterfaceClass 14 Video
bInterfaceSubClass 2 Video Streaming
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x13fc 3x 1020 bytes
bInterval 1
caozilong@caozilong-Vostro-3268:~$
Camera支持信息:
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define CLEAR(x) memset(&(x), 0, sizeof(x))
char* dev_name;
int fd = -1;
int width = 640;
int height = 480;
FILE* f;
void errno_exit(const char *s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(-1);
}
int xioctl(int fh, int request, void *arg)
{
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
void close_device(void)
{
if (-1 == close(fd))
errno_exit("close");
fd = -1;
}
void open_device(void)
{
struct stat st;
if (-1 == stat(dev_name, &st)) {
fprintf(stderr, "Cannot identify '%s': %d, %s\n", dev_name, errno, strerror(errno));
exit(-1);
}
if (!S_ISCHR(st.st_mode)) {
fprintf(stderr, "%s is no devicen\n", dev_name);
exit(-1);
}
fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); // O_RDWR: required
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno));
exit(-1);
}
}
void get_fmt(void)
{
int ret;
struct v4l2_fmtdesc fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.index = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) == 0)
{
fmt.index++;
printf("{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n",
fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF, (fmt.pixelformat >> 16) & 0xFF,
(fmt.pixelformat >> 24) & 0xFF, fmt.description);
}
}
void get_input(void)
{
struct v4l2_input inp;
inp.index = 0;
while (ioctl (fd, VIDIOC_ENUMINPUT, &inp) == 0) {
printf("%s : std: 0x%llx\n", , inp.std);
inp.index++;
}
}
void set_input(void)
{
struct v4l2_input inp;
inp.index = 0;
if (ioctl (fd, VIDIOC_S_INPUT, &inp) < 0) {
printf("set input error.\n");
}
}
void get_cap(void)
{
struct v4l2_capability cap;
if (ioctl(fd,VIDIOC_QUERYCAP,&cap) < 0)
{
printf("get cap error.\n");
return;
}
else
{
printf("Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\n",\
cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&0XFF);
}
printf("Supported feature:\n");
if(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
{
printf(" Video Capture.\n");
}
if(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
{
printf(" Video Output.\n");
}
if(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
{
printf(" Capture MPlane.\n");
}
if(cap.capabilities & V4L2_CAP_STREAMING)
{
printf(" Streaming.\n");
}
if(cap.capabilities & V4L2_CAP_READWRITE)
{
printf(" readwrite.\n");
}
if(cap.capabilities & V4L2_CAP_DEVICE_CAPS)
{
printf(" device caps.\n");
}
if(cap.device_caps & V4L2_CAP_EXT_PIX_FORMAT)
{
printf(" ext pix format.\n");
}
return;
}
int main(void)
{
// reference: https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/capture.c.html
dev_name = "/dev/video0";
open_device();
get_fmt();
get_input();
set_input();
get_cap();
close_device();
return 0;
}
get capability 结果如下:
czl@czl-RedmiBook-14:~/new$ ./a.out
{ pixelformat = ''MJPG'', description = ''Motion-JPEG'' }
{ pixelformat = ''YUYV'', description = ''YUYV 4:2:2'' }
Camera 1 : std: 0x0
Driver Name:uvcvideo
Card Name:GENERAL WEBCAM: GENERAL WEBCAM
Bus info:usb-0000:00:14.0-1
Driver Version:4.15.18
Supported feature:
Video Capture.
Streaming.
device caps.
ext pix format.
czl@czl-RedmiBook-14:~/new$
获取分辨率信息:
void enum_picture_size(void)
{
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
struct v4l2_fmtdesc fmt_1;
struct v4l2_frmsizeenum frmsize;
struct v4l2_frmivalenum frmival;
fmt_1.index = 0;
fmt_1.type = type;
while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt_1) >= 0) {
printf("{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n",
fmt_1.pixelformat & 0xFF, (fmt_1.pixelformat >> 8) & 0xFF, (fmt_1.pixelformat >> 16) & 0xFF,
(fmt_1.pixelformat >> 24) & 0xFF, fmt_1.description);
frmsize.pixel_format = fmt_1.pixelformat;
frmsize.index = 0;
while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0){
if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE){
printf(" res: line:%d %dx%d\n",__LINE__, frmsize.discrete.width, frmsize.discrete.height);
}else if(frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE){
printf(" res: line:%d %dx%d\n",__LINE__, frmsize.discrete.width, frmsize.discrete.height);
}
frmsize.index++;
}
fmt_1.index++;
}
}
输出如下:
这和guvcview工具中显示的设置选项是一致的。
在摆弄摄像头的过程中一直有几个疑惑:
疑惑1.为何有两个video节点?
疑惑2.为何只有/dev/video0节点打开后可以正常抓图,而打开/dev/video1节点,在调用ioctl进行配置的时候会出现IOCTL 调用失败?内核返回-ENOTTY,报告针对设备的非法IOCTL调用。
问题1我已经找到问题答案了,在probe uvc设备的时候,根据uvc usb device的配置描述符,它有两个interface,在USB世界里,一个interface代表的是一个驱动功能。所以这里会出现两个设备节点。
那问题2是什么原因呢?为什么两个节点不对等呢?经过一番苦苦搜索,终于找到答案,其实从USB设备的描述符就可以看出来,两个interface是不对等的,一个代表设备流DMA的产生设备,另一个则是控制设备,并非是可以产生流的设备,反映在驱动中,两个设备是通过不同的路径调用进V4L2核心层的,一个是uvc_meta_register,另一个是uvc_register_video,不同的入口会传递给V4L2核心层不同的struct v4l2_file_operations和struct v4l2_ioctl_ops,进而决定了不同的功能。
[ 41.085019] uvcvideo: Found UVC 1.00 device Integrated Camera (0c45:64ab)
[ 41.103321] CPU: 3 PID: 31 Comm: kworker/3:0 Not tainted 5.4.129+ #22
[ 41.103322] Hardware name: Dell Inc. Vostro 3268/0TJYKK, BIOS 1.11.1 12/11/2018
[ 41.103325] Workqueue: usb_hub_wq hub_event
[ 41.103326] Call Trace:
[ 41.103330] dump_stack+0x6d/0x8b
[ 41.103334] uvc_register_video_device+0x5d/0x1b0 [uvcvideo]
[ 41.103335] uvc_probe+0x25e8/0x2a10 [uvcvideo]
[ 41.103337] usb_probe_interface+0x149/0x300
[ 41.103339] ? uvc_register_video_device+0x1b0/0x1b0 [uvcvideo]
[ 41.103340] ? usb_probe_interface+0x149/0x300
[ 41.103342] really_probe+0xf5/0x440
[ 41.103343] driver_probe_device+0x11b/0x130
[ 41.103344] __device_attach_driver+0x7b/0xe0
[ 41.103345] ? driver_allows_async_probing+0x60/0x60
[ 41.103347] bus_for_each_drv+0x6e/0xb0
[ 41.103348] __device_attach+0xe4/0x160
[ 41.103349] device_initial_probe+0x13/0x20
[ 41.103349] bus_probe_device+0x92/0xa0
[ 41.103351] device_add+0x402/0x690
[ 41.103352] ? _cond_resched+0x19/0x40
[ 41.103353] usb_set_configuration+0x3fd/0x8f0
[ 41.103355] ? kernfs_activate+0x78/0x80
[ 41.103357] generic_probe+0x2e/0x80
[ 41.103357] usb_probe_device+0x31/0x70
[ 41.103358] really_probe+0xf5/0x440
[ 41.103359] driver_probe_device+0x11b/0x130
[ 41.103360] __device_attach_driver+0x7b/0xe0
[ 41.103361] ? driver_allows_async_probing+0x60/0x60
[ 41.103362] bus_for_each_drv+0x6e/0xb0
[ 41.103363] __device_attach+0xe4/0x160
[ 41.103364] device_initial_probe+0x13/0x20
[ 41.103365] bus_probe_device+0x92/0xa0
[ 41.103366] device_add+0x402/0x690
[ 41.103368] ? add_device_randomness+0x9d/0x1c0
[ 41.103369] usb_new_device+0x218/0x4a0
[ 41.103370] hub_event+0x11b1/0x1760
[ 41.103373] process_one_work+0x20f/0x400
[ 41.103374] worker_thread+0x34/0x410
[ 41.103375] kthread+0x121/0x140
[ 41.103377] ? process_one_work+0x400/0x400
[ 41.103377] ? kthread_park+0x90/0x90
[ 41.103379] ret_from_fork+0x35/0x40
[ 41.103380] uvc_register_video_device line 2002, VFL_DIR_RX.
[ 41.103382] name Integrated Camera: Integrated C.determine_valid_ioctls line 546, is_vid 1, isvbi 0, is_radio 0, issdr 0, istec0, is rx1, istx 0.
[ 41.103383] determine_valid_ioctls line 710, valid sinput
[ 41.103385] determine_valid_ioctls line 749, vdev=0x000000006ae2f85d, &vdev->valid_ioctls =0x00000000a6ac5245, ioctls=0xc0000f01c6f8335 ops=0x0000000024f130d9.
[ 41.103464] CPU: 3 PID: 31 Comm: kworker/3:0 Not tainted 5.4.129+ #22
[ 41.103465] Hardware name: Dell Inc. Vostro 3268/0TJYKK, BIOS 1.11.1 12/11/2018
[ 41.103467] Workqueue: usb_hub_wq hub_event
[ 41.103467] Call Trace:
[ 41.103469] dump_stack+0x6d/0x8b
[ 41.103471] uvc_register_video_device+0x5d/0x1b0 [uvcvideo]
[ 41.103473] uvc_meta_register+0x46/0x50 [uvcvideo]
[ 41.103474] uvc_probe+0x25f9/0x2a10 [uvcvideo]
[ 41.103476] usb_probe_interface+0x149/0x300
[ 41.103478] ? uvc_register_video_device+0x1b0/0x1b0 [uvcvideo]
[ 41.103479] ? usb_probe_interface+0x149/0x300
[ 41.103480] really_probe+0xf5/0x440
[ 41.103481] driver_probe_device+0x11b/0x130
[ 41.103482] __device_attach_driver+0x7b/0xe0
[ 41.103482] ? driver_allows_async_probing+0x60/0x60
[ 41.103484] bus_for_each_drv+0x6e/0xb0
[ 41.103485] __device_attach+0xe4/0x160
[ 41.103486] device_initial_probe+0x13/0x20
[ 41.103487] bus_probe_device+0x92/0xa0
[ 41.103488] device_add+0x402/0x690
[ 41.103489] ? _cond_resched+0x19/0x40
[ 41.103490] usb_set_configuration+0x3fd/0x8f0
[ 41.103491] ? kernfs_activate+0x78/0x80
[ 41.103493] generic_probe+0x2e/0x80
[ 41.103494] usb_probe_device+0x31/0x70
[ 41.103495] really_probe+0xf5/0x440
[ 41.103496] driver_probe_device+0x11b/0x130
[ 41.103497] __device_attach_driver+0x7b/0xe0
[ 41.103513] ? driver_allows_async_probing+0x60/0x60
[ 41.103514] bus_for_each_drv+0x6e/0xb0
[ 41.103515] __device_attach+0xe4/0x160
[ 41.103516] device_initial_probe+0x13/0x20
[ 41.103516] bus_probe_device+0x92/0xa0
[ 41.103517] device_add+0x402/0x690
[ 41.103519] ? add_device_randomness+0x9d/0x1c0
[ 41.103520] usb_new_device+0x218/0x4a0
[ 41.103521] hub_event+0x11b1/0x1760
[ 41.103524] process_one_work+0x20f/0x400
[ 41.103525] worker_thread+0x34/0x410
[ 41.103526] kthread+0x121/0x140
[ 41.103527] ? process_one_work+0x400/0x400
[ 41.103528] ? kthread_park+0x90/0x90
[ 41.103529] ret_from_fork+0x35/0x40
[ 41.103530] uvc_register_video_device line 2002, VFL_DIR_RX.
测试1:既然/dev/video1不提供视频流服务,那么把它去掉,UVC还能工作吗?
编译后安装新的内核,发现确实只剩下VIDEO0节点了,这个时候UVC还工作吗?
经过实际测试,只有/dev/video0一个设备节点的情况下,仍然是可以工作的,而且效果设置功能没有受到影响。
需要说明的是,如下的错误打印不是由于去掉/dev/video1节点导致的,存在两个节点的正常情况下也会有这些错误打印输出,错误和去掉video1节点无关。
GUVCVIEW: version 2.0.5
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
V4L2_CORE: (UVCIOC_CTRL_MAP) Error: 没有那个文件或目录
通过命令行方式获取摄像头支持信息,安装V4L2-CTL工具
v4l2-ctl 是一个ELF格式的可执行程序:
czl@czl-RedmiBook-14:sudo apt install v4l-utils
czl@czl-RedmiBook-14:~/Workspace/mjpg-streamer$ which v4l2-ctl
/usr/bin/v4l2-ctl
czl@czl-RedmiBook-14:~/Workspace/mjpg-streamer$ file /usr/bin/v4l2-ctl
/usr/bin/v4l2-ctl: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/.2, for GNU/Linux 3.2.0, BuildID[sha1]=a3f7076c3c6c05c983aac57d3edddba24251b8c8, stripped
v4l2-ctl -d0 --list-formats-ext
caozilong@caozilong-Vostro-3268:~$ v4l2-ctl -d0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
Size: Discrete 1280x720
Interval: Discrete 0.040s (25.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.040s (25.000 fps)
Index : 1
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Size: Discrete 1280x720
Interval: Discrete 0.100s (10.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.050s (20.000 fps)
caozilong@caozilong-Vostro-3268:~$
过程中调用的IOCTL如下:
caozilong@caozilong-Vostro-3268:~$ strace -e trace=openat,ioctl,open v4l2-ctl -d0 --list-formats-ext
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/.8", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/dev/video0", O_RDWR) = 3
openat(AT_FDCWD, "/sys/dev/char/81:0/uevent", O_RDONLY) = 4
ioctl(3, VIDIOC_QUERYCAP, {driver="uvcvideo", card="Integrated Camera: Integrated C", bus_info="usb-0000:00:14.0-2", version=5.4.129, capabilities=V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_STREAMING|V4L2_CAP_DEVICE_CAPS|V4L2_CAP_EXT_PIX_FORMAT|V4L2_CAP_META_CAPTURE, device_caps=V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_STREAMING|V4L2_CAP_EXT_PIX_FORMAT}) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0482c0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffe6d0483b0) = -1 EINVAL (Invalid argument)
ioctl: VIDIOC_ENUM_FMT
ioctl(3, VIDIOC_ENUM_FMT, {index=0, type=V4L2_BUF_TYPE_VIDEO_CAPTURE, flags=V4L2_FMT_FLAG_COMPRESSED, description="Motion-JPEG", pixelformat=v4l2_fourcc('M', 'J', 'P', 'G')}) = 0
Index : 0
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=0, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), type=V4L2_FRMSIZE_TYPE_DISCRETE, discrete={width=1280, height=720}}) = 0
Size: Discrete 1280x720
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=0, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), width=1280, height=720, type=V4L2_FRMIVAL_TYPE_DISCRETE, discrete=1/25}) = 0
Interval: Discrete 0.040s (25.000 fps)
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=1, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), width=1280, height=720}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=1, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), type=V4L2_FRMSIZE_TYPE_DISCRETE, discrete={width=640, height=480}}) = 0
Size: Discrete 640x480
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=0, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), width=640, height=480, type=V4L2_FRMIVAL_TYPE_DISCRETE, discrete=1/25}) = 0
Interval: Discrete 0.040s (25.000 fps)
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=1, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G'), width=640, height=480}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=2, pixel_format=v4l2_fourcc('M', 'J', 'P', 'G')}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FMT, {index=1, type=V4L2_BUF_TYPE_VIDEO_CAPTURE, flags=0, description="YUYV 4:2:2", pixelformat=v4l2_fourcc('Y', 'U', 'Y', 'V')}) = 0
Index : 1
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=0, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), type=V4L2_FRMSIZE_TYPE_DISCRETE, discrete={width=1280, height=720}}) = 0
Size: Discrete 1280x720
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=0, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), width=1280, height=720, type=V4L2_FRMIVAL_TYPE_DISCRETE, discrete=1/10}) = 0
Interval: Discrete 0.100s (10.000 fps)
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=1, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), width=1280, height=720}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=1, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), type=V4L2_FRMSIZE_TYPE_DISCRETE, discrete={width=640, height=480}}) = 0
Size: Discrete 640x480
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=0, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), width=640, height=480, type=V4L2_FRMIVAL_TYPE_DISCRETE, discrete=1/20}) = 0
Interval: Discrete 0.050s (20.000 fps)
ioctl(3, VIDIOC_ENUM_FRAMEINTERVALS, {index=1, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V'), width=640, height=480}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FRAMESIZES, {index=2, pixel_format=v4l2_fourcc('Y', 'U', 'Y', 'V')}) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_ENUM_FMT, {index=2, type=V4L2_BUF_TYPE_VIDEO_CAPTURE}) = -1 EINVAL (Invalid argument)
+++ exited with 0 +++
caozilong@caozilong-Vostro-3268:~$
czl@czl-RedmiBook-14:~/Workspace/mjpg-streamer$ v4l2-ctl -D -d /dev/video0
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : GENERAL WEBCAM: GENERAL WEBCAM
Bus info : usb-0000:00:14.0-4
Driver version: 5.4.119
Capabilities : 0x84A00001
Video Capture
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
czl@czl-RedmiBook-14:~/Workspace/mjpg-streamer$ v4l2-ctl -D -d /dev/video1
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : GENERAL WEBCAM: GENERAL WEBCAM
Bus info : usb-0000:00:14.0-4
Driver version: 5.4.119
Capabilities : 0x84A00001
Video Capture
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04A00000
Metadata Capture
Streaming
Extended Pix Format
czl@czl-RedmiBook-14:~/Workspace/mjpg-streamer$
根据上面v4l2-ctl获取到的信息,两个节点显然是不相同的,/dev/video1是Metadata Capture, /dev/video0是video capture.,以下是谷歌到的一段解释,看来某位国外小哥曾经和我有同样的疑惑. :)
The userspace app has to check the output of an ioctl (VIDIOC_QUERYCAP). It has two capability flags there at the returned struct:
struct v4l2_capability {
...
__u32 capabilities;
__u32 device_caps;
...
};
Those are documented as:
* @capabilities: capabilities of the physical device as a whole
* @device_caps: capabilities accessed via this particular device (node)
In other words, applications need to check the device_caps, and not the capabilities. The two relevant caps here are:
#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 # bit 1
#define V4L2_CAP_META_CAPTURE 0x00800000 # bit 23
/dev/video0 has:
Device Caps : 0x04200001
E.g. bit 1 is set, so this has V4L2_CAP_VIDEO_CAPTURE.
/dev/video1 has:
Device Caps : 0x04A00000
This one has bit 23 set (and bit 1 reset), so it doesn't have capture. It has, instead, meta capture.
The applications need to check this in order to know what kind of buffer it will receive, as this should be used by the streaming ioctls: VIDIOC_REQBUFS, VIDIOC_QBUF, VIDIOC_DQBUF, ...
If the application sets the buffer type correctly, it won't fail.
On other words, for /dev/video1, it has to use V4L2_BUF_TYPE_META_CAPTURE.
For /dev/video0, it has to use V4L2_BUF_TYPE_VIDEO_CAPTURE.
Please notice that what /dev/video1 will return is a meta-data image, with could be used by 3A algorithms to improve the image quality.
V4L2 read control menus:
czl@czl-RedmiBook-14:~$ strace -e trace=ioctl v4l2-ctl -L
ioctl(3, VIDIOC_QUERYCAP, {driver="uvcvideo", card="GENERAL WEBCAM: GENERAL WEBCAM", bus_info="usb-0000:00:14.0-4", version=5.4.119, capabilities=V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_STREAMING|V4L2_CAP_DEVICE_CAPS|V4L2_CAP_EXT_PIX_FORMAT|V4L2_CAP_META_CAPTURE, device_caps=V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_STREAMING|V4L2_CAP_EXT_PIX_FORMAT}) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe7800) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = -1 EINVAL (Invalid argument)
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_G_CTRL, {id=V4L2_CID_BRIGHTNESS, value=16}) = 0
brightness 0x00980900 (int) : min=1 max=255 step=1 default=16 value=16
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_G_CTRL, {id=V4L2_CID_CONTRAST, value=16}) = 0
contrast 0x00980901 (int) : min=1 max=255 step=1 default=16 value=16
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_G_CTRL, {id=V4L2_CID_HUE, value=16}) = 0
hue 0x00980903 (int) : min=-128 max=127 step=1 default=16 value=16
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = 0
ioctl(3, VIDIOC_G_CTRL, {id=V4L2_CID_POWER_LINE_FREQUENCY, value=2}) = 0
power_line_frequency 0x00980918 (menu) : min=0 max=2 default=2 value=2
ioctl(3, VIDIOC_QUERYMENU, 0x7ffc60fe77e0) = 0
0: Disabled
ioctl(3, VIDIOC_QUERYMENU, 0x7ffc60fe77e0) = 0
1: 50 Hz
ioctl(3, VIDIOC_QUERYMENU, 0x7ffc60fe77e0) = 0
2: 60 Hz
ioctl(3, VIDIOC_QUERY_EXT_CTRL, 0x7ffc60fe78f0) = -1 EINVAL (Invalid argument)
+++ exited with 0 +++
czl@czl-RedmiBook-14:~$
AMCapSetup是另一款windows平台上的的摄像头工具,其界面如下所示:
另外,对于S_FMT的参数,要看设备的capability是否支持对应的功能,每一种功能对应一种结构的解释(union结构体),比如上图来说,Device Caps : 0x04200001表示支持streaming, capture, and extent,不支持overlay,所以设置overlay就可能会失败。caputure摄像头都会支持,所以可以设置pix.