Linux V4L2 camera应用程序
·
1、资料快车
1)https://blog.csdn.net/thisway_diy/article/details/121809610
2)https://cloud.tencent.com/developer/article/2359076
在了解摄像头内核驱动框架之前,先来看看简单的摄像头应用程序,毕竟内核设计的功能理应服务与应用程序,了解“客户的需求”很有必要,也是首要任务!
2、摄像头操作逻辑框图

1)重点在于Buffer的管理,APP作为消费者,摄像头则是生产者;
3、数据结构
1.ioctl
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
#define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability)
#define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc)
#define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format)
#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format)
1)ioctl操作分为两类:
1、VideoStreaming接口:VIDIOC_ENUM_FMT、VIDIOC_G_FMT、VIDIOC_S_FMT、VIDIOC_STREAMON、VIDIOC_STREAMOFF
2、VideoControl接口(大多数):VIDIOC_S_CTRL、VIDIOC_G_CTRL
2)注意不同的摄像头有不同的IOCTL能力,根据当前平台实现支持的IOCTL;
2.v4l2_buffer - 用于指定buffer的属性,并没有实际内存
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
struct v4l2_buffer {
__u32 index;
__u32 type;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
__u32 memory;
}
3.v4l2_format
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
struct v4l2_format {
__u32 type;
union {
struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
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 */
struct v4l2_sdr_format sdr; /* V4L2_BUF_TYPE_SDR_CAPTURE */
struct v4l2_meta_format meta; /* V4L2_BUF_TYPE_META_CAPTURE */
__u8 raw_data[200]; /* user-defined */
} fmt;
};
4、v4l2_fmtdesc
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
struct v4l2_fmtdesc {
__u32 index;
__u32 type;
__u32 flags;
__u8 description[32];
__u32 pixelformat;
__u32 reserved[4];
};
5.v4l2_capability
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
struct v4l2_capability {
__u8 driver[16];
__u8 card[32];
__u8 bus_info[32];
__u32 version;
__u32 capabilities;
__u32 device_caps;
__u32 reserved[3];
};
6.v4l2_control - uvc摄像头
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/videodev2.h
struct v4l2_control {
__u32 id;
__s32 value;
};
4、经典V4L2应用程序
#include <linux/videodev2.h>
int main(void)
{
int fd;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_frmsizeenum fsenum;
int frame_index = 0;
fd = open("/dev/video1", O_RDWR);
1.列出帧细节
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc); //获取帧格式
fsenum.index = 0;
fsenum.pixel_format = fmtdesc.pixelformat;
ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &fsenum); //获取帧大小
2.查询摄像头设备能力
struct v4l2_capability cap;
ioctl(fd, VIDIOC_QUERYCAP, &cap);
3.设置格式
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixleformat = V4L2_PIX_FMT_MJPEG;
ioctl(fd, VIDIOC_S_FMT, &fmt)
4.申请buffer
1)申请buffer
struct v4l2_requestbuffers rb;
rb.count = 1;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_REQBUFS, &rb);
2)mmap buffer才可以使用
struct v4l2_buffer buf;
buf.index = 0;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_QUERYBUF, &buf);
mmap(0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
5.启动摄像头
ioctl(fd, VIDIOC_STREAMON, &type);
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_DQBUF, &buf);
6.保存buf为jpg文件
int fd_file = open("capture.jpg", O_RDWR | O_CREAT, 0666);
write(fd_file, bufs[buf.index], buf.bytesused);
close(fd_file,)
7.将buf重新放回队列使用
ioctl(fd, VIDIOC_QBUF, &buf)
8.关闭摄像头
ioctl(fd, VIDIOC_STREAMOFF, &type)
9.设置亮度
1)查询亮度信息 - 最大值、最小值、当前值等信息
struct v4l2_queryctrl qctrl;
qctrl.id = V4L2_CID_BRIGHTNESS; // V4L2_CID_BASE+0;
ioctl(fd, VIDIOC_QUERYCTRL, &qctrl)
2)设置亮度为80
struct v4l2_control ctl;
ctl.id = V4L2_CID_BRIGHTNESS; // V4L2_CID_BASE+0;
ctl.value = 80;
ioctl(fd, VIDIOC_S_CTRL, &ctl);
}
5、UVC应用程序
1)UVC(USB Video class)相对V4L2的操作,稍微有些不同,有少量UVC的特定操作,但大体都使用V4L2 IOCTL来工作;
2)基于USB摄像头的轻量级开源视频流服务器项目(支持命令行),里面有很多UVC摄像头的示例:
https://github.com/jacksonliam/mjpg-streamer
3)源码分析
1.数据结构
1) IOCTL
#define UVCIOC_CTRL_MAP _IOWR('u', 0x20, struct uvc_xu_control_mapping)
#define UVCIOC_CTRL_QUERY _IOWR('u', 0x21, struct uvc_xu_control_query)
2) uvc_xu_control_query
/android/vendor/amlogic/common/kernel/common_5.4/include/uapi/linux/uvcvideo.h
XU:Extension Unit(扩展单元),厂家可以在XU上提供自定义的操作
struct uvc_xu_control_query {
__u8 unit;
__u8 selector;
__u8 query; /* Video Class-Specific Request Code, */
/* defined in linux/usb/video.h A.8. */
__u16 size;
__u8 __user *data;
};
2.UVC摄像头扩展功能Mapping
mjpg-streamer\mjpg-streamer-experimental\plugins\input_uvc\dynctrl.c
struct uvc_xu_control_mapping xu_mappings[] = {
{
.id = V4L2_CID_LED1_MODE_LOGITECH,
.name = "LED1 Mode",
.entity = UVC_GUID_LOGITECH_USER_HW_CONTROL,
.selector = XU_HW_CONTROL_LED1,
.size = 8,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
},
}
xioctl(fd, UVCIOC_CTRL_MAP, &xu_mappings[i])
3.其它功能与经典V4L2类似,操作都是使用V4L2 ioctl来进行;
更多推荐




所有评论(0)