V4L2摄像头测试(一)

1.得到和设置曝光模式。V4L2_CID_EXPOSURE_AUTO
2.得到和设置曝光档次。V4L2_CID_EXPOSURE
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
};
exposure_auto (menu) : min=0 max=3 default=3 value=3
V4L2_CID_EXPOSURE_AUTO enum v4l2_exposure_auto_type
Enables automatic adjustments of the exposure time and/or iris aperture. The effect of manual changes of the exposure time or iris aperture while these features are enabled is undefined, drivers should ignore such requests. Possible values are:
V4L2_EXPOSURE_AUTO Automatic exposure time, automatic iris aperture.
V4L2_EXPOSURE_MANUAL Manual exposure time, manual iris.
V4L2_EXPOSURE_SHUTTER_PRIORITY Manual exposure time, auto iris.
V4L2_EXPOSURE_APERTURE_PRIORITY Auto exposure time, manual iris.
4. 利用VIDIOC_G_CTRL得到一些设置:
一些具体的设置,如曝光模式(Exposure Type),曝光值(Exposure),增益(Gain),白平衡(WHITE_BALANCE),亮度(BRIGHTNESS),饱和度(SATURATION),对比度(CONTRAST)等信息。可以通过VIDIOC_G_CTRL得到当前值。
用法:APP 填写结构体中的id. 通过调用VIDIOC_G_CTRL,driver 会填写结构体中value项。

注意: Sam测试发现,在Linux下,V4L2_EXPOSURE_ATUO并不被Firmware认可,要设置自动曝光,需要设置为:V4L2_EXPOSURE_APERTURE_PRIORITY
曝光:
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. 内容为增益。
5. 利用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];
};
这样,就知道设置什么值是合法的了。那么,下一步就是设置了。
6. 利用VIDIOC_S_CTRL来设置:
很简单,设置id和value.调用ioctl就好。
还是以增益为例:
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_GAIN;
ctrl.value = Gain;
ret = ioctl(Handle, VIDIOC_S_CTRL, &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. 内容为增益。

第二部分:

  1. 利用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. 内容为增益。
  2. 利用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];
    };
    这样,就知道设置什么值是合法的了。那么,下一步就是设置了。
  3. 利用VIDIOC_S_CTRL来设置:
    很简单,设置id和value.调用ioctl就好。
    还是以增益为例:
    struct v4l2_control ctrl;
    ctrl.id = V4L2_CID_GAIN;
    ctrl.value = Gain;
    ret = ioctl(Handle, VIDIOC_S_CTRL, &ctrl);
    有时候,硬件设置很奇怪,可以设置某个信息,却无法得到如何设置的信息。例如:HD-500可以设置增益。却无法得到该如何设置。
  4. 利用扩展Ctrl设置:
    焦距(FOUCE);
    注1:enum v4l2_field field; 详解:
    5.设定分辨率:
    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;
    }
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个简单的v4l2接口的测试程序,可以获取摄像头的视频流并显示在屏幕上: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/videodev2.h> #include <errno.h> #define BUFFER_COUNT 4 struct buffer { void *start; size_t length; }; int main(int argc, char **argv) { int fd; struct v4l2_capability cap; struct v4l2_format fmt; struct v4l2_requestbuffers req; struct buffer *buffers; struct v4l2_buffer buf; unsigned int i, n_buffers; fd = open("/dev/video0", O_RDWR); if (fd == -1) { perror("open"); return EXIT_FAILURE; } if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { perror("VIDIOC_QUERYCAP"); return EXIT_FAILURE; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "The device does not support video capture.\n"); return EXIT_FAILURE; } memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 640; fmt.fmt.pix.height = 480; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_NONE; if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { perror("VIDIOC_S_FMT"); return EXIT_FAILURE; } memset(&req, 0, sizeof(req)); req.count = BUFFER_COUNT; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { perror("VIDIOC_REQBUFS"); return EXIT_FAILURE; } buffers = calloc(req.count, sizeof(*buffers)); if (!buffers) { fprintf(stderr, "Out of memory.\n"); return EXIT_FAILURE; } for (i = 0; i < req.count; ++i) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { perror("VIDIOC_QUERYBUF"); return EXIT_FAILURE; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (buffers[i].start == MAP_FAILED) { perror("mmap"); return EXIT_FAILURE; } } for (i = 0; i < req.count; ++i) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { perror("VIDIOC_QBUF"); return EXIT_FAILURE; } } enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) { perror("VIDIOC_STREAMON"); return EXIT_FAILURE; } for (i = 0; i < BUFFER_COUNT; ++i) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) { perror("VIDIOC_DQBUF"); return EXIT_FAILURE; } // Process the frame here. // ... if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { perror("VIDIOC_QBUF"); return EXIT_FAILURE; } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) { perror("VIDIOC_STREAMOFF"); return EXIT_FAILURE; } for (i = 0; i < req.count; ++i) { if (munmap(buffers[i].start, buffers[i].length) == -1) { perror("munmap"); return EXIT_FAILURE; } } free(buffers); if (close(fd) == -1) { perror("close"); return EXIT_FAILURE; } return EXIT_SUCCESS; } ``` 这个程序可以获取摄像头的视频流,对每一帧进行处理后再显示。其中,V4L2_PIX_FMT_YUYV 是常见的一种像素格式。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值