参考:
1. 《android驱动开发权威指南》
2. YellowMax2001 https://blog.csdn.net/u013904227/category_9277668.html
3. linux Kernel source code: 4.4
简介
v4l2接口种类
V4L2在设计时,是要支持很多广泛的设备的,它们之中只有一部分在本质上是真正的视频设备:
可以支持多种设备,它可以有以下几种接口:
-
视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头。V4L2的最初设计就是应用于这种功能的。
-
视频输出接口(video output interface):可以驱动计算机的外围视频图像设备--像可以输出电视信号格式的设备。
-
直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU。
-
视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号。
-
收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流。
v4l2 设备节点
V4l2的主设备号是81,次设备号为0~255;这些次设备号有分为多类设备:视频设备,Radio设备,VBI设备等。因此v4l2对应的节点有:/dev/videoX、/dev/vbiX、/dev/radioX。其中X一般为0~31的顺序号。
在这里插入图片描述 v4l2仍然是基于设备-驱动-总线模型,采用典型的分层结构。用户应用程序通过设备节点,使用文件调用接口和ioctl与内核进行交互。
数据结构及指令
常见数据结构及指令
常见数据结构见下表
数据结构 | 作用 |
---|---|
struct v4l2_requestbuffers | 申请帧缓冲,对应命令VIDIOC_REQBUFS |
struct v4l2_capability | 视频设备的功能,对应命令VIDIOC_QUERYCAP |
struct v4l2_input | 视频输入信息,对应命令VIDIOC_ENUMINPUT |
struct v4l2_standard | 视频制式所采用的标准,对应命令VIDIOC_ENUMSTD |
struct v4l2_format | 帧格式,对应命令VIDIOC_G_FMT,VIDIOC_S_FMT |
struct v4l2_buffer | 驱动中一帧图像缓存,对应命令VIDIOC_QUERYBUF |
struct v4l2_crop | 视频信号矩形边框 |
v4l2_std_id | 视频制式标准ID号 |
v4l2常用IOCTL见下表
IOCTL | 作用 |
---|---|
VIDIOC_REQBUFS | 分配内存 |
VIDIOC_QUERYBUF | 数据缓存转换位物理地址 |
VIDIOC_QUERYCAP | 查询驱动功能 |
VIDIOC_ENUM_FMT | 获取当前支持的视频格式 |
VIDIOC_S_FMT | 设置当前视频捕获格式 |
VIDIOC_G_FMT | 获取当前视频捕获格式 |
VIDIOC_TRY_FMT | 验证当前显示格式 |
VIDIOC_CROPCAP | 查询驱动的修剪能力 |
VIDIOC_S_CROP | 设置视频信号的矩形边框 |
VIDIOC_G_CROP | 读取视频信号的矩形边框 |
VIDIOC_QBUF | 把数据从缓存中读取出来 |
VIDIOC_DQBUF | 把数据放回缓存队列 |
VIDIOC_STREAMON | 开始视频显示函数 |
VIDIOC_STREAMOFF | 结束视频显示函数 |
VIDIOC_QUERYSTD | 检查当前视频设备支持的标准 |
详细介绍
v4l2_requestbuffers
struct v4l2_requestbuffers {
__u32 count;
__u32 type; /* enum v4l2_buf_type */
__u32 memory; /* enum v4l2_memory */
__u32 reserved[2];
};
其中type是v4l2_buf_type
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_VBI_CAPTURE = 4,
V4L2_BUF_TYPE_VBI_OUTPUT = 5,
V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10,
V4L2_BUF_TYPE_SDR_CAPTURE = 11,
V4L2_BUF_TYPE_SDR_OUTPUT = 12,
V4L2_BUF_TYPE_META_CAPTURE = 13,
/* Deprecated, do not use */
V4L2_BUF_TYPE_PRIVATE = 0x80,
};
memory是v4l2_memory
enum v4l2_memory {
V4L2_MEMORY_MMAP = 1,
V4L2_MEMORY_USERPTR = 2,
V4L2_MEMORY_OVERLAY = 3,
V4L2_MEMORY_DMABUF = 4,
};
v4l2_capability
struct v4l2_capability {
__u8 driver[16];
__u8 card[32];
__u8 bus_info[32];
__u32 version;
__u32 capabilities; //整个设备的capabilities
__u32 device_caps; //该设备特有的capabilities
__u32 reserved[3];
};
内核定义了非常多的capabilities,列出部分如下:
#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */
#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */
v4l2_input
struct v4l2_input {
__u32 index; /* Which input */
__u8 name[32]; /* Label */
__u32 type; /* Type of input */
__u32 audioset; /* Associated audios (bitfield) */
__u32 tuner; /* enum v4l2_tuner_type */
v4l2_std_id std;
__u32 status;
__u32 capabilities;
__u32 reserved[3];
};
有三种输入类型
#define V4L2_INPUT_TYPE_TUNER 1
#define V4L2_INPUT_TYPE_CAMERA 2
#define V4L2_INPUT_TYPE_TOUCH 3
有物种tuner_type
enum v4l2_tuner_type {
V4L2_TUNER_RADIO = 1,
V4L2_TUNER_ANALOG_TV = 2,
V4L2_TUNER_DIGITAL_TV = 3,
V4L2_TUNER_SDR = 4,
V4L2_TUNER_RF = 5,
};
非常多中状态,列举部分如下:
/* field 'status' - general */
#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */
#define V4L2_IN_ST_NO_SIGNAL 0x00000002
#define V4L2_IN_ST_NO_COLOR 0x00000004
/* field 'status' - sensor orientation */
/* If sensor is mounted upside down set both bits */
#define V4L2_IN_ST_HFLIP 0x00000010 /* Frames are flipped horizontally */
#define V4L2_IN_ST_VFLIP 0x00000020 /* Frames are flipped vertically */
v4l2_standard
struct v4l2_standard {
__u32 index;
v4l2_std_id id;
__u8 name[24];
struct v4l2_fract frameperiod; /* Frames, not fields */
__u32 framelines;
__u32 reserved[4];
};
主要有PAL、NTSC、MTS/BTSC、analog等制式
v4l2_format
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;
};
- type就是v4l2_buf_type
- fmt是图像格式。多种标准格式或者自定义图像格式中的一种
v4l2_buffer
struct v4l2_buffer {
__u32 index; //帧索引值
__u32 type; //v4l2_buf_type
__u32 bytesused; //已经使用的bytes
__u32 flags; //buffer相关信息的flag
__u32 field; //v4l2_field
struct timeval timestamp; //frame timestamp
struct v4l2_timecode timecode; //frame timecode
__u32 sequence;
/* memory location */
__u32 memory; //v4l2_memory
union {
__u32 offset; //mmap
unsigned long userptr; //userptr
struct v4l2_plane *planes;
__s32 fd; //dmabuf
} m;
__u32 length;
__u32 reserved2;
__u32 reserved;
};
- 内核定义了许多表示buffer信息的flag,列举部分如下
/* Buffer is mapped (flag) */
#define V4L2_BUF_FLAG_MAPPED 0x00000001
/* Buffer is queued for processing */
#define V4L2_BUF_FLAG_QUEUED 0x00000002
/* Buffer is ready */
#define V4L2_BUF_FLAG_DONE 0x00000004
/* Image is a keyframe (I-frame) */
#define V4L2_BUF_FLAG_KEYFRAME 0x00000008
/* Image is a P-frame */
#define V4L2_BUF_FLAG_PFRAME 0x00000010
/* Image is a B-frame */
#define V4L2_BUF_FLAG_BFRAME 0x00000020
/* Buffer is ready, but the data contained within is corrupted. */
#define V4L2_BUF_FLAG_ERROR 0x00000040
/* timecode field is valid */
#define V4L2_BUF_FLAG_TIMECODE 0x00000100
/* Buffer is prepared for queuing */
#define V4L2_BUF_FLAG_PREPARED 0x00000400
- v4l2_field
enum v4l2_field {
V4L2_FIELD_ANY = 0, /* driver can choose from none,
top, bottom, interlaced
depending on whatever it thinks
is approximate ... */
V4L2_FIELD_NONE = 1, /* this device has no fields ... */
V4L2_FIELD_TOP = 2, /* top field only */
V4L2_FIELD_BOTTOM = 3, /* bottom field only */
V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */
V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one
buffer, top-bottom order */
V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */
V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into
separate buffers */
V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field
first and the top field is
transmitted first */
V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field
first and the bottom field is
transmitted first */
};
v4l2_crop
struct v4l2_crop {
__u32 type; /* enum v4l2_buf_type */
struct v4l2_rect c;
};
- v4l2_rect 四边框
struct v4l2_rect {
__s32 left;
__s32 top;
__u32 width;
__u32 height;
};
v4l2_std_id
模拟信号标准id,用位表示
#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001)
#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002)
#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004)
#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008)
#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010)
#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020)
#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040)
#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080)
#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100)
#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200)
#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400)
#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800)
#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) /* BTSC */
#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) /* EIA-J */
#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000)
#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) /* FM A2 */
#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000)
#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000)
#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000)
#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000)
#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000)
/* ATSC/HDTV */
#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
使用示例
下图详细展示了用户空间到内核驱动的 ioctl 调用顺序与调用过程中所涉及到的文件及步骤顺序。(看不清可以下载或者在新标签页中打开查看)
在这里插入图片描述下图详细展示了用户层使用v4l2框架编写一个摄像头采集程序的完整流程。
在这里插入图片描述下面是一个可执行的完整摄像头采集程序示例(可以下载附件查看):
code.zip
个人博客:www.letcos.top
网友评论