v4l2编程接口

以下内容来自:http://blog.csdn.net/g_salamander/article/details/8107692

在应用程序获取视频数据的流程中,都是通过 ioctl 命令与驱动程序进行交互,常见的 ioctl 命令有:

[cpp] view plaincopy

  1. VIDIOC_QUERYCAP     /* 获取设备支持的操作 */
  2. VIDIOC_G_FMT        /* 获取设置支持的视频格式 */
  3. VIDIOC_S_FMT        /* 设置捕获视频的格式 */
  4. VIDIOC_REQBUFS      /* 向驱动提出申请内存的请求 */
  5. VIDIOC_QUERYBUF     /* 向驱动查询申请到的内存 */
  6. VIDIOC_QBUF         /* 将空闲的内存加入可捕获视频的队列 */
  7. VIDIOC_DQBUF        /* 将已经捕获好视频的内存拉出已捕获视频的队列 */
  8. VIDIOC_STREAMON     /* 打开视频流 */
  9. VIDIOC_STREAMOFF    /* 关闭视频流 */
  10. VIDIOC_QUERYCTRL    /* 查询驱动是否支持该命令 */
  11. VIDIOC_G_CTRL       /* 获取当前命令值 */
  12. VIDIOC_S_CTRL       /* 设置新的命令值 */
  13. VIDIOC_G_TUNER      /* 获取调谐器信息 */
  14. VIDIOC_S_TUNER      /* 设置调谐器信息 */
  15. VIDIOC_G_FREQUENCY  /* 获取调谐器频率 */
  16. VIDIOC_S_FREQUENCY  /* 设置调谐器频率 */

1、struct v4l2_capability 与 VIDIOC_QUERYCAP
VIDIOC_QUERYCAP 命令通过结构 v4l2_capability 获取设备支持的操作模式:

[cpp] view plaincopy

  1. struct v4l2_capability {
  2. __u8    driver[16];     /* i.e. "bttv" */
  3. __u8    card[32];       /* i.e. "Hauppauge WinTV" */
  4. __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
  5. __u32   version;        /* should use KERNEL_VERSION() */
  6. __u32   capabilities;   /* Device capabilities */
  7. __u32   reserved[4];
  8. };

其中域 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 plaincopy

  1. struct v4l2_format {
  2. enum v4l2_buf_type type;
  3. union {
  4. struct v4l2_pix_format         pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
  5. struct v4l2_window             win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
  6. struct v4l2_vbi_format         vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
  7. struct v4l2_sliced_vbi_format  sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
  8. __u8   raw_data[200];                   /* user-defined */
  9. } fmt;
  10. };
  11. 其中
  12. enum v4l2_buf_type {
  13. V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,
  14. V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,
  15. V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,
  16. ...
  17. V4L2_BUF_TYPE_PRIVATE              = 0x80,
  18. };
  19. struct v4l2_pix_format {
  20. __u32                   width;
  21. __u32                   height;
  22. __u32                   pixelformat;
  23. enum v4l2_field         field;
  24. __u32                   bytesperline;   /* for padding, zero if unused */
  25. __u32                   sizeimage;
  26. enum v4l2_colorspace    colorspace;
  27. __u32                   priv;           /* private data, depends on pixelformat */
  28. };

常见的捕获模式为 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 plaincopy

  1. struct v4l2_requestbuffers {
  2. __u32                   count;
  3. enum v4l2_buf_type      type;
  4. enum v4l2_memory        memory;
  5. __u32                   reserved[2];
  6. };
  7. 其中
  8. enum v4l2_memory {
  9. V4L2_MEMORY_MMAP             = 1,
  10. V4L2_MEMORY_USERPTR          = 2,
  11. V4L2_MEMORY_OVERLAY          = 3,
  12. };

count 指定根据图像占用空间大小申请的缓存区个数,type 为视频捕获模式,memory 为内存区的使用方式。

4、struct v4l2_buffer与 VIDIOC_QUERYBUF

