video4linux(v4l)使用摄像头的实例基础教程与体会(转)
- #ifndef _V4L_H_
- #define _V4L_H_
- #include <sys/types.h>
- #include <linux/videodev.h> //使用v4l必须包含的头文件
- struct _v4l_struct
- {
- int fd;//保存打开视频文件的设备描述符
- struct video_capability capability;//设备的基本信息(设备名称、支持的分辨率等)
- struct video_picture picture;//采集图像的各种属性
- struct video_mmap mmap;
- struct video_mbuf mbuf;//利用mmap映射的帧的信息
- unsigned char *map;//用于指向图像数据的指针
- int frame_current;
- int frame_using[VIDEO_MAXFRAME];//这两个变量用于双缓冲在后面介绍。
- };
- typedef struct _v4l_struct v4l_device;
- extern int v4l_open(char *, v4l_device *);
- extern int v4l_close(v4l_device *);
- extern int v4l_get_capability(v4l_device *);
- extern int v4l_get_picture(v4l_device *);
- extern int v4l_get_mbuf(v4l_device *);
- extern int v4l_set_picture(v4l_device *, int, int, int, int, int,);
- extern int v4l_grab_picture(v4l_device *, unsigned int);
- extern int v4l_mmap_init(v4l_device *);
- extern int v4l_grab_init(v4l_device *, int, int);
- extern int v4l_grab_frame(v4l_device *, int);
- extern int v4l_grab_sync(v4l_device *);
- #define DEFAULT_DEVICE “/dev/video0”
- int v4l_open(char *dev , v4l_device *vd)
- {
- if(!dev)dev= DEFAULT_DEVICE;
- if((vd->fd=open(dev,O_RDWR))<0){perror(“v4l_open:”);return -1;}
- if(v4l_get_capability(vd))return -1;
- if(v4l_get_picture(vd))return -1;//这两个函数就是即将要完成的获取设备信息的函数
- return 0
- }
- int v4l_close(v4l_device *vd)
- {close(vd->fd);return 0;}
- int v4l_get_capability(v4l_device *vd)
- {
- if (ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)) < 0) {
- perror("v4l_get_capability:");
- return -1;
- }
- return 0;
- }
- int v4l_get_picture(v4l_device *vd)
- {
- if (ioctl(vd->fd, VIDIOCGPICT, &(vd->picture)) < 0) {
- perror("v4l_get_picture:");
- return -1;
- }
- return 0;
- }
- struct video_capability
- {
- char name[32];
- int type;
- int channels; /* Num channels */
- int audios; /* Num audio devices */
- int maxwidth; /* Supported width */
- int maxheight; /* And height */
- int minwidth; /* Supported width */
- int minheight; /* And height */
- };//capability结构它包括了视频设备的名称,频道数,音频设备数,支持的最大最小宽度和高度等信息。
- struct video_picture
- {
- __u16 brightness;
- __u16 hue;
- __u16 colour;
- __u16 contrast;
- __u16 whiteness; /* Black and white only */
- __u16 depth; /* Capture depth */
- __u16 palette; /* Palette in use */
- };//picture结构包括了亮度,对比度,色深,调色板等等信息。头文件里还列出了palette相关的值,这里并没有给出。
- int v4l_get_mbuf(v4l_device *vd)
- {
- if (ioctl(vd->fd, VIDIOCGMBUF ,&(vd->mbuf)) < 0) {
- perror("v4l_get_mbuf:");
- return -1;
- }
- return 0;
- }
对于结构体video_mbuf在v4l中的定义如下,video_mbuf结构体是为了服务使用mmap内存映射来获取图像的方法而设置的结构体,通过这个结构体可以获得摄像头设备存储图像的内存大小。具体的定义如下,各变量的使用也会在下文详细说明。
- struct video_mbuf
- {
- int size; 可映射的摄像头内存大小
- int frames; 摄像头可同时存储的帧数
- int offsets[VIDEO_MAX_FRAME];每一帧图像的偏移量
- };
- int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)
- {
- if(br) vd->picture.brightnesss=br;
- if(hue) vd->picture.hue=hue;
- if(col) vd->picture.color=col;
- if(cont) vd->picture.contrast=cont;
- if(white) vd->picture.whiteness=white;
- if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0)
- {perror("v4l_set_picture: ");return -1;}
- return 0;
- }
- extern int v4l_grab_picture(v4l_device *, unsigned int);//函数就是完成这个工作的,它的实现也很简单。
- int v4l_grab_picture(v4l_device *vd, unsighed int size)
- {
- if(read(vd->fd,&(vd->map),size)==0)return -1;
- return 0;
- }
- extern int v4l_mmap_init(v4l_device *);//该函数把摄像头图像数据映射到进程内存中,也就是只要使用vd->map指针就可以使用采集到的图像数据(下文详细说明)
- extern int v4l_grab_init(v4l_device *, int, int);//该函数完成图像采集前的初始化工作。
- extern int v4l_grab_frame(v4l_device *, int);//该函数是真正完成图像采集的一步,在本文使用了一个通常都会使用的一个小技巧,可以在处理一帧数据时同时采集下一帧的数据,因为通常我们使用的摄像头都可以至少存储两帧的数据。
- extern int v4l_grab_sync(v4l_device *);//该函数用来完成截取图像的同步工作,在截取一帧图像后调用,返回表明一帧截取结束。
- void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )
- int v4l_mmap_init(v4l_device *vd)
- {
- if (v4l_get_mbuf(vd) < 0)
- return -1;
- if ((vd->map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, vd->fd, 0)) < 0) {
- perror("v4l_mmap_init:mmap");
- return -1;
- }
- return 0;
- }
- int v4l_grab_init(v4l_device *vd, int width, int height)
- {
- vd->mmap.width = width;
- vd->mmap.height = height;
- vd->mmap.format = vd->picture.palette;
- vd->frame_current = 0;
- vd->frame_using[0] = FALSE;
- vd->frame_using[1] = FALSE;
- return v4l_grab_frame(vd, 0);
- }
- <span style="color:#330033;">int v4l_grab_frame(v4l_device *vd, int frame)
- {
- if (vd->frame_using[frame]) {
- fprintf(stderr, "v4l_grab_frame: frame %d is already used.\n", frame);
- return -1;
- }
- vd->mmap.frame = frame;
- if (ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) < 0) {
- perror("v4l_grab_frame");
- return -1;
- }
- vd->frame_using[frame] = TRUE;
- vd->frame_current = frame;
- return 0;
- } </span>
- int v4l_grab_sync(v4l_device *vd)
- {
- if (ioctl(vd->fd, VIDIOCSYNC, &(vd->frame_current)) < 0) {
- perror("v4l_grab_sync");
- }
- vd->frame_using[vd->frame_current] = FALSE;
- return 0;
- }
- //test.c
- include “v4l.h”
- ...
- v4l_device vd;
- void main()
- {
- v4l_open(DEFAULT_DEVICE,&vd);
- v4l_mmap_init(&vd);
- v4l_grab_init(&vd,320,240);
- v4l_grab_sync(&vd);//此时就已经获得了一帧的图像,存在vd.map中
- while(1)
- {
- vd.frame_current ^= 1;
- v4l_grab_frame(&vd, vd.frame_current);
- v4l_grab_sync(&vd);
- 图像处理函数(vd.map+vd. vd.map+vd.mbuf.offsets[vd.frame_current]);
- //循环采集,调用你设计的图像处理函数来处理图像
- //其中vd.map+vd. vd.map+vd.mbuf.offsets[vd.frame_current]就是图像所在位置。
- }
- }
video4linux(v4l)使用摄像头的实例基础教程与体会(转)的更多相关文章
- React实例入门教程(1)基础API,JSX语法--hello world
前 言 毫无疑问,react是目前最最热门的框架(没有之一),了解并学习使用React,可以说是现在每个前端工程师都需要的. 在前端领域,一个框架为何会如此之火爆,无外乎两个原因:性能优秀,开发 ...
- 【原创】React实例入门教程(1)基础API,JSX语法--hello world
前 言 毫无疑问,react是目前最最热门的框架(没有之一),了解并学习使用React,可以说是现在每个前端工程师都需要的. 在前端领域,一个框架为何会如此之火爆,无外乎两个原因:性能优秀,开发效率 ...
- Python 基础教程 —— Pandas 库常用方法实例说明
目录 1. 常用方法 pandas.Series 2. pandas.DataFrame ([data],[index]) 根据行建立数据 3. pandas.DataFrame ({dic}) ...
- WCF基础教程之异常处理:你的Try..Catch语句真的能捕获到异常吗?
在上一篇WCF基础教程之开篇:创建.测试和调用WCF博客中,我们简单的介绍了如何创建一个WCF服务并调用这个服务.其实,上一篇博客主要是为了今天这篇博客做铺垫,考虑到网上大多数WCF教程都是从基础讲起 ...
- objective-c基础教程——学习小结
objective-c基础教程——学习小结 提纲: 简介 与C语言相比要注意的地方 objective-c高级特性 开发工具介绍(cocoa 工具包的功能,框架,源文件组织:XCode使用介绍) ...
- jQuery官方基础教程笔记(转载)
本文转载于阮一峰的博文,内容基础,结构清晰,是jquery入门不可多得的资料,非常好,赞一个. 阮一峰:jQuery官方基础教程笔记 jQuery是目前使用最广泛的javascript函数库. 据统计 ...
- Android程序开发0基础教程(一)
程序猿学英语就上视觉英语网 Android程序开发0基础教程(一) 平台简单介绍 令人激动的Google手机操作系统平台-Android在2007年11月13日正式公布了,这是一个开放源码的操 ...
- (转)Windows驱动编程基础教程
版权声明 本书是免费电子书. 作者保留一切权利.但在保证本书完整性(包括版权声明.前言.正文内容.后记.以及作者的信息),并不增删.改变其中任何文字内容的前提下,欢迎任何读者 以任何形式(包括 ...
- HTML入门基础教程相关知识
HTML入门基础教程 html是什么,什么是html通俗解答: html是hypertext markup language的缩写,即超文本标记语言.html是用于创建可从一个平台移植到另一平台的超文 ...
随机推荐
- CSU-1307-二分+dij
1307: City Tour Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 59 ...
- Nginx启动/重启失败
解决方案: Nginx启动或重启失败,一般是因为配置文件出错了,我们可以使用nginx -t方法查看配置文件出错的地方.也可以通过查看Nginx日志文件定位到Nginx重启失败的原因,Nginx日志文 ...
- 基于vue-cli,测试非父子传值时,碰到 keep-alive的神奇
非父子传值测试 一直都很好奇非父子传值到底如何,结果入坑许久才爬出来,才知道在脚手架里测试就是坑. 问题: 测试非父子传值时,由于组件之间是通过路由进行跳转,值传过去又被刷掉 思路: 因为路由跳转,相 ...
- Accesshelper.cs
using System; using System.Data; using System.Data.OleDb; using System.Collections; using System.IO; ...
- lambda表达式 <二>
概念了解: 1.什么是匿名委托(匿名方法的简单介绍.为什么要用匿名方法) 2.匿名方法的[拉姆达表达式]方法定义 3.匿名方法的调用(匿名方法的参数传递.使用过程中需要注意什么) 什么是匿名方法? 匿 ...
- MD5加密(java和c#)
java代码 public static String md5(String str) { try { MessageDigest md = MessageDigest.getInstance(&qu ...
- 第9课:备份mysql数据库、重写父类、unittest框架、多线程
1. 写代码备份mysql数据库: 1)Linux下,备份mysql数据库,在shell下执行命令:mysqldump -uroot -p123456 -A >db_bak.sql即可 impo ...
- ES的Zen发现机制
ES的Zen发现机制 Zen发现机制是ElasticSearch默认的发现模块.它提供的是单播发现,但是可被拓展为支持云环境下或者其他形式的发现机制.zen 发现模块集成了其他模块,如在发现期间,节点 ...
- this指针逃逸问题
this指针逃逸是指在构造函数返回之前,其他线程已经就持有了该对象的应用,产生的结果自然和预期可能会产生差异.常见的this指针逃逸,在并发编程实战一书中,作者指出:在构造函数中注册事件监听,在构造函 ...
- APUE学习笔记——5.5~5.7数据流的打开与读写
1.open #include <stdio.h> FILE *fopen(const char *restrict pathname,const char *restrict type) ...