博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
V4L2 Video 学习笔记
阅读量:3740 次
发布时间:2019-05-22

本文共 5936 字,大约阅读时间需要 19 分钟。

V4L2 Video 学习笔记

使用到的头文件

#include 
#include
//#include
//#include
#include
/* getopt_long() */#include
/* low-level i/o */#include
#include
#include
#include
#include
#include
#include
#include
#include
/* for videodev2.h */#include

打开设备

int device_open(const char* device_name){
FUNCTION_NAME int fd = -1; fd = open(device_name,O_RDWR|O_NONBLOCK,0); if (fd) {
fprintf(stderr,"camera open success~ fd:(%d)\n",fd); /* code */ }else{
fprintf(stderr,"camera open faild~ fd:(%d)\n",fd); } return fd;}

查询摄像头支持的功能和支持的格式

struct v4l2_capability cap;	device_ioctl(fd, VIDIOC_QUERYCAP, &cap);	fprintf(stderr, "version:%d device info:%s\n", cap.version,cap.driver);	if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)	{
fprintf(stderr, "%s support capture!\n",dev_name); } if (cap.capabilities & V4L2_CAP_STREAMING) {
fprintf(stderr, "%s support steaming capture!\n",dev_name); }

查询摄像头支持的格式

struct v4l2_fmtdesc  fmtdesc;	fmtdesc.index=0;	fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;	int flag = -1;	while((flag=ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc))!=-1){
fprintf(stderr, "%s fmtdesc %s!\n",dev_name,fmtdesc.description); fmtdesc.index++; }

查询摄像头支持的分辨率

struct v4l2_fmtdesc  fmtdesc;	fmtdesc.index=0;	fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;	int flag = -1;	struct v4l2_frmsizeenum supportSizes;	while((flag=ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc))!=-1)	{
supportSizes.pixel_format = fmtdesc.pixelformat; supportSizes.index = 0; while((ioctl(fd,VIDIOC_ENUM_FRAMESIZES,&supportSizes))!=-1) {
fprintf(stderr, "line:%d %sformat: %s!size with:%d height:%d\n",__LINE__,dev_name,fmtdesc.description,supportSizes.discrete.width,supportSizes.discrete.height); supportSizes.index++; } //fprintf(stderr, "%s support fmt: fmtdesc %s!\n",dev_name,fmtdesc.description); fmtdesc.index++; }

设置取景范围(可以设置取景范围,设置流类型)

CLEAR(cropcap);    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    if(0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap))    {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; /* reset to default */ if(-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
switch(errno) {
case EINVAL: /* Cropping not supported. */ break; default: /* Errors ignored. */ break; } } }

设置分辨率,格式等参数

struct v4l2_format fmt;	CLEAR(fmt);    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    fmt.fmt.pix.width = 640;    fmt.fmt.pix.height = 480;    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;    if (device_ioctl(fd,VIDIOC_S_FMT,&fmt) == -1)    {
fprintf(stderr, "dev:%sErrors happens in set format!\n",dev_name); }

内存映射

void device_buf_mmap(int fd){
struct v4l2_requestbuffers req; CLEAR(req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // 内存映射的方式 req.memory = V4L2_MEMORY_MMAP; if (device_ioctl(fd,VIDIOC_REQBUFS,&req) == -1) {
fprintf(stderr, "request buf error!\n"); return; } if (buffers == NULL) {
buffers = calloc(req.count, sizeof(*buffers)); }else{
free(buffers); } if(req.count < 2) {
fprintf(stderr, "Insufficient buffer memory on %s/n", dev_name); exit(EXIT_FAILURE); } fprintf(stderr, "sizeof buffers is:%d\n", sizeof(*buffers)); for (int i = 0; i < req.count; ++i) {
struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (device_ioctl(fd,VIDIOC_QUERYBUF,&buf) != -1) {
buffers[i].length = buf.length; buffers[i].start = mmap(NULL,buf.length,PROT_READ | PROT_WRITE, MAP_SHARED,fd,buf.m.offset); } if (buffers[i].start == MAP_FAILED) {
error_exit("mmap"); } }}

