V4L2开发应用流程的各类超实用VIDIOC命令及其结构体集锦

  本人作为初入音视频领域的新人,观摩了各位大佬关于V4L2详细开发流程的满满干货,特意为这两周的学习做个总结,希望后来者能顺利完成关于V4L2的第一个demo。这期内容主要内容为V4L2的各类实用VIDIOC命令调用,各命令顺序总体上呈现的一个V4L2开发流程。

读前必看:
 1. 在函数原型中出现的 int request , 其中request 参数即所属的VIDIOC命令。
 2. 在例程中出现的函数形参 int fd , fd 是open()函数返回的文件描述符。
 3. 各类VIDIOC命令相关的ioctl接口函数返回值 ret,若小于零,则表示函数调用失败,若等于零,表示成功执行。
 4. 各类VIDIOC命令相关的ioctl接口函数最好有执行失败检测,方便后续调试找问题。
 5. 常用的ioctl接口命令也在include/linux/videodev2.h中定义,则V4L2 必备的头文件:#include <linux/videodev2.h>。
 6. 挖掘头文件的时候,也看看 “/include/media/v4l2-dev.h”,它定义了很多V4L2 ioctl()
将要用到的结构体。

常用的VIDIOC命令:
 1. VIDIOC_QUERYCAP (查询设备属性)
 2. VIDIOC_ENUM_FMT (显示所有支持的格式)
 3. VIDIOC_S_FMT (设置视频捕获格式)
 4. VIDIOC_G_FMT (获取硬件现在的视频捕获格式)
 5. VIDIOC_TRY_FMT (检查是否支持某种帧格式)
 6. VIDIOC_ENUM_FRAMESIZES (枚举设备支持的分辨率信息)
 7. VIDIOC_ENUM_FRAMEINTERVALS (获取设备支持的帧间隔)
 8. VIDIOC_S_PARM && VIDIOC_G_PARM (设置和获取流参数)
 9. VIDIOC_QUERYCAP (查询驱动的修剪能力)
 10. VIDIOC_S_CROP (设置视频信号的边框)
 11. VIDIOC_G_CROP (读取设备信号的边框)
 12. VIDIOC_REQBUFS (向设备申请缓存区)
 13. VIDIOC_QUERYBUF (获取缓存帧的地址、长度)
 14. VIDIOC_QBUF (把帧放入队列)
 15. VIDIOC_DQBUF (从队列中取出帧)
 16. VIDIOC_STREAMON && VIDIOC_STREAMOFF (启动/停止视频数据流)

一. 视频捕获设备的打开和关闭

1.打开设备
  open()
  头文件:
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  函数原型: int fd=open(const char *pathname, int flags);
      or int fd=open(const char *pathname, int flags, mode_t mode);
   ps: 基本上用第一个函数原型

  函数参数:
  1. pathname:打开文件的路径名 ,如 “/dev/video0” ,也可以是预定义字符串的宏,或char*类型的字符串指针。
  2. flags:用来控制打开文件的模式。
  3. mode:用来设置创建文件的权限(rwx). 当flags使用 O_CREAT时才有效。

  flags参数详解:
  1. O_READONLY: 只读模式
  2. O_WRONLY :只写模式
  3. O_RDWR: 可读可写模式

  返回值:
  1.调用失败: 返回-1,并修改errno
  2. 调用成功: 返回一个int类型的文件描述符fd

  应用于V4L2的实例,打开设备节点: /dev/video0,则int fd = open("/dev/video0", O_RDWR);。

2.关闭设备
  头文件:#include <unistd.h>
  原型: int close(int fd);
  实例: close(fd);

二. 查询、设置、获取设备属性(QUERY,ENUM, SET, GET)

2.1 VIDIOC_QUERYCAP
  Fun:查询设备属性,即查询你是谁,你能干什么?
  函数原型:int ioctl(int fd, int request, struct v4l2_capability *argp);
  ps: 此处request 即 VIDIOC_QUERYCAP

 /*相关结构体:*/
