Linux下实现视频读取(二)---camera參数设定

Camera的可设置项极多,V4L2 支持了不少。但Sam之前对这些设置的使用方法和涵义都是在看videodev2.h中边看边理解。感觉很生涩。

直到写这篇blog时,才发现v4l2有专门的SPEC来说明:
http://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html

但也基本没有时间细致看了。

先把自己看头文件看出的一些东西记录在这里吧。以实际设置过程为顺序谈谈V4L2 设置。

1. 查询V4L2 功能集:VIDIOC_QUERYCAP
struct v4l2_capability cap;
int rel = 0;
ioctl(Handle, VIDIOC_QUERYCAP, &cap);

使用ioctl VIDIOC_QUERYCAP 来查询当前driver是否合乎规范。由于V4L2要求全部driver 和Device都支持这个Ioctl。

所以,可以通过这个ioctl是否成功来推断当前设备和dirver 是否支持V4L2规范。当然,这样同一时候还可以得到设备足够的能力信息。



struct v4l2_capability
{
 __u8 driver[16];   //驱动名。
 __u8 card[32];     // Device名
 __u8 bus_info[32];  //在Bus系统中存放位置
 __u32 version;      //driver 版本号
 __u32 capabilities;  //能力集
 __u32 reserved[4];
};
能力集中包括:


V4L2_CAP_VIDEO_CAPTURE 0x00000001     The device supports the Video    Capture interface.
V4L2_CAP_VIDEO_OUTPUT   0x00000002     The device supports the Video    Output interface.
V4L2_CAP_VIDEO_OVERLAY 0x00000004     The device supports the Video    Overlay interface.
A video overlay device typically stores captured images directly in the video memory   of a graphics card,with hardware clipping and scaling.
V4L2_CAP_VBI_CAPTURE     0x00000010 The device supports the Raw  VBI Capture interface, providing Teletext and Closed Caption   data.
V4L2_CAP_VBI_OUTPUT     0x00000020      The device supports the Raw  VBI Output interface.
V4L2_CAP_SLICED_VBI_CAPTURE  0x00000040 The device supports the Sliced VBI Capture interface.
V4L2_CAP_SLICED_VBI_OUTPUT   0x00000080 The device supports the Sliced VBI Output interface.
V4L2_CAP_RDS_CAPTURE    0x00000100          [to be defined]
#define V4L2_CAP_TUNER 0x00010000  
#define V4L2_CAP_AUDIO 0x00020000  
#define V4L2_CAP_RADIO 0x00040000  
#define V4L2_CAP_READWRITE 0x01000000  
#define V4L2_CAP_ASYNCIO 0x02000000  
#define V4L2_CAP_STREAMING 0x04000000  

看起来非常熟悉吧。事实上就是Driver里面的Type。



 __u8 driver[16]; driver名。通常为:uvcvideo
 __u8 card[32];  设备名:厂商会填写。
 __u8 bus_info[32];  bus,通常为:usb-hiusb-ehci-2.4
 __u32 version;
 __u32 capabilities;  通常为:V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
 __u32 reserved[4];

2. 枚举设备所支持的image format:  VIDIOC_ENUM_FMT
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(Handle, VIDIOC_ENUM_FMT, &fmtdesc);

使用ioctl VIDIOC_ENUM_FMT 依次询问,type为:V4L2_BUF_TYPE_VIDEO_CAPTURE。 index从0開始。依次添加,直到返回. Driver会填充结构体struct v4l2_fmtdesc的其他内容。假设index超出范围,则返回-1。
struct v4l2_fmtdesc
{
 __u32 index;                  // 须要填充,从0開始,依次上升。
 enum v4l2_buf_type type;      //Camera,则填写V4L2_BUF_TYPE_VIDEO_CAPTURE
 __u32 flags;                  // 假设压缩的,则Driver 填写:V4L2_FMT_FLAG_COMPRESSED。否则为0 
 __u8 description[32];         // image format的描写叙述,如:YUV 4:2:2 (YUYV)
 __u32 pixelformat;        //所支持的格式。如:V4L2_PIX_FMT_UYVY
 __u32 reserved[4];
}; 

