RK3568平台(camera篇)V4L2查询获取设置设备

一.查询设备能力VIDIOC_QUERYCAP

struct v4l2_capability cap;
ioctl(fd, VIDIOC_QUERYCAP, &cap)

struct v4l2_capability 结构体描述了视频采集设备的 driver 信息。

struct v4l2_capability
{
__u8 driver[16]; // 驱动名字
__u8 card[32]; // 设备名字
__u8 bus_info[32]; // 设备在系统中的位置
__u32 version; // 驱动版本号
__u32 capabilities; // 设备支持的操作
__u32 reserved[4]; // 保留字段
};

video注册的时候fops是v4l2_fops,所以会调用到v4l2_fops.unlocked_ioctl 也就是 v4l2_ioctl

v4l2_ioctl中 调用到 vdev->fops->unlocked_ioctl,vdev->fops对于vivi驱动的vivi_fops,所以unlocked_ioctl就是video_ioctl2

其中VIDIOC_QUERYCAP对应 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;/** 对应vivi驱动的 vidioc_querycap*/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;
}

vivi驱动vidioc_querycap源码如下

static int vidioc_querycap(struct file *file, void  *priv,struct v4l2_capability *cap)
{struct vivi_dev *dev = video_drvdata(file);strcpy(cap->driver, "vivi");strcpy(cap->card, "vivi");/** 这里加深一下理解* dev->v4l2_dev.name 是什么?* vivi驱动中有这样一句代码* snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),"%s-%03d", VIVI_MODULE_NAME, inst);* "vivi-000" "vivi-001" 这种名字*/strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));cap->version = VIVI_VERSION;/** 驱动表示支持capture,streaming及read write*/    cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \V4L2_CAP_READWRITE;return 0;
}

从capabilities的返回值能知道这个设备所支持的功能。

判断设备是否支持拍照功能:

if (ioctl(fd_v4l, VIDIOC_QUERYCAP, &cap) == 0)
{printf("cap=0x%x\n", cap.capabilities);if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){printf("%s not support v4l2 capture device.\n", dev_name);return -1;}
}
else
{close(fd_v4l);return -1;
}

二.设置输入设备VIDIOC_S_INPUT

一个video设备节点可能对应多个视频源,所以需要指定输入的设备。

input.index = index; //指定输入设备
if (ioctl(fd, VIDIOC_S_INPUT, &input) < 0)

设备输入的设备为设备0:

struct v4l2_input inp;
inp.index = 0;
if (ioctl(fd_v4l, VIDIOC_S_INPUT, &inp) < 0)
{printf("VIDIOC_S_INPUT error.!");return -1;
}

 对应vivi的vidioc_s_input

static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{struct vivi_dev *dev = video_drvdata(file);if (i >= NUM_INPUTS)return -EINVAL;dev->input = i;precalculate_bars(dev);precalculate_line(dev);return 0;
}

三.获取设置支持的视频格式VIDIOC_G_FMT

struct v4l2_format {enum v4l2_buf_type type;union {struct v4l2_pix_format         pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */struct v4l2_window             win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */struct v4l2_vbi_format         vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */struct v4l2_sliced_vbi_format  sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */__u8   raw_data[200];                   /* user-defined */} fmt;
};
其中
enum v4l2_buf_type {V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,...V4L2_BUF_TYPE_PRIVATE              = 0x80,
};struct v4l2_pix_format {__u32                   width;__u32                   height;__u32                   pixelformat;enum v4l2_field         field;__u32                   bytesperline;   /* for padding, zero if unused */__u32                   sizeimage;enum v4l2_colorspace    colorspace;__u32                   priv;           /* private data, depends on pixelformat */
};

通过VIDIOC_G_FMT获取输入设备的宽高:

if (ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) < 0)
{printf("get format failed\n");goto fail;
}camera_width  = fmt.fmt.pix_mp.width;
camera_height = fmt.fmt.pix_mp.height;

四.设置视频格式VIDIOC_S_FMT

memset(&v4l2_fmt, 0, sizeof(struct v4l2_format));
v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
v4l2_fmt.fmt.pix.width = width; //宽度
v4l2_fmt.fmt.pix.height = height; //高度
v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //像素格式
v4l2_fmt.fmt.pix.field = V4L2_FIELD_ANY;if (ioctl(fd, VIDIOC_S_FMT, &v4l2_fmt) < 0)

这里对应vivi驱动的vidioc_s_fmt_vid_cap

static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,struct v4l2_format *f)
{struct vivi_dev *dev = video_drvdata(file);struct vb2_queue *q = &dev->vb_vidq;int ret = vidioc_try_fmt_vid_cap(file, priv, f);if (ret < 0)return ret;/** vb2_is_streaming 判断vb2_is_streaming的值,后面的分析我们会看到这个值* 的变化,这里认为值为0,if不满足*/if (vb2_is_streaming(q)) {dprintk(dev, 1, "%s device busy\n", __func__);return -EBUSY;}dev->fmt = get_format(f);dev->width = f->fmt.pix.width;dev->height = f->fmt.pix.height;dev->field = f->fmt.pix.field;return 0;
}