struct v4l2_capability
{
  __u8  driver[16];        // 驱动名字
  __u8  card[32];          // 设备名字
  __u8  bus_info[32];      // 设备在系统中的位置
  __u32 version;           // 驱动版本号
  __u32 capabilities;      // 设备支持的操作
  __u32 reserved[4];       // 保留字段
};

  其中capabilities在摄像头中设置值为 V4L2_CAP_VIDEO_CAPTURE

 //例程:
int querycap_camera(int fd)
{
  //获取驱动信息,VIDIOC_QUERCAP
  struct v4l2_capability cap;
  int ret = 0;
  memset(&cap,0, sizeof(cap));
  ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
  if(ret < 0)
  {
    printf("VIDIOC_QUERYCAP failed(%d)\n", ret);
    return -1;
  }
  else
  {
    /*输出 caoability 信息*/
    printf("Capability Informations:\n");
    printf(" driver: %s\n", cap.driver);
    printf(" card: %s\n", cap.card);
    printf(" bus_info: %s\n", cap.bus_info);
    printf(" version: %08X\n", cap.version);
    printf(" capabilities: %08X\n", cap.capabilities);
  }
  printf("--------------------\n");		//可作为分割线。
  return ret;				
}

2.2 图像格式四剑客:
  1. VIDIOC_ENUM_FMT (显示所有支持的格式)
  2. VIDIOC_S_FMT(设置视频捕获格式)
  3. VIDIOC_G_FMT(获取硬件现在的视频捕获格式)
  4. VIDIOC_TRY_FMT(检查是否支持某种帧格式)

1. VIDIOC_ENUM_FMT
  Fun:显示所有支持的格式,即允许应用查询所支持的格式,属于格式协商的部分
  函数原型: int ioctl(int fd, int request, struct v4l2_fmtdesc *argp);
  此处 request 即 VIDIOC_ENUM_FMT,后续request 都由前文标注的VIDIOC 命令代替。

//相关的结构体:	
struct v4l2_fmtdesc
{
  __u32  index;   	           // 要查询的格式序号,应用程序设置
  enum   v4l2_buf_type type;   // 帧类型,应用程序设置
  __u32  flags;    			   // 是否为压缩格式
  __u8   description[32];      // 格式名称
  __u32  pixelformat;		   // 格式
  __u32	 reserved[4]; 		  // 保留,不使用设置为0
};

 参数分析:
  1. index :是用来确定格式的一个简单整型数。与其他V4L2所使用的索引一样,这个也是从0开始递增,至最大允许值为止。应用可以通过一直递增索引值知道返回-EINVAL的方式枚举所有支持的格式。
  2. type:是描述数据流类型的字段。对于视频捕获设备(摄像头或调谐器)来说,就是V4L2_BUF_TYPE_VIDEO_CAPTURE。
  3. flags: 只定义了一个值,即V4L2_FMT_FLAG_COMPRESSED,表示这是一个压缩的视频格式。
  4. description: 是对这个格式的一种简短的字符串描述。
  5. pixelformat: 应是描述视频表现方式的四字符码
  ps: 其中第3、4、5项为就index所支持的某个图像格式,V4L2驱动会自动填写的结构体成员信息。

//fun: display all supported formats
void enum_camera_format(int fd)
{
  struct v4l2_fmtdesc fmtdesc;
  memset(&fmtdesc, 0, sizeof(fmtdesc));
  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  printf("Supported format:\n");
  while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)
  {
    printf("\t%d.%s\n",fmtdesc.index+1, fmtdesc.description);	
    fmtdesc.index++;
  }
}

2. VIDIOC_S_FMT
  Fun:设置视频捕获格式
  函数原型: int ioctl(int fd, int request, struct v4l2_format* argp);

//相关的结构体	
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;  
}; 

  PS: 此处type 用于视频捕获设备来说也就是V4L2_BUF_TYPE_VIDEO_CAPTURE,对应fmt共用体中的
pix,即pix是重点。

//其中:
enum v4l2_buf_type 
{  
    V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,  
    V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,  
    V4L2_BUF_TYPE_VIDEO_OVERLAY   
  • 9
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值