这样。则知道当前硬件支持什么样的image format. 下一步,则能够设置image 了。当然。设置之前,还能够读取当前缺省设置。



3. 得到和设置Image Format: VIDIOC_G_FMT, VIDIOC_S_FMT:
3.1: 得到当前Image Format:
struct v4l2_format Format;
memset(&Format, 0, sizeof(struct v4l2_format));
Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(Handle, VIDIOC_G_FMT, &Format);

利用ioctl VIDIOC_G_FMT. 得到当前设置。
由于Camera为CAPTURE设备。所以须要设置type为: V4L2_BUF_TYPE_VIDEO_CAPTURE
然后Driver会填充其他内容。

struct v4l2_format
{
 enum v4l2_buf_type type;   // Camera,则用户必须填写:V4L2_BUF_TYPE_VIDEO_CAPTURE
 union
 {
 struct v4l2_pix_format pix;    // used by video capture and output devices
 struct v4l2_window win;
 struct v4l2_vbi_format vbi;
 struct v4l2_sliced_vbi_format sliced;
 __u8 raw_data[200];
 } fmt;
};


由于是Camera, 所以採用pix. 如今分析例如以下:
struct v4l2_pix_format
{
 __u32 width;    //Image width in pixels.
 __u32 height;   // Image Height in pixels.
 __u32 pixelformat;  // Image格式。最常见的有:V4L2_PIX_FMT_YYUV
 enum v4l2_field field; //是否逐行扫描,是否隔行扫描. Sam通常採用V4L2_FIELD_NONE。逐行放置数据 (注1)
 __u32 bytesperline; //每行的byte数
 __u32 sizeimage;     //总共的byte数,bytesperline * height
 enum v4l2_colorspace colorspace;  //This information supplements the pixelformat and must be set by the driver
 __u32 priv;
};

3.2:设置Image Format:VIDIOC_S_FMT
之前通过VIDIOC_ENUM_FMT已经知道Device支持什么Format。所以就不用推測了,直接设置吧。


设置Image  Format ,利用 iocto VIDIOC_S_FMT.
须要APPLICATION填写的Struct项目有:
struct v4l2_format Format;

Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Format.fmt.pix.width =  Width;
Format.fmt.pix.height = Height;
Format.fmt.pix.pixelformat= pixelformat;//V4L2_PIX_FMT_YUYV;
Format.fmt.pix.field = field;
io_rel = ioctl(Handle, VIDIOC_S_FMT, &Format);

SamInfo:之前设置了Image Format。是指每一帧的数据格式,但Stream的行为呢,也须要设置,这就是以下所说的Stream 设置了。它就包括帧数设置和改动。

4. 得到和设置Stream信息:VIDIOC_G_PARM, VIDIOC_S_PARM
Stream信息,主要是设置帧数。
4.1:得到Stream信息:
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);

用户仅仅须要填充type为V4L2_BUF_TYPE_VIDEO_CAPTURE。 Driver就会把结构体中其他部分填充好。


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

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 timeperframe;  //帧数。



struct v4l2_fract {
 __u32 numerator;  // 分子。例:1
 __u32 denominator; //分母。 例:30
};

4.2:设置帧数:
struct v4l2_streamparm Stream_Parm;
memset(&Stream_Parm, 0, sizeof(struct v4l2_streamparm));
Stream_Parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

Stream_Parm.parm.capture.timeperframe.denominator =Denominator;;
Stream_Parm.parm.capture.timeperframe.numerator = Numerator;

io_rel = ioctl(Handle, VIDIOC_S_PARM, &Stream_Parm);

请注意,哪怕ioctl返回0。也有可能没设置成功。所以须要再次Get。
当然。哪怕Get发现设置成功。真正抓帧也可能没那么高。

