ubuntu驱动开发吧 关注:25贴子:177
  • 1回复贴,共1

v4l2 编程接口(一) — ioctl

只看楼主收藏回复

在应用程序获取视频数据的流程中,都是通过 ioctl 命令与驱动程序进行交互,常见的 ioctl 命令有:
VIDIOC_QUERYCAP /* 获取设备支持的操作 */
VIDIOC_G_FMT /* 获取设置支持的视频格式 */
VIDIOC_S_FMT /* 设置捕获视频的格式 */
VIDIOC_REQBUFS /* 向驱动提出申请内存的请求 */
VIDIOC_QUERYBUF /* 向驱动查询申请到的内存 */
VIDIOC_QBUF /* 将空闲的内存加入可捕获视频的队列 */
VIDIOC_DQBUF /* 将已经捕获好视频的内存拉出已捕获视频的队列 */
VIDIOC_STREAMON /* 打开视频流 */
VIDIOC_STREAMOFF /* 关闭视频流 */
VIDIOC_QUERYCTRL /* 查询驱动是否支持该命令 */
VIDIOC_G_CTRL /* 获取当前命令值 */
VIDIOC_S_CTRL /* 设置新的命令值 */
VIDIOC_G_TUNER /* 获取调谐器信息 */
VIDIOC_S_TUNER /* 设置调谐器信息 */
VIDIOC_G_FREQUENCY /* 获取调谐器频率 */
VIDIOC_S_FREQUENCY /* 设置调谐器频率 */
1、struct v4l2_capability 与 VIDIOC_QUERYCAP
VIDIOC_QUERYCAP 命令通过结构 v4l2_capability 获取设备支持的操作模式:
[cpp] view plain copy
struct v4l2_capability {
__u8 driver[16]; /* i.e. "bttv" */
__u8 card[32]; /* i.e. "Hauppauge WinTV" */
__u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
__u32 version; /* should use KERNEL_VERSION() */
__u32 capabilities; /* Device capabilities */
__u32 reserved[4];
};
其中域 capabilities 代表设备支持的操作模式,常见的值有 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING 表示是一个视频捕捉设备并且具有数据流控制模式;另外 driver 域需要和 struct video_device 中的 name 匹配。
2、struct v4l2_format 与 VIDIOC_G_FMT、VIDIOC_S_FMT、VIDIOC_TRY_FMT
通常用 VIDIOC_S_FMT 命令通过结构 v4l2_format 初始化捕获视频的格式,如果要改变格式则用 VIDIOC_TRY_FMT 命令:
[cpp] view plain copy
struct v4l2_format {
enum v4l2_buf_type type;
union {
struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
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 */
__u8 raw_data[200]; /* user-defined */
} fmt;
};
其中
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_PRIVATE = 0x80,
};
struct v4l2_pix_format {
__u32 width;
__u32 height;
__u32 pixelformat;
enum v4l2_field field;
__u32 bytesperline; /* for padding, zero if unused */
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv; /* private data, depends on pixelformat */
};
常见的捕获模式为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即视频捕捉模式,在此模式下 fmt 联合体采用域 v4l2_pix_format:其中 width 为视频的宽、height 为视频的高、pixelformat 为视频数据格式(常见的值有 V4L2_PIX_FMT_YUV422P | V4L2_PIX_FMT_RGB565)、bytesperline 为一行图像占用的字节数、sizeimage 则为图像占用的总字节数、colorspace 指定设备的颜色空间。
3、struct v4l2_requestbuffers 与 VIDIOC_REQBUFS
VIDIOC_REQBUFS 命令通过结构 v4l2_requestbuffers 请求驱动申请一片连续的内存用于缓存视频信息:
[cpp] view plain copy
struct v4l2_requestbuffers {
__u32 count;
enum v4l2_buf_type type;
enum v4l2_memory memory;
__u32 reserved[2];
};
其中
enum v4l2_memory {
V4L2_MEMORY_MMAP = 1,
V4L2_MEMORY_USERPTR = 2,
V4L2_MEMORY_OVERLAY = 3,
};
count 指定根据图像占用空间大小申请的缓存区个数,type 为视频捕获模式,memory 为内存区的使用方式。
4、struct v4l2_buffer与 VIDIOC_QUERYBUF
VIDIOC_QUERYBUF 命令通过结构 v4l2_buffer 查询驱动申请的内存区信息:
[cpp] view plain copy
struct v4l2_buffer {
__u32 index;
enum v4l2_buf_type type;
__u32 bytesused;
__u32 flags;
enum v4l2_field field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
/* memory location */
enum v4l2_memory memory;
union {
__u32 offset;
unsigned long userptr;
} m;
__u32 length;
__u32 input;
__u32 reserved;
};
index 为缓存编号,type 为视频捕获模式,bytesused 为缓存已使用空间大小,flags 为缓存当前状态(常见值有 V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE,分别代表当前缓存已经映射、缓存可以采集数据、缓存可以提取数据),timestamp 为时间戳,sequence为缓存序号,memory 为缓存使用方式,offset 为当前缓存与内存区起始地址的偏移,length 为缓存大小,reserved 一般用于传递物理地址值。
另外 VIDIOC_QBUF 和 VIDIOC_DQBUF 命令都采用结构 v4l2_buffer 与驱动通信:VIDIOC_QBUF 命令向驱动传递应用程序已经处理完的缓存,即将缓存加入空闲可捕获视频的队列,传递的主要参数为 index;VIDIOC_DQBUF 命令向驱动获取已经存放有视频数据的缓存,v4l2_buffer 的各个域几乎都会被更新,但主要的参数也是 index,应用程序会根据 index 确定可用数据的起始地址和范围。