视频采集

void startCapture(int fd){
FUNCTION_NAME; for (int i = 0; i < buff_index; i++) {
struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (device_ioctl(fd,VIDIOC_QBUF,&buf) == -1) {
error_exit("queue buf~"); } } enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (device_ioctl(fd,VIDIOC_STREAMON,&type) == -1) {
error_exit("VIDIOC_STREAMON"); }}

获取视频帧数据(注意这里需要 select fd设备设置超时)

fd_set fds;            struct timeval tv;            int r;            FD_ZERO(&fds);            FD_SET(fd, &fds);            /* Timeout. */            tv.tv_sec = 2;            tv.tv_usec = 0;            r = select(fd + 1, &fds, NULL, NULL, &tv);            if(-1 == r)            {
if(EINTR == errno) continue; error_exit("select"); } if(0 == r) {
fprintf(stderr, "select timeout/n"); exit(EXIT_FAILURE); } if (getFrame(fd)) {
break; }
void startCapture(int fd){
FUNCTION_NAME; for (int i = 0; i < buff_index; i++) {
struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (device_ioctl(fd,VIDIOC_QBUF,&buf) == -1) {
error_exit("queue buf~"); } } enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (device_ioctl(fd,VIDIOC_STREAMON,&type) == -1) {
error_exit("VIDIOC_STREAMON"); }}

停止采集 释放映射

static void stopCapture(int fd){
FUNCTION_NAME; enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(-1 == device_ioctl(fd, VIDIOC_STREAMOFF, &type)){
error_exit("VIDIOC_STREAMOFF"); }}static void uninit_device(void){
FUNCTION_NAME; unsigned int i; for(i = 0; i < n_buffers; ++i) {
if(-1 == munmap(buffers[i].start, buffers[i].length)) {
error_exit("munmap"); } } free(buffers);}

转载地址:http://lhoin.baihongyu.com/

你可能感兴趣的文章
Node.JS 介绍及基础知识(模块化简介、NPM用法、Buffer缓冲区、fs文件系统)
查看>>
①webpack 简介及开发环境配置
查看>>
②webpack 生产环境配置
查看>>
操作系统:Java模拟作业调度算法(先来先服务、短作业优先、高响应者优先)
查看>>
计算机视觉技术:C++和opencv插件 实现比较均值、中值、高斯滤波,对不同噪音(椒盐、高斯噪音)的抑制效果
查看>>
③webpack 优化环境配置
查看>>
④webpack 配置详解
查看>>
①Vue介绍及基本用法(模板语法、计算属性和监视、条件渲染、列表渲染、列表搜索和排序、事件处理、表单输入绑定、生命周期、动画、过滤器、指令)
查看>>
操作系统:Java模拟银行家算法
查看>>
②Vue 使用vue-cli创建模板项目、组件化编码流程简述
查看>>
③Vue vue-ajax、UI组件库、vue-router
查看>>
④Vuex基本用法
查看>>
前端面试题 HTML5 CSS3(盒子模型、盒子水平垂直居中、经典布局) JS(闭包、深浅克隆、数据劫持和拦截) 算法(排序、去重、数组扁平化) Vue(双向数据绑定原理、通信方式)
查看>>
操作系统:Java模拟内存管理(循环首次适应算法、回收空间算法)
查看>>
操作系统:Java模拟页面置换算法(最佳置换算法、先进先出算法、最近最久未使用算法)
查看>>
⑤mpvue 小程序框架 :初始化项目 分析项目结构
查看>>
⑥mpvue 很基础的小程序页面搭建(vuex管理状态、实现收藏和分享功能)
查看>>
⑦mpvue Flyio实现前后台交互
查看>>
操作系统:Java模拟磁盘调度算法(先来先服务、最短寻道优先、电梯调度方法)
查看>>
⑫HTML5与之前HTML的区别
查看>>