5. 利用VIDIOC_G_CTRL得到一些设置:
一些详细的设置,如曝光模式(Exposure Type),曝光值(Exposure),增益(Gain),白平衡(WHITE_BALANCE),亮度(BRIGHTNESS),饱和度(SATURATION),对照度(CONTRAST)等信息。

能够通过VIDIOC_G_CTRL得到当前值。



使用方法:APP 填写结构体中的id. 通过调用VIDIOC_G_CTRL。driver 会填写结构体中value项。
struct v4l2_control ctrl;
struct v4l2_control
{
 __u32 id;
 __s32 value;
};
以曝光模式。曝光,和增益为例; 

曝光模式:
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_EXPOSURE_AUTO;
ret = ioctl(Handle, VIDIOC_G_CTRL, &ctrl);
ctrl.value 则由Driver填写。告知当前曝光模式。
有下面几个选择:
enum  v4l2_exposure_auto_type {
V4L2_EXPOSURE_AUTO = 0,
V4L2_EXPOSURE_MANUAL = 1,
V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
V4L2_EXPOSURE_APERTURE_PRIORITY = 3
};
曝光:
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_EXPOSURE_ABSOLUTE;
ret = ioctl(Handle, VIDIOC_G_CTRL, &ctrl);
相同,driver填写ctrl.value. 内容为曝光值。

增益:
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_GAIN;
ret = ioctl(Handle, VIDIOC_G_CTRL, &ctrl);
相同,driver填写ctrl.value. 内容为增益。



6. 利用VIDIOC_QUERYCTRL 得到设置详细信息:
在非常多情况下。我们并不知道怎样设置一些信息,比如,曝光应该设置为多少?Driver可以接受的范围是多少?最大。最小值是多少?步长是多少?缺省值为多少?
能够通过VIDIOC_QUERYCTRL得到。

咱们还是以增益为例:
struct v4l2_queryctrl  Setting;
Setting.id = V4L2_CID_GAIN;
ret = ioctl(Handle, VIDIOC_QUERYCTRL, &Setting);
Driver就会填写结构体中全部信息。



struct v4l2_queryctrl
{
 __u32 id;  //用户设置。指定查找的是哪个ID。
 enum v4l2_ctrl_type type;
 __u8 name[32];  //ID相应的名字。
 __s32 minimum;
 __s32 maximum;
 __s32 step;   //步长
 __s32 default_value;
 __u32 flags;
 __u32 reserved[2];
};
这样,就知道设置什么值是合法的了。那么,下一步就是设置了。



7. 利用VIDIOC_S_CTRL来设置:
非常easy,设置id和value.调用ioctl就好。


还是以增益为例:
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_GAIN;
ctrl.value = Gain;
ret = ioctl(Handle, VIDIOC_S_CTRL, &ctrl);
有时候,硬件设置非常奇怪,能够设置某个信息,却无法得到怎样设置的信息。比如:HD-500能够设置增益。却无法得到该怎样设置。

8. 利用扩展Ctrl设置:
焦距(FOUCE);

注1:enum v4l2_field field; 具体解释:

9.设定分辨率:

struct v4l2_control control;

memset(&control, 0, sizeof(control));
control.id = V4L2_CID_AUTO_WHITE_BALANCE;
control.value = 1;
if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 
{
printf("Couldn't set auto white balance!\n");
//return -1;
}

memset(&control, 0, sizeof(control));
control.id = V4L2_CID_EXPOSURE_AUTO;
control.value = 1;

if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 
{
printf("Couldn't set auto exposure!\n");
//return -1;
}

memset(&control, 0, sizeof(control));
control.id = V4L2_CID_HFLIP;
control.value = 1;
if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 
{
printf("Couldn't set h flip!\n");
//return -1;
}


memset(&control, 0, sizeof(control));
control.id = V4L2_CID_VFLIP;
control.value = 1;
if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 
{
printf("Couldn't set v flip!\n");
//return -1;
}

