【genius_platform软件平台开发】第五十六讲:Linux系统之V4L2视频驱动-VIDIOC_QUERYCAP 查询设备能力代码详解

  • 1. 应用层代码
  • 2. 驱动层代码
    • 2.1 v4l_querycap函数
    • 2.2 vidioc_querycap函数

1. 应用层代码

函数使用: int ioctl(int fd, int request, struct v4l2_capability *argp);
struct v4l2_capability
{
	u8 driver[16]; // 驱动名字
	u8 card[32]; // 设备名字
	u8 bus_info[32]; // 设备在系统中的位置
	u32 version;// 驱动版本号
	u32 capabilities;// 设备支持的操作
	u32 reserved[4]; // 保留字段
};
  
struct v4l2_capability cap;  
ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);  
if (ret < 0) {  
    LOG("VIDIOC_QUERYCAP failed (%d)\n", ret);  
    return ret;  
}

capabilities 常用值:

V4L2_CAP_VIDEO_CAPTURE (是否支持图像获取)

struct v4l2_capability cap;
ioctl(fd,VIDIOC_QUERYCAP,&cap);
printf(“Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\n”,cap.driver,cap.card,cap.bus_info,cap.capabilities);

V4L2_BUF_TYPE_VIDEO_CAPTURE (获取设备支持的分辨率)

    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) {
      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("line:%d %dx%d\n",__LINE__, frmsize.discrete.width, frmsize.discrete.height);
				}else if(frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE){
 					printf("line:%d %dx%d\n",__LINE__, frmsize.discrete.width, frmsize.discrete.height);
			}
		frmsize.index++;
      }
      fmt_1.index++;
    }
  }

//------2------//
struct v4l2_capability cap;
 
memset(&cap, 0, sizeof(cap));
/* 获取设备支持的操作 */
if(ioctl(dev->fd, VIDIOC_QUERYCAP, &cap) < 0){
    if(EINVAL == errno){   /*EINVAL为返回的错误值*/
        printf(stderr,"%s is no V4L2 device\n", dev->dev);
        return TFAIL;
    }
    else
    {
        printf(stderr,"%s is not V4L2 device,unknow error\n", dev->dev);
        return TFAIL;
    }
}
//获取成功,检查是否有视频捕获功能
if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
    printf(stderr, "%s is no video capture device\n",dev->dev);
    return TFAIL;
}
/* streaming I/O ioctls */
if(!(cap.capabilities & V4L2_CAP_STREAMING)){
    printf(stderr, "%s does not support streaming i/o\n",dev->dev);
    return TFAIL;
}


2. 驱动层代码

2.1 v4l_querycap函数

static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
				struct file *file, void *fh, void *arg)
{
	struct v4l2_capability *cap = (struct v4l2_capability *)arg;
	struct video_device *vfd = video_devdata(file);
	int ret;

	cap->version = LINUX_VERSION_CODE;
	cap->device_caps = vfd->device_caps;
	cap->capabilities = vfd->device_caps | V4L2_CAP_DEVICE_CAPS;

	ret = ops->vidioc_querycap(file, fh, cap);

	cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
	/*
	 * Drivers MUST fill in device_caps, so check for this and
	 * warn if it was forgotten.
	 */
	WARN(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) ||
		!cap->device_caps, "Bad caps for driver %s, %x %x",
		cap->driver, cap->capabilities, cap->device_caps);
	cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;

	return ret;
}

2.2 vidioc_querycap函数

  • 对应走到不同设备的查询接口,拿一个来举例,比较简单
static int vidioc_querycap(struct file *file, void  *priv,
                                        struct v4l2_capability *vc)
{
        struct usb_usbvision *usbvision = video_drvdata(file);
        struct video_device *vdev = video_devdata(file);
		
		// 这里只是将一些信息写回用户空间而已,非常简单
        strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
        strlcpy(vc->card,
                usbvision_device_data[usbvision->dev_model].model_string,
                sizeof(vc->card));
        usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
        vc->device_caps = usbvision->have_tuner ? V4L2_CAP_TUNER : 0;
        if (vdev->vfl_type == VFL_TYPE_GRABBER)
                vc->device_caps |= V4L2_CAP_VIDEO_CAPTURE |
                        V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
        else
                vc->device_caps |= V4L2_CAP_RADIO;

        vc->capabilities = vc->device_caps | V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
        if (usbvision_device_data[usbvision->dev_model].radio)
                vc->capabilities |= V4L2_CAP_RADIO;
        return 0;
}
  • 一般我们只关心 capabilities 成员,比如V4L2_CAP_VIDEO_CAPTURE 具有视频捕获能力,其它定义如下:
 /* Values for 'capabilities' field */  
#define V4L2_CAP_VIDEO_CAPTURE      0x00000001  /* Is a video capture device */  
#define V4L2_CAP_VIDEO_OUTPUT       0x00000002  /* Is a video output device */  
#define V4L2_CAP_VIDEO_OVERLAY      0x00000004  /* Can do video overlay */  
#define V4L2_CAP_VBI_CAPTURE        0x00000010  /* Is a raw VBI capture device */  
#define V4L2_CAP_VBI_OUTPUT     0x00000020  /* Is a raw VBI output device */  
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040  /* Is a sliced VBI capture device */  
#define V4L2_CAP_SLICED_VBI_OUTPUT  0x00000080  /* Is a sliced VBI output device */  
#define V4L2_CAP_RDS_CAPTURE        0x00000100  /* RDS data capture */  
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY   0x00000200  /* Can do video output overlay */  
#define V4L2_CAP_HW_FREQ_SEEK       0x00000400  /* Can do hardware frequency seek  */  
#define V4L2_CAP_RDS_OUTPUT     0x00000800  /* Is an RDS encoder */  


你可能感兴趣的:(linux系统V4L2视频驱动,3,VIDIOC_QUERYCAP,v4l2)