v4l2接口解析和摄像头数据采集

v4l2接⼝解析和摄像头数据采集
⽂章⽬录
V4L2接⼝解析
操作步骤
应⽤程序通过V4L2接⼝采集视频数据步骤
打开视频设备⽂件,通过视频采集的参数初始化,通过V4L2接⼝设置视频图像属性。
申请若⼲视频采集的帧缓存区,并将这些帧缓冲区从内核空间映射到⽤户空间,便于应⽤程序读取/处理视频数据。
将申请到的帧缓冲区在视频采集输⼊队列排队,并启动视频采集。
驱动开始视频数据的采集,应⽤程序从视频采集输出队列中取出帧缓冲区,处理后,将帧缓冲区重新放⼊视频采集输⼊队列,循环往复采集连续的视频数据。
停⽌视频采集。
具体实现如下图
图中⽂字
打开视频设备⽂件
int fd_v4l=open("/dev/video0",O_RDWR)
查询视频设备的能⼒
ioctl(fd_v4l,VIDIOC_QUERYCAP,&cap)
设置视频采集的参数
设置视频的制式,制式包括PAL/NTSC
ioctl(fd_v4l,VIDIOC_S_STD,&std_id)
设置视频图像的采集窗⼝的⼤⼩
ioctl(fd_v4l,VIDIOC_S_CROP,&crop)
设置视频帧格式,包括帧的点阵格式,宽度和⾼度等
ioctl(fd_v4l,VIDIOC_S_FMT,&fmt)
设置视频的帧率
ioctl(fd_v4l,VIDIOC_S_PARM,&parm)
设置视频的旋转⽅式
ioctl(fd_v4l,VIDIOC_S_CTRL,&ctrl)
向驱动申请视频流数据的帧缓冲区
请求/申请若⼲个帧缓冲区,⼀般为不少于3个
ioctl(fd_v4l,VIDIOC_REQBUFS,&req)
查询帧缓冲区在内核空间中的长度和偏移量
ioctl(fd_v4l,VIDIOC_QUERYBUF,&buf)
应⽤程序通过内存映射,将帧缓冲区的地址映射到⽤户空间
buffers[i].start=mmap(NULL,buffers[i].length,PORT_READ|PORT_WRITE,MAP_SHARED,fd_v4l,buffers[i].offset)
将申请到的帧缓冲全部放⼊视频采集输出队列
ioctl(fd_v4l,VIDIOC_QBUF,&buf)
开始视频流数据的采集
ioctl(fd_v4l,VIDIOC_STREAMON,&type)
应⽤程序从视频采集输出队列中取出已含有采集数据的帧缓冲区
ioctl(fd_v4l,VIDIOC_DQBUF,&buf)
应⽤程序将该帧缓冲区重新排⼊输⼊队列
ioctl(fd_v4l,VIDIOC_QBUF,&buf)泡面碗
停⽌视频的采集
ioctl(fd_v4l,VIDIOC_STREAMOFF,&type)
释放申请的视频帧缓冲区unmap,关闭视频设备⽂件close(fd_v4l)
ioctl控制符
VIDIOC_QUERYCAP 查询设备的属性
VIDIOC_ENUM_FMT 帧格式
VIDIOC_S_FMT 设置视频帧格式,对应struct v4l2_format
VIDIOC_G_FMT 获取视频帧格式等
VIDIOC_REQBUFS 请求/申请若⼲个帧缓冲区,⼀般为不少于3个
VIDIOC_QUERYBUF 查询帧缓冲区在内核空间的长度和偏移量
VIDIOC_QBUF 将申请到的帧缓冲区全部放⼊视频采集输出队列
VIDIOC_STREAMON 开始视频流数据的采集
VIDIOC_DQBUF 应⽤程序从视频采集输出队列中取出已含有采集数据的帧缓冲区
VIDIOC_STREAMOFF 应⽤程序将该帧缓冲区重新挂⼊输⼊队列
相关结构体解析
1.VIDIOC_QUERYCAP------>struct v4l2_capability
struct v4l2_capability {
__u8 driver[16];    // 驱动模块的名字
__u8 card[32];      // 设备名字
__u8 bus_info[32];  // 总线信息
__u32  version;      // 内核版本
__u32 capabilities;  // 整个物理设备⽀持的功能
__u32 device_caps;  // 通过这个特定设备访问的功能
__u32 reserved[3];
};
其中capabilities: 4000001通过与各种宏位与,可以获得物理设备的功能属性。⽐如:
//#define V4L2_CAP_VIDEO_CAPTURE  0x00000001  /* Is a video capture device */ // 是否⽀持视频捕获if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE)
{
printf("Device %s: supports capture.\n", FILE_VIDEO);
}
//#define V4L2_CAP_STREAMING            0x04000000  /* streaming I/O ioctls */ // 是否⽀持输⼊输出流控制if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING)
{
printf("Device %s: supports streaming.\n", FILE_VIDEO);
}
2.VIDIOC_ENUM_FMT------>struct v4l2_fmtdesc
struct v4l2_fmtdesc {
__u32      index;          /* Format number      */
__u32      type;            /* enum v4l2_buf_type */
__u32          flags;
皂液盒__u8      description[32]; /* Description string */
__u32      pixelformat;    /* Format fourcc      */
__u32      reserved[4];
};
通过这个结构体,可以显⽰对应的摄像头所⽀持视频帧格式。
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index = 0;
printf("Supportformat:/n");
勇猛的圣灵肩垫while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)
{
printf("/t%d.%s/n",fmtdesc.index+1,fmtdesc.description);
fmtdesc.index++;
}
3.VIDIOC_S_FMT&VIDIOC_G_FMT------>struct v4l2_format
查看或设置视频帧格式
struct v4l2_format {
__u32  type; // 帧类型
union {
/* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_pix_format pix;  //像素格式
/* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
struct v4l2_pix_format_mplane pix_mp;
/* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_window win;
/* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_vbi_format vbi;
/* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced;
/* V4L2_BUF_TYPE_SDR_CAPTURE */
struct v4l2_sdr_format  sdr;
/* user-defined */
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format {
__u32          width;  // 像素⾼度
__u32  height; // 像素宽度
__u32  pixelformat; // 像素格式
__u32  field;  /* enum v4l2_field */
__u32          bytesperline; /* for padding, zero if unused */
__u32            sizeimage;
__u32  colorspace; /* enum v4l2_colorspace */
__u32  priv;  /* private data, depends on pixelformat */
__u32  flags;  /* format flags (V4L2_PIX_FMT_FLAG_*) */
__u32  ycbcr_enc; /* enum v4l2_ycbcr_encoding */
__u32  quantization; /* enum v4l2_quantization */
__u32  xfer_func; /* enum v4l2_xfer_func */
};
4.VIDIOC_CROPCAP------>struct v4l2_cropcap
5.VIDIOC_G_PARM&VIDIOC_S_PARM------>struct v4l2_streamparm
设置Stream信息,主要设置帧率。
struct v4l2_streamparm {
__u32  type;  /* enum v4l2_buf_type */
union {
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200];  /* user-defined */
} parm;
};
struct v4l2_captureparm {
/
导电橡胶片*  Supported modes */
__u32    capability;
/*  Current mode */
__u32    capturemode;
/*  Time per frame in seconds */
struct v4l2_fract  timeperframe;
/*  Driver-specific extensions */
__u32    extendedmode;
/*  # of buffers for read */
__u32          readbuffers;
__u32    reserved[4];
};
// timeperframe
// numerator和denominator可描述为每numerator秒有denominator帧
struct v4l2_fract {
__u32  numerator;        // 分⼦
__u32  denominator;      // 分母
};
6.VIDIOC_REQBUFS------>struct v4l2_requestbuffers
申请和管理缓冲区,应⽤程序和设备有三种交换数据⽅法,直接read/write(裸机)、内存映射(系统),⽤户指针(…)。⼀般在操作系统管理下,都是使⽤内存映射的⽅式。
struct v4l2_requestbuffers {
__u32  count;  // 缓冲区内缓冲帧的数⽬
__u32  type;  // 缓冲帧数据格式
__u32  memory; //
__u32  reserved[2];
};
enum v4l2_memory {
V4L2_MEMORY_MMAP            = 1, // 内存映射
V4L2_MEMORY_USERPTR          = 2, // ⽤户指针
V4L2_MEMORY_OVERLAY          = 3,
V4L2_MEMORY_DMABUF          = 4,
};
7.VIDIOC_QUERYBUF------>struct v4l2_buffer
struct v4l2_buffer {
__u32  index;          // buffer的id
__u32  index;          // buffer的id
__u32  type;            // enum v4l2_buf_type
__u32  bytesused;      // buf中已经使⽤的字节数
__u32  flags;          // MMAP 或 USERPTR
__u32  field;
struct timeval  timestamp;  // 帧时间戳
struct v4l2_timecode timecode;
__u32  sequence;        // 队列中的序号
/* memory location */
__u32  memory;
union {
__u32          offset;      // 设备内存起始offset
unsigned long  userptr;    // 指向⽤户空间的指针
struct v4l2_plane *planes;
__s32  fd;
} m;
__u32  length;        // 缓存帧长度
__u32  reserved2;
__u32  reserved;
};
8.VIDIOC_DQBUF
应⽤程序从视频采集输出队列中取出已含有采集数据的帧缓冲区
9.VIDIOC_STREAMON&VIDIOC_STREAMOFF
开始视频采集和关闭视频采集
10.VIDIOC_QBUF
应⽤程序将该帧缓冲区重新挂⼊输⼊队列
使⽤V4L2接⼝采集图⽚
yuyv格式摄像头
生产H
v4l2grab.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include "v4l2grab.h"
#define  TRUE 1
#define  FALSE 0
#define FILE_VIDEO  "/dev/video0"
#if 1
#define BMP      "/usr/image_bmp.bmp"
#define YUV        "/usr/image_yuv.yuv"
#else
自动排污阀
#define BMP      "//home/book/100ask_roc-rk3399-pc/USBvideo/lab_v4l2_yuyv/image_bmp.bmp" #define YUV        "//home/book/100ask_roc-rk3399-pc/USBvideo/lab_v4l2_yuyv/image_yuv.yuv" #endif

本文发布于:2024-09-23 20:20:46,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/251369.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:视频   采集   缓冲区   数据   设备   队列
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议