转载于:https://www.cnblogs.com/blfshiye/p/5151167.html

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

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

相关文章

微信小程序页面跳转与返回并回传数据

2019独角兽企业重金招聘Python工程师标准>>> A页面&#xff1a; .wxml文件 <view class"flex-wrp"><text style"width: 32%;">选择城市</text><input style"width: 68%;" type"text" bindtap"ci…

地址栏 输入 参数 刷新参数丢失_小米11 Pro屏幕参数曝光:2K屏幕+120Hz刷新率

本周一&#xff0c;高通已经宣布将于12月初举行的骁龙技术峰会上正式发布新一代旗舰处理器——骁龙875。根据此前的曝光消息&#xff0c;小米11系列将首发搭载这颗芯片&#xff0c;网上也已经开始对这款新机进行曝光。日前&#xff0c;海外知名论坛XDA在MIUI 12的代码中发现了一…

Cypress EZ-USB FX3 DMA模式下的串口通讯

由于公司设备升级后出了问题&#xff0c;需要对USB驱动进行修改&#xff0c;原本使用的是寄存器模式进行UART传输&#xff0c;但是由于FX3寄存器模式会出现长时间延时等待的问题&#xff0c;不得不对其传输模式进行修改。虽然赛普拉斯的EZ-USB FX3系列芯片功能强大&#xff0c;…

php如何写一个能让外部访问的接口,如何写一个接口供外界访问

在工作的时候经常调用别人的接口&#xff0c;获取数据&#xff0c;然后就想知道这中间的原理是什么呢&#xff1f;今天上一个自己写的一个测试例子&#xff1a;首先是自己远程写好的一个接口&#xff1a;public function testming(){$arrarray(first > 1,hospitalname > …

win10远程桌面连接

有的情况下&#xff0c;Win10设置了允许远程桌面连接后&#xff0c;远程主机仍然不能桌面连接到目标主机上&#xff0c;这时可以在目标主机上尝试如下修改&#xff1a; 开始-->运行->gpedit.msc->计算机配置->Windows设置->安全设置->本地策略->安全选项-…

10494,没过,待解决,大数除法