VIDIOC_QUERYBUF 命令通过结构 v4l2_buffer 查询驱动申请的内存区信息:

[cpp] view plaincopy

  1. struct v4l2_buffer {
  2. __u32                   index;
  3. enum v4l2_buf_type      type;
  4. __u32                   bytesused;
  5. __u32                   flags;
  6. enum v4l2_field         field;
  7. struct timeval          timestamp;
  8. struct v4l2_timecode    timecode;
  9. __u32                   sequence;
  10. /* memory location */
  11. enum v4l2_memory        memory;
  12. union {
  13. __u32           offset;
  14. unsigned long   userptr;
  15. } m;
  16. __u32                   length;
  17. __u32                   input;
  18. __u32                   reserved;
  19. };

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 确定可用数据的起始地址和范围。

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 plaincopy

  1. struct v4l2_queryctrl {
  2. __u32                id;            /* 命令编号 */
  3. enum v4l2_ctrl_type  type;          /* 命令值的类型 */
  4. __u8                 name[32];      /* 命令名称*/
  5. __s32                minimum;       /* 最小的命令值 */
  6. __s32                maximum;       /* 最大的命令值 */
  7. __s32                step;          /* 命令值变化的步长 */
  8. __s32                default_value; /* 默认的命令值 */
  9. __u32                flags;         /* 命令的标志 */
  10. __u32                reserved[2];   /* 命令值的位图表示 */
  11. };
  12. 其中
  13. enum v4l2_ctrl_type {
  14. V4L2_CTRL_TYPE_INTEGER       = 1,   /* 整形 */
  15. V4L2_CTRL_TYPE_BOOLEAN       = 2,   /* 真值 */
  16. V4L2_CTRL_TYPE_MENU          = 3,   /* 菜单 */
  17. V4L2_CTRL_TYPE_BUTTON        = 4,   /* 无值 */
  18. V4L2_CTRL_TYPE_INTEGER64     = 5,   /* 后面三种不常用 */
  19. V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
  20. V4L2_CTRL_TYPE_STRING        = 7,
  21. };
  22. 命令的标志取值如下:
  23. /*  Control flags  */
  24. #define V4L2_CTRL_FLAG_DISABLED     0x0001
  25. #define V4L2_CTRL_FLAG_GRABBED      0x0002
  26. #define V4L2_CTRL_FLAG_READ_ONLY    0x0004
  27. #define V4L2_CTRL_FLAG_UPDATE       0x0008
  28. #define V4L2_CTRL_FLAG_INACTIVE     0x0010
  29. #define V4L2_CTRL_FLAG_SLIDER       0x0020
  30. #define V4L2_CTRL_FLAG_WRITE_ONLY   0x0040
  31. /*  Query flag, to be ORed with the control ID */
  32. #define V4L2_CTRL_FLAG_NEXT_CTRL    0x80000000

id 是命令的编号,常见的命令有两种:一种以 V4L2_CID_BASE 为起始值,是公用命令;一种以 V4L2_CID_PRIVATE_BASE 为起始值,是私有命令。在一般的应用中命令值可见如下:

[cpp] view plaincopy

  1. V4L2_CID_CONTRAST               (V4L2_CID_BASE+1)            /* 对比度调节 */
  2. V4L2_CID_SATURATION             (V4L2_CID_BASE+2)            /* 饱和度调节 */
  3. V4L2_CID_AUDIO_VOLUME           (V4L2_CID_BASE+5)            /* 音量调节 */
  4. V4L2_CID_AUDIO_MUTE             (V4L2_CID_BASE+9)            /* 静音设置 */
  5. V4L2_CID_DO_WHITE_BALANCE       (V4L2_CID_BASE+13)           /* 白平衡调节 */
  6. V4L2_CID_GAMMA                  (V4L2_CID_BASE+16)           /* 伽马值调节 */
  7. V4L2_CID_EXPOSURE               (V4L2_CID_BASE+17)           /* 曝光度调节 */
  8. V4L2_CID_PRIVATE_ATXX_FLASH     (V4L2_CID_PRIVATE_BASE + 2)  /* 闪光灯控制 */
  9. 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 plaincopy

  1. struct v4l2_control {
  2. __u32            id;
  3. __s32            value;
  4. };