IP属地:安徽1楼2016-05-10 22:04回复
    5、enum v4l2_buf_type 与 VIDIOC_STREAMON、VIDIOC_STREAMOFF
    这两个命令使用的只是一个整形数据,即 v4l2_buf_type,一般只要指定其值为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即可。
    6、struct v4l2_queryctrl 与 VIDIOC_QUERYCTRL
    VIDIOC_QUERYCTRL 命令通过结构 v4l2_queryctrl 查询驱动是否支持该 id 代表的命令,并返回该命令的各种参数:
    [cpp] view plain copy
    struct v4l2_queryctrl {
    __u32 id; /* 命令编号 */
    enum v4l2_ctrl_type type; /* 命令值的类型 */
    __u8 name[32]; /* 命令名称*/
    __s32 minimum; /* 最小的命令值 */
    __s32 maximum; /* 最大的命令值 */
    __s32 step; /* 命令值变化的步长 */
    __s32 default_value; /* 默认的命令值 */
    __u32 flags; /* 命令的标志 */
    __u32 reserved[2]; /* 命令值的位图表示 */
    };
    其中
    enum v4l2_ctrl_type {
    V4L2_CTRL_TYPE_INTEGER = 1, /* 整形 */
    V4L2_CTRL_TYPE_BOOLEAN = 2, /* 真值 */
    V4L2_CTRL_TYPE_MENU = 3, /* 菜单 */
    V4L2_CTRL_TYPE_BUTTON = 4, /* 无值 */
    V4L2_CTRL_TYPE_INTEGER64 = 5, /* 后面三种不常用 */
    V4L2_CTRL_TYPE_CTRL_CLASS = 6,
    V4L2_CTRL_TYPE_STRING = 7,
    };
    命令的标志取值如下:
    /* Control flags */
    #define V4L2_CTRL_FLAG_DISABLED 0x0001
    #define V4L2_CTRL_FLAG_GRABBED 0x0002
    #define V4L2_CTRL_FLAG_READ_ONLY 0x0004
    #define V4L2_CTRL_FLAG_UPDATE 0x0008
    #define V4L2_CTRL_FLAG_INACTIVE 0x0010
    #define V4L2_CTRL_FLAG_SLIDER 0x0020
    #define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040
    /* Query flag, to be ORed with the control ID */
    #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000
    id 是命令的编号,常见的命令有两种:一种以 V4L2_CID_BASE 为起始值,是公用命令;一种以 V4L2_CID_PRIVATE_BASE 为起始值,是私有命令。在一般的应用中命令值可见如下:
    [cpp] view plain copy
    V4L2_CID_CONTRAST (V4L2_CID_BASE+1) /* 对比度调节 */
    V4L2_CID_SATURATION (V4L2_CID_BASE+2) /* 饱和度调节 */
    V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) /* 音量调节 */
    V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) /* 静音设置 */
    V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) /* 白平衡调节 */
    V4L2_CID_GAMMA (V4L2_CID_BASE+16) /* 伽马值调节 */
    V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) /* 曝光度调节 */
    V4L2_CID_PRIVATE_ATXX_FLASH (V4L2_CID_PRIVATE_BASE + 2) /* 闪光灯控制 */
    V4L2_CID_PRIVATE_ATXX_FRAME (V4L2_CID_PRIVATE_BASE + 12) /* 帧率调节 */
    type 为命令值的类型(总共有7中类型的值),name 是命令的名称,reserved 则是命令值的位图表示,驱动会将所有的命令值都以 bit 的形式写到 64 位的域中,上层应用查询时可以根据位图判断命令支持的值。
    7、struct v4l2_control 与 VIDIOC_G_CTRL、VIDIOC_S_CTRL
    VIDIOC_S_CTRL 或 VIDIOC_G_CTRL 命令通过结构 v4l2_control 设置或者获取 id 命令的值:
    [cpp] view plain copy
    struct v4l2_control {
    __u32 id;
    __s32 value;
    };
    这个结构只有 2 个域,id 是命令编号,value 则是命令的值。
    8、struct v4l2_tuner 与 VIDIOC_G_TUNER、VIDIOC_S_TUNER
    VIDIOC_S_TUNER 或 VIDIOC_G_TUNER 命令通过结构 v4l2_tuner 设置调谐器的信息:
    [cpp] view plain copy
    struct v4l2_tuner {
    __u32 index; /* 调谐器编号,由应用程序设置 */
    __u8 name[32]; /* 调谐器名称 */
    enum v4l2_tuner_type type; /* 调谐器类型 */
    __u32 capability; /* 调谐器支持的操作 */
    __u32 rangelow; /* 最低频率值,单位为62.5Hz或者62.5KHz */
    __u32 rangehigh; /* 最高频率值 */
    __u32 rxsubchans; /* 接收的音频信号类型 */
    __u32 audmode; /* 当前音频播放形式 */
    __s32 signal; /* 信号强度 */
    __s32 afc; /* 自动频率控制 */
    __u32 reserved[4]; /* 保留备用 */
    };
    其中
    enum v4l2_tuner_type {
    V4L2_TUNER_RADIO = 1, /* 调频收音机 */
    V4L2_TUNER_ANALOG_TV = 2, /* 模拟电视高频头 */
    V4L2_TUNER_DIGITAL_TV = 3, /* 数字电视高频头 */
    };
    其中域 type 有三种类型;capability 域一般为 V4L2_TUNER_CAP_LOW,表明频率调节的步长是62.5Hz,如果没有这个标志位则步长为62.5KHz;rangelow 与 rangehigh 是调谐器可以调频率的最高值和最低值,但都以步长为单位表示;rxsubchans 表示调谐器接收的音频信号类型,常见值有 V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO 即单声道与立体声;audmode 表示以何种方式播放声音,常见值有 V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO,即以单声道还是立体声的方式播放;signal 为当前信号强度,一般取值范围为 0 - 65535。


    IP属地:安徽2楼2016-05-10 22:07
    回复