10494,没过,待解决,大数除法 import java.io.*; import java.util.*;public class Main {public static void main(String[] args) throws FileNotFoundException{// Scanner scanner new Scanner(new File("d://1.txt"));Scanner scanner new Scanner(System.in);…

springboot md5加密_实在!基于Springboot和WebScoket,写了一个在线聊天小程序

基于Springboot和WebScoket写的一个在线聊天小程序(好几天没有写东西了&#xff0c;也没有去练手了&#xff0c;就看了看这个。。。)项目说明此项目为一个聊天的小demo&#xff0c;采用springbootwebsocketvue开发。其中有一个接口为添加好友接口&#xff0c;添加好友会判断是否…

suse 启动oracle11g,SuSe10下Oracle11g文件系统模式安装及配置、网络配置与连接

SuSe10下Oracle11g文件系统模式安装及配置、网络配置与连接概述本课程主要讲解oracle数据库软件的安装及配置&#xff0c;以及数据库的创建过程和网络配置与连接等&#xff1b;同时讲解一些数据库安装过程中的常见问题解决办法。注意&#xff1a;本文当中引用的package_name均为…

Python pyenv

一、简介 一般在操作系统中我们会安装多个Python版本&#xff0c;所以在进行Python版本切换时会比较麻烦&#xff0c;pyenv就提供了一种简单的方式&#xff0c;能简易地在多个Python版本中进行切换的工具&#xff0c;它简单而优雅。pyenv有以下功能&#xff1a; 1&#xff09;进…

python中add_Python add()函数是如何使用呢?

Python里经常会出现一些不太常见的函数&#xff0c;大家在遇到这类函数时候&#xff0c;是怎么做的呢&#xff1f;没有概念&#xff0c;直接过&#xff0c;还是会去查询下呢&#xff1f;相信大部分人都不会去查询&#xff0c;因为查询的内容太复杂了&#xff0c;所以&#xff0…

JavaScript的DOM编程总结

DOM&#xff08;文档对象模型&#xff09;, 与语言无关, 用于操作XML&#xff08;在Web中&#xff09;和HTML&#xff08;在浏览器在&#xff09;文档的应用程序接口。访问DOM次数越多, 速度越慢, 费用也就越高。 最小化DOM访问次数&#xff0c;尽可能在JavaScript端处理。 如果…

2017.1.20活动

1、根据教程用倾斜开关控制了一个小灯的亮灭&#xff08;倾斜到达一定角度亮或到达一定角度灭&#xff09;&#xff0c;后自己尝试了利用倾斜开关控制两个小灯&#xff0c;即一开始绿灯亮红灯灭&#xff0c;到达一定角度后&#xff0c;绿灯亮起红灯灭掉&#xff0c;附代码&…

oracle 增加间隔分区,oracle分区表之间隔分区(oracle 11g) - 漫兮网

范围分区允许用户根据分区键列值的范围创建分区。下面是一个按范围分区表的示例&#xff1a;create table sales6(sales_id number,sales_dt date)partition by range (sales_dt)(partition p0701 values less than (to_date(2007-02-01,yyyy-mm-dd)),partition p0702 values l…

c++ try catch语句_再问你一遍,你真的了解try..catch(finally)吗???

定义首先来看下 MDN 的定义&#xff1a;The try...catch statement marks a block of statements to try and specifies a response should an exception be thrown.try...catch语句标记要执行的语句&#xff0c;并指定一个当有异常抛出时候的响应简短的一句的确描述了try...ca…

lamp架构,搭建一个网络平台

首先更改主机名和 hosts 安装软件包&#xff0c;设置启动服务 设置数据库密码 上传discuz论坛包 将discuz注册的用户名写在mariadb数据库中 解压discuz包 unzip discuz包 -d /var/www/html cd到upload下 cp -rf * /var/www/html 进入数据库 mysql -uroot -p create database…

MyEclipse中SVN的使用方法

1、 加载插件 svn-myeclipse插件site-1.10.2.zip&#xff0c;解压缩后&#xff0c;将文件夹下的所有文件拷贝到MyEclipse安装包下的MyEclipse 8.5\dropins文件夹下&#xff0c;然后重新打开myeclipse&#xff0c;会弹出一个报错窗口&#xff0c;不要管它&#xff0c;关闭后&…

oracle数据泵导出csv文件,数据泵expdp导出遇到ORA-01555和ORA-22924问题的分析和处理...

使用数据泵导出数据库数据时&#xff0c;发现如下错误提示&#xff1a;ORA-31693: Table data object "CAMS_CORE"."BP_EXCEPTION_LOG" failed to load/unload and is being skipped due to error:ORA-02354: error in exporting/importing dataORA-01555:…

Go程序开发---Go环境配置:CentOS6.5+Go1.8标准包安装

1.Go安装 1.1Go的三种安装方式 Go有多种安装方式&#xff0c;可以选择自己习惯的方式进行&#xff0c;这里介绍三种安装方式&#xff1a; 1&#xff09;Go源码安装 2&#xff09;Go标准包安装 3&#xff09;第三方工具安装 这里主要介绍下Go标准包在CentOS6.5系统中的安装方式 …

python矩阵乘法_鱼书——第一章 Python入门

one 第一章1.1 Python是什么Python是一个简单、易读、易记的编程语言&#xff0c;而且是开源的&#xff0c;可以免费地自由使用。Python可以用类似英语的语法编写程序&#xff0c;编译起来也不费力&#xff0c;因此我们可以很轻松地使用Python。特别是对首次接触编程的人士来说…

深入浅出面向对象分析与设计

深入浅出面向对象分析与设计书籍 下载位置&#xff1a;http://pan.baidu.com/s/1o7gmmuu转载于:https://www.cnblogs.com/wlming/p/5160140.html