五.获取Stream信息VIDIOC_G_PARM

struct v4l2_streamparm Stream_Parm;
memset(&Stream_Parm, 0, sizeof(struct v4l2_streamparm));
Stream_Parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
io_rel = ioctl(Handle, VIDIOC_G_PARM, &Stream_Parm);
struct v4l2_streamparm
{
enum v4l2_buf_type type;
union
{
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200];
} parm;
};因为是Camera, 所以使用capture。
struct v4l2_captureparm
{
__u32 capability;   // 是否可以被timeperframe控制帧数。可以则:V4L2_CAP_TIMEPERFRAME
__u32 capturemode;  // 是否为高清模式。如果是则设置为:V4L2_MODE_HIGHQUALITY。 高清模式会牺牲其它信息。通常设置为0。
struct v4l2_fract timeperframe;  //帧数。
__u32 extendedmode; //定制的。如果不支持,设置为0
__u32 readbuffers;
__u32 reserved[4];
};struct v4l2_fract {
__u32 numerator;   // 分子。 例:1
__u32 denominator; // 分母。 例:30
};

六.设置Stream信息VIDIOC_S_PARM

struct v4l2_streamparm streamparm = {0};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd, VIDIOC_G_PARM, &streamparm);
if (V4L2_CAP_TIMEPERFRAME & streamparm.parm.capture.capability) 
{streamparm.parm.capture.timeperframe.numerator = 1;streamparm.parm.capture.timeperframe.denominator = 30;//30fpsif (0 > ioctl(fd, VIDIOC_S_PARM, &streamparm)) {printf("ioctl error: VIDIOC_S_PARM");return -1;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/18244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解makefile中的foreach

在 Makefile 中&#xff0c;foreach 函数用于迭代处理一个以空格分隔的列表&#xff0c;并针对列表中的每个元素执行相同的操作。这个函数通常用于循环处理一组变量或文件名&#xff0c;并执行相同的规则或命令。 语法&#xff1a; makefile Copy Code $(foreach var, list, …

ThingsBoard物联网网关在智慧城市数据采集中的应用

智慧城市由监控中心、采集网关、前端采集设备、前端感应执行器组成。 为何选用ThingsBoard作为平台 监控中心为物联网平台&#xff0c;该平台包含云计算、大数据、人工智能、物联网、GIS、云安全等主要模块&#xff0c;具备数据采集、数据交换、超大规模计算、数据分析、数据应…

防火墙如何端口映射?

防火墙端口映射&#xff08;Firewall Port Mapping&#xff09;是一种网络技术&#xff0c;通过对防火墙配置进行调整&#xff0c;允许外部网络用户访问内部网络中的指定端口。该技术使得外部用户可以通过公共网络访问内部网络中的特定服务或应用程序&#xff0c;从而实现远程访…

JavaScript--作用域是什么

作用域是什么 编译原理 在传统的编译语言中&#xff0c;程序中的一段源代码在执行之前会经历三个步骤。成为编译 分词/词法分析 这个过程由字符组成的字符串分解成有意义的代码块&#xff0c;这些代码块成为词法单元。 分词和词法分析之间的主要差异在于词法单元的识别是有…

实战指南:Vue 2基座 + Vue 3 + Vite + TypeScript微前端架构实现动态菜单与登录共享

实战指南&#xff1a;Vue 2基座 Vue 3 Vite TypeScript子应用vue2微前端架构实现动态菜单与登录共享 导读&#xff1a; 在当今的前端开发中&#xff0c;微前端架构已经成为了一种流行的架构模式。本文将介绍如何结合Vue 2基座、Vue 3子应用、Vite构建工具和TypeScript语言…

基于Docker的ROS开发

本文主要介绍如何使用Docker在Windows和Linux环境中部署并使用ROS&#xff0c;通过Docker Container运行ROS&#xff0c;可以方便我们在一个本地环境中运行多个ROS版本。 更多内容&#xff0c;访问专栏目录获取实时更新。 关于ROS的版本 参考ROS1 Distribution Wiki和ROS2 Dis…

nginx源码阅读理解 [持续更新,建议关注]

文章目录 前述一、nginx 进程模型基本流程二、源码里的小点1.对字符串操作都进行了原生实现2.配置文件解析也是原生实现待续 前述 通过对 nginx 的了解和代码简单阅读&#xff0c;发现这个C代码的中间件确实存在过人之处&#xff0c;使用场景特别多&#xff0c;插件模块很丰富…

10款AI工具,让工作生活学习更高效

我看大家都推荐的差不多了&#xff0c;常见好用的PC软件就那些&#xff0c;我不想反复“咀嚼”了&#xff0c;我想另辟蹊径推荐点不一样的&#xff0c;比如10款PC端的AI网站。AI已经全方位“侵入”我们的生活&#xff0c;从AI写作到AI绘画&#xff0c;从AI视频到AI语音&#xf…

Thingsboard规则链:Switch节点详解

在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据的高效处理与自动化决策是构建智能系统的核心。作为一款强大的物联网平台&#xff0c;Thingsboard通过其规则引擎为开发者提供了高度灵活的工具&#xff0c;其中Switch节点是实现消息条件路由的关键组件。本文将全方位…

【深度学习】Transformer梳理

零、前言 对于transformer&#xff0c;网上的教程使用记号、术语不一 。 最关键的一点&#xff0c;网上各种图的简化程度不一 &#xff08;画个图怎么能这么偷懒&#xff09; &#xff0c;所以我打算自己手画一次图。 看到的最和善&#xff08;但是不是那么靠谱&#xff0c;我…

黑龙江某市数字孪生地下水监测系统平台项目建设经验

项目背景 地下水是一种特殊而珍贵的资源&#xff0c;它具有不可替代性&#xff0c;与经济发展及人民生活息息相关&#xff0c;针对日趋严峻的水资源危机&#xff0c;如何合理利用有限的水资源&#xff0c;保障国民经济的可持续发展是一个迫切需要解决的问题。 黑龙江某市积极…

eclipse启动时间过长的问题

项目场景&#xff1a; 由于我用eclipse比较习惯&#xff0c;虽然IDEA很好&#xff0c;但是因为收费&#xff0c;所以在个人开发学习过程中一直还是使用eclipse&#xff0c;本文不讨论eclipse与IDEA孰优孰劣问题。 开发环境&#xff1a; 操作系统&#xff1a;Windows 11 22631…

【小呆的力学笔记】连续介质力学的知识点回顾一:运动和变形

文章目录 1. 运动的描述2. 拉格朗日描述下的变形2.1 线元的变化2.2 体元的变化2.3 面元的变化 1. 运动的描述 在连续介质力学中&#xff0c;存在着两种对运动的描述&#xff0c;一种为拉格朗日描述&#xff0c;即通过描述每个物质点的运动来描述整个变形体的运动&#xff0c;也…

如何将音频中的人声分离出来?

想要把一段视频中的人声跟背景音乐分离开来&#xff0c;找个好一点的音频处理软件就能把声音分离了&#xff0c;常见的有以下方法&#xff0c;一起来看看吧。 pr 打开软件&#xff0c;然后将电脑上的音频文件&#xff0c;上传到软件中&#xff0c;然后按住[ctrla]选择所有音频…

【数据结构】 排序算法 ~ 总结篇

文章目录 1. 排序几个重点概念的理解2. 排序算法的分析&#x1f427; 1. 排序几个重点概念的理解 2. 排序算法的分析&#x1f427;

Git学习篇

目录 使用命令导入项目 使用命令导入项目 1. 使用git init 命令初始化一个新的Git仓库。 git init 是 Git 命令&#xff0c;用于初始化一个新的 Git 仓库。当您想要开始跟踪一个新项目的版本控制时&#xff0c;可以运行 git init 命令来初始化一个空的 Git 仓库。 如果出现以下…

6-继承

6-继承 1、基本语法和方式2、继承的基本特点2.1 三种继承方式相同的基本点2.2 三种继承方式的差别2.3 公有继承的独有特点 3、子类的构造、析构3.1 子类的构造3.2 子类的析构3.3 子类的拷贝构造函数3.4 子类的拷贝赋值 4、多重继承4.1 内存布局4.2 类型转换4.3 名字冲突问题 5、…

10. C++异步IO处理库和使用libevent实现高性能服务器

C比较有名的异步IO处理库 libevent 这个主要使用的是epoll。libevthplibuvlibev 我们主要介绍libevent。 libevent重要函数 event_base_new 这个可以对应于epoll_create也就是创建一个实例。还可以初始化libevent所有管理相关的代码。比如说所能用到的队列&#xff0c;栈&a…

Linux内核编译流程3.10

一、内核源代码编译流程 编译环境&#xff1a; cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) Linux内核版本&#xff1a; uname -r 3.10.0-693.el7.x86_64 编译内核源代码版本&#xff1a;linux-4.19.90-all-arch-master cp /boot/config-xxx到内核源…

数据库(9)——DQL基础查询

数据查询 数据查询是SQL中最复杂的&#xff0c;语法结构为 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后字段列表 ORDER BY 排序字段列表 LIMIT 分页参数 查询多个字段 SELECT 字段1&#xff0c;字段2...FROM…