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;
}
Linux下实现视频读取(二)---camera參数设定的更多相关文章
- Linux下实现视频读取(三)---Buffer的准备和数据读取
前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度.曝光时间,帧数,增益.白平衡等.今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取. 1. 初始化 Memory ...
- Linux下实现视频读取
V4L(video4linux是一些视频系统,视频软件.音频软件的基础,经常时候在需要采集图像的场合,如视频监控,webcam,可视电话,经常使用在embedded linux中是linux嵌入式开发 ...
- 嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍
**************************************************************************************************** ...
- Linux下的视频字幕编辑
一.Linux下的字幕编辑软件 常用的有subtitleeditor, gnome-subtitles, gaupol 1.gnome-subtitles:不支持多字幕文件批量处理2.gaupol:全 ...
- Linux下从视频提取音频的方法
Linux下可以利用mencoder将视频里的音频提取出来.方法如下: 1.首先安装mencoder.对于Ubuntu来说,软件仓库里就有mencoder,可直接输入如下命令安装 sudo apt-g ...
- linux下动态链接库解决方案(二)
以前写过一个关于linux下用c++写动态链接库无法通过的解决方案,今天看到<linux C程序设计-王者归来>这本书,书中有个更容易的解决方案,特此记录下来 书中使用的是c语言,我改用c ...
- Linux下修改当前用户的最大线程数和 open files
1 查看当前用户的线程 ulimit -a 2 修改配置文件 vi /etc/security/limits.d/90-nproc.conf 3 改完即可生效 4 修改可打开的最大文件数 vi /e ...
- Linux 下 Bash配置文件读取
Linux安装时可能要修改的配置文件:/etc/profile./etc/bashrc(ubuntu没有这个文件,对应地,其有/etc/bash.bashrc文件.我用的是ubuntu系统,所以下面将 ...
- linux 下shell程序(二)
输入和输出 输入指的是Shell程序读入数据.有从文件读取.从用户输入读取等方式读入数据.输出指的是Shell程序的运行 结果的处理,可以显示到屏幕或保存到文件. 用ceho命令输出结果 echo $ ...
随机推荐
- 学习linux之用户-文件-权限操作
添加用户组 添加 gropuadd 用户组名 修改 groupmod 用户组名 删除 groupdel 用户组名 添加用户 添加 useradd 用户名 设密码 passwd 密码 删除 userde ...
- select自动选中
//筛选 var typeid = "<!--{$typeid}-->"; var bigclassid = "<!--{$bigclassid}--& ...
- hdu 2222 Keywords_ac自动机模板
题意:给你n个单词,再给你一串字符,求在字符中有多少个单词出现过 #include <iostream> #include<cstdio> #include<cstrin ...
- SharePoint 2013的100个新功能之场管理
一:改进的SPSite命令 SharePoint 2013中对SPSite PowerShell命令行做了改进提升,使网站集操作更简便.比如,一个新的参数“HostHeaderWebApplicati ...
- 关于CoreData的理解和使用.
CoreData是苹果官方推出的一种方便的面向对象的存储方式,相信大家都已经对其有所了解,但是对于CoreData的概念大家都存在部分的误区.给大家推荐个网址是苹果的官方文档的翻译版(http://o ...
- poj 3641 Pseudoprime numbers(快速幂)
Description Fermat's theorem states that for any prime number p and for any integer a > 1, ap = a ...
- Java替代C语言的可能性
前不久CSDN刊登了一篇<C语言已经死了>的文章,引起了一些争论.事实上那篇文章是从Ed Burnette的博客上转载来的,原文题目是“Die, C, die!”,直译过来应该是& ...
- 《Effective C++ 》学习笔记——条款03
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- .NET 创建并写CSV文件
/// <summary> /// 创建并写日志 /// </summary> /// <param name="SuccessA100">&l ...
- 前端自动化学习笔记(一)——Yeoman,bower,Grunt的安装
最近看视频学习了前端自动化的一些知识,确实让我大开眼界.感觉前端越来越神器了.同时跟着视频自己也尝试运用了一些工具去构建前端项目,但是中间遇见了很多坑,磕磕绊绊的才实现了一点功能,所以打算记录一下学习 ...