这个结构只有 2 个域,id 是命令编号,value 则是命令的值。

8、struct v4l2_tuner 与 VIDIOC_G_TUNER、VIDIOC_S_TUNER

VIDIOC_S_TUNER 或 VIDIOC_G_TUNER 命令通过结构 v4l2_tuner 设置调谐器的信息:

[cpp] view plaincopy

  1. struct v4l2_tuner {
  2. __u32                   index;           /* 调谐器编号,由应用程序设置 */
  3. __u8                    name[32];        /* 调谐器名称 */
  4. enum v4l2_tuner_type    type;            /* 调谐器类型 */
  5. __u32                   capability;      /* 调谐器支持的操作 */
  6. __u32                   rangelow;        /* 最低频率值,单位为62.5Hz或者62.5KHz */
  7. __u32                   rangehigh;       /* 最高频率值 */
  8. __u32                   rxsubchans;      /* 接收的音频信号类型 */
  9. __u32                   audmode;         /* 当前音频播放形式 */
  10. __s32                   signal;          /* 信号强度 */
  11. __s32                   afc;             /* 自动频率控制 */
  12. __u32                   reserved[4];     /* 保留备用 */
  13. };
  14. 其中
  15. enum v4l2_tuner_type {
  16. V4L2_TUNER_RADIO             = 1,        /* 调频收音机 */
  17. V4L2_TUNER_ANALOG_TV         = 2,        /* 模拟电视高频头 */
  18. V4L2_TUNER_DIGITAL_TV        = 3,        /* 数字电视高频头 */
  19. };

其中域 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。
9、struct v4l2_frequency 与 VIDIOC_G_FREQUENCY、VIDIOC_S_FREQUENCY

VIDIOC_S_FREQUENCY 或 VIDIOC_G_FREQUENCY 命令通过结构 v4l2_frequency 设置或获取当前频率值:

[cpp] view plaincopy

  1. struct v4l2_frequency {
  2. __u32                 tuner;          /* 调谐器编号 */
  3. enum v4l2_tuner_type  type;           /* 调谐器类型 */
  4. __u32                 frequency;      /* 调谐器频率 */
  5. __u32                 reserved[8];
  6. };

注意:frequency 的值是以62.5Hz 或者 62.5KHZ 为单位的。

附:_IO、_IOR、_IOW、_IOWR 宏的使用说明

驱动程序中 ioctl  函数传递的变量 cmd 是应用程序向驱动程序请求处理的命令。cmd 除了用于区别不同命令的数值,还可包含有助于处理的几种信息。cmd 的大小为 32 bit,共分 4 个域:

bit29 ~ bit31: 3bit  为 “读写” 区,作用是区分是读命令还是写命令。
bit16 ~ bit28:13bit 为 "数据大小" 区,表示 ioctl 中的 arg 变量传递的数据大小;有时候为 14bit 即将 bit29 覆盖。
bit8 ~ bit15:   8bit  为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。
bit0 ~ bit7:     8bit  为 "序号" 区,是区分命令的命令顺序序号。

魔数(magic number)
魔数范围为 0~255 。通常,用英文字符 ‘A‘ ~ ‘Z‘ 或者 ‘a‘ ~ ‘z‘ 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助参数。设备驱动程序可以通过宏 _IOC_TYPE (cmd) 来获取魔数。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。

基数(序号)
基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读和写命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时使用 switch ,且直接使用命令变量 cmd 值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序想要从命令中获取该基数,就使用宏 _IOC_NR (cmd)。

下面我们看一下上述宏在内核中的原型:

[cpp] view plaincopy

  1. /*
  2. * Our DIR and SIZE overlap in order to simulteneously provide
  3. * a non-zero _IOC_NONE (for binary compatibility) and
  4. * 14 bits of size as on i386. Here‘s the layout:
  5. *
  6. *   0xE0000000   DIR            3bit
  7. *   0x80000000   DIR = WRITE    bit31
  8. *   0x40000000   DIR = READ     bit30
  9. *   0x20000000   DIR = NONE     bit29
  10. *   0x3FFF0000   SIZE (overlaps NONE bit)  13bit
  11. *   0x0000FF00   TYPE           8bit
  12. *   0x000000FF   NR (CMD)       8bit
  13. */
  14. /* 各个域的长度 */
  15. #define _IOC_NRBITS      8
  16. #define _IOC_TYPEBITS    8
  17. #define _IOC_SIZEBITS   13  /* Actually 14, see below. */
  18. #define _IOC_DIRBITS     3
  19. /* 各个域的掩码 */
  20. #define _IOC_NRMASK      ((1 << _IOC_NRBITS)-1)
  21. #define _IOC_TYPEMASK    ((1 << _IOC_TYPEBITS)-1)
  22. #define _IOC_SIZEMASK    ((1 << _IOC_SIZEBITS)-1)
  23. #define _IOC_XSIZEMASK   ((1 << (_IOC_SIZEBITS+1))-1)
  24. #define _IOC_DIRMASK     ((1 << _IOC_DIRBITS)-1)
  25. /* 各个域的偏移 */
  26. #define _IOC_NRSHIFT     0
  27. #define _IOC_TYPESHIFT   (_IOC_NRSHIFT + _IOC_NRBITS)       /* 8 */
  28. #define _IOC_SIZESHIFT   (_IOC_TYPESHIFT + _IOC_TYPEBITS)   /* 16 */
  29. #define _IOC_DIRSHIFT    (_IOC_SIZESHIFT + _IOC_SIZEBITS)   /* 29 */
  30. /* 读写域的值 */
  31. #define _IOC_NONE        1U
  32. #define _IOC_READ        2U
  33. #define _IOC_WRITE       4U
  34. #define _IOC(dir,type,nr,size) \
  35. (((dir)  << _IOC_DIRSHIFT) | \      /* 读写方向左移 29bit */
  36. ((type) << _IOC_TYPESHIFT) | \     /* 幻数左移 8bit */
  37. ((nr)   << _IOC_NRSHIFT) | \       /* 命令序号 */
  38. ((size) << _IOC_SIZESHIFT))        /* 参数大小左移 16bit */
  39. /* 宏原型,这里将会根据传递的数据类型取其长度 */
  40. #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
  41. #define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
  42. #define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
  43. #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
  44. /* 获取各个域的值 */
  45. #define _IOC_DIR(nr)        (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
  46. #define _IOC_TYPE(nr)       (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
  47. #define _IOC_NR(nr)         (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
  48. #define _IOC_SIZE(nr)       (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

这里特别说明一下 _IO 宏,该宏没有可传递的变量,只用于发送命令。这是因为变量需要可变数据,只作为命令(比如 reset)使用时,没有必要判断设备上的数据,因此设备驱动程序没有必要执行文件相关的处理。在 v4l2 中使用示例如下:

[cpp] view plaincopy

  1. #define VIDIOC_QUERYCAP      _IOR(‘V‘,  0, struct v4l2_capability)
  2. #define VIDIOC_RESERVED       _IO(‘V‘,  1)
  3. #define VIDIOC_S_FMT        _IOWR(‘V‘,  5, struct v4l2_format)
  4. #define VIDIOC_STREAMON      _IOW(‘V‘, 18, int)

v4l2 中对上述宏命令的处理在 video_ioctl2 函数中:

[cpp] view plaincopy

  1. static unsigned long cmd_input_size(unsigned int cmd)
  2. {
  3. #define CMDINSIZE(cmd, type, field)                 \
  4. case VIDIOC_##cmd:                  \
  5. return offsetof(struct v4l2_##type, field) +    \  /* 域的偏移 */
  6. sizeof(((struct v4l2_##type *)0)->field);      /* 域的长度 */
  7. switch (cmd) {
  8. CMDINSIZE(ENUM_FMT,     fmtdesc,    type);
  9. CMDINSIZE(G_FMT,        format,     type);
  10. ...
  11. CMDINSIZE(ENUM_FRAMESIZES,  frmsizeenum,    pixel_format);
  12. CMDINSIZE(ENUM_FRAMEINTERVALS,  frmivalenum,    height);
  13. default:
  14. return _IOC_SIZE(cmd);  /* 剩下的是需要全部拷贝的命令 */
  15. }
  16. }
  17. long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg)
  18. {
  19. char    sbuf[128];          /* 在栈中分配128个字节空间用来储存命令的参数 */
  20. void    *mbuf = NULL;
  21. void    *parg = NULL;       /* 参数存放的首地址 */
  22. long    err  = -EINVAL;
  23. int     is_ext_ctrl;
  24. size_t  ctrls_size = 0;
  25. void __user *user_ptr = NULL;
  26. ...
  27. /* 判断是否包含读写命令,如果是则将用户空间的参数值拷贝到内核 */
  28. if (_IOC_DIR(cmd) != _IOC_NONE) {
  29. /* 判断参数大小是否超过128字节 */
  30. if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
  31. parg = sbuf;
  32. } else {
  33. /* 如果超过128字节则从堆中申请 */
  34. mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
  35. if (NULL == mbuf)
  36. return -ENOMEM;
  37. parg = mbuf;
  38. }
  39. err = -EFAULT;
  40. /* 如果包含写命令 */
  41. if (_IOC_DIR(cmd) & _IOC_WRITE) {
  42. /* 计算需要拷贝的有效数据长度,有的命令不需要全部拷贝 */
  43. unsigned long n = cmd_input_size(cmd);
  44. /* 从用户空间拷贝参数值 */
  45. if (copy_from_user(parg, (void __user *)arg, n))
  46. goto out;
  47. /* 将剩下的空间清零 */
  48. if (n < _IOC_SIZE(cmd))
  49. memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
  50. } else {
  51. /* 如果是只读命令则将整个buffer清零 */
  52. memset(parg, 0, _IOC_SIZE(cmd));
  53. }
  54. }
  55. ...
  56. /* 调用 v4l2_ioctl_ops 的成员函数处理命令 */
  57. err = __video_do_ioctl(file, cmd, parg);
  58. if (err == -ENOIOCTLCMD)
  59. err = -EINVAL;
  60. ...
  61. if (err < 0)
  62. goto out;
  63. out_ext_ctrl:
  64. /* 如果包含读命令则将参数值拷贝到用户空间 */
  65. switch (_IOC_DIR(cmd)) {
  66. case _IOC_READ:
  67. case (_IOC_WRITE | _IOC_READ):
  68. if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
  69. err = -EFAULT;
  70. break;
  71. }
  72. out:
  73. kfree(mbuf);
  74. return err;
  75. }
  76. EXPORT_SYMBOL(video_ioctl2);

然后我们在 struct v4l2_file_operations 中将 ioctl 成员设置为 video_ioctl2 即可

时间: 2024-10-28 20:26:52

v4l2编程接口的相关文章

摄像头驱动的使能配置、V4L2编程接口的设计应用

摄像头采集子系统 一.摄像头驱动的使能配置 摄像头软件驱动构架 摄像头采集系统由上图所示,硬件(摄像头) -> 驱动(Linux内核配置中,选择支持V4L2的驱动选项) -> V4L2接口设计 -> 图像采集. 硬件:选择USB摄像头,内置芯片ZC30系列,Linux包含的万能驱动兼容: 驱动:配置Linux内核,选择万能摄像头驱动中ZC30系列驱动文件.支持V4L2接口,编译下载内核: 内核下载至开发板并挂载后,摄像头开发环境以搭建完成,以下即为应用采集. V4L2接口:编写基于V4L

操作系统知识点_用户编程接口

3.用户编程接口 函数调用和系统调用 函数调用运行在用户空间,为程序员提供调用真正的幕后完成实际事务的是系统调用接口.系统函数是内核提供给应用程序的接口,属于系统的一部分. 函数调用:调用函数库中的一段程序或函数:与用户程序联系:在用户地址空间执行:运行时间属于"用户时间":属于过程调用,系统开销小: 系统调用:各个系统的系统调用是不同的:调用系统的内核服务:是操作系统的入口点:在内核地址空间执行:"系统"时间:在用户和内核空间切换开销大:unix中有大约90个.如

网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结

引: http://coach.iteye.com/blog/2024511 什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议.这种协议可以提供面向连接的.可靠的.点到点的通信. UDP全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信. 使用TCP还是UDP,那要看你的程序注重哪一个方面,可靠(tcp)还是快速(udp). TCP/IP 建立连接的过程 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.   

Linux系统调用及用户编程接口(API)

系统调用 所谓系统调用是指操作系统提供给用户程序调用的一组"特殊"接口,用户程序可以通过这组"特殊"接口来获得操作系统内核提供的服务.例如用户可以通过进程控制相关的系统调用来创建进程.实现进程调度.进程管理等. 为什么用户程序不能直接访问系统内核提供的服务呢?这是由于在Linux中,为了更好地保护内核空间,将程序的运行空间分为内核空间和用户空间(也就是常称的内核态和用户态),它们分别运行在不同的级别上,在逻辑上是相互隔离的.因此,用户进程在通常情况下不允许访问内核数

了解一下Android常见的编程接口

手机开发的编程模型是什么,了解一下 下面是android的编程接口,看来一下和swing差不多,尤其是异步处理模型. ================================================ UI组件TextViewEditTextTab+TabHostActionBar+FragmentViewPagerSlidingMenu 异步执行AsyncTask 布局LinearLayoutRelativeLayoutFrameLayoutTableLayout 组件Activ

NetBIOS与Winsock编程接口

最近在看网络编程方面的书,由于不是通信专业出身的,以前理解的网络体系感觉就是tcp/ip,最近工作上接触到了一些光环网等乱七八糟的东西,有些基本的LC.SC连接器都不认识.花时间看了下计算机网络体系结构的知识,从ARPRANET开始计算机网络的实现方式可以分为资源子网和通信子网.如下图: 资源子网主要由网络的服务器.工作站.共享的打印机和其他设备及相关软件所组成.通信子网:是指网络中实现网络通信功能的设备及其软件的集合,包括原始的信号中继器.集线器,网桥.交换机.路由器网关等设备.ARPNET出

CUDA C编程入门-编程接口

CUDA C给熟悉C编程语言的人提供一个简单的途径去编写在设备(GPU)上执行的代码. 由一个最小的C语言的扩展集和运行时库组成. 核心的语言扩展在编程模型这一章节已经介绍过了.允许程序员定义核函数并且使用一些新的语法指定核函数每次运行时的grid和block的维数.可以在C语言扩展这个章节里找到扩展的完整描述.所有的含有这些扩展的源代码都需要使用nvcc编译,nvcc的概述可以查看使用nvcc编译这一小节. 在CUDA C运行这一小节介绍运行时.运行时提供在主机执行的用于分配和回收设备内存.设

api (应用程序编程接口)

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节. 原文:http://baike.baidu.com/link?url=Jk71oJNRj5OjUpr6Lf38NF74-EI85FtwXiyye6_Da_cD9-o_9w_TMOpuoFwPf-tIug26_GSMUEGZrUgfpbqN3K

使用 COM 风格的编程接口

使用COM 风格的编程接口 假设不直接使用 COM 库.不创建自己的包装.那么更可能的是使用 COM 风格的编程接口.这是由于如今很多开发商公布应用程序时.提供了首选的互操作程序集(Primary Interop Assemblies).这是预先创建的 COM 包装,因此,我们就不须要再自己考虑用 TlbImp.exe 来创建包装了. 注意 很多其它有关首选的互操作程序集的内容.能够在 MSDN 上找到.http://msdn.microsoft.com/en-us/library/aax7sd